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

[Xen-changelog] [xen-unstable] [xen][tracing] Introduce variable-size trace records



# HG changeset patch
# User George Dunlap <gdunlap@xxxxxxxxxxxxx>
# Date 1190384767 -3600
# Node ID 7ed576909132407b0c98c8374c38179cda4cfd39
# Parent  517432b9f8b585df5b22ec3682ffba416e718d22
[xen][tracing] Introduce variable-size trace records

This patch introduces variable-size trace records.  Each record consists of
a 32-bit "header", an optional cycle count, and up to seven more 32-bit words.

The header is packed with the following information:
 bits  0-27: The trace event.
 bits 28-30: The number of 32-bit "extra" words in the records
 bit     31: Does the trace include a 64-bit tsc?

This patch standardizes behavior wrt 32 and 64-bit hypervisors and dom0s.

Note that this patch requires a new version of the xentrace daemon running in
dom0.  The new daemon, instead of pre-pending the cpu to every record as it
writes it, inserts a "cpu change" record to the trace file that record the
cpu and the number of records it's about to write.

Signed-off-by: George Dunlap <gdunlap@xxxxxxxxxxxxx>
---
 tools/xentrace/xentrace.c  |  140 +++++++++++++++----
 xen/common/trace.c         |  323 +++++++++++++++++++++++++++++++++++----------
 xen/include/public/trace.h |   43 ++++-
 xen/include/xen/trace.h    |   85 +++++++++--
 4 files changed, 460 insertions(+), 131 deletions(-)

diff -r 517432b9f8b5 -r 7ed576909132 tools/xentrace/xentrace.c
--- a/tools/xentrace/xentrace.c Fri Sep 21 16:52:17 2007 +0100
+++ b/tools/xentrace/xentrace.c Fri Sep 21 15:26:07 2007 +0100
@@ -22,6 +22,7 @@
 #include <signal.h>
 #include <inttypes.h>
 #include <string.h>
+#include <assert.h>
 
 #include <xen/xen.h>
 #include <xen/trace.h>
@@ -83,24 +84,58 @@ struct timespec millis_to_timespec(unsig
 }
 
 /**
- * write_rec - output a trace record in binary format
+ * write_buffer - write a section of the trace buffer
  * @cpu      - source buffer CPU ID
- * @rec      - trace record to output
+ * @start
+ * @size     - size of write (may be less than total window size)
+ * @total_size - total size of the window (0 on 2nd write of wrapped windows)
  * @out      - output stream
  *
- * Outputs the trace record to a filestream, prepending the CPU ID of the
- * source trace buffer.
- */
-void write_rec(unsigned int cpu, struct t_rec *rec, FILE *out)
+ * Outputs the trace buffer to a filestream, prepending the CPU and size
+ * of the buffer write.
+ */
+void write_buffer(unsigned int cpu, unsigned char *start, int size,
+               int total_size, int outfd)
 {
     size_t written = 0;
-    written += fwrite(&cpu, sizeof(cpu), 1, out);
-    written += fwrite(rec, sizeof(*rec), 1, out);
-    if ( written != 2 )
-    {
-        PERROR("Failed to write trace record");
-        exit(EXIT_FAILURE);
-    }
+    
+    /* Write a CPU_BUF record on each buffer "window" written.  Wrapped
+     * windows may involve two writes, so only write the record on the
+     * first write. */
+    if(total_size)
+    {
+        struct {
+            uint32_t header;
+            struct {
+                unsigned cpu;
+                unsigned byte_count;
+            } extra;
+        } rec;
+
+        rec.header = TRC_TRACE_CPU_CHANGE
+            | ((sizeof(rec.extra)/sizeof(uint32_t)) << TRACE_EXTRA_SHIFT);
+        rec.extra.cpu = cpu;
+        rec.extra.byte_count = total_size;
+
+        written = write(outfd, &rec, sizeof(rec));
+
+        if(written!=sizeof(rec)) {
+            fprintf(stderr, "Cannot write cpu change (write returned %d)\n",
+                    written);
+            goto fail;
+        }
+    }
+
+    written = write(outfd, start, size);
+    if ( written != size ) {
+        fprintf(stderr, "Write failed! (size %d, returned %d)\n",
+                size, written);
+        goto fail;
+    }
+    return;
+ fail:
+    PERROR("Failed to write trace data");
+    exit(EXIT_FAILURE);
 }
 
 static void get_tbufs(unsigned long *mfn, unsigned long *size)
