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] xentrace 5/7: Additional tracing for the

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] xentrace 5/7: Additional tracing for the shadow code.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 08 Sep 2008 12:40:17 -0700
Delivery-date: Mon, 08 Sep 2008 12:40:52 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1220885884 -3600
# Node ID 74621a2add541e2f6363f1627091bb5d5d5307f0
# Parent  8305efd067497dcd8bba608f1d4102113a795243
xentrace 5/7: Additional tracing for the shadow code.

Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
Signed-off-by: Trolle Selander <trolle.selander@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c       |    4 
 xen/arch/x86/hvm/vmx/vmx.c       |   13 +-
 xen/arch/x86/mm/shadow/common.c  |   63 ++++++++++-
 xen/arch/x86/mm/shadow/multi.c   |  208 ++++++++++++++++++++++++++++++++++++---
 xen/arch/x86/mm/shadow/private.h |   43 ++++++++
 xen/common/trace.c               |   28 +++++
 xen/include/public/trace.h       |   17 +++
 xen/include/xen/trace.h          |    2 
 8 files changed, 353 insertions(+), 25 deletions(-)

diff -r 8305efd06749 -r 74621a2add54 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Sep 08 15:52:50 2008 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Sep 08 15:58:04 2008 +0100
@@ -1261,7 +1261,9 @@ asmlinkage void svm_vmexit_handler(struc
 
         if ( paging_fault(va, regs) )
         {
-            if (hvm_long_mode_enabled(v))
+            if ( trace_will_trace_event(TRC_SHADOW) )
+                break;
+            if ( hvm_long_mode_enabled(v) )
                 HVMTRACE_LONG_2D(PF_XEN, regs->error_code, TRC_PAR_LONG(va));
             else
                 HVMTRACE_2D(PF_XEN, regs->error_code, va);
diff -r 8305efd06749 -r 74621a2add54 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Sep 08 15:52:50 2008 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Mon Sep 08 15:58:04 2008 +0100
@@ -2101,7 +2101,8 @@ asmlinkage void vmx_vmexit_handler(struc
              !(__vmread(IDT_VECTORING_INFO) & INTR_INFO_VALID_MASK) &&
              (vector != TRAP_double_fault) )
             __vmwrite(GUEST_INTERRUPTIBILITY_INFO,
-                    __vmread(GUEST_INTERRUPTIBILITY_INFO)|VMX_INTR_SHADOW_NMI);
+                      __vmread(GUEST_INTERRUPTIBILITY_INFO)
+                      | VMX_INTR_SHADOW_NMI);
 
         perfc_incra(cause_vector, vector);
 
@@ -2128,12 +2129,14 @@ asmlinkage void vmx_vmexit_handler(struc
 
             if ( paging_fault(exit_qualification, regs) )
             {
+                if ( trace_will_trace_event(TRC_SHADOW) )
+                    break;
                 if ( hvm_long_mode_enabled(v) )
-                    HVMTRACE_LONG_2D (PF_XEN, regs->error_code,
-                        TRC_PAR_LONG(exit_qualification) );
+                    HVMTRACE_LONG_2D(PF_XEN, regs->error_code,
+                                     TRC_PAR_LONG(exit_qualification) );
                 else
-                    HVMTRACE_2D (PF_XEN,
-                        regs->error_code, exit_qualification );
+                    HVMTRACE_2D(PF_XEN,
+                                regs->error_code, exit_qualification );
                 break;
             }
 
diff -r 8305efd06749 -r 74621a2add54 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Mon Sep 08 15:52:50 2008 +0100
+++ b/xen/arch/x86/mm/shadow/common.c   Mon Sep 08 15:58:04 2008 +0100
@@ -39,6 +39,7 @@
 #include <xen/numa.h>
 #include "private.h"
 
+DEFINE_PER_CPU(uint32_t,trace_shadow_path_flags);
 
 /* Set up the shadow-specific parts of a domain struct at start of day.
  * Called for every domain from arch_domain_create() */
@@ -630,6 +631,8 @@ void oos_fixup_add(struct vcpu *v, mfn_t
 
             if ( mfn_x(oos_fixup[idx].smfn[next]) != INVALID_MFN )
             {
+                TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_OOS_FIXUP_EVICT);
+
                 /* Reuse this slot and remove current writable mapping. */
                 sh_remove_write_access_from_sl1p(v, gmfn, 
                                                  oos_fixup[idx].smfn[next],
@@ -645,6 +648,8 @@ void oos_fixup_add(struct vcpu *v, mfn_t
             oos_fixup[idx].smfn[next] = smfn;
             oos_fixup[idx].off[next] = off;
             oos_fixup[idx].next = (next + 1) % SHADOW_OOS_FIXUPS;
+
+            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_OOS_FIXUP_ADD);
             return;
         }
     }
@@ -687,6 +692,16 @@ static int oos_remove_write_access(struc
 }
 
 
+static inline void trace_resync(int event, mfn_t gmfn)
+{
+    if ( tb_init_done )
+    {
+        /* Convert gmfn to gfn */
+        unsigned long gfn = mfn_to_gfn(current->domain, gmfn);
+        __trace_var(event, 0/*!tsc*/, sizeof(gfn), (unsigned char*)&gfn);
+    }
+}
+
 /* Pull all the entries on an out-of-sync page back into sync. */
 static void _sh_resync(struct vcpu *v, mfn_t gmfn,
                        struct oos_fixup *fixup, mfn_t snp)
@@ -719,6 +734,7 @@ static void _sh_resync(struct vcpu *v, m
     /* Now we know all the entries are synced, and will stay that way */
     pg->shadow_flags &= ~SHF_out_of_sync;
     perfc_incr(shadow_resync);
+    trace_resync(TRC_SHADOW_RESYNC_FULL, gmfn);
 }
 
 
@@ -930,6 +946,7 @@ void sh_resync_all(struct vcpu *v, int s
                 /* Update the shadows and leave the page OOS. */
                 if ( sh_skip_sync(v, oos[idx]) )
                     continue;
+                trace_resync(TRC_SHADOW_RESYNC_ONLY, oos[idx]);
                 _sh_resync_l1(other, oos[idx], oos_snapshot[idx]);
             }
             else
@@ -945,7 +962,8 @@ void sh_resync_all(struct vcpu *v, int s
     }
 }
 
-/* Allow a shadowed page to go out of sync */
+/* Allow a shadowed page to go out of sync. Unsyncs are traced in
+ * multi.c:sh_page_fault() */
 int sh_unsync(struct vcpu *v, mfn_t gmfn)
 {
     struct page_info *pg;
@@ -970,6 +988,7 @@ int sh_unsync(struct vcpu *v, mfn_t gmfn
     pg->shadow_flags |= SHF_out_of_sync|SHF_oos_may_write;
     oos_hash_add(v, gmfn);
     perfc_incr(shadow_unsync);
+    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_UNSYNC);
     return 1;
 }
 
@@ -1005,6 +1024,7 @@ void shadow_promote(struct vcpu *v, mfn_
 
     ASSERT(!test_bit(type, &page->shadow_flags));
     set_bit(type, &page->shadow_flags);
+    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_PROMOTE);
 }
 
 void shadow_demote(struct vcpu *v, mfn_t gmfn, u32 type)
