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

[Xen-changelog] [xen-unstable] xentrace 5/7: Additional tracing for the shadow code.



# 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


 


Rackspace

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