Protection Keys: Implemented Supervisor-Mode Protection Keys (PKS)

This commit is contained in:
Stanislav Shwartsman 2020-05-29 12:35:30 +00:00
parent 2b79641f3a
commit 4023b640d6
16 changed files with 212 additions and 46 deletions

View File

@ -1023,7 +1023,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 %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 %s %s %s %s %s\n", cr4,
(cr4 & (1<<24)) ? "PKS" : "pks",
(cr4 & (1<<23)) ? "CET" : "cet",
(cr4 & (1<<22)) ? "PKE" : "pke",
(cr4 & (1<<21)) ? "SMAP" : "smap",
@ -1033,8 +1034,9 @@ void bx_dbg_info_control_regs_command(void)
(cr4 & (1<<16)) ? "FSGSBASE" : "fsgsbase",
(cr4 & (1<<14)) ? "SMX" : "smx",
(cr4 & (1<<13)) ? "VMX" : "vmx",
(cr4 & (1<<10)) ? "OSXMMEXCPT" : "osxmmexcpt",
(cr4 & (1<<12)) ? "LA57" : "la57",
(cr4 & (1<<11)) ? "UMIP" : "umip",
(cr4 & (1<<10)) ? "OSXMMEXCPT" : "osxmmexcpt",
(cr4 & (1<<9)) ? "OSFXSR" : "osfxsr",
(cr4 & (1<<8)) ? "PCE" : "pce",
(cr4 & (1<<7)) ? "PGE" : "pge",

View File

@ -924,6 +924,7 @@ public: // for now...
#if BX_SUPPORT_PKEYS
// protection keys
Bit32u pkru;
Bit32u pkrs;
// unpacked protection keys to be tested together with accessBits from TLB
// the unpacked key is stored in the accessBits format:
@ -4861,7 +4862,7 @@ public: // for now...
#endif
#if BX_SUPPORT_PKEYS
BX_SMF void set_PKRU(Bit32u pkru);
BX_SMF void set_PKeys(Bit32u pkru, Bit32u pkrs);
#endif
#if BX_SUPPORT_FPU

View File

@ -122,6 +122,7 @@ static const char *cpu_feature_name[] =
"fcs_fds_deprecation", // BX_ISA_FCS_FDS_DEPRECATION
"fdp_deprecation", // BX_ISA_FDP_DEPRECATION
"pku", // BX_ISA_PKU
"pks", // BX_ISA_PKS
"umip", // BX_ISA_UMIP
"rdpid", // BX_ISA_RDPID
"tce", // BX_ISA_TCE

View File

@ -407,7 +407,7 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
// [28:28] MOVDIR64B: MOVDIR64B instruction support
// [29:29] ENQCMD: Enqueue Stores support
// [30:30] SGX_LC: SGX Launch Configuration
// [31:31] reserved
// [31:31] PKS: Protection keys for supervisor-mode pages
#define BX_CPUID_EXT4_PREFETCHWT1 (1 << 0)
#define BX_CPUID_EXT4_AVX512_VBMI (1 << 1)
@ -440,7 +440,7 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
#define BX_CPUID_EXT4_MOVDIR64B (1 << 28)
#define BX_CPUID_EXT4_ENQCMD (1 << 29)
#define BX_CPUID_EXT4_SGX_LAUNCH_CONFIG (1 << 30)
#define BX_CPUID_EXT4_RESERVED31 (1 << 31)
#define BX_CPUID_EXT4_PKS (1 << 31)
// CPUID defines - EXT5 features CPUID[0x00000007].EDX
// -----------------------------
@ -450,7 +450,9 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
// [4:4] Support of Fast REP MOV instructions with short length
// [7:5] reserved
// [8:8] AVX512 VP2INTERSECT instructions support
// [13:9] reserved
// [9:9] reserved
// [10:10] MD clear
// [13:11] reserved
// [14:14] SERIALIZE instruction support
// [15:15] Hybrid
// [16:16] TSXLDTRK: TSX suspent load tracking support
@ -474,7 +476,7 @@ typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu);
#define BX_CPUID_EXT5_RESERVED7 (1 << 7)
#define BX_CPUID_EXT5_AVX512_VPINTERSECT (1 << 8)
#define BX_CPUID_EXT5_RESERVED9 (1 << 9)
#define BX_CPUID_EXT5_RESERVED10 (1 << 10)
#define BX_CPUID_EXT5_MD_CLEAR (1 << 10)
#define BX_CPUID_EXT5_RESERVED11 (1 << 11)
#define BX_CPUID_EXT5_RESERVED12 (1 << 12)
#define BX_CPUID_EXT5_RESERVED13 (1 << 13)

