Merged X2APIC + X2APIC virtualization

This commit is contained in:
Stanislav Shwartsman 2010-04-08 15:50:39 +00:00
parent df7db31fb4
commit 6e1204cb84
17 changed files with 549 additions and 144 deletions

View File

@ -4,6 +4,7 @@
./configure \
--enable-smp \
--enable-x2apic \
--enable-x86-64 \
--enable-all-optimizations \
--enable-long-phy-address \

View File

@ -4,6 +4,7 @@ Brief summary :
- Major configure/cpu rework allowing to enable/disable CPU options at runtime
through .bochsrc (Stanislav)
- Bugfixes for CPU emulation correctness and stability
- Implemented X2APIC extensions (Stanislav)
- Implemented Intel VMXx2 extensions (Stanislav)
- Extended VMX capability MSRs, APIC Virtualization,
Extended Page Tables (EPT), VPID, new VMX controls support
@ -38,6 +39,7 @@ Detailed change log :
- CPU
- Implemented PCLMULQDQ AES instruction
- Implemented X2APIC extensions / enable extended topology CPUID leaf (0xb)
- Implemented Intel VMXx2 extensions:
- Enabled extended VMX capability MSRs
- Implemented VMX controls for loading/storing of MSR_PAT and MSR_EFER
@ -46,6 +48,7 @@ Detailed change log :
- Implemented Extended Page Tables (EPT) mode
- Implemented Descriptor Table Access VMEXIT control
- Implemented RDTSCP VMEXIT control
- Implemented Virtualize X2APIC mode control
- Implemented Virtual Process ID (VPID)
- Implemented WBINVD VMEXIT control
In order to enable emulation of VMXx2 extensions configure with
@ -70,6 +73,7 @@ Detailed change log :
- Updated Bochs TESTFORM to version 0.5
- SF patches applied
[2864402] outstanding x2apic patches by Stanislav
[2960379] Fix build with -Wformat -Werror=format-security by Per Oyvind Karlsen
[2938273] allow instrumentation to change execute by Konrad Grochowski
[2926072] Indirection operators in expressions by Derek Peschel

View File

@ -761,6 +761,12 @@ typedef
#define BX_SUPPORT_APIC 0
#endif
#define BX_SUPPORT_X2APIC 0
#if (BX_SUPPORT_X2APIC && !BX_SUPPORT_APIC)
#error APIC is required for X2APIC emulation !
#endif
#define BX_HAVE_GETENV 0
#define BX_HAVE_SETENV 0
#define BX_HAVE_SELECT 0

86
bochs/configure vendored
View File

@ -1,5 +1,5 @@
#! /bin/sh
# From configure.in Id: configure.in,v 1.432 2010/04/03 07:30:23 sshwarts Exp .
# From configure.in Id: configure.in,v 1.433 2010/04/04 18:37:53 sshwarts Exp .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.65.
#
@ -951,6 +951,7 @@ enable_pcidev
enable_usb
enable_usb_ohci
enable_pnic
enable_x2apic
enable_1g_pages
enable_repeat_speedups
enable_trace_cache
@ -1669,6 +1670,7 @@ Optional Features:
--enable-usb enable limited USB UHCI support
--enable-usb-ohci enable limited USB OHCI support
--enable-pnic enable PCI pseudo NIC support
--enable-x2apic support for X2APIC
--enable-1g-pages support for 1G pages in long mode
--enable-repeat-speedups support repeated IO and mem copy speedups
--enable-trace-cache support instruction trace cache
@ -5099,7 +5101,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5102 "configure"' > conftest.$ac_ext
echo '#line 5104 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@ -6788,11 +6790,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:6791: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6793: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6795: \$? = $ac_status" >&5
echo "$as_me:6797: \$? = $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
@ -7021,11 +7023,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:7024: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7026: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7028: \$? = $ac_status" >&5
echo "$as_me:7030: \$? = $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
@ -7088,11 +7090,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:7091: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7093: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7095: \$? = $ac_status" >&5
echo "$as_me:7097: \$? = $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
@ -8878,7 +8880,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 8881 "configure"
#line 8883 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -8976,7 +8978,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 8979 "configure"
#line 8981 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -11091,11 +11093,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:11094: $lt_compile\"" >&5)
(eval echo "\"\$as_me:11096: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:11098: \$? = $ac_status" >&5
echo "$as_me:11100: \$? = $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
@ -11158,11 +11160,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:11161: $lt_compile\"" >&5)
(eval echo "\"\$as_me:11163: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:11165: \$? = $ac_status" >&5
echo "$as_me:11167: \$? = $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
@ -12183,7 +12185,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 12186 "configure"
#line 12188 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -12281,7 +12283,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 12284 "configure"
#line 12286 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -13104,11 +13106,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:13107: $lt_compile\"" >&5)
(eval echo "\"\$as_me:13109: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:13111: \$? = $ac_status" >&5
echo "$as_me:13113: \$? = $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
@ -13171,11 +13173,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:13174: $lt_compile\"" >&5)
(eval echo "\"\$as_me:13176: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:13178: \$? = $ac_status" >&5
echo "$as_me:13180: \$? = $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
@ -15136,11 +15138,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:15139: $lt_compile\"" >&5)
(eval echo "\"\$as_me:15141: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:15143: \$? = $ac_status" >&5
echo "$as_me:15145: \$? = $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
@ -15369,11 +15371,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:15372: $lt_compile\"" >&5)
(eval echo "\"\$as_me:15374: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:15376: \$? = $ac_status" >&5
echo "$as_me:15378: \$? = $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
@ -15436,11 +15438,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:15439: $lt_compile\"" >&5)
(eval echo "\"\$as_me:15441: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:15443: \$? = $ac_status" >&5
echo "$as_me:15445: \$? = $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
@ -17226,7 +17228,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 17229 "configure"
#line 17231 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -17324,7 +17326,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 17327 "configure"
#line 17329 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -19011,7 +19013,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 19014 "configure"
#line 19016 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -22215,6 +22217,32 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X2APIC support" >&5
$as_echo_n "checking for X2APIC support... " >&6; }
# Check whether --enable-x2apic was given.
if test "${enable_x2apic+set}" = set; then :
enableval=$enable_x2apic; if test "$enableval" = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define BX_SUPPORT_X2APIC 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define BX_SUPPORT_X2APIC 0" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define BX_SUPPORT_X2APIC 0" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for long mode 1G pages support" >&5
$as_echo_n "checking for long mode 1G pages support... " >&6; }
# Check whether --enable-1g-pages was given.

