Protection Keys: Implemented Supervisor-Mode Protection Keys (PKS)
This commit is contained in:
parent
2b79641f3a
commit
4023b640d6
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) */
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
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 (user) {
|
||||
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));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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,15 +1347,17 @@ 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()) {
|
||||
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);
|
||||
@ -1370,6 +1372,21 @@ void BX_CPU_C::set_PKRU(Bit32u pkru_val)
|
||||
}
|
||||
}
|
||||
|
||||
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 (pkrs_val & (1<<(i*2+1))) {
|
||||
if (BX_CPU_THIS_PTR cr0.get_WP())
|
||||
BX_CPU_THIS_PTR wr_pkey[i] &= ~(TLB_SysWriteOK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_CET
|
||||
// replicate pkey access bits for shadow stack checks
|
||||
BX_CPU_THIS_PTR rd_pkey[i] |= BX_CPU_THIS_PTR rd_pkey[i]<<4;
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user