X86: Remove enforcement of APIC register access alignment. Panic if more than one...
authorGabe Black <gblack@eecs.umich.edu>
Thu, 12 Jun 2008 04:46:22 +0000 (00:46 -0400)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 12 Jun 2008 04:46:22 +0000 (00:46 -0400)
src/arch/x86/mmaped_ipr.hh
src/arch/x86/tlb.cc

index eda85c08448000024679334a150429d32563b6f6..cf3eba5e9960a27c18a8882a9ad90c11a0b4631d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
  * All rights reserved.
  *
  * Redistribution and use of this software in source and binary forms,
@@ -78,15 +78,12 @@ namespace X86ISA
 #if !FULL_SYSTEM
         panic("Shouldn't have a memory mapped register in SE\n");
 #else
+        Addr offset = pkt->getAddr() & mask(3);
         MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg));
-        if (index == MISCREG_PCI_CONFIG_ADDRESS ||
-                (index >= MISCREG_APIC_START &&
-                 index <= MISCREG_APIC_END)) {
-            pkt->set((uint32_t)(xc->readMiscReg(pkt->getAddr() /
-                            sizeof(MiscReg))));
-        } else {
-            pkt->set(xc->readMiscReg(pkt->getAddr() / sizeof(MiscReg)));
-        }
+        MiscReg data = htog(xc->readMiscReg(index));
+        // Make sure we don't trot off the end of data.
+        assert(offset + pkt->getSize() <= sizeof(MiscReg));
+        pkt->setData(((uint8_t *)&data) + offset);
 #endif
         return xc->getCpuPtr()->ticks(1);
     }
@@ -97,15 +94,13 @@ namespace X86ISA
 #if !FULL_SYSTEM
         panic("Shouldn't have a memory mapped register in SE\n");
 #else
+        Addr offset = pkt->getAddr() & mask(3);
         MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg));
-        if (index == MISCREG_PCI_CONFIG_ADDRESS ||
-                (index >= MISCREG_APIC_START &&
-                 index <= MISCREG_APIC_END)) {
-            xc->setMiscReg(index, gtoh(pkt->get<uint32_t>()));
-        } else {
-            xc->setMiscReg(pkt->getAddr() / sizeof(MiscReg),
-                    gtoh(pkt->get<uint64_t>()));
-        }
+        MiscReg data = htog(xc->readMiscRegNoEffect(index));
+        // Make sure we don't trot off the end of data.
+        assert(offset + pkt->getSize() <= sizeof(MiscReg));
+        pkt->writeData(((uint8_t *)&data) + offset);
+        xc->setMiscReg(index, gtoh(data));
 #endif
         return xc->getCpuPtr()->ticks(1);
     }
index 3e720c9ae58827e9a627c89f98c3ff725f3afc9e..cbd59c19ec9d5b87b029e725884a27d7063eb8b6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
  * All rights reserved.
  *
  * Redistribution and use of this software in source and binary forms,
@@ -598,13 +598,24 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
     Addr paddr = req->getPaddr();
     if (baseAddr <= paddr && baseAddr + (1 << 12) > paddr) {
         req->setMmapedIpr(true);
+        // The Intel developer's manuals say the below restrictions apply,
+        // but the linux kernel, because of a compiler optimization, breaks
+        // them.
+        /*
         // Check alignment
         if (paddr & ((32/8) - 1))
             return new GeneralProtection(0);
         // Check access size
         if (req->getSize() != (32/8))
             return new GeneralProtection(0);
+        */
+
+        //Make sure we're at least only accessing one register.
+        if ((paddr & ~mask(3)) != ((paddr + req->getSize()) & ~mask(3)))
+            panic("Accessed more than one register at a time in the APIC!\n");
         MiscReg regNum;
+        Addr offset = paddr & mask(3);
+        paddr &= ~mask(3);
         switch (paddr - baseAddr)
         {
           case 0x20:
@@ -732,7 +743,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
             return new GeneralProtection(0);
             break;
         }
-        req->setPaddr(regNum * sizeof(MiscReg));
+        req->setPaddr(regNum * sizeof(MiscReg) + offset);
     }
 #endif
     return NoFault;