X86: All x86 fault classes now attempt to do something useful.
authorGabe Black <gblack@eecs.umich.edu>
Mon, 2 Feb 2009 01:09:08 +0000 (17:09 -0800)
committerGabe Black <gblack@eecs.umich.edu>
Mon, 2 Feb 2009 01:09:08 +0000 (17:09 -0800)
src/arch/x86/faults.cc
src/arch/x86/faults.hh
src/arch/x86/isa/insts/romutil.py

index 7702d98ebcee7cbc17a5976f2e8b6c4c081a6928..1234e68e5d2381b8c1591b8a94ad627c73e14fa7 100644 (file)
 namespace X86ISA
 {
 #if FULL_SYSTEM
-    void X86Trap::invoke(ThreadContext * tc)
-    {
-        panic("X86 faults are not implemented!");
-    }
-
-    void X86Abort::invoke(ThreadContext * tc)
-    {
-        panic("X86 faults are not implemented!");
-    }
-
-    void X86Interrupt::invoke(ThreadContext * tc)
+    void X86FaultBase::invoke(ThreadContext * tc)
     {
         using namespace X86ISAInst::RomLabels;
         HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
         MicroPC entry;
         if (m5reg.mode == LongMode) {
-            entry = extern_label_longModeInterrupt;
+            if (isSoft()) {
+                entry = extern_label_longModeSoftInterrupt;
+            } else {
+                entry = extern_label_longModeInterrupt;
+            }
         } else {
             entry = extern_label_legacyModeInterrupt;
         }
         tc->setIntReg(INTREG_MICRO(1), vector);
         tc->setIntReg(INTREG_MICRO(7), tc->readPC());
         if (errorCode != (uint64_t)(-1)) {
+            if (m5reg.mode == LongMode) {
+                entry = extern_label_longModeInterruptWithError;
+            } else {
+                panic("Legacy mode interrupts with error codes "
+                        "aren't implementde.\n");
+            }
+            // Software interrupts shouldn't have error codes. If one does,
+            // there would need to be microcode to set it up.
+            assert(!isSoft());
             tc->setIntReg(INTREG_MICRO(15), errorCode);
         }
         tc->setMicroPC(romMicroPC(entry));
         tc->setNextMicroPC(romMicroPC(entry) + 1);
     }
+    
+    void X86Trap::invoke(ThreadContext * tc)
+    {
+        X86FaultBase::invoke(tc);
+        // This is the same as a fault, but it happens -after- the instruction.
+        tc->setPC(tc->readNextPC());
+        tc->setNextPC(tc->readNextNPC());
+        tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst));
+    }
+
+    void X86Abort::invoke(ThreadContext * tc)
+    {
+        panic("Abort exception!");
+    }
+
+    void PageFault::invoke(ThreadContext * tc)
+    {
+        HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+        X86FaultBase::invoke(tc);
+        /*
+         * If something bad happens while trying to enter the page fault
+         * handler, I'm pretty sure that's a double fault and then all bets are
+         * off. That means it should be safe to update this state now.
+         */
+        if (m5reg.mode == LongMode) {
+            tc->setMiscReg(MISCREG_CR2, addr);
+        } else {
+            tc->setMiscReg(MISCREG_CR2, (uint32_t)addr);
+        }
+    }
 
     void FakeITLBFault::invoke(ThreadContext * tc)
     {
index 9c9cf39094f8f41781eab86b1c2bc0cee7be2cfa..6a6dfc80a5ec675c99a76f6c0cd2a267acdf0133 100644 (file)
@@ -95,11 +95,14 @@ namespace X86ISA
             return mnem;
         }
 
-        void
-        invoke(ThreadContext * tc)
+        virtual bool isSoft()
         {
-            panic("Unimplemented fault %s.\n", name());
+            return false;
         }
+
+#if FULL_SYSTEM
+        void invoke(ThreadContext * tc);
+#endif
     };
 
     // Base class for x86 faults which behave as if the underlying instruction
@@ -150,10 +153,6 @@ namespace X86ISA
                 const uint8_t _vector, uint64_t _errorCode = -1) :
             X86FaultBase(name, mnem, _vector, _errorCode)
         {}
-
-#if FULL_SYSTEM
-        void invoke(ThreadContext * tc);
-#endif
     };
 
     class UnimpInstFault : public FaultBase
@@ -321,13 +320,16 @@ namespace X86ISA
             Bitfield<4> fetch;
         EndBitUnion(PageFaultErrorCode)
 
+        Addr addr;
+
       public:
-        PageFault(uint32_t _errorCode) :
-            X86Fault("Page-Fault", "#PF", 14, _errorCode)
+        PageFault(Addr _addr, uint32_t _errorCode) :
+            X86Fault("Page-Fault", "#PF", 14, _errorCode), addr(_addr)
         {}
-        PageFault(bool present, bool write, bool user,
-                bool reserved, bool fetch) :
-            X86Fault("Page-Fault", "#PF", 14, 0)
+
+        PageFault(Addr _addr, bool present, bool write,
+                bool user, bool reserved, bool fetch) :
+            X86Fault("Page-Fault", "#PF", 14, 0), addr(_addr)
         {
             PageFaultErrorCode code = 0;
             code.present = present;
@@ -337,6 +339,10 @@ namespace X86ISA
             code.fetch = fetch;
             errorCode = code;
         }
+
+#if FULL_SYSTEM
+        void invoke(ThreadContext * tc);
+#endif
     };
 
     class X87FpExceptionPending : public X86Fault
@@ -410,6 +416,11 @@ namespace X86ISA
         SoftwareInterrupt(uint8_t _vector) :
             X86Interrupt("Software Interrupt", "INTn", _vector)
         {}
+
+        bool isSoft()
+        {
+            return true;
+        }
     };
 
     // These faults aren't part of the ISA definition. They trigger filling
index ea41d2ca814438c6c1b0eed37f940743c38a3868..1345c3d0569d9d8bbaf64339fc2f14c046209b25 100644 (file)
@@ -95,7 +95,7 @@ def rom
 
     # If we're here, it's because the stack isn't being switched.
     # Set t6 to the new aligned rsp.
-    mov t6, rsp, dataSize=8
+    mov t6, t6, rsp, dataSize=8
     andi t6, t6, 0xF0, dataSize=1
     subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8