implemented SMAP (Supervisor Mode Access Protection) from [Intel Architecture Instruction Set Extensions Programming Reference] rev14

fixed enabling of ADX extensions in generic CPUID when enabled through .bochsrc

Small code cleanups on the way to implementation of APIC Registers Virtualization features disclosed in recent Intel SDM rev043
This commit is contained in:
Stanislav Shwartsman 2012-09-10 15:22:26 +00:00
parent 0386f49e03
commit 2f3c7ff8e4
25 changed files with 166 additions and 38 deletions

View File

@ -285,6 +285,10 @@ cpu: cpuid_limit_winnt=0
# Enable Supervisor Mode Execution Protection (SMEP) support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# SMAP:
# Enable Supervisor Mode Access Protection (SMAP) support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# MWAIT:
# Select MONITOR/MWAIT instructions support.
# This option exists only if Bochs compiled with --enable-monitor-mwait.

View File

@ -58,6 +58,7 @@ cpuid
pcid
fsgsbase
smep
smap
mwait
memory

View File

@ -982,7 +982,8 @@ void bx_dbg_info_control_regs_command(void)
dbg_printf(" PWT=page-level write-through=%d\n", (cr3>>3) & 1);
#if BX_CPU_LEVEL >= 5
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 %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 %s %s\n", cr4,
(cr4 & (1<<21)) ? "SMAP" : "smap",
(cr4 & (1<<20)) ? "SMEP" : "smep",
(cr4 & (1<<18)) ? "OSXSAVE" : "osxsave",
(cr4 & (1<<17)) ? "PCID" : "pcid",

View File