@@ -233,12 +268,12 @@ struct t_buf **init_bufs_ptrs(void *bufs
  * mapped in user space.  Note that the trace buffer metadata contains machine
  * pointers - the array returned allows more convenient access to them.
  */
-struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num)
+unsigned char **init_rec_ptrs(struct t_buf **meta, unsigned int num)
 {
     int i;
-    struct t_rec **data;
-    
-    data = calloc(num, sizeof(struct t_rec *));
+    unsigned char **data;
+    
+    data = calloc(num, sizeof(unsigned char *));
     if ( data == NULL )
     {
         PERROR("Failed to allocate memory for data pointers\n");
@@ -246,7 +281,7 @@ struct t_rec **init_rec_ptrs(struct t_bu
     }
 
     for ( i = 0; i < num; i++ )
-        data[i] = (struct t_rec *)(meta[i] + 1);
+        data[i] = (unsigned char *)(meta[i] + 1);
 
     return data;
 }
@@ -281,19 +316,19 @@ unsigned int get_num_cpus(void)
  * monitor_tbufs - monitor the contents of tbufs and output to a file
  * @logfile:       the FILE * representing the file to log to
  */
-int monitor_tbufs(FILE *logfile)
+int monitor_tbufs(int outfd)
 {
     int i;
 
     void *tbufs_mapped;          /* pointer to where the tbufs are mapped    */
     struct t_buf **meta;         /* pointers to the trace buffer metadata    */
-    struct t_rec **data;         /* pointers to the trace buffer data areas
+    unsigned char **data;        /* pointers to the trace buffer data areas
                                   * where they are mapped into user space.   */
     unsigned long tbufs_mfn;     /* mfn of the tbufs                         */
     unsigned int  num;           /* number of trace buffers / logical CPUS   */
     unsigned long size;          /* size of a single trace buffer            */
 
-    int size_in_recs;
+    unsigned long data_size;
 
     /* get number of logical CPUs (and therefore number of trace buffers) */
     num = get_num_cpus();
@@ -302,7 +337,7 @@ int monitor_tbufs(FILE *logfile)
     get_tbufs(&tbufs_mfn, &size);
     tbufs_mapped = map_tbufs(tbufs_mfn, num, size);
 
-    size_in_recs = (size - sizeof(struct t_buf)) / sizeof(struct t_rec);
+    data_size = (size - sizeof(struct t_buf));
 
     /* build arrays of convenience ptrs */
     meta  = init_bufs_ptrs(tbufs_mapped, num, size);
@@ -317,13 +352,48 @@ int monitor_tbufs(FILE *logfile)
     {
         for ( i = 0; (i < num) && !interrupted; i++ )
         {
-            while ( meta[i]->cons != meta[i]->prod )
+            unsigned long start_offset, end_offset, window_size, cons, prod;
+            rmb(); /* read prod, then read item. */
+                
+            /* Read window information only once. */
+            cons = meta[i]->cons;
+            prod = meta[i]->prod;
+            
+            if(cons == prod)
+                continue;
+           
+            assert(prod > cons);
+
+            window_size = prod - cons;
+            start_offset = cons % data_size;
+            end_offset = prod % data_size;
+
+            if(end_offset > start_offset)
             {
-                rmb(); /* read prod, then read item. */
-                write_rec(i, data[i] + meta[i]->cons % size_in_recs, logfile);
-                mb(); /* read item, then update cons. */
-                meta[i]->cons++;
+                /* If window does not wrap, write in one big chunk */
+                write_buffer(i, data[i]+start_offset,
+                             window_size,
+                             window_size,
+                             outfd);
             }
+            else
+            {
+                /* If wrapped, write in two chunks:
+                 * - first, start to the end of the buffer
+                 * - second, start of buffer to end of window
+                 */
+                write_buffer(i, data[i]+start_offset,
+                             data_size - start_offset,
+                             window_size,
+                             outfd);
+                write_buffer(i, data[i],
+                             end_offset,
+                             0,
+                             outfd);
+            }
+
+            mb(); /* read buffer, then update cons. */
+            meta[i]->cons = meta[i]->prod;
         }
 
         nanosleep(&opts.poll_sleep, NULL);
@@ -333,7 +403,7 @@ int monitor_tbufs(FILE *logfile)
     free(meta);
     free(data);
     /* don't need to munmap - cleanup is automatic */
-    fclose(logfile);
+    close(outfd);
 
     return 0;
 }
@@ -503,7 +573,6 @@ int main(int argc, char **argv)
 int main(int argc, char **argv)
 {
     int outfd = 1, ret;
-    FILE *logfile;
     struct sigaction act;
 
     opts.outfile = 0;
@@ -537,8 +606,6 @@ int main(int argc, char **argv)
         exit(EXIT_FAILURE);
     }
 
-    logfile = fdopen(outfd, "w");
-    
     /* ensure that if we get a signal, we'll do cleanup, then exit */
     act.sa_handler = close_handler;
     act.sa_flags = 0;
@@ -547,7 +614,16 @@ int main(int argc, char **argv)
     sigaction(SIGTERM, &act, NULL);
     sigaction(SIGINT,  &act, NULL);
 
-    ret = monitor_tbufs(logfile);
+    ret = monitor_tbufs(outfd);
 
     return ret;
 }
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 517432b9f8b5 -r 7ed576909132 xen/common/trace.c
--- a/xen/common/trace.c        Fri Sep 21 16:52:17 2007 +0100
+++ b/xen/common/trace.c        Fri Sep 21 15:26:07 2007 +0100
@@ -43,19 +43,14 @@ CHECK_t_buf;
 #define TB_COMPAT 0
 #endif
 
-typedef union {
-       struct t_rec *nat;
-       struct compat_t_rec *cmp;
-} t_rec_u;
-
 /* opt_tbuf_size: trace buffer size (in pages) */
 static unsigned int opt_tbuf_size = 0;
 integer_param("tbuf_size", opt_tbuf_size);
 
 /* Pointers to the meta-data objects for all system trace buffers */
 static DEFINE_PER_CPU(struct t_buf *, t_bufs);
-static DEFINE_PER_CPU(t_rec_u, t_recs);
-static int nr_recs;
+static DEFINE_PER_CPU(unsigned char *, t_data);
+static int data_size;
 
 /* High water mark for trace buffers; */
 /* Send virtual interrupt when buffer level reaches this point */
@@ -102,8 +97,7 @@ static int alloc_trace_bufs(void)
 
     nr_pages = num_online_cpus() * opt_tbuf_size;
     order    = get_order_from_pages(nr_pages);
-    nr_recs  = (opt_tbuf_size * PAGE_SIZE - sizeof(struct t_buf)) /
-        (!TB_COMPAT ? sizeof(struct t_rec) : sizeof(struct compat_t_rec));
+    data_size  = (opt_tbuf_size * PAGE_SIZE - sizeof(struct t_buf));
     
     if ( (rawbuf = alloc_xenheap_pages(order)) == NULL )
     {
@@ -122,10 +116,10 @@ static int alloc_trace_bufs(void)
         buf = per_cpu(t_bufs, i) = (struct t_buf *)
             &rawbuf[i*opt_tbuf_size*PAGE_SIZE];
         buf->cons = buf->prod = 0;
-        per_cpu(t_recs, i).nat = (struct t_rec *)(buf + 1);
-    }
-
-    t_buf_highwater = nr_recs >> 1; /* 50% high water */
+        per_cpu(t_data, i) = (unsigned char *)(buf + 1);
+    }
+
+    t_buf_highwater = data_size >> 1; /* 50% high water */
     open_softirq(TRACE_SOFTIRQ, trace_notify_guest);
 
     return 0;
