ia64/xen-unstable

changeset 15290:a7601de2f733

Add backtrace support to xenoprof.

Signed-off-by: Amitabha Roy <amitabha.roy@gmail.com>
Reviewed-by: Jose Renato G Santos <joserenato.santos@hp.com>
author kfraser@localhost.localdomain
date Thu Jun 07 14:30:21 2007 +0100 (2007-06-07)
parents 1cae82505e9e
children 56bab6f498ac
files xen/Rules.mk xen/arch/ia64/xen/oprofile/perfmon.c xen/arch/x86/oprofile/Makefile xen/arch/x86/oprofile/backtrace.c xen/arch/x86/oprofile/op_model_athlon.c xen/arch/x86/oprofile/op_model_p4.c xen/arch/x86/oprofile/op_model_ppro.c xen/arch/x86/traps.c xen/common/xenoprof.c xen/include/asm-ia64/xenoprof.h xen/include/asm-x86/xenoprof.h xen/include/public/xenoprof.h xen/include/xen/xenoprof.h
line diff
     1.1 --- a/xen/Rules.mk	Thu Jun 07 11:15:24 2007 +0100
     1.2 +++ b/xen/Rules.mk	Thu Jun 07 14:30:21 2007 +0100
     1.3 @@ -3,10 +3,11 @@
     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 -perfc       ?= n
     1.9 -perfc_arrays?= n
    1.10 -crash_debug ?= n
    1.11 +verbose       ?= n
    1.12 +perfc         ?= n
    1.13 +perfc_arrays  ?= n
    1.14 +crash_debug   ?= n
    1.15 +frame_pointer ?= n
    1.16  
    1.17  XEN_ROOT=$(BASEDIR)/..
    1.18  include $(XEN_ROOT)/Config.mk
    1.19 @@ -14,11 +15,15 @@ include $(XEN_ROOT)/Config.mk
    1.20  # Hardcoded configuration implications and dependencies.
    1.21  # Do this is a neater way if it becomes unwieldy.
    1.22  ifeq ($(debug),y)
    1.23 -verbose := y
    1.24 +verbose       := y
    1.25 +frame_pointer := y
    1.26  endif
    1.27  ifeq ($(perfc_arrays),y)
    1.28  perfc := y
    1.29  endif
    1.30 +ifeq ($(frame_pointer),y)
    1.31 +CFLAGS := $(shell echo $(CFLAGS) | sed -e 's/-f[^ ]*omit-frame-pointer//g')
    1.32 +endif
    1.33  
    1.34  # Set ARCH/SUBARCH appropriately.
    1.35  override COMPILE_SUBARCH := $(XEN_COMPILE_ARCH)
    1.36 @@ -50,18 +55,19 @@ ALL_OBJS-y               += $(BASEDIR)/d
    1.37  ALL_OBJS-$(ACM_SECURITY) += $(BASEDIR)/acm/built_in.o
    1.38  ALL_OBJS-y               += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o
    1.39  
    1.40 -CFLAGS-y               += -g -D__XEN__
    1.41 -CFLAGS-$(ACM_SECURITY) += -DACM_SECURITY
    1.42 -CFLAGS-$(verbose)      += -DVERBOSE
    1.43 -CFLAGS-$(crash_debug)  += -DCRASH_DEBUG
    1.44 -CFLAGS-$(perfc)        += -DPERF_COUNTERS
    1.45 -CFLAGS-$(perfc_arrays) += -DPERF_ARRAYS
    1.46 +CFLAGS-y                += -g -D__XEN__
    1.47 +CFLAGS-$(ACM_SECURITY)  += -DACM_SECURITY
    1.48 +CFLAGS-$(verbose)       += -DVERBOSE
    1.49 +CFLAGS-$(crash_debug)   += -DCRASH_DEBUG
    1.50 +CFLAGS-$(perfc)         += -DPERF_COUNTERS
    1.51 +CFLAGS-$(perfc_arrays)  += -DPERF_ARRAYS
    1.52 +CFLAGS-$(frame_pointer) += -fno-omit-frame-pointer -DCONFIG_FRAME_POINTER
    1.53  
    1.54  ifneq ($(max_phys_cpus),)
    1.55 -CFLAGS-y               += -DMAX_PHYS_CPUS=$(max_phys_cpus)
    1.56 +CFLAGS-y                += -DMAX_PHYS_CPUS=$(max_phys_cpus)
    1.57  endif
    1.58  
    1.59 -AFLAGS-y               += -D__ASSEMBLY__
    1.60 +AFLAGS-y                += -D__ASSEMBLY__
    1.61  
    1.62  ALL_OBJS := $(ALL_OBJS-y)
    1.63  
     2.1 --- a/xen/arch/ia64/xen/oprofile/perfmon.c	Thu Jun 07 11:15:24 2007 +0100
     2.2 +++ b/xen/arch/ia64/xen/oprofile/perfmon.c	Thu Jun 07 14:30:21 2007 +0100
     2.3 @@ -37,7 +37,7 @@
     2.4  #include <asm/ptrace.h>
     2.5  
     2.6  // XXX move them to an appropriate header file
     2.7 -extern void xenoprof_log_event(struct vcpu *vcpu,
     2.8 +extern void xenoprof_log_event(struct vcpu *vcpu, struct pt_regs * regs,
     2.9                                 unsigned long eip, int mode, int event);
    2.10  extern int is_active(struct domain *d);
    2.11  
    2.12 @@ -55,7 +55,10 @@ xenoprof_handler(struct task_struct *tas
    2.13      if (!allow_virq || !allow_ints)
    2.14          return 0;
    2.15  
    2.16 -    xenoprof_log_event(current, ip, xenoprofile_get_mode(task, regs), event);
    2.17 +    // Note that log event actually expect cpu_user_regs, cast back 
    2.18 +    // appropriately when doing the backtrace implementation in ia64
    2.19 +    xenoprof_log_event(current, regs, ip, xenoprofile_get_mode(task, regs), 
    2.20 +					   event);
    2.21      
    2.22      // send VIRQ_XENOPROF
    2.23      if (is_active(current->domain) && !ring_0(regs))
     3.1 --- a/xen/arch/x86/oprofile/Makefile	Thu Jun 07 11:15:24 2007 +0100
     3.2 +++ b/xen/arch/x86/oprofile/Makefile	Thu Jun 07 14:30:21 2007 +0100
     3.3 @@ -3,3 +3,4 @@ obj-y += nmi_int.o
     3.4  obj-y += op_model_p4.o
     3.5  obj-y += op_model_ppro.o
     3.6  obj-y += op_model_athlon.o
     3.7 +obj-y += backtrace.o
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen/arch/x86/oprofile/backtrace.c	Thu Jun 07 14:30:21 2007 +0100
     4.3 @@ -0,0 +1,132 @@
     4.4 +/**
     4.5 + * @file backtrace.c
     4.6 + *
     4.7 + * @remark Copyright 2002 OProfile authors
     4.8 + * @remark Read the file COPYING
     4.9 + *
    4.10 + * @author John Levon
    4.11 + * @author David Smith
    4.12 + * Modified for Xen by Amitabha Roy
    4.13 + *
    4.14 + */
    4.15 +
    4.16 +#include<xen/types.h>
    4.17 +#include<asm/page.h>
    4.18 +#include<xen/xenoprof.h>
    4.19 +#include<asm/guest_access.h>
    4.20 +
    4.21 +struct frame_head {
    4.22 +	struct frame_head * ebp;
    4.23 +	unsigned long ret;
    4.24 +} __attribute__((packed));
    4.25 +
    4.26 +static struct frame_head *
    4.27 +dump_hypervisor_backtrace(struct domain *d, struct vcpu *vcpu, 
    4.28 +			  struct frame_head * head, int mode)
    4.29 +{
    4.30 +	if (!xenoprof_add_trace(d, vcpu, head->ret, mode))
    4.31 +		return 0;
    4.32 +
    4.33 +	/* frame pointers should strictly progress back up the stack
    4.34 +	 * (towards higher addresses) */
    4.35 +	if (head >= head->ebp)
    4.36 +		return NULL;
    4.37 +
    4.38 +	return head->ebp;
    4.39 +}
    4.40 +
    4.41 +static struct frame_head *
    4.42 +dump_guest_backtrace(struct domain *d, struct vcpu *vcpu, 
    4.43 +		     struct frame_head * head, int mode)
    4.44 +{
    4.45 +	struct frame_head bufhead[2];
    4.46 +	XEN_GUEST_HANDLE(char) guest_head = guest_handle_from_ptr(head, char);
    4.47 +	
    4.48 +	/* Also check accessibility of one struct frame_head beyond */
    4.49 +	if (!guest_handle_okay(guest_head, sizeof(bufhead)))
    4.50 +		return 0;
    4.51 +	if (__copy_from_guest_offset((char *)bufhead, guest_head, 0, 
    4.52 +	    sizeof(bufhead)))
    4.53 +		return 0;
    4.54 +
    4.55 +	if (!xenoprof_add_trace(d, vcpu, bufhead[0].ret, mode))
    4.56 +	    return 0;
    4.57 +
    4.58 +	/* frame pointers should strictly progress back up the stack
    4.59 +	 * (towards higher addresses) */
    4.60 +	if (head >= bufhead[0].ebp)
    4.61 +		return NULL;
    4.62 +
    4.63 +	return bufhead[0].ebp;
    4.64 +}
    4.65 +
    4.66 +/*
    4.67 + * |             | /\ Higher addresses
    4.68 + * |             |
    4.69 + * --------------- stack base (address of current_thread_info)
    4.70 + * | thread info |
    4.71 + * .             .
    4.72 + * |    stack    |
    4.73 + * --------------- saved regs->ebp value if valid (frame_head address)
    4.74 + * .             .
    4.75 + * --------------- saved regs->rsp value if x86_64
    4.76 + * |             |
    4.77 + * --------------- struct pt_regs * stored on stack if 32-bit
    4.78 + * |             |
    4.79 + * .             .
    4.80 + * |             |
    4.81 + * --------------- %esp
    4.82 + * |             |
    4.83 + * |             | \/ Lower addresses
    4.84 + *
    4.85 + * Thus, regs (or regs->rsp for x86_64) <-> stack base restricts the
    4.86 + * valid(ish) ebp values. Note: (1) for x86_64, NMI and several other
    4.87 + * exceptions use special stacks, maintained by the interrupt stack table
    4.88 + * (IST). These stacks are set up in trap_init() in
    4.89 + * arch/x86_64/kernel/traps.c. Thus, for x86_64, regs now does not point
    4.90 + * to the kernel stack; instead, it points to some location on the NMI
    4.91 + * stack. On the other hand, regs->rsp is the stack pointer saved when the
    4.92 + * NMI occurred. (2) For 32-bit, regs->esp is not valid because the
    4.93 + * processor does not save %esp on the kernel stack when interrupts occur
    4.94 + * in the kernel mode.
    4.95 + */
    4.96 +#if defined(CONFIG_FRAME_POINTER)
    4.97 +static int valid_hypervisor_stack(struct frame_head * head, 
    4.98 +				  struct cpu_user_regs * regs)
    4.99 +{
   4.100 +	unsigned long headaddr = (unsigned long)head;
   4.101 +#ifdef CONFIG_X86_64
   4.102 +	unsigned long stack = (unsigned long)regs->rsp;
   4.103 +#else
   4.104 +	unsigned long stack = (unsigned long)regs;
   4.105 +#endif
   4.106 +	unsigned long stack_base = (stack & ~(STACK_SIZE - 1)) + STACK_SIZE;
   4.107 +
   4.108 +	return headaddr > stack && headaddr < stack_base;
   4.109 +}
   4.110 +#else
   4.111 +/* without fp, it's just junk */
   4.112 +static int valid_hypervisor_stack(struct frame_head * head, 
   4.113 +				  struct cpu_user_regs * regs)
   4.114 +{
   4.115 +	return 0;
   4.116 +}
   4.117 +#endif
   4.118 +
   4.119 +void xenoprof_backtrace(struct domain *d, struct vcpu *vcpu, 
   4.120 +			struct cpu_user_regs * const regs,
   4.121 +			unsigned long depth, int mode)
   4.122 +{
   4.123 +	struct frame_head *head;
   4.124 +
   4.125 +	head = (struct frame_head *)regs->ebp;
   4.126 +
   4.127 +	if (mode > 1) {
   4.128 +		while (depth-- && valid_hypervisor_stack(head, regs))
   4.129 +		    head = dump_hypervisor_backtrace(d, vcpu, head, mode);
   4.130 +		return;
   4.131 +	}
   4.132 +
   4.133 +	while (depth-- && head)
   4.134 +	    head = dump_guest_backtrace(d, vcpu, head, mode);
   4.135 +}
     5.1 --- a/xen/arch/x86/oprofile/op_model_athlon.c	Thu Jun 07 11:15:24 2007 +0100
     5.2 +++ b/xen/arch/x86/oprofile/op_model_athlon.c	Thu Jun 07 14:30:21 2007 +0100
     5.3 @@ -43,8 +43,8 @@
     5.4  
     5.5  static unsigned long reset_value[NUM_COUNTERS];
     5.6  
     5.7 -extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
     5.8 -			       int mode, int event);
     5.9 +extern void xenoprof_log_event(struct vcpu *v, struct cpu_user_regs * regs, 
    5.10 +			       unsigned long eip, int mode, int event);
    5.11  extern int xenoprofile_get_mode(struct vcpu *v,
    5.12  				struct cpu_user_regs * const regs);
    5.13  
    5.14 @@ -130,7 +130,7 @@ static int athlon_check_ctrs(unsigned in
    5.15  	for (i = 0 ; i < NUM_COUNTERS; ++i) {
    5.16  		CTR_READ(low, high, msrs, i);
    5.17  		if (CTR_OVERFLOWED(low)) {
    5.18 -			xenoprof_log_event(current, eip, mode, i);
    5.19 +			xenoprof_log_event(current, regs, eip, mode, i);
    5.20  			CTR_WRITE(reset_value[i], msrs, i);
    5.21  			ovf = 1;
    5.22  		}
     6.1 --- a/xen/arch/x86/oprofile/op_model_p4.c	Thu Jun 07 11:15:24 2007 +0100
     6.2 +++ b/xen/arch/x86/oprofile/op_model_p4.c	Thu Jun 07 14:30:21 2007 +0100
     6.3 @@ -620,8 +620,8 @@ static void p4_setup_ctrs(struct op_msrs
     6.4  	}
     6.5  }
     6.6  
     6.7 -extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
     6.8 -			       int mode, int event);
     6.9 +extern void xenoprof_log_event(struct vcpu *v, struct cpu_user_regs * regs, 
    6.10 +			       unsigned long eip, int mode, int event);
    6.11  extern int xenoprofile_get_mode(struct vcpu *v,
    6.12  				struct cpu_user_regs * const regs);
    6.13  
    6.14 @@ -664,8 +664,8 @@ static int p4_check_ctrs(unsigned int co
    6.15  		CCCR_READ(low, high, real);
    6.16   		CTR_READ(ctr, high, real);
    6.17  		if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) {
    6.18 -			xenoprof_log_event(current, eip, mode, i);
    6.19 - 			CTR_WRITE(reset_value[i], real);
    6.20 +			xenoprof_log_event(current, regs, eip, mode, i);
    6.21 +			CTR_WRITE(reset_value[i], real);
    6.22  			CCCR_CLEAR_OVF(low);
    6.23  			CCCR_WRITE(low, high, real);
    6.24   			CTR_WRITE(reset_value[i], real);
     7.1 --- a/xen/arch/x86/oprofile/op_model_ppro.c	Thu Jun 07 11:15:24 2007 +0100
     7.2 +++ b/xen/arch/x86/oprofile/op_model_ppro.c	Thu Jun 07 14:30:21 2007 +0100
     7.3 @@ -88,8 +88,8 @@ static void ppro_setup_ctrs(struct op_ms
     7.4  	}
     7.5  }
     7.6  
     7.7 -extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
     7.8 -			       int mode, int event);
     7.9 +extern void xenoprof_log_event(struct vcpu *v, struct cpu_user_regs * regs, 
    7.10 +			       unsigned long eip, int mode, int event);
    7.11  extern int xenoprofile_get_mode(struct vcpu *v,
    7.12  				struct cpu_user_regs * const regs);
    7.13   
    7.14 @@ -106,7 +106,7 @@ static int ppro_check_ctrs(unsigned int 
    7.15  	for (i = 0 ; i < NUM_COUNTERS; ++i) {
    7.16  		CTR_READ(low, high, msrs, i);
    7.17  		if (CTR_OVERFLOWED(low)) {
    7.18 -			xenoprof_log_event(current, eip, mode, i);
    7.19 +			xenoprof_log_event(current, regs, eip, mode, i);
    7.20  			CTR_WRITE(reset_value[i], msrs, i);
    7.21  			ovf = 1;
    7.22  		}
     8.1 --- a/xen/arch/x86/traps.c	Thu Jun 07 11:15:24 2007 +0100
     8.2 +++ b/xen/arch/x86/traps.c	Thu Jun 07 14:30:21 2007 +0100
     8.3 @@ -167,7 +167,7 @@ static void show_guest_stack(struct cpu_
     8.4      printk("\n");
     8.5  }
     8.6  
     8.7 -#ifdef NDEBUG
     8.8 +#if !defined(CONFIG_FRAME_POINTER)
     8.9  
    8.10  static void show_trace(struct cpu_user_regs *regs)
    8.11  {
     9.1 --- a/xen/common/xenoprof.c	Thu Jun 07 11:15:24 2007 +0100
     9.2 +++ b/xen/common/xenoprof.c	Thu Jun 07 14:30:21 2007 +0100
     9.3 @@ -31,6 +31,7 @@ unsigned int pdomains;
     9.4  unsigned int activated;
     9.5  struct domain *xenoprof_primary_profiler;
     9.6  int xenoprof_state = XENOPROF_IDLE;
     9.7 +static unsigned long backtrace_depth;
     9.8  
     9.9  u64 total_samples;
    9.10  u64 invalid_buffer_samples;
    9.11 @@ -205,7 +206,8 @@ static int alloc_xenoprof_struct(
    9.12      i = 0;
    9.13      for_each_vcpu ( d, v )
    9.14      {
    9.15 -        xenoprof_buf_t *buf = (xenoprof_buf_t *)&d->xenoprof->rawbuf[i * bufsize];
    9.16 +        xenoprof_buf_t *buf = (xenoprof_buf_t *)
    9.17 +            &d->xenoprof->rawbuf[i * bufsize];
    9.18  
    9.19          d->xenoprof->vcpu[v->vcpu_id].event_size = max_samples;
    9.20          d->xenoprof->vcpu[v->vcpu_id].buffer = buf;
    9.21 @@ -414,21 +416,82 @@ static int add_passive_list(XEN_GUEST_HA
    9.22      return ret;
    9.23  }
    9.24  
    9.25 -void xenoprof_log_event(
    9.26 -    struct vcpu *vcpu, unsigned long eip, int mode, int event)
    9.27 +
    9.28 +/* Get space in the buffer */
    9.29 +static int xenoprof_buf_space(struct domain *d, xenoprof_buf_t * buf, int size)
    9.30 +{
    9.31 +    int head, tail;
    9.32 +
    9.33 +    head = xenoprof_buf(d, buf, event_head);
    9.34 +    tail = xenoprof_buf(d, buf, event_tail);
    9.35 +
    9.36 +    return ((tail > head) ? 0 : size) + tail - head - 1;
    9.37 +}
    9.38 +
    9.39 +/* Check for space and add a sample. Return 1 if successful, 0 otherwise. */
    9.40 +static int xenoprof_add_sample(struct domain *d, xenoprof_buf_t *buf,
    9.41 +                               unsigned long eip, int mode, int event)
    9.42 +{
    9.43 +    int head, tail, size;
    9.44 +
    9.45 +    head = xenoprof_buf(d, buf, event_head);
    9.46 +    tail = xenoprof_buf(d, buf, event_tail);
    9.47 +    size = xenoprof_buf(d, buf, event_size);
    9.48 +    
    9.49 +    /* make sure indexes in shared buffer are sane */
    9.50 +    if ( (head < 0) || (head >= size) || (tail < 0) || (tail >= size) )
    9.51 +    {
    9.52 +        corrupted_buffer_samples++;
    9.53 +        return 0;
    9.54 +    }
    9.55 +
    9.56 +    if ( xenoprof_buf_space(d, buf, size) > 0 )
    9.57 +    {
    9.58 +        xenoprof_buf(d, buf, event_log[head].eip) = eip;
    9.59 +        xenoprof_buf(d, buf, event_log[head].mode) = mode;
    9.60 +        xenoprof_buf(d, buf, event_log[head].event) = event;
    9.61 +        head++;
    9.62 +        if ( head >= size )
    9.63 +            head = 0;
    9.64 +        
    9.65 +        xenoprof_buf(d, buf, event_head) = head;
    9.66 +    }
    9.67 +    else
    9.68 +    {
    9.69 +        xenoprof_buf(d, buf, lost_samples)++;
    9.70 +        lost_samples++;
    9.71 +        return 0;
    9.72 +    }
    9.73 +
    9.74 +    return 1;
    9.75 +}
    9.76 +
    9.77 +int xenoprof_add_trace(struct domain *d, struct vcpu *vcpu,
    9.78 +                       unsigned long eip, int mode)
    9.79 +{
    9.80 +    xenoprof_buf_t *buf = d->xenoprof->vcpu[vcpu->vcpu_id].buffer;
    9.81 +
    9.82 +    /* Do not accidentally write an escape code due to a broken frame. */
    9.83 +    if ( eip == XENOPROF_ESCAPE_CODE )
    9.84 +    {
    9.85 +        invalid_buffer_samples++;
    9.86 +        return 0;
    9.87 +    }
    9.88 +
    9.89 +    return xenoprof_add_sample(d, buf, eip, mode, 0);
    9.90 +}
    9.91 +
    9.92 +void xenoprof_log_event(struct vcpu *vcpu, 
    9.93 +                        struct cpu_user_regs * regs, unsigned long eip, 
    9.94 +                        int mode, int event)
    9.95  {
    9.96      struct domain *d = vcpu->domain;
    9.97      struct xenoprof_vcpu *v;
    9.98      xenoprof_buf_t *buf;
    9.99 -    int head;
   9.100 -    int tail;
   9.101 -    int size;
   9.102 -
   9.103  
   9.104      total_samples++;
   9.105  
   9.106 -    /* ignore samples of un-monitored domains */
   9.107 -    /* Count samples in idle separate from other unmonitored domains */
   9.108 +    /* Ignore samples of un-monitored domains. */
   9.109      if ( !is_profiled(d) )
   9.110      {
   9.111          others_samples++;
   9.112 @@ -436,41 +499,29 @@ void xenoprof_log_event(
   9.113      }
   9.114  
   9.115      v = &d->xenoprof->vcpu[vcpu->vcpu_id];
   9.116 -
   9.117 -    /* Sanity check. Should never happen */ 
   9.118      if ( v->buffer == NULL )
   9.119      {
   9.120          invalid_buffer_samples++;
   9.121          return;
   9.122      }
   9.123 -
   9.124 +    
   9.125      buf = v->buffer;
   9.126  
   9.127 -    head = xenoprof_buf(d, buf, event_head);
   9.128 -    tail = xenoprof_buf(d, buf, event_tail);
   9.129 -    size = v->event_size;
   9.130 -
   9.131 -    /* make sure indexes in shared buffer are sane */
   9.132 -    if ( (head < 0) || (head >= size) || (tail < 0) || (tail >= size) )
   9.133 +    /* Provide backtrace if requested. */
   9.134 +    if ( backtrace_depth > 0 )
   9.135      {
   9.136 -        corrupted_buffer_samples++;
   9.137 -        return;
   9.138 +        if ( (xenoprof_buf_space(d, buf, v->event_size) < 2) ||
   9.139 +             !xenoprof_add_sample(d, buf, XENOPROF_ESCAPE_CODE, mode, 
   9.140 +                                  XENOPROF_TRACE_BEGIN) )
   9.141 +        {
   9.142 +            xenoprof_buf(d, buf, lost_samples)++;
   9.143 +            lost_samples++;
   9.144 +            return;
   9.145 +        }
   9.146      }
   9.147  
   9.148 -    if ( (head == tail - 1) || (head == size - 1 && tail == 0) )
   9.149 -    {
   9.150 -        xenoprof_buf(d, buf, lost_samples)++;
   9.151 -        lost_samples++;
   9.152 -    }
   9.153 -    else
   9.154 +    if ( xenoprof_add_sample(d, buf, eip, mode, event) )
   9.155      {
   9.156 -        xenoprof_buf(d, buf, event_log[head].eip) = eip;
   9.157 -        xenoprof_buf(d, buf, event_log[head].mode) = mode;
   9.158 -        xenoprof_buf(d, buf, event_log[head].event) = event;
   9.159 -        head++;
   9.160 -        if ( head >= size )
   9.161 -            head = 0;
   9.162 -        xenoprof_buf(d, buf, event_head) = head;
   9.163          if ( is_active(vcpu->domain) )
   9.164              active_samples++;
   9.165          else
   9.166 @@ -481,9 +532,15 @@ void xenoprof_log_event(
   9.167              xenoprof_buf(d, buf, kernel_samples)++;
   9.168          else
   9.169              xenoprof_buf(d, buf, xen_samples)++;
   9.170 +    
   9.171      }
   9.172 +
   9.173 +    if ( backtrace_depth > 0 )
   9.174 +        xenoprof_backtrace(d, vcpu, regs, backtrace_depth, mode);
   9.175  }
   9.176  
   9.177 +
   9.178 +
   9.179  static int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
   9.180  {
   9.181      struct xenoprof_init xenoprof_init;
   9.182 @@ -685,7 +742,8 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
   9.183          break;
   9.184  
   9.185      case XENOPROF_stop:
   9.186 -        if ( xenoprof_state != XENOPROF_PROFILING ) {
   9.187 +        if ( xenoprof_state != XENOPROF_PROFILING )
   9.188 +        {
   9.189              ret = -EPERM;
   9.190              break;
   9.191          }
   9.192 @@ -729,9 +787,18 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
   9.193              activated = 0;
   9.194              adomains=0;
   9.195              xenoprof_primary_profiler = NULL;
   9.196 +            backtrace_depth=0;
   9.197              ret = 0;
   9.198          }
   9.199          break;
   9.200 +                
   9.201 +    case XENOPROF_set_backtrace:
   9.202 +        ret = 0;
   9.203 +        if ( !xenoprof_backtrace_supported() )
   9.204 +            ret = -EINVAL;
   9.205 +        else if ( copy_from_guest(&backtrace_depth, arg, 1) )
   9.206 +            ret = -EFAULT;
   9.207 +        break;
   9.208  
   9.209      default:
   9.210          ret = -ENOSYS;
    10.1 --- a/xen/include/asm-ia64/xenoprof.h	Thu Jun 07 11:15:24 2007 +0100
    10.2 +++ b/xen/include/asm-ia64/xenoprof.h	Thu Jun 07 14:30:21 2007 +0100
    10.3 @@ -37,7 +37,17 @@ void xenoprof_arch_release_counters(void
    10.4  struct vcpu;
    10.5  struct cpu_user_regs;
    10.6  int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
    10.7 -
    10.8 +static inline int xenoprof_backtrace_supported(void)
    10.9 +{
   10.10 +    return 0;
   10.11 +}
   10.12 +static inline void xenoprof_backtrace(
   10.13 +    struct domain *d, struct vcpu *vcpu, 
   10.14 +    struct pt_regs *const regs, unsigned long depth, int mode)
   10.15 +{
   10.16 +    /* To be implemented */
   10.17 +    return;
   10.18 +}
   10.19  #define xenoprof_shared_gmfn(d, gmaddr, maddr)  \
   10.20      assign_domain_page((d), (gmaddr), (maddr));
   10.21  
    11.1 --- a/xen/include/asm-x86/xenoprof.h	Thu Jun 07 11:15:24 2007 +0100
    11.2 +++ b/xen/include/asm-x86/xenoprof.h	Thu Jun 07 14:30:21 2007 +0100
    11.3 @@ -46,7 +46,18 @@ int xenoprof_arch_counter(XEN_GUEST_HAND
    11.4  
    11.5  struct vcpu;
    11.6  struct cpu_user_regs;
    11.7 +
    11.8  int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
    11.9 +
   11.10 +static inline int xenoprof_backtrace_supported(void)
   11.11 +{
   11.12 +    return 1;
   11.13 +}
   11.14 +
   11.15 +void xenoprof_backtrace(
   11.16 +    struct domain *d, struct vcpu *vcpu, 
   11.17 +    struct cpu_user_regs *const regs, unsigned long depth, int mode);
   11.18 +
   11.19  #define xenoprof_shared_gmfn(d, gmaddr, maddr)                      \
   11.20      do {                                                            \
   11.21          (void)(maddr);                                              \
    12.1 --- a/xen/include/public/xenoprof.h	Thu Jun 07 11:15:24 2007 +0100
    12.2 +++ b/xen/include/public/xenoprof.h	Thu Jun 07 14:30:21 2007 +0100
    12.3 @@ -49,7 +49,8 @@
    12.4  #define XENOPROF_release_counters   12
    12.5  #define XENOPROF_shutdown           13
    12.6  #define XENOPROF_get_buffer         14
    12.7 -#define XENOPROF_last_op            14
    12.8 +#define XENOPROF_set_backtrace      15
    12.9 +#define XENOPROF_last_op            15
   12.10  
   12.11  #define MAX_OPROF_EVENTS    32
   12.12  #define MAX_OPROF_DOMAINS   25
   12.13 @@ -62,6 +63,11 @@ struct event_log {
   12.14      uint8_t event;
   12.15  };
   12.16  
   12.17 +/* PC value that indicates a special code */
   12.18 +#define XENOPROF_ESCAPE_CODE ~0UL
   12.19 +/* Transient events for the xenoprof->oprofile cpu buf */
   12.20 +#define XENOPROF_TRACE_BEGIN 1
   12.21 +
   12.22  /* Xenoprof buffer shared between Xen and domain - 1 per VCPU */
   12.23  struct xenoprof_buf {
   12.24      uint32_t event_head;
    13.1 --- a/xen/include/xen/xenoprof.h	Thu Jun 07 11:15:24 2007 +0100
    13.2 +++ b/xen/include/xen/xenoprof.h	Thu Jun 07 14:30:21 2007 +0100
    13.3 @@ -66,6 +66,8 @@ struct domain;
    13.4  void free_xenoprof_pages(struct domain *d);
    13.5  
    13.6  int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg);
    13.7 +int xenoprof_add_trace(struct domain *d, struct vcpu *v, 
    13.8 +                       unsigned long eip, int mode);
    13.9  
   13.10  extern struct domain *xenoprof_primary_profiler;
   13.11