[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/1 V3] x86/AMD: Fix nested svm crash due to assertion in __virt_to_maddr



From: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>

Fix assertion in __virt_to_maddr when starting nested SVM guest
in debug mode. Investigation has shown that svm_vmsave/svm_vmload
make use of __pa() with invalid address.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
---
Changes in V3:
        - Map L1-GPA to MPA before calling svm_vmload/svm_vmsave

Changes in V2:
        - Uses paddr_t instead of uint64_t (suggested by Tim).
        - Rename the nestedsvm_vmxxxx() to svm_vmxxxx_by_paddr() (suggested by 
Tim).
        - Wrapped svm_vmxxxx_by_paddr() with svm_vmxxxx() (suggested by Jan).
 xen/arch/x86/hvm/svm/svm.c          |   27 +++++++++++++++++++++++++--
 xen/arch/x86/mm/hap/nested_hap.c    |   13 +++++++++++++
 xen/include/asm-x86/hvm/nestedhvm.h |    3 +++
 xen/include/asm-x86/hvm/svm/svm.h   |   11 +++++++----
 4 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 4a7aeee..efc821e 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1798,6 +1798,7 @@ svm_vmexit_do_vmload(struct vmcb_struct *vmcb,
                      struct vcpu *v, uint64_t vmcbaddr)
 {
     int ret;
+    paddr_t mpa;
     unsigned int inst_len;
     struct nestedvcpu *nv = &vcpu_nestedhvm(v);
 
@@ -1816,7 +1817,18 @@ svm_vmexit_do_vmload(struct vmcb_struct *vmcb,
         goto inject;
     }
 
-    svm_vmload(nv->nv_vvmcx);
+    /* Need to translate L1-GPA to MPA */
+    if ( NESTEDHVM_PAGEFAULT_DONE != nestedhvm_walk_L0_p2m(
+                                        v, nv->nv_vvmcxaddr, &mpa) )
+    {
+        gdprintk(XENLOG_ERR,
+            "VMLOAD: mapping vmcb L1-GPA to MPA failed, injecting #UD\n");
+        ret = TRAP_invalid_op;
+        goto inject;
+    }
+
+    svm_vmload_pa(mpa);
+
     /* State in L1 VMCB is stale now */
     v->arch.hvm_svm.vmcb_in_sync = 0;
 
@@ -1834,6 +1846,7 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
                      struct vcpu *v, uint64_t vmcbaddr)
 {
     int ret;
+    paddr_t mpa;
     unsigned int inst_len;
     struct nestedvcpu *nv = &vcpu_nestedhvm(v);
 
@@ -1852,7 +1865,17 @@ svm_vmexit_do_vmsave(struct vmcb_struct *vmcb,
         goto inject;
     }
 
-    svm_vmsave(nv->nv_vvmcx);
+    /* Need to translate L1-GPA to MPA */
+    if ( NESTEDHVM_PAGEFAULT_DONE != nestedhvm_walk_L0_p2m(
+                                        v, nv->nv_vvmcxaddr, &mpa) )
+    {
+        gdprintk(XENLOG_ERR,
+            "VMSAVE: mapping vmcb L1-GPA to MPA failed, injecting #UD\n");
+        ret = TRAP_invalid_op;
+        goto inject;
+    }
+
+    svm_vmsave_pa(mpa);
 
     __update_guest_eip(regs, inst_len);
     return;
diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c
index c2ef1d1..af557d5 100644
--- a/xen/arch/x86/mm/hap/nested_hap.c
+++ b/xen/arch/x86/mm/hap/nested_hap.c
@@ -191,6 +191,19 @@ out:
     return rc;
 }
 
+int
+nestedhvm_walk_L0_p2m(struct vcpu *v, paddr_t L1_gpa, paddr_t *L0_gpa)
+{
+    p2m_type_t p2mt_10;
+    unsigned int page_order_10;
+    p2m_access_t p2ma_10 = p2m_access_rwx;
+
+    return nestedhap_walk_L0_p2m ( p2m_get_hostp2m(v->domain),
+                                 L1_gpa, L0_gpa,
+                                 &p2mt_10, &p2ma_10, &page_order_10,
+                                 0, 0, 0);
+}
+
 /*
  * The following function, nestedhap_page_fault(), is for steps (3)--(10).
  *
diff --git a/xen/include/asm-x86/hvm/nestedhvm.h 
b/xen/include/asm-x86/hvm/nestedhvm.h
index 649c511..228b6eb 100644
--- a/xen/include/asm-x86/hvm/nestedhvm.h
+++ b/xen/include/asm-x86/hvm/nestedhvm.h
@@ -56,6 +56,9 @@ bool_t nestedhvm_vcpu_in_guestmode(struct vcpu *v);
 int nestedhvm_hap_nested_page_fault(struct vcpu *v, paddr_t *L2_gpa,
     bool_t access_r, bool_t access_w, bool_t access_x);
 
+int nestedhvm_walk_L0_p2m(struct vcpu *v,
+    paddr_t L1_gpa, paddr_t *L0_gpa);
+
 /* IO permission map */
 unsigned long *nestedhvm_vcpu_iomap_get(bool_t ioport_80, bool_t ioport_ed);
 
diff --git a/xen/include/asm-x86/hvm/svm/svm.h 
b/xen/include/asm-x86/hvm/svm/svm.h
index 64e7e25..1ffe6d6 100644
--- a/xen/include/asm-x86/hvm/svm/svm.h
+++ b/xen/include/asm-x86/hvm/svm/svm.h
@@ -41,18 +41,21 @@
 #define SVM_REG_R14 (14)
 #define SVM_REG_R15 (15)
 
-static inline void svm_vmload(void *vmcb)
+#define svm_vmload(x)     svm_vmload_pa(__pa(x))
+#define svm_vmsave(x)     svm_vmsave_pa(__pa(x))
+
+static inline void svm_vmload_pa(paddr_t vmcb)
 {
     asm volatile (
         ".byte 0x0f,0x01,0xda" /* vmload */
-        : : "a" (__pa(vmcb)) : "memory" );
+        : : "a" (vmcb) : "memory" );
 }
 
-static inline void svm_vmsave(void *vmcb)
+static inline void svm_vmsave_pa(paddr_t vmcb)
 {
     asm volatile (
         ".byte 0x0f,0x01,0xdb" /* vmsave */
-        : : "a" (__pa(vmcb)) : "memory" );
+        : : "a" (vmcb) : "memory" );
 }
 
 static inline void svm_invlpga(unsigned long vaddr, uint32_t asid)
-- 
1.7.10.4



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.