mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
KVM: VMX: Reject kvm_intel if an inconsistent VMCS config is detected
Add an on-by-default module param, error_on_inconsistent_vmcs_config, to allow rejecting the load of kvm_intel if an inconsistent VMCS config is detected. Continuing on with an inconsistent, degraded config is undesirable in the vast majority of use cases, e.g. may result in a misconfigured VM, poor performance due to lack of fast MSR switching, or even security issues in the unlikely event the guest is relying on MPX. Practically speaking, an inconsistent VMCS config should never be encountered in a production quality environment, e.g. on bare metal it indicates a silicon defect (or a disturbing lack of validation by the hardware vendor), and in a virtualized machine (KVM as L1) it indicates a buggy/misconfigured L0 VMM/hypervisor. Provide a module param to override the behavior for testing purposes, or in the unlikely scenario that KVM is deployed on a flawed-but-usable CPU or virtual machine. Note, what is or isn't an inconsistency is somewhat subjective, e.g. one might argue that LOAD_EFER without SAVE_EFER is an inconsistency. KVM's unofficial guideline for an "inconsistency" is either scenarios that are completely nonsensical, e.g. the existing checks on having EPT/VPID knobs without EPT/VPID, and/or scenarios that prevent KVM from virtualizing or utilizing a feature, e.g. the unpaired entry/exit controls checks. Other checks that fall into one or both of the covered scenarios could be added in the future, e.g. asserting that a VMCS control exists available if and only if the associated feature is supported in bare metal. Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20220527170658.3571367-3-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
f5a81d0eb0
commit
3dbec44d9c
@ -119,6 +119,9 @@ module_param(nested, bool, S_IRUGO);
|
|||||||
bool __read_mostly enable_pml = 1;
|
bool __read_mostly enable_pml = 1;
|
||||||
module_param_named(pml, enable_pml, bool, S_IRUGO);
|
module_param_named(pml, enable_pml, bool, S_IRUGO);
|
||||||
|
|
||||||
|
static bool __read_mostly error_on_inconsistent_vmcs_config = true;
|
||||||
|
module_param(error_on_inconsistent_vmcs_config, bool, 0444);
|
||||||
|
|
||||||
static bool __read_mostly dump_invalid_vmcs = 0;
|
static bool __read_mostly dump_invalid_vmcs = 0;
|
||||||
module_param(dump_invalid_vmcs, bool, 0644);
|
module_param(dump_invalid_vmcs, bool, 0644);
|
||||||
|
|
||||||
@ -2547,15 +2550,23 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
|
|||||||
CPU_BASED_CR3_STORE_EXITING |
|
CPU_BASED_CR3_STORE_EXITING |
|
||||||
CPU_BASED_INVLPG_EXITING);
|
CPU_BASED_INVLPG_EXITING);
|
||||||
} else if (vmx_cap->ept) {
|
} else if (vmx_cap->ept) {
|
||||||
vmx_cap->ept = 0;
|
|
||||||
pr_warn_once("EPT CAP should not exist if not support "
|
pr_warn_once("EPT CAP should not exist if not support "
|
||||||
"1-setting enable EPT VM-execution control\n");
|
"1-setting enable EPT VM-execution control\n");
|
||||||
|
|
||||||
|
if (error_on_inconsistent_vmcs_config)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
vmx_cap->ept = 0;
|
||||||
}
|
}
|
||||||
if (!(_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_VPID) &&
|
if (!(_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_VPID) &&
|
||||||
vmx_cap->vpid) {
|
vmx_cap->vpid) {
|
||||||
vmx_cap->vpid = 0;
|
|
||||||
pr_warn_once("VPID CAP should not exist if not support "
|
pr_warn_once("VPID CAP should not exist if not support "
|
||||||
"1-setting enable VPID VM-execution control\n");
|
"1-setting enable VPID VM-execution control\n");
|
||||||
|
|
||||||
|
if (error_on_inconsistent_vmcs_config)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
vmx_cap->vpid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) {
|
if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) {
|
||||||
@ -2613,6 +2624,9 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
|
|||||||
pr_warn_once("Inconsistent VM-Entry/VM-Exit pair, entry = %x, exit = %x\n",
|
pr_warn_once("Inconsistent VM-Entry/VM-Exit pair, entry = %x, exit = %x\n",
|
||||||
_vmentry_control & n_ctrl, _vmexit_control & x_ctrl);
|
_vmentry_control & n_ctrl, _vmexit_control & x_ctrl);
|
||||||
|
|
||||||
|
if (error_on_inconsistent_vmcs_config)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
_vmentry_control &= ~n_ctrl;
|
_vmentry_control &= ~n_ctrl;
|
||||||
_vmexit_control &= ~x_ctrl;
|
_vmexit_control &= ~x_ctrl;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user