Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4432

kernel-2.6.18-194.11.1.el5.src.rpm

From: Chris Lalancette <clalance@redhat.com>
Date: Thu, 5 Mar 2009 14:16:05 +0100
Subject: [xen] fix 32-on-64 PV oops in xen_set_pud
Message-id: 49AFD095.5080307@redhat.com
O-Subject: [RHEL5.4 PATCH]: fix 32-on-64 PV oops in xen_set_pud
Bugzilla: 467698
RH-Acked-by: Justin M. Forbes <jforbes@redhat.com>

All,
     With the current 5.3 Xen hypervisor, trying to start certain 32-bit guests
(Fedora 10 is one example) will end up crashing the guest during boot.  The
problem stems from the order in which we are modifying the PTE entries for a
guest.  In the case of a PTE modification that we care about (changing the RW or
PRESENT bits), then we must first "get" the page before we modify the PTE.
     The following patch is a backport of upstream xen-3.1-testing.hg c/s 15653,
and has had good results in the virttest kernels.  This should resolve BZ
467698.  Please review and ACK.

--
Chris Lalancette

diff --git a/arch/x86/mm.c b/arch/x86/mm.c
index 1d49d4a..452c829 100644
--- a/arch/x86/mm.c
+++ b/arch/x86/mm.c
@@ -1380,16 +1380,18 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
             return 0;
         }
 
-        adjust_guest_l1e(nl1e, d);
-
         /* Fast path for identical mapping, r/w and presence. */
         if ( !l1e_has_changed(ol1e, nl1e, _PAGE_RW | _PAGE_PRESENT) )
+	{
+            adjust_guest_l1e(nl1e, d);
             return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, current,
                                 preserve_ad);
+	}
 
         if ( unlikely(!get_page_from_l1e(nl1e, FOREIGNDOM)) )
             return 0;
-        
+
+        adjust_guest_l1e(nl1e, d);
         if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, current,
                                     preserve_ad)) )
         {
@@ -1437,16 +1439,18 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
             return 0;
         }
 
-        adjust_guest_l2e(nl2e, d);
-
         /* Fast path for identical mapping and presence. */
         if ( !l2e_has_changed(ol2e, nl2e, _PAGE_PRESENT))
-            return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, current,
-                                preserve_ad);
+        {
+            adjust_guest_l2e(nl2e, d);
+            return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, current, preserve_ad);
+        }
 
         if ( unlikely(!get_page_from_l2e(nl2e, pfn, d)) )
             return 0;
 
+        adjust_guest_l2e(nl2e, d);
+
         if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, current,
                                     preserve_ad)) )
         {
@@ -1503,16 +1507,18 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
             return 0;
         }
 
-        adjust_guest_l3e(nl3e, d);
-
         /* Fast path for identical mapping and presence. */
         if (!l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT))
-            return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, current,
-                                preserve_ad);
+        {
+            adjust_guest_l3e(nl3e, d);
+            return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, current, preserve_ad);
+        }
 
         if ( unlikely(!get_page_from_l3e(nl3e, pfn, d)) )
             return 0;
 
+        adjust_guest_l3e(nl3e, d);
+
         if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, current,
                                     preserve_ad)) )
         {
@@ -1566,16 +1572,18 @@ static int mod_l4_entry(struct domain *d,
             return 0;
         }
 
-        adjust_guest_l4e(nl4e, current->domain);
-
         /* Fast path for identical mapping and presence. */
         if (!l4e_has_changed(ol4e, nl4e, _PAGE_PRESENT))
-            return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, current,
-                                preserve_ad);
+        {
+            adjust_guest_l4e(nl4e, current->domain);
+            return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, current, preserve_ad);
+        }
 
         if ( unlikely(!get_page_from_l4e(nl4e, pfn, current->domain)) )
             return 0;
 
+        adjust_guest_l4e(nl4e, current->domain);
+
         if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, current,
                                     preserve_ad)) )
         {