View File

@ -1143,7 +1143,7 @@ bx_bool BX_CPU_C::SetCR0(bxInstruction_c *i, bx_address val)
if ((oldCR0 & 0x80010001) != (val_32 & 0x80010001)) {
TLB_flush(); // Flush Global entries also
#if BX_SUPPORT_PKEYS
set_PKRU(BX_CPU_THIS_PTR pkru); // recalculate protection keys due to CR0.WP change
set_PKeys(BX_CPU_THIS_PTR pkru, BX_CPU_THIS_PTR pkrs); // recalculate protection keys due to CR0.WP change
#endif
}
@ -1256,6 +1256,11 @@ Bit32u BX_CPU_C::get_cr4_allow_mask(void)
allowMask |= BX_CR4_CET_MASK;
#endif
#if BX_SUPPORT_PKEYS
if (is_cpu_extension_supported(BX_ISA_PKS))
allowMask |= BX_CR4_PKS_MASK;
#endif
#endif
return allowMask;
@ -1361,9 +1366,9 @@ bx_bool BX_CPU_C::SetCR4(bxInstruction_c *i, bx_address val)
#endif
#endif
// re-calculate protection keys if CR4.PKE was set
// re-calculate protection keys if CR4.PKE/CR4.PKS was set
#if BX_SUPPORT_PKEYS
set_PKRU(BX_CPU_THIS_PTR pkru);
set_PKeys(BX_CPU_THIS_PTR pkru, BX_CPU_THIS_PTR pkrs);
#endif
return 1;

View File

