Skip to content

Commit a835023

Browse files
vittyvkbonzini
authored andcommitted
x86/kvm/hyper-v: don't allow to turn on unsupported VMX controls for 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]>
1 parent 31de3d2 commit a835023

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

arch/x86/kvm/vmx/evmcs.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "evmcs.h"
88
#include "vmcs.h"
99
#include "vmx.h"
10+
#include "trace.h"
1011

1112
DEFINE_STATIC_KEY_FALSE(enable_evmcs);
1213

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

376+
int nested_evmcs_check_controls(struct vmcs12 *vmcs12)
377+
{
378+
int ret = 0;
379+
u32 unsupp_ctl;
380+
381+
unsupp_ctl = vmcs12->pin_based_vm_exec_control &
382+
EVMCS1_UNSUPPORTED_PINCTRL;
383+
if (unsupp_ctl) {
384+
trace_kvm_nested_vmenter_failed(
385+
"eVMCS: unsupported pin-based VM-execution controls",
386+
unsupp_ctl);
387+
ret = -EINVAL;
388+
}
389+
390+
unsupp_ctl = vmcs12->secondary_vm_exec_control &
391+
EVMCS1_UNSUPPORTED_2NDEXEC;
392+
if (unsupp_ctl) {
393+
trace_kvm_nested_vmenter_failed(
394+
"eVMCS: unsupported secondary VM-execution controls",
395+
unsupp_ctl);
396+
ret = -EINVAL;
397+
}
398+
399+
unsupp_ctl = vmcs12->vm_exit_controls &
400+
EVMCS1_UNSUPPORTED_VMEXIT_CTRL;
401+
if (unsupp_ctl) {
402+
trace_kvm_nested_vmenter_failed(
403+
"eVMCS: unsupported VM-exit controls",
404+
unsupp_ctl);
405+
ret = -EINVAL;
406+
}
407+
408+
unsupp_ctl = vmcs12->vm_entry_controls &
409+
EVMCS1_UNSUPPORTED_VMENTRY_CTRL;
410+
if (unsupp_ctl) {
411+
trace_kvm_nested_vmenter_failed(
412+
"eVMCS: unsupported VM-entry controls",
413+
unsupp_ctl);
414+
ret = -EINVAL;
415+
}
416+
417+
unsupp_ctl = vmcs12->vm_function_control & EVMCS1_UNSUPPORTED_VMFUNC;
418+
if (unsupp_ctl) {
419+
trace_kvm_nested_vmenter_failed(
420+
"eVMCS: unsupported VM-function controls",
421+
unsupp_ctl);
422+
ret = -EINVAL;
423+
}
424+
425+
return ret;
426+
}
427+
375428
int nested_enable_evmcs(struct kvm_vcpu *vcpu,
376429
uint16_t *vmcs_version)
377430
{

arch/x86/kvm/vmx/evmcs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "capabilities.h"
1212
#include "vmcs.h"
13+
#include "vmcs12.h"
1314

1415
struct vmcs_config;
1516

@@ -202,5 +203,6 @@ uint16_t nested_get_evmcs_version(struct kvm_vcpu *vcpu);
202203
int nested_enable_evmcs(struct kvm_vcpu *vcpu,
203204
uint16_t *vmcs_version);
204205
void nested_evmcs_filter_control_msr(u32 msr_index, u64 *pdata);
206+
int nested_evmcs_check_controls(struct vmcs12 *vmcs12);
205207

206208
#endif /* __KVM_X86_VMX_EVMCS_H */

arch/x86/kvm/vmx/nested.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2757,6 +2757,9 @@ static int nested_vmx_check_controls(struct kvm_vcpu *vcpu,
27572757
nested_check_vm_entry_controls(vcpu, vmcs12))
27582758
return -EINVAL;
27592759

2760+
if (to_vmx(vcpu)->nested.enlightened_vmcs_enabled)
2761+
return nested_evmcs_check_controls(vmcs12);
2762+
27602763
return 0;
27612764
}
27622765

0 commit comments

Comments
 (0)