@ -597,6 +597,10 @@ void bx_init_options()
"smep", "Supervisor Mode Execution Protection support",
"Supervisor Mode Execution Protection support",
0);
new bx_param_bool_c(cpuid_param,
"smap", "Supervisor Mode Access Protection support",
"Supervisor Mode Access Protection support",
0);
#if BX_SUPPORT_MONITOR_MWAIT
new bx_param_bool_c(cpuid_param,
"mwait", "MONITOR/MWAIT instructions support",
@ -2625,6 +2629,10 @@ static int parse_line_formatted(const char *context, int num_params, char *param
if (parse_param_bool(params[i], 5, BXPN_CPUID_SMEP) < 0) {
PARSE_ERR(("%s: cpuid directive malformed.", context));
}
} else if (!strncmp(params[i], "smap=", 5)) {
if (parse_param_bool(params[i], 5, BXPN_CPUID_SMAP) < 0) {
PARSE_ERR(("%s: cpuid directive malformed.", context));
}
#if BX_SUPPORT_MONITOR_MWAIT
} else if (!strncmp(params[i], "mwait=", 6)) {
if (parse_param_bool(params[i], 6, BXPN_CPUID_MWAIT) < 0) {
@ -3572,7 +3580,7 @@ int bx_write_configuration(const char *rc, int overwrite)
SIM->get_param_enum(BXPN_CPUID_APIC)->get_selected());
#endif
#if BX_CPU_LEVEL >= 6
fprintf(fp, ", sse=%s, sse4a=%d, sep=%d, aes=%d, xsave=%d, xsaveopt=%d, movbe=%d, adx=%d, smep=%d",
fprintf(fp, ", sse=%s, sse4a=%d, sep=%d, aes=%d, xsave=%d, xsaveopt=%d, movbe=%d, adx=%d, smep=%d, smap=%d",
SIM->get_param_enum(BXPN_CPUID_SSE)->get_selected(),
SIM->get_param_bool(BXPN_CPUID_SSE4A)->get(),
SIM->get_param_bool(BXPN_CPUID_SEP)->get(),
@ -3581,7 +3589,8 @@ int bx_write_configuration(const char *rc, int overwrite)
SIM->get_param_bool(BXPN_CPUID_XSAVEOPT)->get(),
SIM->get_param_bool(BXPN_CPUID_MOVBE)->get(),
SIM->get_param_bool(BXPN_CPUID_ADX)->get(),
SIM->get_param_bool(BXPN_CPUID_SMEP)->get());
SIM->get_param_bool(BXPN_CPUID_SMEP)->get(),
SIM->get_param_bool(BXPN_CPUID_SMAP)->get());
#if BX_SUPPORT_AVX
fprintf(fp, ", avx=%d, avx_f16c=%d, avx_fma=%d, bmi=%d, xop=%d, tbm=%d, fma4=%d",
SIM->get_param_num(BXPN_CPUID_AVX)->get(),

View File

@ -564,7 +564,7 @@ BOCHSAPI extern BX_CPU_C bx_cpu;
#if BX_CPU_LEVEL >= 4
#define IMPLEMENT_EFLAG_SET_ACCESSOR_AC(bitnum) \
BX_CPP_INLINE void BX_CPU_C::assert_AC () { \
BX_CPP_INLINE void BX_CPU_C::assert_AC() { \
BX_CPU_THIS_PTR eflags |= (1<<bitnum); \
handleAlignmentCheck(); \
} \
@ -3170,6 +3170,11 @@ public: // for now...
BX_SMF BX_INSF_TYPE ADOX_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
#endif
// SMAP
BX_SMF BX_INSF_TYPE CLAC(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF BX_INSF_TYPE STAC(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
// SMAP
#if BX_SUPPORT_X86_64
// 64 bit extensions
BX_SMF BX_INSF_TYPE ADD_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
@ -4118,6 +4123,7 @@ public: // for now...
BX_SMF BX_CPP_INLINE int bx_cpuid_support_rdtscp(void);
BX_SMF BX_CPP_INLINE int bx_cpuid_support_tsc_deadline(void);
BX_SMF BX_CPP_INLINE int bx_cpuid_support_xapic_extensions(void);
BX_SMF BX_CPP_INLINE int bx_cpuid_support_smap(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; }
@ -4272,8 +4278,10 @@ public: // for now...
BX_SMF bx_bool is_virtual_apic_page(bx_phy_address paddr) BX_CPP_AttrRegparmN(1);
BX_SMF void VMX_Virtual_Apic_Read(bx_phy_address paddr, unsigned len, void *data);
BX_SMF void VMX_Virtual_Apic_Write(bx_phy_address paddr, unsigned len, void *data);
BX_SMF Bit32u VMX_Read_VTPR(void);
BX_SMF void VMX_Write_VTPR(Bit8u vtpr);
BX_SMF void VMX_TPR_Virtualization(Bit8u vtpr);
BX_SMF Bit32u VMX_Read_Virtual_APIC(unsigned offset);
BX_SMF void VMX_Write_Virtual_APIC(unsigned offset, Bit32u val32);
#endif
// vmexit reasons
BX_SMF void VMexit_Instruction(bxInstruction_c *i, Bit32u reason, bx_bool rw = BX_READ) BX_CPP_AttrRegparmN(3);
@ -4630,6 +4638,11 @@ BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_fsgsbase(void)
#endif
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_smap(void)
{
return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_SMAP) != 0;
}
BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_smep(void)
{
return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_SMEP) != 0;

View File

@ -117,6 +117,7 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
#define BX_ISA_TBM (BX_CONST64(1) << 38) /* TBM instruction (AMD) */
#define BX_ISA_SVM (BX_CONST64(1) << 39) /* SVM instruction (AMD) */
#define BX_ISA_ADX (BX_CONST64(1) << 40) /* ADCX/ADOX instruction */
#define BX_ISA_SMAP (BX_CONST64(1) << 41) /* SMAP support */
// cpuid non-ISA features
#define BX_CPU_DEBUG_EXTENSIONS (1 << 0) /* Debug Extensions support */
@ -317,7 +318,8 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
// [17:12] reserved
// [18:18] RDSEED instruction support
// [19:19] ADCX/ADOX instructions support
// [31:20] reserved
// [20:20] SMAP: Supervisor Mode Access Protection
// [31:21] reserved
#define BX_CPUID_EXT3_FSGSBASE (1 << 0)
#define BX_CPUID_EXT3_RESERVED1 (1 << 1)
@ -339,6 +341,7 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
#define BX_CPUID_EXT3_RESERVED17 (1 << 17)
#define BX_CPUID_EXT3_RDSEED (1 << 18)
#define BX_CPUID_EXT3_ADX (1 << 19)
#define BX_CPUID_EXT3_SMAP (1 << 20)
// ...

View File

@ -1049,6 +1049,7 @@ Bit32u BX_CPU_C::get_cr4_allow_mask(void)
// CR4 bits definitions:
// [31-21] Reserved, Must be Zero
// [21] SMAP: Supervisor Mode Access Protection R/W
// [20] SMEP: Supervisor Mode Execution Protection R/W
// [19] Reserved, Must be Zero
// [18] OSXSAVE: Operating System XSAVE Support R/W
@ -1127,6 +1128,9 @@ Bit32u BX_CPU_C::get_cr4_allow_mask(void)
if (bx_cpuid_support_smep())
allowMask |= BX_CR4_SMEP_MASK;
if (bx_cpuid_support_smap())
allowMask |= BX_CR4_SMAP_MASK;
#endif
return allowMask;
@ -1340,7 +1344,7 @@ Bit32u BX_CPU_C::ReadCR8(bxInstruction_c *i)
VMexit_CR8_Read(i);
if (BX_CPU_THIS_PTR in_vmx_guest && VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW)) {
Bit32u tpr = (VMX_Read_VTPR() >> 4) & 0xf;
Bit32u tpr = (VMX_Read_Virtual_APIC(BX_LAPIC_TPR) >> 4) & 0xf;
return tpr;
}
#endif

View File

@ -105,6 +105,7 @@ struct bx_cr0_t {
#define BX_CR4_PCIDE_MASK (1 << 17)
#define BX_CR4_OSXSAVE_MASK (1 << 18)
#define BX_CR4_SMEP_MASK (1 << 20)
#define BX_CR4_SMAP_MASK (1 << 21)
struct bx_cr4_t {
Bit32u val32; // 32bit value of register
@ -130,6 +131,7 @@ struct bx_cr4_t {
IMPLEMENT_CRREG_ACCESSORS(PCIDE, 17);
IMPLEMENT_CRREG_ACCESSORS(OSXSAVE, 18);
IMPLEMENT_CRREG_ACCESSORS(SMEP, 20);
IMPLEMENT_CRREG_ACCESSORS(SMAP, 21);
BX_CPP_INLINE Bit32u get32() const { return val32; }
BX_CPP_INLINE void set32(Bit32u val) { val32 = val; }

View File

@ -462,8 +462,8 @@ static const BxOpcodeInfo_t BxOpcodeInfoG7[64+8] = {
/* 0F 01 C7 */ { 0, BX_IA_ERROR },
/* 0F 01 C8 */ { BxPrefixSSE, BX_IA_MONITOR, BxOpcodeGroupSSE_ERR },
/* 0F 01 C9 */ { BxPrefixSSE | BxTraceEnd, BX_IA_MWAIT, BxOpcodeGroupSSE_ERR },
/* 0F 01 CA */ { 0, BX_IA_ERROR },
/* 0F 01 CB */ { 0, BX_IA_ERROR },
/* 0F 01 CA */ { 0, BX_IA_CLAC },
/* 0F 01 CB */ { 0, BX_IA_STAC },
/* 0F 01 CC */ { 0, BX_IA_ERROR },
/* 0F 01 CD */ { 0, BX_IA_ERROR },
/* 0F 01 CE */ { 0, BX_IA_ERROR },
@ -541,8 +541,8 @@ static const BxOpcodeInfo_t BxOpcodeInfoG7q[64+8] = {
/* 0F 01 C7 */ { 0, BX_IA_ERROR },
/* 0F 01 C8 */ { BxPrefixSSE, BX_IA_MONITOR, BxOpcodeGroupSSE_ERR },
/* 0F 01 C9 */ { BxPrefixSSE | BxTraceEnd, BX_IA_MWAIT, BxOpcodeGroupSSE_ERR },
/* 0F 01 CA */ { 0, BX_IA_ERROR },
/* 0F 01 CB */ { 0, BX_IA_ERROR },
/* 0F 01 CA */ { 0, BX_IA_CLAC },
/* 0F 01 CB */ { 0, BX_IA_STAC },
/* 0F 01 CC */ { 0, BX_IA_ERROR },
/* 0F 01 CD */ { 0, BX_IA_ERROR },
/* 0F 01 CE */ { 0, BX_IA_ERROR },

View File

@ -393,3 +393,27 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SALC(bxInstruction_c *i)
BX_NEXT_INSTR(i);
}
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STAC(bxInstruction_c *i)
{
if (CPL != 0) {
BX_ERROR(("STAC is not recognized when CPL != 0"));
exception(BX_UD_EXCEPTION, 0);
}
assert_AC();
BX_NEXT_INSTR(i);
}
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLAC(bxInstruction_c *i)
{
if (CPL != 0) {
BX_ERROR(("CLAC is not recognized when CPL != 0"));
exception(BX_UD_EXCEPTION, 0);
}
clear_AC();
BX_NEXT_INSTR(i);
}

View File

@ -998,6 +998,10 @@ void bx_generic_cpuid_t::init_cpu_extensions_bitmask(void)
if (smep_enabled)
features_bitmask |= BX_CPU_SMEP;
static bx_bool smap_enabled = SIM->get_param_bool(BXPN_CPUID_SMAP)->get();
if (smap_enabled)
features_bitmask |= BX_ISA_SMAP;
#if BX_SUPPORT_X86_64
static bx_bool x86_64_enabled = SIM->get_param_bool(BXPN_CPUID_X86_64)->get();
if (x86_64_enabled) {
@ -1456,14 +1460,19 @@ Bit32u bx_generic_cpuid_t::get_ext3_cpuid_features(void) const
// [0:0] FS/GS BASE access instructions
// [2:1] reserved
// [3:3] BMI1: Advanced Bit Manipulation Extensions
// [4:4] reserved
// [4:4] HLE: Hardware Lock Elision
// [5:5] AVX2
// [6:6] reserved
// [7:7] SMEP: Supervisor Mode Execution Protection
// [8:8] BMI2: Advanced Bit Manipulation Extensions
// [9:9] Support for Enhanced REP MOVSB/STOSB
// [10:10] Support for INVPCID instruction
// [31:10] reserved
// [11:11] RTM: Restricted Transactional Memory
// [17:12] reserved
// [18:18] RDSEED instruction support
// [19:19] ADCX/ADOX instructions support
// [20:20] SMAP: Supervisor Mode Access Protection
// [31:21] reserved
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_FSGSBASE))
features |= BX_CPUID_EXT3_FSGSBASE;
@ -1482,6 +1491,12 @@ Bit32u bx_generic_cpuid_t::get_ext3_cpuid_features(void) const
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_INVPCID))
features |= BX_CPUID_EXT3_INVPCID;
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_ADX))
features |= BX_CPUID_EXT3_ADX;
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SMAP))
features |= BX_CPUID_EXT3_SMAP;
return features;
}

