@@ -140,6 +140,7 @@
#define X86_FEATURE_RDSEED 18 /* RDSEED instruction */
#define X86_FEATURE_ADX 19 /* ADCX, ADOX instructions */
#define X86_FEATURE_SMAP 20 /* Supervisor Mode Access Protection */
+#define X86_FEATURE_PCOMMIT 22 /* PCOMMIT instruction */
#define X86_FEATURE_CLFLUSHOPT 23 /* CLFLUSHOPT instruction */
#define X86_FEATURE_CLWB 24 /* CLWB instruction */
@@ -427,6 +427,7 @@ static void xc_cpuid_hvm_policy(xc_interface *xch,
bitmaskof(X86_FEATURE_ADX) |
bitmaskof(X86_FEATURE_SMAP) |
bitmaskof(X86_FEATURE_FSGSBASE) |
+ bitmaskof(X86_FEATURE_PCOMMIT) |
bitmaskof(X86_FEATURE_CLWB) |
bitmaskof(X86_FEATURE_CLFLUSHOPT));
} else
@@ -4583,21 +4583,28 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
*edx &= ~cpufeat_mask(X86_FEATURE_PSE36);
break;
case 0x7:
- if ( (count == 0) && !cpu_has_smep )
- *ebx &= ~cpufeat_mask(X86_FEATURE_SMEP);
+ if ( count == 0 )
+ {
+ if ( !cpu_has_smep )
+ *ebx &= ~cpufeat_mask(X86_FEATURE_SMEP);
+
+ if ( !cpu_has_smap )
+ *ebx &= ~cpufeat_mask(X86_FEATURE_SMAP);
- if ( (count == 0) && !cpu_has_smap )
- *ebx &= ~cpufeat_mask(X86_FEATURE_SMAP);
+ /* Don't expose MPX to hvm when VMX support is not available */
+ if ( !(vmx_vmexit_control & VM_EXIT_CLEAR_BNDCFGS) ||
+ !(vmx_vmentry_control & VM_ENTRY_LOAD_BNDCFGS) )
+ *ebx &= ~cpufeat_mask(X86_FEATURE_MPX);
- /* Don't expose MPX to hvm when VMX support is not available */
- if ( (count == 0) &&
- (!(vmx_vmexit_control & VM_EXIT_CLEAR_BNDCFGS) ||
- !(vmx_vmentry_control & VM_ENTRY_LOAD_BNDCFGS)) )
- *ebx &= ~cpufeat_mask(X86_FEATURE_MPX);
+ /* Don't expose INVPCID to non-hap hvm. */
+ if ( !hap_enabled(d) )
+ *ebx &= ~cpufeat_mask(X86_FEATURE_INVPCID);
+
+ /* Don't expose PCOMMIT to hvm when VMX support is not available */
+ if ( !cpu_has_vmx_pcommit )
+ *ebx &= ~cpufeat_mask(X86_FEATURE_PCOMMIT);
+ }
- /* Don't expose INVPCID to non-hap hvm. */
- if ( (count == 0) && !hap_enabled(d) )
- *ebx &= ~cpufeat_mask(X86_FEATURE_INVPCID);
break;
case 0xb:
/* Fix the x2APIC identifier. */
@@ -242,7 +242,8 @@ static int vmx_init_vmcs_config(void)
SECONDARY_EXEC_ENABLE_INVPCID |
SECONDARY_EXEC_ENABLE_VM_FUNCTIONS |
SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS |
- SECONDARY_EXEC_XSAVES);
+ SECONDARY_EXEC_XSAVES |
+ SECONDARY_EXEC_PCOMMIT);
rdmsrl(MSR_IA32_VMX_MISC, _vmx_misc_cap);
if ( _vmx_misc_cap & VMX_MISC_VMWRITE_ALL )
opt |= SECONDARY_EXEC_ENABLE_VMCS_SHADOWING;
@@ -1075,6 +1076,12 @@ static int construct_vmcs(struct vcpu *v)
__vmwrite(PLE_WINDOW, ple_window);
}
+ /*
+ * We do not intercept pcommit for L1 guest and allow L1 hypervisor to
+ * intercept pcommit for L2 guest (see nvmx_n2_vmexit_handler()).
+ */
+ v->arch.hvm_vmx.secondary_exec_control &= ~SECONDARY_EXEC_PCOMMIT;
+
if ( cpu_has_vmx_secondary_exec_control )
__vmwrite(SECONDARY_VM_EXEC_CONTROL,
v->arch.hvm_vmx.secondary_exec_control);
@@ -3517,6 +3517,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs)
case EXIT_REASON_ACCESS_LDTR_OR_TR:
case EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED:
case EXIT_REASON_INVPCID:
+ case EXIT_REASON_PCOMMIT:
/* fall through */
default:
exit_and_crash:
@@ -1950,6 +1950,8 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 *msr_content)
SECONDARY_EXEC_ENABLE_VPID |
SECONDARY_EXEC_UNRESTRICTED_GUEST |
SECONDARY_EXEC_ENABLE_EPT;
+ if ( cpu_has_vmx_pcommit )
+ data |= SECONDARY_EXEC_PCOMMIT;
data = gen_vmx_msr(data, 0, host_data);
break;
case MSR_IA32_VMX_EXIT_CTLS:
@@ -2226,6 +2228,7 @@ int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs,
case EXIT_REASON_VMXON:
case EXIT_REASON_INVEPT:
case EXIT_REASON_XSETBV:
+ case EXIT_REASON_PCOMMIT:
/* inject to L1 */
nvcpu->nv_vmexit_pending = 1;
break;
@@ -162,6 +162,7 @@
#define X86_FEATURE_RDSEED (7*32+18) /* RDSEED instruction */
#define X86_FEATURE_ADX (7*32+19) /* ADCX, ADOX instructions */
#define X86_FEATURE_SMAP (7*32+20) /* Supervisor Mode Access Prevention */
+#define X86_FEATURE_PCOMMIT (7*32+22) /* PCOMMIT instruction */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 8 */
#define X86_FEATURE_PKU (8*32+ 3) /* Protection Keys for Userspace */
@@ -236,6 +236,7 @@ extern u32 vmx_vmentry_control;
#define SECONDARY_EXEC_ENABLE_PML 0x00020000
#define SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS 0x00040000
#define SECONDARY_EXEC_XSAVES 0x00100000
+#define SECONDARY_EXEC_PCOMMIT 0x00200000
extern u32 vmx_secondary_exec_control;
#define VMX_EPT_EXEC_ONLY_SUPPORTED 0x00000001
@@ -303,7 +304,8 @@ extern u64 vmx_ept_vpid_cap;
(vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_PML)
#define cpu_has_vmx_xsaves \
(vmx_secondary_exec_control & SECONDARY_EXEC_XSAVES)
-
+#define cpu_has_vmx_pcommit \
+ (vmx_secondary_exec_control & SECONDARY_EXEC_PCOMMIT)
#define VMCS_RID_TYPE_MASK 0x80000000
/* GUEST_INTERRUPTIBILITY_INFO flags. */
@@ -213,6 +213,7 @@ static inline void pi_clear_sn(struct pi_desc *pi_desc)
#define EXIT_REASON_PML_FULL 62
#define EXIT_REASON_XSAVES 63
#define EXIT_REASON_XRSTORS 64
+#define EXIT_REASON_PCOMMIT 65
/*
* Interruption-information format