@@ -235,6 +229,129 @@ int tb_control(xen_sysctl_tbuf_op_t *tbc
     return rc;
 }
 
+static inline int calc_rec_size(int cycles, int extra) 
+{
+    int rec_size;
+    rec_size = 4;
+    if(cycles)
+        rec_size += 8;
+    rec_size += extra;
+    return rec_size;
+}
+
+static inline int calc_bytes_to_wrap(struct t_buf *buf)
+{
+    return data_size - (buf->prod % data_size);
+}
+
+static inline unsigned calc_bytes_avail(struct t_buf *buf)
+{
+    return data_size - (buf->prod - buf->cons);
+}
+
+static inline int __insert_record(struct t_buf *buf,
+                                  unsigned long event,
+                                  int extra,
+                                  int cycles,
+                                  int rec_size,
+                                  unsigned char * extra_data) 
+{
+    struct t_rec *rec;
+    unsigned char * dst;
+    unsigned long extra_word = extra/sizeof(u32);
+    int local_rec_size = calc_rec_size(cycles, extra);
+
+    BUG_ON(local_rec_size != rec_size);
+
+    /* Double-check once more that we have enough space.
+     * Don't bugcheck here, in case the userland tool is doing
+     * something stupid. */
+    if(calc_bytes_avail(buf) < rec_size )
+    {
+        printk("%s: %u bytes left (%u - (%u - %u)) recsize %u.\n",
+               __func__,
+               data_size - (buf->prod - buf->cons),
+               data_size,
+               buf->prod, buf->cons, rec_size);
+        return 0;
+    }
+    rmb();
+
+    rec = (struct t_rec *)&this_cpu(t_data)[buf->prod % data_size];
+    rec->header = event;
+    rec->header |= extra_word << TRACE_EXTRA_SHIFT;
+    if(cycles) 
+    {
+        u64 tsc = (u64)get_cycles();
+
+        rec->header |= TRC_HD_CYCLE_FLAG;
+        rec->u.cycles.cycles_lo = tsc & ((((u64)1)<<32)-1);
+        rec->u.cycles.cycles_hi = tsc >> 32;
+        dst = rec->u.cycles.data;
+    } 
+    else
+        dst = rec->u.nocycles.data;
+
+    if(extra_data && extra)
+        memcpy(dst, extra_data, extra);
+
+    wmb();
+    buf->prod+=rec_size;
+
+    return rec_size;
+}
+
+static inline int insert_wrap_record(struct t_buf *buf, int size)
+{
+    int space_left = calc_bytes_to_wrap(buf);
+    unsigned long extra_space = space_left - sizeof(u32);
+    int cycles=0;
+
+    if(space_left > size)
+        printk("%s: space_left %d, size %d!\n",
+               __func__, space_left, size);
+
+    BUG_ON(space_left > size);
+
+    /* We may need to add cycles to take up enough space... */
+    if((extra_space/sizeof(u32)) > TRACE_EXTRA_MAX)
+    {
+        cycles = 1;
+        extra_space -= sizeof(u64);
+        
+        ASSERT((extra_space/sizeof(u32)) <= TRACE_EXTRA_MAX);
+    }
+
+
+    return __insert_record(buf,
+                    TRC_TRACE_WRAP_BUFFER,
+                    extra_space,
+                    cycles,
+                    space_left,
+                    NULL);
+}
+
+#define LOST_REC_SIZE 8
+
+static inline int insert_lost_records(struct t_buf *buf)
+{
+    struct {
+        u32 lost_records;
+    } ed;
+
+    ed.lost_records = this_cpu(lost_records);
+
+    this_cpu(lost_records) = 0;
+
+    return __insert_record(buf,
+                           TRC_LOST_RECORDS,
+                           sizeof(ed),
+                           0 /* !cycles */,
+                           LOST_REC_SIZE,
+                           (unsigned char *)&ed);
+}
+
+
 /**
  * trace - Enters a trace tuple into the trace buffer for the current CPU.
  * @event: the event type being logged
@@ -244,14 +361,32 @@ int tb_control(xen_sysctl_tbuf_op_t *tbc
  * failure, otherwise 0.  Failure occurs only if the trace buffers are not yet
  * initialised.
  */
