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

[Xen-changelog] [xen master] x86: handle paged gfn in wrmsr_hypervisor_regs



commit 013e34f5a61725012467f17650597d351fc0ca99
Author:     Olaf Hering <olaf@xxxxxxxxx>
AuthorDate: Tue May 7 16:41:24 2013 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue May 7 16:41:24 2013 +0200

    x86: handle paged gfn in wrmsr_hypervisor_regs
    
    If xenpaging is started very early for a guest the gfn for the hypercall
    page may be paged-out already. This leads to a guest crash:
    
    ...
    (XEN) HVM10: Allocated Xen hypercall page at 169ff000
    (XEN) traps.c:654:d10 Bad GMFN 169ff (MFN 3e900000000) to MSR 40000000
    (XEN) HVM10: Detected Xen v4.3
    (XEN) io.c:201:d10 MMIO emulation failed @ 0008:c2c2c2c2: 18 7c 55 6d 03 83 
ff ff 10 7c
    (XEN) hvm.c:1253:d10 Triple fault on VCPU0 - invoking HVM shutdown action 1.
    (XEN) HVM11: HVM Loader
    ...
    
    Update return codes of wrmsr_hypervisor_regs, update callers to deal
    with the new return codes:
     0: not handled
     1: handled
     -EAGAIN: retry
    
    Currently wrmsr_hypervisor_regs will not return the following error, it
    will be added in a separate patch:
     -EINVAL: error during handling
    
    Also update the gdprintk to handle a page value of NULL to avoid
    printing a bogus MFN value. Update also computing of MSR value in
    gdprintk, the idx was always zero.
    
    Signed-off-by: Olaf Hering <olaf@xxxxxxxxx>
    Acked-by: Keir Fraser <keir@xxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c |   16 +++++++++++++---
 xen/arch/x86/hvm/vmx/vmx.c |   11 ++++++++++-
 xen/arch/x86/traps.c       |   14 +++++++++++---
 3 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index bc1fe62..cdc176d 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1569,7 +1569,7 @@ static int svm_msr_read_intercept(unsigned int msr, 
uint64_t *msr_content)
 
 static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
 {
-    int ret;
+    int ret, result = X86EMUL_OKAY;
     struct vcpu *v = current;
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     int sync = 0;
@@ -1682,14 +1682,24 @@ static int svm_msr_write_intercept(unsigned int msr, 
uint64_t msr_content)
         if ( wrmsr_viridian_regs(msr, msr_content) )
             break;
 
-        wrmsr_hypervisor_regs(msr, msr_content);
+        switch ( wrmsr_hypervisor_regs(msr, msr_content) )
+        {
+        case -EAGAIN:
+            result = X86EMUL_RETRY;
+            break;
+        case 0:
+        case 1:
+            break;
+        default:
+            goto gpf;
+        }
         break;
     }
 
     if ( sync )
         svm_vmload(vmcb);
 
-    return X86EMUL_OKAY;
+    return result;
 
  gpf:
     hvm_inject_hw_exception(TRAP_gp_fault, 0);
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 51187a9..d0de44a 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2088,7 +2088,16 @@ static int vmx_msr_write_intercept(unsigned int msr, 
uint64_t msr_content)
             case HNDL_unhandled:
                 if ( (vmx_write_guest_msr(msr, msr_content) != 0) &&
                      !is_last_branch_msr(msr) )
-                    wrmsr_hypervisor_regs(msr, msr_content);
+                    switch ( wrmsr_hypervisor_regs(msr, msr_content) )
+                    {
+                    case -EAGAIN:
+                        return X86EMUL_RETRY;
+                    case 0:
+                    case 1:
+                        break;
+                    default:
+                        goto gp_fault;
+                    }
                 break;
             case HNDL_exception_raised:
                 return X86EMUL_EXCEPTION;
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index fbbe31d..f630f83 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -634,6 +634,7 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val)
         unsigned long gmfn = val >> 12;
         unsigned int idx  = val & 0xfff;
         struct page_info *page;
+        p2m_type_t t;
 
         if ( idx > 0 )
         {
@@ -643,15 +644,22 @@ int wrmsr_hypervisor_regs(uint32_t idx, uint64_t val)
             return 0;
         }
 
-        page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
+        page = get_page_from_gfn(d, gmfn, &t, P2M_ALLOC);
 
         if ( !page || !get_page_type(page, PGT_writable_page) )
         {
             if ( page )
                 put_page(page);
+
+            if ( p2m_is_paging(t) )
+            {
+                p2m_mem_paging_populate(d, gmfn);
+                return -EAGAIN;
+            }
+
             gdprintk(XENLOG_WARNING,
                      "Bad GMFN %lx (MFN %lx) to MSR %08x\n",
-                     gmfn, page_to_mfn(page), base + idx);
+                     gmfn, page ? page_to_mfn(page) : -1UL, base);
             return 0;
         }
 
@@ -2490,7 +2498,7 @@ static int emulate_privileged_op(struct cpu_user_regs 
*regs)
                 goto fail;
             break;
         default:
-            if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) )
+            if ( wrmsr_hypervisor_regs(regs->ecx, msr_content) == 1 )
                 break;
 
             rc = vmce_wrmsr(regs->ecx, msr_content);
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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