WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] shadow: drop guest VRAM write access after some idle

shadow: drop guest VRAM write access after some idleness

If the video RAM has been kept clean for at least 2 seconds, we can
afford taking the time to drop guest write access, which allows us to
save the dirty bit scanning entirely until we get a guest page handle.

diff -r 3bc6ad3beafc -r 98b06d404e6b xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Fri May 02 14:59:35 2008 +0100
+++ b/xen/arch/x86/mm/shadow/common.c   Thu May 08 12:50:34 2008 +0100
@@ -2871,6 +2871,8 @@ int shadow_track_dirty_vram(struct domai
     unsigned long end_pfn = begin_pfn + nr;
     unsigned long dirty_size = (nr + 7) / 8;
     int flush_tlb = 0;
+    unsigned long i;
+    p2m_type_t t;
 
     if (end_pfn < begin_pfn
             || begin_pfn > d->arch.p2m->max_mapped_pfn
@@ -2881,7 +2883,8 @@ int shadow_track_dirty_vram(struct domai
 
     if ( d->dirty_vram && (!nr ||
              ( begin_pfn != d->dirty_vram->begin_pfn
-            || end_pfn   != d->dirty_vram->end_pfn )) ) {
+            || end_pfn   != d->dirty_vram->end_pfn )) )
+    {
         /* Different tracking, tear the previous down. */
         gdprintk(XENLOG_INFO, "stopping tracking VRAM %lx - %lx\n", 
d->dirty_vram->begin_pfn, d->dirty_vram->end_pfn);
         xfree(d->dirty_vram->sl1ma);
@@ -2890,17 +2893,16 @@ int shadow_track_dirty_vram(struct domai
         d->dirty_vram = NULL;
     }
 
-    if ( !nr ) {
+    if ( !nr )
+    {
         rc = 0;
         goto out;
     }
 
     /* This should happen seldomly (Video mode change),
      * no need to be careful. */
-    if ( !d->dirty_vram ) {
-        unsigned long i;
-        p2m_type_t t;
-
+    if ( !d->dirty_vram )
+    {
         /* Just recount from start. */
         for ( i = begin_pfn; i < end_pfn; i++ )
             flush_tlb |= sh_remove_all_mappings(d->vcpu[0], gfn_to_mfn(d, i, 
&t));
@@ -2921,10 +2923,20 @@ int shadow_track_dirty_vram(struct domai
             goto out_sl1ma;
         memset(d->dirty_vram->dirty_bitmap, 0, dirty_size);
 
+        d->dirty_vram->last_dirty = NOW();
+
         /* Tell the caller that this time we could not track dirty bits. */
         rc = -ENODATA;
-    } else {
-        int i;
+    }
+    else if (d->dirty_vram->last_dirty == -1)
+    {
+        /* still completely clean, just copy our empty bitmap */
+        rc = -EFAULT;
+        if ( copy_to_guest(dirty_bitmap, d->dirty_vram->dirty_bitmap, 
dirty_size) == 0 )
+            rc = 0;
+    }
+    else
+    {
 #ifdef __i386__
         unsigned long map_mfn = INVALID_MFN;
         void *map_sl1p = NULL;
@@ -2932,26 +2944,29 @@ int shadow_track_dirty_vram(struct domai
 
         /* Iterate over VRAM to track dirty bits. */
         for ( i = 0; i < nr; i++ ) {
-            p2m_type_t t;
             mfn_t mfn = gfn_to_mfn(d, begin_pfn + i, &t);
             struct page_info *page = mfn_to_page(mfn);
             u32 count_info = page->u.inuse.type_info & PGT_count_mask;
             int dirty = 0;
             paddr_t sl1ma = d->dirty_vram->sl1ma[i];
 
-            switch (count_info) {
+            switch (count_info)
+            {
             case 0:
                 /* No guest reference, nothing to track. */
                 break;
             case 1:
                 /* One guest reference. */
-                if ( sl1ma == INVALID_PADDR ) {
+                if ( sl1ma == INVALID_PADDR )
+                {
                     /* We don't know which sl1e points to this, too bad. */
                     dirty = 1;
                     /* TODO: Heuristics for finding the single mapping of
                      * this gmfn */
                     flush_tlb |= sh_remove_all_mappings(d->vcpu[0], 
gfn_to_mfn(d, begin_pfn + i, &t));
-                } else {
+                }
+                else
+                {
                     /* Hopefully the most common case: only one mapping,
                      * whose dirty bit we can use. */
                     l1_pgentry_t *sl1e;
@@ -2970,7 +2985,8 @@ int shadow_track_dirty_vram(struct domai
                     sl1e = maddr_to_virt(sl1ma);
 #endif
 
-                    if ( l1e_get_flags(*sl1e) & _PAGE_DIRTY ) {
+                    if ( l1e_get_flags(*sl1e) & _PAGE_DIRTY )
+                    {
                         dirty = 1;
                         /* Note: this is atomic, so we may clear a
                          * _PAGE_ACCESSED set by another processor. */
@@ -2987,7 +3003,10 @@ int shadow_track_dirty_vram(struct domai
             }
 
             if ( dirty )
+            {
                 d->dirty_vram->dirty_bitmap[i / 8] |= 1 << (i % 8);
+                d->dirty_vram->last_dirty = NOW();
+            }
         }
 
 #ifdef __i386__
@@ -2998,6 +3017,14 @@ int shadow_track_dirty_vram(struct domai
         rc = -EFAULT;
         if ( copy_to_guest(dirty_bitmap, d->dirty_vram->dirty_bitmap, 
dirty_size) == 0 ) {
             memset(d->dirty_vram->dirty_bitmap, 0, dirty_size);
+            if (d->dirty_vram->last_dirty + SECONDS(2) < NOW())
+            {
+                /* was clean for more than two seconds, try to disable guest
+                 * write access */
+                for ( i = begin_pfn; i < end_pfn; i++ )
+                    flush_tlb |= sh_remove_write_access(d->vcpu[0], 
gfn_to_mfn(d, i, &t), 1, 0);
+                d->dirty_vram->last_dirty = -1;
+            }
             rc = 0;
         }
     }
diff -r 3bc6ad3beafc -r 98b06d404e6b xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Fri May 02 14:59:35 2008 +0100
+++ b/xen/arch/x86/mm/shadow/multi.c    Thu May 08 12:50:34 2008 +0100
@@ -870,6 +870,17 @@ _sh_propagate(struct vcpu *v,
         }
     }
 
+    if ( unlikely((level == 1) && d->dirty_vram
+            && d->dirty_vram->last_dirty == -1
+            && gfn_x(target_gfn) >= d->dirty_vram->begin_pfn
+            && gfn_x(target_gfn) < d->dirty_vram->end_pfn) )
+    {
+        if ( ft & FETCH_TYPE_WRITE )
+            d->dirty_vram->last_dirty = NOW();
+        else
+            sflags &= ~_PAGE_RW;
+    }
+
     /* Read-only memory */
     if ( p2mt == p2m_ram_ro ) 
         sflags &= ~_PAGE_RW;
@@ -1320,8 +1331,10 @@ static inline void shadow_vram_put_l1e(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();
+        }
     }
 }
 
diff -r 3bc6ad3beafc -r 98b06d404e6b xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h  Fri May 02 14:59:35 2008 +0100
+++ b/xen/arch/x86/mm/shadow/private.h  Thu May 08 12:50:34 2008 +0100
@@ -536,6 +536,7 @@ struct sh_dirty_vram {
     unsigned long end_pfn;
     paddr_t *sl1ma;
     uint8_t *dirty_bitmap;
+    s_time_t last_dirty;
 };
 
 /**************************************************************************/

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>