-void trace(u32 event, unsigned long d1, unsigned long d2,
-           unsigned long d3, unsigned long d4, unsigned long d5)
+void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
 {
     struct t_buf *buf;
-    t_rec_u rec;
-    unsigned long flags;
+    unsigned long flags, bytes_to_tail, bytes_to_wrap;
+    int rec_size, total_size;
+    int extra_word;
+    int started_below_highwater;
+
+    if(!tb_init_done)
+        return;
+
+    /* Convert byte count into word count, rounding up */
+    extra_word = (extra / sizeof(u32));
+    if((extra % sizeof(u32)) != 0)
+        extra_word++;
     
-    BUG_ON(!tb_init_done);
+#if !NDEBUG
+    ASSERT(extra_word<=TRACE_EXTRA_MAX);
+#else
+    /* Not worth crashing a production system over */
+    if(extra_word > TRACE_EXTRA_MAX)
+        extra_word = TRACE_EXTRA_MAX;
+#endif
+
+    /* Round size up to nearest word */
+    extra = extra_word * sizeof(u32);
 
     if ( (tb_event_mask & event) == 0 )
         return;
@@ -275,73 +410,125 @@ void trace(u32 event, unsigned long d1, 
 
     local_irq_save(flags);
 
-    /* Check if space for two records (we write two if there are lost recs). */
-    if ( (buf->prod - buf->cons) >= (nr_recs - 1) )
+    started_below_highwater = ( (buf->prod - buf->cons) < t_buf_highwater );
+
+    /* Calculate the record size */
+    rec_size = calc_rec_size(cycles, extra);
+ 
+    /* How many bytes are available in the buffer? */
+    bytes_to_tail = calc_bytes_avail(buf);
+    
+    /* How many bytes until the next wrap-around? */
+    bytes_to_wrap = calc_bytes_to_wrap(buf);
+    
+    /* 
+     * Calculate expected total size to commit this record by
+     * doing a dry-run.
+     */
+    total_size = 0;
+
+    /* First, check to see if we need to include a lost_record.
+     *
+     * calc_bytes_to_wrap() involves integer division, which we'd like to
+     * avoid if we can.  So do the math, check it in debug versions, and
+     * do a final check always if we happen to write a record.
+     */
+    if(this_cpu(lost_records))
+    {
+        if(LOST_REC_SIZE > bytes_to_wrap)
+        {
+            total_size += bytes_to_wrap;
+            bytes_to_wrap = data_size;
+        } 
+        else
+        {
+            bytes_to_wrap -= LOST_REC_SIZE;
+            if(bytes_to_wrap == 0)
+                bytes_to_wrap == data_size;
+        }
+        total_size += LOST_REC_SIZE;
+    }
+
+    ASSERT(bytes_to_wrap == calc_bytes_to_wrap(buf));
+
+    if(rec_size > bytes_to_wrap)
+    {
+        total_size += bytes_to_wrap;
+        bytes_to_wrap = data_size;
+    } 
+    else
+    {
+        bytes_to_wrap -= rec_size;
+    }
+
+    total_size += rec_size;
+
+    /* Do we have enough space for everything? */
+    if(total_size > bytes_to_tail) 
     {
         this_cpu(lost_records)++;
         local_irq_restore(flags);
         return;
     }
 
-    if ( unlikely(this_cpu(lost_records) != 0) )
-    {
-        if ( !TB_COMPAT )
+    /*
+     * Now, actually write information 
+     */
+    bytes_to_wrap = calc_bytes_to_wrap(buf);
+
+    if(this_cpu(lost_records))
+    {
+        if(LOST_REC_SIZE > bytes_to_wrap)
         {
-            rec.nat = &this_cpu(t_recs).nat[buf->prod % nr_recs];
-            memset(rec.nat, 0, sizeof(*rec.nat));
-            rec.nat->cycles  = (u64)get_cycles();
-            rec.nat->event   = TRC_LOST_RECORDS;
-            rec.nat->data[0] = this_cpu(lost_records);
-            this_cpu(lost_records) = 0;
-        }
+            insert_wrap_record(buf, LOST_REC_SIZE);
+            bytes_to_wrap = data_size;
+        } 
         else
         {
-            rec.cmp = &this_cpu(t_recs).cmp[buf->prod % nr_recs];
-            memset(rec.cmp, 0, sizeof(*rec.cmp));
-            rec.cmp->cycles  = (u64)get_cycles();
-            rec.cmp->event   = TRC_LOST_RECORDS;
-            rec.cmp->data[0] = this_cpu(lost_records);
-            this_cpu(lost_records) = 0;
+            bytes_to_wrap -= LOST_REC_SIZE;
+            /* LOST_REC might line up perfectly with the buffer wrap */
+            if(bytes_to_wrap == 0)
+                bytes_to_wrap = data_size;
         }
-
-        wmb();
-        buf->prod++;
-    }
-
-    if ( !TB_COMPAT )
-    {
-        rec.nat = &this_cpu(t_recs).nat[buf->prod % nr_recs];
-        rec.nat->cycles  = (u64)get_cycles();
-        rec.nat->event   = event;
-        rec.nat->data[0] = d1;
-        rec.nat->data[1] = d2;
-        rec.nat->data[2] = d3;
-        rec.nat->data[3] = d4;
-        rec.nat->data[4] = d5;
-    }
-    else
-    {
-        rec.cmp = &this_cpu(t_recs).cmp[buf->prod % nr_recs];
-        rec.cmp->cycles  = (u64)get_cycles();
-        rec.cmp->event   = event;
-        rec.cmp->data[0] = d1;
-        rec.cmp->data[1] = d2;
-        rec.cmp->data[2] = d3;
-        rec.cmp->data[3] = d4;
-        rec.cmp->data[4] = d5;
-    }
-
-    wmb();
-    buf->prod++;
+        insert_lost_records(buf);
+    }
+
+    ASSERT(bytes_to_wrap == calc_bytes_to_wrap(buf));
+
+    if(rec_size > bytes_to_wrap)
+    {
+        insert_wrap_record(buf, rec_size);
+    } 
+
+    /* Write the original record */
+    __insert_record(buf, event, extra, cycles, rec_size, extra_data);
 
     local_irq_restore(flags);
 
     /*
-     * Notify trace buffer consumer that we've reached the high water mark.
+     * Notify trace buffer consumer that we've crossed the high water mark.
      *
      */
-    if ( (buf->prod - buf->cons) == t_buf_highwater )
+    if ( started_below_highwater
+         && ( (buf->prod - buf->cons) > t_buf_highwater ) )
         raise_softirq(TRACE_SOFTIRQ);
+}
+
+
+void __trace_fixed(u32 event, unsigned long d1, unsigned long d2,
+           unsigned long d3, unsigned long d4, unsigned long d5)
+{
+    u32 extra_data[5];
+    
+    /* In a 64-bit hypervisor, this will truncate to 32 bits. */
+    extra_data[0]=d1;
+    extra_data[1]=d2;
+    extra_data[2]=d3;
+    extra_data[3]=d4;
+    extra_data[4]=d5;
+
+    __trace_var(event, 1/* include cycles */, sizeof(*extra_data)*5,
+              (unsigned char *)extra_data);
 }
 
 /*
diff -r 517432b9f8b5 -r 7ed576909132 xen/include/public/trace.h
--- a/xen/include/public/trace.h        Fri Sep 21 16:52:17 2007 +0100
+++ b/xen/include/public/trace.h        Fri Sep 21 15:26:07 2007 +0100
@@ -26,14 +26,21 @@
 #ifndef __XEN_PUBLIC_TRACE_H__
 #define __XEN_PUBLIC_TRACE_H__
 
+#define TRACE_EXTRA_MAX    7
+#define TRACE_EXTRA_SHIFT 28
+
 /* Trace classes */
 #define TRC_CLS_SHIFT 16