@@ -1027,6 +1047,8 @@ void shadow_demote(struct vcpu *v, mfn_t
 #endif 
         clear_bit(_PGC_page_table, &page->count_info);
     }
+
+    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_DEMOTE);
 }
 
 /**************************************************************************/
@@ -1094,6 +1116,7 @@ sh_validate_guest_entry(struct vcpu *v, 
     ASSERT((page->shadow_flags 
             & (SHF_L4_64|SHF_L3_64|SHF_L2H_64|SHF_L2_64|SHF_L1_64)) == 0);
 #endif
+    this_cpu(trace_shadow_path_flags) |= (result<<(TRCE_SFLAG_SET_CHANGED)); 
 
     return result;
 }
@@ -1295,6 +1318,18 @@ static void shadow_unhook_mappings(struc
     }
 }
 
+static inline void trace_shadow_prealloc_unpin(struct domain *d, mfn_t smfn)
+{
+    if ( tb_init_done )
+    {
+        /* Convert smfn to gfn */
+        unsigned long gfn;
+        ASSERT(mfn_valid(smfn));
+        gfn = mfn_to_gfn(d, _mfn(mfn_to_shadow_page(smfn)->backpointer));
+        __trace_var(TRC_SHADOW_PREALLOC_UNPIN, 0/*!tsc*/,
+                    sizeof(gfn), (unsigned char*)&gfn);
+    }
+}
 
 /* Make sure there are at least count order-sized pages
  * available in the shadow page pool. */
