File 19317-vram-tracking-fix.patch of Package xen

# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1237301895 0
# Node ID f54cf790ffc79bc6a80fabe6bb45744b6ac5c7ea
# Parent  f3bdb4a66257ad67e380f4ac4ccd967bd309d4c1
x86 shadow: fix vram tracking

Check for writable mappings in ptes before assuming that the type
count in the page has changed.

Signed-off-by: Gianluca Guida <gianluca.guida@eu.citrix.com>
xen-unstable changeset:   19317:cc9b41a476dc62149d7a385aad70ce6e221e928f
xen-unstable date:        Thu Mar 12 10:55:43 2009 +0000

Index: xen-3.3.1-testing/xen/arch/x86/mm/shadow/multi.c
===================================================================
--- xen-3.3.1-testing.orig/xen/arch/x86/mm/shadow/multi.c
+++ xen-3.3.1-testing/xen/arch/x86/mm/shadow/multi.c
@@ -1320,18 +1320,19 @@ static inline void shadow_vram_get_l1e(s
                                        mfn_t sl1mfn,
                                        struct domain *d)
 { 
-    mfn_t mfn;
+    mfn_t mfn = shadow_l1e_get_mfn(new_sl1e);
+    int flags = shadow_l1e_get_flags(new_sl1e);
     unsigned long gfn;
 
-    if ( !d->dirty_vram ) return;
-
-    mfn = shadow_l1e_get_mfn(new_sl1e);
-
-    if ( !mfn_valid(mfn) ) return; /* m2p for mmio_direct may not exist */
+    if ( !d->dirty_vram         /* tracking disabled? */
+         || !(flags & _PAGE_RW) /* read-only mapping? */
+         || !mfn_valid(mfn) )   /* mfn can be invalid in mmio_direct */
+        return;
 
     gfn = mfn_to_gfn(d, mfn);
 
-    if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) ) {
+    if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) )
+    {
         unsigned long i = gfn - d->dirty_vram->begin_pfn;
         struct page_info *page = mfn_to_page(mfn);
         
@@ -1347,18 +1348,19 @@ static inline void shadow_vram_put_l1e(s
                                        mfn_t sl1mfn,
                                        struct domain *d)
 {
-    mfn_t mfn;
+    mfn_t mfn = shadow_l1e_get_mfn(old_sl1e);
+    int flags = shadow_l1e_get_flags(old_sl1e);
     unsigned long gfn;
 
-    if ( !d->dirty_vram ) return;
-
-    mfn = shadow_l1e_get_mfn(old_sl1e);
-
-    if ( !mfn_valid(mfn) ) return;
+    if ( !d->dirty_vram         /* tracking disabled? */
+         || !(flags & _PAGE_RW) /* read-only mapping? */
+         || !mfn_valid(mfn) )   /* mfn can be invalid in mmio_direct */
+        return;
 
     gfn = mfn_to_gfn(d, mfn);
 
-    if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) ) {
+    if ( (gfn >= d->dirty_vram->begin_pfn) && (gfn < d->dirty_vram->end_pfn) )
+    {
         unsigned long i = gfn - d->dirty_vram->begin_pfn;
         struct page_info *page = mfn_to_page(mfn);
         int dirty = 0;
@@ -1367,28 +1369,37 @@ static inline void shadow_vram_put_l1e(s
 
         if ( (page->u.inuse.type_info & PGT_count_mask) == 1 ) {
             /* Last reference */
-            if ( d->dirty_vram->sl1ma[i] == INVALID_PADDR ) {
+            if ( d->dirty_vram->sl1ma[i] == INVALID_PADDR )
+            {
                 /* We didn't know it was that one, let's say it is dirty */
                 dirty = 1;
-            } else {
+            }
+            else
+            {
                 ASSERT(d->dirty_vram->sl1ma[i] == sl1ma);
                 d->dirty_vram->sl1ma[i] = INVALID_PADDR;
-                if ( shadow_l1e_get_flags(old_sl1e) & _PAGE_DIRTY )
+                if ( flags & _PAGE_DIRTY )
                     dirty = 1;
             }
-        } else {
+        }
+        else
+        {
             /* We had more than one reference, just consider the page dirty. */
             dirty = 1;
             /* Check that it's not the one we recorded. */
-            if ( d->dirty_vram->sl1ma[i] == sl1ma ) {
+            if ( d->dirty_vram->sl1ma[i] == sl1ma )
+            {
                 /* Too bad, we remembered the wrong one... */
                 d->dirty_vram->sl1ma[i] = INVALID_PADDR;
-            } else {
+            }
+            else
+            {
                 /* Ok, our recorded sl1e is still pointing to this page, let's
                  * just hope it will remain. */
             }
         }
-        if ( dirty ) {
+        if ( dirty )
+        {
             d->dirty_vram->dirty_bitmap[i / 8] |= 1 << (i % 8);
             d->dirty_vram->last_dirty = NOW();
         }
openSUSE Build Service is sponsored by