-#define TRC_GEN     0x0001f000    /* General trace            */
-#define TRC_SCHED   0x0002f000    /* Xen Scheduler trace      */
-#define TRC_DOM0OP  0x0004f000    /* Xen DOM0 operation trace */
-#define TRC_HVM     0x0008f000    /* Xen HVM trace            */
-#define TRC_MEM     0x0010f000    /* Xen memory trace         */
-#define TRC_ALL     0xfffff000
+#define TRC_GEN      0x0001f000    /* General trace            */
+#define TRC_SCHED    0x0002f000    /* Xen Scheduler trace      */
+#define TRC_DOM0OP   0x0004f000    /* Xen DOM0 operation trace */
+#define TRC_HVM      0x0008f000    /* Xen HVM trace            */
+#define TRC_MEM      0x0010f000    /* Xen memory trace         */
+#define TRC_ALL      0x0ffff000
+#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff)
+#define TRC_HD_CYCLE_FLAG (1UL<<31)
+#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & TRC_HD_CYCLE_FLAG ) )
+#define TRC_HD_EXTRA(x)    (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX)
 
 /* Trace subclasses */
 #define TRC_SUBCLS_SHIFT 12
@@ -44,6 +51,8 @@
 
 /* Trace events per class */
 #define TRC_LOST_RECORDS        (TRC_GEN + 1)
