implemented GS/FS BASE access instructions published in _319433-007.pdf document

This commit is contained in:
Stanislav Shwartsman 2010-07-22 16:41:59 +00:00
parent 7f7c249934
commit 91ac0df65c
12 changed files with 156 additions and 23 deletions

View File

@ -179,6 +179,10 @@ cpu: count=1, ips=50000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="ms
# Enable Process-Context Identifiers (PCID) support in long mode.
# This option exists only if Bochs compiled with x86-64 support.
#
# FSGSBASE:
# Enable GS/GS BASE access instructions support in long mode.
# This option exists only if Bochs compiled with x86-64 support.
#
# MWAIT_IS_NOP:
# When this option is enabled MWAIT will not put the CPU into a sleep state.
# This option exists only if Bochs compiled with --enable-monitor-mwait.

View File

@ -1,4 +1,4 @@
$Id: PARAM_TREE.txt,v 1.31 2010-07-03 05:34:27 vruppert Exp $
$Id: PARAM_TREE.txt,v 1.32 2010-07-22 16:41:57 sshwarts Exp $
Starting from Bochs 2.3 the parameters are organized in a tree structure
instead of a huge flat list. The parameter tree was required for implementing
@ -27,6 +27,7 @@ cpu
cpuid
cpuid_limit_winnt
stepping
vendor_string
brand_string
mmx
@ -38,6 +39,7 @@ cpuid
xapic
1g_pages
pcid
fsgsbase
mwait_is_nop
memory

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: dbg_main.cc,v 1.237 2010-05-04 20:17:26 sshwarts Exp $
// $Id: dbg_main.cc,v 1.238 2010-07-22 16:41:58 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2009 The Bochs Project
@ -850,9 +850,10 @@ void bx_dbg_info_control_regs_command(void)
dbg_printf(" PWT=page-level write-through=%d\n", (cr3>>3) & 1);
#if BX_CPU_LEVEL >= 4
Bit32u cr4 = SIM->get_param_num("CR4", dbg_cpu_list)->get();
dbg_printf("CR4=0x%08x: %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", cr4,
dbg_printf("CR4=0x%08x: %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", cr4,
(cr4 & (1<<18)) ? "OSXSAVE" : "osxsave",
(cr4 & (1<<17)) ? "PCID" : "pcid",
(cr4 & (1<<16)) ? "FSGSBASE" : "fsgsbase",
(cr4 & (1<<14)) ? "SMX" : "smx",
(cr4 & (1<<13)) ? "VMX" : "vmx",
(cr4 & (1<<10)) ? "OSXMMEXCPT" : "osxmmexcpt",

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: config.cc,v 1.209 2010-07-16 21:10:48 sshwarts Exp $
// $Id: config.cc,v 1.210 2010-07-22 16:41:58 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002-2009 The Bochs Project
@ -366,7 +366,7 @@ void bx_init_options()
cpu_param->set_options(menu->SHOW_PARENT);
// cpuid subtree
bx_list_c *cpuid_param = new bx_list_c(root_param, "cpuid", "CPUID Options", 15);
bx_list_c *cpuid_param = new bx_list_c(root_param, "cpuid", "CPUID Options", 16);
new bx_param_bool_c(cpuid_param,
"cpuid_limit_winnt", "Limit max CPUID function to 3",
@ -446,6 +446,10 @@ void bx_init_options()
"pcid", "PCID support in long mode",
"Support for process context ID (PCID) in long mode",
0);
new bx_param_bool_c(cpuid_param,
"fsgsbase", "FS/GS BASE access instructions support",
"FS/GS BASE access instructions support in long mode",
0);
#endif
#if BX_SUPPORT_MONITOR_MWAIT
new bx_param_bool_c(cpuid_param,
@ -2717,6 +2721,10 @@ static int parse_line_formatted(const char *context, int num_params, char *param
if (parse_param_bool(params[i], 5, BXPN_CPUID_PCID) < 0) {
PARSE_ERR(("%s: cpuid directive malformed.", context));
}
} else if (!strncmp(params[i], "fsgsbase=", 9)) {
if (parse_param_bool(params[i], 9, BXPN_CPUID_FSGSBASE) < 0) {
PARSE_ERR(("%s: cpuid directive malformed.", context));
}
#endif
#if BX_SUPPORT_MONITOR_MWAIT
} else if (!strncmp(params[i], "mwait_is_nop=", 13)) {
@ -3893,9 +3901,10 @@ int bx_write_configuration(const char *rc, int overwrite)
SIM->get_param_bool(BXPN_CPUID_XSAVE)->get(),
SIM->get_param_bool(BXPN_CPUID_MOVBE)->get());
#if BX_SUPPORT_X86_64
fprintf(fp, ", 1g_pages=%d, pcid=%d",
fprintf(fp, ", 1g_pages=%d, pcid=%d fsgsbase=%d",
SIM->get_param_bool(BXPN_CPUID_1G_PAGES)->get(),
SIM->get_param_bool(BXPN_CPUID_PCID)->get());
SIM->get_param_bool(BXPN_CPUID_PCID)->get(),
SIM->get_param_bool(BXPN_CPUID_FSGSBASE)->get());
#endif
#if BX_SUPPORT_MONITOR_MWAIT
fprintf(fp, ", mwait_is_nop=%d", SIM->get_param_bool(BXPN_CPUID_MWAIT_IS_NOP)->get());

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.681 2010-07-22 15:12:08 sshwarts Exp $
// $Id: cpu.h,v 1.682 2010-07-22 16:41:58 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2010 The Bochs Project
@ -2735,10 +2735,15 @@ public: // for now...
BX_SMF void SYSCALL(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void SYSRET(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void SWAPGS(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void RDTSCP(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void CMPXCHG16B(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void SWAPGS(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void RDFSBASE(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void RDGSBASE(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void WRFSBASE(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void WRGSBASE(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void LOOPNE64_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void LOOPE64_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void LOOP64_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
@ -3270,6 +3275,7 @@ public: // for now...
BX_SMF BX_CPP_INLINE int bx_cpuid_support_pse(void);
BX_SMF BX_CPP_INLINE int bx_cpuid_support_pse36(void);
BX_SMF BX_CPP_INLINE int bx_cpuid_support_pcid(void);
BX_SMF BX_CPP_INLINE int bx_cpuid_support_fsgsbase(void);
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; }
@ -3693,6 +3699,15 @@ BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pcid(void)
#endif
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_fsgsbase(void)
{
#if BX_SUPPORT_X86_64
return BX_CPU_THIS_PTR cpuid_std_function[7].ecx & 0x1;
#else
return 0;
#endif
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_vme(void)
{
return (BX_CPU_THIS_PTR cpuid_std_function[1].edx >> 1) & 0x1;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpuid.cc,v 1.121 2010-07-22 15:12:08 sshwarts Exp $
// $Id: cpuid.cc,v 1.122 2010-07-22 16:41:59 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2010 Stanislav Shwartsman
@ -218,9 +218,14 @@ Bit32u BX_CPU_C::get_extended_cpuid_features(void)
Bit32u BX_CPU_C::get_ext2_cpuid_features(void)
{
// [0:0] FS/GS BASE access instructions
Bit32u features = 0;
return 0;
// [0:0] FS/GS BASE access instructions
// [31:1] Reserved
if (BX_CPU_SUPPORT_ISA_EXTENSION(BX_CPU_FSGSBASE))
features |= 1;
return features;
}
/* Get CPU feature flags. Returned by CPUID functions 1 and 80000001. */
@ -561,6 +566,7 @@ void BX_CPU_C::set_cpuid_defaults(void)
else
cpuid->eax = 0; /* leaf 7 not supported */
BX_INFO(("CPUID[0x00000007]: %08x %08x %08x %08x", cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx));
// ------------------------------------------------------
// CPUID function 0x0000000d
@ -932,6 +938,9 @@ void BX_CPU_C::init_isa_features_bitmask(void)
xapic_enabled = SIM->get_param_bool(BXPN_CPUID_XAPIC)->get();
sse_enabled = SIM->get_param_enum(BXPN_CPUID_SSE)->get();
#endif
#if BX_SUPPORT_X86_64
bx_bool fsgsbase_enabled = SIM->get_param_bool(BXPN_CPUID_FSGSBASE)->get();
#endif
// sanity checks
#if BX_SUPPORT_3DNOW
@ -1074,6 +1083,9 @@ void BX_CPU_C::init_isa_features_bitmask(void)
#if BX_SUPPORT_X86_64
features_bitmask |= BX_CPU_X86_64;
if (fsgsbase_enabled)
features_bitmask |= BX_CPU_FSGSBASE;
#endif
BX_CPU_THIS_PTR isa_extensions_bitmask = features_bitmask;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: crregs.cc,v 1.18 2010-05-12 21:33:04 sshwarts Exp $
// $Id: crregs.cc,v 1.19 2010-07-22 16:41:59 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010 Stanislav Shwartsman
@ -909,7 +909,8 @@ Bit32u BX_CPU_C::get_cr4_allow_mask(void)
// [31-19] Reserved, Must be Zero
// [18] OSXSAVE: Operating System XSAVE Support R/W
// [17] PCIDE: PCID Support R/W
// [16-15] Reserved, Must be Zero
// [16] FSGSBASE: FS/GS BASE access R/W
// [15] Reserved, Must be Zero
// [14] SMXE: SMX Extensions R/W
// [13] VMXE: VMX Extensions R/W
// [12-11] Reserved, Must be Zero
@ -975,6 +976,9 @@ Bit32u BX_CPU_C::get_cr4_allow_mask(void)
#if BX_SUPPORT_X86_64
if (bx_cpuid_support_pcid())
allowMask |= BX_CR4_PCIDE_MASK;
if (bx_cpuid_support_fsgsbase())
allowMask |= BX_CR4_FSGSBASE_MASK;
#endif
#if BX_CPU_LEVEL >= 6

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode.h,v 1.103 2010-05-18 07:28:04 sshwarts Exp $
// $Id: fetchdecode.h,v 1.104 2010-07-22 16:41:59 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2005-2010 Stanislav Shwartsman
@ -971,4 +971,17 @@ static const BxOpcodeInfo_t BxOpcodeInfoG15R[8] = {
/* 7 */ { BxPrefixSSE, BX_IA_SFENCE, BxOpcodeGroupSSE_ERR }
};
#if BX_SUPPORT_X86_64
static const BxOpcodeInfo_t BxOpcodeInfoG15R64[8] = {
/* 0 */ { BxPrefixSSEF3, BX_IA_RDFSBASE },
/* 1 */ { BxPrefixSSEF3, BX_IA_RDGSBASE },
/* 2 */ { BxPrefixSSEF3, BX_IA_WRFSBASE },
/* 3 */ { BxPrefixSSEF3, BX_IA_WRGSBASE },
/* 4 */ { 0, BX_IA_ERROR },
/* 5 */ { BxPrefixSSE, BX_IA_LFENCE, BxOpcodeGroupSSE_ERR },
/* 6 */ { BxPrefixSSE, BX_IA_MFENCE, BxOpcodeGroupSSE_ERR },
/* 7 */ { BxPrefixSSE, BX_IA_SFENCE, BxOpcodeGroupSSE_ERR }
};
#endif
#endif // BX_COMMON_FETCHDECODE_TABLES_H

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode64.cc,v 1.269 2010-05-26 18:37:54 sshwarts Exp $
// $Id: fetchdecode64.cc,v 1.270 2010-07-22 16:41:59 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2010 The Bochs Project
@ -1017,7 +1017,7 @@ static const BxOpcodeInfo_t BxOpcodeInfo64[512*3*2] = {
/* 0F AC /wm */ { BxImmediate_Ib, BX_IA_SHRD_EwGwM },
/* 0F AD /wr */ { 0, BX_IA_SHRD_EwGwR },
/* 0F AD /wm */ { 0, BX_IA_SHRD_EwGwM },
/* 0F AE /wr */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15R },
/* 0F AE /wr */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15R64 },
/* 0F AE /wm */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15M },
/* 0F AF /wr */ { 0, BX_IA_IMUL_GwEwR },
/* 0F AF /wm */ { 0, BX_IA_IMUL_GwEwM },
@ -2044,7 +2044,7 @@ static const BxOpcodeInfo_t BxOpcodeInfo64[512*3*2] = {
/* 0F AC /dm */ { BxImmediate_Ib, BX_IA_SHRD_EdGdM },
/* 0F AD /dr */ { 0, BX_IA_SHRD_EdGdR },
/* 0F AD /dm */ { 0, BX_IA_SHRD_EdGdM },
/* 0F AE /dr */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15R },
/* 0F AE /dr */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15R64 },
/* 0F AE /dm */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15M },
/* 0F AF /dr */ { 0, BX_IA_IMUL_GdEdR },
/* 0F AF /dm */ { 0, BX_IA_IMUL_GdEdM },
@ -3071,7 +3071,7 @@ static const BxOpcodeInfo_t BxOpcodeInfo64[512*3*2] = {
/* 0F AC /qm */ { BxImmediate_Ib, BX_IA_SHRD_EqGqM },
/* 0F AD /qr */ { 0, BX_IA_SHRD_EqGqR },
/* 0F AD /qm */ { 0, BX_IA_SHRD_EqGqM },
/* 0F AE /qr */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15R },
/* 0F AE /qr */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15R64 },
/* 0F AE /qm */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15M },
/* 0F AF /qr */ { 0, BX_IA_IMUL_GqEqR },
/* 0F AF /qm */ { 0, BX_IA_IMUL_GqEqM },

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ia_opcodes.h,v 1.49 2010-05-18 07:28:04 sshwarts Exp $
// $Id: ia_opcodes.h,v 1.50 2010-07-22 16:41:59 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2008-2010 Stanislav Shwartsman
@ -1620,7 +1620,6 @@ bx_define_opcode(BX_IA_SGDT64_Ms, &BX_CPU_C::SGDT64_Ms, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_SIDT64_Ms, &BX_CPU_C::SIDT64_Ms, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_LGDT64_Ms, &BX_CPU_C::LGDT64_Ms, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_LIDT64_Ms, &BX_CPU_C::LIDT64_Ms, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_SWAPGS, &BX_CPU_C::SWAPGS, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_RDTSCP, &BX_CPU_C::RDTSCP, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_CMPXCHG16B, &BX_CPU_C::CMPXCHG16B, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_LOOPNE64_Jb, &BX_CPU_C::LOOPNE64_Jb, NULL, BX_CPU_X86_64)
@ -1636,6 +1635,11 @@ bx_define_opcode(BX_IA_MOVQ_VdqEqM, &BX_CPU_C::MOVQ_VqWqM, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_MOVNTI_MqGq, &BX_CPU_C::MOVNTI_MqGq, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_SYSCALL, &BX_CPU_C::SYSCALL, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_SYSRET, &BX_CPU_C::SYSRET, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_SWAPGS, &BX_CPU_C::SWAPGS, NULL, BX_CPU_X86_64)
bx_define_opcode(BX_IA_RDFSBASE, &BX_CPU_C::RDFSBASE, NULL, BX_CPU_X86_64 | BX_CPU_FSGSBASE)
bx_define_opcode(BX_IA_RDGSBASE, &BX_CPU_C::RDGSBASE, NULL, BX_CPU_X86_64 | BX_CPU_FSGSBASE)
bx_define_opcode(BX_IA_WRFSBASE, &BX_CPU_C::WRFSBASE, NULL, BX_CPU_X86_64 | BX_CPU_FSGSBASE)
bx_define_opcode(BX_IA_WRGSBASE, &BX_CPU_C::WRGSBASE, NULL, BX_CPU_X86_64 | BX_CPU_FSGSBASE)
#endif
// VMX

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.334 2010-07-15 20:18:03 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.335 2010-07-22 16:41:59 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2010 The Bochs Project
@ -1274,4 +1274,72 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SWAPGS(bxInstruction_c *i)
MSR_GSBASE = MSR_KERNELGSBASE;
MSR_KERNELGSBASE = temp_GS_base;
}
/* F3 0F AE /0 */
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RDFSBASE(bxInstruction_c *i)
{
if (! BX_CPU_THIS_PTR cr4.get_FSGSBASE())
exception(BX_UD_EXCEPTION, 0);
if (i->os64L()) {
BX_WRITE_64BIT_REG(i->rm(), MSR_FSBASE);
}
else {
BX_WRITE_32BIT_REGZ(i->rm(), (Bit32u) MSR_FSBASE);
}
}
/* F3 0F AE /1 */
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RDGSBASE(bxInstruction_c *i)
{
if (! BX_CPU_THIS_PTR cr4.get_FSGSBASE())
exception(BX_UD_EXCEPTION, 0);
if (i->os64L()) {
BX_WRITE_64BIT_REG(i->rm(), MSR_GSBASE);
}
else {
BX_WRITE_32BIT_REGZ(i->rm(), (Bit32u) MSR_GSBASE);
}
}
/* F3 0F AE /2 */
void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRFSBASE(bxInstruction_c *i)
{
if (! BX_CPU_THIS_PTR cr4.get_FSGSBASE())
exception(BX_UD_EXCEPTION, 0);
if (i->os64L()) {
Bit64u fsbase = BX_READ_64BIT_REG(i->rm());
if (!IsCanonical(fsbase)) {
BX_ERROR(("WRFSBASE: canonical failure !"));
exception(BX_GP_EXCEPTION, 0);
}
MSR_FSBASE = fsbase;
}
else {
// 32-bit value is always canonical
MSR_FSBASE = BX_READ_32BIT_REG(i->rm());
}
}
/* F3 0F AE /3 */
void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRGSBASE(bxInstruction_c *i)
{
if (! BX_CPU_THIS_PTR cr4.get_FSGSBASE())
exception(BX_UD_EXCEPTION, 0);
if (i->os64L()) {
Bit64u gsbase = BX_READ_64BIT_REG(i->rm());
if (!IsCanonical(gsbase)) {
BX_ERROR(("WRGSBASE: canonical failure !"));
exception(BX_GP_EXCEPTION, 0);
}
MSR_GSBASE = gsbase;
}
else {
// 32-bit value is always canonical
MSR_GSBASE = BX_READ_32BIT_REG(i->rm());
}
}
#endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: param_names.h,v 1.10 2010-07-16 21:03:52 sshwarts Exp $
// $Id: param_names.h,v 1.11 2010-07-22 16:41:58 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2009 The Bochs Project
@ -54,6 +54,7 @@
#define BXPN_CPUID_MWAIT_IS_NOP "cpuid.mwait_is_nop"
#define BXPN_CPUID_1G_PAGES "cpuid.1g_pages"
#define BXPN_CPUID_PCID "cpuid.pcid"
#define BXPN_CPUID_FSGSBASE "cpuid.fsgsbase"
#define BXPN_MEM_SIZE "memory.standard.ram.size"
#define BXPN_HOST_MEM_SIZE "memory.standard.ram.host_size"
#define BXPN_ROM_PATH "memory.standard.rom.path"