@@ -1327,6 +1362,7 @@ static void _shadow_prealloc(
         smfn = shadow_page_to_mfn(sp);
 
         /* Unpin this top-level shadow */
+        trace_shadow_prealloc_unpin(d, smfn);
         sh_unpin(v, smfn);
 
         /* See if that freed up enough space */
@@ -1343,6 +1379,7 @@ static void _shadow_prealloc(
         {
             if ( !pagetable_is_null(v2->arch.shadow_table[i]) )
             {
+                TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_PREALLOC_UNHOOK);
                 shadow_unhook_mappings(v, 
                                pagetable_get_mfn(v2->arch.shadow_table[i]));
 
@@ -2200,6 +2237,16 @@ void sh_destroy_shadow(struct vcpu *v, m
     }    
 }
 
+static inline void trace_shadow_wrmap_bf(mfn_t gmfn)
+{
+    if ( tb_init_done )
+    {
+        /* Convert gmfn to gfn */
+        unsigned long gfn = mfn_to_gfn(current->domain, gmfn);
+        __trace_var(TRC_SHADOW_WRMAP_BF, 0/*!tsc*/, sizeof(gfn), (unsigned 
char*)&gfn);
+    }
+}
+
 /**************************************************************************/
 /* Remove all writeable mappings of a guest frame from the shadow tables 
  * Returns non-zero if we need to flush TLBs. 
@@ -2265,6 +2312,8 @@ int sh_remove_write_access(struct vcpu *
          || (pg->u.inuse.type_info & PGT_count_mask) == 0 )
         return 0;
 
+    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_WRMAP);
+
     perfc_incr(shadow_writeable);
 
     /* If this isn't a "normal" writeable page, the domain is trying to 
@@ -2285,11 +2334,14 @@ int sh_remove_write_access(struct vcpu *
          * and that mapping is likely to be in the current pagetable,
          * in the guest's linear map (on non-HIGHPTE linux and windows)*/
 
-#define GUESS(_a, _h) do {                                                \
+#define GUESS(_a, _h) do {                                              \
             if ( v->arch.paging.mode->shadow.guess_wrmap(v, (_a), gmfn) ) \
-                perfc_incr(shadow_writeable_h_ ## _h);                   \
-            if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 )          \
-                return 1;                                                 \
+                perfc_incr(shadow_writeable_h_ ## _h);                  \
+            if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 )        \
+            {                                                           \
+                TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_WRMAP_GUESS_FOUND);   \
+                return 1;                                               \
+            }                                                           \
         } while (0)
 
         if ( level == 0 && fault_addr )
@@ -2377,6 +2429,7 @@ int sh_remove_write_access(struct vcpu *
 #endif /* SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC */
     
     /* Brute-force search of all the shadows, by walking the hash */
+    trace_shadow_wrmap_bf(gmfn);
     if ( level == 0 )
         perfc_incr(shadow_writeable_bf_1);
     else
diff -r 8305efd06749 -r 74621a2add54 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Mon Sep 08 15:52:50 2008 +0100
+++ b/xen/arch/x86/mm/shadow/multi.c    Mon Sep 08 15:58:04 2008 +0100
@@ -225,6 +225,7 @@ static uint32_t set_ad_bits(void *guest_
 static uint32_t set_ad_bits(void *guest_p, void *walk_p, int set_dirty)
 {
     guest_intpte_t old, new;
+    int ret = 0;
 
     old = *(guest_intpte_t *)walk_p;
     new = old | _PAGE_ACCESSED | (set_dirty ? _PAGE_DIRTY : 0);
@@ -234,10 +235,16 @@ static uint32_t set_ad_bits(void *guest_
          * into the guest table as well.  If the guest table has changed
          * under out feet then leave it alone. */
         *(guest_intpte_t *)walk_p = new;
-        if ( cmpxchg(((guest_intpte_t *)guest_p), old, new) == old ) 
-            return 1;
-    }
-    return 0;
+        if( cmpxchg(((guest_intpte_t *)guest_p), old, new) == old ) 
+            ret = 1;
+
+        /* FIXME -- this code is longer than necessary */
+        if(set_dirty)
+            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SET_AD);
+        else
+            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SET_A);
+    }
+    return ret;
 }
 
 /* This validation is called with lock held, and after write permission
@@ -1432,6 +1439,7 @@ static int shadow_set_l1e(struct vcpu *v
     {
         /* About to install a new reference */        
         if ( shadow_mode_refcounts(d) ) {
+            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SHADOW_L1_GET_REF);
             if ( shadow_get_page_from_l1e(new_sl1e, d) == 0 ) 
             {
                 /* Doesn't look like a pagetable. */
@@ -1461,6 +1469,7 @@ static int shadow_set_l1e(struct vcpu *v
         {
             shadow_vram_put_l1e(old_sl1e, sl1e, sl1mfn, d);
             shadow_put_page_from_l1e(old_sl1e, d);
+            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SHADOW_L1_PUT_REF);
         } 
     }
     return flags;
