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

[Xen-changelog] [xen-unstable] xen: arm: do not panic when failing to translate a guest address


  • To: xen-changelog@xxxxxxxxxxxxxxxxxxx
  • From: Xen patchbot-unstable <patchbot@xxxxxxx>
  • Date: Mon, 04 Feb 2013 15:44:24 +0000
  • Delivery-date: Mon, 04 Feb 2013 15:44:29 +0000
  • List-id: "Change log for Mercurial \(receive only\)" <xen-changelog.lists.xen.org>

# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxx>
# Date 1359031675 0
# Node ID a26b37fdfd3d4a124338073089fae52624912ce2
# Parent  b6fd9302594bee36e31d20dc14b65fbd2819d2d0
xen: arm: do not panic when failing to translate a guest address

The gva_to_{par,ipa} functions currently panic if the guest address
cannot be translated. Often the input comes from the guest so
panicing the host is a bit harsh!

Change the API of those functions to allow them to return a failure
and plumb it through where it is used.

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Committed-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---


diff -r b6fd9302594b -r a26b37fdfd3d xen/arch/arm/guestcopy.c
--- a/xen/arch/arm/guestcopy.c  Thu Jan 24 12:47:55 2013 +0000
+++ b/xen/arch/arm/guestcopy.c  Thu Jan 24 12:47:55 2013 +0000
@@ -12,10 +12,16 @@ unsigned long raw_copy_to_guest(void *to
 
     while ( len )
     {
-        paddr_t g = gvirt_to_maddr((uint32_t) to);
-        void *p = map_domain_page(g>>PAGE_SHIFT);
+        int rc;
+        paddr_t g;
+        void *p;
         unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
 
+        rc = gvirt_to_maddr((uint32_t) to, &g);
+        if ( rc )
+            return rc;
+
+        p = map_domain_page(g>>PAGE_SHIFT);
         p += offset;
         memcpy(p, from, size);
 
@@ -36,10 +42,16 @@ unsigned long raw_clear_guest(void *to, 
 
     while ( len )
     {
-        paddr_t g = gvirt_to_maddr((uint32_t) to);
-        void *p = map_domain_page(g>>PAGE_SHIFT);
+        int rc;
+        paddr_t g;
+        void *p;
         unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
 
+        rc = gvirt_to_maddr((uint32_t) to, &g);
+        if ( rc )
+            return rc;
+
+        p = map_domain_page(g>>PAGE_SHIFT);
         p += offset;
         memset(p, 0x00, size);
 
@@ -56,10 +68,16 @@ unsigned long raw_copy_from_guest(void *
 {
     while ( len )
     {
-        paddr_t g = gvirt_to_maddr((uint32_t) from & PAGE_MASK);
-        void *p = map_domain_page(g>>PAGE_SHIFT);
+        int rc;
+        paddr_t g;
+        void *p;
         unsigned size = min(len, (unsigned)(PAGE_SIZE - ((unsigned)from & 
(~PAGE_MASK))));
 
+        rc = gvirt_to_maddr((uint32_t) from & PAGE_MASK, &g);
+        if ( rc )
+            return rc;
+
+        p = map_domain_page(g>>PAGE_SHIFT);
         p += ((unsigned long)from & (~PAGE_MASK));
 
         memcpy(to, p, size);
diff -r b6fd9302594b -r a26b37fdfd3d xen/arch/arm/kernel.c
--- a/xen/arch/arm/kernel.c     Thu Jan 24 12:47:55 2013 +0000
+++ b/xen/arch/arm/kernel.c     Thu Jan 24 12:47:55 2013 +0000
@@ -76,12 +76,22 @@ static void kernel_zimage_load(struct ke
            paddr, load_addr, load_addr + len);
     for ( offs = 0; offs < len; )
     {
-        paddr_t s, l, ma = gvirt_to_maddr(load_addr + offs);
-        void *dst = map_domain_page(ma>>PAGE_SHIFT);
+        int rc;
+        paddr_t s, l, ma;
+        void *dst;
 
         s = offs & ~PAGE_MASK;
         l = min(PAGE_SIZE - s, len);
 
+        rc = gvirt_to_maddr(load_addr + offs, &ma);
+        if ( rc )
+        {
+            panic("\nUnable to map translate guest address\n");
+            return;
+        }
+
+        dst = map_domain_page(ma>>PAGE_SHIFT);
+
         copy_from_paddr(dst + s, paddr + offs, l, attr);
 
         unmap_domain_page(dst);
diff -r b6fd9302594b -r a26b37fdfd3d xen/arch/arm/traps.c
--- a/xen/arch/arm/traps.c      Thu Jan 24 12:47:55 2013 +0000
+++ b/xen/arch/arm/traps.c      Thu Jan 24 12:47:55 2013 +0000
@@ -200,32 +200,22 @@ static const char *fsc_level_str(int lev
     }
 }
 
-void panic_PAR(uint64_t par, const char *when)
+void panic_PAR(uint64_t par)
 {
-    if ( par & PAR_F )
-    {
-        const char *msg;
-        int level = -1;
-        int stage = par & PAR_STAGE2 ? 2 : 1;
-        int second_in_first = !!(par & PAR_STAGE21);
+    const char *msg;
+    int level = -1;
+    int stage = par & PAR_STAGE2 ? 2 : 1;
+    int second_in_first = !!(par & PAR_STAGE21);
 
-        msg = decode_fsc( (par&PAR_FSC_MASK) >> PAR_FSC_SHIFT, &level);
+    msg = decode_fsc( (par&PAR_FSC_MASK) >> PAR_FSC_SHIFT, &level);
 
-        printk("PAR: %010"PRIx64": %s stage %d%s%s\n",
-               par, msg,
-               stage,
-               second_in_first ? " during second stage lookup" : "",
-               fsc_level_str(level));
-    }
-    else
-    {
-        printk("PAR: %010"PRIx64": paddr:%010"PRIx64
-               " attr %"PRIx64" sh %"PRIx64" %s\n",
-               par, par & PADDR_MASK, par >> PAR_MAIR_SHIFT,
-               (par & PAR_SH_MASK) >> PAR_SH_SHIFT,
-               (par & PAR_NS) ? "Non-Secure" : "Secure");
-    }
-    panic("Error during %s-to-physical address translation\n", when);
+    printk("PAR: %010"PRIx64": %s stage %d%s%s\n",
+           par, msg,
+           stage,
+           second_in_first ? " during second stage lookup" : "",
+           fsc_level_str(level));
+
+    panic("Error during Hypervisor-to-physical address translation\n");
 }
 
 struct reg_ctxt {
@@ -721,7 +711,7 @@ static void do_trap_data_abort_guest(str
                                      struct hsr_dabt dabt)
 {
     const char *msg;
-    int level = -1;
+    int rc, level = -1;
     mmio_info_t info;
 
     info.dabt = dabt;
@@ -730,7 +720,9 @@ static void do_trap_data_abort_guest(str
     if (dabt.s1ptw)
         goto bad_data_abort;
 
-    info.gpa = gva_to_ipa(info.gva);
+    rc = gva_to_ipa(info.gva, &info.gpa);
+    if ( rc == -EFAULT )
+        goto bad_data_abort;
 
     if (handle_mmio(&info))
     {
@@ -742,6 +734,7 @@ bad_data_abort:
 
     msg = decode_fsc( dabt.dfsc, &level);
 
+    /* XXX inject a suitable fault into the guest */
     printk("Guest data abort: %s%s%s\n"
            "    gva=%"PRIx32"\n",
            msg, dabt.s1ptw ? " S2 during S1" : "",
@@ -761,7 +754,7 @@ bad_data_abort:
     else
         dump_guest_s1_walk(current->domain, info.gva);
     show_execution_state(regs);
-    panic("Unhandled guest data abort\n");
+    domain_crash_synchronous();
 }
 
 asmlinkage void do_trap_hypervisor(struct cpu_user_regs *regs)
diff -r b6fd9302594b -r a26b37fdfd3d xen/include/asm-arm/mm.h
--- a/xen/include/asm-arm/mm.h  Thu Jan 24 12:47:55 2013 +0000
+++ b/xen/include/asm-arm/mm.h  Thu Jan 24 12:47:55 2013 +0000
@@ -192,10 +192,13 @@ static inline void *maddr_to_virt(paddr_
     return (void *)(unsigned long) ma + XENHEAP_VIRT_START;
 }
 
-static inline paddr_t gvirt_to_maddr(uint32_t va)
+static inline int gvirt_to_maddr(uint32_t va, paddr_t *pa)
 {
-    uint64_t par = gva_to_par(va);
-    return (par & PADDR_MASK & PAGE_MASK) | ((unsigned long) va & ~PAGE_MASK);
+    uint64_t par = gva_to_ma_par(va);
+    if ( par & PAR_F )
+        return -EFAULT;
+    *pa = (par & PADDR_MASK & PAGE_MASK) | ((unsigned long) va & ~PAGE_MASK);
+    return 0;
 }
 
 /* Convert between Xen-heap virtual addresses and machine addresses. */
diff -r b6fd9302594b -r a26b37fdfd3d xen/include/asm-arm/page.h
--- a/xen/include/asm-arm/page.h        Thu Jan 24 12:47:55 2013 +0000
+++ b/xen/include/asm-arm/page.h        Thu Jan 24 12:47:55 2013 +0000
@@ -2,6 +2,7 @@
 #define __ARM_PAGE_H__
 
 #include <xen/config.h>
+#include <xen/errno.h>
 #include <public/xen.h>
 #include <asm/processor.h>
 
@@ -366,13 +367,13 @@ static inline uint64_t va_to_par(uint32_
     if ( par & PAR_F )
     {
         dump_hyp_walk(va);
-        panic_PAR(par, "Hypervisor");
+        panic_PAR(par);
     }
     return par;
 }
 
 /* Ask the MMU to translate a Guest VA for us */
-static inline uint64_t __gva_to_par(uint32_t va)
+static inline uint64_t gva_to_ma_par(uint32_t va)
 {
     uint64_t par, tmp;
     tmp = READ_CP64(PAR);
@@ -382,15 +383,7 @@ static inline uint64_t __gva_to_par(uint
     WRITE_CP64(tmp, PAR);
     return par;
 }
-static inline uint64_t gva_to_par(uint32_t va)
-{
-    uint64_t par = __gva_to_par(va);
-    /* It is not OK to call this with an invalid VA */
-    /* XXX harsh for a guest address... */
-    if ( par & PAR_F ) panic_PAR(par, "Guest");
-    return par;
-}
-static inline uint64_t __gva_to_ipa(uint32_t va)
+static inline uint64_t gva_to_ipa_par(uint32_t va)
 {
     uint64_t par, tmp;
     tmp = READ_CP64(PAR);
@@ -400,14 +393,16 @@ static inline uint64_t __gva_to_ipa(uint
     WRITE_CP64(tmp, PAR);
     return par;
 }
-static inline uint64_t gva_to_ipa(uint32_t va)
+
+static inline int gva_to_ipa(uint32_t va, paddr_t *paddr)
 {
-    uint64_t par = __gva_to_ipa(va);
-    /* It is not OK to call this with an invalid VA */
-    /* XXX harsh for a guest address... */
-    if ( par & PAR_F ) panic_PAR(par, "Guest");
-    return (par & PADDR_MASK & PAGE_MASK) | ((unsigned long) va & ~PAGE_MASK);
+    uint64_t par = gva_to_ipa_par(va);
+    if ( par & PAR_F )
+        return -EFAULT;
+    *paddr = (par & PADDR_MASK & PAGE_MASK) | ((unsigned long) va & 
~PAGE_MASK);
+    return 0;
 }
+
 /* Bits in the PAR returned by va_to_par */
 #define PAR_FAULT 0x1
 
diff -r b6fd9302594b -r a26b37fdfd3d xen/include/asm-arm/processor.h
--- a/xen/include/asm-arm/processor.h   Thu Jan 24 12:47:55 2013 +0000
+++ b/xen/include/asm-arm/processor.h   Thu Jan 24 12:47:55 2013 +0000
@@ -231,7 +231,7 @@ union hsr {
 #ifndef __ASSEMBLY__
 extern uint32_t hyp_traps_vector[8];
 
-void panic_PAR(uint64_t par, const char *when);
+void panic_PAR(uint64_t par);
 
 void show_execution_state(struct cpu_user_regs *regs);
 void show_registers(struct cpu_user_regs *regs);

_______________________________________________
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®.