+#define TRC_TRACE_WRAP_BUFFER  (TRC_GEN + 2)
+#define TRC_TRACE_CPU_CHANGE    (TRC_GEN + 3)
 
 #define TRC_SCHED_DOM_ADD       (TRC_SCHED +  1)
 #define TRC_SCHED_DOM_REM       (TRC_SCHED +  2)
@@ -92,9 +101,19 @@
 
 /* This structure represents a single trace buffer record. */
 struct t_rec {
-    uint64_t cycles;          /* cycle counter timestamp */
-    uint32_t event;           /* event ID                */
-    unsigned long data[5];    /* event data items        */
+    uint32_t header;           /* 31   : Cycles included?
+                                  30-28: # of extra words
+                                  27- 0: event ID                */
+    union {
+        struct {
+            uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */
+            unsigned char data[28];        /* event data items        */
+        } cycles;
+        struct {
+            unsigned char data[28];        /* event data items        */
+        } nocycles;
+    }u;
+        
 };
 
 /*
@@ -102,9 +121,9 @@ struct t_rec {
  * field, indexes into an array of struct t_rec's.
  */
 struct t_buf {
-    uint32_t cons;      /* Next item to be consumed by control tools. */
-    uint32_t prod;      /* Next item to be produced by Xen.           */
-    /* 'nr_recs' records follow immediately after the meta-data header.    */
+    uint32_t cons;   /* Offset of next item to be consumed by control tools. */
+    uint32_t prod;   /* Offset of next item to be produced by Xen.           */
+    /*  Records follow immediately after the meta-data header.    */
 };
 
 #endif /* __XEN_PUBLIC_TRACE_H__ */