@@ -2896,6 +2905,7 @@ static inline void check_for_early_unsha
     {
         perfc_incr(shadow_early_unshadow);
         sh_remove_shadows(v, gmfn, 1, 0 /* Fast, can fail to unshadow */ );
+        TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_EARLY_UNSHADOW);
     }
     v->arch.paging.shadow.last_emulated_mfn_for_unshadow = mfn_x(gmfn);
 #endif
@@ -3012,6 +3022,132 @@ static void sh_prefetch(struct vcpu *v, 
 
 #endif /* SHADOW_OPTIMIZATIONS & SHOPT_PREFETCH */
 
+#if GUEST_PAGING_LEVELS == 4
+typedef u64 guest_va_t;
+typedef u64 guest_pa_t;
+#elif GUEST_PAGING_LEVELS == 3
+typedef u32 guest_va_t;
+typedef u64 guest_pa_t;
+#else
+typedef u32 guest_va_t;
+typedef u32 guest_pa_t;
+#endif
+
+static inline void trace_shadow_gen(u32 event, guest_va_t va)
+{
+    if ( tb_init_done )
+    {
+        event |= (GUEST_PAGING_LEVELS-2)<<8;
+        __trace_var(event, 0/*!tsc*/, sizeof(va), (unsigned char*)&va);
+    }
+}
+
+static inline void trace_shadow_fixup(guest_l1e_t gl1e,
+                                      guest_va_t va)
+{
+    if ( tb_init_done )
+    {
+        struct {
+            /* for PAE, guest_l1e may be 64 while guest_va may be 32;
+               so put it first for alignment sake. */
+            guest_l1e_t gl1e;
+            guest_va_t va;
+            u32 flags;
+        } __attribute__((packed)) d;
+        u32 event;
+
+        event = TRC_SHADOW_FIXUP | ((GUEST_PAGING_LEVELS-2)<<8);
+
+        d.gl1e = gl1e;
+        d.va = va;
+        d.flags = this_cpu(trace_shadow_path_flags);
+
+        __trace_var(event, 0/*!tsc*/, sizeof(d), (unsigned char*)&d);
+    }
+}
+                                          
+static inline void trace_not_shadow_fault(guest_l1e_t gl1e,
+                                          guest_va_t va)
+{
+    if ( tb_init_done )
+    {
+        struct {
+            /* for PAE, guest_l1e may be 64 while guest_va may be 32;
+               so put it first for alignment sake. */
+            guest_l1e_t gl1e;
+            guest_va_t va;
+            u32 flags;
+        } __attribute__((packed)) d;
+        u32 event;
+
+        event = TRC_SHADOW_NOT_SHADOW | ((GUEST_PAGING_LEVELS-2)<<8);
+
+        d.gl1e = gl1e;
+        d.va = va;
+        d.flags = this_cpu(trace_shadow_path_flags);
+
+        __trace_var(event, 0/*!tsc*/, sizeof(d), (unsigned char*)&d);
+    }
+}
+                                          
+static inline void trace_shadow_emulate_other(u32 event,
+                                                 guest_va_t va,
+                                                 gfn_t gfn)
+{
+    if ( tb_init_done )
+    {
+        struct {
+            /* for PAE, guest_l1e may be 64 while guest_va may be 32;
+               so put it first for alignment sake. */
+#if GUEST_PAGING_LEVELS == 2
+            u32 gfn;
+#else
+            u64 gfn;
+#endif
+            guest_va_t va;
+        } __attribute__((packed)) d;
+
+        event |= ((GUEST_PAGING_LEVELS-2)<<8);
+
+        d.gfn=gfn_x(gfn);
+        d.va = va;
+
+        __trace_var(event, 0/*!tsc*/, sizeof(d), (unsigned char*)&d);
+    }
+}
+
+#if GUEST_PAGING_LEVELS == 3
+static DEFINE_PER_CPU(guest_va_t,trace_emulate_initial_va);
+static DEFINE_PER_CPU(int,trace_extra_emulation_count);
+#endif
+static DEFINE_PER_CPU(guest_pa_t,trace_emulate_write_val);
+
+static inline void trace_shadow_emulate(guest_l1e_t gl1e, unsigned long va)
+{
+    if ( tb_init_done )
+    {
+        struct {
+            /* for PAE, guest_l1e may be 64 while guest_va may be 32;
+               so put it first for alignment sake. */
+            guest_l1e_t gl1e, write_val;
+            guest_va_t va;
+            unsigned flags:29, emulation_count:3;
+        } __attribute__((packed)) d;
+        u32 event;
+
+        event = TRC_SHADOW_EMULATE | ((GUEST_PAGING_LEVELS-2)<<8);
+
+        d.gl1e = gl1e;
+        d.write_val.l1 = this_cpu(trace_emulate_write_val);
+        d.va = va;
+#if GUEST_PAGING_LEVELS == 3
+        d.emulation_count = this_cpu(trace_extra_emulation_count);
+#endif
+        d.flags = this_cpu(trace_shadow_path_flags);
+
+        __trace_var(event, 0/*!tsc*/, sizeof(d), (unsigned char*)&d);
+    }
+}
 
 /**************************************************************************/
 /* Entry points into the shadow code */
@@ -3027,8 +3163,8 @@ static int sh_page_fault(struct vcpu *v,
 {
     struct domain *d = v->domain;
     walk_t gw;
-    gfn_t gfn;
-    mfn_t gmfn, sl1mfn=_mfn(0);
+    gfn_t gfn = _gfn(0);
+    mfn_t gmfn, sl1mfn = _mfn(0);
     shadow_l1e_t sl1e, *ptr_sl1e;
     paddr_t gpa;
     struct sh_emulate_ctxt emul_ctxt;
@@ -3132,6 +3268,7 @@ static int sh_page_fault(struct vcpu *v,
                 reset_early_unshadow(v);
                 perfc_incr(shadow_fault_fast_gnp);
                 SHADOW_PRINTK("fast path not-present\n");
+                trace_shadow_gen(TRC_SHADOW_FAST_PROPAGATE, va);
                 return 0;
             }
             else
@@ -3145,6 +3282,7 @@ static int sh_page_fault(struct vcpu *v,
             perfc_incr(shadow_fault_fast_mmio);
             SHADOW_PRINTK("fast path mmio %#"PRIpaddr"\n", gpa);
             reset_early_unshadow(v);
+            trace_shadow_gen(TRC_SHADOW_FAST_MMIO, va);
             return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT)
                     ? EXCRET_fault_fixed : 0);
         }
@@ -3155,6 +3293,7 @@ static int sh_page_fault(struct vcpu *v,
              * Retry and let the hardware give us the right fault next time. */
             perfc_incr(shadow_fault_fast_fail);
             SHADOW_PRINTK("fast path false alarm!\n");            
+            trace_shadow_gen(TRC_SHADOW_FALSE_FAST_PATH, va);
             return EXCRET_fault_fixed;
         }
     }
