ia64/xen-unstable

changeset 18454:74621a2add54

xentrace 5/7: Additional tracing for the shadow code.

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
Signed-off-by: Trolle Selander <trolle.selander@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Sep 08 15:58:04 2008 +0100 (2008-09-08)
parents 8305efd06749
children b8734df52a90
files xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/mm/shadow/common.c xen/arch/x86/mm/shadow/multi.c xen/arch/x86/mm/shadow/private.h xen/common/trace.c xen/include/public/trace.h xen/include/xen/trace.h
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/svm.c	Mon Sep 08 15:52:50 2008 +0100
     1.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Mon Sep 08 15:58:04 2008 +0100
     1.3 @@ -1261,7 +1261,9 @@ asmlinkage void svm_vmexit_handler(struc
     1.4  
     1.5          if ( paging_fault(va, regs) )
     1.6          {
     1.7 -            if (hvm_long_mode_enabled(v))
     1.8 +            if ( trace_will_trace_event(TRC_SHADOW) )
     1.9 +                break;
    1.10 +            if ( hvm_long_mode_enabled(v) )
    1.11                  HVMTRACE_LONG_2D(PF_XEN, regs->error_code, TRC_PAR_LONG(va));
    1.12              else
    1.13                  HVMTRACE_2D(PF_XEN, regs->error_code, va);
     2.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Mon Sep 08 15:52:50 2008 +0100
     2.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Mon Sep 08 15:58:04 2008 +0100
     2.3 @@ -2101,7 +2101,8 @@ asmlinkage void vmx_vmexit_handler(struc
     2.4               !(__vmread(IDT_VECTORING_INFO) & INTR_INFO_VALID_MASK) &&
     2.5               (vector != TRAP_double_fault) )
     2.6              __vmwrite(GUEST_INTERRUPTIBILITY_INFO,
     2.7 -                    __vmread(GUEST_INTERRUPTIBILITY_INFO)|VMX_INTR_SHADOW_NMI);
     2.8 +                      __vmread(GUEST_INTERRUPTIBILITY_INFO)
     2.9 +                      | VMX_INTR_SHADOW_NMI);
    2.10  
    2.11          perfc_incra(cause_vector, vector);
    2.12  
    2.13 @@ -2128,12 +2129,14 @@ asmlinkage void vmx_vmexit_handler(struc
    2.14  
    2.15              if ( paging_fault(exit_qualification, regs) )
    2.16              {
    2.17 +                if ( trace_will_trace_event(TRC_SHADOW) )
    2.18 +                    break;
    2.19                  if ( hvm_long_mode_enabled(v) )
    2.20 -                    HVMTRACE_LONG_2D (PF_XEN, regs->error_code,
    2.21 -                        TRC_PAR_LONG(exit_qualification) );
    2.22 +                    HVMTRACE_LONG_2D(PF_XEN, regs->error_code,
    2.23 +                                     TRC_PAR_LONG(exit_qualification) );
    2.24                  else
    2.25 -                    HVMTRACE_2D (PF_XEN,
    2.26 -                        regs->error_code, exit_qualification );
    2.27 +                    HVMTRACE_2D(PF_XEN,
    2.28 +                                regs->error_code, exit_qualification );
    2.29                  break;
    2.30              }
    2.31  
     3.1 --- a/xen/arch/x86/mm/shadow/common.c	Mon Sep 08 15:52:50 2008 +0100
     3.2 +++ b/xen/arch/x86/mm/shadow/common.c	Mon Sep 08 15:58:04 2008 +0100
     3.3 @@ -39,6 +39,7 @@
     3.4  #include <xen/numa.h>
     3.5  #include "private.h"
     3.6  
     3.7 +DEFINE_PER_CPU(uint32_t,trace_shadow_path_flags);
     3.8  
     3.9  /* Set up the shadow-specific parts of a domain struct at start of day.
    3.10   * Called for every domain from arch_domain_create() */
    3.11 @@ -630,6 +631,8 @@ void oos_fixup_add(struct vcpu *v, mfn_t
    3.12  
    3.13              if ( mfn_x(oos_fixup[idx].smfn[next]) != INVALID_MFN )
    3.14              {
    3.15 +                TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_OOS_FIXUP_EVICT);
    3.16 +
    3.17                  /* Reuse this slot and remove current writable mapping. */
    3.18                  sh_remove_write_access_from_sl1p(v, gmfn, 
    3.19                                                   oos_fixup[idx].smfn[next],
    3.20 @@ -645,6 +648,8 @@ void oos_fixup_add(struct vcpu *v, mfn_t
    3.21              oos_fixup[idx].smfn[next] = smfn;
    3.22              oos_fixup[idx].off[next] = off;
    3.23              oos_fixup[idx].next = (next + 1) % SHADOW_OOS_FIXUPS;
    3.24 +
    3.25 +            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_OOS_FIXUP_ADD);
    3.26              return;
    3.27          }
    3.28      }
    3.29 @@ -687,6 +692,16 @@ static int oos_remove_write_access(struc
    3.30  }
    3.31  
    3.32  
    3.33 +static inline void trace_resync(int event, mfn_t gmfn)
    3.34 +{
    3.35 +    if ( tb_init_done )
    3.36 +    {
    3.37 +        /* Convert gmfn to gfn */
    3.38 +        unsigned long gfn = mfn_to_gfn(current->domain, gmfn);
    3.39 +        __trace_var(event, 0/*!tsc*/, sizeof(gfn), (unsigned char*)&gfn);
    3.40 +    }
    3.41 +}
    3.42 +
    3.43  /* Pull all the entries on an out-of-sync page back into sync. */
    3.44  static void _sh_resync(struct vcpu *v, mfn_t gmfn,
    3.45                         struct oos_fixup *fixup, mfn_t snp)
    3.46 @@ -719,6 +734,7 @@ static void _sh_resync(struct vcpu *v, m
    3.47      /* Now we know all the entries are synced, and will stay that way */
    3.48      pg->shadow_flags &= ~SHF_out_of_sync;
    3.49      perfc_incr(shadow_resync);
    3.50 +    trace_resync(TRC_SHADOW_RESYNC_FULL, gmfn);
    3.51  }
    3.52  
    3.53  
    3.54 @@ -930,6 +946,7 @@ void sh_resync_all(struct vcpu *v, int s
    3.55                  /* Update the shadows and leave the page OOS. */
    3.56                  if ( sh_skip_sync(v, oos[idx]) )
    3.57                      continue;
    3.58 +                trace_resync(TRC_SHADOW_RESYNC_ONLY, oos[idx]);
    3.59                  _sh_resync_l1(other, oos[idx], oos_snapshot[idx]);
    3.60              }
    3.61              else
    3.62 @@ -945,7 +962,8 @@ void sh_resync_all(struct vcpu *v, int s
    3.63      }
    3.64  }
    3.65  
    3.66 -/* Allow a shadowed page to go out of sync */
    3.67 +/* Allow a shadowed page to go out of sync. Unsyncs are traced in
    3.68 + * multi.c:sh_page_fault() */
    3.69  int sh_unsync(struct vcpu *v, mfn_t gmfn)
    3.70  {
    3.71      struct page_info *pg;
    3.72 @@ -970,6 +988,7 @@ int sh_unsync(struct vcpu *v, mfn_t gmfn
    3.73      pg->shadow_flags |= SHF_out_of_sync|SHF_oos_may_write;
    3.74      oos_hash_add(v, gmfn);
    3.75      perfc_incr(shadow_unsync);
    3.76 +    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_UNSYNC);
    3.77      return 1;
    3.78  }
    3.79  
    3.80 @@ -1005,6 +1024,7 @@ void shadow_promote(struct vcpu *v, mfn_
    3.81  
    3.82      ASSERT(!test_bit(type, &page->shadow_flags));
    3.83      set_bit(type, &page->shadow_flags);
    3.84 +    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_PROMOTE);
    3.85  }
    3.86  
    3.87  void shadow_demote(struct vcpu *v, mfn_t gmfn, u32 type)
    3.88 @@ -1027,6 +1047,8 @@ void shadow_demote(struct vcpu *v, mfn_t
    3.89  #endif 
    3.90          clear_bit(_PGC_page_table, &page->count_info);
    3.91      }
    3.92 +
    3.93 +    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_DEMOTE);
    3.94  }
    3.95  
    3.96  /**************************************************************************/
    3.97 @@ -1094,6 +1116,7 @@ sh_validate_guest_entry(struct vcpu *v, 
    3.98      ASSERT((page->shadow_flags 
    3.99              & (SHF_L4_64|SHF_L3_64|SHF_L2H_64|SHF_L2_64|SHF_L1_64)) == 0);
   3.100  #endif
   3.101 +    this_cpu(trace_shadow_path_flags) |= (result<<(TRCE_SFLAG_SET_CHANGED)); 
   3.102  
   3.103      return result;
   3.104  }
   3.105 @@ -1295,6 +1318,18 @@ static void shadow_unhook_mappings(struc
   3.106      }
   3.107  }
   3.108  
   3.109 +static inline void trace_shadow_prealloc_unpin(struct domain *d, mfn_t smfn)
   3.110 +{
   3.111 +    if ( tb_init_done )
   3.112 +    {
   3.113 +        /* Convert smfn to gfn */
   3.114 +        unsigned long gfn;
   3.115 +        ASSERT(mfn_valid(smfn));
   3.116 +        gfn = mfn_to_gfn(d, _mfn(mfn_to_shadow_page(smfn)->backpointer));
   3.117 +        __trace_var(TRC_SHADOW_PREALLOC_UNPIN, 0/*!tsc*/,
   3.118 +                    sizeof(gfn), (unsigned char*)&gfn);
   3.119 +    }
   3.120 +}
   3.121  
   3.122  /* Make sure there are at least count order-sized pages
   3.123   * available in the shadow page pool. */
   3.124 @@ -1327,6 +1362,7 @@ static void _shadow_prealloc(
   3.125          smfn = shadow_page_to_mfn(sp);
   3.126  
   3.127          /* Unpin this top-level shadow */
   3.128 +        trace_shadow_prealloc_unpin(d, smfn);
   3.129          sh_unpin(v, smfn);
   3.130  
   3.131          /* See if that freed up enough space */
   3.132 @@ -1343,6 +1379,7 @@ static void _shadow_prealloc(
   3.133          {
   3.134              if ( !pagetable_is_null(v2->arch.shadow_table[i]) )
   3.135              {
   3.136 +                TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_PREALLOC_UNHOOK);
   3.137                  shadow_unhook_mappings(v, 
   3.138                                 pagetable_get_mfn(v2->arch.shadow_table[i]));
   3.139  
   3.140 @@ -2200,6 +2237,16 @@ void sh_destroy_shadow(struct vcpu *v, m
   3.141      }    
   3.142  }
   3.143  
   3.144 +static inline void trace_shadow_wrmap_bf(mfn_t gmfn)
   3.145 +{
   3.146 +    if ( tb_init_done )
   3.147 +    {
   3.148 +        /* Convert gmfn to gfn */
   3.149 +        unsigned long gfn = mfn_to_gfn(current->domain, gmfn);
   3.150 +        __trace_var(TRC_SHADOW_WRMAP_BF, 0/*!tsc*/, sizeof(gfn), (unsigned char*)&gfn);
   3.151 +    }
   3.152 +}
   3.153 +
   3.154  /**************************************************************************/
   3.155  /* Remove all writeable mappings of a guest frame from the shadow tables 
   3.156   * Returns non-zero if we need to flush TLBs. 
   3.157 @@ -2265,6 +2312,8 @@ int sh_remove_write_access(struct vcpu *
   3.158           || (pg->u.inuse.type_info & PGT_count_mask) == 0 )
   3.159          return 0;
   3.160  
   3.161 +    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_WRMAP);
   3.162 +
   3.163      perfc_incr(shadow_writeable);
   3.164  
   3.165      /* If this isn't a "normal" writeable page, the domain is trying to 
   3.166 @@ -2285,11 +2334,14 @@ int sh_remove_write_access(struct vcpu *
   3.167           * and that mapping is likely to be in the current pagetable,
   3.168           * in the guest's linear map (on non-HIGHPTE linux and windows)*/
   3.169  
   3.170 -#define GUESS(_a, _h) do {                                                \
   3.171 +#define GUESS(_a, _h) do {                                              \
   3.172              if ( v->arch.paging.mode->shadow.guess_wrmap(v, (_a), gmfn) ) \
   3.173 -                perfc_incr(shadow_writeable_h_ ## _h);                   \
   3.174 -            if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 )          \
   3.175 -                return 1;                                                 \
   3.176 +                perfc_incr(shadow_writeable_h_ ## _h);                  \
   3.177 +            if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 )        \
   3.178 +            {                                                           \
   3.179 +                TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_WRMAP_GUESS_FOUND);   \
   3.180 +                return 1;                                               \
   3.181 +            }                                                           \
   3.182          } while (0)
   3.183  
   3.184          if ( level == 0 && fault_addr )
   3.185 @@ -2377,6 +2429,7 @@ int sh_remove_write_access(struct vcpu *
   3.186  #endif /* SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC */
   3.187      
   3.188      /* Brute-force search of all the shadows, by walking the hash */
   3.189 +    trace_shadow_wrmap_bf(gmfn);
   3.190      if ( level == 0 )
   3.191          perfc_incr(shadow_writeable_bf_1);
   3.192      else
     4.1 --- a/xen/arch/x86/mm/shadow/multi.c	Mon Sep 08 15:52:50 2008 +0100
     4.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Mon Sep 08 15:58:04 2008 +0100
     4.3 @@ -225,6 +225,7 @@ static uint32_t mandatory_flags(struct v
     4.4  static uint32_t set_ad_bits(void *guest_p, void *walk_p, int set_dirty)
     4.5  {
     4.6      guest_intpte_t old, new;
     4.7 +    int ret = 0;
     4.8  
     4.9      old = *(guest_intpte_t *)walk_p;
    4.10      new = old | _PAGE_ACCESSED | (set_dirty ? _PAGE_DIRTY : 0);
    4.11 @@ -234,10 +235,16 @@ static uint32_t set_ad_bits(void *guest_
    4.12           * into the guest table as well.  If the guest table has changed
    4.13           * under out feet then leave it alone. */
    4.14          *(guest_intpte_t *)walk_p = new;
    4.15 -        if ( cmpxchg(((guest_intpte_t *)guest_p), old, new) == old ) 
    4.16 -            return 1;
    4.17 +        if( cmpxchg(((guest_intpte_t *)guest_p), old, new) == old ) 
    4.18 +            ret = 1;
    4.19 +
    4.20 +        /* FIXME -- this code is longer than necessary */
    4.21 +        if(set_dirty)
    4.22 +            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SET_AD);
    4.23 +        else
    4.24 +            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SET_A);
    4.25      }
    4.26 -    return 0;
    4.27 +    return ret;
    4.28  }
    4.29  
    4.30  /* This validation is called with lock held, and after write permission
    4.31 @@ -1432,6 +1439,7 @@ static int shadow_set_l1e(struct vcpu *v
    4.32      {
    4.33          /* About to install a new reference */        
    4.34          if ( shadow_mode_refcounts(d) ) {
    4.35 +            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SHADOW_L1_GET_REF);
    4.36              if ( shadow_get_page_from_l1e(new_sl1e, d) == 0 ) 
    4.37              {
    4.38                  /* Doesn't look like a pagetable. */
    4.39 @@ -1461,6 +1469,7 @@ static int shadow_set_l1e(struct vcpu *v
    4.40          {
    4.41              shadow_vram_put_l1e(old_sl1e, sl1e, sl1mfn, d);
    4.42              shadow_put_page_from_l1e(old_sl1e, d);
    4.43 +            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SHADOW_L1_PUT_REF);
    4.44          } 
    4.45      }
    4.46      return flags;
    4.47 @@ -2896,6 +2905,7 @@ static inline void check_for_early_unsha
    4.48      {
    4.49          perfc_incr(shadow_early_unshadow);
    4.50          sh_remove_shadows(v, gmfn, 1, 0 /* Fast, can fail to unshadow */ );
    4.51 +        TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_EARLY_UNSHADOW);
    4.52      }
    4.53      v->arch.paging.shadow.last_emulated_mfn_for_unshadow = mfn_x(gmfn);
    4.54  #endif
    4.55 @@ -3012,6 +3022,132 @@ static void sh_prefetch(struct vcpu *v, 
    4.56  
    4.57  #endif /* SHADOW_OPTIMIZATIONS & SHOPT_PREFETCH */
    4.58  
    4.59 +#if GUEST_PAGING_LEVELS == 4
    4.60 +typedef u64 guest_va_t;
    4.61 +typedef u64 guest_pa_t;
    4.62 +#elif GUEST_PAGING_LEVELS == 3
    4.63 +typedef u32 guest_va_t;
    4.64 +typedef u64 guest_pa_t;
    4.65 +#else
    4.66 +typedef u32 guest_va_t;
    4.67 +typedef u32 guest_pa_t;
    4.68 +#endif
    4.69 +
    4.70 +static inline void trace_shadow_gen(u32 event, guest_va_t va)
    4.71 +{
    4.72 +    if ( tb_init_done )
    4.73 +    {
    4.74 +        event |= (GUEST_PAGING_LEVELS-2)<<8;
    4.75 +        __trace_var(event, 0/*!tsc*/, sizeof(va), (unsigned char*)&va);
    4.76 +    }
    4.77 +}
    4.78 +
    4.79 +static inline void trace_shadow_fixup(guest_l1e_t gl1e,
    4.80 +                                      guest_va_t va)
    4.81 +{
    4.82 +    if ( tb_init_done )
    4.83 +    {
    4.84 +        struct {
    4.85 +            /* for PAE, guest_l1e may be 64 while guest_va may be 32;
    4.86 +               so put it first for alignment sake. */
    4.87 +            guest_l1e_t gl1e;
    4.88 +            guest_va_t va;
    4.89 +            u32 flags;
    4.90 +        } __attribute__((packed)) d;
    4.91 +        u32 event;
    4.92 +
    4.93 +        event = TRC_SHADOW_FIXUP | ((GUEST_PAGING_LEVELS-2)<<8);
    4.94 +
    4.95 +        d.gl1e = gl1e;
    4.96 +        d.va = va;
    4.97 +        d.flags = this_cpu(trace_shadow_path_flags);
    4.98 +
    4.99 +        __trace_var(event, 0/*!tsc*/, sizeof(d), (unsigned char*)&d);
   4.100 +    }
   4.101 +}
   4.102 +                                          
   4.103 +static inline void trace_not_shadow_fault(guest_l1e_t gl1e,
   4.104 +                                          guest_va_t va)
   4.105 +{
   4.106 +    if ( tb_init_done )
   4.107 +    {
   4.108 +        struct {
   4.109 +            /* for PAE, guest_l1e may be 64 while guest_va may be 32;
   4.110 +               so put it first for alignment sake. */
   4.111 +            guest_l1e_t gl1e;
   4.112 +            guest_va_t va;
   4.113 +            u32 flags;
   4.114 +        } __attribute__((packed)) d;
   4.115 +        u32 event;
   4.116 +
   4.117 +        event = TRC_SHADOW_NOT_SHADOW | ((GUEST_PAGING_LEVELS-2)<<8);
   4.118 +
   4.119 +        d.gl1e = gl1e;
   4.120 +        d.va = va;
   4.121 +        d.flags = this_cpu(trace_shadow_path_flags);
   4.122 +
   4.123 +        __trace_var(event, 0/*!tsc*/, sizeof(d), (unsigned char*)&d);
   4.124 +    }
   4.125 +}
   4.126 +                                          
   4.127 +static inline void trace_shadow_emulate_other(u32 event,
   4.128 +                                                 guest_va_t va,
   4.129 +                                                 gfn_t gfn)
   4.130 +{
   4.131 +    if ( tb_init_done )
   4.132 +    {
   4.133 +        struct {
   4.134 +            /* for PAE, guest_l1e may be 64 while guest_va may be 32;
   4.135 +               so put it first for alignment sake. */
   4.136 +#if GUEST_PAGING_LEVELS == 2
   4.137 +            u32 gfn;
   4.138 +#else
   4.139 +            u64 gfn;
   4.140 +#endif
   4.141 +            guest_va_t va;
   4.142 +        } __attribute__((packed)) d;
   4.143 +
   4.144 +        event |= ((GUEST_PAGING_LEVELS-2)<<8);
   4.145 +
   4.146 +        d.gfn=gfn_x(gfn);
   4.147 +        d.va = va;
   4.148 +
   4.149 +        __trace_var(event, 0/*!tsc*/, sizeof(d), (unsigned char*)&d);
   4.150 +    }
   4.151 +}
   4.152 +
   4.153 +#if GUEST_PAGING_LEVELS == 3
   4.154 +static DEFINE_PER_CPU(guest_va_t,trace_emulate_initial_va);
   4.155 +static DEFINE_PER_CPU(int,trace_extra_emulation_count);
   4.156 +#endif
   4.157 +static DEFINE_PER_CPU(guest_pa_t,trace_emulate_write_val);
   4.158 +
   4.159 +static inline void trace_shadow_emulate(guest_l1e_t gl1e, unsigned long va)
   4.160 +{
   4.161 +    if ( tb_init_done )
   4.162 +    {
   4.163 +        struct {
   4.164 +            /* for PAE, guest_l1e may be 64 while guest_va may be 32;
   4.165 +               so put it first for alignment sake. */
   4.166 +            guest_l1e_t gl1e, write_val;
   4.167 +            guest_va_t va;
   4.168 +            unsigned flags:29, emulation_count:3;
   4.169 +        } __attribute__((packed)) d;
   4.170 +        u32 event;
   4.171 +
   4.172 +        event = TRC_SHADOW_EMULATE | ((GUEST_PAGING_LEVELS-2)<<8);
   4.173 +
   4.174 +        d.gl1e = gl1e;
   4.175 +        d.write_val.l1 = this_cpu(trace_emulate_write_val);
   4.176 +        d.va = va;
   4.177 +#if GUEST_PAGING_LEVELS == 3
   4.178 +        d.emulation_count = this_cpu(trace_extra_emulation_count);
   4.179 +#endif
   4.180 +        d.flags = this_cpu(trace_shadow_path_flags);
   4.181 +
   4.182 +        __trace_var(event, 0/*!tsc*/, sizeof(d), (unsigned char*)&d);
   4.183 +    }
   4.184 +}
   4.185  
   4.186  /**************************************************************************/
   4.187  /* Entry points into the shadow code */
   4.188 @@ -3027,8 +3163,8 @@ static int sh_page_fault(struct vcpu *v,
   4.189  {
   4.190      struct domain *d = v->domain;
   4.191      walk_t gw;
   4.192 -    gfn_t gfn;
   4.193 -    mfn_t gmfn, sl1mfn=_mfn(0);
   4.194 +    gfn_t gfn = _gfn(0);
   4.195 +    mfn_t gmfn, sl1mfn = _mfn(0);
   4.196      shadow_l1e_t sl1e, *ptr_sl1e;
   4.197      paddr_t gpa;
   4.198      struct sh_emulate_ctxt emul_ctxt;
   4.199 @@ -3132,6 +3268,7 @@ static int sh_page_fault(struct vcpu *v,
   4.200                  reset_early_unshadow(v);
   4.201                  perfc_incr(shadow_fault_fast_gnp);
   4.202                  SHADOW_PRINTK("fast path not-present\n");
   4.203 +                trace_shadow_gen(TRC_SHADOW_FAST_PROPAGATE, va);
   4.204                  return 0;
   4.205              }
   4.206              else
   4.207 @@ -3145,6 +3282,7 @@ static int sh_page_fault(struct vcpu *v,
   4.208              perfc_incr(shadow_fault_fast_mmio);
   4.209              SHADOW_PRINTK("fast path mmio %#"PRIpaddr"\n", gpa);
   4.210              reset_early_unshadow(v);
   4.211 +            trace_shadow_gen(TRC_SHADOW_FAST_MMIO, va);
   4.212              return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT)
   4.213                      ? EXCRET_fault_fixed : 0);
   4.214          }
   4.215 @@ -3155,6 +3293,7 @@ static int sh_page_fault(struct vcpu *v,
   4.216               * Retry and let the hardware give us the right fault next time. */
   4.217              perfc_incr(shadow_fault_fast_fail);
   4.218              SHADOW_PRINTK("fast path false alarm!\n");            
   4.219 +            trace_shadow_gen(TRC_SHADOW_FALSE_FAST_PATH, va);
   4.220              return EXCRET_fault_fixed;
   4.221          }
   4.222      }
   4.223 @@ -3190,7 +3329,7 @@ static int sh_page_fault(struct vcpu *v,
   4.224          perfc_incr(shadow_fault_bail_real_fault);
   4.225          SHADOW_PRINTK("not a shadow fault\n");
   4.226          reset_early_unshadow(v);
   4.227 -        return 0;
   4.228 +        goto propagate;
   4.229      }
   4.230  
   4.231      /* It's possible that the guest has put pagetables in memory that it has 
   4.232 @@ -3200,7 +3339,7 @@ static int sh_page_fault(struct vcpu *v,
   4.233      if ( unlikely(d->is_shutting_down) )
   4.234      {
   4.235          SHADOW_PRINTK("guest is shutting down\n");
   4.236 -        return 0;
   4.237 +        goto propagate;
   4.238      }
   4.239  
   4.240      /* What kind of access are we dealing with? */
   4.241 @@ -3218,7 +3357,7 @@ static int sh_page_fault(struct vcpu *v,
   4.242          SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"PRI_mfn"\n", 
   4.243                        gfn_x(gfn), mfn_x(gmfn));
   4.244          reset_early_unshadow(v);
   4.245 -        return 0;
   4.246 +        goto propagate;
   4.247      }
   4.248  
   4.249  #if (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB)
   4.250 @@ -3229,6 +3368,8 @@ static int sh_page_fault(struct vcpu *v,
   4.251  
   4.252      shadow_lock(d);
   4.253  
   4.254 +    TRACE_CLEAR_PATH_FLAGS;
   4.255 +    
   4.256      rc = gw_remove_write_accesses(v, va, &gw);
   4.257  
   4.258      /* First bit set: Removed write access to a page. */
   4.259 @@ -3281,6 +3422,7 @@ static int sh_page_fault(struct vcpu *v,
   4.260           * Get out of the fault handler immediately. */
   4.261          ASSERT(d->is_shutting_down);
   4.262          shadow_unlock(d);
   4.263 +        trace_shadow_gen(TRC_SHADOW_DOMF_DYING, va);
   4.264          return 0;
   4.265      }
   4.266  
   4.267 @@ -3383,6 +3525,7 @@ static int sh_page_fault(struct vcpu *v,
   4.268      d->arch.paging.log_dirty.fault_count++;
   4.269      reset_early_unshadow(v);
   4.270  
   4.271 +    trace_shadow_fixup(gw.l1e, va);
   4.272   done:
   4.273      sh_audit_gw(v, &gw);
   4.274      SHADOW_PRINTK("fixed\n");
   4.275 @@ -3405,6 +3548,8 @@ static int sh_page_fault(struct vcpu *v,
   4.276                        mfn_x(gmfn));
   4.277          perfc_incr(shadow_fault_emulate_failed);
   4.278          sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */);
   4.279 +        trace_shadow_emulate_other(TRC_SHADOW_EMULATE_UNSHADOW_USER,
   4.280 +                                      va, gfn);
   4.281          goto done;
   4.282      }
   4.283  
   4.284 @@ -3421,6 +3566,8 @@ static int sh_page_fault(struct vcpu *v,
   4.285      shadow_audit_tables(v);
   4.286      shadow_unlock(d);
   4.287  
   4.288 +    this_cpu(trace_emulate_write_val) = 0;
   4.289 +
   4.290  #if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION
   4.291   early_emulation:
   4.292  #endif
   4.293 @@ -3446,6 +3593,8 @@ static int sh_page_fault(struct vcpu *v,
   4.294                       "injection: cr2=%#lx, mfn=%#lx\n", 
   4.295                       va, mfn_x(gmfn));
   4.296              sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */);
   4.297 +            trace_shadow_emulate_other(TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ,
   4.298 +                                       va, gfn);
   4.299              return EXCRET_fault_fixed;
   4.300          }
   4.301      }
   4.302 @@ -3478,6 +3627,10 @@ static int sh_page_fault(struct vcpu *v,
   4.303           * to support more operations in the emulator.  More likely, 
   4.304           * though, this is a hint that this page should not be shadowed. */
   4.305          shadow_remove_all_shadows(v, gmfn);
   4.306 +
   4.307 +        trace_shadow_emulate_other(TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED,
   4.308 +                                   va, gfn);
   4.309 +        goto emulate_done;
   4.310      }
   4.311  
   4.312  #if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION
   4.313 @@ -3504,7 +3657,8 @@ static int sh_page_fault(struct vcpu *v,
   4.314  
   4.315  #if GUEST_PAGING_LEVELS == 3 /* PAE guest */
   4.316      if ( r == X86EMUL_OKAY ) {
   4.317 -        int i;
   4.318 +        int i, emulation_count=0;
   4.319 +        this_cpu(trace_emulate_initial_va) = va;
   4.320          /* Emulate up to four extra instructions in the hope of catching 
   4.321           * the "second half" of a 64-bit pagetable write. */
   4.322          for ( i = 0 ; i < 4 ; i++ )
   4.323 @@ -3513,10 +3667,12 @@ static int sh_page_fault(struct vcpu *v,
   4.324              v->arch.paging.last_write_was_pt = 0;
   4.325              r = x86_emulate(&emul_ctxt.ctxt, emul_ops);
   4.326              if ( r == X86EMUL_OKAY )
   4.327 -            {
   4.328 +            { 
   4.329 +                emulation_count++;
   4.330                  if ( v->arch.paging.last_write_was_pt )
   4.331                  {
   4.332                      perfc_incr(shadow_em_ex_pt);
   4.333 +                    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_EMULATION_2ND_PT_WRITTEN);
   4.334                      break; /* Don't emulate past the other half of the write */
   4.335                  }
   4.336                  else 
   4.337 @@ -3525,12 +3681,16 @@ static int sh_page_fault(struct vcpu *v,
   4.338              else
   4.339              {
   4.340                  perfc_incr(shadow_em_ex_fail);
   4.341 +                TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_EMULATION_LAST_FAILED);
   4.342                  break; /* Don't emulate again if we failed! */
   4.343              }
   4.344          }
   4.345 +        this_cpu(trace_extra_emulation_count)=emulation_count;
   4.346      }
   4.347  #endif /* PAE guest */
   4.348  
   4.349 +    trace_shadow_emulate(gw.l1e, va);
   4.350 + emulate_done:
   4.351      SHADOW_PRINTK("emulated\n");
   4.352      return EXCRET_fault_fixed;
   4.353  
   4.354 @@ -3543,6 +3703,7 @@ static int sh_page_fault(struct vcpu *v,
   4.355      shadow_audit_tables(v);
   4.356      reset_early_unshadow(v);
   4.357      shadow_unlock(d);
   4.358 +    trace_shadow_gen(TRC_SHADOW_MMIO, va);
   4.359      return (handle_mmio_with_translation(va, gpa >> PAGE_SHIFT)
   4.360              ? EXCRET_fault_fixed : 0);
   4.361  
   4.362 @@ -3552,6 +3713,10 @@ static int sh_page_fault(struct vcpu *v,
   4.363      shadow_audit_tables(v);
   4.364      reset_early_unshadow(v);
   4.365      shadow_unlock(d);
   4.366 +
   4.367 +propagate:
   4.368 +    trace_not_shadow_fault(gw.l1e, va);
   4.369 +
   4.370      return 0;
   4.371  }
   4.372  
   4.373 @@ -3990,7 +4155,7 @@ sh_detach_old_tables(struct vcpu *v)
   4.374              sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable);
   4.375          v->arch.paging.shadow.guest_vtable = NULL;
   4.376      }
   4.377 -#endif
   4.378 +#endif // !NDEBUG
   4.379  
   4.380  
   4.381      ////
   4.382 @@ -4446,6 +4611,7 @@ static int sh_guess_wrmap(struct vcpu *v
   4.383      sl1e = shadow_l1e_remove_flags(sl1e, _PAGE_RW);
   4.384      r = shadow_set_l1e(v, sl1p, sl1e, sl1mfn);
   4.385      ASSERT( !(r & SHADOW_SET_ERROR) );
   4.386 +    TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_WRMAP_GUESS_FOUND);
   4.387      return 1;
   4.388  }
   4.389  #endif
   4.390 @@ -4800,7 +4966,7 @@ static void emulate_unmap_dest(struct vc
   4.391  
   4.392  static int
   4.393  sh_x86_emulate_write(struct vcpu *v, unsigned long vaddr, void *src,
   4.394 -                      u32 bytes, struct sh_emulate_ctxt *sh_ctxt)
   4.395 +                     u32 bytes, struct sh_emulate_ctxt *sh_ctxt)
   4.396  {
   4.397      void *addr;
   4.398  
   4.399 @@ -4815,6 +4981,22 @@ sh_x86_emulate_write(struct vcpu *v, uns
   4.400      shadow_lock(v->domain);
   4.401      memcpy(addr, src, bytes);
   4.402  
   4.403 +    if ( tb_init_done )
   4.404 +    {
   4.405 +#if GUEST_PAGING_LEVELS == 3
   4.406 +        if ( vaddr == this_cpu(trace_emulate_initial_va) )
   4.407 +            memcpy(&this_cpu(trace_emulate_write_val), src, bytes);
   4.408 +        else if ( (vaddr & ~(0x7UL)) == this_cpu(trace_emulate_initial_va) )
   4.409 +        {
   4.410 +            TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_EMULATE_FULL_PT);
   4.411 +            memcpy(&this_cpu(trace_emulate_write_val),
   4.412 +                   (void *)(((unsigned long) addr) & ~(0x7UL)), GUEST_PTE_SIZE);
   4.413 +        }
   4.414 +#else
   4.415 +        memcpy(&this_cpu(trace_emulate_write_val), src, bytes);
   4.416 +#endif
   4.417 +    }
   4.418 +
   4.419      emulate_unmap_dest(v, addr, bytes, sh_ctxt);
   4.420      shadow_audit_tables(v);
   4.421      shadow_unlock(v->domain);
     5.1 --- a/xen/arch/x86/mm/shadow/private.h	Mon Sep 08 15:52:50 2008 +0100
     5.2 +++ b/xen/arch/x86/mm/shadow/private.h	Mon Sep 08 15:58:04 2008 +0100
     5.3 @@ -92,6 +92,43 @@ extern int shadow_audit_enable;
     5.4  #define SHADOW_DEBUG_LOGDIRTY          0
     5.5  
     5.6  /******************************************************************************
     5.7 + * Tracing
     5.8 + */
     5.9 +DECLARE_PER_CPU(uint32_t,trace_shadow_path_flags);
    5.10 +
    5.11 +#define TRACE_SHADOW_PATH_FLAG(_x)                      \
    5.12 +    do {                                                \
    5.13 +        this_cpu(trace_shadow_path_flags) |= (1<<(_x));      \
    5.14 +    } while(0)
    5.15 +
    5.16 +#define TRACE_CLEAR_PATH_FLAGS                  \
    5.17 +    this_cpu(trace_shadow_path_flags) = 0
    5.18 +
    5.19 +enum {
    5.20 +    TRCE_SFLAG_SET_AD,
    5.21 +    TRCE_SFLAG_SET_A,
    5.22 +    TRCE_SFLAG_SHADOW_L1_GET_REF,
    5.23 +    TRCE_SFLAG_SHADOW_L1_PUT_REF,
    5.24 +    TRCE_SFLAG_L2_PROPAGATE,
    5.25 +    TRCE_SFLAG_SET_CHANGED,
    5.26 +    TRCE_SFLAG_SET_FLUSH,
    5.27 +    TRCE_SFLAG_SET_ERROR,
    5.28 +    TRCE_SFLAG_DEMOTE,
    5.29 +    TRCE_SFLAG_PROMOTE,
    5.30 +    TRCE_SFLAG_WRMAP,
    5.31 +    TRCE_SFLAG_WRMAP_GUESS_FOUND,
    5.32 +    TRCE_SFLAG_WRMAP_BRUTE_FORCE,
    5.33 +    TRCE_SFLAG_EARLY_UNSHADOW,
    5.34 +    TRCE_SFLAG_EMULATION_2ND_PT_WRITTEN,
    5.35 +    TRCE_SFLAG_EMULATION_LAST_FAILED,
    5.36 +    TRCE_SFLAG_EMULATE_FULL_PT,
    5.37 +    TRCE_SFLAG_PREALLOC_UNHOOK,
    5.38 +    TRCE_SFLAG_UNSYNC,
    5.39 +    TRCE_SFLAG_OOS_FIXUP_ADD,
    5.40 +    TRCE_SFLAG_OOS_FIXUP_EVICT,
    5.41 +};
    5.42 +
    5.43 +/******************************************************************************
    5.44   * The shadow lock.
    5.45   *
    5.46   * This lock is per-domain.  It is intended to allow us to make atomic
    5.47 @@ -143,6 +180,12 @@ extern int shadow_audit_enable;
    5.48      } while (0)
    5.49  
    5.50  
    5.51 +/* Size (in bytes) of a guest PTE */
    5.52 +#if GUEST_PAGING_LEVELS >= 3
    5.53 +# define GUEST_PTE_SIZE 8
    5.54 +#else
    5.55 +# define GUEST_PTE_SIZE 4
    5.56 +#endif
    5.57  
    5.58  /******************************************************************************
    5.59   * Auditing routines 
     6.1 --- a/xen/common/trace.c	Mon Sep 08 15:52:50 2008 +0100
     6.2 +++ b/xen/common/trace.c	Mon Sep 08 15:58:04 2008 +0100
     6.3 @@ -148,6 +148,31 @@ static int tb_set_size(int size)
     6.4      return 0;
     6.5  }
     6.6  
     6.7 +int trace_will_trace_event(u32 event)
     6.8 +{
     6.9 +    if ( !tb_init_done )
    6.10 +        return 0;
    6.11 +
    6.12 +    /*
    6.13 +     * Copied from __trace_var()
    6.14 +     */
    6.15 +    if ( (tb_event_mask & event) == 0 )
    6.16 +        return 0;
    6.17 +
    6.18 +    /* match class */
    6.19 +    if ( ((tb_event_mask >> TRC_CLS_SHIFT) & (event >> TRC_CLS_SHIFT)) == 0 )
    6.20 +        return 0;
    6.21 +
    6.22 +    /* then match subclass */
    6.23 +    if ( (((tb_event_mask >> TRC_SUBCLS_SHIFT) & 0xf )
    6.24 +                & ((event >> TRC_SUBCLS_SHIFT) & 0xf )) == 0 )
    6.25 +        return 0;
    6.26 +
    6.27 +    if ( !cpu_isset(smp_processor_id(), tb_cpu_mask) )
    6.28 +        return 0;
    6.29 +
    6.30 +    return 1;
    6.31 +}
    6.32  
    6.33  /**
    6.34   * init_trace_bufs - performs initialization of the per-cpu trace buffers.
    6.35 @@ -407,7 +432,8 @@ void __trace_var(u32 event, int cycles, 
    6.36      int extra_word;
    6.37      int started_below_highwater;
    6.38  
    6.39 -    ASSERT(tb_init_done);
    6.40 +    if( !tb_init_done )
    6.41 +        return;
    6.42  
    6.43      /* Convert byte count into word count, rounding up */
    6.44      extra_word = (extra / sizeof(u32));
     7.1 --- a/xen/include/public/trace.h	Mon Sep 08 15:52:50 2008 +0100
     7.2 +++ b/xen/include/public/trace.h	Mon Sep 08 15:58:04 2008 +0100
     7.3 @@ -37,6 +37,7 @@
     7.4  #define TRC_HVM      0x0008f000    /* Xen HVM trace            */
     7.5  #define TRC_MEM      0x0010f000    /* Xen memory trace         */
     7.6  #define TRC_PV       0x0020f000    /* Xen PV traces            */
     7.7 +#define TRC_SHADOW   0x0040f000    /* Xen shadow tracing       */
     7.8  #define TRC_ALL      0x0ffff000
     7.9  #define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff)
    7.10  #define TRC_HD_CYCLE_FLAG (1UL<<31)
    7.11 @@ -93,6 +94,22 @@
    7.12    /* Indicates that addresses in trace record are 64 bits */
    7.13  #define TRC_64_FLAG               (0x100) 
    7.14  
    7.15 +#define TRC_SHADOW_NOT_SHADOW                 (TRC_SHADOW +  1)
    7.16 +#define TRC_SHADOW_FAST_PROPAGATE             (TRC_SHADOW +  2)
    7.17 +#define TRC_SHADOW_FAST_MMIO                  (TRC_SHADOW +  3)
    7.18 +#define TRC_SHADOW_FALSE_FAST_PATH            (TRC_SHADOW +  4)
    7.19 +#define TRC_SHADOW_MMIO                       (TRC_SHADOW +  5)
    7.20 +#define TRC_SHADOW_FIXUP                      (TRC_SHADOW +  6)
    7.21 +#define TRC_SHADOW_DOMF_DYING                 (TRC_SHADOW +  7)
    7.22 +#define TRC_SHADOW_EMULATE                    (TRC_SHADOW +  8)
    7.23 +#define TRC_SHADOW_EMULATE_UNSHADOW_USER      (TRC_SHADOW +  9)
    7.24 +#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ    (TRC_SHADOW + 10)
    7.25 +#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED (TRC_SHADOW + 11)
    7.26 +#define TRC_SHADOW_WRMAP_BF                   (TRC_SHADOW + 12)
    7.27 +#define TRC_SHADOW_PREALLOC_UNPIN             (TRC_SHADOW + 13)
    7.28 +#define TRC_SHADOW_RESYNC_FULL                (TRC_SHADOW + 14)
    7.29 +#define TRC_SHADOW_RESYNC_ONLY                (TRC_SHADOW + 15)
    7.30 +
    7.31  /* trace events per subclass */
    7.32  #define TRC_HVM_VMENTRY         (TRC_HVM_ENTRYEXIT + 0x01)
    7.33  #define TRC_HVM_VMEXIT          (TRC_HVM_ENTRYEXIT + 0x02)
     8.1 --- a/xen/include/xen/trace.h	Mon Sep 08 15:52:50 2008 +0100
     8.2 +++ b/xen/include/xen/trace.h	Mon Sep 08 15:58:04 2008 +0100
     8.3 @@ -34,6 +34,8 @@ void init_trace_bufs(void);
     8.4  /* used to retrieve the physical address of the trace buffers */
     8.5  int tb_control(struct xen_sysctl_tbuf_op *tbc);
     8.6  
     8.7 +int trace_will_trace_event(u32 event);
     8.8 +
     8.9  void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data);
    8.10  
    8.11  static inline void trace_var(u32 event, int cycles, int extra,