View File

@ -2218,3 +2218,7 @@ bx_define_opcode(BX_IA_ADOX_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::ADOX_GdEdR, BX_
bx_define_opcode(BX_IA_ADCX_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::ADCX_GqEqR, BX_ISA_ADX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0)
bx_define_opcode(BX_IA_ADOX_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::ADOX_GqEqR, BX_ISA_ADX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0)
#endif
// SMAP
bx_define_opcode(BX_IA_STAC, NULL, &BX_CPU_C::STAC, BX_ISA_SMAP, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0)
bx_define_opcode(BX_IA_CLAC, NULL, &BX_CPU_C::STAC, BX_ISA_SMAP, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0)

View File

@ -371,7 +371,7 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDMSR(bxInstruction_c *i)
#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;
RAX = VMX_Read_Virtual_APIC(BX_LAPIC_TPR) & 0xff;
RDX = 0;
BX_NEXT_INSTR(i);
}

View File

@ -750,6 +750,12 @@ bx_phy_address BX_CPU_C::translate_linear_long_mode(bx_address laddr, Bit32u &lp
page_fault(ERROR_PROTECTION, laddr, user, rw);
}
// SMAP protections are disabled if EFLAGS.AC=1
if (BX_CPU_THIS_PTR cr4.get_SMAP() && ! BX_CPU_THIS_PTR get_AC() && rw != BX_EXECUTE && ! user) {
if (combined_access & 0x4) // User page
page_fault(ERROR_PROTECTION, laddr, user, rw);
}
if (BX_CPU_THIS_PTR cr4.get_PGE())
combined_access |= (entry[leaf] & 0x100); // G
@ -956,6 +962,12 @@ bx_phy_address BX_CPU_C::translate_linear_PAE(bx_address laddr, Bit32u &lpf_mask
page_fault(ERROR_PROTECTION, laddr, user, rw);
}
// SMAP protections are disabled if EFLAGS.AC=1
if (BX_CPU_THIS_PTR cr4.get_SMAP() && ! BX_CPU_THIS_PTR get_AC() && rw != BX_EXECUTE && ! user) {
if (combined_access & 0x4) // User page
page_fault(ERROR_PROTECTION, laddr, user, rw);
}
if (BX_CPU_THIS_PTR cr4.get_PGE())
combined_access |= (entry[leaf] & 0x100); // G
@ -1062,6 +1074,12 @@ bx_phy_address BX_CPU_C::translate_linear_legacy(bx_address laddr, Bit32u &lpf_m
page_fault(ERROR_PROTECTION, laddr, user, rw);
}
// SMAP protections are disabled if EFLAGS.AC=1
if (BX_CPU_THIS_PTR cr4.get_SMAP() && ! BX_CPU_THIS_PTR get_AC() && rw != BX_EXECUTE && ! user) {
if (combined_access & 0x4) // User page
page_fault(ERROR_PROTECTION, laddr, user, rw);
}
if (BX_CPU_THIS_PTR cr4.get_PGE())
combined_access |= (entry[leaf] & 0x100); // G
#endif