@@ -3190,7 +3329,7 @@ static int sh_page_fault(struct vcpu *v,
         perfc_incr(shadow_fault_bail_real_fault);
         SHADOW_PRINTK("not a shadow fault\n");
         reset_early_unshadow(v);
-        return 0;
+        goto propagate;
     }
 
     /* It's possible that the guest has put pagetables in memory that it has 
@@ -3200,7 +3339,7 @@ static int sh_page_fault(struct vcpu *v,
     if ( unlikely(d->is_shutting_down) )
     {
         SHADOW_PRINTK("guest is shutting down\n");
-        return 0;
+        goto propagate;
     }
 
     /* What kind of access are we dealing with? */
@@ -3218,7 +3357,7 @@ static int sh_page_fault(struct vcpu *v,
         SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"PRI_mfn"\n", 
                       gfn_x(gfn), mfn_x(gmfn));
         reset_early_unshadow(v);
-        return 0;
+        goto propagate;
     }
 
 #if (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB)
@@ -3229,6 +3368,8 @@ static int sh_page_fault(struct vcpu *v,
 
     shadow_lock(d);
 
+    TRACE_CLEAR_PATH_FLAGS;
+    
     rc = gw_remove_write_accesses(v, va, &gw);
 
     /* First bit set: Removed write access to a page. */
@@ -3281,6 +3422,7 @@ static int sh_page_fault(struct vcpu *v,
          * Get out of the fault handler immediately. */
         ASSERT(d->is_shutting_down);
         shadow_unlock(d);
+        trace_shadow_gen(TRC_SHADOW_DOMF_DYING, va);
         return 0;
     }
 
@@ -3383,6 +3525,7 @@ static int sh_page_fault(struct vcpu *v,
     d->arch.paging.log_dirty.fault_count++;
     reset_early_unshadow(v);
 
+    trace_shadow_fixup(gw.l1e, va);
  done:
     sh_audit_gw(v, &gw);
     SHADOW_PRINTK("fixed\n");
@@ -3405,6 +3548,8 @@ static int sh_page_fault(struct vcpu *v,
                       mfn_x(gmfn));
         perfc_incr(shadow_fault_emulate_failed);
         sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */);
+        trace_shadow_emulate_other(TRC_SHADOW_EMULATE_UNSHADOW_USER,
+                                      va, gfn);
         goto done;
     }
 
