Skip to content

Commit

Permalink
x86/kvm/hyper-v: don't allow to turn on unsupported VMX controls for …
Browse files Browse the repository at this point in the history
…nested guests

Sane L1 hypervisors are not supposed to turn any of the unsupported VMX
controls on for its guests and nested_vmx_check_controls() checks for
that. This is, however, not the case for the controls which are supported
on the host but are missing in enlightened VMCS and when eVMCS is in use.

It would certainly be possible to add these missing checks to
nested_check_vm_execution_controls()/_vm_exit_controls()/.. but it seems
preferable to keep eVMCS-specific stuff in eVMCS and reduce the impact on
non-eVMCS guests by doing less unrelated checks. Create a separate
nested_evmcs_check_controls() for this purpose.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
  • Loading branch information
vittyvk authored and bonzini committed Feb 5, 2020
1 parent 31de3d2 commit a835023
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
53 changes: 53 additions & 0 deletions arch/x86/kvm/vmx/evmcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "evmcs.h"
#include "vmcs.h"
#include "vmx.h"
#include "trace.h"

DEFINE_STATIC_KEY_FALSE(enable_evmcs);

Expand Down Expand Up @@ -372,6 +373,58 @@ void nested_evmcs_filter_control_msr(u32 msr_index, u64 *pdata)
*pdata = ctl_low | ((u64)ctl_high << 32);
}

int nested_evmcs_check_controls(struct vmcs12 *vmcs12)
{
int ret = 0;
u32 unsupp_ctl;

unsupp_ctl = vmcs12->pin_based_vm_exec_control &
EVMCS1_UNSUPPORTED_PINCTRL;
if (unsupp_ctl) {
trace_kvm_nested_vmenter_failed(
"eVMCS: unsupported pin-based VM-execution controls",
unsupp_ctl);
ret = -EINVAL;
}

unsupp_ctl = vmcs12->secondary_vm_exec_control &
EVMCS1_UNSUPPORTED_2NDEXEC;
if (unsupp_ctl) {
trace_kvm_nested_vmenter_failed(
"eVMCS: unsupported secondary VM-execution controls",
unsupp_ctl);
ret = -EINVAL;
}

unsupp_ctl = vmcs12->vm_exit_controls &
EVMCS1_UNSUPPORTED_VMEXIT_CTRL;
if (unsupp_ctl) {
trace_kvm_nested_vmenter_failed(
"eVMCS: unsupported VM-exit controls",
unsupp_ctl);
ret = -EINVAL;
}

unsupp_ctl = vmcs12->vm_entry_controls &
EVMCS1_UNSUPPORTED_VMENTRY_CTRL;
if (unsupp_ctl) {
trace_kvm_nested_vmenter_failed(
"eVMCS: unsupported VM-entry controls",
unsupp_ctl);
ret = -EINVAL;
}

unsupp_ctl = vmcs12->vm_function_control & EVMCS1_UNSUPPORTED_VMFUNC;
if (unsupp_ctl) {
trace_kvm_nested_vmenter_failed(
"eVMCS: unsupported VM-function controls",
unsupp_ctl);
ret = -EINVAL;
}

return ret;
}

int nested_enable_evmcs(struct kvm_vcpu *vcpu,
uint16_t *vmcs_version)
{
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/kvm/vmx/evmcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "capabilities.h"
#include "vmcs.h"
#include "vmcs12.h"

struct vmcs_config;

Expand Down Expand Up @@ -202,5 +203,6 @@ uint16_t nested_get_evmcs_version(struct kvm_vcpu *vcpu);
int nested_enable_evmcs(struct kvm_vcpu *vcpu,
uint16_t *vmcs_version);
void nested_evmcs_filter_control_msr(u32 msr_index, u64 *pdata);
int nested_evmcs_check_controls(struct vmcs12 *vmcs12);

#endif /* __KVM_X86_VMX_EVMCS_H */
3 changes: 3 additions & 0 deletions arch/x86/kvm/vmx/nested.c
Original file line number Diff line number Diff line change
Expand Up @@ -2757,6 +2757,9 @@ static int nested_vmx_check_controls(struct kvm_vcpu *vcpu,
nested_check_vm_entry_controls(vcpu, vmcs12))
return -EINVAL;

if (to_vmx(vcpu)->nested.enlightened_vmcs_enabled)
return nested_evmcs_check_controls(vmcs12);

return 0;
}

Expand Down

0 comments on commit a835023

Please sign in to comment.