View File

@ -1351,4 +1351,5 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::WRGSBASE(bxInstruction_c *i)
BX_NEXT_INSTR(i);
}
#endif

View File

@ -39,30 +39,27 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::is_virtual_apic_page(bx_phy_address pad
return 0;
}
Bit32u BX_CPU_C::VMX_Read_VTPR(void)
Bit32u BX_CPU_C::VMX_Read_Virtual_APIC(unsigned offset)
{
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcs.virtual_apic_page_addr + BX_LAPIC_TPR;
Bit32u vtpr;
access_read_physical(pAddr, 4, (Bit8u*)(&vtpr));
BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_READ, BX_VMX_VAPIC_ACCESS, (Bit8u*)(&vtpr));
return vtpr;
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcs.virtual_apic_page_addr + offset;
Bit32u field32;
access_read_physical(pAddr, 4, (Bit8u*)(&field32));
BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_READ, BX_VMX_VAPIC_ACCESS, (Bit8u*)(&field32));
return field32;
}
void BX_CPU_C::VMX_Write_Virtual_APIC(unsigned offset, Bit32u val32)
{
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcs.virtual_apic_page_addr + offset;
access_write_physical(pAddr, 4, (Bit8u*)(&val32));
BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_WRITE, BX_VMX_VAPIC_ACCESS, (Bit8u*)(&val32));
}
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 + BX_LAPIC_TPR;
Bit32u field32 = vtpr;
VMX_Write_Virtual_APIC(BX_LAPIC_TPR, vtpr);
access_write_physical(pAddr, 4, (Bit8u*)(&field32));
BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_WRITE, BX_VMX_VAPIC_ACCESS, (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
VMexit(VMX_VMEXIT_TPR_THRESHOLD, 0);
}
VMX_TPR_Virtualization(vtpr);
}
void BX_CPU_C::VMX_Virtual_Apic_Read(bx_phy_address paddr, unsigned len, void *data)
@ -74,7 +71,7 @@ void BX_CPU_C::VMX_Virtual_Apic_Read(bx_phy_address paddr, unsigned len, void *d
// access is not instruction fetch because cpu::prefetch will crash them
if (VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW) && offset == BX_LAPIC_TPR && len <= 4) {
// VTPR access
Bit32u vtpr = VMX_Read_VTPR();
Bit32u vtpr = VMX_Read_Virtual_APIC(BX_LAPIC_TPR);
if (len == 1)
*((Bit8u *) data) = vtpr & 0xff;
else if (len == 2)
@ -108,4 +105,16 @@ void BX_CPU_C::VMX_Virtual_Apic_Write(bx_phy_address paddr, unsigned len, void *
VMexit(VMX_VMEXIT_APIC_ACCESS, qualification);
}
void BX_CPU_C::VMX_TPR_Virtualization(Bit8u vtpr)
{
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
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
VMexit(VMX_VMEXIT_TPR_THRESHOLD, 0);
}
}
#endif // BX_SUPPORT_VMX && BX_SUPPORT_X86_64