@@ -3421,6 +3566,8 @@ static int sh_page_fault(struct vcpu *v,
     shadow_audit_tables(v);
     shadow_unlock(d);
 
+    this_cpu(trace_emulate_write_val) = 0;
+
 #if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION
  early_emulation:
 #endif
@@ -3446,6 +3593,8 @@ static int sh_page_fault(struct vcpu *v,
                      "injection: cr2=%#lx, mfn=%#lx\n", 
                      va, mfn_x(gmfn));
             sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */);
+            trace_shadow_emulate_other(TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ,
+                                       va, gfn);
             return EXCRET_fault_fixed;
         }
     }
@@ -3478,6 +3627,10 @@ static int sh_page_fault(struct vcpu *v,
          * to support more operations in the emulator.  More likely, 
          * though, this is a hint that this page should not be shadowed. */
         shadow_remove_all_shadows(v, gmfn);
+
+        trace_shadow_emulate_other(TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED,
+                                   va, gfn);
+        goto emulate_done;
     }
 
 #if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION
@@ -3504,7 +3657,8 @@ static int sh_page_fault(struct vcpu *v,
 
 #if GUEST_PAGING_LEVELS == 3 /* PAE guest */
     if ( r == X86EMUL_OKAY ) {
-        int i;
+        int i, emulation_count=0;
+        this_cpu(trace_emulate_initial_va) = va;
         /* Emulate up to four extra instructions in the hope of catching 
          * the "second half" of a 64-bit pagetable write. */
         for ( i = 0 ; i < 4 ; i++ )
@@ -3513,10 +3667,12 @@ static int sh_page_fault(struct vcpu *v,
             v->arch.paging.last_write_was_pt = 0;
             r = x86_emulate(&emul_ctxt.ctxt, emul_ops);
             if ( r == X86EMUL_OKAY )
-            {
+            { 
+                emulation_count++;
                 if ( v->arch.paging.last_write_was_pt )
                 {
                     perfc_incr(shadow_em_ex_pt);
+                    
TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_EMULATION_2ND_PT_WRITTEN);
                     break; /* Don't emulate past the other half of the write */
                 }
                 else 
@@ -3525,12 +3681,16 @@ static int sh_page_fault(struct vcpu *v,
             else
             {
                 perfc_incr(shadow_em_ex_fail);
+                TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_EMULATION_LAST_FAILED);
                 break; /* Don't emulate again if we failed! */
             }
         }
+        this_cpu(trace_extra_emulation_count)=emulation_count;
     }
 #endif /* PAE guest */
 
+    trace_shadow_emulate(gw.l1e, va);
+ emulate_done:
     SHADOW_PRINTK("emulated\n");
     return EXCRET_fault_fixed;
 
@@ -3543,6 +3703,7 @@ static int sh_page_fault(struct vcpu *v,
     shadow_audit_tables(v);
     reset_early_unshadow(v);
     shadow_unlock(d);
+    trace_shadow_gen(TRC_SHADOW_MMIO, va);
     return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT)
             ? EXCRET_fault_fixed : 0);
 
@@ -3552,6 +3713,10 @@ static int sh_page_fault(struct vcpu *v,
     shadow_audit_tables(v);
     reset_early_unshadow(v);
     shadow_unlock(d);
+
+propagate:
+    trace_not_shadow_fault(gw.l1e, va);
+
     return 0;
 }
 
@@ -3990,7 +4155,7 @@ sh_detach_old_tables(struct vcpu *v)
             sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable);
         v->arch.paging.shadow.guest_vtable = NULL;
     }
-#endif
+#endif // !NDEBUG
 
 
     ////
@@ -4446,6 +4611,7 @@ static int sh_guess_wrmap(struct vcpu *v
     sl1e = shadow_l1e_remove_flags(sl1e, _PAGE_RW);
     r = shadow_set_l1e(v, sl1p, sl1e, sl1mfn);
     ASSERT( !(r & SHADOW_SET_ERROR) );
+    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_WRMAP_GUESS_FOUND);
     return 1;
 }
 #endif
