]> Zhao Yanbai Git Server - minix.git/commitdiff
ahci: prevent compiler memory access misordering
authorDavid van Moolenbroek <david@minix3.org>
Fri, 4 Nov 2011 13:11:34 +0000 (14:11 +0100)
committerDavid van Moolenbroek <david@minix3.org>
Fri, 4 Nov 2011 13:13:24 +0000 (14:13 +0100)
While no problems have been observed in practice yet, modern compilers
may reorder memory access operations, and that could lead to problems
with memory-mapped I/O typically done by drivers. This patch prevents
any potentially problematic reordering by the compiler in the AHCI
driver.

drivers/ahci/ahci.c

index 0ecf1d60231a1c2b352d85b1cb9bbad083f2c140..09bffce4cffcf12f6dc48b2c7a5698e1626a4fc1 100644 (file)
 
 /* Host Bus Adapter (HBA) state. */
 PRIVATE struct {
-       u32_t *base;            /* base address of memory-mapped registers */
+       volatile u32_t *base;   /* base address of memory-mapped registers */
        size_t size;            /* size of memory-mapped register area */
 
        int nr_ports;           /* addressable number of ports (1..NR_PORTS) */
@@ -131,7 +131,7 @@ PRIVATE struct port_state {
        int state;              /* port state */
        unsigned int flags;     /* port flags */
 
-       u32_t *reg;             /* memory-mapped port registers */
+       volatile u32_t *reg;    /* memory-mapped port registers */
 
        u8_t *mem_base;         /* primary memory buffer virtual address */
        phys_bytes mem_phys;    /* primary memory buffer physical address */
@@ -1573,6 +1573,11 @@ PRIVATE void port_issue(struct port_state *ps, int cmd, clock_t timeout)
        ps->reg[AHCI_PORT_SERR] = ~0L;
        ps->reg[AHCI_PORT_IS] = ~0L;
 
+       /* Make sure that the compiler does not delay any previous write
+        * operations until after the write to the CI register.
+        */
+       __insn_barrier();
+
        /* Tell the controller that a new command is ready. */
        ps->reg[AHCI_PORT_CI] = (1L << cmd);
 
@@ -1909,7 +1914,8 @@ PRIVATE void ahci_stop(void)
 
        ahci_reset();
 
-       if ((r = vm_unmap_phys(SELF, hba_state.base, hba_state.size)) != OK)
+       if ((r = vm_unmap_phys(SELF, (void *) hba_state.base,
+                       hba_state.size)) != OK)
                panic("unable to unmap HBA memory: %d", r);
 
        if ((r = sys_irqrmpolicy(&hba_state.hook_id)) != OK)