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-changelog

[Xen-changelog] [xen-unstable] [XEN] Shadow mode no longer obtains page

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [XEN] Shadow mode no longer obtains page type references.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 21 Sep 2006 11:20:25 +0000
Delivery-date: Thu, 21 Sep 2006 04:21:04 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 69e52712fbc460c4f417d418b2f47b8bbf8b5810
# Parent  e50872355390c03227064c8bb6c5dfb4e4d6d292
[XEN] Shadow mode no longer obtains page type references.
This allows the shadow destructor hook in free_page_type()
to work properly.

Also, move mark_dirty() back to alloc/free_page_type(). It
doesn't matter that this happens before the type count is
modified -- bitmap is extracted by the tools with the domain
paused, so these non-blocking paths are atomic from p.o.v of
the tools.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/mm.c               |   56 +++++++++++++++++++---------------------
 xen/arch/x86/mm/shadow/common.c |   25 -----------------
 xen/include/asm-x86/mm.h        |   19 +++++++------
 xen/include/asm-x86/shadow.h    |   13 ++-------
 4 files changed, 42 insertions(+), 71 deletions(-)

diff -r e50872355390 -r 69e52712fbc4 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Sep 21 09:37:28 2006 +0100
+++ b/xen/arch/x86/mm.c Thu Sep 21 10:47:05 2006 +0100
@@ -1490,6 +1490,12 @@ static int mod_l4_entry(l4_pgentry_t *pl
 
 int alloc_page_type(struct page_info *page, unsigned long type)
 {
+    struct domain *owner = page_get_owner(page);
+
+    /* A page table is dirtied when its type count becomes non-zero. */
+    if ( likely(owner != NULL) )
+        mark_dirty(owner, page_to_mfn(page));
+
     switch ( type & PGT_type_mask )
     {
     case PGT_l1_page_table:
@@ -1528,9 +1534,11 @@ void free_page_type(struct page_info *pa
          */
         this_cpu(percpu_mm_info).deferred_ops |= DOP_FLUSH_ALL_TLBS;
 
-        if ( unlikely(shadow_mode_enabled(owner)
-                 && !shadow_lock_is_acquired(owner)) )
-        {
+        if ( unlikely(shadow_mode_enabled(owner)) )
+        {
+            /* A page table is dirtied when its type count becomes zero. */
+            mark_dirty(owner, page_to_mfn(page));
+
             if ( shadow_mode_refcounts(owner) )
                 return;
 
@@ -1603,19 +1611,19 @@ void put_page_type(struct page_info *pag
                 nx &= ~PGT_validated;
             }
 
-            /* Record TLB information for flush later. */
-            page->tlbflush_timestamp = tlbflush_current_time();
+            /*
+             * Record TLB information for flush later. We do not stamp page
+             * tables when running in shadow mode:
+             *  1. Pointless, since it's the shadow pt's which must be tracked.
+             *  2. Shadow mode reuses this field for shadowed page tables to
+             *     store flags info -- we don't want to conflict with that.
+             */
+            if ( !shadow_mode_enabled(page_get_owner(page)) ||
+                 ((nx & PGT_type_mask) == PGT_writable_page) )
+                page->tlbflush_timestamp = tlbflush_current_time();
         }
     }
     while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) );
-
-    /*
-     * A page table is dirtied when its type count becomes zero.
-     * We cannot set the dirty flag earlier than this because we must wait
-     * until the type count has been zeroed by the CMPXCHG above.
-     */
-    if ( unlikely((nx & (PGT_validated|PGT_count_mask)) == 0) )
-        mark_dirty(page_get_owner(page), page_to_mfn(page));
 }
 
 
@@ -1648,7 +1656,10 @@ int get_page_type(struct page_info *page
                     page_get_owner(page)->domain_dirty_cpumask;
                 tlbflush_filter(mask, page->tlbflush_timestamp);
 
-                if ( unlikely(!cpus_empty(mask)) )
+                if ( unlikely(!cpus_empty(mask)) &&
+                     /* Shadow mode: track only writable pages. */
+                     (!shadow_mode_enabled(page_get_owner(page)) ||
+                      ((nx & PGT_type_mask) == PGT_writable_page)) )
                 {
                     perfc_incrc(need_flush_tlb_flush);
                     flush_tlb_mask(mask);
@@ -1701,13 +1712,6 @@ int get_page_type(struct page_info *page
 
         /* Noone else is updating simultaneously. */
         __set_bit(_PGT_validated, &page->u.inuse.type_info);
-
-        /*
-         * A page table is dirtied when its type count becomes non-zero. It is
-         * safe to mark dirty here because any PTE modifications in
-         * alloc_page_type() have now happened.
-         */
-        mark_dirty(page_get_owner(page), page_to_mfn(page));
     }
 
     return 1;
@@ -2001,14 +2005,8 @@ int do_mmuext_op(
             {
                 put_page_and_type(page);
                 put_page(page);
-                if ( shadow_mode_enabled(d) )
-                {
-                    shadow_lock(d);
-                    shadow_remove_all_shadows(v, _mfn(mfn));
-                    /* A page is dirtied when its pin status is cleared. */
-                    sh_mark_dirty(d, _mfn(mfn));
-                    shadow_unlock(d);
-                }
+                /* A page is dirtied when its pin status is cleared. */
+                mark_dirty(d, mfn);
             }
             else
             {
diff -r e50872355390 -r 69e52712fbc4 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Thu Sep 21 09:37:28 2006 +0100
+++ b/xen/arch/x86/mm/shadow/common.c   Thu Sep 21 10:47:05 2006 +0100
@@ -232,32 +232,15 @@ void shadow_promote(struct vcpu *v, mfn_
 void shadow_promote(struct vcpu *v, mfn_t gmfn, u32 type)
 {
     struct page_info *page = mfn_to_page(gmfn);
-    unsigned long type_info;
 
     ASSERT(valid_mfn(gmfn));
 
     /* We should never try to promote a gmfn that has writeable mappings */
     ASSERT(shadow_remove_write_access(v, gmfn, 0, 0) == 0);
 
-    // Is the page already shadowed?
+    /* Is the page already shadowed? */
     if ( !test_and_set_bit(_PGC_page_table, &page->count_info) )
-    {
-        // No prior shadow exists...
-
-        // Grab a type-ref.  We don't really care if we are racing with another
-        // vcpu or not, or even what kind of type we get; we just want the type
-        // count to be > 0.
-        //
-        do {
-            type_info = page->u.inuse.type_info &
-                (PGT_type_mask | PGT_pae_xen_l2);
-        } while ( !get_page_type(page, type_info) );
-
-        // Now that the type ref is non-zero, we can safely use the
-        // shadow_flags.
-        //
         page->shadow_flags = 0;
-    }
 
     ASSERT(!test_bit(type >> PGC_SH_type_shift, &page->shadow_flags));
     set_bit(type >> PGC_SH_type_shift, &page->shadow_flags);
@@ -273,13 +256,7 @@ void shadow_demote(struct vcpu *v, mfn_t
     clear_bit(type >> PGC_SH_type_shift, &page->shadow_flags);
 
     if ( (page->shadow_flags & SHF_page_type_mask) == 0 )
-    {
-        // release the extra type ref
-        put_page_type(page);
-
-        // clear the is-a-page-table bit.
         clear_bit(_PGC_page_table, &page->count_info);
-    }
 }
 
 /**************************************************************************/
diff -r e50872355390 -r 69e52712fbc4 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Thu Sep 21 09:37:28 2006 +0100
+++ b/xen/include/asm-x86/mm.h  Thu Sep 21 10:47:05 2006 +0100
@@ -51,18 +51,19 @@ struct page_info
     } u;
 
     union {
-        /* Timestamp from 'TLB clock', used to reduce need for safety
-         * flushes.  Only valid on a) free pages, and b) guest pages with a
-         * zero type count. */
+        /*
+         * Timestamp from 'TLB clock', used to avoid extra safety flushes.
+         * Only valid for: a) free pages, and b) pages with zero type count
+         * (except page table pages when the guest is in shadow mode).
+         */
         u32 tlbflush_timestamp;
 
-        /* Only used on guest pages with a shadow.
-         * Guest pages with a shadow must have a non-zero type count, so this
-         * does not conflict with the tlbflush timestamp. */
+        /*
+         * Guest pages with a shadow. This does not conflict with
+         * tlbflush_timestamp since page table pages are explicitly not
+         * tracked for TLB-flush avoidance when a guest runs in shadow mode.
+         */
         u32 shadow_flags;
-
-        // XXX -- we expect to add another field here, to be used for min/max
-        // purposes, which is only used for shadow pages.
     };
 };
 
diff -r e50872355390 -r 69e52712fbc4 xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Thu Sep 21 09:37:28 2006 +0100
+++ b/xen/include/asm-x86/shadow.h      Thu Sep 21 10:47:05 2006 +0100
@@ -325,24 +325,19 @@ void sh_do_mark_dirty(struct domain *d, 
 void sh_do_mark_dirty(struct domain *d, mfn_t gmfn);
 static inline void mark_dirty(struct domain *d, unsigned long gmfn)
 {
-    int caller_locked;
-
-    if ( unlikely(d == NULL) || likely(!shadow_mode_log_dirty(d)) )
+    if ( likely(!shadow_mode_log_dirty(d)) )
         return;
 
-    caller_locked = shadow_lock_is_acquired(d);
-    if ( !caller_locked )
-        shadow_lock(d);
+    shadow_lock(d);
     sh_do_mark_dirty(d, _mfn(gmfn));
-    if ( !caller_locked )
-        shadow_unlock(d);
+    shadow_unlock(d);
 }
 
 /* Internal version, for when the shadow lock is already held */
 static inline void sh_mark_dirty(struct domain *d, mfn_t gmfn)
 {
     ASSERT(shadow_lock_is_acquired(d));
-    if ( shadow_mode_log_dirty(d) )
+    if ( unlikely(shadow_mode_log_dirty(d)) )
         sh_do_mark_dirty(d, gmfn);
 }
 

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [XEN] Shadow mode no longer obtains page type references., Xen patchbot-unstable <=