@@ -4800,7 +4966,7 @@ static void emulate_unmap_dest(struct vc
 
 static int
 sh_x86_emulate_write(struct vcpu *v, unsigned long vaddr, void *src,
-                      u32 bytes, struct sh_emulate_ctxt *sh_ctxt)
+                     u32 bytes, struct sh_emulate_ctxt *sh_ctxt)
 {
     void *addr;
 
@@ -4814,6 +4980,22 @@ sh_x86_emulate_write(struct vcpu *v, uns
 
     shadow_lock(v->domain);
     memcpy(addr, src, bytes);
+
+    if ( tb_init_done )
+    {
+#if GUEST_PAGING_LEVELS == 3
+        if ( vaddr == this_cpu(trace_emulate_initial_va) )
+            memcpy(&this_cpu(trace_emulate_write_val), src, bytes);
+        else if ( (vaddr & ~(0x7UL)) == this_cpu(trace_emulate_initial_va) )
+        {
+            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_EMULATE_FULL_PT);
+            memcpy(&this_cpu(trace_emulate_write_val),
+                   (void *)(((unsigned long) addr) & ~(0x7UL)), 
GUEST_PTE_SIZE);
+        }
+#else
+        memcpy(&this_cpu(trace_emulate_write_val), src, bytes);
+#endif
+    }
 
     emulate_unmap_dest(v, addr, bytes, sh_ctxt);
     shadow_audit_tables(v);
diff -r 8305efd06749 -r 74621a2add54 xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h  Mon Sep 08 15:52:50 2008 +0100
+++ b/xen/arch/x86/mm/shadow/private.h  Mon Sep 08 15:58:04 2008 +0100
@@ -90,6 +90,43 @@ extern int shadow_audit_enable;
 #define SHADOW_DEBUG_EMULATE           1
 #define SHADOW_DEBUG_P2M               1
 #define SHADOW_DEBUG_LOGDIRTY          0
+
+/******************************************************************************
+ * Tracing
+ */
+DECLARE_PER_CPU(uint32_t,trace_shadow_path_flags);
+
+#define TRACE_SHADOW_PATH_FLAG(_x)                      \
+    do {                                                \
+        this_cpu(trace_shadow_path_flags) |= (1<<(_x));      \
+    } while(0)
+
+#define TRACE_CLEAR_PATH_FLAGS                  \
+    this_cpu(trace_shadow_path_flags) = 0
+
+enum {
+    TRCE_SFLAG_SET_AD,
+    TRCE_SFLAG_SET_A,
+    TRCE_SFLAG_SHADOW_L1_GET_REF,
+    TRCE_SFLAG_SHADOW_L1_PUT_REF,
+    TRCE_SFLAG_L2_PROPAGATE,
+    TRCE_SFLAG_SET_CHANGED,
+    TRCE_SFLAG_SET_FLUSH,
+    TRCE_SFLAG_SET_ERROR,
+    TRCE_SFLAG_DEMOTE,
+    TRCE_SFLAG_PROMOTE,
+    TRCE_SFLAG_WRMAP,
+    TRCE_SFLAG_WRMAP_GUESS_FOUND,
+    TRCE_SFLAG_WRMAP_BRUTE_FORCE,
+    TRCE_SFLAG_EARLY_UNSHADOW,
+    TRCE_SFLAG_EMULATION_2ND_PT_WRITTEN,
+    TRCE_SFLAG_EMULATION_LAST_FAILED,
+    TRCE_SFLAG_EMULATE_FULL_PT,
+    TRCE_SFLAG_PREALLOC_UNHOOK,
+    TRCE_SFLAG_UNSYNC,
+    TRCE_SFLAG_OOS_FIXUP_ADD,
+    TRCE_SFLAG_OOS_FIXUP_EVICT,
+};
 
 /******************************************************************************
  * The shadow lock.
@@ -143,6 +180,12 @@ extern int shadow_audit_enable;
     } while (0)
 
 
+/* Size (in bytes) of a guest PTE */
+#if GUEST_PAGING_LEVELS >= 3
+# define GUEST_PTE_SIZE 8
+#else
+# define GUEST_PTE_SIZE 4
+#endif
 
 /******************************************************************************
  * Auditing routines 
diff -r 8305efd06749 -r 74621a2add54 xen/common/trace.c
--- a/xen/common/trace.c        Mon Sep 08 15:52:50 2008 +0100
+++ b/xen/common/trace.c        Mon Sep 08 15:58:04 2008 +0100
@@ -148,6 +148,31 @@ static int tb_set_size(int size)
     return 0;
 }
 
+int trace_will_trace_event(u32 event)
+{
+    if ( !tb_init_done )
+        return 0;
+
+    /*
+     * Copied from __trace_var()
+     */
+    if ( (tb_event_mask & event) == 0 )
+        return 0;
+
+    /* match class */
+    if ( ((tb_event_mask >> TRC_CLS_SHIFT) & (event >> TRC_CLS_SHIFT)) == 0 )
+        return 0;
+
+    /* then match subclass */
+    if ( (((tb_event_mask >> TRC_SUBCLS_SHIFT) & 0xf )
+                & ((event >> TRC_SUBCLS_SHIFT) & 0xf )) == 0 )
+        return 0;
+
+    if ( !cpu_isset(smp_processor_id(), tb_cpu_mask) )
+        return 0;
+
+    return 1;
+}
 
 /**
  * init_trace_bufs - performs initialization of the per-cpu trace buffers.
@@ -407,7 +432,8 @@ void __trace_var(u32 event, int cycles, 
     int extra_word;
     int started_below_highwater;
 
-    ASSERT(tb_init_done);
+    if( !tb_init_done )
+        return;
 
     /* Convert byte count into word count, rounding up */
     extra_word = (extra / sizeof(u32));
