X86: Change how segment loading is performed.
This commit is contained in:
parent
129831c116
commit
66f54a6037
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2007 The Hewlett-Packard Development Company
|
# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use of this software in source and binary forms,
|
# 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]
|
ld t1, ss, [1, t0, rsp]
|
||||||
|
|
||||||
# Get the return CS
|
# Get the return CS
|
||||||
ld t2, ss, [1, t0, rsp], dsz
|
ld t2, ss, [1, t0, rsp], ssz
|
||||||
|
|
||||||
# Get the rpl
|
# Get the rpl
|
||||||
andi t3, t2, 0x3
|
andi t3, t2, 0x3
|
||||||
|
@ -96,12 +96,21 @@ def macroop RET_FAR {
|
||||||
# that doesn't happen yet.
|
# that doesn't happen yet.
|
||||||
|
|
||||||
# Do stuff if they're equal
|
# Do stuff if they're equal
|
||||||
chks t4, t2, flags=(EZF,)
|
andi t0, t2, 0xFC, flags=(EZF,), dataSize=2
|
||||||
fault "new GeneralProtection(0)", flags=(CEZF,)
|
bri t0, label("processDescriptor"), flags=(CEZF,)
|
||||||
ld t3, flatseg, [1, t0, t4], addressSize=8, dataSize=8
|
andi t3, t2, 0xF8, dataSize=8
|
||||||
wrdl cs, t3, t2
|
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
|
# There should be validity checks on the RIP checks here, but I'll do
|
||||||
# that later.
|
# that later.
|
||||||
|
wrdl reg, t3, t2
|
||||||
|
wrsel reg, t2
|
||||||
wrip t0, t1
|
wrip t0, t1
|
||||||
bri t0, label("end")
|
bri t0, label("end")
|
||||||
|
|
||||||
|
|
|
@ -237,65 +237,104 @@ def macroop MOV_REAL_S_P {
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop MOV_S_R {
|
def macroop MOV_S_R {
|
||||||
chks t1, regm, flags=(EZF,), dataSize=8
|
andi t0, regm, 0xFC, flags=(EZF,), dataSize=2
|
||||||
bri t0, label("end"), flags=(CEZF,)
|
bri t0, label("processDescriptor"), flags=(CEZF,)
|
||||||
ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
|
andi t2, regm, 0xF8, dataSize=8
|
||||||
wrdl reg, t2, regm
|
andi t0, regm, 0x4, flags=(EZF,), dataSize=2
|
||||||
end:
|
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
|
wrsel reg, regm
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop MOV_S_M {
|
def macroop MOV_S_M {
|
||||||
ld t1, seg, sib, disp, dataSize=2
|
ld t1, seg, sib, disp, dataSize=2
|
||||||
chks t2, t1, flags=(EZF,), dataSize=8
|
andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
|
||||||
bri t0, label("end"), flags=(CEZF,)
|
bri t0, label("processDescriptor"), flags=(CEZF,)
|
||||||
ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
|
andi t2, t1, 0xF8, dataSize=8
|
||||||
wrdl reg, t2, t1
|
andi t0, t1, 0x4, flags=(EZF,), dataSize=2
|
||||||
end:
|
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
|
wrsel reg, t1
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop MOV_S_P {
|
def macroop MOV_S_P {
|
||||||
rdip t7
|
rdip t7
|
||||||
ld t1, seg, riprel, disp, dataSize=2
|
ld t1, seg, riprel, disp, dataSize=2
|
||||||
chks t2, t1, flags=(EZF,), dataSize=8
|
andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
|
||||||
bri t0, label("end"), flags=(CEZF,)
|
bri t0, label("processDescriptor"), flags=(CEZF,)
|
||||||
ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
|
andi t2, t1, 0xF8, dataSize=8
|
||||||
wrdl reg, t2, t1
|
andi t0, t1, 0x4, flags=(EZF,), dataSize=2
|
||||||
end:
|
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
|
wrsel reg, t1
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop MOVSS_S_R {
|
def macroop MOVSS_S_R {
|
||||||
chks t1, regm, flags=(EZF,), dataSize=8
|
andi t0, regm, 0xFC, flags=(EZF,), dataSize=2
|
||||||
# This actually needs to use the selector as the error code, but it would
|
bri t0, label("processDescriptor"), flags=(CEZF,)
|
||||||
# be hard to get that information into the instruction at the moment.
|
andi t2, regm, 0xF8, dataSize=8
|
||||||
fault "new GeneralProtection(0)", flags=(CEZF,)
|
andi t0, regm, 0x4, flags=(EZF,), dataSize=2
|
||||||
ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
|
bri t0, label("globalDescriptor"), flags=(CEZF,)
|
||||||
wrdl reg, t2, regm
|
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
|
wrsel reg, regm
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop MOVSS_S_M {
|
def macroop MOVSS_S_M {
|
||||||
ld t1, seg, sib, disp, dataSize=2
|
ld t1, seg, sib, disp, dataSize=2
|
||||||
chks t2, t1, flags=(EZF,), dataSize=8
|
andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
|
||||||
# This actually needs to use the selector as the error code, but it would
|
bri t0, label("processDescriptor"), flags=(CEZF,)
|
||||||
# be hard to get that information into the instruction at the moment.
|
andi t2, t1, 0xF8, dataSize=8
|
||||||
fault "new GeneralProtection(0)", flags=(CEZF,)
|
andi t0, t1, 0x4, flags=(EZF,), dataSize=2
|
||||||
ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
|
bri t0, label("globalDescriptor"), flags=(CEZF,)
|
||||||
wrdl reg, t2, t1
|
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
|
wrsel reg, t1
|
||||||
};
|
};
|
||||||
|
|
||||||
def macroop MOVSS_S_P {
|
def macroop MOVSS_S_P {
|
||||||
rdip t7
|
rdip t7
|
||||||
ld t1, seg, riprel, disp, dataSize=2
|
ld t1, seg, riprel, disp, dataSize=2
|
||||||
chks t2, t1, flags=(EZF,), dataSize=8
|
andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
|
||||||
# This actually needs to use the selector as the error code, but it would
|
bri t0, label("processDescriptor"), flags=(CEZF,)
|
||||||
# be hard to get that information into the instruction at the moment.
|
andi t2, t1, 0xF8, dataSize=8
|
||||||
fault "new GeneralProtection(0)", flags=(CEZF,)
|
andi t0, t1, 0x4, flags=(EZF,), dataSize=2
|
||||||
ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
|
bri t0, label("globalDescriptor"), flags=(CEZF,)
|
||||||
wrdl reg, t2, t1
|
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
|
wrsel reg, t1
|
||||||
};
|
};
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -1030,7 +1030,9 @@ let {{
|
||||||
src1, src2, flags, dataSize)
|
src1, src2, flags, dataSize)
|
||||||
code = '''
|
code = '''
|
||||||
// The selector is in source 1 and can be at most 16 bits.
|
// 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)
|
switch (imm8)
|
||||||
{
|
{
|
||||||
|
@ -1044,15 +1046,31 @@ let {{
|
||||||
"not implemented.\\n");
|
"not implemented.\\n");
|
||||||
break;
|
break;
|
||||||
case SegSSCheck:
|
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;
|
break;
|
||||||
case SegIretCheck:
|
case SegIretCheck:
|
||||||
{
|
{
|
||||||
SegAttr csAttr = CSAttr;
|
if ((!selector.si && !selector.ti) ||
|
||||||
if (!selector.si && !selector.ti)
|
(selector.rpl < m5reg.cpl) ||
|
||||||
return new GeneralProtection(psrc1 & 0xFFFF);
|
!(desc.s == 1 && desc.type.codeOrData == 1) ||
|
||||||
if (selector.rpl < csAttr.dpl)
|
(!desc.type.c && desc.dpl != selector.rpl) ||
|
||||||
|
(desc.type.c && desc.dpl > selector.rpl))
|
||||||
return new GeneralProtection(psrc1 & 0xFFFF);
|
return new GeneralProtection(psrc1 & 0xFFFF);
|
||||||
|
if (!desc.p)
|
||||||
|
return new SegmentNotPresent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SegIntCSCheck:
|
case SegIntCSCheck:
|
||||||
|
@ -1062,21 +1080,6 @@ let {{
|
||||||
default:
|
default:
|
||||||
panic("Undefined segment check type.\\n");
|
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 = '''
|
flag_code = '''
|
||||||
// Check for a NULL selector and set ZF,EZF appropriately.
|
// Check for a NULL selector and set ZF,EZF appropriately.
|
||||||
|
@ -1108,6 +1111,8 @@ let {{
|
||||||
class Wrdl(RegOp):
|
class Wrdl(RegOp):
|
||||||
code = '''
|
code = '''
|
||||||
SegDescriptor desc = SrcReg1;
|
SegDescriptor desc = SrcReg1;
|
||||||
|
SegSelector selector = SrcReg2;
|
||||||
|
if (selector.si || selector.ti) {
|
||||||
SegAttr attr = 0;
|
SegAttr attr = 0;
|
||||||
attr.dpl = desc.dpl;
|
attr.dpl = desc.dpl;
|
||||||
attr.defaultSize = desc.d;
|
attr.defaultSize = desc.d;
|
||||||
|
@ -1135,5 +1140,10 @@ let {{
|
||||||
SegLimitDest = limit;
|
SegLimitDest = limit;
|
||||||
SegAttrDest = attr;
|
SegAttrDest = attr;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
SegBaseDest = SegBaseDest;
|
||||||
|
SegLimitDest = SegLimitDest;
|
||||||
|
SegAttrDest = SegAttrDest;
|
||||||
|
}
|
||||||
'''
|
'''
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -574,14 +574,18 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
|
||||||
// Check for a NULL segment selector.
|
// Check for a NULL segment selector.
|
||||||
if (!tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg)))
|
if (!tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg)))
|
||||||
return new GeneralProtection(0);
|
return new GeneralProtection(0);
|
||||||
|
bool expandDown = false;
|
||||||
|
if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) {
|
||||||
SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
|
SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
|
||||||
if (!attr.writable && write)
|
if (!attr.writable && write)
|
||||||
return new GeneralProtection(0);
|
return new GeneralProtection(0);
|
||||||
if (!attr.readable && !write && !execute)
|
if (!attr.readable && !write && !execute)
|
||||||
return new GeneralProtection(0);
|
return new GeneralProtection(0);
|
||||||
|
expandDown = attr.expandDown;
|
||||||
|
}
|
||||||
Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg));
|
Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg));
|
||||||
Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg));
|
Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg));
|
||||||
if (!attr.expandDown) {
|
if (expandDown) {
|
||||||
DPRINTF(TLB, "Checking an expand down segment.\n");
|
DPRINTF(TLB, "Checking an expand down segment.\n");
|
||||||
// We don't have to worry about the access going around the
|
// We don't have to worry about the access going around the
|
||||||
// end of memory because accesses will be broken up into
|
// end of memory because accesses will be broken up into
|
||||||
|
|
Loading…
Reference in a new issue