ia64/xen-unstable

changeset 6150:424166f4f3cf

Add some profiling support for writeable pagetables.

Signed-off-by: ian@xensource.com
author iap10@freefall.cl.cam.ac.uk
date Sat Aug 13 20:47:47 2005 +0000 (2005-08-13)
parents ab3813d38b20
children 8864f0be80c6 a8a88f85a3e6
files xen/Rules.mk xen/arch/x86/mm.c xen/arch/x86/traps.c xen/common/perfc.c xen/include/asm-x86/mm.h
line diff
     1.1 --- a/xen/Rules.mk	Fri Aug 12 16:05:37 2005 +0000
     1.2 +++ b/xen/Rules.mk	Sat Aug 13 20:47:47 2005 +0000
     1.3 @@ -2,7 +2,7 @@
     1.4  # If you change any of these configuration options then you must
     1.5  # 'make clean' before rebuilding.
     1.6  #
     1.7 -verbose     ?= n
     1.8 +verbose     ?= y
     1.9  debug       ?= n
    1.10  perfc       ?= n
    1.11  perfc_arrays?= n
     2.1 --- a/xen/arch/x86/mm.c	Fri Aug 12 16:05:37 2005 +0000
     2.2 +++ b/xen/arch/x86/mm.c	Sat Aug 13 20:47:47 2005 +0000
     2.3 @@ -2625,6 +2625,129 @@ int ptwr_debug = 0x0;
     2.4  #define PTWR_PRINTK(_f, _a...) ((void)0)
     2.5  #endif
     2.6  
     2.7 +
     2.8 +#ifdef PERF_ARRAYS
     2.9 +
    2.10 +/**************** writeable pagetables profiling functions *****************/
    2.11 +
    2.12 +#define ptwr_eip_buckets        256
    2.13 +
    2.14 +int ptwr_eip_stat_threshold[] = {1, 10, 50, 100, L1_PAGETABLE_ENTRIES};
    2.15 +
    2.16 +#define ptwr_eip_stat_thresholdN (sizeof(ptwr_eip_stat_threshold)/sizeof(int))
    2.17 +
    2.18 +struct {
    2.19 +    unsigned long eip;
    2.20 +    domid_t       id;
    2.21 +    u32           val[ptwr_eip_stat_thresholdN];
    2.22 +} typedef ptwr_eip_stat_t;
    2.23 +
    2.24 +ptwr_eip_stat_t ptwr_eip_stats[ptwr_eip_buckets];
    2.25 +
    2.26 +static inline unsigned int ptwr_eip_stat_hash( unsigned long eip, domid_t id )
    2.27 +{
    2.28 +    return (((unsigned long) id) ^ eip ^ (eip>>8) ^ (eip>>16) ^ (eip>24)) % 
    2.29 +	ptwr_eip_buckets;
    2.30 +}
    2.31 +
    2.32 +static void ptwr_eip_stat_inc(u32 *n)
    2.33 +{
    2.34 +    (*n)++;
    2.35 +    if(*n == 0)
    2.36 +    {
    2.37 +	(*n)=~0;
    2.38 +	/* rescale all buckets */
    2.39 +	int i;
    2.40 +	for(i=0;i<ptwr_eip_buckets;i++)
    2.41 +	{
    2.42 +	    int j;
    2.43 +	    for(j=0;j<ptwr_eip_stat_thresholdN;j++)
    2.44 +		ptwr_eip_stats[i].val[j] = 
    2.45 +		    (((u64)ptwr_eip_stats[i].val[j])+1)>>1;
    2.46 +	}
    2.47 +    }
    2.48 +}
    2.49 +
    2.50 +static void ptwr_eip_stat_update( unsigned long eip, domid_t id, int modified )
    2.51 +{
    2.52 +    int i, b;
    2.53 +
    2.54 +    i = b = ptwr_eip_stat_hash( eip, id );
    2.55 +
    2.56 +    do
    2.57 +    {
    2.58 +	if (!ptwr_eip_stats[i].eip)
    2.59 +	{ /* doesn't exist */
    2.60 +	    ptwr_eip_stats[i].eip = eip;
    2.61 +	    ptwr_eip_stats[i].id = id;
    2.62 +	    memset(ptwr_eip_stats[i].val,0, sizeof(ptwr_eip_stats[i].val));
    2.63 +	}
    2.64 +
    2.65 +	if (ptwr_eip_stats[i].eip == eip)
    2.66 +	{
    2.67 +	    int j;
    2.68 +	    for(j=0;j<ptwr_eip_stat_thresholdN;j++)
    2.69 +	    {
    2.70 +		if(modified <= ptwr_eip_stat_threshold[j])
    2.71 +		{
    2.72 +		    break;
    2.73 +		}
    2.74 +	    }
    2.75 +	    BUG_ON(j>=ptwr_eip_stat_thresholdN);
    2.76 +	    ptwr_eip_stat_inc(&(ptwr_eip_stats[i].val[j]));    
    2.77 +	    return;
    2.78 +	}
    2.79 +	i = (i+1) % ptwr_eip_buckets;
    2.80 +    }
    2.81 +    while(i!=b);
    2.82 +   
    2.83 +    printk("ptwr_eip_stat: too many EIPs in use!\n");
    2.84 +    
    2.85 +    ptwr_eip_stat_print();
    2.86 +    ptwr_eip_stat_reset();
    2.87 +}
    2.88 +
    2.89 +void ptwr_eip_stat_reset()
    2.90 +{
    2.91 +    memset( ptwr_eip_stats, 0, sizeof(ptwr_eip_stats));
    2.92 +}
    2.93 +
    2.94 +void ptwr_eip_stat_print()
    2.95 +{
    2.96 +    struct domain *e;
    2.97 +    domid_t d;
    2.98 +
    2.99 +    for_each_domain(e)
   2.100 +    {
   2.101 +	int i;
   2.102 +	d = e->domain_id;
   2.103 +
   2.104 +	for(i=0;i<ptwr_eip_buckets;i++)
   2.105 +	{
   2.106 +	    if ( ptwr_eip_stats[i].eip && ptwr_eip_stats[i].id == d )
   2.107 +	    {
   2.108 +		int j;
   2.109 +		printk("D %d  eip %08lx ",
   2.110 +		       ptwr_eip_stats[i].id, ptwr_eip_stats[i].eip );
   2.111 +
   2.112 +		for(j=0;j<ptwr_eip_stat_thresholdN;j++)
   2.113 +		    printk("<=%u %4u \t",
   2.114 +			   ptwr_eip_stat_threshold[j],
   2.115 +			   ptwr_eip_stats[i].val[j] );
   2.116 +		printk("\n");
   2.117 +	    }	
   2.118 +	}
   2.119 +    }
   2.120 +}
   2.121 +
   2.122 +#else /* PERF_ARRAYS */
   2.123 +
   2.124 +#define ptwr_eip_stat_update( eip, id, modified ) ((void)0)
   2.125 +
   2.126 +#endif
   2.127 +
   2.128 +/*******************************************************************/
   2.129 +
   2.130  /* Re-validate a given p.t. page, given its prior snapshot */
   2.131  int revalidate_l1(
   2.132      struct domain *d, l1_pgentry_t *l1page, l1_pgentry_t *snapshot)
   2.133 @@ -2742,6 +2865,7 @@ void ptwr_flush(struct domain *d, const 
   2.134      modified = revalidate_l1(d, pl1e, d->arch.ptwr[which].page);
   2.135      unmap_domain_page(pl1e);
   2.136      perfc_incr_histo(wpt_updates, modified, PT_UPDATES);
   2.137 +    ptwr_eip_stat_update(  d->arch.ptwr[which].eip, d->domain_id, modified);
   2.138      d->arch.ptwr[which].prev_nr_updates  = modified;
   2.139  
   2.140      /*
   2.141 @@ -2897,7 +3021,8 @@ static struct x86_mem_emulator ptwr_mem_
   2.142  };
   2.143  
   2.144  /* Write page fault handler: check if guest is trying to modify a PTE. */
   2.145 -int ptwr_do_page_fault(struct domain *d, unsigned long addr)
   2.146 +int ptwr_do_page_fault(struct domain *d, unsigned long addr, 
   2.147 +		       struct cpu_user_regs *regs)
   2.148  {
   2.149      unsigned long    pfn;
   2.150      struct pfn_info *page;
   2.151 @@ -2933,6 +3058,10 @@ int ptwr_do_page_fault(struct domain *d,
   2.152          return 0;
   2.153      }
   2.154  
   2.155 +#if 0 /* Leave this in as useful for debugging */ 
   2.156 +    goto emulate; 
   2.157 +#endif
   2.158 +
   2.159      /* Get the L2 index at which this L1 p.t. is always mapped. */
   2.160      l2_idx = page->u.inuse.type_info & PGT_va_mask;
   2.161      if ( unlikely(l2_idx >= PGT_va_unknown) )
   2.162 @@ -3002,7 +3131,11 @@ int ptwr_do_page_fault(struct domain *d,
   2.163      d->arch.ptwr[which].l1va   = addr | 1;
   2.164      d->arch.ptwr[which].l2_idx = l2_idx;
   2.165      d->arch.ptwr[which].vcpu   = current;
   2.166 -    
   2.167 +
   2.168 +#ifdef PERF_ARRAYS
   2.169 +    d->arch.ptwr[which].eip    = regs->eip;
   2.170 +#endif
   2.171 +
   2.172      /* For safety, disconnect the L1 p.t. page from current space. */
   2.173      if ( which == PTWR_PT_ACTIVE )
   2.174      {
     3.1 --- a/xen/arch/x86/traps.c	Fri Aug 12 16:05:37 2005 +0000
     3.2 +++ b/xen/arch/x86/traps.c	Sat Aug 13 20:47:47 2005 +0000
     3.3 @@ -438,7 +438,7 @@ asmlinkage int do_page_fault(struct cpu_
     3.4               &&
     3.5               KERNEL_MODE(v, regs) &&
     3.6               ((regs->error_code & 3) == 3) && /* write-protection fault */
     3.7 -             ptwr_do_page_fault(d, addr) )
     3.8 +             ptwr_do_page_fault(d, addr, regs) )
     3.9          {
    3.10              UNLOCK_BIGLOCK(d);
    3.11              return EXCRET_fault_fixed;
     4.1 --- a/xen/common/perfc.c	Fri Aug 12 16:05:37 2005 +0000
     4.2 +++ b/xen/common/perfc.c	Sat Aug 13 20:47:47 2005 +0000
     4.3 @@ -7,6 +7,7 @@
     4.4  #include <xen/spinlock.h>
     4.5  #include <public/dom0_ops.h>
     4.6  #include <asm/uaccess.h>
     4.7 +#include <xen/mm.h>
     4.8  
     4.9  #undef  PERFCOUNTER
    4.10  #undef  PERFCOUNTER_CPU
    4.11 @@ -81,6 +82,10 @@ void perfc_printall(unsigned char key)
    4.12          }
    4.13          printk("\n");
    4.14      }
    4.15 +
    4.16 +#ifdef PERF_ARRAYS
    4.17 +    ptwr_eip_stat_print();
    4.18 +#endif
    4.19  }
    4.20  
    4.21  void perfc_reset(unsigned char key)
    4.22 @@ -118,6 +123,10 @@ void perfc_reset(unsigned char key)
    4.23              break;
    4.24          }
    4.25      }
    4.26 +
    4.27 +#ifdef PERF_ARRAYS
    4.28 +    ptwr_eip_stat_reset();
    4.29 +#endif
    4.30  }
    4.31  
    4.32  static dom0_perfc_desc_t perfc_d[NR_PERFCTRS];
     5.1 --- a/xen/include/asm-x86/mm.h	Fri Aug 12 16:05:37 2005 +0000
     5.2 +++ b/xen/include/asm-x86/mm.h	Sat Aug 13 20:47:47 2005 +0000
     5.3 @@ -316,6 +316,9 @@ struct ptwr_info {
     5.4      unsigned int prev_nr_updates;
     5.5      /* Exec domain which created writable mapping. */
     5.6      struct vcpu *vcpu;
     5.7 +    /* EIP of the address which took the original write fault
     5.8 +       used for stats collection only */
     5.9 +    unsigned long eip;
    5.10  };
    5.11  
    5.12  #define PTWR_PT_ACTIVE 0
    5.13 @@ -327,7 +330,8 @@ struct ptwr_info {
    5.14  int  ptwr_init(struct domain *);
    5.15  void ptwr_destroy(struct domain *);
    5.16  void ptwr_flush(struct domain *, const int);
    5.17 -int  ptwr_do_page_fault(struct domain *, unsigned long);
    5.18 +int  ptwr_do_page_fault(struct domain *, unsigned long, 
    5.19 +			struct cpu_user_regs *);
    5.20  int  revalidate_l1(struct domain *, l1_pgentry_t *, l1_pgentry_t *);
    5.21  
    5.22  void cleanup_writable_pagetable(struct domain *d);
    5.23 @@ -353,6 +357,18 @@ void audit_domains(void);
    5.24  
    5.25  #endif
    5.26  
    5.27 +#ifdef PERF_ARRAYS
    5.28 +
    5.29 +void ptwr_eip_stat_reset();
    5.30 +void ptwr_eip_stat_print();
    5.31 +
    5.32 +#else
    5.33 +
    5.34 +#define ptwr_eip_stat_reset() ((void)0)
    5.35 +#define ptwr_eip_stat_print() ((void)0)
    5.36 +
    5.37 +#endif
    5.38 +
    5.39  int new_guest_cr3(unsigned long pfn);
    5.40  
    5.41  void propagate_page_fault(unsigned long addr, u16 error_code);