Implemented SYSCALL and SYSRET as part of x86-64 emulation.
Since the SYSCALL replaces the LOADALL instruction, it is incompatible with earlier CPU types. At moment, the SYSCALL is only enabled by x86-64 emulation, but the code can be incorporated in IA32 only emulations. Instructions added: 0F 05 SYSCALL (replaces LOADALL) 0F 07 SYSRET (new) TODO: restructure #if ... so that it can be used by non x86-64 emulations.
This commit is contained in:
parent
6ba1fd1b06
commit
a0d90e9b39
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.78 2002-09-24 18:33:37 kevinlawton Exp $
|
||||
// $Id: cpu.h,v 1.79 2002-09-25 12:54:39 ptrumpet Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -166,6 +166,13 @@ typedef Bit32u bx_address;
|
||||
#if BX_SUPPORT_X86_64
|
||||
// access to 64 bit instruction pointer
|
||||
#define RIP BX_CPU_THIS_PTR rip
|
||||
|
||||
// access to 64 bit MSR registers
|
||||
#define MSR_STAR (BX_CPU_THIS_PTR msr.star)
|
||||
#define MSR_LSTAR (BX_CPU_THIS_PTR msr.lstar)
|
||||
#define MSR_CSTAR (BX_CPU_THIS_PTR msr.cstar)
|
||||
#define MSR_FMASK (BX_CPU_THIS_PTR msr.fmask)
|
||||
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
@ -2226,6 +2233,10 @@ union {
|
||||
BX_SMF void POP64_GS(bxInstruction_c *);
|
||||
BX_SMF void PUSH64_SS(bxInstruction_c *);
|
||||
BX_SMF void POP64_SS(bxInstruction_c *);
|
||||
|
||||
BX_SMF void SYSCALL(bxInstruction_c *i);
|
||||
BX_SMF void SYSRET(bxInstruction_c *i);
|
||||
|
||||
#endif // #if BX_SUPPORT_X86_64
|
||||
|
||||
// mch added
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: exception.cc,v 1.19 2002-09-25 06:36:42 ptrumpet Exp $
|
||||
// $Id: exception.cc,v 1.20 2002-09-25 12:54:40 ptrumpet Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -1059,3 +1059,262 @@ BX_CPU_C::shutdown_cpu(void)
|
||||
BX_PANIC(("shutdown_cpu(): not finished"));
|
||||
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
void
|
||||
BX_CPU_C::SYSCALL(bxInstruction_c *i)
|
||||
{
|
||||
|
||||
/* pseudo code from AMD manual.
|
||||
|
||||
SYSCALL_START:
|
||||
|
||||
IF (MSR_EFER.SCE = 0) // Check if syscall/sysret are enabled.
|
||||
EXCEPTION [#UD]
|
||||
|
||||
IF (LONG_MODE)
|
||||
SYSCALL_LONG_MODE
|
||||
ELSE // (LEGACY_MODE)
|
||||
SYSCALL_LEGACY_MODE
|
||||
|
||||
|
||||
SYSCALL_LONG_MODE:
|
||||
|
||||
RCX.q = next_RIP
|
||||
R11.q = RFLAGS // with rf cleared
|
||||
|
||||
IF (64BIT_MODE)
|
||||
temp_RIP.q = MSR_LSTAR
|
||||
ELSE // (COMPATIBILITY_MODE)
|
||||
temp_RIP.q = MSR_CSTAR
|
||||
|
||||
CS.sel = MSR_STAR.SYSCALL_CS AND 0xFFFC
|
||||
CS.attr = 64-bit code,dpl0 // Always switch to 64-bit mode in long mode.
|
||||
CS.base = 0x00000000
|
||||
CS.limit = 0xFFFFFFFF
|
||||
|
||||
SS.sel = MSR_STAR.SYSCALL_CS + 8
|
||||
SS.attr = 64-bit stack,dpl0
|
||||
SS.base = 0x00000000
|
||||
SS.limit = 0xFFFFFFFF
|
||||
|
||||
RFLAGS = RFLAGS AND ~MSR_SFMASK
|
||||
RFLAGS.RF = 0
|
||||
|
||||
CPL = 0
|
||||
|
||||
RIP = temp_RIP
|
||||
EXIT
|
||||
|
||||
SYSCALL_LEGACY_MODE:
|
||||
|
||||
RCX.d = next_RIP
|
||||
|
||||
temp_RIP.d = MSR_STAR.EIP
|
||||
|
||||
CS.sel = MSR_STAR.SYSCALL_CS AND 0xFFFC
|
||||
CS.attr = 32-bit code,dpl0 // Always switch to 32-bit mode in legacy mode.
|
||||
CS.base = 0x00000000
|
||||
CS.limit = 0xFFFFFFFF
|
||||
|
||||
SS.sel = MSR_STAR.SYSCALL_CS + 8
|
||||
SS.attr = 32-bit stack,dpl0
|
||||
SS.base = 0x00000000
|
||||
SS.limit = 0xFFFFFFFF
|
||||
|
||||
RFLAGS.VM,IF,RF=0
|
||||
|
||||
CPL = 0
|
||||
|
||||
RIP = temp_RIP
|
||||
EXIT
|
||||
|
||||
*/
|
||||
|
||||
bx_address temp_RIP;
|
||||
bx_descriptor_t cs_descriptor,ss_descriptor;
|
||||
bx_selector_t cs_selector,ss_selector;
|
||||
Bit32u dword1, dword2;
|
||||
|
||||
|
||||
|
||||
if (!BX_CPU_THIS_PTR msr.sce) {
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
invalidate_prefetch_q();
|
||||
if (BX_CPU_THIS_PTR msr.lma) {
|
||||
|
||||
RCX = RIP;
|
||||
#warning - PRT: SYSCALL -- do we reset RF/VM before saving to R11?
|
||||
R11 = read_eflags();
|
||||
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
|
||||
temp_RIP = MSR_LSTAR;
|
||||
}
|
||||
else {
|
||||
temp_RIP = MSR_CSTAR;
|
||||
}
|
||||
|
||||
parse_selector((MSR_STAR >> 32) & 0xFFFC, &cs_selector);
|
||||
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &cs_descriptor);
|
||||
load_cs(&cs_selector, &cs_descriptor, 0);
|
||||
|
||||
parse_selector((MSR_STAR >> 32) + 8, &ss_selector);
|
||||
fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &ss_descriptor);
|
||||
load_ss(&ss_selector, &ss_descriptor, 0);
|
||||
|
||||
write_eflags(read_eflags() & MSR_FMASK,1,1,1,0);
|
||||
BX_CPU_THIS_PTR clear_RF ();
|
||||
RIP = temp_RIP;
|
||||
}
|
||||
else {
|
||||
// legacy mode
|
||||
|
||||
ECX = EIP;
|
||||
|
||||
temp_RIP = MSR_STAR & 0xFFFFFFFF;
|
||||
|
||||
parse_selector((MSR_STAR >> 32) & 0xFFFC, &cs_selector);
|
||||
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &cs_descriptor);
|
||||
load_cs(&cs_selector, &cs_descriptor, 0);
|
||||
|
||||
parse_selector((MSR_STAR >> 32) + 8, &ss_selector);
|
||||
fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &ss_descriptor);
|
||||
load_ss(&ss_selector, &ss_descriptor, 0);
|
||||
|
||||
BX_CPU_THIS_PTR clear_VM ();
|
||||
BX_CPU_THIS_PTR clear_IF ();
|
||||
BX_CPU_THIS_PTR clear_RF ();
|
||||
RIP = temp_RIP;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
BX_CPU_C::SYSRET(bxInstruction_c *i)
|
||||
{
|
||||
/* from AMD manual
|
||||
|
||||
SYSRET_START:
|
||||
|
||||
IF (MSR_EFER.SCE = 0) // Check if syscall/sysret are enabled.
|
||||
EXCEPTION [#UD]
|
||||
|
||||
IF ((!PROTECTED_MODE) || (CPL != 0))
|
||||
EXCEPTION [#GP(0)] // SYSRET requires protected mode, cpl0
|
||||
|
||||
IF (64BIT_MODE)
|
||||
SYSRET_64BIT_MODE
|
||||
ELSE // (!64BIT_MODE)
|
||||
SYSRET_NON_64BIT_MODE
|
||||
|
||||
SYSRET_64BIT_MODE:
|
||||
IF (OPERAND_SIZE = 64) // Return to 64-bit mode.
|
||||
{
|
||||
CS.sel = (MSR_STAR.SYSRET_CS + 16) OR 3
|
||||
CS.base = 0x00000000
|
||||
CS.limit = 0xFFFFFFFF
|
||||
CS.attr = 64-bit code,dpl3
|
||||
temp_RIP.q = RCX
|
||||
}
|
||||
ELSE // Return to 32-bit compatibility mode.
|
||||
{
|
||||
CS.sel = MSR_STAR.SYSRET_CS OR 3
|
||||
CS.base = 0x00000000
|
||||
CS.limit = 0xFFFFFFFF
|
||||
CS.attr = 32-bit code,dpl3
|
||||
temp_RIP.d = RCX
|
||||
}
|
||||
SS.sel = MSR_STAR.SYSRET_CS + 8 // SS selector is changed,
|
||||
// SS base, limit, attributes unchanged.
|
||||
RFLAGS.q = R11 // RF=0,VM=0
|
||||
CPL = 3
|
||||
RIP = temp_RIP
|
||||
EXIT
|
||||
|
||||
SYSRET_NON_64BIT_MODE:
|
||||
CS.sel = MSR_STAR.SYSRET_CS OR 3 // Return to 32-bit legacy protected mode.
|
||||
CS.base = 0x00000000
|
||||
CS.limit = 0xFFFFFFFF
|
||||
CS.attr = 32-bit code,dpl3
|
||||
temp_RIP.d = RCX
|
||||
SS.sel = MSR_STAR.SYSRET_CS + 8 // SS selector is changed.
|
||||
// SS base, limit, attributes unchanged.
|
||||
RFLAGS.IF = 1
|
||||
CPL = 3
|
||||
RIP = temp_RIP
|
||||
EXIT
|
||||
|
||||
*/
|
||||
|
||||
bx_address temp_RIP;
|
||||
bx_descriptor_t cs_descriptor,ss_descriptor;
|
||||
bx_selector_t cs_selector,ss_selector;
|
||||
Bit32u dword1, dword2;
|
||||
|
||||
if (!BX_CPU_THIS_PTR msr.sce) {
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
if(real_mode() || CPL != 0) {
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
|
||||
if (i->os64L()) { // Return to 64-bit mode.
|
||||
|
||||
parse_selector(((MSR_STAR >> 48) + 16) | 3, &cs_selector);
|
||||
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &cs_descriptor);
|
||||
load_cs(&cs_selector, &cs_descriptor, 3);
|
||||
|
||||
temp_RIP = RCX;
|
||||
|
||||
}
|
||||
else { // Return to 32-bit compatibility mode.
|
||||
|
||||
parse_selector((MSR_STAR >> 48) | 3, &cs_selector);
|
||||
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &cs_descriptor);
|
||||
load_cs(&cs_selector, &cs_descriptor, 3);
|
||||
|
||||
temp_RIP = ECX;
|
||||
|
||||
}
|
||||
|
||||
parse_selector((MSR_STAR >> 48) + 8, &ss_selector);
|
||||
fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &ss_descriptor);
|
||||
load_ss(&ss_selector, &ss_descriptor, 0);
|
||||
|
||||
// SS base, limit, attributes unchanged.
|
||||
write_eflags(R11,1,1,1,1);
|
||||
|
||||
RIP = temp_RIP;
|
||||
|
||||
}
|
||||
else { // (!64BIT_MODE)
|
||||
|
||||
parse_selector((MSR_STAR >> 48) + 16, &cs_selector);
|
||||
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &cs_descriptor);
|
||||
load_cs(&cs_selector, &cs_descriptor, 3);
|
||||
|
||||
temp_RIP = ECX;
|
||||
|
||||
parse_selector((MSR_STAR >> 48) + 8, &ss_selector);
|
||||
fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION);
|
||||
parse_descriptor(dword1, dword2, &ss_descriptor);
|
||||
load_ss(&ss_selector, &ss_descriptor, 0);
|
||||
|
||||
BX_CPU_THIS_PTR assert_IF ();
|
||||
|
||||
RIP = temp_RIP;
|
||||
}
|
||||
|
||||
}
|
||||
#endif // BX_SUPPORT_X86_64
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: fetchdecode.cc,v 1.19 2002-09-22 18:22:24 kevinlawton Exp $
|
||||
// $Id: fetchdecode.cc,v 1.20 2002-09-25 12:54:41 ptrumpet Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -646,9 +646,17 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
|
||||
/* 0F 02 */ { BxAnother, &BX_CPU_C::LAR_GvEw },
|
||||
/* 0F 03 */ { BxAnother, &BX_CPU_C::LSL_GvEw },
|
||||
/* 0F 04 */ { 0, &BX_CPU_C::BxError },
|
||||
#if BX_SUPPORT_X86_64
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::SYSCALL },
|
||||
#else
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::LOADALL },
|
||||
#endif
|
||||
/* 0F 06 */ { 0, &BX_CPU_C::CLTS },
|
||||
#if BX_SUPPORT_X86_64
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::SYSRET },
|
||||
#else
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::BxError },
|
||||
#endif
|
||||
/* 0F 08 */ { 0, &BX_CPU_C::INVD },
|
||||
/* 0F 09 */ { 0, &BX_CPU_C::WBINVD },
|
||||
/* 0F 0A */ { 0, &BX_CPU_C::BxError },
|
||||
@ -1167,9 +1175,17 @@ static BxOpcodeInfo_t BxOpcodeInfo[512*2] = {
|
||||
/* 0F 02 */ { BxAnother, &BX_CPU_C::LAR_GvEw },
|
||||
/* 0F 03 */ { BxAnother, &BX_CPU_C::LSL_GvEw },
|
||||
/* 0F 04 */ { 0, &BX_CPU_C::BxError },
|
||||
#if BX_SUPPORT_X86_64
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::SYSCALL },
|
||||
#else
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::LOADALL },
|
||||
#endif
|
||||
/* 0F 06 */ { 0, &BX_CPU_C::CLTS },
|
||||
#if BX_SUPPORT_X86_64
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::SYSRET },
|
||||
#else
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::BxError },
|
||||
#endif
|
||||
/* 0F 08 */ { 0, &BX_CPU_C::INVD },
|
||||
/* 0F 09 */ { 0, &BX_CPU_C::WBINVD },
|
||||
/* 0F 0A */ { 0, &BX_CPU_C::BxError },
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: fetchdecode64.cc,v 1.12 2002-09-25 03:32:12 bdenney Exp $
|
||||
// $Id: fetchdecode64.cc,v 1.13 2002-09-25 12:54:41 ptrumpet Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -726,9 +726,9 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
|
||||
/* 0F 02 */ { BxAnother, &BX_CPU_C::LAR_GvEw },
|
||||
/* 0F 03 */ { BxAnother, &BX_CPU_C::LSL_GvEw },
|
||||
/* 0F 04 */ { 0, &BX_CPU_C::BxError },
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::LOADALL },
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::SYSCALL },
|
||||
/* 0F 06 */ { 0, &BX_CPU_C::CLTS },
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::BxError },
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::SYSRET },
|
||||
/* 0F 08 */ { 0, &BX_CPU_C::INVD },
|
||||
/* 0F 09 */ { 0, &BX_CPU_C::WBINVD },
|
||||
/* 0F 0A */ { 0, &BX_CPU_C::BxError },
|
||||
@ -1242,9 +1242,9 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
|
||||
/* 0F 02 */ { BxAnother, &BX_CPU_C::LAR_GvEw },
|
||||
/* 0F 03 */ { BxAnother, &BX_CPU_C::LSL_GvEw },
|
||||
/* 0F 04 */ { 0, &BX_CPU_C::BxError },
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::LOADALL },
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::SYSCALL },
|
||||
/* 0F 06 */ { 0, &BX_CPU_C::CLTS },
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::BxError },
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::SYSRET },
|
||||
/* 0F 08 */ { 0, &BX_CPU_C::INVD },
|
||||
/* 0F 09 */ { 0, &BX_CPU_C::WBINVD },
|
||||
/* 0F 0A */ { 0, &BX_CPU_C::BxError },
|
||||
@ -1757,9 +1757,9 @@ static BxOpcodeInfo_t BxOpcodeInfo64[512*3] = {
|
||||
/* 0F 02 */ { BxAnother, &BX_CPU_C::LAR_GvEw },
|
||||
/* 0F 03 */ { BxAnother, &BX_CPU_C::LSL_GvEw },
|
||||
/* 0F 04 */ { 0, &BX_CPU_C::BxError },
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::LOADALL },
|
||||
/* 0F 05 */ { 0, &BX_CPU_C::SYSCALL },
|
||||
/* 0F 06 */ { 0, &BX_CPU_C::CLTS },
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::BxError },
|
||||
/* 0F 07 */ { 0, &BX_CPU_C::SYSRET },
|
||||
/* 0F 08 */ { 0, &BX_CPU_C::INVD },
|
||||
/* 0F 09 */ { 0, &BX_CPU_C::WBINVD },
|
||||
/* 0F 0A */ { 0, &BX_CPU_C::BxError },
|
||||
|
Loading…
x
Reference in New Issue
Block a user