mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-09 03:58:34 +00:00
add vmx capability check
check some essential vmx capablility, will panic if processor doesn't support it. Tracked-On: #6584 Signed-off-by: Mingqiang Chi <mingqiang.chi@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
2b3c4b6d49
commit
db98f01b6e
@ -41,6 +41,42 @@ static struct cpu_capability {
|
|||||||
|
|
||||||
static struct cpuinfo_x86 boot_cpu_data;
|
static struct cpuinfo_x86 boot_cpu_data;
|
||||||
|
|
||||||
|
struct vmx_capability {
|
||||||
|
uint32_t msr;
|
||||||
|
uint32_t bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SDM APPENDIX A:
|
||||||
|
* Bits 31:0 indicate the allowed 0-settings of these controls. VM entry allows control X
|
||||||
|
* to be 0 if bit X in the MSR is cleared to 0; if bit X in the MSR is set to 1,
|
||||||
|
* VM entry fails if control X is 0.
|
||||||
|
* Bits 63:32 indicate the allowed 1-settings of these controls. VM entry allows control X to be 1
|
||||||
|
* if bit 32+X in the MSR is set to 1; if bit 32+X in the MSR is cleared to 0, VM entry fails if control X is 1.
|
||||||
|
*/
|
||||||
|
static struct vmx_capability vmx_caps[] = {
|
||||||
|
{
|
||||||
|
MSR_IA32_VMX_PINBASED_CTLS, VMX_PINBASED_CTLS_IRQ_EXIT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MSR_IA32_VMX_PROCBASED_CTLS, VMX_PROCBASED_CTLS_TSC_OFF | VMX_PROCBASED_CTLS_TPR_SHADOW |
|
||||||
|
VMX_PROCBASED_CTLS_IO_BITMAP | VMX_PROCBASED_CTLS_MSR_BITMAP |
|
||||||
|
VMX_PROCBASED_CTLS_HLT | VMX_PROCBASED_CTLS_SECONDARY
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MSR_IA32_VMX_PROCBASED_CTLS2, VMX_PROCBASED_CTLS2_VAPIC | VMX_PROCBASED_CTLS2_EPT |
|
||||||
|
VMX_PROCBASED_CTLS2_VPID | VMX_PROCBASED_CTLS2_RDTSCP |
|
||||||
|
VMX_PROCBASED_CTLS2_UNRESTRICT | VMX_PROCBASED_CTLS2_XSVE_XRSTR |
|
||||||
|
VMX_PROCBASED_CTLS2_PAUSE_LOOP
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MSR_IA32_VMX_EXIT_CTLS, VMX_EXIT_CTLS_ACK_IRQ | VMX_EXIT_CTLS_SAVE_PAT |
|
||||||
|
VMX_EXIT_CTLS_LOAD_PAT | VMX_EXIT_CTLS_HOST_ADDR64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MSR_IA32_VMX_ENTRY_CTLS, VMX_ENTRY_CTLS_LOAD_PAT | VMX_ENTRY_CTLS_IA32E_MODE
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool pcpu_has_cap(uint32_t bit)
|
bool pcpu_has_cap(uint32_t bit)
|
||||||
{
|
{
|
||||||
uint32_t feat_idx = bit >> 5U;
|
uint32_t feat_idx = bit >> 5U;
|
||||||
@ -457,6 +493,49 @@ static int32_t check_vmx_mmu_cap(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_vmx_cap_supported(uint32_t msr, uint32_t bits)
|
||||||
|
{
|
||||||
|
uint64_t vmx_msr;
|
||||||
|
uint32_t vmx_msr_low, vmx_msr_high;
|
||||||
|
|
||||||
|
vmx_msr = msr_read(msr);
|
||||||
|
vmx_msr_low = (uint32_t)vmx_msr;
|
||||||
|
vmx_msr_high = (uint32_t)(vmx_msr >> 32U);
|
||||||
|
/* Bits 31:0 indicate the allowed 0-settings
|
||||||
|
* Bits 63:32 indicate the allowed 1-settings
|
||||||
|
*/
|
||||||
|
return (((vmx_msr_high & bits) == bits) && ((vmx_msr_low & bits) == 0U));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t check_essential_vmx_caps(void)
|
||||||
|
{
|
||||||
|
int32_t ret = 0;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if (check_vmx_mmu_cap() != 0) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
} else if (!pcpu_has_vmx_unrestricted_guest_cap()) {
|
||||||
|
printf("%s, unrestricted guest not supported\n", __func__);
|
||||||
|
ret = -ENODEV;
|
||||||
|
} else if (pcpu_vmx_set_32bit_addr_width()) {
|
||||||
|
printf("%s, Only support Intel 64 architecture.\n", __func__);
|
||||||
|
ret = -ENODEV;
|
||||||
|
} else if (!is_valid_xsave_combination()) {
|
||||||
|
printf("%s, check XSAVE combined Capability failed\n", __func__);
|
||||||
|
ret = -ENODEV;
|
||||||
|
} else {
|
||||||
|
for (i = 0U; i < ARRAY_SIZE(vmx_caps); i++) {
|
||||||
|
if (!is_vmx_cap_supported(vmx_caps[i].msr, vmx_caps[i].bits)) {
|
||||||
|
printf("%s, check MSR[0x%x]:0x%lx bits:0x%x failed\n", __func__,
|
||||||
|
vmx_caps[i].msr, msr_read(vmx_caps[i].msr), vmx_caps[i].bits);
|
||||||
|
ret = -ENODEV;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* basic hardware capability check
|
* basic hardware capability check
|
||||||
@ -515,9 +594,6 @@ int32_t detect_hardware_support(void)
|
|||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
} else if (!is_fast_string_erms_supported_and_enabled()) {
|
} else if (!is_fast_string_erms_supported_and_enabled()) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
} else if (!pcpu_has_vmx_unrestricted_guest_cap()) {
|
|
||||||
printf("%s, unrestricted guest not supported\n", __func__);
|
|
||||||
ret = -ENODEV;
|
|
||||||
} else if (!is_ept_supported()) {
|
} else if (!is_ept_supported()) {
|
||||||
printf("%s, EPT not supported\n", __func__);
|
printf("%s, EPT not supported\n", __func__);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
@ -530,9 +606,6 @@ int32_t detect_hardware_support(void)
|
|||||||
} else if (is_vmx_disabled()) {
|
} else if (is_vmx_disabled()) {
|
||||||
printf("%s, VMX can not be enabled\n", __func__);
|
printf("%s, VMX can not be enabled\n", __func__);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
} else if (pcpu_vmx_set_32bit_addr_width()) {
|
|
||||||
printf("%s, Only support Intel 64 architecture.\n", __func__);
|
|
||||||
ret = -ENODEV;
|
|
||||||
} else if (!pcpu_has_cap(X86_FEATURE_X2APIC)) {
|
} else if (!pcpu_has_cap(X86_FEATURE_X2APIC)) {
|
||||||
printf("%s, x2APIC not supported\n", __func__);
|
printf("%s, x2APIC not supported\n", __func__);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
@ -545,11 +618,8 @@ int32_t detect_hardware_support(void)
|
|||||||
} else if (!pcpu_has_cap(X86_FEATURE_RDRAND)) {
|
} else if (!pcpu_has_cap(X86_FEATURE_RDRAND)) {
|
||||||
printf("%s, RDRAND is not supported\n", __func__);
|
printf("%s, RDRAND is not supported\n", __func__);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
} else if (!is_valid_xsave_combination()) {
|
|
||||||
printf("%s, check XSAVE combined Capability failed\n", __func__);
|
|
||||||
ret = -ENODEV;
|
|
||||||
} else {
|
} else {
|
||||||
ret = check_vmx_mmu_cap();
|
ret = check_essential_vmx_caps();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user