According to sections "Canonicalization and Consistency Checks" and "Event Injection" in APM vol 2 VMRUN exits with VMEXIT_INVALID error code if either: - Reserved values of TYPE have been specified, or - TYPE = 3 (exception) has been specified with a vector that does not correspond to an exception (this includes vector 2, which is an NMI, not an exception). Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> --- arch/x86/include/asm/svm.h | 4 ++++ arch/x86/kvm/svm/nested.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index 8a1f5382a4ea..261240acc7e9 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -272,9 +272,13 @@ struct __attribute__ ((__packed__)) vmcb { #define SVM_EVTINJ_TYPE_MASK (7 << SVM_EVTINJ_TYPE_SHIFT) #define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT) +#define SVM_EVTINJ_TYPE_RESV1 (1 << SVM_EVTINJ_TYPE_SHIFT) #define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT) #define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT) #define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT) +#define SVM_EVTINJ_TYPE_RESV5 (5 << SVM_EVTINJ_TYPE_SHIFT) +#define SVM_EVTINJ_TYPE_RESV6 (6 << SVM_EVTINJ_TYPE_SHIFT) +#define SVM_EVTINJ_TYPE_RESV7 (7 << SVM_EVTINJ_TYPE_SHIFT) #define SVM_EVTINJ_VALID (1 << 31) #define SVM_EVTINJ_VALID_ERR (1 << 11) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index e90bc436f584..840fbf0582bb 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -202,6 +202,9 @@ static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm) static bool nested_vmcb_check_controls(struct vmcb_control_area *control) { + u32 type, vector; + bool valid; + if ((control->intercept & (1ULL << INTERCEPT_VMRUN)) == 0) return false; @@ -212,6 +215,17 @@ static bool nested_vmcb_check_controls(struct vmcb_control_area *control) !npt_enabled) return false; + valid = control->event_inj & SVM_EVTINJ_VALID; + type = control->event_inj & SVM_EVTINJ_TYPE_MASK; + if (valid && ((type == SVM_EVTINJ_TYPE_RESV1) || + (type >= SVM_EVTINJ_TYPE_RESV5))) + return false; + + vector = control->event_inj & SVM_EVTINJ_VEC_MASK; + if (valid && (type == SVM_EVTINJ_TYPE_EXEPT) && + (vector == NMI_VECTOR || (vector > 31 && vector < 256))) + return false; + return true; } -- 2.18.4