[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEN] Allow log-dirty mode to be enabled on already-shadowed domains.



# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1172498161 0
# Node ID 720afbf740018c55ce984c09bbc61dbeb4f0d74e
# Parent  bfd4fad0f0529449a1204426770c226824c97e2e
[XEN] Allow log-dirty mode to be enabled on already-shadowed domains.
and catch a few missing mark_dirty() calls
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/hvm.c           |    2 +
 xen/arch/x86/hvm/io.c            |   10 ++++++++
 xen/arch/x86/mm/shadow/common.c  |   47 ++++++++++++++-------------------------
 xen/arch/x86/mm/shadow/multi.c   |   34 ++++------------------------
 xen/arch/x86/mm/shadow/private.h |    3 --
 xen/include/asm-x86/shadow.h     |    5 ++--
 6 files changed, 39 insertions(+), 62 deletions(-)

diff -r bfd4fad0f052 -r 720afbf74001 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Mon Feb 26 11:53:35 2007 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Mon Feb 26 13:56:01 2007 +0000
@@ -398,6 +398,8 @@ static int __hvm_copy(void *buf, paddr_t
             memcpy(buf, p, count); /* dir == FALSE: *from guest */
 
         unmap_domain_page(p);
+        
+        mark_dirty(current->domain, mfn);
 
         addr += count;
         buf  += count;
diff -r bfd4fad0f052 -r 720afbf74001 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Mon Feb 26 11:53:35 2007 +0000
+++ b/xen/arch/x86/hvm/io.c     Mon Feb 26 13:56:01 2007 +0000
@@ -33,6 +33,8 @@
 #include <asm/msr.h>
 #include <asm/apic.h>
 #include <asm/paging.h>
+#include <asm/shadow.h>
+#include <asm/p2m.h>
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
 #include <asm/hvm/vpt.h>
@@ -739,6 +741,7 @@ void hvm_io_assist(struct vcpu *v)
     ioreq_t *p;
     struct cpu_user_regs *regs;
     struct hvm_io_op *io_opp;
+    unsigned long gmfn;
 
     io_opp = &v->arch.hvm_vcpu.io_op;
     regs   = &io_opp->io_context;
@@ -763,6 +766,13 @@ void hvm_io_assist(struct vcpu *v)
     /* Copy register changes back into current guest state. */
     hvm_load_cpu_guest_regs(v, regs);
     memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES);
+
+    /* Has memory been dirtied? */
+    if ( p->dir == IOREQ_READ && p->data_is_ptr ) 
+    {
+        gmfn = get_mfn_from_gpfn(paging_gva_to_gfn(v, p->data));
+        mark_dirty(v->domain, gmfn);
+    }
 }
 
 /*
diff -r bfd4fad0f052 -r 720afbf74001 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Mon Feb 26 11:53:35 2007 +0000
+++ b/xen/arch/x86/mm/shadow/common.c   Mon Feb 26 13:56:01 2007 +0000
@@ -981,7 +981,6 @@ mfn_t shadow_alloc(struct domain *d,
         INIT_LIST_HEAD(&sp[i].list);
         sp[i].type = shadow_type;
         sp[i].pinned = 0;
-        sp[i].logdirty = 0;
         sp[i].count = 0;
         sp[i].backpointer = backpointer;
         sp[i].next_shadow = NULL;
@@ -1230,7 +1229,6 @@ static unsigned int sh_set_allocation(st
             {
                 sp[j].type = 0;  
                 sp[j].pinned = 0;
-                sp[j].logdirty = 0;
                 sp[j].count = 0;
                 sp[j].mbz = 0;
                 sp[j].tlbflush_timestamp = 0; /* Not in any TLB */
