Fixes in SYSCALL/SYSRET instructions

Use parse_selector to avoid code duplication
This commit is contained in:
Stanislav Shwartsman 2006-06-11 21:37:22 +00:00
parent bfebb40326
commit 308521e7ce
4 changed files with 222 additions and 105 deletions

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: cpu.cc,v 1.159 2006-06-06 16:46:07 sshwarts Exp $ // $Id: cpu.cc,v 1.160 2006-06-11 21:37:22 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -224,7 +224,7 @@ void BX_CPU_C::cpu_loop(Bit32u max_instr_count)
// the debugger may request that control is returned to it so that // the debugger may request that control is returned to it so that
// the situation may be examined. // the situation may be examined.
if (bx_guard.special_unwind_stack) { if (bx_guard.special_unwind_stack) {
BX_ERROR(("CPU_LOOP bx_guard.special_unwind_stack=%d\n", bx_guard.special_unwind_stack)); BX_ERROR(("CPU_LOOP bx_guard.special_unwind_stack=%d", bx_guard.special_unwind_stack));
return; return;
} }
#endif #endif

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: init.cc,v 1.116 2006-06-06 18:36:50 vruppert Exp $ // $Id: init.cc,v 1.117 2006-06-11 21:37:22 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -775,20 +775,19 @@ void BX_CPU_C::reset(unsigned source)
* 286 F000 FF0000 FFFF FFF0 * 286 F000 FF0000 FFFF FFF0
* 386+ F000 FFFF0000 FFFF FFF0 * 386+ F000 FFFF0000 FFFF FFF0
*/ */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = 0xF000;
#if BX_CPU_LEVEL >= 2
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl = 0;
parse_selector(0xf000,
&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector);
#if BX_CPU_LEVEL >= 2
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = 11; /* executable/readable/access code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = 11; /* executable/readable/access code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1; /* data/stack segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1; /* executable segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; /* normal expand up */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; /* non-confirming */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; /* writeable */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; /* writeable */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a = 1; /* accessed */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a = 1; /* accessed */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0xFFFF0000; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0xFFFF0000;
@ -809,12 +808,11 @@ void BX_CPU_C::reset(unsigned source)
#endif #endif
/* DS (Data Segment) and descriptor cache */ /* DS (Data Segment) and descriptor cache */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value = 0x0000;
#if BX_CPU_LEVEL >= 2
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.index = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.ti = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.rpl = 0;
parse_selector(0x0000,
&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector);
#if BX_CPU_LEVEL >= 2
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.dpl = 0;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.151 2006-06-09 22:29:07 sshwarts Exp $ // $Id: proc_ctrl.cc,v 1.152 2006-06-11 21:37:22 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -1864,18 +1864,16 @@ do_exception:
#endif #endif
} }
void BX_CPU_C::SYSENTER (bxInstruction_c *i) void BX_CPU_C::SYSENTER(bxInstruction_c *i)
{ {
#if BX_SUPPORT_SEP #if BX_SUPPORT_SEP
if (!protected_mode ()) { if (!protected_mode()) {
BX_INFO(("sysenter not from protected mode !")); BX_ERROR(("sysenter not from protected mode !"));
exception(BX_GP_EXCEPTION, 0, 0); exception(BX_GP_EXCEPTION, 0, 0);
return;
} }
if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) { if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) {
BX_INFO(("sysenter with zero sysenter_cs_msr !")); BX_ERROR(("sysenter with zero sysenter_cs_msr !"));
exception(BX_GP_EXCEPTION, 0, 0); exception(BX_GP_EXCEPTION, 0, 0);
return;
} }
invalidate_prefetch_q(); invalidate_prefetch_q();
@ -1884,10 +1882,9 @@ void BX_CPU_C::SYSENTER (bxInstruction_c *i)
BX_CPU_THIS_PTR clear_IF(); BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_RF(); BX_CPU_THIS_PTR clear_RF();
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK; parse_selector(BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index = BX_CPU_THIS_PTR msr.sysenter_cs_msr >> 3; &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti =(BX_CPU_THIS_PTR msr.sysenter_cs_msr >> 2) & 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1; // code segment BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1; // code segment
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; // non-conforming BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; // non-conforming
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; // readable BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; // readable
@ -1903,10 +1900,9 @@ void BX_CPU_C::SYSENTER (bxInstruction_c *i)
BX_CPU_THIS_PTR updateFetchModeMask(); BX_CPU_THIS_PTR updateFetchModeMask();
#endif #endif
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value = (BX_CPU_THIS_PTR msr.sysenter_cs_msr + 8) & BX_SELECTOR_RPL_MASK; parse_selector((BX_CPU_THIS_PTR msr.sysenter_cs_msr + 8) & BX_SELECTOR_RPL_MASK,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.index = (BX_CPU_THIS_PTR msr.sysenter_cs_msr + 8) >> 3; &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.ti =((BX_CPU_THIS_PTR msr.sysenter_cs_msr + 8) >> 2) & 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.executable = 0; // data segment BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.executable = 0; // data segment
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.c_ed = 0; // expand-up BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.c_ed = 0; // expand-up
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.r_w = 1; // writeable BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.r_w = 1; // writeable
@ -1926,15 +1922,15 @@ void BX_CPU_C::SYSENTER (bxInstruction_c *i)
#endif #endif
} }
void BX_CPU_C::SYSEXIT (bxInstruction_c *i) void BX_CPU_C::SYSEXIT(bxInstruction_c *i)
{ {
#if BX_SUPPORT_SEP #if BX_SUPPORT_SEP
if (!protected_mode ()) { if (!protected_mode()) {
BX_INFO(("sysexit not from protected mode !")); BX_ERROR(("sysexit not from protected mode !"));
exception(BX_GP_EXCEPTION, 0, 0); exception(BX_GP_EXCEPTION, 0, 0);
} }
if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) { if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) {
BX_INFO(("sysexit with zero sysenter_cs_msr !")); BX_ERROR(("sysexit with zero sysenter_cs_msr !"));
exception(BX_GP_EXCEPTION, 0, 0); exception(BX_GP_EXCEPTION, 0, 0);
} }
if (CPL != 0) { if (CPL != 0) {
@ -1944,10 +1940,9 @@ void BX_CPU_C::SYSEXIT (bxInstruction_c *i)
invalidate_prefetch_q(); invalidate_prefetch_q();
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = (BX_CPU_THIS_PTR msr.sysenter_cs_msr + 16) | 3; parse_selector((BX_CPU_THIS_PTR msr.sysenter_cs_msr + 16) | 3,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index = (BX_CPU_THIS_PTR msr.sysenter_cs_msr + 16) >> 3; &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti =((BX_CPU_THIS_PTR msr.sysenter_cs_msr + 16) >> 2) & 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl = 3;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1; // code segment BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1; // code segment
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; // non-conforming BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; // non-conforming
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; // readable BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; // readable
@ -1963,10 +1958,9 @@ void BX_CPU_C::SYSEXIT (bxInstruction_c *i)
BX_CPU_THIS_PTR updateFetchModeMask(); BX_CPU_THIS_PTR updateFetchModeMask();
#endif #endif
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value = (BX_CPU_THIS_PTR msr.sysenter_cs_msr + 24) | 3; parse_selector((BX_CPU_THIS_PTR msr.sysenter_cs_msr + 24) | 3,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.index = (BX_CPU_THIS_PTR msr.sysenter_cs_msr + 24) >> 3; &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.ti =((BX_CPU_THIS_PTR msr.sysenter_cs_msr + 24) >> 2) & 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl = 3;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.executable = 0; // data segment BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.executable = 0; // data segment
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.c_ed = 0; // expand-up BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.c_ed = 0; // expand-up
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.r_w = 1; // writeable BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.r_w = 1; // writeable
@ -2057,9 +2051,6 @@ SYSCALL_LEGACY_MODE:
*/ */
bx_address temp_RIP; bx_address temp_RIP;
bx_descriptor_t cs_descriptor,ss_descriptor;
bx_selector_t cs_selector,ss_selector;
Bit32u dword1, dword2;
BX_DEBUG(("Execute SYSCALL instruction")); BX_DEBUG(("Execute SYSCALL instruction"));
@ -2081,15 +2072,51 @@ SYSCALL_LEGACY_MODE:
temp_RIP = MSR_CSTAR; temp_RIP = MSR_CSTAR;
} }
parse_selector((MSR_STAR >> 32) & 0xFFFC, &cs_selector); // set up CS segment, flat, 64-bit DPL=0
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_selector((MSR_STAR >> 32) & BX_SELECTOR_RPL_MASK,
parse_descriptor(dword1, dword2, &cs_descriptor); &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector);
load_cs(&cs_selector, &cs_descriptor, 0);
parse_selector((MSR_STAR >> 32) + 8, &ss_selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1;
fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1;
parse_descriptor(dword1, dword2, &ss_descriptor); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0;
load_ss(&ss_selector, &ss_descriptor, 0); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = 11; /* executable/readable/access code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; /* non-conforming */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; /* writeable */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a = 1; /* accessed */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFF; /* segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 1; /* 64-bit code */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */
#if BX_SUPPORT_ICACHE
BX_CPU_THIS_PTR updateFetchModeMask();
#endif
// set up SS segment, flat, 64-bit DPL=0
parse_selector(((MSR_STAR >> 32) + 8) & BX_SELECTOR_RPL_MASK,
&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type = 3; /* read/write/access */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.executable = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.c_ed = 0; /* normal expand up */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.r_w = 1; /* writeable */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.a = 1; /* accessed */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base = 0; /* base address */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit = 0xFFFF; /* segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g = 1; /* 4k granularity */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b = 1; /* 32 bit stack */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.l = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.avl = 0; /* available for use by system */
writeEFlags(read_eflags() & (~MSR_FMASK), EFlagsValidMask); writeEFlags(read_eflags() & (~MSR_FMASK), EFlagsValidMask);
BX_CPU_THIS_PTR clear_RF(); BX_CPU_THIS_PTR clear_RF();
@ -2101,19 +2128,55 @@ SYSCALL_LEGACY_MODE:
ECX = EIP; ECX = EIP;
temp_RIP = MSR_STAR & 0xFFFFFFFF; temp_RIP = MSR_STAR & 0xFFFFFFFF;
parse_selector((MSR_STAR >> 32) & 0xFFFC, &cs_selector); // set up CS segment, flat, 32-bit DPL=0
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_selector((MSR_STAR >> 32) & BX_SELECTOR_RPL_MASK,
parse_descriptor(dword1, dword2, &cs_descriptor); &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector);
load_cs(&cs_selector, &cs_descriptor, 0);
parse_selector((MSR_STAR >> 32) + 8, &ss_selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1;
fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1;
parse_descriptor(dword1, dword2, &ss_descriptor); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0;
load_ss(&ss_selector, &ss_descriptor, 0); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = 11; /* executable/readable/access code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; /* non-conforming */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; /* writeable */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a = 1; /* accessed */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFF; /* segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; /* 32-bit code */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */
BX_CPU_THIS_PTR clear_VM (); #if BX_SUPPORT_ICACHE
BX_CPU_THIS_PTR clear_IF (); BX_CPU_THIS_PTR updateFetchModeMask();
BX_CPU_THIS_PTR clear_RF (); #endif
// set up SS segment, flat, 32-bit DPL=0
parse_selector(((MSR_STAR >> 32) + 8) & BX_SELECTOR_RPL_MASK,
&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type = 3; /* read/write/access */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.executable = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.c_ed = 0; /* normal expand up */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.r_w = 1; /* writeable */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.a = 1; /* accessed */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base = 0; /* base address */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit = 0xFFFF; /* segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g = 1; /* 4k granularity */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b = 1; /* 32 bit stack */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.l = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.avl = 0; /* available for use by system */
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_RF();
RIP = temp_RIP; RIP = temp_RIP;
} }
} }
@ -2175,9 +2238,6 @@ SYSRET_NON_64BIT_MODE:
*/ */
bx_address temp_RIP; bx_address temp_RIP;
bx_descriptor_t cs_descriptor,ss_descriptor;
bx_selector_t cs_selector,ss_selector;
Bit32u dword1, dword2;
BX_DEBUG(("Execute SYSRET instruction")); BX_DEBUG(("Execute SYSRET instruction"));
@ -2194,51 +2254,112 @@ SYSRET_NON_64BIT_MODE:
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
{ {
if (i->os64L()) { // Return to 64-bit mode if (i->os64L()) {
parse_selector(((MSR_STAR >> 48) + 16) | 3, &cs_selector); // Return to 64-bit mode, set up CS segment, flat, 64-bit DPL=3
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_selector(((MSR_STAR >> 48) + 16) | 3,
parse_descriptor(dword1, dword2, &cs_descriptor); &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector);
load_cs(&cs_selector, &cs_descriptor, 3);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 3;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = 11; /* executable/readable/access code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; /* non-conforming */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; /* writeable */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a = 1; /* accessed */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFF; /* segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 1; /* 64-bit code */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */
temp_RIP = RCX; temp_RIP = RCX;
} }
else { // Return to 32-bit compatibility mode else {
parse_selector((MSR_STAR >> 48) | 3, &cs_selector); // Return to 32-bit compatibility mode, set up CS segment, flat, 32-bit DPL=3
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_selector((MSR_STAR >> 48) | 3,
parse_descriptor(dword1, dword2, &cs_descriptor); &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector);
load_cs(&cs_selector, &cs_descriptor, 3);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 3;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = 11; /* executable/readable/access code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; /* non-conforming */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; /* writeable */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a = 1; /* accessed */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFF; /* segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; /* 32-bit code */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */
temp_RIP = ECX; temp_RIP = ECX;
} }
parse_selector((MSR_STAR >> 48) + 8, &ss_selector); #if BX_SUPPORT_ICACHE
fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION); BX_CPU_THIS_PTR updateFetchModeMask();
parse_descriptor(dword1, dword2, &ss_descriptor); #endif
// SS base, limit, attributes unchanged.
load_ss(&ss_selector, &ss_descriptor, 0); // SS base, limit, attributes unchanged
parse_selector((MSR_STAR >> 48) + 8,
&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 3;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */
writeEFlags(R11, EFlagsValidMask); writeEFlags(R11, EFlagsValidMask);
RIP = temp_RIP; RIP = temp_RIP;
} }
else { // (!64BIT_MODE) else { // (!64BIT_MODE)
parse_selector((MSR_STAR >> 48) | 3, &cs_selector); // Return to 32-bit legacy mode, set up CS segment, flat, 32-bit DPL=3
fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_selector((MSR_STAR >> 48) | 3,
parse_descriptor(dword1, dword2, &cs_descriptor); &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector);
load_cs(&cs_selector, &cs_descriptor, 3);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 3;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = 11; /* executable/readable/access code segment */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; /* non-conforming */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; /* writeable */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a = 1; /* accessed */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFF; /* segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; /* 32-bit code */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */
#if BX_SUPPORT_ICACHE
BX_CPU_THIS_PTR updateFetchModeMask();
#endif
// SS base, limit, attributes unchanged
parse_selector((MSR_STAR >> 48) + 8,
&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 3;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */
BX_CPU_THIS_PTR assert_IF();
temp_RIP = ECX; 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);
// SS base, limit, attributes unchanged.
load_ss(&ss_selector, &ss_descriptor, 0);
BX_CPU_THIS_PTR assert_IF ();
RIP = temp_RIP;
} }
RIP = temp_RIP;
} }
void BX_CPU_C::SWAPGS(bxInstruction_c *i) void BX_CPU_C::SWAPGS(bxInstruction_c *i)

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: smm.cc,v 1.17 2006-05-21 20:41:48 sshwarts Exp $ // $Id: smm.cc,v 1.18 2006-06-11 21:37:22 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2006 Stanislav Shwartsman // Copyright (c) 2006 Stanislav Shwartsman
@ -153,10 +153,9 @@ void BX_CPU_C::enter_system_management_mode(void)
BX_CPU_THIS_PTR msr.lma = 0; BX_CPU_THIS_PTR msr.lma = 0;
#endif #endif
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = BX_CPU_THIS_PTR smbase >> 4; parse_selector(BX_CPU_THIS_PTR smbase >> 4,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index = 0; &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0;
@ -182,10 +181,9 @@ void BX_CPU_C::enter_system_management_mode(void)
#endif #endif
/* DS (Data Segment) and descriptor cache */ /* DS (Data Segment) and descriptor cache */
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value = 0x0000; parse_selector(0x0000,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.index = 0; &BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.ti = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.rpl = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.p = 1;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.dpl = 0;