X86: First crack at far returns. This is grossly approximate.
--HG-- extra : convert_revision : 23da0338af1f7663ae5ddf2289fb45dd32f37c42
This commit is contained in:
@@ -413,7 +413,10 @@
|
||||
0x0: Inst::ENTER(Iw,Iw);
|
||||
0x1: Inst::LEAVE();
|
||||
0x2: ret_far_Iw();
|
||||
0x3: ret_far();
|
||||
0x3: decode MODE_SUBMODE {
|
||||
0x3, 0x4: ret_far_real();
|
||||
default: Inst::RET_FAR();
|
||||
}
|
||||
0x4: int3();
|
||||
0x5: int_Ib();
|
||||
0x6: decode MODE_SUBMODE {
|
||||
|
||||
@@ -77,4 +77,36 @@ def macroop RET_NEAR_I
|
||||
add rsp, rsp, t2
|
||||
wripi t1, 0
|
||||
};
|
||||
|
||||
def macroop RET_FAR {
|
||||
.adjust_env oszIn64Override
|
||||
|
||||
# Get the return RIP
|
||||
ld t1, ss, [1, t0, rsp]
|
||||
|
||||
# Get the return CS
|
||||
ld t2, ss, [1, t0, rsp], dsz
|
||||
|
||||
# Get the rpl
|
||||
andi t3, t2, 0x3
|
||||
|
||||
# Get the cpl
|
||||
|
||||
# Here we'd check if we're changing priviledge levels. We'll just hope
|
||||
# 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
|
||||
# There should be validity checks on the RIP checks here, but I'll do
|
||||
# that later.
|
||||
wrip t0, t1
|
||||
bri t0, label("end")
|
||||
|
||||
# Do other stuff if they're not.
|
||||
end:
|
||||
fault "NoFault"
|
||||
};
|
||||
'''
|
||||
|
||||
@@ -1010,27 +1010,31 @@ let {{
|
||||
code = '''
|
||||
SegDescriptor desc = SrcReg1;
|
||||
SegAttr attr = 0;
|
||||
Addr base = 0, limit = 0;
|
||||
attr.dpl = desc.dpl;
|
||||
attr.defaultSize = desc.d;
|
||||
if (!desc.p)
|
||||
panic("Segment not present.\\n");
|
||||
if (!desc.s)
|
||||
if (!desc.s) {
|
||||
SegBaseDest = SegBaseDest;
|
||||
SegLimitDest = SegLimitDest;
|
||||
SegAttrDest = SegAttrDest;
|
||||
panic("System segment encountered.\\n");
|
||||
if (desc.type.codeOrData) {
|
||||
panic("Code segment encountered with c = %d, r = %d, a = %d.\\n",
|
||||
desc.type.c, desc.type.r, desc.type.a);
|
||||
} else {
|
||||
attr.expandDown = desc.type.e;
|
||||
attr.readable = 1;
|
||||
attr.writable = desc.type.w;
|
||||
base = desc.baseLow | (desc.baseHigh << 24);
|
||||
limit = desc.limitLow | (desc.limitHigh << 16);
|
||||
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;
|
||||
}
|
||||
SegBaseDest = base;
|
||||
SegLimitDest = limit;
|
||||
SegAttrDest = attr;
|
||||
'''
|
||||
}};
|
||||
|
||||
Reference in New Issue
Block a user