View File

@ -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.433 2010-04-04 18:37:53 sshwarts Exp $]])
AC_REVISION([[$Id: configure.in,v 1.434 2010-04-08 15:50:39 sshwarts Exp $]])
AC_CONFIG_HEADER(config.h)
AC_CONFIG_HEADER(ltdlconf.h)
@ -860,6 +860,22 @@ fi
AC_SUBST(NETLOW_OBJS)
AC_MSG_CHECKING(for X2APIC support)
AC_ARG_ENABLE(x2apic,
[ --enable-x2apic support for X2APIC],
[if test "$enableval" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(BX_SUPPORT_X2APIC, 1)
else
AC_MSG_RESULT(no)
AC_DEFINE(BX_SUPPORT_X2APIC, 0)
fi],
[
AC_MSG_RESULT(no)
AC_DEFINE(BX_SUPPORT_X2APIC, 0)
]
)
AC_MSG_CHECKING(for long mode 1G pages support)
AC_ARG_ENABLE(1g-pages,
[ --enable-1g-pages support for 1G pages in long mode],

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: apic.cc,v 1.142 2010-04-05 09:36:17 sshwarts Exp $
// $Id: apic.cc,v 1.143 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002-2009 Zwane Mwaikambo, Stanislav Shwartsman
@ -241,6 +241,10 @@ void bx_local_apic_c::reset(unsigned type)
void bx_local_apic_c::set_base(bx_phy_address newbase)
{
#if BX_SUPPORT_X2APIC
if (mode == BX_APIC_X2APIC_MODE)
ldr = ((apic_id & 0xfffffff0) << 16) | (1 << (apic_id & 0xf));
#endif
mode = (newbase >> 10) & 3;
newbase &= ~((bx_phy_address) 0xfff);
base_addr = newbase;
@ -808,6 +812,17 @@ bx_bool bx_local_apic_c::match_logical_addr(apic_dest_t address)
{
bx_bool match = 0;
#if BX_SUPPORT_X2APIC
if (mode == BX_APIC_X2APIC_MODE) {
// only cluster model supported in x2apic mode
if (address == 0xffffffff) // // broadcast all
return 1;
if ((address & 0xffff0000) == (ldr & 0xffff0000))
match = ((address & ldr & 0x0000ffff) != 0);
return match;
}
#endif
if (dest_format == 0xf) {
// flat model
match = ((address & ldr) != 0);
@ -962,6 +977,167 @@ void bx_local_apic_c::set_initial_timer_count(Bit32u value)
}
}
#if BX_SUPPORT_X2APIC
// return false when x2apic is not supported/not readable
bx_bool bx_local_apic_c::read_x2apic(unsigned index, Bit64u *val_64)
{
index = (index - 0x800) << 4;
switch(index) {
// return full 32-bit lapic id
case BX_LAPIC_ID:
*val_64 = apic_id;
break;
case BX_LAPIC_LDR:
*val_64 = ldr;
break;
// full 64-bit access to ICR
case BX_LAPIC_ICR_LO:
*val_64 = ((Bit64u) icr_lo) | (((Bit64u) icr_hi) << 32);
break;
// not supported/not readable in x2apic mode
case BX_LAPIC_ARBITRATION_PRIORITY:
case BX_LAPIC_DESTINATION_FORMAT:
case BX_LAPIC_ICR_HI:
case BX_LAPIC_EOI: // write only
case BX_LAPIC_SELF_IPI: // write only
return 0;
// compatible to legacy lapic mode
case BX_LAPIC_VERSION:
case BX_LAPIC_TPR:
case BX_LAPIC_PPR:
case BX_LAPIC_SPURIOUS_VECTOR:
case BX_LAPIC_ISR1:
case BX_LAPIC_ISR2:
case BX_LAPIC_ISR3:
case BX_LAPIC_ISR4:
case BX_LAPIC_ISR5:
case BX_LAPIC_ISR6:
case BX_LAPIC_ISR7:
case BX_LAPIC_ISR8:
case BX_LAPIC_TMR1:
case BX_LAPIC_TMR2:
case BX_LAPIC_TMR3:
case BX_LAPIC_TMR4:
case BX_LAPIC_TMR5:
case BX_LAPIC_TMR6:
case BX_LAPIC_TMR7:
case BX_LAPIC_TMR8:
case BX_LAPIC_IRR1:
case BX_LAPIC_IRR2:
case BX_LAPIC_IRR3:
case BX_LAPIC_IRR4:
case BX_LAPIC_IRR5:
case BX_LAPIC_IRR6:
case BX_LAPIC_IRR7:
case BX_LAPIC_IRR8:
case BX_LAPIC_ESR:
case BX_LAPIC_LVT_TIMER:
case BX_LAPIC_LVT_THERMAL:
case BX_LAPIC_LVT_PERFMON:
case BX_LAPIC_LVT_LINT0:
case BX_LAPIC_LVT_LINT1:
case BX_LAPIC_LVT_ERROR:
case BX_LAPIC_TIMER_INITIAL_COUNT:
case BX_LAPIC_TIMER_CURRENT_COUNT:
case BX_LAPIC_TIMER_DIVIDE_CFG:
*val_64 = read_aligned(index);
break;
default:
BX_DEBUG(("read_x2apic: not supported apic register 0x%08x", index));
return 0;
}
return 1;
}
// return false when x2apic is not supported/not writeable
bx_bool bx_local_apic_c::write_x2apic(unsigned index, Bit64u val_64)
{
Bit32u val32_lo = GET32L(val_64);
index = (index - 0x800) << 4;
switch(index) {
// read only/not available in x2apic mode
case BX_LAPIC_ID:
case BX_LAPIC_VERSION:
case BX_LAPIC_ARBITRATION_PRIORITY:
case BX_LAPIC_PPR:
case BX_LAPIC_LDR:
case BX_LAPIC_DESTINATION_FORMAT:
case BX_LAPIC_ISR1:
case BX_LAPIC_ISR2:
case BX_LAPIC_ISR3:
case BX_LAPIC_ISR4:
case BX_LAPIC_ISR5:
case BX_LAPIC_ISR6:
case BX_LAPIC_ISR7:
case BX_LAPIC_ISR8:
case BX_LAPIC_TMR1:
case BX_LAPIC_TMR2:
case BX_LAPIC_TMR3:
case BX_LAPIC_TMR4:
case BX_LAPIC_TMR5:
case BX_LAPIC_TMR6:
case BX_LAPIC_TMR7:
case BX_LAPIC_TMR8:
case BX_LAPIC_IRR1:
case BX_LAPIC_IRR2:
case BX_LAPIC_IRR3:
case BX_LAPIC_IRR4:
case BX_LAPIC_IRR5:
case BX_LAPIC_IRR6:
case BX_LAPIC_IRR7:
case BX_LAPIC_IRR8:
case BX_LAPIC_ICR_HI:
case BX_LAPIC_TIMER_CURRENT_COUNT:
return 0;
// send self ipi
case BX_LAPIC_SELF_IPI:
trigger_irq(val32_lo & 0xff, APIC_EDGE_TRIGGERED);
break;
// handle full 64-bit write
case BX_LAPIC_ICR_LO:
send_ipi(GET32H(val_64), val32_lo);
break;
case BX_LAPIC_TPR:
// handle reserved bits, only bits 0-7 are writeable
if ((val32_lo & 0xffffff00) != 0)
return 0;
break; // use legacy write
case BX_LAPIC_SPURIOUS_VECTOR:
// handle reserved bits, only bits 0-8, 12 are writeable
// we do not support directed EOI capability, so reserve bit 12 as well
if ((val32_lo & 0xfffffe00) != 0)
return 0;
break; // use legacy write
case BX_LAPIC_EOI:
case BX_LAPIC_ESR:
if (val_64 != 0) return 0;
break; // use legacy write
case BX_LAPIC_LVT_TIMER:
case BX_LAPIC_LVT_THERMAL:
case BX_LAPIC_LVT_PERFMON:
case BX_LAPIC_LVT_LINT0:
case BX_LAPIC_LVT_LINT1:
case BX_LAPIC_LVT_ERROR:
case BX_LAPIC_TIMER_INITIAL_COUNT:
case BX_LAPIC_TIMER_DIVIDE_CFG:
break; // use legacy write
default:
BX_DEBUG(("write_x2apic: not supported apic register 0x%08x", index));
return 0;
}
if (GET32H(val_64) != 0) // upper 32-bit are reserved for all x2apic MSRs
return 0;
write_aligned(index, val32_lo);
return 1;
}
#endif
void bx_local_apic_c::register_state(bx_param_c *parent)
{
unsigned i;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: apic.h,v 1.54 2010-03-27 09:56:30 sshwarts Exp $
// $Id: apic.h,v 1.55 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002-2009 Zwane Mwaikambo, Stanislav Shwartsman
@ -71,6 +71,7 @@ class BOCHSAPI bx_local_apic_c : public logfunctions
#define APIC_ERR_ILLEGAL_ADDR 0x80
#define APIC_ERR_RX_ILLEGAL_VEC 0x40
#define APIC_ERR_TX_ILLEGAL_VEC 0x20
#define X2APIC_ERR_REDIRECTIBLE_IPI 0x08
#define APIC_ERR_RX_ACCEPT_ERR 0x08
#define APIC_ERR_TX_ACCEPT_ERR 0x04
#define APIC_ERR_RX_CHECKSUM 0x02
@ -128,7 +129,10 @@ public:
void write(bx_phy_address addr, void *data, unsigned len);
void write_aligned(bx_phy_address addr, Bit32u data);
Bit32u read_aligned(bx_phy_address address);
void startup_msg(Bit8u vector);
#if BX_SUPPORT_X2APIC
bx_bool read_x2apic(unsigned index, Bit64u *msr);
bx_bool write_x2apic(unsigned index, Bit64u msr);
#endif
// on local APIC, trigger means raise the CPU's INTR line. For now
// I also have to raise pc_system.INTR but that should be replaced
// with the cpu-specific INTR signals.
@ -152,6 +156,7 @@ public:
void periodic(void);
void set_divide_configuration(Bit32u value);
void set_initial_timer_count(Bit32u value);
void startup_msg(Bit8u vector);
void register_state(bx_param_c *parent);
};

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.666 2010-04-07 17:12:17 sshwarts Exp $
// $Id: cpu.h,v 1.667 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2010 The Bochs Project
@ -610,7 +610,7 @@ typedef struct
#define BX_CPU_P6 0x00000008 /* P6 new instruction */
#define BX_CPU_MMX 0x00000010 /* MMX instruction */
#define BX_CPU_3DNOW 0x00000020 /* 3DNow! instruction */
#define BX_CPU_FXSAVE_FXRSTOR 0x00000040 /* SYSENTER/SYSEXIT instruction */
#define BX_CPU_FXSAVE_FXRSTOR 0x00000040 /* FXSAVE/FXRSTOR instruction */
#define BX_CPU_SYSENTER_SYSEXIT 0x00000080 /* SYSENTER/SYSEXIT instruction */
#define BX_CPU_CLFLUSH 0x00000100 /* CLFLUSH instruction */
#define BX_CPU_SSE 0x00000200 /* SSE instruction */
@ -3122,7 +3122,6 @@ public: // for now...
#endif
BX_SMF void TLB_flush(void);
BX_SMF void TLB_invlpg(bx_address laddr);
BX_SMF void TLB_init(void);
BX_SMF void set_INTR(bx_bool value);
BX_SMF const char *strseg(bx_segment_reg_t *seg);
BX_SMF void interrupt(Bit8u vector, unsigned type, bx_bool push_error,
@ -3265,6 +3264,10 @@ public: // for now...
BX_SMF void init_isa_features_bitmask(void);
BX_SMF void init_FetchDecodeTables(void);
#if BX_SUPPORT_X2APIC
BX_SMF void bx_cpuid_extended_topology_leaf(Bit32u subfunction);
#endif
BX_SMF void bx_cpuid_xsave_leaf(Bit32u subfunction);
BX_SMF BX_CPP_INLINE unsigned which_cpu(void) { return BX_CPU_THIS_PTR bx_cpuid; }
BX_SMF BX_CPP_INLINE const bx_gen_reg_t *get_gen_regfile() { return BX_CPU_THIS_PTR gen_reg; }
@ -3407,7 +3410,7 @@ public: // for now...
BX_SMF Bit16u VMX_Get_Current_VPID(void);
#endif
BX_SMF Bit32u VMX_Read_VTPR(void);
BX_SMF void VMX_Write_TPR_Shadow(Bit8u tpr_shadow);
BX_SMF void VMX_Write_VTPR(Bit8u vtpr);
BX_SMF Bit64s VMX_TSC_Offset(void);
// vmexit reasons
BX_SMF void VMexit_Instruction(bxInstruction_c *i, Bit32u reason) BX_CPP_AttrRegparmN(2);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpuid.cc,v 1.111 2010-04-03 05:59:07 sshwarts Exp $
// $Id: cpuid.cc,v 1.112 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2010 Stanislav Shwartsman
@ -164,47 +164,51 @@ Bit32u BX_CPU_C::get_extended_cpuid_features(void)
Bit32u features = 0;
// support SSE3
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_SSE3)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_SSE3))
features |= (1<<0);
// support for PCLMULQDQ
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_AES_PCLMULQDQ)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_AES_PCLMULQDQ))
features |= (1<<1);
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_MONITOR_MWAIT)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_MONITOR_MWAIT))
features |= (1<<3);
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_VMX)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_VMX))
features |= (1<<5);
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_SSSE3)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_SSSE3))
features |= (1<<9);
#if BX_SUPPORT_X86_64
// support CMPXCHG16B
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_X86_64)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_X86_64))
features |= (1<<13);
#endif
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_SSE4_1)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_SSE4_1))
features |= (1<<19);
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_SSE4_2)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_SSE4_2))
features |= (1<<20);
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_MOVBE)
#if BX_SUPPORT_X2APIC
features |= (1<<21); // support X2APIC
#endif
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_MOVBE))
features |= (1<<22);
// enable POPCNT if SSE4_2 is enabled
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_SSE4_2)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_SSE4_2))
features |= (1<<23);
// support for AES
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_AES_PCLMULQDQ)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_AES_PCLMULQDQ))
features |= (1<<25);
// support XSAVE extensions
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_XSAVE)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE))
features |= (1<<26) | (1<<27);
return features;
@ -248,11 +252,11 @@ Bit32u BX_CPU_C::get_std_cpuid_features(void)
Bit32u features = 0;
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_X87)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_X87))
features |= (1<<0);
#if BX_CPU_LEVEL >= 5
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_PENTIUM) {
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_PENTIUM)) {
// Pentium only features
features |= (1<<1); // support VME
features |= (1<<3); // support PSE
@ -272,19 +276,19 @@ Bit32u BX_CPU_C::get_std_cpuid_features(void)
features |= (1<<9); // APIC on chip
#endif
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_SYSENTER_SYSEXIT)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_SYSENTER_SYSEXIT))
features |= (1<<11);
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_CLFLUSH)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_CLFLUSH))
features |= (1<<19);
#if BX_CPU_LEVEL >= 5
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_MMX)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_MMX))
features |= (1<<23);
#endif
#if BX_CPU_LEVEL >= 6
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_P6) {
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_P6)) {
features |= (1<<6); // support PAE
features |= (1<<12); // support MTRRs
features |= (1<<13); // support Global pages
@ -293,13 +297,13 @@ Bit32u BX_CPU_C::get_std_cpuid_features(void)
features |= (1<<17); // support PSE-36
}
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_FXSAVE_FXRSTOR)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_FXSAVE_FXRSTOR))
features |= (1<<24); // support FSAVE/FXRSTOR instructions
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_SSE)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_SSE))
features |= (1<<25);
if (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_CPU_SSE2)
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_SSE2))
features |= (1<<26);
#endif
@ -330,16 +334,20 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CPUID(bxInstruction_c *i)
if(function < 0x80000000) {
if(function <= max_std_function) {
#if BX_SUPPORT_X2APIC
if (function == 0xb) {
bx_cpuid_extended_topology_leaf(subfunction);
return;
}
#endif
if (function == 0xd) {
bx_cpuid_xsave_leaf(subfunction);
return;
}
RAX = BX_CPU_THIS_PTR cpuid_std_function[function].eax;
RBX = BX_CPU_THIS_PTR cpuid_std_function[function].ebx;
RCX = BX_CPU_THIS_PTR cpuid_std_function[function].ecx;
RDX = BX_CPU_THIS_PTR cpuid_std_function[function].edx;
if (function == 0xD && subfunction > 0) {
RAX = 0;
RBX = 0;
RCX = 0;
RDX = 0;
}
return;
}
}
@ -406,8 +414,11 @@ void BX_CPU_C::set_cpuid_defaults(void)
if (! cpuid_limit_winnt) {
if (BX_SUPPORT_MONITOR_MWAIT)
cpuid->eax = 0x5;
#if BX_SUPPORT_X2APIC
cpuid->eax = 0xb;
#endif
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE))
cpuid->eax = 0xD;
cpuid->eax = 0xd;
}
#endif
@ -582,10 +593,10 @@ void BX_CPU_C::set_cpuid_defaults(void)
#endif
// ------------------------------------------------------
// CPUID function 0x0000000D
// CPUID function 0x0000000d
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE))
{
cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[0xD]);
cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[0xd]);
// EAX - XCR0 lower 32 bits
// EBX - Maximum size (in bytes) required by enabled features
@ -792,6 +803,123 @@ void BX_CPU_C::set_cpuid_defaults(void)
#endif // BX_CPU_LEVEL >= 6
}
#if BX_SUPPORT_X2APIC
#include <math.h>
void BX_CPU_C::bx_cpuid_extended_topology_leaf(Bit32u subfunction)
{
static int nthreads = SIM->get_param_num(BXPN_CPU_NTHREADS)->get();
static int ncores = SIM->get_param_num(BXPN_CPU_NCORES)->get();
static int nprocessors = SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get();
switch(subfunction) {
case 0:
if (nthreads > 1) {
RAX = (bx_address) ceil(log(nthreads)/log(2));
RBX = nthreads;
RCX = subfunction | (1<<8);
}
else if (ncores > 1) {
RAX = (bx_address) ceil(log(ncores)/log(2));
RBX = ncores;
RCX = subfunction | (2<<8);
}
else if (nprocessors > 1) {
RAX = (bx_address) ceil(log(nprocessors)/log(2));
RBX = nprocessors;
RCX = subfunction;
}
else {
RAX = 0;
RBX = 0;
RCX = subfunction;
}
break;
case 1:
if (nthreads > 1) {
if (ncores > 1) {
RAX = (bx_address) ceil(log(ncores)/log(2));
RBX = ncores;
RCX = subfunction | (2<<8);
}
else if (nprocessors > 1) {
RAX = (bx_address) ceil(log(nprocessors)/log(2));
RBX = nprocessors;
RCX = subfunction;
}
else {
RAX = 0;
RBX = 0;
RCX = subfunction;
}
}
else if (ncores > 1) {
if (nprocessors > 1) {
RAX = (bx_address) ceil(log(nprocessors)/log(2));
RBX = nprocessors;
RCX = subfunction;
}
else {
RAX = 0;
RBX = 0;
RCX = subfunction;
}
} else {
RAX = 0;
RBX = 0;
RCX = subfunction;
}
break;
case 2:
if (nthreads > 1) {
if (nprocessors > 1) {
RAX = (bx_address) ceil(log(nprocessors)/log(2));
RBX = nprocessors;
}
else {
RAX = 0;
RBX = 0;
}
}
else {
RAX = 0;
RBX = 0;
}
RCX = subfunction;
break;
default:
RAX = 0;
RBX = 0;
RCX = subfunction;
break;
}
RDX = BX_CPU_THIS_PTR lapic.get_id(); // x2apic ID
}
#endif
void BX_CPU_C::bx_cpuid_xsave_leaf(Bit32u subfunction)
{
BX_ASSERT(BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_XSAVE));
if (subfunction == 0) {
RAX = BX_CPU_THIS_PTR cpuid_std_function[0xd].eax;
RBX = BX_CPU_THIS_PTR cpuid_std_function[0xd].ebx;
RCX = BX_CPU_THIS_PTR cpuid_std_function[0xd].ecx;
RDX = BX_CPU_THIS_PTR cpuid_std_function[0xd].edx;
}
else {
RAX = 0; // reserved
RBX = 0; // reserved
RCX = 0; // reserved
RDX = 0; // reserved
}
}
void BX_CPU_C::init_isa_features_bitmask(void)
{
Bit32u features_bitmask = 0;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: crregs.cc,v 1.10 2010-04-06 19:26:02 sshwarts Exp $
// $Id: crregs.cc,v 1.11 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010 Stanislav Shwartsman
@ -575,11 +575,11 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
}
#if BX_SUPPORT_VMX
if (BX_CPU_THIS_PTR in_vmx_guest && VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW)) {
VMX_Write_TPR_Shadow(val_64 & 0xF);
VMX_Write_VTPR((val_64 & 0xF) << 4);
break;
}
#endif
BX_CPU_THIS_PTR lapic.set_tpr((val_64 & 0xF) << 0x4);
BX_CPU_THIS_PTR lapic.set_tpr((val_64 & 0xF) << 4);
break;
#endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: init.cc,v 1.238 2010-04-06 19:26:03 sshwarts Exp $
// $Id: init.cc,v 1.239 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2009 The Bochs Project
@ -993,7 +993,8 @@ void BX_CPU_C::reset(unsigned source)
BX_CPU_THIS_PTR EXT = 0;
TLB_init();
TLB_flush();
BX_CPU_THIS_PTR PDPTR_CACHE.valid = 0;
// invalidate the prefetch queue
BX_CPU_THIS_PTR eipPageBias = 0;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: msr.cc,v 1.47 2010-04-07 17:12:17 sshwarts Exp $
// $Id: msr.cc,v 1.48 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2008-2010 Stanislav Shwartsman
@ -40,6 +40,15 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::rdmsr(Bit32u index, Bit64u *msr)
if ((index & 0x3FFFFFFF) >= BX_MSR_MAX_INDEX)
return 0;
#if BX_SUPPORT_X2APIC
if (index >= 0x800 && index <= 0xBFF) {
if (BX_CPU_THIS_PTR msr.apicbase & 0x400) // X2APIC mode
return BX_CPU_THIS_PTR lapic.read_x2apic(index, msr);
else
return 0;
}
#endif
switch(index) {
#if BX_CPU_LEVEL >= 6
@ -273,6 +282,16 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::RDMSR(bxInstruction_c *i)
VMexit_MSR(i, VMX_VMEXIT_RDMSR, index);
#endif
#if BX_SUPPORT_VMX >= 2
if (BX_CPU_THIS_PTR in_vmx_guest && index == 0x808) {
if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE)) {
RAX = VMX_Read_VTPR() & 0xff;
RDX = 0;
return;
}
}
#endif
if (!rdmsr(index, &val64))
exception(BX_GP_EXCEPTION, 0);
@ -341,6 +360,15 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64)
if ((index & 0x3FFFFFFF) >= BX_MSR_MAX_INDEX)
return 0;
#if BX_SUPPORT_X2APIC
if (index >= 0x800 && index <= 0xBFF) {
if (BX_CPU_THIS_PTR msr.apicbase & 0x400) // X2APIC mode
return BX_CPU_THIS_PTR lapic.write_x2apic(index, val_64);
else
return 0;
}
#endif
switch(index) {
#if BX_CPU_LEVEL >= 6
@ -636,7 +664,7 @@ bx_bool BX_CPU_C::relocate_apic(Bit64u val_64)
* [M:63] Reserved
*/
#define BX_MSR_APICBASE_RESERVED_BITS 0x6ff
#define BX_MSR_APICBASE_RESERVED_BITS (0x2ff | (BX_SUPPORT_X2APIC ? 0 : 0x400))
if (BX_CPU_THIS_PTR msr.apicbase & 0x800) {
Bit32u val32_hi = GET32H(val_64), val32_lo = GET32L(val_64);
@ -651,6 +679,20 @@ bx_bool BX_CPU_C::relocate_apic(Bit64u val_64)
BX_ERROR(("relocate_apic: attempt to set reserved bits"));
return 0;
}
#if BX_SUPPORT_X2APIC
unsigned apic_state = (BX_CPU_THIS_PTR msr.apicbase >> 10) & 3;
unsigned new_state = (val32_lo >> 10) & 3;
if (new_state == BX_APIC_STATE_INVALID) {
BX_ERROR(("relocate_apic: attempt to set invalid apic state"));
return 0;
}
if (apic_state == BX_APIC_X2APIC_MODE && new_state != BX_APIC_GLOBALLY_DISABLED) {
BX_ERROR(("relocate_apic: attempt to switch from x2apic -> xapic"));
return 0;
}
#endif
BX_CPU_THIS_PTR msr.apicbase = (bx_phy_address) val_64;
BX_CPU_THIS_PTR lapic.set_base(BX_CPU_THIS_PTR msr.apicbase);
// TLB flush is required for emulation correctness
@ -685,6 +727,15 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
VMexit_MSR(i, VMX_VMEXIT_WRMSR, index);
#endif
#if BX_SUPPORT_VMX >= 2
if (BX_CPU_THIS_PTR in_vmx_guest && index == 0x808) {
if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE)) {
VMX_Write_VTPR(AL);
return;
}
}
#endif
if (! wrmsr(index, val_64))
exception(BX_GP_EXCEPTION, 0);
#endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: paging.cc,v 1.216 2010-04-07 17:12:17 sshwarts Exp $
// $Id: paging.cc,v 1.217 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2010 The Bochs Project
@ -253,7 +253,14 @@
// | +------------> u/s of current access
// +---------------> Current CR0.WP value
static Bit8u priv_check[BX_PRIV_CHECK_SIZE];
/* 0xff0bbb0b */
static const Bit8u priv_check[BX_PRIV_CHECK_SIZE] =
{
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
#if BX_CPU_LEVEL >= 4
1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1
#endif
};
#define BX_PAGING_PHY_ADDRESS_RESERVED_BITS \
(BX_PHY_ADDRESS_RESERVED_BITS & BX_CONST64(0xfffffffffffff))
@ -360,47 +367,6 @@ static unsigned tlbNonGlobalFlushes=0;
// ==============================================================
// Called to initialize the TLB upon startup.
// Unconditional initialization of all TLB entries.
void BX_CPU_C::TLB_init(void)
{
unsigned n, wp, us_combined, rw_combined, us_current, rw_current;
//
// Setup privilege check matrix.
//
for (n=0; n<BX_PRIV_CHECK_SIZE; n++) {
wp = (n & 0x10) >> 4;
us_current = (n & 0x08) >> 3;
us_combined = (n & 0x04) >> 2;
rw_combined = (n & 0x02) >> 1;
rw_current = (n & 0x01) >> 0;
if (wp) { // when write protect on
if (us_current > us_combined) // user access, supervisor page
priv_check[n] = 0;
else if (rw_current > rw_combined) // RW access, RO page
priv_check[n] = 0;
else
priv_check[n] = 1;
}
else { // when write protect off
if (us_current == 0) // Supervisor mode access, anything goes
priv_check[n] = 1;
else {
// user mode access
if (us_combined == 0) // user access, supervisor Page
priv_check[n] = 0;
else if (rw_current > rw_combined) // RW access, RO page
priv_check[n] = 0;
else
priv_check[n] = 1;
}
}
}
TLB_flush();
}
void BX_CPU_C::TLB_flush(void)
{
#if InstrumentTLB
@ -857,6 +823,7 @@ bx_phy_address BX_CPU_C::translate_linear_PAE(bx_address laddr, Bit32u &lpf_mask
#endif
if (! BX_CPU_THIS_PTR PDPTR_CACHE.valid) {
BX_ERROR(("PDPTR_CACHE not valid !"));
if (! CheckPDPTR(BX_CPU_THIS_PTR cr3)) {
BX_ERROR(("translate_linear_PAE(): PDPTR check failed !"));
exception(BX_GP_EXCEPTION, 0);
@ -1350,12 +1317,13 @@ bx_bool BX_CPU_C::dbg_translate_guest_physical(bx_phy_address guest_paddr, bx_ph
{
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
bx_phy_address pt_address = LPFOf(vm->eptptr);
bx_phy_address offset_mask = 0xfff;
Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff);
for (int level = 3; level >= 0; --level) {
Bit64u pte;
pt_address += ((guest_paddr >> (9 + 9*level)) & 0xff8);
BX_MEM(0)->readPhysicalPage(BX_CPU_THIS, pt_address, 8, &pte);
offset_mask >>= 9;
switch(pte & 7) {
case BX_EPT_ENTRY_NOT_PRESENT:
@ -1370,14 +1338,12 @@ bx_bool BX_CPU_C::dbg_translate_guest_physical(bx_phy_address guest_paddr, bx_ph
if (pte & 0x80) {
if (level == BX_LEVEL_PDE) { // 2M page
offset_mask = 0x1fffff;
pt_address &= BX_CONST64(0x000fffffffffe000);
if (pt_address & offset_mask) return 0;
break;
}
#if BX_SUPPORT_1G_PAGES
if (level == BX_LEVEL_PDPE) { // 1G page
offset_mask = 0x3fffffff;
pt_address &= BX_CONST64(0x000fffffffffe000);
if (pt_address & offset_mask) return 0;
break;
@ -1401,7 +1367,6 @@ bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy)
bx_phy_address paddress;
bx_phy_address pt_address = BX_CPU_THIS_PTR cr3 & BX_CR3_PAGING_MASK;
bx_address offset_mask = 0xfff;
// see if page is in the TLB first
bx_address lpf = LPFOf(laddr);
@ -1416,10 +1381,15 @@ bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy)
#if BX_CPU_LEVEL >= 6
if (BX_CPU_THIS_PTR cr4.get_PAE()) {
if (! long_mode()) pt_address &= BX_CR3_LEGACY_PAE_PAGING_MASK;
Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff);
if (! long_mode()) {
pt_address &= BX_CR3_LEGACY_PAE_PAGING_MASK;
offset_mask >>= 9;
}
for (int level = 2 + long_mode(); level >= 0; --level) {
Bit64u pte;
pt_address += ((laddr >> (9 + 9*level)) & 0xff8);
offset_mask >>= 9;
#if BX_SUPPORT_VMX >= 2
if (BX_CPU_THIS_PTR in_vmx_guest) {
if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_ENABLE)) {
@ -1434,9 +1404,9 @@ bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy)
if (pte & BX_PAGING_PHY_ADDRESS_RESERVED_BITS)
goto page_fault;
pt_address = bx_phy_address(pte & BX_CONST64(0x000ffffffffff000));
if (level == BX_LEVEL_PTE) break;
if (pte & 0x80) {
if (level == BX_LEVEL_PDE) { // 2M page
offset_mask = 0x1fffff;
pt_address &= BX_CONST64(0x000fffffffffe000);
if (pt_address & offset_mask)
goto page_fault;
@ -1444,15 +1414,13 @@ bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy)
}
#if BX_SUPPORT_1G_PAGES
if (level == BX_LEVEL_PDPE && long_mode()) { // 1G page
offset_mask = 0x3fffffff;
pt_address &= BX_CONST64(0x000fffffffffe000);
if (pt_address & offset_mask)
goto page_fault;
break;
}
#endif
if (level != BX_LEVEL_PTE)
goto page_fault;
goto page_fault;
}
}
paddress = pt_address + (bx_phy_address)(laddr & offset_mask);
@ -1460,6 +1428,7 @@ bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy)
else // not PAE
#endif
{
Bit32u offset_mask = 0xfff;
for (int level = 1; level >= 0; --level) {
Bit32u pte;
pt_address += ((laddr >> (10 + 10*level)) & 0xffc);
@ -1473,14 +1442,14 @@ bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy)
#endif
BX_MEM(0)->readPhysicalPage(BX_CPU_THIS, pt_address, 4, &pte);
if (!(pte & 1))
goto page_fault;
goto page_fault;
pt_address = pte & 0xfffff000;
if (level == BX_LEVEL_PDE && (pte & 0x80)) { // PSE page
offset_mask = 0x3fffff;
offset_mask = 0x3fffff;
#if BX_PHY_ADDRESS_WIDTH > 32
pt_address += ((bx_phy_address)(pte & 0x003fe000)) << 19;
#endif
break;
break;
}
}
paddress = pt_address + (bx_phy_address)(laddr & offset_mask);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: vmexit.cc,v 1.24 2010-04-07 17:12:17 sshwarts Exp $
// $Id: vmexit.cc,v 1.25 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009-2010 Stanislav Shwartsman
@ -688,15 +688,16 @@ Bit32u BX_CPU_C::VMX_Read_VTPR(void)
return vtpr;
}
void BX_CPU_C::VMX_Write_TPR_Shadow(Bit8u tpr_shadow)
void BX_CPU_C::VMX_Write_VTPR(Bit8u vtpr)
{
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
bx_phy_address pAddr = vm->virtual_apic_page_addr + 0x80;
Bit32u field32 = tpr_shadow << 4;
Bit32u field32 = vtpr;
access_write_physical(pAddr, 4, (Bit8u*)(&field32));
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 4, BX_WRITE, (Bit8u*)(&field32));
Bit8u tpr_shadow = vtpr >> 4;
if (tpr_shadow < vm->vm_tpr_threshold) {
// commit current instruction to produce trap-like VMexit
BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP
@ -750,7 +751,7 @@ void BX_CPU_C::VMX_Virtual_Apic_Write(bx_phy_address paddr, unsigned len, void *
if (VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW) && offset == 0x80 && len <= 4) {
// VTPR access
VMX_Write_TPR_Shadow(*((Bit8u *) data));
VMX_Write_VTPR(*((Bit8u *) data));
return;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: vmx.cc,v 1.59 2010-04-07 17:12:17 sshwarts Exp $
// $Id: vmx.cc,v 1.60 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009-2010 Stanislav Shwartsman
@ -447,9 +447,16 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckVmControls(void)
return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD;
}
}
#endif
#if BX_SUPPORT_VMX >= 2
if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE) {
// 'use TPR shadow' must be set and "virtualize APIC accesses" must be clear
if (!(vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_TPR_SHADOW) ||
(vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES)) {
BX_ERROR(("VMFAIL: VMCS EXEC CTRL: virtualize X2APIC mode misconfigured"));
return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD;
}
}
if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_EPT_ENABLE) {
vm->eptptr = (bx_phy_address) VMread64(VMCS_64BIT_CONTROL_EPTPTR);
if (! is_eptptr_valid(vm->eptptr)) {
@ -1626,6 +1633,11 @@ Bit32u BX_CPU_C::LoadMSRs(Bit32u msr_cnt, bx_phy_address pAddr)
return msr;
#endif
#if BX_SUPPORT_X2APIC
if ((index & 0xfffff800) == 0x800) // X2APIC range
return msr;
#endif
if (! wrmsr(index, msr_hi))
return msr;
@ -1648,6 +1660,11 @@ Bit32u BX_CPU_C::StoreMSRs(Bit32u msr_cnt, bx_phy_address pAddr)
Bit32u index = GET32L(msr_lo);
#if BX_SUPPORT_X2APIC
if ((index & 0xfffff800) == 0x800) // X2APIC range
return msr;
#endif
if (! rdmsr(index, &msr_hi))
return msr;
@ -3183,8 +3200,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::INVEPT(bxInstruction_c *i)
if (i->os64L()) {
type = BX_READ_64BIT_REG(i->nnn());
}
else
{
else {
type = BX_READ_32BIT_REG(i->nnn());
}
@ -3245,8 +3261,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::INVVPID(bxInstruction_c *i)
if (i->os64L()) {
type = BX_READ_64BIT_REG(i->nnn());
}
else
{
else {
type = BX_READ_32BIT_REG(i->nnn());
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: vmx.h,v 1.27 2010-04-07 17:12:17 sshwarts Exp $
// $Id: vmx.h,v 1.28 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009 Stanislav Shwartsman
@ -594,6 +594,7 @@ typedef struct bx_VMCS
VMX_VM_EXEC_CTRL3_EPT_ENABLE | \
VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT | \
VMX_VM_EXEC_CTRL3_RDTSCP | \
VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE | \
VMX_VM_EXEC_CTRL3_VPID_ENABLE | \
VMX_VM_EXEC_CTRL3_WBINVD_VMEXIT)

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: disasm.h,v 1.61 2010-04-02 19:01:17 sshwarts Exp $
// $Id: disasm.h,v 1.62 2010-04-08 15:50:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2009 Stanislav Shwartsman
@ -45,7 +45,7 @@
#define IA_P6 0x00000008 /* P6 new instruction */
#define IA_MMX 0x00000010 /* MMX instruction */
#define IA_3DNOW 0x00000020 /* 3DNow! instruction */
#define IA_FXSAVE_FXRSTOR 0x00000040 /* SYSENTER/SYSEXIT instruction */
#define IA_FXSAVE_FXRSTOR 0x00000040 /* FXSAVE/FXRSTOR instruction */
#define IA_SYSENTER_SYSEXIT 0x00000080 /* SYSENTER/SYSEXIT instruction */
#define IA_CLFLUSH 0x00000100 /* CLFLUSH instruction */
#define IA_SSE 0x00000200 /* SSE instruction */