@@ -2558,7 +2556,7 @@ static int shadow_one_bit_enable(struct 
     ASSERT(shadow_locked_by_me(d));
 
     /* Sanity check the call */
-    if ( d == current->domain || (d->arch.paging.mode & mode) )
+    if ( d == current->domain || (d->arch.paging.mode & mode) == mode )
     {
         return -EINVAL;
     }
@@ -2589,7 +2587,7 @@ static int shadow_one_bit_disable(struct
     ASSERT(shadow_locked_by_me(d));
 
     /* Sanity check the call */
-    if ( d == current->domain || !(d->arch.paging.mode & mode) )
+    if ( d == current->domain || !((d->arch.paging.mode & mode) == mode) )
     {
         return -EINVAL;
     }
@@ -2646,17 +2644,7 @@ static int shadow_test_enable(struct dom
 
     domain_pause(d);
     shadow_lock(d);
-
-    if ( shadow_mode_enabled(d) )
-    {
-        SHADOW_ERROR("Don't support enabling test mode"
-                      " on already shadowed doms\n");
-        ret = -EINVAL;
-        goto out;
-    }
-
     ret = shadow_one_bit_enable(d, PG_SH_enable);
- out:
     shadow_unlock(d);
     domain_unpause(d);
 
@@ -2722,10 +2710,10 @@ static int shadow_log_dirty_enable(struc
 
     if ( shadow_mode_enabled(d) )
     {
-        SHADOW_ERROR("Don't (yet) support enabling log-dirty"
-                      " on already shadowed doms\n");
-        ret = -EINVAL;
-        goto out;
+        /* This domain already has some shadows: need to clear them out 
+         * of the way to make sure that all references to guest memory are 
+         * properly write-protected */
+        shadow_blow_tables(d);
     }
 
 #if (SHADOW_OPTIMIZATIONS & SHOPT_LINUX_L3_TOPLEVEL)
@@ -2917,11 +2905,17 @@ void sh_mark_dirty(struct domain *d, mfn
 void sh_mark_dirty(struct domain *d, mfn_t gmfn)
 {
     unsigned long pfn;
-
-    ASSERT(shadow_locked_by_me(d));
+    int do_locking;
 
     if ( !shadow_mode_log_dirty(d) || !mfn_valid(gmfn) )
         return;
+
+    /* Although this is an externally visible function, we do not know
+     * whether the shadow lock will be held when it is called (since it
+     * can be called from __hvm_copy during emulation).
+     * If the lock isn't held, take it for the duration of the call. */
+    do_locking = !shadow_locked_by_me(d);
+    if ( do_locking ) shadow_lock(d);
 
     ASSERT(d->arch.paging.shadow.dirty_bitmap != NULL);
 
@@ -2962,13 +2956,8 @@ void sh_mark_dirty(struct domain *d, mfn
                        mfn_to_page(gmfn)->count_info, 
                        mfn_to_page(gmfn)->u.inuse.type_info);
     }
-}
-
-void shadow_mark_dirty(struct domain *d, mfn_t gmfn)
-{
-    shadow_lock(d);
-    sh_mark_dirty(d, gmfn);
-    shadow_unlock(d);
+
+    if ( do_locking ) shadow_unlock(d);
 }
 
 /**************************************************************************/
@@ -2992,9 +2981,7 @@ int shadow_domctl(struct domain *d,
         if ( shadow_mode_log_dirty(d) )
             if ( (rc = shadow_log_dirty_disable(d)) != 0 ) 
                 return rc;
-        if ( is_hvm_domain(d) )
-            return -EINVAL;
-        if ( d->arch.paging.mode & PG_SH_enable )
+        if ( d->arch.paging.mode == PG_SH_enable )
             if ( (rc = shadow_test_disable(d)) != 0 ) 
                 return rc;
         return 0;
diff -r bfd4fad0f052 -r 720afbf74001 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Mon Feb 26 11:53:35 2007 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c    Mon Feb 26 13:56:01 2007 +0000
@@ -101,14 +101,6 @@ get_fl1_shadow_status(struct vcpu *v, gf
 /* Look for FL1 shadows in the hash table */
 {
     mfn_t smfn = shadow_hash_lookup(v, gfn_x(gfn), SH_type_fl1_shadow);
-
-    if ( unlikely(shadow_mode_log_dirty(v->domain) && mfn_valid(smfn)) )
-    {
-        struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
-        if ( !(sp->logdirty) )
-            shadow_convert_to_log_dirty(v, smfn);
-    }
-
     return smfn;
 }
 
@@ -118,14 +110,6 @@ get_shadow_status(struct vcpu *v, mfn_t 
 {
     mfn_t smfn = shadow_hash_lookup(v, mfn_x(gmfn), shadow_type);
     perfc_incrc(shadow_get_shadow_status);
-
-    if ( unlikely(shadow_mode_log_dirty(v->domain) && mfn_valid(smfn)) )
-    {
-        struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
-        if ( !(sp->logdirty) )
-            shadow_convert_to_log_dirty(v, smfn);
-    }
-
     return smfn;
 }
 
@@ -136,12 +120,6 @@ set_fl1_shadow_status(struct vcpu *v, gf
     SHADOW_PRINTK("gfn=%"SH_PRI_gfn", type=%08x, smfn=%05lx\n",
                    gfn_x(gfn), SH_type_fl1_shadow, mfn_x(smfn));
 
-    if ( unlikely(shadow_mode_log_dirty(v->domain)) )
-        // mark this shadow as a log dirty shadow...
-        mfn_to_shadow_page(smfn)->logdirty = 1;
-    else
-        mfn_to_shadow_page(smfn)->logdirty = 0;
-
     shadow_hash_insert(v, gfn_x(gfn), SH_type_fl1_shadow, smfn);
 }
 
@@ -155,12 +133,6 @@ set_shadow_status(struct vcpu *v, mfn_t 
     SHADOW_PRINTK("d=%d, v=%d, gmfn=%05lx, type=%08x, smfn=%05lx\n",
                    d->domain_id, v->vcpu_id, mfn_x(gmfn),
                    shadow_type, mfn_x(smfn));
-
-    if ( unlikely(shadow_mode_log_dirty(d)) )
-        // mark this shadow as a log dirty shadow...
-        mfn_to_shadow_page(smfn)->logdirty = 1;
-    else
-        mfn_to_shadow_page(smfn)->logdirty = 0;
 
 #ifdef CONFIG_COMPAT
     if ( !IS_COMPAT(d) || shadow_type != SH_type_l4_64_shadow )
@@ -3994,6 +3966,8 @@ sh_x86_emulate_write(struct vcpu *v, uns
     /* If we are writing zeros to this page, might want to unshadow */
     if ( likely(bytes >= 4) && (*(u32 *)addr == 0) && is_lo_pte(vaddr) )
         check_for_early_unshadow(v, mfn);
+    
+    sh_mark_dirty(v->domain, mfn);
 
     sh_unmap_domain_page(addr);
     shadow_audit_tables(v);
@@ -4047,6 +4021,8 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u
     if ( likely(bytes >= 4) && (*(u32 *)addr == 0) && is_lo_pte(vaddr) )
         check_for_early_unshadow(v, mfn);
 
+    sh_mark_dirty(v->domain, mfn);
+
     sh_unmap_domain_page(addr);
     shadow_audit_tables(v);
     return rv;
@@ -4086,6 +4062,8 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v,
     /* If we are writing zeros to this page, might want to unshadow */
     if ( *(u32 *)addr == 0 )
         check_for_early_unshadow(v, mfn);
+
+    sh_mark_dirty(v->domain, mfn);
 
     sh_unmap_domain_page(addr);
     shadow_audit_tables(v);
diff -r bfd4fad0f052 -r 720afbf74001 xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h  Mon Feb 26 11:53:35 2007 +0000
+++ b/xen/arch/x86/mm/shadow/private.h  Mon Feb 26 13:56:01 2007 +0000
@@ -229,8 +229,7 @@ struct shadow_page_info
     struct {
         unsigned int type:4;      /* What kind of shadow is this? */
         unsigned int pinned:1;    /* Is the shadow pinned? */
-        unsigned int logdirty:1;  /* Was it made in log-dirty mode? */
-        unsigned int count:26;    /* Reference count */
+        unsigned int count:27;    /* Reference count */
         u32 mbz;                  /* Must be zero: this is where the owner 
                                    * field lives in a non-shadow page */
     } __attribute__((packed));
diff -r bfd4fad0f052 -r 720afbf74001 xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Mon Feb 26 11:53:35 2007 +0000
+++ b/xen/include/asm-x86/shadow.h      Mon Feb 26 13:56:01 2007 +0000
@@ -87,12 +87,13 @@ void shadow_final_teardown(struct domain
 
 /* Mark a page as dirty in the log-dirty bitmap: called when Xen 
  * makes changes to guest memory on its behalf. */
-void shadow_mark_dirty(struct domain *d, mfn_t gmfn);
+void sh_mark_dirty(struct domain *d, mfn_t gmfn);
 /* Cleaner version so we don't pepper shadow_mode tests all over the place */
 static inline void mark_dirty(struct domain *d, unsigned long gmfn)
 {
     if ( unlikely(shadow_mode_log_dirty(d)) )
-        shadow_mark_dirty(d, _mfn(gmfn));
+        /* See the comment about locking in sh_mark_dirty */
+        sh_mark_dirty(d, _mfn(gmfn));
 }
 
 /* Update all the things that are derived from the guest's CR0/CR3/CR4.

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.