View File

@ -429,7 +429,7 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckVmControls(void)
}
if (! (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES)) {
Bit8u tpr_shadow = (VMX_Read_VTPR() >> 4) & 0xf;
Bit8u tpr_shadow = (VMX_Read_Virtual_APIC(BX_LAPIC_TPR) >> 4) & 0xf;
if (vm->vm_tpr_threshold > tpr_shadow) {
BX_ERROR(("VMFAIL: VMCS EXEC CTRL: TPR threshold > TPR shadow"));
return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD;

View File

@ -641,9 +641,10 @@ typedef struct bx_VMCS
Bit64u executive_vmcsptr;
#if BX_SUPPORT_VMX >= 2
// used for pause loop exiting
Bit32u pause_loop_exiting_gap;
Bit32u pause_loop_exiting_window;
Bit64u last_pause_time; // used for pause loop exiting
Bit64u last_pause_time;
Bit32u first_pause_time;
#endif

View File

@ -406,8 +406,8 @@ static BxDisasmOpcodeTable_t BxDisasmGroupSSE_G7VMX[4] = {
static BxDisasmOpcodeTable_t BxDisasmGroupRmMONITOR[8] = {
/* 0 */ { 0, &Ia_monitor },
/* 1 */ { 0, &Ia_mwait },
/* 2 */ { 0, &Ia_Invalid },
/* 3 */ { 0, &Ia_Invalid },
/* 2 */ { 0, &Ia_clac },
/* 3 */ { 0, &Ia_stac },
/* 4 */ { 0, &Ia_Invalid },
/* 5 */ { 0, &Ia_Invalid },
/* 6 */ { 0, &Ia_Invalid },

View File

@ -80,6 +80,7 @@
#define IA_TBM (BX_CONST64(1) << 38) /* TBM instruction (AMD) */
#define IA_SVM (BX_CONST64(1) << 39) /* SVM instruction (AMD) */
#define IA_ADX (BX_CONST64(1) << 40) /* ADCX/ADOX instruction */
#define IA_SMAP (BX_CONST64(1) << 41) /* SMAP instruction */
/* general purpose bit register */
enum {

View File

@ -164,6 +164,7 @@ Ia_cbw = { "cbw", "cbtw", XX, XX, XX, XX, 0 },
Ia_cdq = { "cdq", "cltd", XX, XX, XX, XX, 0 },
Ia_cdqe = { "cdqe", "cltq", XX, XX, XX, XX, 0 },
Ia_cflush = { "cflush", "cflush", Mb, XX, XX, XX, IA_CLFLUSH },
Ia_clac = { "clac", "clac", XX, XX, XX, XX, IA_SMAP },
Ia_clc = { "clc", "clc", XX, XX, XX, XX, 0 },
Ia_cld = { "cld", "cld", XX, XX, XX, XX, 0 },
Ia_clgi = { "clgi", "clgi", XX, XX, XX, XX, IA_SVM },
@ -1273,6 +1274,7 @@ Ia_sqrtpd_Vpd_Wpd = { "sqrtpd", "sqrtpd", Vpd, Wpd, XX, XX, IA_SSE2 },
Ia_sqrtps_Vps_Wps = { "sqrtps", "sqrtps", Vps, Wps, XX, XX, IA_SSE },
Ia_sqrtsd_Vsd_Wsd = { "sqrtsd", "sqrtsd", Vsd, Wsd, XX, XX, IA_SSE2 },
Ia_sqrtss_Vss_Wss = { "sqrtss", "sqrtss", Vss, Wss, XX, XX, IA_SSE },
Ia_stac = { "stac", "stac", XX, XX, XX, XX, IA_SMAP },
Ia_stc = { "stc", "stc", XX, XX, XX, XX, 0 },
Ia_std = { "std", "std", XX, XX, XX, XX, 0 },
Ia_stgi = { "stgi", "stgi", XX, XX, XX, XX, IA_SVM },

View File

@ -3194,6 +3194,11 @@ This option exists only if Bochs compiled with x86-64 support.
Enable Supervisor Mode Execution Protection (SMEP) support.
This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
</para>
<para><command>smap</command></para>
<para>
Enable Supervisor Mode Access Protection (SMAP) support.
This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
</para>
<para><command>mwait</command></para>
<para>
Select MONITOR/MWAIT instructions support.

View File

@ -325,6 +325,11 @@ smep:
Enable Supervisor Mode Execution Protection (SMEP) support.
This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
smap:
Enable Supervisor Mode Access Protection (SMAP) support.
This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
mwait:
Select MONITOR/MWAIT instructions support.

View File

@ -413,7 +413,6 @@ Bochs CPU configurability - go over all CPUID feature extensions and see how and
Enables CPUID[0x00000007].EBX[7] flag.
Controls ability to set CR4[20] (SMEP) bit.
Enables Supervisor Mode Execution Protection during PAE mode page walk.
Enables FS/GS BASE access instructions (will #UD otherwise).
Dependency: PAE
@ -513,3 +512,9 @@ Bochs CPU configurability - go over all CPUID feature extensions and see how and
Dependency: SSSE3 (3-byte opcodes)
61. CPU Feature: SMAP
Enables CPUID[0x00000007].EBX[20] flag.
Controls ability to set CR4[21] (SMAP) bit.
Enables Supervisor Mode Access Protection during page walk.
Enables CLAC/STAC instructions.

View File

@ -74,6 +74,7 @@
#define BXPN_CPUID_PCID "cpuid.pcid"
#define BXPN_CPUID_FSGSBASE "cpuid.fsgsbase"
#define BXPN_CPUID_SMEP "cpuid.smep"
#define BXPN_CPUID_SMAP "cpuid.smap"
#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"