diff -r 8305efd06749 -r 74621a2add54 xen/include/public/trace.h
--- a/xen/include/public/trace.h        Mon Sep 08 15:52:50 2008 +0100
+++ b/xen/include/public/trace.h        Mon Sep 08 15:58:04 2008 +0100
@@ -37,6 +37,7 @@
 #define TRC_HVM      0x0008f000    /* Xen HVM trace            */
 #define TRC_MEM      0x0010f000    /* Xen memory trace         */
 #define TRC_PV       0x0020f000    /* Xen PV traces            */
+#define TRC_SHADOW   0x0040f000    /* Xen shadow tracing       */
 #define TRC_ALL      0x0ffff000
 #define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff)
 #define TRC_HD_CYCLE_FLAG (1UL<<31)
@@ -92,6 +93,22 @@
 #define TRC_PV_PTWR_EMULATION_PAE    (TRC_PV + 12)
   /* Indicates that addresses in trace record are 64 bits */
 #define TRC_64_FLAG               (0x100) 
+
+#define TRC_SHADOW_NOT_SHADOW                 (TRC_SHADOW +  1)
+#define TRC_SHADOW_FAST_PROPAGATE             (TRC_SHADOW +  2)
+#define TRC_SHADOW_FAST_MMIO                  (TRC_SHADOW +  3)
+#define TRC_SHADOW_FALSE_FAST_PATH            (TRC_SHADOW +  4)
+#define TRC_SHADOW_MMIO                       (TRC_SHADOW +  5)
+#define TRC_SHADOW_FIXUP                      (TRC_SHADOW +  6)
+#define TRC_SHADOW_DOMF_DYING                 (TRC_SHADOW +  7)
+#define TRC_SHADOW_EMULATE                    (TRC_SHADOW +  8)
+#define TRC_SHADOW_EMULATE_UNSHADOW_USER      (TRC_SHADOW +  9)
+#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ    (TRC_SHADOW + 10)
+#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED (TRC_SHADOW + 11)
+#define TRC_SHADOW_WRMAP_BF                   (TRC_SHADOW + 12)
+#define TRC_SHADOW_PREALLOC_UNPIN             (TRC_SHADOW + 13)
+#define TRC_SHADOW_RESYNC_FULL                (TRC_SHADOW + 14)
+#define TRC_SHADOW_RESYNC_ONLY                (TRC_SHADOW + 15)
 
 /* trace events per subclass */
 #define TRC_HVM_VMENTRY         (TRC_HVM_ENTRYEXIT + 0x01)
diff -r 8305efd06749 -r 74621a2add54 xen/include/xen/trace.h
--- a/xen/include/xen/trace.h   Mon Sep 08 15:52:50 2008 +0100
+++ b/xen/include/xen/trace.h   Mon Sep 08 15:58:04 2008 +0100
@@ -33,6 +33,8 @@ void init_trace_bufs(void);
 
 /* used to retrieve the physical address of the trace buffers */
 int tb_control(struct xen_sysctl_tbuf_op *tbc);
+
+int trace_will_trace_event(u32 event);
 
 void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data);
 

_______________________________________________
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] xentrace 5/7: Additional tracing for the shadow code., Xen patchbot-unstable <=