From 8adbbcf17c7e7b5d00f7abfc483339c9c1652711 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Thu, 11 Oct 2007 21:29:01 +0000 Subject: [PATCH] Started first implementation of MONITOR/MWAIT --- bochs/config.h.in | 1 + bochs/configure | 92 ++++++++++++------ bochs/configure.in | 19 +++- bochs/cpu/cpu.h | 16 +--- bochs/cpu/cpuid.cc | 36 ++++++- bochs/cpu/crregs.h | 13 ++- bochs/cpu/fetchdecode.cc | 17 +++- bochs/cpu/fetchdecode64.cc | 22 +++-- bochs/cpu/proc_ctrl.cc | 191 +++++++++++++------------------------ bochs/cpu/todo | 2 + bochs/main.cc | 3 +- 11 files changed, 225 insertions(+), 187 deletions(-) diff --git a/bochs/config.h.in b/bochs/config.h.in index 0e4b4b8f8..2792f91b0 100644 --- a/bochs/config.h.in +++ b/bochs/config.h.in @@ -733,6 +733,7 @@ typedef #define BX_SUPPORT_SEP 0 #define BX_SUPPORT_VME 0 #define BX_SUPPORT_POPCNT 0 +#define BX_SUPPORT_MONITOR_MWAIT 0 #define BX_SUPPORT_MTRR 0 #define BX_SUPPORT_LARGE_PAGES 0 diff --git a/bochs/configure b/bochs/configure index 694054921..e77203179 100755 --- a/bochs/configure +++ b/bochs/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Id: configure.in,v 1.345 2007/09/28 20:26:33 sshwarts Exp . +# From configure.in Id: configure.in,v 1.346 2007/10/08 19:46:37 sshwarts Exp . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.60. # @@ -1583,6 +1583,7 @@ Optional Features: --enable-misaligned-sse misaligned SSE support --enable-sep SYSENTER/SYSEXIT support --enable-popcnt support for POPCNT instruction + --enable-monitor-mwait support for MONITOR/MWAIT instructions --enable-x86-debugger x86 debugger support --enable-cdrom CDROM support --enable-sb16=xxx Sound Blaster 16 Support (xxx=dummy|win|linux|freebsd|osx) @@ -4502,7 +4503,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 4505 "configure"' > conftest.$ac_ext + echo '#line 4506 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6868,11 +6869,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6871: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6872: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:6875: \$? = $ac_status" >&5 + echo "$as_me:6876: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -7101,11 +7102,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7104: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7105: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7108: \$? = $ac_status" >&5 + echo "$as_me:7109: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -7168,11 +7169,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7171: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7172: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7175: \$? = $ac_status" >&5 + echo "$as_me:7176: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -9441,7 +9442,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:11750: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:11753: \$? = $ac_status" >&5 + echo "$as_me:11754: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -11813,11 +11814,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11816: $lt_compile\"" >&5) + (eval echo "\"\$as_me:11817: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:11820: \$? = $ac_status" >&5 + echo "$as_me:11821: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -13235,7 +13236,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"\$as_me:14160: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14163: \$? = $ac_status" >&5 + echo "$as_me:14164: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -14223,11 +14224,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14226: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14227: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:14230: \$? = $ac_status" >&5 + echo "$as_me:14231: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -16266,11 +16267,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16269: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16270: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16273: \$? = $ac_status" >&5 + echo "$as_me:16274: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -16499,11 +16500,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16502: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16503: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16506: \$? = $ac_status" >&5 + echo "$as_me:16507: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings @@ -16566,11 +16567,11 @@ else -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16569: $lt_compile\"" >&5) + (eval echo "\"\$as_me:16570: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:16573: \$? = $ac_status" >&5 + echo "$as_me:16574: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -18839,7 +18840,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <&5 +echo $ECHO_N "checking for MONITOR/MWAIT instructions support... $ECHO_C" >&6; } +# Check whether --enable-monitor_mwait was given. +if test "${enable_monitor_mwait+set}" = set; then + enableval=$enable_monitor_mwait; if test "$enableval" = yes; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + cat >>confdefs.h <<\_ACEOF +#define BX_SUPPORT_MONITOR_MWAIT 1 +_ACEOF + + elif test "$enableval" = no; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + cat >>confdefs.h <<\_ACEOF +#define BX_SUPPORT_MONITOR_MWAIT 0 +_ACEOF + + fi + +else + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + cat >>confdefs.h <<\_ACEOF +#define BX_SUPPORT_MONITOR_MWAIT 0 +_ACEOF + + + fi diff --git a/bochs/configure.in b/bochs/configure.in index 583f05134..804db9502 100644 --- a/bochs/configure.in +++ b/bochs/configure.in @@ -2,7 +2,7 @@ dnl // Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) AC_INIT(bochs.h) -AC_REVISION([[$Id: configure.in,v 1.346 2007-10-08 19:46:37 sshwarts Exp $]]) +AC_REVISION([[$Id: configure.in,v 1.347 2007-10-11 21:28:57 sshwarts Exp $]]) AC_CONFIG_HEADER(config.h) AC_CONFIG_HEADER(ltdlconf.h) @@ -1724,6 +1724,23 @@ AC_ARG_ENABLE(popcnt, ] ) +AC_MSG_CHECKING(for MONITOR/MWAIT instructions support) +AC_ARG_ENABLE(monitor_mwait, + [ --enable-monitor-mwait support for MONITOR/MWAIT instructions], + [if test "$enableval" = yes; then + AC_MSG_RESULT(yes) + AC_DEFINE(BX_SUPPORT_MONITOR_MWAIT, 1) + elif test "$enableval" = no; then + AC_MSG_RESULT(no) + AC_DEFINE(BX_SUPPORT_MONITOR_MWAIT, 0) + fi + ], + [ + AC_MSG_RESULT(no) + AC_DEFINE(BX_SUPPORT_MONITOR_MWAIT, 0) + ] + ) + AC_MSG_CHECKING(for x86 debugger support) AC_ARG_ENABLE(x86-debugger, [ --enable-x86-debugger x86 debugger support], diff --git a/bochs/cpu/cpu.h b/bochs/cpu/cpu.h index 8e7f73b6c..abb997bec 100644 --- a/bochs/cpu/cpu.h +++ b/bochs/cpu/cpu.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpu.h,v 1.332 2007-10-11 18:11:58 sshwarts Exp $ +// $Id: cpu.h,v 1.333 2007-10-11 21:28:58 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -588,17 +588,6 @@ typedef struct } bx_regs_msr_t; #endif -#if BX_SUPPORT_X86_64 -typedef struct bx_efer_t { - // x86-64 EFER bits - bx_bool sce; // system call extensions - bx_bool lme; // long mode enable - bx_bool lma; // long mode active - bx_bool nxe; // no-execute enable - bx_bool ffxsr; // fast FXSAVE/FXRSTOR -} bx_efer_t; -#endif - #include "crregs.h" #include "descriptor.h" @@ -2588,6 +2577,9 @@ public: // for now... BX_SMF void SYSENTER(bxInstruction_c *); BX_SMF void SYSEXIT(bxInstruction_c *); + BX_SMF void MONITOR(bxInstruction_c *); + BX_SMF void MWAIT(bxInstruction_c *); + BX_SMF unsigned fetchDecode32(Bit8u *, bxInstruction_c *, unsigned); #if BX_SUPPORT_X86_64 BX_SMF unsigned fetchDecode64(Bit8u *, bxInstruction_c *, unsigned); diff --git a/bochs/cpu/cpuid.cc b/bochs/cpu/cpuid.cc index c90fbe2c6..2953daefa 100755 --- a/bochs/cpu/cpuid.cc +++ b/bochs/cpu/cpuid.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: cpuid.cc,v 1.50 2007-10-01 21:08:26 sshwarts Exp $ +// $Id: cpuid.cc,v 1.51 2007-10-11 21:28:58 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -41,6 +41,7 @@ #define RDX EDX #endif +#define CACHE_LINE_SIZE 64 /* Get CPU version information. */ Bit32u BX_CPU_C::get_cpu_version_information() @@ -148,6 +149,9 @@ Bit32u BX_CPU_C::get_extended_cpuid_features() #if BX_SUPPORT_SSE >= 3 features |= 0x1; // support SSE3 #endif +#if BX_SUPPORT_MONITOR_MWAIT + features |= (1<<3); // support MONITOR/MWAIT +#endif #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0) features |= (1<<9); // support SSE3E #endif @@ -260,8 +264,10 @@ void BX_CPU_C::CPUID(bxInstruction_c *i) // EAX: highest input value understood by CPUID #if BX_CPU_LEVEL <= 5 RAX = 1; // 486 and Pentium processors +#elif BX_SUPPORT_MONITOR_MWAIT + RAX = 5; // support MONITOR/MWAIT leaf #else - RAX = 2; // for Pentium Pro, Pentium II, Pentium 4 processors + RAX = 2; // for Pentium Pro, Pentium II, Pentium 4 processors #endif // EBX: vendor ID string // EDX: vendor ID string @@ -346,7 +352,7 @@ void BX_CPU_C::CPUID(bxInstruction_c *i) RBX |= (BX_CPU_THIS_PTR local_apic.get_id() << 24); #endif #if BX_SUPPORT_CLFLUSH - RBX |= 8 << 8; // 64 byte cache line size + RBX |= (CACHE_LINE_SIZE / 8) << 8; #endif #if BX_SUPPORT_SMP n_logical_processors = SIM->get_param_num(BXPN_CPU_NCORES)->get()*SIM->get_param_num(BXPN_CPU_NTHREADS)->get(); @@ -365,6 +371,30 @@ void BX_CPU_C::CPUID(bxInstruction_c *i) RDX = 0; break; +#if BX_SUPPORT_MONITOR_MWAIT + case 3: + case 4: + RAX = 0; + RBX = 0; + RCX = 0; + RDX = 0; + break; + + case 5: + // EAX - Smallest monitor-line size in bytes + // EBX - Largest monitor-line size in bytes + // ECX - + // [32:2] - reserved + // [1:1] - exit MWAIT even with EFLAGS.IF = 0 + // [0:0] - MONITOR/MWAIT extensions are supported + // EDX - Reserved + RAX = CACHE_LINE_SIZE; + RBX = CACHE_LINE_SIZE; + RCX = 3; + RDX = 0; + break; +#endif + #if BX_SUPPORT_SSE >= 2 #if BX_SUPPORT_X86_64 diff --git a/bochs/cpu/crregs.h b/bochs/cpu/crregs.h index eb5b176fe..53ffcdb58 100755 --- a/bochs/cpu/crregs.h +++ b/bochs/cpu/crregs.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: crregs.h,v 1.2 2007-09-10 16:04:41 sshwarts Exp $ +// $Id: crregs.h,v 1.3 2007-10-11 21:28:58 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2007 MandrakeSoft S.A. @@ -106,6 +106,17 @@ struct bx_cr4_t { #define CR4_VME_ENABLED (0) #endif +#if BX_SUPPORT_X86_64 +typedef struct bx_efer_t { + // x86-64 EFER bits + bx_bool sce; // system call extensions + bx_bool lme; // long mode enable + bx_bool lma; // long mode active + bx_bool nxe; // no-execute enable + bx_bool ffxsr; // fast FXSAVE/FXRSTOR +} bx_efer_t; +#endif + #undef IMPLEMENT_CRREG_ACCESSORS #endif diff --git a/bochs/cpu/fetchdecode.cc b/bochs/cpu/fetchdecode.cc index fc575e3c4..a7b8f1d5c 100644 --- a/bochs/cpu/fetchdecode.cc +++ b/bochs/cpu/fetchdecode.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: fetchdecode.cc,v 1.109 2007-09-19 19:38:09 sshwarts Exp $ +// $Id: fetchdecode.cc,v 1.110 2007-10-11 21:28:58 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -282,7 +282,6 @@ static const BxOpcodeInfo_t BxOpcodeInfoG5d[8] = { }; static const BxOpcodeInfo_t BxOpcodeInfoG6[8] = { - // attributes defined in main area /* 0 */ { 0, &BX_CPU_C::SLDT_Ew }, /* 1 */ { 0, &BX_CPU_C::STR_Ew }, /* 2 */ { 0, &BX_CPU_C::LLDT_Ew }, @@ -293,10 +292,20 @@ static const BxOpcodeInfo_t BxOpcodeInfoG6[8] = { /* 7 */ { 0, &BX_CPU_C::BxError } }; +static const BxOpcodeInfo_t opcodesGroupRmMONITOR[8] = { + /* 0 */ { 0, &BX_CPU_C::MONITOR }, + /* 1 */ { 0, &BX_CPU_C::MWAIT }, + /* 2 */ { 0, &BX_CPU_C::BxError }, + /* 3 */ { 0, &BX_CPU_C::BxError }, + /* 4 */ { 0, &BX_CPU_C::BxError }, + /* 5 */ { 0, &BX_CPU_C::BxError }, + /* 6 */ { 0, &BX_CPU_C::BxError }, + /* 7 */ { 0, &BX_CPU_C::BxError } +}; + static const BxOpcodeInfo_t BxOpcodeInfoG7R[8] = { - // attributes defined in main area /* 0 */ { 0, &BX_CPU_C::BxError }, - /* 1 */ { 0, &BX_CPU_C::BxError }, + /* 1 */ { BxRMGroup, NULL, opcodesGroupRmMONITOR }, /* 2 */ { 0, &BX_CPU_C::BxError }, /* 3 */ { 0, &BX_CPU_C::BxError }, /* 4 */ { 0, &BX_CPU_C::SMSW_Ew }, diff --git a/bochs/cpu/fetchdecode64.cc b/bochs/cpu/fetchdecode64.cc index 6ab07b478..5f1e16dbf 100644 --- a/bochs/cpu/fetchdecode64.cc +++ b/bochs/cpu/fetchdecode64.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: fetchdecode64.cc,v 1.114 2007-09-19 19:38:10 sshwarts Exp $ +// $Id: fetchdecode64.cc,v 1.115 2007-10-11 21:29:01 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -354,7 +354,6 @@ static const BxOpcodeInfo_t BxOpcodeInfo64G4[8] = { }; static const BxOpcodeInfo_t BxOpcodeInfo64G5w[8] = { - // attributes defined in main area /* 0 */ { BxLockable, &BX_CPU_C::INC_Ew }, /* 1 */ { BxLockable, &BX_CPU_C::DEC_Ew }, /* 2 */ { 0, &BX_CPU_C::CALL_Eq }, @@ -366,7 +365,6 @@ static const BxOpcodeInfo_t BxOpcodeInfo64G5w[8] = { }; static const BxOpcodeInfo_t BxOpcodeInfo64G5d[8] = { - // attributes defined in main area /* 0 */ { BxLockable, &BX_CPU_C::INC_Ed }, /* 1 */ { BxLockable, &BX_CPU_C::DEC_Ed }, /* 2 */ { 0, &BX_CPU_C::CALL_Eq }, @@ -378,7 +376,6 @@ static const BxOpcodeInfo_t BxOpcodeInfo64G5d[8] = { }; static const BxOpcodeInfo_t BxOpcodeInfo64G5q[8] = { - // attributes defined in main area /* 0 */ { BxLockable, &BX_CPU_C::INC_Eq }, /* 1 */ { BxLockable, &BX_CPU_C::DEC_Eq }, /* 2 */ { 0, &BX_CPU_C::CALL_Eq }, @@ -390,7 +387,6 @@ static const BxOpcodeInfo_t BxOpcodeInfo64G5q[8] = { }; static const BxOpcodeInfo_t BxOpcodeInfo64G6[8] = { - // attributes defined in main area /* 0 */ { 0, &BX_CPU_C::SLDT_Ew }, /* 1 */ { 0, &BX_CPU_C::STR_Ew }, /* 2 */ { 0, &BX_CPU_C::LLDT_Ew }, @@ -410,7 +406,6 @@ static const BxOpcodeInfo_t BxOpcodeInfo64G6[8] = { // MOD == 11 7 2-7 | #UD | #UD static const BxOpcodeInfo_t opcodesGroup64RmINVLPG[8] = { - // attributes defined in main area /* 0 */ { 0, &BX_CPU_C::SWAPGS }, /* 1 */ { 0, &BX_CPU_C::RDTSCP }, /* 2 */ { 0, &BX_CPU_C::BxError }, @@ -421,10 +416,20 @@ static const BxOpcodeInfo_t opcodesGroup64RmINVLPG[8] = { /* 7 */ { 0, &BX_CPU_C::BxError } }; +static const BxOpcodeInfo_t opcodesGroup64RmMONITOR[8] = { + /* 0 */ { 0, &BX_CPU_C::MONITOR }, + /* 1 */ { 0, &BX_CPU_C::MWAIT }, + /* 2 */ { 0, &BX_CPU_C::BxError }, + /* 3 */ { 0, &BX_CPU_C::BxError }, + /* 4 */ { 0, &BX_CPU_C::BxError }, + /* 5 */ { 0, &BX_CPU_C::BxError }, + /* 6 */ { 0, &BX_CPU_C::BxError }, + /* 7 */ { 0, &BX_CPU_C::BxError } +}; + static const BxOpcodeInfo_t BxOpcodeInfo64G7R[8] = { - // attributes defined in main area /* 0 */ { 0, &BX_CPU_C::BxError }, - /* 1 */ { 0, &BX_CPU_C::BxError }, + /* 1 */ { BxRMGroup, NULL, opcodesGroup64RmMONITOR }, /* 2 */ { 0, &BX_CPU_C::BxError }, /* 3 */ { 0, &BX_CPU_C::BxError }, /* 4 */ { 0, &BX_CPU_C::SMSW_Ew }, @@ -434,7 +439,6 @@ static const BxOpcodeInfo_t BxOpcodeInfo64G7R[8] = { }; static const BxOpcodeInfo_t BxOpcodeInfo64G7M[8] = { - // attributes defined in main area /* 0 */ { 0, &BX_CPU_C::SGDT64_Ms }, /* 1 */ { 0, &BX_CPU_C::SIDT64_Ms }, /* 2 */ { 0, &BX_CPU_C::LGDT64_Ms }, diff --git a/bochs/cpu/proc_ctrl.cc b/bochs/cpu/proc_ctrl.cc index 13c519277..43b34647a 100644 --- a/bochs/cpu/proc_ctrl.cc +++ b/bochs/cpu/proc_ctrl.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: proc_ctrl.cc,v 1.173 2007-10-11 18:12:00 sshwarts Exp $ +// $Id: proc_ctrl.cc,v 1.174 2007-10-11 21:29:01 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -1894,15 +1894,73 @@ void BX_CPU_C::WRMSR(bxInstruction_c *i) #endif } +void BX_CPU_C::MONITOR(bxInstruction_c *i) +{ +#if BX_SUPPORT_MONITOR_MWAIT + // TODO: #UD when CPL > 0 and + // MSR 0xC0010015[MONITOR_MWAIT_USER_UNABLE] = 1 + BX_INFO(("MONITOR instruction executed")); + + if (RCX != 0) { + BX_ERROR(("MONITOR: no optional extensions supported")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + bx_address addr; + +#if BX_SUPPORT_X86_64 + if (i->as64L()) { + addr = RAX; + } + else +#endif + if (i->as32L()) { + addr = EAX; + } + else { + addr = AX; + } + + read_virtual_checks(&BX_CPU_THIS_PTR sregs[i->seg()], addr, 1); + + // TODO: Implemented actual MONITOR functionality + +#else + BX_INFO(("MONITOR: use --enable-monitor-mwait to enable MONITOR/MWAIT support")); + UndefinedOpcode (i); +#endif +} + +void BX_CPU_C::MWAIT(bxInstruction_c *i) +{ +#if BX_SUPPORT_MONITOR_MWAIT + // TODO: #UD when CPL > 0 and + // MSR 0xC0010015[MONITOR_MWAIT_USER_UNABLE] = 1 + BX_INFO(("MWAIT instruction executed")); + + // only one extension is supported + // ECX[0] - interrupt MWAIT even if EFLAGS.IF = 0 + if (RCX & ~((Bit64u)(1))) { + BX_ERROR(("MWAIT: incorrect optional extensions in RCX")); + exception(BX_GP_EXCEPTION, 0, 0); + } + + // TODO: Implemented actual MWAIT functionality +#else + BX_INFO(("MWAIT: use --enable-monitor-mwait to enable MONITOR/MWAIT support")); + UndefinedOpcode (i); +#endif +} + void BX_CPU_C::SYSENTER(bxInstruction_c *i) { #if BX_SUPPORT_SEP if (!protected_mode()) { - BX_ERROR(("sysenter not from protected mode !")); + BX_ERROR(("SYSENTER not from protected mode !")); exception(BX_GP_EXCEPTION, 0, 0); } if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) { - BX_ERROR(("sysenter with zero sysenter_cs_msr !")); + BX_ERROR(("SYSENTER with zero sysenter_cs_msr !")); exception(BX_GP_EXCEPTION, 0, 0); } @@ -1958,15 +2016,15 @@ void BX_CPU_C::SYSEXIT(bxInstruction_c *i) { #if BX_SUPPORT_SEP if (!protected_mode()) { - BX_ERROR(("sysexit not from protected mode !")); + BX_ERROR(("SYSEXIT not from protected mode !")); exception(BX_GP_EXCEPTION, 0, 0); } if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) { - BX_ERROR(("sysexit with zero sysenter_cs_msr !")); + BX_ERROR(("SYSEXIT with zero sysenter_cs_msr !")); exception(BX_GP_EXCEPTION, 0, 0); } if (CPL != 0) { - BX_ERROR(("sysexit at non-zero cpl %u !", CPL)); + BX_ERROR(("SYSEXIT at non-zero cpl %u !", CPL)); exception(BX_GP_EXCEPTION, 0, 0); } @@ -2017,73 +2075,6 @@ void BX_CPU_C::SYSEXIT(bxInstruction_c *i) #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_DEBUG(("Execute SYSCALL instruction")); @@ -2201,60 +2192,6 @@ SYSCALL_LEGACY_MODE: 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_DEBUG(("Execute SYSRET instruction")); diff --git a/bochs/cpu/todo b/bochs/cpu/todo index 4dcceb455..122aae327 100755 --- a/bochs/cpu/todo +++ b/bochs/cpu/todo @@ -42,3 +42,5 @@ TODO (know issues in CPU model): [!] More flexible CPUID - vendor and etc [!] SSE4A, SSE5, VMX, SVM + +[!] MONITOR/MWAIT functionality \ No newline at end of file diff --git a/bochs/main.cc b/bochs/main.cc index a433d98b7..bbd6bf7ea 100644 --- a/bochs/main.cc +++ b/bochs/main.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: main.cc,v 1.357 2007-09-28 19:51:42 sshwarts Exp $ +// $Id: main.cc,v 1.358 2007-10-11 21:28:57 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 MandrakeSoft S.A. @@ -991,6 +991,7 @@ int bx_init_hardware() BX_INFO((" PSE support: %s",BX_SUPPORT_LARGE_PAGES?"yes":"no")); BX_INFO((" x86-64 support: %s",BX_SUPPORT_X86_64?"yes":"no")); BX_INFO((" SEP support: %s",BX_SUPPORT_SEP?"yes":"no")); + BX_INFO((" MWAIT support: %s",BX_SUPPORT_MONITOR_MWAIT?"yes":"no")); BX_INFO(("Optimization configuration")); BX_INFO((" Guest2HostTLB support: %s",BX_SupportGuest2HostTLB?"yes":"no")); BX_INFO((" RepeatSpeedups support: %s",BX_SupportRepeatSpeedups?"yes":"no"));