File 22999-x86-mod_l1_entry-retcode.patch of Package xen

References: bnc#675363

# HG changeset patch
# User Jan Beulich <jbeulich@novell.com>
# Date 1299687409 0
# Node ID 82b5f8d12903e140f957ae8d13d66e44be076b05
# Parent  e9fab50d7b61d151d51a4b1088930c9e1ca2da47
x86: make mod_l1_entry() return a proper error code

... again is so that the guest can actually know the reason for the
(hypercall) failure.

Signed-off-by: Jan Beulich <jbeulich@novell.com>

--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -1745,15 +1745,16 @@ static int mod_l1_entry(l1_pgentry_t *pl
     struct domain *pt_dom = pt_vcpu->domain;
     unsigned long mfn;
     p2m_type_t p2mt;
-    int rc = 1;
+    int rc = 0;
 
     if ( unlikely(__copy_from_user(&ol1e, pl1e, sizeof(ol1e)) != 0) )
-        return 0;
+        return -EFAULT;
 
     if ( unlikely(paging_mode_refcounts(pt_dom)) )
     {
-        rc = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu, preserve_ad);
-        return rc;
+        if ( UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu, preserve_ad) )
+            return 0;
+        return -EBUSY;
     }
 
     if ( l1e_get_flags(nl1e) & _PAGE_PRESENT )
@@ -1761,7 +1762,7 @@ static int mod_l1_entry(l1_pgentry_t *pl
         /* Translate foreign guest addresses. */
         mfn = mfn_x(gfn_to_mfn(pg_dom, l1e_get_pfn(nl1e), &p2mt));
         if ( !p2m_is_ram(p2mt) || unlikely(mfn == INVALID_MFN) )
-            return 0;
+            return -EINVAL;
         ASSERT((mfn & ~(PADDR_MASK >> PAGE_SHIFT)) == 0);
         nl1e = l1e_from_pfn(mfn, l1e_get_flags(nl1e));
 
@@ -1769,33 +1770,34 @@ static int mod_l1_entry(l1_pgentry_t *pl
         {
             MEM_LOG("Bad L1 flags %x",
                     l1e_get_flags(nl1e) & l1_disallow_mask(pt_dom));
-            return 0;
+            return -EINVAL;
         }
 
         /* Fast path for identical mapping, r/w and presence. */
         if ( !l1e_has_changed(ol1e, nl1e, _PAGE_RW | _PAGE_PRESENT) )
         {
             adjust_guest_l1e(nl1e, pt_dom);
-            rc = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu,
-                              preserve_ad);
-            return rc;
+            if ( UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu,
+                              preserve_ad) )
+                return 0;
+            return -EBUSY;
         }
 
-        if ( unlikely(get_page_from_l1e(nl1e, pt_dom, pg_dom) < 0) )
-            return 0;
+        if ( unlikely((rc = get_page_from_l1e(nl1e, pt_dom, pg_dom)) < 0) )
+            return rc;
         
         adjust_guest_l1e(nl1e, pt_dom);
         if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu,
                                     preserve_ad)) )
         {
             ol1e = nl1e;
-            rc = 0;
+            rc = -EBUSY;
         }
     }
     else if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu,
                                      preserve_ad)) )
     {
-        return 0;
+        return -EBUSY;
     }
 
     put_page_from_l1e(ol1e, pt_dom);
@@ -3225,9 +3227,10 @@ int do_mmu_update(
                     } 
 #endif
 
-                    okay = mod_l1_entry(va, l1e, mfn,
-                                        cmd == MMU_PT_UPDATE_PRESERVE_AD, v,
-                                        pg_owner);
+                    rc = mod_l1_entry(va, l1e, mfn,
+                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, v,
+                                      pg_owner);
+                    okay = !rc;
                 }
                 break;
                 case PGT_l2_page_table:
@@ -4026,7 +4029,7 @@ static int __do_update_va_mapping(
         goto out;
     }
 
-    rc = mod_l1_entry(pl1e, val, gl1mfn, 0, v, pg_owner) ? 0 : -EINVAL;
+    rc = mod_l1_entry(pl1e, val, gl1mfn, 0, v, pg_owner);
 
     page_unlock(gl1pg);
     put_page(gl1pg);
openSUSE Build Service is sponsored by