ia64/xen-unstable

changeset 4496:5c90ed25ab58

bitkeeper revision 1.1278.1.1 (4254b244uWvJejlkGeqN8mp1CLtN5w)

New Xen trace buffer implementation that avoids blocking
interrupts. Add support for trace buffer CPU mask and
event mask. Add support for trace classes. New DOM0 trace
buffer hypercall. Fix 'xentrace' signal handler bug.

Signed-off-by: bin.ren@cl.cam.ac.uk
author bren@br260.wolfson.cam.ac.uk
date Thu Apr 07 04:08:36 2005 +0000 (2005-04-07)
parents 28c4d8ceff3c
children 6a9598f401d9
files tools/xentrace/formats tools/xentrace/xentrace.c xen/common/dom0_ops.c xen/common/schedule.c xen/common/trace.c xen/include/asm-x86/vmx.h xen/include/public/dom0_ops.h xen/include/public/trace.h xen/include/xen/trace.h
line diff
     1.1 --- a/tools/xentrace/formats	Wed Apr 06 12:46:25 2005 +0000
     1.2 +++ b/tools/xentrace/formats	Thu Apr 07 04:08:36 2005 +0000
     1.3 @@ -1,34 +1,17 @@
     1.4 -0x00010000	CPU%(cpu)d	%(tsc)d		sched_add_domain	[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
     1.5 -0x00010001	CPU%(cpu)d	%(tsc)d		sched_rem_domain	[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
     1.6 -0x00010002	CPU%(cpu)d	%(tsc)d		domain_sleep		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
     1.7 -0x00010003	CPU%(cpu)d	%(tsc)d		domain_wake		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
     1.8 -0x00010004	CPU%(cpu)d	%(tsc)d		do_yield		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
     1.9 -0x00010005	CPU%(cpu)d	%(tsc)d		do_block		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
    1.10 -0x00010006	CPU%(cpu)d	%(tsc)d		domain_shutdown		[ domid = 0x%(1)08x, edomid = 0x%(2)08x, reason = 0x%(3)08x ]
    1.11 -0x00010007	CPU%(cpu)d	%(tsc)d		sched_ctl
    1.12 -0x00010008	CPU%(cpu)d	%(tsc)d		sched_adjdom		[ domid = 0x%(1)08x ]
    1.13 -0x00010009	CPU%(cpu)d	%(tsc)d		__enter_scheduler	[ prev<domid:edomid> = 0x%(1)08x : 0x%(2)08x, next<domid:edomid> = 0x%(3)08x : 0x%(4)08x ]
    1.14 -0x0001000A	CPU%(cpu)d	%(tsc)d		s_timer_fn
    1.15 -0x0001000B	CPU%(cpu)d	%(tsc)d		t_timer_fn
    1.16 -0x0001000C	CPU%(cpu)d	%(tsc)d		dom_timer_fn
    1.17 -
    1.18 +0x00020001	CPU%(cpu)d	%(tsc)d		sched_add_domain	[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
    1.19 +0x00020002	CPU%(cpu)d	%(tsc)d		sched_rem_domain	[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
    1.20 +0x00020003	CPU%(cpu)d	%(tsc)d		domain_sleep		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
    1.21 +0x00020004	CPU%(cpu)d	%(tsc)d		domain_wake		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
    1.22 +0x00020005	CPU%(cpu)d	%(tsc)d		do_yield		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
    1.23 +0x00020006	CPU%(cpu)d	%(tsc)d		do_block		[ domid = 0x%(1)08x, edomid = 0x%(2)08x ]
    1.24 +0x00020007	CPU%(cpu)d	%(tsc)d		domain_shutdown		[ domid = 0x%(1)08x, edomid = 0x%(2)08x, reason = 0x%(3)08x ]
    1.25 +0x00020008	CPU%(cpu)d	%(tsc)d		sched_ctl
    1.26 +0x00020009	CPU%(cpu)d	%(tsc)d		sched_adjdom		[ domid = 0x%(1)08x ]
    1.27 +0x0002000a	CPU%(cpu)d	%(tsc)d		__enter_scheduler	[ prev<domid:edomid> = 0x%(1)08x : 0x%(2)08x, next<domid:edomid> = 0x%(3)08x : 0x%(4)08x ]
    1.28 +0x0002000B	CPU%(cpu)d	%(tsc)d		s_timer_fn
    1.29 +0x0002000c	CPU%(cpu)d	%(tsc)d		t_timer_fn
    1.30 +0x0002000d	CPU%(cpu)d	%(tsc)d		dom_timer_fn
    1.31  
    1.32 -0x00020008	CPU%(cpu)d	%(tsc)d		enter: dom0_create_dom
    1.33 -0x00030008	CPU%(cpu)d	%(tsc)d		leave: dom0_create_dom
    1.34 -0x00020009	CPU%(cpu)d	%(tsc)d		enter: dom0_destroy_dom
    1.35 -0x00030009	CPU%(cpu)d	%(tsc)d		leave: dom0_destroy_dom
    1.36 -0x0002000A	CPU%(cpu)d	%(tsc)d		enter: dom0_start_dom
    1.37 -0x0003000A	CPU%(cpu)d	%(tsc)d		leave: dom0_start_dom
    1.38 -0x0002000B	CPU%(cpu)d	%(tsc)d		enter: dom0_stop_dom
    1.39 -0x0003000B	CPU%(cpu)d	%(tsc)d		leave: dom0_stop_dom
    1.40 -0x0002000C	CPU%(cpu)d	%(tsc)d		enter: dom0_getinfo
    1.41 -0x0003000C	CPU%(cpu)d	%(tsc)d		leave: dom0_getinfo
    1.42 -0x0002000D	CPU%(cpu)d	%(tsc)d		enter: dom0_build
    1.43 -0x0003000D	CPU%(cpu)d	%(tsc)d		leave: dom0_build
    1.44 -0x00020019	CPU%(cpu)d	%(tsc)d		enter: dom0_shadow_op
    1.45 -0x00030019	CPU%(cpu)d	%(tsc)d		leave: dom0_shadow_op
    1.46 -
    1.47 -
    1.48 -0x00040001	CPU%(cpu)d      %(tsc)d		VMX_VMEXIT		[ domid = 0x%(1)08x, eip = 0x%(2)08x, reason = 0x%(3)08x ]
    1.49 -0x00040002	CPU%(cpu)d      %(tsc)d		VMX_VECTOR		[ domid = 0x%(1)08x, eip = 0x%(2)08x, vector = 0x%(3)08x ]
    1.50 -0x00040003	CPU%(cpu)d      %(tsc)d		VMX_INT			[ domid = 0x%(1)08x, trap = 0x%(2)08x, va = 0x%(3)08x ]
    1.51 \ No newline at end of file
    1.52 +0x00080001	CPU%(cpu)d      %(tsc)d		VMX_VMEXIT		[ domid = 0x%(1)08x, eip = 0x%(2)08x, reason = 0x%(3)08x ]
    1.53 +0x00080002	CPU%(cpu)d      %(tsc)d		VMX_VECTOR		[ domid = 0x%(1)08x, eip = 0x%(2)08x, vector = 0x%(3)08x ]
    1.54 +0x00080003	CPU%(cpu)d      %(tsc)d		VMX_INT			[ domid = 0x%(1)08x, trap = 0x%(2)08x, va = 0x%(3)08x ]
     2.1 --- a/tools/xentrace/xentrace.c	Wed Apr 06 12:46:25 2005 +0000
     2.2 +++ b/tools/xentrace/xentrace.c	Thu Apr 07 04:08:36 2005 +0000
     2.3 @@ -11,10 +11,10 @@
     2.4  
     2.5  #include <time.h>
     2.6  #include <stdlib.h>
     2.7 +#include <stdio.h>
     2.8  #include <sys/mman.h>
     2.9 -#include <stdio.h>
    2.10 +#include <sys/stat.h>
    2.11  #include <sys/types.h>
    2.12 -#include <sys/stat.h>
    2.13  #include <fcntl.h>
    2.14  #include <unistd.h>
    2.15  #include <errno.h>
    2.16 @@ -101,8 +101,9 @@ void get_tbufs(unsigned long *mach_addr,
    2.17      dom0_op_t op;                        /* dom0 op we'll build             */
    2.18      int xc_handle = xc_interface_open(); /* for accessing control interface */
    2.19  
    2.20 -    op.cmd = DOM0_GETTBUFS;
    2.21 +    op.cmd = DOM0_TBUFCONTROL;
    2.22      op.interface_version = DOM0_INTERFACE_VERSION;
    2.23 +    op.u.tbufcontrol.op  = DOM0_TBUF_GET_INFO;
    2.24  
    2.25      ret = do_dom0_op(xc_handle, &op);
    2.26  
    2.27 @@ -114,8 +115,8 @@ void get_tbufs(unsigned long *mach_addr,
    2.28          exit(EXIT_FAILURE);
    2.29      }
    2.30  
    2.31 -    *mach_addr = op.u.gettbufs.mach_addr;
    2.32 -    *size      = op.u.gettbufs.size;
    2.33 +    *mach_addr = op.u.tbufcontrol.mach_addr;
    2.34 +    *size      = op.u.tbufcontrol.size;
    2.35  }
    2.36  
    2.37  /**
    2.38 @@ -141,8 +142,8 @@ struct t_buf *map_tbufs(unsigned long tb
    2.39      }
    2.40  
    2.41      tbufs_mapped = xc_map_foreign_range(xc_handle, 0 /* Dom 0 ID */,
    2.42 -					size * num, PROT_READ,
    2.43 -					tbufs_mach >> PAGE_SHIFT);
    2.44 +                                        size * num, PROT_READ,
    2.45 +                                        tbufs_mach >> PAGE_SHIFT);
    2.46  
    2.47      xc_interface_close(xc_handle);
    2.48  
    2.49 @@ -152,7 +153,7 @@ struct t_buf *map_tbufs(unsigned long tb
    2.50          exit(EXIT_FAILURE);
    2.51      }
    2.52  
    2.53 -    return (struct t_buf *)tbufs_mapped;
    2.54 +    return tbufs_mapped;
    2.55  }
    2.56  
    2.57  
    2.58 @@ -181,8 +182,7 @@ struct t_buf **init_bufs_ptrs(void *bufs
    2.59      /* initialise pointers to the trace buffers - given the size of a trace
    2.60       * buffer and the value of bufs_maped, we can easily calculate these */
    2.61      for ( i = 0; i<num; i++ )
    2.62 -        user_ptrs[i] = (struct t_buf *)(
    2.63 -            (unsigned long)bufs_mapped + size * i);
    2.64 +        user_ptrs[i] = (struct t_buf *)((unsigned long)bufs_mapped + size * i);
    2.65  
    2.66      return user_ptrs;
    2.67  }
    2.68 @@ -214,9 +214,9 @@ struct t_rec **init_rec_ptrs(unsigned lo
    2.69          exit(EXIT_FAILURE);
    2.70      }
    2.71  
    2.72 -    for ( i = 0; i<num; i++ )
    2.73 -        data[i] = (struct t_rec *)(meta[i]->data - tbufs_mach
    2.74 -				   + (unsigned long)tbufs_mapped);
    2.75 +    for ( i = 0; i < num; i++ )
    2.76 +        data[i] = (struct t_rec *)(meta[i]->rec_addr - tbufs_mach
    2.77 +                                   + (unsigned long)tbufs_mapped);
    2.78  
    2.79      return data;
    2.80  }
    2.81 @@ -242,7 +242,7 @@ unsigned long *init_tail_idxs(struct t_b
    2.82      }
    2.83      
    2.84      for ( i = 0; i<num; i++ )
    2.85 -        tails[i] = bufs[i]->head;
    2.86 +        tails[i] = atomic_read(&bufs[i]->rec_idx);
    2.87  
    2.88      return tails;
    2.89  }
    2.90 @@ -299,7 +299,7 @@ int monitor_tbufs(FILE *logfile)
    2.91      get_tbufs(&tbufs_mach, &size);
    2.92      tbufs_mapped = map_tbufs(tbufs_mach, num, size);
    2.93  
    2.94 -    size_in_recs = (size / sizeof(struct t_rec) )-1;
    2.95 +    size_in_recs = (size - sizeof(struct t_buf)) / sizeof(struct t_rec);
    2.96  
    2.97      /* build arrays of convenience ptrs */
    2.98      meta  = init_bufs_ptrs (tbufs_mapped, num, size);
    2.99 @@ -310,11 +310,11 @@ int monitor_tbufs(FILE *logfile)
   2.100      while ( !interrupted )
   2.101      {
   2.102          for ( i = 0; ( i < num ) && !interrupted; i++ )
   2.103 -	    while( cons[i] != meta[i]->head )
   2.104 -	    {
   2.105 -		write_rec(i, data[i] + (cons[i] % size_in_recs), logfile);
   2.106 -		cons[i]++;
   2.107 -	    }
   2.108 +            while( cons[i] != atomic_read(&meta[i]->rec_idx) )
   2.109 +            {
   2.110 +                write_rec(i, data[i] + cons[i], logfile);
   2.111 +                cons[i] = (cons[i] + 1) % size_in_recs;
   2.112 +            }
   2.113  
   2.114          nanosleep(&opts.poll_sleep, NULL);
   2.115      }
   2.116 @@ -445,9 +445,11 @@ int main(int argc, char **argv)
   2.117      
   2.118      /* ensure that if we get a signal, we'll do cleanup, then exit */
   2.119      act.sa_handler = close_handler;
   2.120 -    sigaction(SIGHUP,  &act, 0);
   2.121 -    sigaction(SIGTERM, &act, 0);
   2.122 -    sigaction(SIGINT,  &act, 0);
   2.123 +    act.sa_flags = 0;
   2.124 +    sigemptyset(&act.sa_mask);
   2.125 +    sigaction(SIGHUP,  &act, NULL);
   2.126 +    sigaction(SIGTERM, &act, NULL);
   2.127 +    sigaction(SIGINT,  &act, NULL);
   2.128  
   2.129      ret = monitor_tbufs(logfile);
   2.130  
     3.1 --- a/xen/common/dom0_ops.c	Wed Apr 06 12:46:25 2005 +0000
     3.2 +++ b/xen/common/dom0_ops.c	Thu Apr 07 04:08:36 2005 +0000
     3.3 @@ -19,9 +19,6 @@
     3.4  #include <xen/physdev.h>
     3.5  #include <public/sched_ctl.h>
     3.6  
     3.7 -#define TRC_DOM0OP_ENTER_BASE  0x00020000
     3.8 -#define TRC_DOM0OP_LEAVE_BASE  0x00030000
     3.9 -
    3.10  extern unsigned int alloc_new_dom_mem(struct domain *, unsigned int);
    3.11  extern long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op);
    3.12  extern void arch_getdomaininfo_ctxt(
    3.13 @@ -385,9 +382,9 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
    3.14      break;
    3.15  
    3.16  #ifdef TRACE_BUFFER
    3.17 -    case DOM0_GETTBUFS:
    3.18 +    case DOM0_TBUFCONTROL:
    3.19      {
    3.20 -        ret = get_tb_info(&op->u.gettbufs);
    3.21 +        ret = tb_control(&op->u.tbufcontrol);
    3.22          copy_to_user(u_dom0_op, op, sizeof(*op));
    3.23      }
    3.24      break;
     4.1 --- a/xen/common/schedule.c	Wed Apr 06 12:46:25 2005 +0000
     4.2 +++ b/xen/common/schedule.c	Thu Apr 07 04:08:36 2005 +0000
     4.3 @@ -42,24 +42,6 @@ string_param("sched", opt_sched);
     4.4  
     4.5  #define TIME_SLOP      (s32)MICROSECS(50)     /* allow time to slip a bit */
     4.6  
     4.7 -/*
     4.8 - * TODO MAW pull trace-related #defines out of here and into an auto-generated
     4.9 - * header file later on!
    4.10 - */
    4.11 -#define TRC_SCHED_DOM_ADD             0x00010000
    4.12 -#define TRC_SCHED_DOM_REM             0x00010001
    4.13 -#define TRC_SCHED_SLEEP               0x00010002
    4.14 -#define TRC_SCHED_WAKE                0x00010003
    4.15 -#define TRC_SCHED_YIELD               0x00010004
    4.16 -#define TRC_SCHED_BLOCK               0x00010005
    4.17 -#define TRC_SCHED_SHUTDOWN            0x00010006
    4.18 -#define TRC_SCHED_CTL                 0x00010007
    4.19 -#define TRC_SCHED_ADJDOM              0x00010008
    4.20 -#define TRC_SCHED_SWITCH              0x00010009
    4.21 -#define TRC_SCHED_S_TIMER_FN          0x0001000A
    4.22 -#define TRC_SCHED_T_TIMER_FN          0x0001000B
    4.23 -#define TRC_SCHED_DOM_TIMER_FN        0x0001000C
    4.24 -
    4.25  /* Various timer handlers. */
    4.26  static void s_timer_fn(unsigned long unused);
    4.27  static void t_timer_fn(unsigned long unused);
     5.1 --- a/xen/common/trace.c	Wed Apr 06 12:46:25 2005 +0000
     5.2 +++ b/xen/common/trace.c	Thu Apr 07 04:08:36 2005 +0000
     5.3 @@ -8,6 +8,8 @@
     5.4   * Author: Mark Williamson, mark.a.williamson@intel.com
     5.5   * Date:   January 2004
     5.6   *
     5.7 + * Copyright (C) 2005 Bin Ren
     5.8 + *
     5.9   * The trace buffer code is designed to allow debugging traces of Xen to be
    5.10   * generated on UP / SMP machines.  Each trace entry is timestamped so that
    5.11   * it's possible to reconstruct a chronological record of trace events.
    5.12 @@ -39,6 +41,11 @@ struct t_buf *t_bufs[NR_CPUS];
    5.13  /* a flag recording whether initialisation has been done */
    5.14  int tb_init_done = 0;
    5.15  
    5.16 +/* which CPUs tracing is enabled on */
    5.17 +unsigned long tb_cpu_mask = (~0UL);
    5.18 +
    5.19 +/* which tracing events are enabled */
    5.20 +u32 tb_event_mask = TRC_ALL;
    5.21  /**
    5.22   * init_trace_bufs - performs initialisation of the per-cpu trace buffers.
    5.23   *
    5.24 @@ -69,25 +76,18 @@ void init_trace_bufs(void)
    5.25      }
    5.26  
    5.27      /* Share pages so that xentrace can map them. */
    5.28 -
    5.29      for ( i = 0; i < nr_pages; i++ )
    5.30 -        SHARE_PFN_WITH_DOMAIN(virt_to_page(rawbuf+(i*PAGE_SIZE)), dom0);
    5.31 +        SHARE_PFN_WITH_DOMAIN(virt_to_page(rawbuf + i * PAGE_SIZE), dom0);
    5.32      
    5.33      for ( i = 0; i < smp_num_cpus; i++ )
    5.34      {
    5.35          buf = t_bufs[i] = (struct t_buf *)&rawbuf[i*opt_tbuf_size*PAGE_SIZE];
    5.36          
    5.37 -        /* For use in Xen. */
    5.38 -        buf->vdata    = (struct t_rec *)(buf+1);
    5.39 -        buf->head_ptr = buf->vdata;
    5.40 -        
    5.41 -        /* For use in user space. */
    5.42 -        buf->data = __pa(buf->vdata);
    5.43 -        buf->head = 0;
    5.44 -
    5.45 -        /* For use in both. */
    5.46 -        buf->size = (opt_tbuf_size * PAGE_SIZE - sizeof(struct t_buf))
    5.47 -            / sizeof(struct t_rec);
    5.48 +        _atomic_set(buf->rec_idx, 0);
    5.49 +        buf->rec_num  = (opt_tbuf_size * PAGE_SIZE - sizeof(struct t_buf))
    5.50 +                        / sizeof(struct t_rec);
    5.51 +        buf->rec      = (struct t_rec *)(buf + 1);
    5.52 +        buf->rec_addr = __pa(buf->rec);
    5.53      }
    5.54  
    5.55      printk("Xen trace buffers: initialised\n");
    5.56 @@ -98,27 +98,40 @@ void init_trace_bufs(void)
    5.57  }
    5.58  
    5.59  /**
    5.60 - * get_tb_info - get trace buffer details
    5.61 - * @st: a pointer to a dom0_gettbufs_t to be filled out
    5.62 - *
    5.63 - * Called by the %DOM0_GETTBUFS dom0 op to fetch the machine address of the
    5.64 - * trace buffers.
    5.65 + * tb_control - DOM0 operations on trace buffers.
    5.66 + * @tbc: a pointer to a dom0_tbufcontrol_t to be filled out
    5.67   */
    5.68 -int get_tb_info(dom0_gettbufs_t *st)
    5.69 +int tb_control(dom0_tbufcontrol_t *tbc)
    5.70  {
    5.71 -    if ( tb_init_done )
    5.72 +    static spinlock_t lock = SPIN_LOCK_UNLOCKED;
    5.73 +    int rc = 0;
    5.74 +
    5.75 +    if ( !tb_init_done )
    5.76 +        return -EINVAL;
    5.77 +
    5.78 +    spin_lock(&lock);
    5.79 +
    5.80 +    switch ( tbc->op)
    5.81      {
    5.82 -        st->mach_addr = __pa(t_bufs[0]);
    5.83 -        st->size      = opt_tbuf_size * PAGE_SIZE;
    5.84 -        
    5.85 -        return 0;
    5.86 +    case DOM0_TBUF_GET_INFO:
    5.87 +        tbc->cpu_mask  = tb_cpu_mask;
    5.88 +        tbc->evt_mask  = tb_event_mask;
    5.89 +        tbc->mach_addr = __pa(t_bufs[0]);
    5.90 +        tbc->size      = opt_tbuf_size * PAGE_SIZE;
    5.91 +        break;
    5.92 +    case DOM0_TBUF_SET_CPU_MASK:
    5.93 +        tb_cpu_mask = tbc->cpu_mask;
    5.94 +        break;
    5.95 +    case DOM0_TBUF_SET_EVT_MASK:
    5.96 +        tb_event_mask = tbc->evt_mask;
    5.97 +        break;
    5.98 +    default:
    5.99 +        rc = -EINVAL;
   5.100      }
   5.101 -    else
   5.102 -    {
   5.103 -        st->mach_addr = 0;
   5.104 -        st->size      = 0;
   5.105 -        return -ENODATA;
   5.106 -    }
   5.107 +
   5.108 +    spin_unlock(&lock);
   5.109 +
   5.110 +    return rc;
   5.111  }
   5.112  
   5.113  /*
     6.1 --- a/xen/include/asm-x86/vmx.h	Wed Apr 06 12:46:25 2005 +0000
     6.2 +++ b/xen/include/asm-x86/vmx.h	Thu Apr 07 04:08:36 2005 +0000
     6.3 @@ -249,8 +249,4 @@ static inline int __vmxon (u64 addr)
     6.4      return 0;
     6.5  }
     6.6  
     6.7 -#define TRC_VMX_VMEXIT 0x00040001
     6.8 -#define TRC_VMX_VECTOR 0x00040002
     6.9 -#define TRC_VMX_INT    0x00040003
    6.10 -
    6.11  #endif /* __ASM_X86_VMX_H__ */
     7.1 --- a/xen/include/public/dom0_ops.h	Wed Apr 06 12:46:25 2005 +0000
     7.2 +++ b/xen/include/public/dom0_ops.h	Thu Apr 07 04:08:36 2005 +0000
     7.3 @@ -185,12 +185,20 @@ typedef struct {
     7.4  } dom0_pincpudomain_t;
     7.5  
     7.6  /* Get trace buffers machine base address */
     7.7 -#define DOM0_GETTBUFS         21
     7.8 +#define DOM0_TBUFCONTROL       21
     7.9  typedef struct {
    7.10 +    /* IN variables */
    7.11 +#define DOM0_TBUF_GET_INFO     0
    7.12 +#define DOM0_TBUF_SET_CPU_MASK 1
    7.13 +#define DOM0_TBUF_SET_EVT_MASK 2
    7.14 +    u8 op;
    7.15 +    /* IN/OUT variables */
    7.16 +    unsigned long cpu_mask;
    7.17 +    u32           evt_mask;
    7.18      /* OUT variables */
    7.19      memory_t mach_addr;
    7.20      u32      size;
    7.21 -} dom0_gettbufs_t;
    7.22 +} dom0_tbufcontrol_t;
    7.23  
    7.24  /*
    7.25   * Get physical information about the host machine
    7.26 @@ -374,9 +382,9 @@ typedef struct {
    7.27          dom0_msr_t               msr;
    7.28          dom0_debug_t             debug;
    7.29          dom0_settime_t           settime;
    7.30 -        dom0_readconsole_t	 readconsole;
    7.31 +        dom0_readconsole_t       readconsole;
    7.32          dom0_pincpudomain_t      pincpudomain;
    7.33 -        dom0_gettbufs_t          gettbufs;
    7.34 +        dom0_tbufcontrol_t       tbufcontrol;
    7.35          dom0_physinfo_t          physinfo;
    7.36          dom0_pcidev_access_t     pcidev_access;
    7.37          dom0_sched_id_t          sched_id;
     8.1 --- a/xen/include/public/trace.h	Wed Apr 06 12:46:25 2005 +0000
     8.2 +++ b/xen/include/public/trace.h	Thu Apr 07 04:08:36 2005 +0000
     8.3 @@ -1,17 +1,47 @@
     8.4  /******************************************************************************
     8.5 - * trace.h
     8.6 + * include/public/trace.h
     8.7   * 
     8.8   * Mark Williamson, (C) 2004 Intel Research Cambridge
     8.9 + * Copyright (C) 2005 Bin Ren
    8.10   */
    8.11  
    8.12  #ifndef __XEN_PUBLIC_TRACE_H__
    8.13  #define __XEN_PUBLIC_TRACE_H__
    8.14  
    8.15 +#include <asm/atomic.h>
    8.16 +
    8.17 +/* Trace classes */
    8.18 +#define TRC_GEN     0x00010000    /* General trace            */
    8.19 +#define TRC_SCHED   0x00020000    /* Xen Scheduler trace      */
    8.20 +#define TRC_DOM0OP  0x00040000    /* Xen DOM0 operation trace */
    8.21 +#define TRC_VMX     0x00080000    /* Xen VMX trace            */
    8.22 +#define TRC_ALL     0xffff0000
    8.23 +
    8.24 +/* Trace events per class */
    8.25 +
    8.26 +#define TRC_SCHED_DOM_ADD       (TRC_SCHED +  1)
    8.27 +#define TRC_SCHED_DOM_REM       (TRC_SCHED +  2)
    8.28 +#define TRC_SCHED_SLEEP         (TRC_SCHED +  3)
    8.29 +#define TRC_SCHED_WAKE          (TRC_SCHED +  4)
    8.30 +#define TRC_SCHED_YIELD         (TRC_SCHED +  5)
    8.31 +#define TRC_SCHED_BLOCK         (TRC_SCHED +  6)
    8.32 +#define TRC_SCHED_SHUTDOWN      (TRC_SCHED +  7)
    8.33 +#define TRC_SCHED_CTL           (TRC_SCHED +  8)
    8.34 +#define TRC_SCHED_ADJDOM        (TRC_SCHED +  9)
    8.35 +#define TRC_SCHED_SWITCH        (TRC_SCHED + 10)
    8.36 +#define TRC_SCHED_S_TIMER_FN    (TRC_SCHED + 11)
    8.37 +#define TRC_SCHED_T_TIMER_FN    (TRC_SCHED + 12)
    8.38 +#define TRC_SCHED_DOM_TIMER_FN  (TRC_SCHED + 13)
    8.39 +
    8.40 +#define TRC_VMX_VMEXIT          (TRC_VMX + 1)
    8.41 +#define TRC_VMX_VECTOR          (TRC_VMX + 2)
    8.42 +#define TRC_VMX_INT             (TRC_VMX + 3)
    8.43 +
    8.44  /* This structure represents a single trace buffer record. */
    8.45  struct t_rec {
    8.46 -    u64 cycles;               /* 64 bit cycle counter timestamp */
    8.47 -    u32 event;                /* 32 bit event ID                */
    8.48 -    u32 d1, d2, d3, d4, d5;   /* event data items               */
    8.49 +    u64 cycles;               /* cycle counter timestamp */
    8.50 +    u32 event;                /* event ID                */
    8.51 +    unsigned long data[5];    /* event data items        */
    8.52  };
    8.53  
    8.54  /*
    8.55 @@ -19,15 +49,13 @@ struct t_rec {
    8.56   * field, indexes into an array of struct t_rec's.
    8.57   */
    8.58  struct t_buf {
    8.59 -    unsigned long data;      /* pointer to data area.  machine address
    8.60 -                              * for convenience in user space code           */
    8.61 -
    8.62 -    unsigned long size;      /* size of the data area, in t_recs             */
    8.63 -    unsigned long head;      /* array index of the most recent record        */
    8.64 -
    8.65 -    /* Xen-private elements follow... */
    8.66 -    struct t_rec *head_ptr; /* pointer to the head record                    */
    8.67 -    struct t_rec *vdata;    /* virtual address pointer to data               */
    8.68 +    /* Used by both Xen and user space. */
    8.69 +    atomic_t      rec_idx;   /* the next record to save to */
    8.70 +    unsigned int  rec_num;   /* number of records in this trace buffer  */
    8.71 +    /* Used by Xen only. */
    8.72 +    struct t_rec  *rec;      /* start of records */
    8.73 +    /* Used by user space only. */
    8.74 +    unsigned long rec_addr;  /* machine address of the start of records */
    8.75  };
    8.76  
    8.77  #endif /* __XEN_PUBLIC_TRACE_H__ */
     9.1 --- a/xen/include/xen/trace.h	Wed Apr 06 12:46:25 2005 +0000
     9.2 +++ b/xen/include/xen/trace.h	Thu Apr 07 04:08:36 2005 +0000
     9.3 @@ -8,6 +8,8 @@
     9.4   * Author: Mark Williamson, mark.a.williamson@intel.com
     9.5   * Date:   January 2004
     9.6   *
     9.7 + * Copyright (C) 2005 Bin Ren
     9.8 + *
     9.9   * The trace buffer code is designed to allow debugging traces of Xen to be
    9.10   * generated on UP / SMP machines.  Each trace entry is timestamped so that
    9.11   * it's possible to reconstruct a chronological record of trace events.
    9.12 @@ -25,7 +27,6 @@
    9.13  
    9.14  #ifdef TRACE_BUFFER
    9.15  
    9.16 -#include <xen/spinlock.h>
    9.17  #include <asm/page.h>
    9.18  #include <xen/types.h>
    9.19  #include <xen/sched.h>
    9.20 @@ -34,11 +35,16 @@
    9.21  #include <asm/msr.h>
    9.22  #include <public/dom0_ops.h>
    9.23  
    9.24 +extern struct t_buf *t_bufs[];
    9.25 +extern int tb_init_done;
    9.26 +extern unsigned long tb_cpu_mask;
    9.27 +extern u32 tb_event_mask;
    9.28 +
    9.29  /* Used to initialise trace buffer functionality */
    9.30  void init_trace_bufs(void);
    9.31  
    9.32  /* used to retrieve the physical address of the trace buffers */
    9.33 -int get_tb_info(dom0_gettbufs_t *st);
    9.34 +int tb_control(dom0_tbufcontrol_t *tbc);
    9.35  
    9.36  /**
    9.37   * trace - Enters a trace tuple into the trace buffer for the current CPU.
    9.38 @@ -49,42 +55,43 @@ int get_tb_info(dom0_gettbufs_t *st);
    9.39   * failure, otherwise 0.  Failure occurs only if the trace buffers are not yet
    9.40   * initialised.
    9.41   */
    9.42 -static inline int trace(u32 event, u32 d1, u32 d2, u32 d3, u32 d4, u32 d5)
    9.43 +static inline int trace(u32 event, unsigned long d1, unsigned long d2,
    9.44 +                        unsigned long d3, unsigned long d4, unsigned long d5)
    9.45  {
    9.46 -    extern struct t_buf *t_bufs[];      /* global array of pointers to bufs */
    9.47 -    extern int tb_init_done;            /* set when buffers are initialised */
    9.48 -    unsigned long flags;                /* for saving interrupt flags       */
    9.49 -    struct t_buf *buf;                  /* the buffer we're working on      */
    9.50 -    struct t_rec *rec;                  /* next record to fill out          */
    9.51 -
    9.52 +    atomic_t old, new, seen;
    9.53 +    struct t_buf *buf;
    9.54 +    struct t_rec *rec;
    9.55  
    9.56      if ( !tb_init_done )
    9.57          return -1;
    9.58  
    9.59 +    if ( (tb_event_mask & event) == 0 )
    9.60 +        return 0;
    9.61 +
    9.62 +    if ( (tb_cpu_mask & (1UL << smp_processor_id())) == 0 )
    9.63 +        return 0;
    9.64  
    9.65      buf = t_bufs[smp_processor_id()];
    9.66  
    9.67 -    local_irq_save(flags);
    9.68 +    do
    9.69 +    {
    9.70 +        old = buf->rec_idx;
    9.71 +        _atomic_set(new, (_atomic_read(old) + 1) % buf->rec_num);
    9.72 +        seen = atomic_compareandswap(old, new, &buf->rec_idx);
    9.73 +    }
    9.74 +    while ( unlikely(_atomic_read(seen) != _atomic_read(old)) );
    9.75  
    9.76 -    rec = buf->head_ptr;
    9.77 +    wmb();
    9.78  
    9.79 +    rec = &buf->rec[_atomic_read(old)];
    9.80      rdtscll(rec->cycles);
    9.81 -    rec->event = event;
    9.82 -    rec->d1 = d1;
    9.83 -    rec->d2 = d2;
    9.84 -    rec->d3 = d3;
    9.85 -    rec->d4 = d4;
    9.86 -    rec->d5 = d5;
    9.87 +    rec->event   = event;
    9.88 +    rec->data[0] = d1;
    9.89 +    rec->data[1] = d2;
    9.90 +    rec->data[2] = d3;
    9.91 +    rec->data[3] = d4;
    9.92 +    rec->data[4] = d5;
    9.93  
    9.94 -    wmb(); /* above must be visible before reader sees index updated */
    9.95 -
    9.96 -    buf->head_ptr++;
    9.97 -    buf->head++;
    9.98 -    if ( buf->head_ptr == (buf->vdata + buf->size) )
    9.99 -        buf->head_ptr = buf->vdata;
   9.100 -
   9.101 -    local_irq_restore(flags);
   9.102 -    
   9.103      return 0;
   9.104  }
   9.105