@ -100,6 +100,7 @@ struct bx_cr0_t {
#define BX_CR4_OSFXSR_MASK (1 << 9)
#define BX_CR4_OSXMMEXCPT_MASK (1 << 10)
#define BX_CR4_UMIP_MASK (1 << 11)
#define BX_CR4_LA57_MASK (1 << 12)
#define BX_CR4_VMXE_MASK (1 << 13)
#define BX_CR4_SMXE_MASK (1 << 14)
#define BX_CR4_FSGSBASE_MASK (1 << 16)
@ -109,6 +110,7 @@ struct bx_cr0_t {
#define BX_CR4_SMAP_MASK (1 << 21)
#define BX_CR4_PKE_MASK (1 << 22)
#define BX_CR4_CET_MASK (1 << 23)
#define BX_CR4_PKS_MASK (1 << 24)
struct bx_cr4_t {
Bit32u val32; // 32bit value of register
@ -125,6 +127,7 @@ struct bx_cr4_t {
IMPLEMENT_CRREG_ACCESSORS(OSFXSR, 9);
IMPLEMENT_CRREG_ACCESSORS(OSXMMEXCPT, 10);
IMPLEMENT_CRREG_ACCESSORS(UMIP, 11);
IMPLEMENT_CRREG_ACCESSORS(LA57, 12);
#if BX_SUPPORT_VMX
IMPLEMENT_CRREG_ACCESSORS(VMXE, 13);
#endif
@ -138,12 +141,13 @@ struct bx_cr4_t {
IMPLEMENT_CRREG_ACCESSORS(SMAP, 21);
IMPLEMENT_CRREG_ACCESSORS(PKE, 22);
IMPLEMENT_CRREG_ACCESSORS(CET, 23);
IMPLEMENT_CRREG_ACCESSORS(PKS, 24);
BX_CPP_INLINE Bit32u get32() const { return val32; }
BX_CPP_INLINE void set32(Bit32u val) { val32 = val; }
};
const Bit32u BX_CR4_FLUSH_TLB_MASK = (BX_CR4_PSE_MASK | BX_CR4_PAE_MASK | BX_CR4_PGE_MASK | BX_CR4_PCIDE_MASK | BX_CR4_SMEP_MASK | BX_CR4_SMAP_MASK | BX_CR4_PKE_MASK | BX_CR4_CET_MASK);
const Bit32u BX_CR4_FLUSH_TLB_MASK = (BX_CR4_PSE_MASK | BX_CR4_PAE_MASK | BX_CR4_PGE_MASK | BX_CR4_PCIDE_MASK | BX_CR4_SMEP_MASK | BX_CR4_SMAP_MASK | BX_CR4_PKE_MASK | BX_CR4_CET_MASK | BX_CR4_PKS_MASK);
#endif // #if BX_CPU_LEVEL >= 5

View File

@ -118,6 +118,7 @@ enum x86_feature_name {
BX_ISA_FCS_FDS_DEPRECATION, /* FCS/FDS Deprecation */
BX_ISA_FDP_DEPRECATION, /* FDP Deprecation - FDP update on unmasked x87 exception only */
BX_ISA_PKU, /* User-Mode Protection Keys */
BX_ISA_PKS, /* Supervisor-Mode Protection Keys */
BX_ISA_UMIP, /* User-Mode Instructions Prevention */
BX_ISA_RDPID, /* RDPID Support */
BX_ISA_TCE, /* Translation Cache Extensions (TCE) support (AMD) */

View File

@ -277,6 +277,7 @@ void BX_CPU_C::register_state(void)
#if BX_SUPPORT_PKEYS
BXRS_HEX_PARAM_FIELD(cpu, pkru, pkru);
BXRS_HEX_PARAM_FIELD(cpu, pkrs, pkrs);
#endif
for(n=0; n<6; n++) {
@ -656,7 +657,7 @@ void BX_CPU_C::after_restore_state(void)
#endif
#if BX_SUPPORT_PKEYS
set_PKRU(BX_CPU_THIS_PTR pkru);
set_PKeys(BX_CPU_THIS_PTR pkru, BX_CPU_THIS_PTR pkrs);
#endif
assert_checks();
@ -942,7 +943,7 @@ void BX_CPU_C::reset(unsigned source)
if (source == BX_RESET_HARDWARE) {
#if BX_SUPPORT_PKEYS
BX_CPU_THIS_PTR set_PKRU(0);
BX_CPU_THIS_PTR set_PKeys(0, 0);
#endif
#if BX_CPU_LEVEL >= 6

View File

@ -212,6 +212,16 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::rdmsr(Bit32u index, Bit64u *msr)
break;
#endif
#if BX_SUPPORT_PKEYS
case BX_MSR_IA32_PKRS:
if (! is_cpu_extension_supported(BX_ISA_PKS)) {
BX_ERROR(("RDMSR BX_MSR_IS32_PKS: Supervisor-Mode Protection Keys not enabled in the cpu model"));
return handle_unknown_rdmsr(index, msr);
}
val64 = BX_CPU_THIS_PTR pkrs;
break;
#endif
#if BX_CPU_LEVEL >= 6
case BX_MSR_TSC_DEADLINE:
if (! is_cpu_extension_supported(BX_ISA_TSC_DEADLINE)) {
@ -842,6 +852,17 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64)
break;
#endif
#if BX_SUPPORT_PKEYS
case BX_MSR_IA32_PKRS:
if (! is_cpu_extension_supported(BX_ISA_PKS)) {
BX_ERROR(("WRMSR BX_MSR_IS32_PKS: Supervisor-Mode Protection Keys not enabled in the cpu model"));
return handle_unknown_wrmsr(index, val_64);
}
BX_CPU_THIS_PTR pkrs = val_64;
set_PKeys(BX_CPU_THIS_PTR pkru, BX_CPU_THIS_PTR pkrs);
break;
#endif
#if BX_CPU_LEVEL >= 6
case BX_MSR_TSC_DEADLINE:
if (! is_cpu_extension_supported(BX_ISA_TSC_DEADLINE)) {

View File

@ -135,6 +135,8 @@ enum MSR_Register {
BX_MSR_IA32_INTERRUPT_SSP_TABLE_ADDR = 0x6A8,
BX_MSR_IA32_PKRS = 0x6E1,
BX_MSR_XSS = 0xda0,
/* AMD MSRs */

View File

@ -732,13 +732,13 @@ bx_phy_address BX_CPU_C::translate_linear_long_mode(bx_address laddr, Bit32u &lp
if (curr_entry & 0x80) {
if (leaf > (BX_LEVEL_PDE + !!is_cpu_extension_supported(BX_ISA_1G_PAGES))) {
BX_DEBUG(("PAE %s: PS bit set !", bx_paging_level[leaf]));
BX_DEBUG(("long mode %s: PS bit set !", bx_paging_level[leaf]));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, user, rw);
}
ppf &= BX_CONST64(0x000fffffffffe000);
if (ppf & offset_mask) {
BX_DEBUG(("PAE %s: reserved bit is set: 0x" FMT_ADDRX64, bx_paging_level[leaf], curr_entry));
BX_DEBUG(("long mode %s: reserved bit is set: 0x" FMT_ADDRX64, bx_paging_level[leaf], curr_entry));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, user, rw);
}
@ -752,20 +752,40 @@ bx_phy_address BX_CPU_C::translate_linear_long_mode(bx_address laddr, Bit32u &lp
bx_bool isWrite = (rw & 1); // write or r-m-w
#if BX_SUPPORT_PKEYS
if (BX_CPU_THIS_PTR cr4.get_PKE() && user) {
pkey = (entry[leaf] >> 59) & 0xf;
if (rw != BX_EXECUTE) {
if (BX_CPU_THIS_PTR cr4.get_PKE()) {
pkey = (entry[leaf] >> 59) & 0xf;
if (rw != BX_EXECUTE) {
// check of accessDisable bit set
if (BX_CPU_THIS_PTR pkru & (1<<(pkey*2))) {
BX_ERROR(("PAE: protection key access not allowed PKRU=%x pkey=%d", BX_CPU_THIS_PTR pkru, pkey));
page_fault(ERROR_PROTECTION | ERROR_PKEY, laddr, user, rw);
if (user) {
if (BX_CPU_THIS_PTR pkru & (1<<(pkey*2))) {
BX_ERROR(("protection key access not allowed PKRU=%x pkey=%d", BX_CPU_THIS_PTR pkru, pkey));
page_fault(ERROR_PROTECTION | ERROR_PKEY, laddr, user, rw);
}
}
// check of writeDisable bit set
if (BX_CPU_THIS_PTR pkru & (1<<(pkey*2+1))) {
if (isWrite && (user || BX_CPU_THIS_PTR cr0.get_WP())) {
BX_ERROR(("PAE: protection key write not allowed PKRU=%x pkey=%d", BX_CPU_THIS_PTR pkru, pkey));
BX_ERROR(("protection key write not allowed PKRU=%x pkey=%d", BX_CPU_THIS_PTR pkru, pkey));
page_fault(ERROR_PROTECTION | ERROR_PKEY, laddr, user, rw);
}
}
}
if (BX_CPU_THIS_PTR cr4.get_PKS() && !user) {
pkey = (entry[leaf] >> 59) & 0xf;
// check of accessDisable bit set
if (BX_CPU_THIS_PTR pkrs & (1<<(pkey*2))) {
BX_ERROR(("protection key access not allowed PKRS=%x pkey=%d", BX_CPU_THIS_PTR pkrs, pkey));
page_fault(ERROR_PROTECTION | ERROR_PKEY, laddr, user, rw);
}
// check of writeDisable bit set
if (BX_CPU_THIS_PTR pkrs & (1<<(pkey*2+1))) {
if (isWrite && BX_CPU_THIS_PTR cr0.get_WP()) {
BX_ERROR(("protection key write not allowed PKRS=%x pkey=%d", BX_CPU_THIS_PTR pkrs, pkey));
page_fault(ERROR_PROTECTION | ERROR_PKEY, laddr, user, rw);
}
}

View File

@ -375,7 +375,7 @@ void BX_CPU_C::handleCpuModeChange(void)
// re-initialize protection keys
#if BX_SUPPORT_PKEYS
set_PKRU(BX_CPU_THIS_PTR pkru);
set_PKeys(BX_CPU_THIS_PTR pkru, BX_CPU_THIS_PTR pkrs);
#endif
if (mode != BX_CPU_THIS_PTR cpu_mode) {
@ -1347,26 +1347,43 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRGSBASE_Eq(bxInstruction_c *i)
#if BX_SUPPORT_PKEYS
void BX_CPU_C::set_PKRU(Bit32u pkru_val)
void BX_CPU_C::set_PKeys(Bit32u pkru_val, Bit32u pkrs_val)
{
BX_CPU_THIS_PTR pkru = pkru_val;
BX_CPU_THIS_PTR pkrs = pkrs_val;
for (unsigned i=0; i<16; i++) {
BX_CPU_THIS_PTR rd_pkey[i] = BX_CPU_THIS_PTR wr_pkey[i] =
TLB_SysReadOK | TLB_UserReadOK | TLB_SysWriteOK | TLB_UserWriteOK;
if (long_mode() && BX_CPU_THIS_PTR cr4.get_PKE()) {
// accessDisable bit set
if (pkru_val & (1<<(i*2))) {
BX_CPU_THIS_PTR rd_pkey[i] &= ~(TLB_UserReadOK | TLB_UserWriteOK);
BX_CPU_THIS_PTR wr_pkey[i] &= ~(TLB_UserReadOK | TLB_UserWriteOK);
if (long_mode()) {
if (BX_CPU_THIS_PTR cr4.get_PKE()) {
// accessDisable bit set
if (pkru_val & (1<<(i*2))) {
BX_CPU_THIS_PTR rd_pkey[i] &= ~(TLB_UserReadOK | TLB_UserWriteOK);
BX_CPU_THIS_PTR wr_pkey[i] &= ~(TLB_UserReadOK | TLB_UserWriteOK);
}
// writeDisable bit set
if (pkru_val & (1<<(i*2+1))) {
BX_CPU_THIS_PTR wr_pkey[i] &= ~(TLB_UserWriteOK);
if (BX_CPU_THIS_PTR cr0.get_WP())
BX_CPU_THIS_PTR wr_pkey[i] &= ~(TLB_SysWriteOK);
}
}
if (BX_CPU_THIS_PTR cr4.get_PKS()) {
// accessDisable bit set
if (pkrs_val & (1<<(i*2))) {
BX_CPU_THIS_PTR rd_pkey[i] &= ~(TLB_SysReadOK | TLB_SysWriteOK);
BX_CPU_THIS_PTR wr_pkey[i] &= ~(TLB_SysReadOK | TLB_SysWriteOK);
}
// writeDisable bit set
if (pkru_val & (1<<(i*2+1))) {
BX_CPU_THIS_PTR wr_pkey[i] &= ~(TLB_UserWriteOK);
if (BX_CPU_THIS_PTR cr0.get_WP())
BX_CPU_THIS_PTR wr_pkey[i] &= ~(TLB_SysWriteOK);
// writeDisable bit set
if (pkrs_val & (1<<(i*2+1))) {
if (BX_CPU_THIS_PTR cr0.get_WP())
BX_CPU_THIS_PTR wr_pkey[i] &= ~(TLB_SysWriteOK);
}
}
}
@ -1400,7 +1417,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRPKRU(bxInstruction_c *i)
if ((ECX|EDX) != 0)
exception(BX_GP_EXCEPTION, 0);
BX_CPU_THIS_PTR set_PKRU(EAX);
BX_CPU_THIS_PTR set_PKeys(EAX, BX_CPU_THIS_PTR pkrs);
BX_NEXT_TRACE(i);
}

View File

@ -407,6 +407,12 @@ bx_bool BX_CPU_C::vmcs_field_supported(Bit32u encoding)
return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT);
#endif
#if BX_SUPPORT_PKEYS
case VMCS_64BIT_GUEST_IA32_PKRS:
case VMCS_64BIT_GUEST_IA32_PKRS_HI:
return is_cpu_extension_supported(BX_ISA_PKS);
#endif
#if BX_SUPPORT_VMX >= 2
/* VMCS 64-bit host state fields */
/* binary 0010_11xx_xxxx_xxx0 */
@ -423,6 +429,12 @@ bx_bool BX_CPU_C::vmcs_field_supported(Bit32u encoding)
case VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL_HI:
return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PERF_GLOBAL_CTRL);
#if BX_SUPPORT_PKEYS
case VMCS_64BIT_HOST_IA32_PKRS:
case VMCS_64BIT_HOST_IA32_PKRS_HI:
return is_cpu_extension_supported(BX_ISA_PKS);
#endif
/* VMCS natural width control fields */
/* binary 0110_00xx_xxxx_xxx0 */
case VMCS_CONTROL_CR0_GUEST_HOST_MASK:
@ -800,6 +812,8 @@ void BX_CPU_C::init_vmexit_ctrls(void)
// [20] Save guest MSR_EFER on VMEXIT
// [21] Load host MSR_EFER on VMEXIT
// [22] Save VMX preemption timer counter on VMEXIT
// [28] Save host CET state on VMEXIT
// [29] Save host MSR_IA32_PKRS on VMEXIT
cap->vmx_vmexit_ctrl_supported_bits =
VMX_VMEXIT_CTRL1_INTA_ON_VMEXIT | VMX_VMEXIT_CTRL1_SAVE_DBG_CTRLS;
@ -826,6 +840,10 @@ void BX_CPU_C::init_vmexit_ctrls(void)
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CET))
cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_LOAD_HOST_CET_STATE;
#endif
#if BX_SUPPORT_PKEYS
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_PKS))
cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_LOAD_HOST_PKRS;
#endif
}
void BX_CPU_C::init_vmentry_ctrls(void)
@ -844,6 +862,8 @@ void BX_CPU_C::init_vmentry_ctrls(void)
// [13] Load guest MSR_PERF_GLOBAL_CTRL
// [14] Load guest MSR_PAT
// [15] Load guest MSR_EFER
// [17] Load guest CET state
// [17] Load guest MSR_IA32_PKRS value
cap->vmx_vmentry_ctrl_supported_bits = VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS |
VMX_VMENTRY_CTRL1_SMM_ENTER |
@ -865,6 +885,10 @@ void BX_CPU_C::init_vmentry_ctrls(void)
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CET))
cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_GUEST_CET_STATE;
#endif
#if BX_SUPPORT_PKEYS
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_PKS))
cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS;
#endif
}
#endif // BX_SUPPORT_VMX

View File

@ -1222,6 +1222,10 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckHostState(void)
BX_ERROR(("VMFAIL: VMCS host SSP non canonical or invalid"));
return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD;
}
if ((host_state->ssp & 0x3) != 0) {
BX_ERROR(("VMFAIL: VMCS host SSP[1:0] not zero"));
return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD;
}
host_state->interrupt_ssp_table_address = VMread_natural(VMCS_HOST_INTERRUPT_SSP_TABLE_ADDR);
if (!IsCanonical(host_state->interrupt_ssp_table_address)) {
@ -1230,7 +1234,17 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckHostState(void)
}
if ((host_state->cr4 & BX_CR4_CET_MASK) && (host_state->cr0 & BX_CR0_WP_MASK) == 0) {
BX_ERROR(("VMENTER FAIL: VMCS host CR4.CET=1 when CR0.WP=0"));
BX_ERROR(("FAIL: VMCS host CR4.CET=1 when CR0.WP=0"));
return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD;
}
}
#endif
#if BX_SUPPORT_PKEYS
if (vmexit_ctrls & VMX_VMEXIT_CTRL1_LOAD_HOST_PKRS) {
host_state->pkrs = VMread64(VMCS_64BIT_HOST_IA32_PKRS);
if (GET32H(host_state->pkrs) != 0) {
BX_ERROR(("VMFAIL: invalid host IA32_PKRS value"));
return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD;
}
}
@ -1444,6 +1458,10 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
BX_ERROR(("VMFAIL: VMCS guest SSP non canonical or invalid"));
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
}
if ((guest.ssp & 0x3) != 0) {
BX_ERROR(("VMFAIL: VMCS guest SSP[1:0] not zero"));
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
}
guest.interrupt_ssp_table_address = VMread_natural(VMCS_GUEST_INTERRUPT_SSP_TABLE_ADDR);
if (!IsCanonical(guest.interrupt_ssp_table_address)) {
@ -1453,6 +1471,16 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
}
#endif
#if BX_SUPPORT_PKEYS
if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS) {
guest.pkrs = VMread64(VMCS_64BIT_GUEST_IA32_PKRS);
if (GET32H(guest.pkrs) != 0) {
BX_ERROR(("VMFAIL: invalid guest IA32_PKRS value"));
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
}
}
#endif
//
// Load and Check Guest State from VMCS - Segment Registers
//
@ -2041,6 +2069,12 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
}
#endif
#if BX_SUPPORT_PKEYS
if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS) {
set_PKeys(BX_CPU_THIS_PTR pkru, guest.pkrs);
}
#endif
BX_CPU_THIS_PTR async_event = 0;
setEFlags((Bit32u) guest.rflags);
@ -2322,6 +2356,12 @@ void BX_CPU_C::VMexitSaveGuestState(void)
}
#endif
#if BX_SUPPORT_PKEYS
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_PKS)) {
VMwrite64(VMCS_64BIT_GUEST_IA32_PKRS, BX_CPU_THIS_PTR pkrs);
}
#endif
for (n=0; n<6; n++) {
Bit32u selector = BX_CPU_THIS_PTR sregs[n].selector.value;
bx_bool invalid = !BX_CPU_THIS_PTR sregs[n].cache.valid;
@ -2613,6 +2653,12 @@ void BX_CPU_C::VMexitLoadHostState(void)
}
#endif
#if BX_SUPPORT_PKEYS
if (vmexit_ctrls & VMX_VMEXIT_CTRL1_LOAD_HOST_PKRS) {
set_PKeys(BX_CPU_THIS_PTR pkru, host_state->pkrs);
}
#endif
BX_CPU_THIS_PTR inhibit_mask = 0;
BX_CPU_THIS_PTR debug_trap = 0;
@ -4028,6 +4074,9 @@ void BX_CPU_C::register_vmx_state(bx_param_c *parent)
BXRS_HEX_PARAM_FIELD(host, SSP, BX_CPU_THIS_PTR vmcs.host_state.ssp);
BXRS_HEX_PARAM_FIELD(host, interrupt_ssp_table_address, BX_CPU_THIS_PTR vmcs.host_state.interrupt_ssp_table_address);
#endif
#if BX_SUPPORT_PKEYS
BXRS_HEX_PARAM_FIELD(host, pkrs, BX_CPU_THIS_PTR vmcs.host_state.pkrs);
#endif
}
#endif // BX_SUPPORT_VMX

