X86: Change how segment loading is performed.
This commit is contained in:
parent
129831c116
commit
66f54a6037
4 changed files with 151 additions and 89 deletions
|
@ -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")
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
'''
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
'''
|
||||
}};
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue