summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2008-06-12 00:52:12 -0400
committerGabe Black <gblack@eecs.umich.edu>2008-06-12 00:52:12 -0400
commit66f54a6037873420dbc3bc2c91723225538feddb (patch)
treefaad63a49ecf26057d96a65c64e10b860a34d8ae /src
parent129831c116a6c7031093df624761f8d67bf4e115 (diff)
downloadgem5-66f54a6037873420dbc3bc2c91723225538feddb.tar.xz
X86: Change how segment loading is performed.
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py21
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_transfer/move.py105
-rw-r--r--src/arch/x86/isa/microops/regop.isa98
-rw-r--r--src/arch/x86/tlb.cc16
4 files changed, 151 insertions, 89 deletions
diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
index 0b2e81cbd..b18d48264 100644
--- a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
+++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
@@ -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")
diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
index 16196bcc8..d9a83dfde 100644
--- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
+++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
@@ -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
};
'''
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index 35f319528..b751b9b4f 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -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;
}
'''
}};
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index 5d101a5ae..ba8f63a0e 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -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