View File

@ -302,8 +302,12 @@ const Bit64u VMX_VMFUNC_EPTP_SWITCHING_MASK = (BX_CONST64(1) << VMX_VMFUNC_EPTP_
#define VMCS_64BIT_GUEST_IA32_PDPTE2_HI 0x0000280F
#define VMCS_64BIT_GUEST_IA32_PDPTE3 0x00002810
#define VMCS_64BIT_GUEST_IA32_PDPTE3_HI 0x00002811
#define VMCS_64BIT_GUEST_IA32_BNDCFGS 0x00002812 /* MPX */
#define VMCS_64BIT_GUEST_IA32_BNDCFGS 0x00002812 /* MPX (not implemented) */
#define VMCS_64BIT_GUEST_IA32_BNDCFGS_HI 0x00002813
#define VMCS_64BIT_GUEST_IA32_RTIT_CTL 0x00002814 /* Processor Trace (not implemented) */
#define VMCS_64BIT_GUEST_IA32_RTIT_CTL_HI 0x00002815
#define VMCS_64BIT_GUEST_IA32_PKRS 0x00002818 /* Supervisor-Mode Protection Keys */
#define VMCS_64BIT_GUEST_IA32_PKRS_HI 0x00002819
/* VMCS 64-bit host state fields */
/* binary 0010_11xx_xxxx_xxx0 */
@ -313,6 +317,8 @@ const Bit64u VMX_VMFUNC_EPTP_SWITCHING_MASK = (BX_CONST64(1) << VMX_VMFUNC_EPTP_
#define VMCS_64BIT_HOST_IA32_EFER_HI 0x00002C03
#define VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL 0x00002C04 /* Perf Global Ctrl */
#define VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL_HI 0x00002C05
#define VMCS_64BIT_HOST_IA32_PKRS 0x00002C06 /* Supervisor-Mode Protection Keys */
#define VMCS_64BIT_HOST_IA32_PKRS_HI 0x00002C07
/* VMCS 32_bit control fields */
/* binary 0100_00xx_xxxx_xxx0 */
@ -597,6 +603,10 @@ typedef struct bx_VMCS_GUEST_STATE
bx_address ssp;
bx_address interrupt_ssp_table_address;
#endif
#if BX_SUPPORT_PKEYS
Bit32u pkrs;
#endif
} VMCS_GUEST_STATE;
typedef struct bx_VMCS_HOST_STATE
@ -635,6 +645,10 @@ typedef struct bx_VMCS_HOST_STATE
bx_address ssp;
bx_address interrupt_ssp_table_address;
#endif
#if BX_SUPPORT_PKEYS
Bit32u pkrs;
#endif
} VMCS_HOST_STATE;
typedef struct bx_VMX_Cap
@ -676,7 +690,7 @@ typedef struct bx_VMCS
#define VMX_VM_EXEC_CTRL1_NMI_EXITING (1 << 3)
#define VMX_VM_EXEC_CTRL1_VIRTUAL_NMI (1 << 5) /* Virtual NMI */
#define VMX_VM_EXEC_CTRL1_VMX_PREEMPTION_TIMER_VMEXIT (1 << 6) /* VMX preemption timer */
#define VMX_VM_EXEC_CTRL1_PROCESS_POSTED_INTERRUPTS (1 << 7) /* Posted Interrupts */
#define VMX_VM_EXEC_CTRL1_PROCESS_POSTED_INTERRUPTS (1 << 7) /* Posted Interrupts (not implemented) */
#define VMX_VM_EXEC_CTRL1_SUPPORTED_BITS \
(BX_CPU_THIS_PTR vmx_cap.vmx_pin_vmexec_ctrl_supported_bits)
@ -729,7 +743,7 @@ typedef struct bx_VMCS
#define VMX_VM_EXEC_CTRL3_RDSEED_VMEXIT (1 << 16)
#define VMX_VM_EXEC_CTRL3_PML_ENABLE (1 << 17) /* Page Modification Logging */
#define VMX_VM_EXEC_CTRL3_EPT_VIOLATION_EXCEPTION (1 << 18) /* #VE Exception */
#define VMX_VM_EXEC_CTRL3_SUPPRESS_GUEST_VMX_TRACE (1 << 19) /* Processor Trace */
#define VMX_VM_EXEC_CTRL3_SUPPRESS_GUEST_VMX_TRACE (1 << 19) /* Processor Trace (not implemented) */
#define VMX_VM_EXEC_CTRL3_XSAVES_XRSTORS (1 << 20) /* XSAVES */
#define VMX_VM_EXEC_CTRL3_MBE_CTRL (1 << 22) /* Mode Based Execution Control (not implemented yet) */
#define VMX_VM_EXEC_CTRL3_SUBPAGE_WR_PROTECT_CTRL (1 << 23) /* Sub-Page Write Protection Control */
@ -813,9 +827,10 @@ typedef struct bx_VMCS
#define VMX_VMEXIT_CTRL1_STORE_EFER_MSR (1 << 20) /* EFER */
#define VMX_VMEXIT_CTRL1_LOAD_EFER_MSR (1 << 21) /* EFER */
#define VMX_VMEXIT_CTRL1_STORE_VMX_PREEMPTION_TIMER (1 << 22) /* VMX preemption timer */
#define VMX_VMEXIT_CTRL1_CLEAR_BNDCFGS (1 << 23) /* MPX */
#define VMX_VMEXIT_CTRL1_SUPPRESS_VMX_PACKETS (1 << 24) /* Processor Trace */
#define VMX_VMEXIT_CTRL1_CLEAR_BNDCFGS (1 << 23) /* MPX (not implemented) */
#define VMX_VMEXIT_CTRL1_SUPPRESS_VMX_PACKETS (1 << 24) /* Processor Trace (not implemented) */
#define VMX_VMEXIT_CTRL1_LOAD_HOST_CET_STATE (1 << 28) /* CET */
#define VMX_VMEXIT_CTRL1_LOAD_HOST_PKRS (1 << 29) /* Supervisor-Mode Protection Keys */
#define VMX_VMEXIT_CTRL1_SUPPORTED_BITS \
(BX_CPU_THIS_PTR vmx_cap.vmx_vmexit_ctrl_supported_bits)
@ -838,9 +853,10 @@ typedef struct bx_VMCS
#define VMX_VMENTRY_CTRL1_LOAD_PERF_GLOBAL_CTRL_MSR (1 << 13) /* Perf Global Ctrl */
#define VMX_VMENTRY_CTRL1_LOAD_PAT_MSR (1 << 14) /* PAT */
#define VMX_VMENTRY_CTRL1_LOAD_EFER_MSR (1 << 15) /* EFER */
#define VMX_VMENTRY_CTRL1_LOAD_BNDCFGS (1 << 16) /* MPX */
#define VMX_VMENTRY_CTRL1_SUPPRESS_VMX_PACKETS (1 << 17) /* Processor Trace */
#define VMX_VMENTRY_CTRL1_LOAD_BNDCFGS (1 << 16) /* MPX (not implemented) */
#define VMX_VMENTRY_CTRL1_SUPPRESS_VMX_PACKETS (1 << 17) /* Processor Trace (not implemented) */
#define VMX_VMENTRY_CTRL1_LOAD_GUEST_CET_STATE (1 << 20) /* CET */
#define VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS (1 << 22) /* Supervisor-Mode Protection Keys */
#define VMX_VMENTRY_CTRL1_SUPPORTED_BITS \
(BX_CPU_THIS_PTR vmx_cap.vmx_vmentry_ctrl_supported_bits)

View File

@ -422,7 +422,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::XRSTOR(bxInstruction_c *i)
#if BX_SUPPORT_PKEYS
// take effect of changing the PKRU state
if ((requested_feature_bitmap & BX_XCR0_PKRU_MASK) != 0) {
set_PKRU(TMP32);
set_PKeys(TMP32, BX_CPU_THIS_PTR pkrs);
}
#endif
@ -875,14 +875,14 @@ void BX_CPU_C::xsave_pkru_state(bxInstruction_c *i, bx_address offset)
void BX_CPU_C::xrstor_pkru_state(bxInstruction_c *i, bx_address offset)
{
// just write the pkru to TMP register for now and don't call set_PKRU
// just write the pkru to TMP register for now and don't call set_PKeys
// calling it will take immediate effect on all future memory accesses including load of other XRSTOR components
TMP32 = read_virtual_dword(i->seg(), offset);
}
void BX_CPU_C::xrstor_init_pkru_state(void)
{
// just write the pkru to TMP register for now and don't call set_PKRU
// just write the pkru to TMP register for now and don't call set_PKeys
// calling it will take immediate effect on all future memory accesses including load of other XRSTOR components
TMP32 = 0;
}