Checks the hvm EFER.SVME bit to make sure the EFER.SVME bit it high
before allowing nested SVM intercepts to be handled successfully.  On
SVME being low, it generates a #UD as per the AMD APM vol2 15.4.

Reported-by: Andrew Cooper <andrew.coop...@citrix.com>
Signed-off-by: Brian Woods <brian.wo...@amd.com>
---
 xen/arch/x86/hvm/svm/svm.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 2e62b9bb6d..2d0a82ae77 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -2587,6 +2587,35 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
                                      eventinj.fields.vector) )
         vmcb->eventinj = eventinj;
 
+    /*
+     * Making sure SVME is enabled see AMD APM vol2 section 15.4
+     * Nested Xen needs VMMCALL to boot.  It hasn't set SVME by the time
+     * it uses it, therefore it isn't checked
+     */
+    switch ( exit_reason )
+    {
+    case VMEXIT_VMRUN:
+    case VMEXIT_VMLOAD:
+    case VMEXIT_VMSAVE:
+    case VMEXIT_CLGI:
+    case VMEXIT_INVLPGA:
+        if ( !(nestedhvm_enabled(v->domain) &&
+             nsvm_efer_svm_enabled(v)) )
+        {
+            gdprintk(XENLOG_ERR, "nestedhvm nested/SVME disabled, injecting 
#UD\n");
+            hvm_inject_hw_exception(TRAP_invalid_op, X86_EVENT_NO_EC);
+           goto out;
+        }
+    case VMEXIT_STGI:
+    case VMEXIT_SKINIT:
+        if ( !nestedhvm_enabled(v->domain) )
+        {
+            gdprintk(XENLOG_ERR, "nestedhvm nested disabled, injecting #UD\n");
+            hvm_inject_hw_exception(TRAP_invalid_op, X86_EVENT_NO_EC);
+           goto out;
+        }
+    }
+
     switch ( exit_reason )
     {
     case VMEXIT_INTR:
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Reply via email to