From fe833dd2c33818a1f92f87ea26b17e6b85d3976e Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 1 Dec 2007 23:05:01 -0800 Subject: X86: First crack at far returns. This is grossly approximate. --HG-- extra : convert_revision : 23da0338af1f7663ae5ddf2289fb45dd32f37c42 --- src/arch/x86/isa/decoder/one_byte_opcodes.isa | 5 +++- .../general_purpose/control_transfer/xreturn.py | 32 ++++++++++++++++++++ src/arch/x86/isa/microops/regop.isa | 34 ++++++++++++---------- 3 files changed, 55 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index 0d1d7aacd..332ae1641 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -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 { 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 8993f5ac4..0b2e81cbd 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 @@ -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" +}; ''' diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 7f72fcf1d..de9f76e73 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -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; ''' }}; -- cgit v1.2.3