On Tue, 2018-02-20 at 21:24 -0500, Krish Sadhukhan wrote: > According to Intel SDM 26.2.1.1, the following rules should be enforced > on vmentry: > > * If the "NMI exiting" VM-execution control is 0, "Virtual NMIs" > VM-execution control must be 0. > * If the “virtual NMIs” VM-execution control is 0, the “NMI-window > exiting” VM-execution control must be 0. > > This patch enforces these rules when entering an L2 guest. > > Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> > Reviewed-by: Liran Alon <liran.alon@xxxxxxxxxx> > Reviewed-by: Reviewed-by: Jim Mattson <jmattson@xxxxxxxxxx> s/^Reviewed-by: Reviewed-by:/Reviewed-by:/ > --- > arch/x86/kvm/vmx.c | 29 +++++++++++++++++++++++++++-- > 1 file changed, 27 insertions(+), 2 deletions(-) > > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c > index 8eba631..24b88db 100644 > --- a/arch/x86/kvm/vmx.c > +++ b/arch/x86/kvm/vmx.c > @@ -1366,6 +1366,16 @@ static inline bool nested_cpu_has_preemption_timer(struct vmcs12 *vmcs12) > PIN_BASED_VMX_PREEMPTION_TIMER; > } > > +static inline bool nested_cpu_has_nmi_exiting(struct vmcs12 *vmcs12) > +{ > + return vmcs12->pin_based_vm_exec_control & PIN_BASED_NMI_EXITING; > +} > + > +static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12) > +{ > + return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS; > +} > + > static inline int nested_cpu_has_ept(struct vmcs12 *vmcs12) > { > return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT); > @@ -5667,8 +5677,7 @@ static bool nested_exit_intr_ack_set(struct kvm_vcpu *vcpu) > > static bool nested_exit_on_nmi(struct kvm_vcpu *vcpu) > { > - return get_vmcs12(vcpu)->pin_based_vm_exec_control & > - PIN_BASED_NMI_EXITING; > + return nested_cpu_has_nmi_exiting(get_vmcs12(vcpu)); > } > > static void enable_irq_window(struct kvm_vcpu *vcpu) > @@ -10752,6 +10761,19 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, > return 0; > } > > +static int nested_vmx_check_nmi_controls(struct vmcs12 *vmcs12) > +{ > + if (!nested_cpu_has_nmi_exiting(vmcs12) && > + nested_cpu_has_virtual_nmis(vmcs12)) > + return -EINVAL; > + > + if (!nested_cpu_has_virtual_nmis(vmcs12) && > + nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_NMI_PENDING)) > + return -EINVAL; > + > + return 0; > +} > + > static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) > { > struct vcpu_vmx *vmx = to_vmx(vcpu); > @@ -10796,6 +10818,9 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) > vmx->nested.nested_vmx_entry_ctls_high)) > return VMXERR_ENTRY_INVALID_CONTROL_FIELD; > > + if (nested_vmx_check_nmi_controls(vmcs12)) > + return VMXERR_ENTRY_INVALID_CONTROL_FIELD; > + > if (nested_cpu_has_vmfunc(vmcs12)) { > if (vmcs12->vm_function_control & > ~vmx->nested.nested_vmx_vmfunc_controls) On a related note, which VMentry checks do we decide to do in software and which ones we defer to hardware? The spec has like a dizillion checks that are enfored by hardware on VMEntry, which ones do we decide that it makes sense to validate in software before-hand? Regards. Amazon Development Center Germany GmbH Berlin - Dresden - Aachen main office: Krausenstr. 38, 10117 Berlin Geschaeftsfuehrer: Dr. Ralf Herbrich, Christian Schlaeger Ust-ID: DE289237879 Eingetragen am Amtsgericht Charlottenburg HRB 149173 B