X86: Change how segment loading is performed.
authorGabe Black <gblack@eecs.umich.edu>
Thu, 12 Jun 2008 04:52:12 +0000 (00:52 -0400)
committerGabe Black <gblack@eecs.umich.edu>
Thu, 12 Jun 2008 04:52:12 +0000 (00:52 -0400)
src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
src/arch/x86/isa/microops/regop.isa
src/arch/x86/tlb.cc

index 0b2e81cbdacd788f0db84f0e568d3f79e9f9096b..b18d4826457142ad1bcab268457729a12917a1db 100644 (file)
@@ -1,4 +1,4 @@
-# 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,
@@ -85,7 +85,7 @@ def macroop RET_FAR {
     ld t1, ss, [1, t0, rsp]
 
     # Get the return CS
-    ld t2, ss, [1, t0, rsp], dsz
+    ld t2, ss, [1, t0, rsp], ssz
 
     # Get the rpl
     andi t3, t2, 0x3
@@ -96,12 +96,21 @@ def macroop RET_FAR {
     # that doesn't happen yet.
 
     # Do stuff if they're equal
-    chks t4, t2, flags=(EZF,)
-    fault "new GeneralProtection(0)", flags=(CEZF,)
-    ld t3, flatseg, [1, t0, t4], addressSize=8, dataSize=8
-    wrdl cs, t3, t2
+    andi t0, t2, 0xFC, flags=(EZF,), dataSize=2
+    bri t0, label("processDescriptor"), flags=(CEZF,)
+    andi t3, t2, 0xF8, dataSize=8
+    andi t0, t2, 0x4, flags=(EZF,), dataSize=2
+    bri t0, label("globalDescriptor"), flags=(CEZF,)
+    ld t3, tsl, [1, t0, t3], dataSize=8
+    bri t0, label("processDescriptor")
+globalDescriptor:
+    ld t3, tsg, [1, t0, t3], dataSize=8
+processDescriptor:
+    chks t2, t3, IretCheck, dataSize=8
     # There should be validity checks on the RIP checks here, but I'll do
     # that later.
+    wrdl reg, t3, t2
+    wrsel reg, t2
     wrip t0, t1
     bri t0, label("end")
 
index 16196bcc8e5e19e045f4574ca55b65712fc782a8..d9a83dfde33b0b59078e6106850ba2e878ccc57b 100644 (file)
@@ -237,65 +237,104 @@ def macroop MOV_REAL_S_P {
 };
 
 def macroop MOV_S_R {
-    chks t1, regm, flags=(EZF,), dataSize=8
-    bri t0, label("end"), flags=(CEZF,)
-    ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
-    wrdl reg, t2, regm
-end:
+    andi t0, regm, 0xFC, flags=(EZF,), dataSize=2
+    bri t0, label("processDescriptor"), flags=(CEZF,)
+    andi t2, regm, 0xF8, dataSize=8
+    andi t0, regm, 0x4, flags=(EZF,), dataSize=2
+    bri t0, label("globalDescriptor"), flags=(CEZF,)
+    ld t3, tsl, [1, t0, t2], dataSize=8
+    bri t0, label("processDescriptor")
+globalDescriptor:
+    ld t3, tsg, [1, t0, t2], dataSize=8
+processDescriptor:
+    chks regm, t3, dataSize=8
+    wrdl reg, t3, regm
     wrsel reg, regm
 };
 
 def macroop MOV_S_M {
     ld t1, seg, sib, disp, dataSize=2
-    chks t2, t1, flags=(EZF,), dataSize=8
-    bri t0, label("end"), flags=(CEZF,)
-    ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
-    wrdl reg, t2, t1
-end:
+    andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
+    bri t0, label("processDescriptor"), flags=(CEZF,)
+    andi t2, t1, 0xF8, dataSize=8
+    andi t0, t1, 0x4, flags=(EZF,), dataSize=2
+    bri t0, label("globalDescriptor"), flags=(CEZF,)
+    ld t3, tsl, [1, t0, t2], dataSize=8
+    bri t0, label("processDescriptor")
+globalDescriptor:
+    ld t3, tsg, [1, t0, t2], dataSize=8
+processDescriptor:
+    chks t1, t3, dataSize=8
+    wrdl reg, t3, t1
     wrsel reg, t1
 };
 
 def macroop MOV_S_P {
     rdip t7
     ld t1, seg, riprel, disp, dataSize=2
-    chks t2, t1, flags=(EZF,), dataSize=8
-    bri t0, label("end"), flags=(CEZF,)
-    ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
-    wrdl reg, t2, t1
-end:
+    andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
+    bri t0, label("processDescriptor"), flags=(CEZF,)
+    andi t2, t1, 0xF8, dataSize=8
+    andi t0, t1, 0x4, flags=(EZF,), dataSize=2
+    bri t0, label("globalDescriptor"), flags=(CEZF,)
+    ld t3, tsl, [1, t0, t2], dataSize=8
+    bri t0, label("processDescriptor")
+globalDescriptor:
+    ld t3, tsg, [1, t0, t2], dataSize=8
+processDescriptor:
+    chks t1, t3, dataSize=8
+    wrdl reg, t3, t1
     wrsel reg, t1
 };
 
 def macroop MOVSS_S_R {
-    chks t1, regm, flags=(EZF,), dataSize=8
-    # This actually needs to use the selector as the error code, but it would
-    # be hard to get that information into the instruction at the moment.
-    fault "new GeneralProtection(0)", flags=(CEZF,)
-    ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
-    wrdl reg, t2, regm
+    andi t0, regm, 0xFC, flags=(EZF,), dataSize=2
+    bri t0, label("processDescriptor"), flags=(CEZF,)
+    andi t2, regm, 0xF8, dataSize=8
+    andi t0, regm, 0x4, flags=(EZF,), dataSize=2
+    bri t0, label("globalDescriptor"), flags=(CEZF,)
+    ld t3, tsl, [1, t0, t2], dataSize=8
+    bri t0, label("processDescriptor")
+globalDescriptor:
+    ld t3, tsg, [1, t0, t2], dataSize=8
+processDescriptor:
+    chks regm, t3, SSCheck, dataSize=8
+    wrdl reg, t3, regm
     wrsel reg, regm
 };
 
 def macroop MOVSS_S_M {
     ld t1, seg, sib, disp, dataSize=2
-    chks t2, t1, flags=(EZF,), dataSize=8
-    # This actually needs to use the selector as the error code, but it would
-    # be hard to get that information into the instruction at the moment.
-    fault "new GeneralProtection(0)", flags=(CEZF,)
-    ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
-    wrdl reg, t2, t1
+    andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
+    bri t0, label("processDescriptor"), flags=(CEZF,)
+    andi t2, t1, 0xF8, dataSize=8
+    andi t0, t1, 0x4, flags=(EZF,), dataSize=2
+    bri t0, label("globalDescriptor"), flags=(CEZF,)
+    ld t3, tsl, [1, t0, t2], dataSize=8
+    bri t0, label("processDescriptor")
+globalDescriptor:
+    ld t3, tsg, [1, t0, t2], dataSize=8
+processDescriptor:
+    chks t1, t3, SSCheck, dataSize=8
+    wrdl reg, t3, t1
     wrsel reg, t1
 };
 
 def macroop MOVSS_S_P {
     rdip t7
     ld t1, seg, riprel, disp, dataSize=2
-    chks t2, t1, flags=(EZF,), dataSize=8
-    # This actually needs to use the selector as the error code, but it would
-    # be hard to get that information into the instruction at the moment.
-    fault "new GeneralProtection(0)", flags=(CEZF,)
-    ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
-    wrdl reg, t2, t1
+    andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
+    bri t0, label("processDescriptor"), flags=(CEZF,)
+    andi t2, t1, 0xF8, dataSize=8
+    andi t0, t1, 0x4, flags=(EZF,), dataSize=2
+    bri t0, label("globalDescriptor"), flags=(CEZF,)
+    ld t3, tsl, [1, t0, t2], dataSize=8
+    bri t0, label("processDescriptor")
+globalDescriptor:
+    ld t3, tsg, [1, t0, t2], dataSize=8
+processDescriptor:
+    chks t1, t3, SSCheck, dataSize=8
+    wrdl reg, t3, t1
     wrsel reg, t1
 };
 '''
index 35f319528ce89d107f88d7e9bc1b128ac2771c44..b751b9b4f6b79ecbfd482cd5d4ccd322891f34da 100644 (file)
@@ -1030,7 +1030,9 @@ let {{
                     src1, src2, flags, dataSize)
         code = '''
             // The selector is in source 1 and can be at most 16 bits.
-            SegSelector selector = psrc1;
+            SegSelector selector = DestReg;
+            SegDescriptor desc = SrcReg1;
+            HandyM5Reg m5reg = M5Reg;
 
             switch (imm8)
             {
@@ -1044,15 +1046,31 @@ let {{
                         "not implemented.\\n");
                 break;
               case SegSSCheck:
-                panic("SS selector checks not implemented.\\n");
+                if (selector.si || selector.ti) {
+                    if (!desc.p) {
+                        //FIXME This needs to also push the selector.
+                        return new StackFault;
+                    }
+                } else {
+                    if ((m5reg.mode != SixtyFourBitMode || m5reg.cpl == 3) ||
+                            !(desc.s == 1 &&
+                            desc.type.codeOrData == 0 && desc.type.w) ||
+                            (desc.dpl != m5reg.cpl) ||
+                            (selector.rpl != m5reg.cpl)) {
+                        return new GeneralProtection(psrc1 & 0xFFFF);
+                    }
+                }
                 break;
               case SegIretCheck:
                 {
-                    SegAttr csAttr = CSAttr;
-                    if (!selector.si && !selector.ti)
-                        return new GeneralProtection(psrc1 & 0xFFFF);
-                    if (selector.rpl < csAttr.dpl)
+                    if ((!selector.si && !selector.ti) ||
+                            (selector.rpl < m5reg.cpl) ||
+                            !(desc.s == 1 && desc.type.codeOrData == 1) ||
+                            (!desc.type.c && desc.dpl != selector.rpl) ||
+                            (desc.type.c && desc.dpl > selector.rpl))
                         return new GeneralProtection(psrc1 & 0xFFFF);
+                    if (!desc.p)
+                        return new SegmentNotPresent;
                     break;
                 }
               case SegIntCSCheck:
@@ -1062,21 +1080,6 @@ let {{
               default:
                 panic("Undefined segment check type.\\n");
             }
-
-            // Compute the address of the descriptor and set DestReg to it.
-            if (selector.ti) {
-                // A descriptor in the LDT
-                Addr target = (selector.si << 3) + LDTRBase;
-                if (!LDTRSel || (selector.si << 3) + dataSize > LDTRLimit)
-                    fault = new GeneralProtection(selector & mask(16));
-                DestReg = target;
-            } else {
-                // A descriptor in the GDT
-                Addr target = (selector.si << 3) + GDTRBase;
-                if ((selector.si << 3) + dataSize > GDTRLimit)
-                    fault = new GeneralProtection(selector & mask(16));
-                DestReg = target;
-            }
         '''
         flag_code = '''
             // Check for a NULL selector and set ZF,EZF appropriately.
@@ -1108,32 +1111,39 @@ let {{
     class Wrdl(RegOp):
         code = '''
             SegDescriptor desc = SrcReg1;
-            SegAttr attr = 0;
-            attr.dpl = desc.dpl;
-            attr.defaultSize = desc.d;
-            if (!desc.s) {
+            SegSelector selector = SrcReg2;
+            if (selector.si || selector.ti) {
+                SegAttr attr = 0;
+                attr.dpl = desc.dpl;
+                attr.defaultSize = desc.d;
+                if (!desc.s) {
+                    SegBaseDest = SegBaseDest;
+                    SegLimitDest = SegLimitDest;
+                    SegAttrDest = SegAttrDest;
+                    panic("System segment encountered.\\n");
+                } else {
+                    if (!desc.p)
+                        panic("Segment not present.\\n");
+                    if (desc.type.codeOrData) {
+                        attr.readable = desc.type.r;
+                        attr.longMode = desc.l;
+                    } else {
+                        attr.expandDown = desc.type.e;
+                        attr.readable = 1;
+                        attr.writable = desc.type.w;
+                    }
+                    Addr base = desc.baseLow | (desc.baseHigh << 24);
+                    Addr limit = desc.limitLow | (desc.limitHigh << 16);
+                    if (desc.g)
+                        limit = (limit << 12) | mask(12);
+                    SegBaseDest = base;
+                    SegLimitDest = limit;
+                    SegAttrDest = attr;
+                }
+            } else {
                 SegBaseDest = SegBaseDest;
                 SegLimitDest = SegLimitDest;
                 SegAttrDest = SegAttrDest;
-                panic("System segment encountered.\\n");
-            } else {
-                if (!desc.p)
-                    panic("Segment not present.\\n");
-                if (desc.type.codeOrData) {
-                    attr.readable = desc.type.r;
-                    attr.longMode = desc.l;
-                } else {
-                    attr.expandDown = desc.type.e;
-                    attr.readable = 1;
-                    attr.writable = desc.type.w;
-                }
-                Addr base = desc.baseLow | (desc.baseHigh << 24);
-                Addr limit = desc.limitLow | (desc.limitHigh << 16);
-                if (desc.g)
-                    limit = (limit << 12) | mask(12);
-                SegBaseDest = base;
-                SegLimitDest = limit;
-                SegAttrDest = attr;
             }
         '''
 }};
index 5d101a5ae05945115c8b31affeb03b71e01fa959..ba8f63a0e59b94a8dd59ba6cea004b00a21373f3 100644 (file)
@@ -574,14 +574,18 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
             // Check for a NULL segment selector.
             if (!tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg)))
                 return new GeneralProtection(0);
-            SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
-            if (!attr.writable && write)
-                return new GeneralProtection(0);
-            if (!attr.readable && !write && !execute)
-                return new GeneralProtection(0);
+            bool expandDown = false;
+            if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) {
+                SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
+                if (!attr.writable && write)
+                    return new GeneralProtection(0);
+                if (!attr.readable && !write && !execute)
+                    return new GeneralProtection(0);
+                expandDown = attr.expandDown;
+            }
             Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg));
             Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg));
-            if (!attr.expandDown) {
+            if (expandDown) {
                 DPRINTF(TLB, "Checking an expand down segment.\n");
                 // We don't have to worry about the access going around the
                 // end of memory because accesses will be broken up into