diff -r 517432b9f8b5 -r 7ed576909132 xen/include/xen/trace.h
--- a/xen/include/xen/trace.h   Fri Sep 21 16:52:17 2007 +0100
+++ b/xen/include/xen/trace.h   Fri Sep 21 15:26:07 2007 +0100
@@ -33,27 +33,74 @@ void init_trace_bufs(void);
 /* used to retrieve the physical address of the trace buffers */
 int tb_control(struct xen_sysctl_tbuf_op *tbc);
 
-void trace(u32 event, unsigned long d1, unsigned long d2,
+void __trace_fixed(u32 event, unsigned long d1, unsigned long d2,
            unsigned long d3, unsigned long d4, unsigned long d5);
+void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data);
 
-/* Avoids troubling the caller with casting their arguments to a trace macro */
-#define trace_do_casts(e,d1,d2,d3,d4,d5) \
-    do {                                 \
-        if ( unlikely(tb_init_done) )    \
-            trace(e,                     \
-                  (unsigned long)(d1),   \
-                  (unsigned long)(d2),   \
-                  (unsigned long)(d3),   \
-                  (unsigned long)(d4),   \
-                  (unsigned long)(d5));  \
+static inline void trace_fixed(u32 event, unsigned long d1,
+                               unsigned long d2, unsigned long d3,
+                               unsigned long d4, unsigned long d5)
+{
+    if( unlikely(tb_init_done) )
+        __trace_fixed(event, d1, d2, d3, d4, d5);
+}
+
+static inline void trace_var(u32 event, int cycles, int extra,
+                               unsigned char *extra_data)
+{
+    if( unlikely(tb_init_done) )
+        __trace_var(event, cycles, extra, extra_data);
+}
+
+/* Convenience macros for calling the trace function. */
+#define TRACE_0D(_e)                            \
+    do {                                        \
+        trace_var(_e, 1, 0, NULL);              \
+    } while ( 0 )
+  
+#define TRACE_1D(_e,_d)                                         \
+    do {                                                        \
+        u32 _d1;                                                \
+        _d1 = _d;                                               \
+        trace_var(_e, 1, sizeof(_d1), (unsigned char *)&_d1);  \
+    } while ( 0 )
+ 
+#define TRACE_2D(_e,d1,d2)                                      \
+    do {                                                       \
+        u32 _d[2];                                             \
+        _d[0]=d1;                                              \
+        _d[1]=d2;                                              \
+        trace_var(_e, 1, sizeof(*_d)*2, (unsigned char *)_d);  \
+    } while ( 0 )
+ 
+#define TRACE_3D(_e,d1,d2,d3)                                   \
+    do {                                                        \
+        u32 _d[3];                                              \
+        _d[0]=d1;                                               \
+        _d[1]=d2;                                               \
+        _d[2]=d3;                                               \
+        trace_var(_e, 1, sizeof(*_d)*3, (unsigned char *)_d);  \
+    } while ( 0 )
+ 
+#define TRACE_4D(_e,d1,d2,d3,d4)                                \
+    do {                                                        \
+        u32 _d[4];                                              \
+        _d[0]=d1;                                               \
+        _d[1]=d2;                                               \
+        _d[2]=d3;                                               \
+        _d[3]=d4;                                               \
+        trace_var(_e, 1, sizeof(*_d)*4, (unsigned char *)_d);  \
+    } while ( 0 )
+ 
+#define TRACE_5D(_e,d1,d2,d3,d4,d5)                             \
+    do {                                                       \
+        u32 _d[5];                                             \
+        _d[0]=d1;                                              \
+        _d[1]=d2;                                              \
+        _d[2]=d3;                                              \
+        _d[3]=d4;                                              \
+        _d[4]=d5;                                              \
+        trace_var(_e, 1, sizeof(*_d)*5, (unsigned char *)_d);  \
     } while ( 0 )
 
-/* Convenience macros for calling the trace function. */
-#define TRACE_0D(event)                trace_do_casts(event,0, 0, 0, 0, 0 )
-#define TRACE_1D(event,d)              trace_do_casts(event,d, 0, 0, 0, 0 )
-#define TRACE_2D(event,d1,d2)          trace_do_casts(event,d1,d2,0, 0, 0 )
-#define TRACE_3D(event,d1,d2,d3)       trace_do_casts(event,d1,d2,d3,0, 0 )
-#define TRACE_4D(event,d1,d2,d3,d4)    trace_do_casts(event,d1,d2,d3,d4,0 )
-#define TRACE_5D(event,d1,d2,d3,d4,d5) trace_do_casts(event,d1,d2,d3,d4,d5)
-
 #endif /* __XEN_TRACE_H__ */

_______________________________________________
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®.