All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add callgraph support to Xenoprofile
@ 2007-06-07  3:34 Amitabha Roy
  2007-06-07  9:01 ` Keir Fraser
  0 siblings, 1 reply; 6+ messages in thread
From: Amitabha Roy @ 2007-06-07  3:34 UTC (permalink / raw)
  To: Xen developers mailing list; +Cc: Keir Fraser, Santos, Jose Renato G

[-- Attachment #1: Type: text/plain, Size: 331 bytes --]

Hi

This patch implements backtrace support in Xenoprofile. It's been
reviewed by Renato. I've tested it out successfully on xen x86_32 and
x86_64. I've added stubs for the backtrace for ia64 to ensure that it
compiles ok but havent been able to test that out. However, I believe
there shouldn't be any problems.

Thanks
-Amitabha

[-- Attachment #2: xenoprof_backtrace_patch.txt --]
[-- Type: text/plain, Size: 17804 bytes --]

# HG changeset patch
# User root@localhost.localdomain
# Date 1181186537 -19800
# Node ID 1d47ef825eb4f53fdb6d686ddf4d2ae9e47a70a0
# Parent  bd3d6b4c52ec809f080c89c4ffcf61dc6e445978
Add backtrace support to xenoprof

Signed-off-by: Amitabha Roy <amitabha.roy@gmail.com>
Reviewed-by: Jose Renato G Santos <joserenato.santos@hp.com>

diff -r bd3d6b4c52ec -r 1d47ef825eb4 Config.mk
--- a/Config.mk	Fri Jun 01 14:50:52 2007 +0100
+++ b/Config.mk	Thu Jun 07 08:52:17 2007 +0530
@@ -12,13 +12,19 @@ XEN_TARGET_X86_PAE  ?= y
 XEN_TARGET_X86_PAE  ?= y
 endif
 
+ifneq ($(FRAME_POINTER),y)
+CONFIG_FRAME_POINTER ?= -fomit-frame-pointer
+else
+CONFIG_FRAME_POINTER ?= -DCONFIG_FRAME_POINTER -fno-omit-frame-pointer
+endif 
+
 CONFIG_$(XEN_OS) := y
 
 SHELL     ?= /bin/sh
 
 # Tools to run on system hosting the build
 HOSTCC     = gcc
-HOSTCFLAGS = -Wall -Werror -Wstrict-prototypes -O2 -fomit-frame-pointer
+HOSTCFLAGS = -Wall -Werror -Wstrict-prototypes -O2 $(CONFIG_FRAME_POINTER)
 
 DISTDIR     ?= $(XEN_ROOT)/dist
 DESTDIR     ?= /
diff -r bd3d6b4c52ec -r 1d47ef825eb4 config/StdGNU.mk
--- a/config/StdGNU.mk	Fri Jun 01 14:50:52 2007 +0100
+++ b/config/StdGNU.mk	Thu Jun 07 08:52:17 2007 +0530
@@ -26,8 +26,8 @@ SHLIB_CFLAGS = -shared
 
 ifneq ($(debug),y)
 # Optimisation flags are overridable
-CFLAGS ?= -O2 -fomit-frame-pointer
+CFLAGS ?= -O2 $(CONFIG_FRAME_POINTER)
 else
 # Less than -O1 produces bad code and large stack frames
-CFLAGS ?= -O1 -fno-omit-frame-pointer
+CFLAGS ?= -O1 $(CONFIG_FRAME_POINTER)
 endif
diff -r bd3d6b4c52ec -r 1d47ef825eb4 linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c	Thu Jun 07 08:52:17 2007 +0530
@@ -51,6 +51,8 @@ static int xenoprof_is_primary = 0;
 static int xenoprof_is_primary = 0;
 static int active_defined;
 
+extern unsigned long backtrace_depth;
+
 /* Number of buffers in shared area (one per VCPU) */
 int nbuf;
 /* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
@@ -115,38 +117,57 @@ unsigned int pdomains;
 unsigned int pdomains;
 struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
 
+
+/* Check whether the given entry is an escape code */
+static int xenoprof_is_escape(xenoprof_buf_t * buf, int tail){
+    return (buf->event_log[tail].eip == XENOPROF_ESCAPE_CODE);
+}
+
+/* Get the event at the given entry  */
+static uint8_t xenoprof_get_event(xenoprof_buf_t * buf, int tail){
+    return (buf->event_log[tail].event);
+}
+
+
+
+
 static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive)
 {
 	int head, tail, size;
+	int tracing = 0;
 
 	head = buf->event_head;
 	tail = buf->event_tail;
 	size = buf->event_size;
 
-	if (tail > head) {
-		while (tail < size) {
-			oprofile_add_pc(buf->event_log[tail].eip,
-					buf->event_log[tail].mode,
-					buf->event_log[tail].event);
+	while(tail != head) {
+		if(xenoprof_is_escape(buf, tail) && 
+		   xenoprof_get_event(buf, tail)==XENOPROF_TRACE_BEGIN){
+			tracing=1;
+			oprofile_add_pc(ESCAPE_CODE, buf->event_log[tail].mode, 
+					CPU_TRACE_BEGIN); 
 			if (!is_passive)
 				oprofile_samples++;
 			else
 				p_oprofile_samples++;
-			tail++;
-		}
-		tail = 0;
-	}
-	while (tail < head) {
-		oprofile_add_pc(buf->event_log[tail].eip,
-				buf->event_log[tail].mode,
-				buf->event_log[tail].event);
-		if (!is_passive)
-			oprofile_samples++;
-		else
-			p_oprofile_samples++;
+			
+		}
+		else{
+			oprofile_add_pc(buf->event_log[tail].eip,
+					buf->event_log[tail].mode,
+					buf->event_log[tail].event);
+			if(!tracing){
+				if (!is_passive)
+					oprofile_samples++;
+				else
+					p_oprofile_samples++;
+			}
+       
+		}
 		tail++;
-	}
-
+		if(tail==size)
+		    tail=0;
+	}
 	buf->event_tail = tail;
 }
 
@@ -294,9 +315,16 @@ static int xenoprof_setup(void)
 			active_defined = 1;
 		}
 
+		if(backtrace_depth > 0){
+		    ret = HYPERVISOR_xenoprof_op(XENOPROF_set_backtrace, 
+						 &backtrace_depth);
+		    if (ret)
+			backtrace_depth = 0;
+		}
 		ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
 		if (ret)
 			goto err;
+		
 		xenoprof_arch_counter();
 		ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL);
 
@@ -438,8 +466,21 @@ out:
 	for (j = 0; j < i; j++)
 		xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]);
 
- 	return ret;
-}
+	return ret;
+}
+
+
+/* The dummy backtrace function to keep oprofile happy
+ * The real backtrace is done in xen
+ */
+static void xenoprof_dummy_backtrace(struct pt_regs * const regs, 
+				     unsigned int depth){
+	/* this should never be called */
+	BUG();
+	return;
+}
+
+
 
 struct oprofile_operations xenoprof_ops = {
 #ifdef HAVE_XENOPROF_CREATE_FILES
@@ -450,7 +491,8 @@ struct oprofile_operations xenoprof_ops 
 	.setup 		= xenoprof_setup,
 	.shutdown	= xenoprof_shutdown,
 	.start		= xenoprof_start,
-	.stop		= xenoprof_stop
+	.stop		= xenoprof_stop,
+	.backtrace	= xenoprof_dummy_backtrace
 };
 
 
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/arch/ia64/xen/oprofile/perfmon.c
--- a/xen/arch/ia64/xen/oprofile/perfmon.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/ia64/xen/oprofile/perfmon.c	Thu Jun 07 08:52:17 2007 +0530
@@ -37,7 +37,7 @@
 #include <asm/ptrace.h>
 
 // XXX move them to an appropriate header file
-extern void xenoprof_log_event(struct vcpu *vcpu,
+extern void xenoprof_log_event(struct vcpu *vcpu, struct pt_regs * regs,
                                unsigned long eip, int mode, int event);
 extern int is_active(struct domain *d);
 
@@ -55,7 +55,10 @@ xenoprof_handler(struct task_struct *tas
     if (!allow_virq || !allow_ints)
         return 0;
 
-    xenoprof_log_event(current, ip, xenoprofile_get_mode(task, regs), event);
+    // Note that log event actually expect cpu_user_regs, cast back 
+    // appropriately when doing the backtrace implementation in ia64
+    xenoprof_log_event(current, regs, ip, xenoprofile_get_mode(task, regs), 
+					   event);
     
     // send VIRQ_XENOPROF
     if (is_active(current->domain) && !ring_0(regs))
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/arch/x86/oprofile/Makefile
--- a/xen/arch/x86/oprofile/Makefile	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/x86/oprofile/Makefile	Thu Jun 07 08:52:17 2007 +0530
@@ -3,3 +3,4 @@ obj-y += op_model_p4.o
 obj-y += op_model_p4.o
 obj-y += op_model_ppro.o
 obj-y += op_model_athlon.o
+obj-y += backtrace.o
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/arch/x86/oprofile/op_model_athlon.c
--- a/xen/arch/x86/oprofile/op_model_athlon.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/x86/oprofile/op_model_athlon.c	Thu Jun 07 08:52:17 2007 +0530
@@ -43,8 +43,8 @@
 
 static unsigned long reset_value[NUM_COUNTERS];
 
-extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
-			       int mode, int event);
+extern void xenoprof_log_event(struct vcpu *v, struct cpu_user_regs * regs, 
+			       unsigned long eip, int mode, int event);
 extern int xenoprofile_get_mode(struct vcpu *v,
 				struct cpu_user_regs * const regs);
 
@@ -130,7 +130,7 @@ static int athlon_check_ctrs(unsigned in
 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
 		CTR_READ(low, high, msrs, i);
 		if (CTR_OVERFLOWED(low)) {
-			xenoprof_log_event(current, eip, mode, i);
+			xenoprof_log_event(current, regs, eip, mode, i);
 			CTR_WRITE(reset_value[i], msrs, i);
 			ovf = 1;
 		}
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/arch/x86/oprofile/op_model_p4.c
--- a/xen/arch/x86/oprofile/op_model_p4.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/x86/oprofile/op_model_p4.c	Thu Jun 07 08:52:17 2007 +0530
@@ -620,8 +620,8 @@ static void p4_setup_ctrs(struct op_msrs
 	}
 }
 
-extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
-			       int mode, int event);
+extern void xenoprof_log_event(struct vcpu *v, struct cpu_user_regs * regs, 
+			       unsigned long eip, int mode, int event);
 extern int xenoprofile_get_mode(struct vcpu *v,
 				struct cpu_user_regs * const regs);
 
@@ -664,8 +664,8 @@ static int p4_check_ctrs(unsigned int co
 		CCCR_READ(low, high, real);
  		CTR_READ(ctr, high, real);
 		if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) {
-			xenoprof_log_event(current, eip, mode, i);
- 			CTR_WRITE(reset_value[i], real);
+			xenoprof_log_event(current, regs, eip, mode, i);
+			CTR_WRITE(reset_value[i], real);
 			CCCR_CLEAR_OVF(low);
 			CCCR_WRITE(low, high, real);
  			CTR_WRITE(reset_value[i], real);
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/arch/x86/oprofile/op_model_ppro.c
--- a/xen/arch/x86/oprofile/op_model_ppro.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/x86/oprofile/op_model_ppro.c	Thu Jun 07 08:52:17 2007 +0530
@@ -88,8 +88,8 @@ static void ppro_setup_ctrs(struct op_ms
 	}
 }
 
-extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
-			       int mode, int event);
+extern void xenoprof_log_event(struct vcpu *v, struct cpu_user_regs * regs, 
+			       unsigned long eip, int mode, int event);
 extern int xenoprofile_get_mode(struct vcpu *v,
 				struct cpu_user_regs * const regs);
  
@@ -106,7 +106,7 @@ static int ppro_check_ctrs(unsigned int 
 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
 		CTR_READ(low, high, msrs, i);
 		if (CTR_OVERFLOWED(low)) {
-			xenoprof_log_event(current, eip, mode, i);
+			xenoprof_log_event(current, regs, eip, mode, i);
 			CTR_WRITE(reset_value[i], msrs, i);
 			ovf = 1;
 		}
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/common/xenoprof.c
--- a/xen/common/xenoprof.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/common/xenoprof.c	Thu Jun 07 08:52:17 2007 +0530
@@ -31,6 +31,7 @@ unsigned int activated;
 unsigned int activated;
 struct domain *xenoprof_primary_profiler;
 int xenoprof_state = XENOPROF_IDLE;
+static unsigned long backtrace_depth=0;
 
 u64 total_samples;
 u64 invalid_buffer_samples;
@@ -414,55 +415,47 @@ static int add_passive_list(XEN_GUEST_HA
     return ret;
 }
 
-void xenoprof_log_event(
-    struct vcpu *vcpu, unsigned long eip, int mode, int event)
-{
-    struct domain *d = vcpu->domain;
-    struct xenoprof_vcpu *v;
-    xenoprof_buf_t *buf;
+
+/* Get space in the buffer */
+static int xenoprof_buf_space(struct domain *d, xenoprof_buf_t * buf, int size)
+{
+    int head;
+    int tail;
+
+    head = xenoprof_buf(d, buf, event_head);
+    tail = xenoprof_buf(d, buf, event_tail);
+
+    if(tail > head){
+        return ((tail - head) - 1);
+    }
+    else {
+        return (size - (head -tail) -1);
+    }
+}
+
+/* check for space and add a sample
+ * return 1 if successful, 0 otherwise
+ */
+
+inline int xenoprof_add_sample(struct domain *d, xenoprof_buf_t *buf, 
+                               unsigned long eip, int mode, int event)
+{
     int head;
     int tail;
     int size;
 
-
-    total_samples++;
-
-    /* ignore samples of un-monitored domains */
-    /* Count samples in idle separate from other unmonitored domains */
-    if ( !is_profiled(d) )
-    {
-        others_samples++;
-        return;
-    }
-
-    v = &d->xenoprof->vcpu[vcpu->vcpu_id];
-
-    /* Sanity check. Should never happen */ 
-    if ( v->buffer == NULL )
-    {
-        invalid_buffer_samples++;
-        return;
-    }
-
-    buf = v->buffer;
-
     head = xenoprof_buf(d, buf, event_head);
     tail = xenoprof_buf(d, buf, event_tail);
-    size = v->event_size;
-
+    size = xenoprof_buf(d, buf, event_size);
+    
     /* make sure indexes in shared buffer are sane */
     if ( (head < 0) || (head >= size) || (tail < 0) || (tail >= size) )
     {
         corrupted_buffer_samples++;
-        return;
-    }
-
-    if ( (head == tail - 1) || (head == size - 1 && tail == 0) )
-    {
-        xenoprof_buf(d, buf, lost_samples)++;
-        lost_samples++;
-    }
-    else
+        return 0;
+    }
+
+    if(xenoprof_buf_space(d, buf, size) > 0)
     {
         xenoprof_buf(d, buf, event_log[head].eip) = eip;
         xenoprof_buf(d, buf, event_log[head].mode) = mode;
@@ -470,7 +463,87 @@ void xenoprof_log_event(
         head++;
         if ( head >= size )
             head = 0;
+        
         xenoprof_buf(d, buf, event_head) = head;
+    }
+    else
+    {
+        xenoprof_buf(d, buf, lost_samples)++;
+        lost_samples++;
+        return 0;
+    }
+    return 1;
+}
+
+/* add a trace to the buffer */
+int xenoprof_add_trace(struct domain *d, struct vcpu *vcpu,
+                       unsigned long eip, int mode)
+{
+    xenoprof_buf_t * buf;
+    
+    /* Assume buffer is not null, it should have been checked before entering
+     * the arch specific backtrace code
+     */
+    
+    buf = (d->xenoprof->vcpu[vcpu->vcpu_id]).buffer;    
+
+    /* Ensure we do not accidentally write an escape code due to 
+     * a broken frame
+     */
+
+    if(eip==XENOPROF_ESCAPE_CODE)
+    {
+        invalid_buffer_samples++;
+        return 0;
+    }
+
+    return xenoprof_add_sample(d, buf, eip, mode, 0);
+}
+
+void xenoprof_log_event(
+    struct vcpu *vcpu, struct cpu_user_regs * regs, unsigned long eip, int mode,
+    int event)
+{
+    struct domain *d = vcpu->domain;
+    struct xenoprof_vcpu *v;
+    xenoprof_buf_t *buf;
+
+    total_samples++;
+
+    /* ignore samples of un-monitored domains */
+    /* Count samples in idle separate from other unmonitored domains */
+    if ( !is_profiled(d) )
+    {
+        others_samples++;
+        return;
+    }
+
+    v = &d->xenoprof->vcpu[vcpu->vcpu_id];
+    
+    if(v->buffer == NULL)
+    {
+        invalid_buffer_samples++;
+        return;
+    }
+    
+    buf = v->buffer;
+
+    /* Backtrace if asked for */
+    if(backtrace_depth > 0)
+    {
+        if(xenoprof_buf_space(d, buf, v->event_size) < 2){
+            xenoprof_buf(d, buf, lost_samples)++;
+            lost_samples++;
+            return;
+        }       
+        if(!xenoprof_add_sample(d, buf, XENOPROF_ESCAPE_CODE, mode, 
+		   XENOPROF_TRACE_BEGIN))
+        { /* could happen due to a corrupted buffer */
+            return;
+        }
+    }
+    if(xenoprof_add_sample(d, buf, eip, mode, event))
+    {
         if ( is_active(vcpu->domain) )
             active_samples++;
         else
@@ -481,8 +554,15 @@ void xenoprof_log_event(
             xenoprof_buf(d, buf, kernel_samples)++;
         else
             xenoprof_buf(d, buf, xen_samples)++;
-    }
-}
+    
+    }
+    if(backtrace_depth > 0)
+    {
+        backtrace(d, vcpu, regs, backtrace_depth, mode);
+    }
+}
+
+
 
 static int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
 {
@@ -729,7 +809,18 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
             activated = 0;
             adomains=0;
             xenoprof_primary_profiler = NULL;
+            backtrace_depth=0;
             ret = 0;
+        }
+        break;
+                
+    case XENOPROF_set_backtrace:
+        ret = 0;
+        if(!arch_backtrace_supported()){
+            ret = -EINVAL;
+        }
+        else if(copy_from_guest(&backtrace_depth, arg, 1)){
+            ret=-EFAULT;
         }
         break;
 
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/include/asm-ia64/xenoprof.h
--- a/xen/include/asm-ia64/xenoprof.h	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/include/asm-ia64/xenoprof.h	Thu Jun 07 08:52:17 2007 +0530
@@ -37,7 +37,16 @@ struct vcpu;
 struct vcpu;
 struct cpu_user_regs;
 int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
-
+static inline int arch_backtrace_supported(void)
+{
+	return 0;
+}
+static inline void backtrace(struct domain *d, struct vcpu *vcpu, 
+                      struct pt_regs *const regs, unsigned long depth, int mode)
+{
+    /* To be implemented */
+    return;
+}
 #define xenoprof_shared_gmfn(d, gmaddr, maddr)  \
     assign_domain_page((d), (gmaddr), (maddr));
 
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/include/asm-x86/xenoprof.h
--- a/xen/include/asm-x86/xenoprof.h	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/include/asm-x86/xenoprof.h	Thu Jun 07 08:52:17 2007 +0530
@@ -47,6 +47,12 @@ struct vcpu;
 struct vcpu;
 struct cpu_user_regs;
 int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
+static inline int arch_backtrace_supported(void)
+{
+	return 1;
+}
+void backtrace(struct domain *d, struct vcpu *vcpu, 
+               struct cpu_user_regs *const regs, unsigned long depth, int mode);
 #define xenoprof_shared_gmfn(d, gmaddr, maddr)                      \
     do {                                                            \
         (void)(maddr);                                              \
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/include/public/xenoprof.h
--- a/xen/include/public/xenoprof.h	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/include/public/xenoprof.h	Thu Jun 07 08:52:17 2007 +0530
@@ -49,7 +49,8 @@
 #define XENOPROF_release_counters   12
 #define XENOPROF_shutdown           13
 #define XENOPROF_get_buffer         14
-#define XENOPROF_last_op            14
+#define XENOPROF_set_backtrace      15
+#define XENOPROF_last_op            15
 
 #define MAX_OPROF_EVENTS    32
 #define MAX_OPROF_DOMAINS   25
@@ -61,6 +62,11 @@ struct event_log {
     uint8_t mode;
     uint8_t event;
 };
+
+/* PC value that indicates a special code */
+#define XENOPROF_ESCAPE_CODE ~0UL
+/* Transient events for the xenoprof->oprofile cpu buf */
+#define XENOPROF_TRACE_BEGIN 1
 
 /* Xenoprof buffer shared between Xen and domain - 1 per VCPU */
 struct xenoprof_buf {
diff -r bd3d6b4c52ec -r 1d47ef825eb4 xen/include/xen/xenoprof.h
--- a/xen/include/xen/xenoprof.h	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/include/xen/xenoprof.h	Thu Jun 07 08:52:17 2007 +0530
@@ -66,6 +66,8 @@ void free_xenoprof_pages(struct domain *
 void free_xenoprof_pages(struct domain *d);
 
 int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg);
+int xenoprof_add_trace(struct domain *d, struct vcpu *v, 
+                       unsigned long eip, int mode);
 
 extern struct domain *xenoprof_primary_profiler;
 

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Add callgraph support to Xenoprofile
  2007-06-07  3:34 [PATCH] Add callgraph support to Xenoprofile Amitabha Roy
@ 2007-06-07  9:01 ` Keir Fraser
  2007-06-07  9:20   ` Amitabha Roy
  0 siblings, 1 reply; 6+ messages in thread
From: Keir Fraser @ 2007-06-07  9:01 UTC (permalink / raw)
  To: Amitabha Roy, Xen developers mailing list; +Cc: Santos, Jose Renato G

On 7/6/07 04:34, "Amitabha Roy" <amitabha.roy@gmail.com> wrote:

> This patch implements backtrace support in Xenoprofile. It's been
> reviewed by Renato. I've tested it out successfully on xen x86_32 and
> x86_64. I've added stubs for the backtrace for ia64 to ensure that it
> compiles ok but havent been able to test that out. However, I believe
> there shouldn't be any problems.

Coding style is all over the shop. Where does CONFIG_FRAME_POINTER get used?
I'm not sure that FRAME_POINTER needs to be a top-level option -- it's only
necessary for Xen build isn't it?

 -- Keir

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Add callgraph support to Xenoprofile
  2007-06-07  9:01 ` Keir Fraser
@ 2007-06-07  9:20   ` Amitabha Roy
  2007-06-07  9:30     ` Keir Fraser
  0 siblings, 1 reply; 6+ messages in thread
From: Amitabha Roy @ 2007-06-07  9:20 UTC (permalink / raw)
  To: Keir Fraser; +Cc: Xen developers mailing list, Santos, Jose Renato G

Hi Keir

Coding style is likely because I've preserved the formatting of the
original files (esp. of backtrace.c from Linux for simple diffs).
There isnt a consistent style across the files that I could follow.

CONFIG_FRAME_POINTER gets used in config/StdGNU.mk.
I simply followed whatever was done for XEN_TARGET_X86_PAE. However
unlike the PAE case I haven't ensured that frame pointers are turned
on both in the kernel and Xen. If you want I can move all the frame
pointer related stuff into xen/Rules.mk.

-Amitabha


On 6/7/07, Keir Fraser <keir@xensource.com> wrote:
> On 7/6/07 04:34, "Amitabha Roy" <amitabha.roy@gmail.com> wrote:
>
> > This patch implements backtrace support in Xenoprofile. It's been
> > reviewed by Renato. I've tested it out successfully on xen x86_32 and
> > x86_64. I've added stubs for the backtrace for ia64 to ensure that it
> > compiles ok but havent been able to test that out. However, I believe
> > there shouldn't be any problems.
>
> Coding style is all over the shop. Where does CONFIG_FRAME_POINTER get used?
> I'm not sure that FRAME_POINTER needs to be a top-level option -- it's only
> necessary for Xen build isn't it?
>
>  -- Keir
>
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Add callgraph support to Xenoprofile
  2007-06-07  9:20   ` Amitabha Roy
@ 2007-06-07  9:30     ` Keir Fraser
  2007-06-07 11:45       ` Amitabha Roy
  0 siblings, 1 reply; 6+ messages in thread
From: Keir Fraser @ 2007-06-07  9:30 UTC (permalink / raw)
  To: Amitabha Roy; +Cc: Xen developers mailing list, Santos, Jose Renato G

On 7/6/07 10:20, "Amitabha Roy" <amitabha.roy@gmail.com> wrote:

> Coding style is likely because I've preserved the formatting of the
> original files (esp. of backtrace.c from Linux for simple diffs).
> There isnt a consistent style across the files that I could follow.

Linux-derived files follow Linux style (this will apply to many of the files
under arch/x86/oprofile). Xen-specific files follow Xen style as in e.g.,
page_alloc.c, xmalloc.c, xenoprof.c).

If any of the files you edit don't follow this, please fix them first, and
send a separate patch as a prerequisite for your own.

> CONFIG_FRAME_POINTER gets used in config/StdGNU.mk.
> I simply followed whatever was done for XEN_TARGET_X86_PAE. However
> unlike the PAE case I haven't ensured that frame pointers are turned
> on both in the kernel and Xen. If you want I can move all the frame
> pointer related stuff into xen/Rules.mk.

Yes, please. Call the option frame_pointer, in line with other Xen-specific
options which are also lower case.

 -- Keir

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Add callgraph support to Xenoprofile
  2007-06-07  9:30     ` Keir Fraser
@ 2007-06-07 11:45       ` Amitabha Roy
  2007-06-07 11:46         ` Amitabha Roy
  0 siblings, 1 reply; 6+ messages in thread
From: Amitabha Roy @ 2007-06-07 11:45 UTC (permalink / raw)
  To: Keir Fraser; +Cc: Xen developers mailing list, Santos, Jose Renato G

[-- Attachment #1: Type: text/plain, Size: 1644 bytes --]

I've moved the frame pointer code into the xen specific makefile.
I've also fixed the per file inconsistencies. I noticed that some
files already have a few inconsistencies within themselves in places
other than my code.

Perhaps you could accept this patch and I can send a separate one
later fixing those ?
One of the suggestions I had from Renato was to minimize any diffs of
files based off linux versions so that pulling in updates will be
easier. So I can look into those on a case by case basis with him.

-Amitabha


On 6/7/07, Keir Fraser <keir@xensource.com> wrote:
> On 7/6/07 10:20, "Amitabha Roy" <amitabha.roy@gmail.com> wrote:
>
> > Coding style is likely because I've preserved the formatting of the
> > original files (esp. of backtrace.c from Linux for simple diffs).
> > There isnt a consistent style across the files that I could follow.
>
> Linux-derived files follow Linux style (this will apply to many of the files
> under arch/x86/oprofile). Xen-specific files follow Xen style as in e.g.,
> page_alloc.c, xmalloc.c, xenoprof.c).
>
> If any of the files you edit don't follow this, please fix them first, and
> send a separate patch as a prerequisite for your own.
>
> > CONFIG_FRAME_POINTER gets used in config/StdGNU.mk.
> > I simply followed whatever was done for XEN_TARGET_X86_PAE. However
> > unlike the PAE case I haven't ensured that frame pointers are turned
> > on both in the kernel and Xen. If you want I can move all the frame
> > pointer related stuff into xen/Rules.mk.
>
> Yes, please. Call the option frame_pointer, in line with other Xen-specific
> options which are also lower case.
>
>  -- Keir
>
>

[-- Attachment #2: xenoprof_backtrace_patch.txt --]
[-- Type: text/plain, Size: 21712 bytes --]

# HG changeset patch
# User root@localhost.localdomain
# Date 1181216195 -19800
# Node ID e6f484a96f435fd882de142797f6b309928a1ee9
# Parent  bd3d6b4c52ec809f080c89c4ffcf61dc6e445978
Add backtrace support to xenoprof

Signed-off-by: Amitabha Roy <amitabha.roy@gmail.com>
Reviewed-by: Jose Renato G Santos <joserenato.santos@hp.com>

diff -r bd3d6b4c52ec -r e6f484a96f43 linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c	Thu Jun 07 17:06:35 2007 +0530
@@ -51,6 +51,8 @@ static int xenoprof_is_primary = 0;
 static int xenoprof_is_primary = 0;
 static int active_defined;
 
+extern unsigned long backtrace_depth;
+
 /* Number of buffers in shared area (one per VCPU) */
 int nbuf;
 /* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
@@ -115,38 +117,59 @@ unsigned int pdomains;
 unsigned int pdomains;
 struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
 
+
+/* Check whether the given entry is an escape code */
+static int xenoprof_is_escape(xenoprof_buf_t * buf, int tail)
+{
+	return (buf->event_log[tail].eip == XENOPROF_ESCAPE_CODE);
+}
+
+/* Get the event at the given entry  */
+static uint8_t xenoprof_get_event(xenoprof_buf_t * buf, int tail)
+{
+	return (buf->event_log[tail].event);
+}
+
+
+
+
 static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive)
 {
 	int head, tail, size;
+	int tracing = 0;
 
 	head = buf->event_head;
 	tail = buf->event_tail;
 	size = buf->event_size;
 
-	if (tail > head) {
-		while (tail < size) {
-			oprofile_add_pc(buf->event_log[tail].eip,
-					buf->event_log[tail].mode,
-					buf->event_log[tail].event);
+	while(tail != head) {
+		if(xenoprof_is_escape(buf, tail) && 
+		   xenoprof_get_event(buf, tail)==XENOPROF_TRACE_BEGIN){
+			tracing=1;
+			oprofile_add_pc(ESCAPE_CODE, buf->event_log[tail].mode, 
+					CPU_TRACE_BEGIN); 
 			if (!is_passive)
 				oprofile_samples++;
 			else
 				p_oprofile_samples++;
-			tail++;
-		}
-		tail = 0;
-	}
-	while (tail < head) {
-		oprofile_add_pc(buf->event_log[tail].eip,
-				buf->event_log[tail].mode,
-				buf->event_log[tail].event);
-		if (!is_passive)
-			oprofile_samples++;
-		else
-			p_oprofile_samples++;
+			
+		}
+		else{
+			oprofile_add_pc(buf->event_log[tail].eip,
+					buf->event_log[tail].mode,
+					buf->event_log[tail].event);
+			if(!tracing){
+				if (!is_passive)
+					oprofile_samples++;
+				else
+					p_oprofile_samples++;
+			}
+       
+		}
 		tail++;
-	}
-
+		if(tail==size)
+		    tail=0;
+	}
 	buf->event_tail = tail;
 }
 
@@ -294,9 +317,16 @@ static int xenoprof_setup(void)
 			active_defined = 1;
 		}
 
+		if(backtrace_depth > 0){
+			ret = HYPERVISOR_xenoprof_op(XENOPROF_set_backtrace, 
+						 &backtrace_depth);
+			if (ret)
+			backtrace_depth = 0;
+		}
 		ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
 		if (ret)
 			goto err;
+		
 		xenoprof_arch_counter();
 		ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL);
 
@@ -438,8 +468,22 @@ out:
 	for (j = 0; j < i; j++)
 		xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]);
 
- 	return ret;
-}
+	return ret;
+}
+
+
+/* The dummy backtrace function to keep oprofile happy
+ * The real backtrace is done in xen
+ */
+static void xenoprof_dummy_backtrace(struct pt_regs * const regs, 
+				     unsigned int depth)
+{
+	/* this should never be called */
+	BUG();
+	return;
+}
+
+
 
 struct oprofile_operations xenoprof_ops = {
 #ifdef HAVE_XENOPROF_CREATE_FILES
@@ -450,7 +494,8 @@ struct oprofile_operations xenoprof_ops 
 	.setup 		= xenoprof_setup,
 	.shutdown	= xenoprof_shutdown,
 	.start		= xenoprof_start,
-	.stop		= xenoprof_stop
+	.stop		= xenoprof_stop,
+	.backtrace	= xenoprof_dummy_backtrace
 };
 
 
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/Rules.mk
--- a/xen/Rules.mk	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/Rules.mk	Thu Jun 07 17:06:35 2007 +0530
@@ -3,10 +3,11 @@
 # If you change any of these configuration options then you must
 # 'make clean' before rebuilding.
 #
-verbose     ?= n
-perfc       ?= n
-perfc_arrays?= n
-crash_debug ?= n
+verbose      ?= n
+perfc        ?= n
+perfc_arrays ?= n
+crash_debug  ?= n
+frame_pointer?= n
 
 XEN_ROOT=$(BASEDIR)/..
 include $(XEN_ROOT)/Config.mk
@@ -19,6 +20,15 @@ ifeq ($(perfc_arrays),y)
 ifeq ($(perfc_arrays),y)
 perfc := y
 endif
+ifeq ($(frame_pointer),y)
+FRAME_ON := -fno-omit-frame-pointer -DCONFIG_FRAME_POINTER
+ifdef $(CFLAGS)
+CFLAGS   :=  $(shell echo $(CFLAGS) |\
+               sed -e 's/-fomit-frame-pointer/'"$(FRAME_ON)/")
+else
+CFLAGS   := $(FRAME_ON) 
+endif # CFLAGS defined ?
+endif # Need frame pointer
 
 # Set ARCH/SUBARCH appropriately.
 override COMPILE_SUBARCH := $(XEN_COMPILE_ARCH)
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/arch/ia64/xen/oprofile/perfmon.c
--- a/xen/arch/ia64/xen/oprofile/perfmon.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/ia64/xen/oprofile/perfmon.c	Thu Jun 07 17:06:35 2007 +0530
@@ -37,7 +37,7 @@
 #include <asm/ptrace.h>
 
 // XXX move them to an appropriate header file
-extern void xenoprof_log_event(struct vcpu *vcpu,
+extern void xenoprof_log_event(struct vcpu *vcpu, struct pt_regs * regs,
                                unsigned long eip, int mode, int event);
 extern int is_active(struct domain *d);
 
@@ -55,7 +55,10 @@ xenoprof_handler(struct task_struct *tas
     if (!allow_virq || !allow_ints)
         return 0;
 
-    xenoprof_log_event(current, ip, xenoprofile_get_mode(task, regs), event);
+    // Note that log event actually expect cpu_user_regs, cast back 
+    // appropriately when doing the backtrace implementation in ia64
+    xenoprof_log_event(current, regs, ip, xenoprofile_get_mode(task, regs), 
+					   event);
     
     // send VIRQ_XENOPROF
     if (is_active(current->domain) && !ring_0(regs))
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/arch/x86/oprofile/Makefile
--- a/xen/arch/x86/oprofile/Makefile	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/x86/oprofile/Makefile	Thu Jun 07 17:06:35 2007 +0530
@@ -3,3 +3,4 @@ obj-y += op_model_p4.o
 obj-y += op_model_p4.o
 obj-y += op_model_ppro.o
 obj-y += op_model_athlon.o
+obj-y += backtrace.o
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/arch/x86/oprofile/op_model_athlon.c
--- a/xen/arch/x86/oprofile/op_model_athlon.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/x86/oprofile/op_model_athlon.c	Thu Jun 07 17:06:35 2007 +0530
@@ -43,8 +43,8 @@
 
 static unsigned long reset_value[NUM_COUNTERS];
 
-extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
-			       int mode, int event);
+extern void xenoprof_log_event(struct vcpu *v, struct cpu_user_regs * regs, 
+			       unsigned long eip, int mode, int event);
 extern int xenoprofile_get_mode(struct vcpu *v,
 				struct cpu_user_regs * const regs);
 
@@ -130,7 +130,7 @@ static int athlon_check_ctrs(unsigned in
 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
 		CTR_READ(low, high, msrs, i);
 		if (CTR_OVERFLOWED(low)) {
-			xenoprof_log_event(current, eip, mode, i);
+			xenoprof_log_event(current, regs, eip, mode, i);
 			CTR_WRITE(reset_value[i], msrs, i);
 			ovf = 1;
 		}
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/arch/x86/oprofile/op_model_p4.c
--- a/xen/arch/x86/oprofile/op_model_p4.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/x86/oprofile/op_model_p4.c	Thu Jun 07 17:06:35 2007 +0530
@@ -620,8 +620,8 @@ static void p4_setup_ctrs(struct op_msrs
 	}
 }
 
-extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
-			       int mode, int event);
+extern void xenoprof_log_event(struct vcpu *v, struct cpu_user_regs * regs, 
+			       unsigned long eip, int mode, int event);
 extern int xenoprofile_get_mode(struct vcpu *v,
 				struct cpu_user_regs * const regs);
 
@@ -664,8 +664,8 @@ static int p4_check_ctrs(unsigned int co
 		CCCR_READ(low, high, real);
  		CTR_READ(ctr, high, real);
 		if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) {
-			xenoprof_log_event(current, eip, mode, i);
- 			CTR_WRITE(reset_value[i], real);
+			xenoprof_log_event(current, regs, eip, mode, i);
+			CTR_WRITE(reset_value[i], real);
 			CCCR_CLEAR_OVF(low);
 			CCCR_WRITE(low, high, real);
  			CTR_WRITE(reset_value[i], real);
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/arch/x86/oprofile/op_model_ppro.c
--- a/xen/arch/x86/oprofile/op_model_ppro.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/arch/x86/oprofile/op_model_ppro.c	Thu Jun 07 17:06:35 2007 +0530
@@ -88,8 +88,8 @@ static void ppro_setup_ctrs(struct op_ms
 	}
 }
 
-extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
-			       int mode, int event);
+extern void xenoprof_log_event(struct vcpu *v, struct cpu_user_regs * regs, 
+			       unsigned long eip, int mode, int event);
 extern int xenoprofile_get_mode(struct vcpu *v,
 				struct cpu_user_regs * const regs);
  
@@ -106,7 +106,7 @@ static int ppro_check_ctrs(unsigned int 
 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
 		CTR_READ(low, high, msrs, i);
 		if (CTR_OVERFLOWED(low)) {
-			xenoprof_log_event(current, eip, mode, i);
+			xenoprof_log_event(current, regs, eip, mode, i);
 			CTR_WRITE(reset_value[i], msrs, i);
 			ovf = 1;
 		}
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/common/xenoprof.c
--- a/xen/common/xenoprof.c	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/common/xenoprof.c	Thu Jun 07 17:06:35 2007 +0530
@@ -31,6 +31,7 @@ unsigned int activated;
 unsigned int activated;
 struct domain *xenoprof_primary_profiler;
 int xenoprof_state = XENOPROF_IDLE;
+static unsigned long backtrace_depth=0;
 
 u64 total_samples;
 u64 invalid_buffer_samples;
@@ -414,55 +415,47 @@ static int add_passive_list(XEN_GUEST_HA
     return ret;
 }
 
-void xenoprof_log_event(
-    struct vcpu *vcpu, unsigned long eip, int mode, int event)
-{
-    struct domain *d = vcpu->domain;
-    struct xenoprof_vcpu *v;
-    xenoprof_buf_t *buf;
+
+/* Get space in the buffer */
+static int xenoprof_buf_space(struct domain *d, xenoprof_buf_t * buf, int size)
+{
+    int head;
+    int tail;
+
+    head = xenoprof_buf(d, buf, event_head);
+    tail = xenoprof_buf(d, buf, event_tail);
+
+    if(tail > head){
+        return ((tail - head) - 1);
+    }
+    else {
+        return (size - (head -tail) -1);
+    }
+}
+
+/* check for space and add a sample
+ * return 1 if successful, 0 otherwise
+ */
+
+static inline int xenoprof_add_sample(struct domain *d, xenoprof_buf_t *buf,
+                                      unsigned long eip, int mode, int event)
+{
     int head;
     int tail;
     int size;
 
-
-    total_samples++;
-
-    /* ignore samples of un-monitored domains */
-    /* Count samples in idle separate from other unmonitored domains */
-    if ( !is_profiled(d) )
-    {
-        others_samples++;
-        return;
-    }
-
-    v = &d->xenoprof->vcpu[vcpu->vcpu_id];
-
-    /* Sanity check. Should never happen */ 
-    if ( v->buffer == NULL )
-    {
-        invalid_buffer_samples++;
-        return;
-    }
-
-    buf = v->buffer;
-
     head = xenoprof_buf(d, buf, event_head);
     tail = xenoprof_buf(d, buf, event_tail);
-    size = v->event_size;
-
+    size = xenoprof_buf(d, buf, event_size);
+    
     /* make sure indexes in shared buffer are sane */
     if ( (head < 0) || (head >= size) || (tail < 0) || (tail >= size) )
     {
         corrupted_buffer_samples++;
-        return;
-    }
-
-    if ( (head == tail - 1) || (head == size - 1 && tail == 0) )
-    {
-        xenoprof_buf(d, buf, lost_samples)++;
-        lost_samples++;
-    }
-    else
+        return 0;
+    }
+
+    if(xenoprof_buf_space(d, buf, size) > 0)
     {
         xenoprof_buf(d, buf, event_log[head].eip) = eip;
         xenoprof_buf(d, buf, event_log[head].mode) = mode;
@@ -470,7 +463,87 @@ void xenoprof_log_event(
         head++;
         if ( head >= size )
             head = 0;
+        
         xenoprof_buf(d, buf, event_head) = head;
+    }
+    else
+    {
+        xenoprof_buf(d, buf, lost_samples)++;
+        lost_samples++;
+        return 0;
+    }
+    return 1;
+}
+
+/* add a trace to the buffer */
+int xenoprof_add_trace(struct domain *d, struct vcpu *vcpu,
+                       unsigned long eip, int mode)
+{
+    xenoprof_buf_t * buf;
+    
+    /* Assume buffer is not null, it should have been checked before entering
+     * the arch specific backtrace code
+     */
+    
+    buf = (d->xenoprof->vcpu[vcpu->vcpu_id]).buffer;    
+
+    /* Ensure we do not accidentally write an escape code due to 
+     * a broken frame
+     */
+
+    if(eip==XENOPROF_ESCAPE_CODE)
+    {
+        invalid_buffer_samples++;
+        return 0;
+    }
+
+    return xenoprof_add_sample(d, buf, eip, mode, 0);
+}
+
+void xenoprof_log_event(struct vcpu *vcpu, 
+                        struct cpu_user_regs * regs, unsigned long eip, 
+                        int mode, int event)
+{
+    struct domain *d = vcpu->domain;
+    struct xenoprof_vcpu *v;
+    xenoprof_buf_t *buf;
+
+    total_samples++;
+
+    /* ignore samples of un-monitored domains */
+    /* Count samples in idle separate from other unmonitored domains */
+    if ( !is_profiled(d) )
+    {
+        others_samples++;
+        return;
+    }
+
+    v = &d->xenoprof->vcpu[vcpu->vcpu_id];
+    
+    if(v->buffer == NULL)
+    {
+        invalid_buffer_samples++;
+        return;
+    }
+    
+    buf = v->buffer;
+
+    /* Backtrace if asked for */
+    if(backtrace_depth > 0)
+    {
+        if(xenoprof_buf_space(d, buf, v->event_size) < 2){
+            xenoprof_buf(d, buf, lost_samples)++;
+            lost_samples++;
+            return;
+        }       
+        if(!xenoprof_add_sample(d, buf, XENOPROF_ESCAPE_CODE, mode, 
+		   XENOPROF_TRACE_BEGIN))
+        { /* could happen due to a corrupted buffer */
+            return;
+        }
+    }
+    if(xenoprof_add_sample(d, buf, eip, mode, event))
+    {
         if ( is_active(vcpu->domain) )
             active_samples++;
         else
@@ -481,8 +554,15 @@ void xenoprof_log_event(
             xenoprof_buf(d, buf, kernel_samples)++;
         else
             xenoprof_buf(d, buf, xen_samples)++;
-    }
-}
+    
+    }
+    if(backtrace_depth > 0)
+    {
+        backtrace(d, vcpu, regs, backtrace_depth, mode);
+    }
+}
+
+
 
 static int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
 {
@@ -729,7 +809,18 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
             activated = 0;
             adomains=0;
             xenoprof_primary_profiler = NULL;
+            backtrace_depth=0;
             ret = 0;
+        }
+        break;
+                
+    case XENOPROF_set_backtrace:
+        ret = 0;
+        if(!arch_backtrace_supported()){
+            ret = -EINVAL;
+        }
+        else if(copy_from_guest(&backtrace_depth, arg, 1)){
+            ret=-EFAULT;
         }
         break;
 
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/include/asm-ia64/xenoprof.h
--- a/xen/include/asm-ia64/xenoprof.h	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/include/asm-ia64/xenoprof.h	Thu Jun 07 17:06:35 2007 +0530
@@ -37,7 +37,16 @@ struct vcpu;
 struct vcpu;
 struct cpu_user_regs;
 int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
-
+static inline int arch_backtrace_supported(void)
+{
+    return 0;
+}
+static inline void backtrace(struct domain *d, struct vcpu *vcpu, 
+                      struct pt_regs *const regs, unsigned long depth, int mode)
+{
+    /* To be implemented */
+    return;
+}
 #define xenoprof_shared_gmfn(d, gmaddr, maddr)  \
     assign_domain_page((d), (gmaddr), (maddr));
 
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/include/asm-x86/xenoprof.h
--- a/xen/include/asm-x86/xenoprof.h	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/include/asm-x86/xenoprof.h	Thu Jun 07 17:06:35 2007 +0530
@@ -47,6 +47,12 @@ struct vcpu;
 struct vcpu;
 struct cpu_user_regs;
 int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
+static inline int arch_backtrace_supported(void)
+{
+    return 1;
+}
+void backtrace(struct domain *d, struct vcpu *vcpu, 
+               struct cpu_user_regs *const regs, unsigned long depth, int mode);
 #define xenoprof_shared_gmfn(d, gmaddr, maddr)                      \
     do {                                                            \
         (void)(maddr);                                              \
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/include/public/xenoprof.h
--- a/xen/include/public/xenoprof.h	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/include/public/xenoprof.h	Thu Jun 07 17:06:35 2007 +0530
@@ -49,7 +49,8 @@
 #define XENOPROF_release_counters   12
 #define XENOPROF_shutdown           13
 #define XENOPROF_get_buffer         14
-#define XENOPROF_last_op            14
+#define XENOPROF_set_backtrace      15
+#define XENOPROF_last_op            15
 
 #define MAX_OPROF_EVENTS    32
 #define MAX_OPROF_DOMAINS   25
@@ -61,6 +62,11 @@ struct event_log {
     uint8_t mode;
     uint8_t event;
 };
+
+/* PC value that indicates a special code */
+#define XENOPROF_ESCAPE_CODE ~0UL
+/* Transient events for the xenoprof->oprofile cpu buf */
+#define XENOPROF_TRACE_BEGIN 1
 
 /* Xenoprof buffer shared between Xen and domain - 1 per VCPU */
 struct xenoprof_buf {
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/include/xen/xenoprof.h
--- a/xen/include/xen/xenoprof.h	Fri Jun 01 14:50:52 2007 +0100
+++ b/xen/include/xen/xenoprof.h	Thu Jun 07 17:06:35 2007 +0530
@@ -66,6 +66,8 @@ void free_xenoprof_pages(struct domain *
 void free_xenoprof_pages(struct domain *d);
 
 int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg);
+int xenoprof_add_trace(struct domain *d, struct vcpu *v, 
+                       unsigned long eip, int mode);
 
 extern struct domain *xenoprof_primary_profiler;
 
diff -r bd3d6b4c52ec -r e6f484a96f43 xen/arch/x86/oprofile/backtrace.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/oprofile/backtrace.c	Thu Jun 07 17:06:35 2007 +0530
@@ -0,0 +1,138 @@
+/**
+ * @file backtrace.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author David Smith
+ * Modified for Xen by Amitabha Roy
+ *
+ */
+
+#include<xen/types.h>
+#include<asm/page.h>
+#include<xen/xenoprof.h>
+#include<asm/guest_access.h>
+
+struct frame_head {
+	struct frame_head * ebp;
+	unsigned long ret;
+} __attribute__((packed));
+
+static struct frame_head *
+dump_hypervisor_backtrace(struct domain *d, struct vcpu *vcpu, 
+			  struct frame_head * head, int mode)
+{
+	if(!xenoprof_add_trace(d, vcpu, head->ret, mode))
+		return 0;
+
+	/* frame pointers should strictly progress back up the stack
+	 * (towards higher addresses) */
+	if (head >= head->ebp)
+		return NULL;
+
+	return head->ebp;
+}
+
+static struct frame_head *
+dump_guest_backtrace(struct domain *d, struct vcpu *vcpu, 
+		     struct frame_head * head, int mode)
+{
+	struct frame_head bufhead[2];
+	XEN_GUEST_HANDLE(char) guest_head = guest_handle_from_ptr(head, char);
+	
+	/* Also check accessibility of one struct frame_head beyond */
+	if (!guest_handle_okay(guest_head, sizeof(bufhead)))
+		return 0;
+	if (__copy_from_guest_offset((char *)bufhead, guest_head, 0, 
+	    sizeof(bufhead)))
+		return 0;
+
+	if(!xenoprof_add_trace(d, vcpu, bufhead[0].ret, mode))
+	    return 0;
+
+	/* frame pointers should strictly progress back up the stack
+	 * (towards higher addresses) */
+	if (head >= bufhead[0].ebp)
+		return NULL;
+
+	return bufhead[0].ebp;
+}
+
+/*
+ * |             | /\ Higher addresses
+ * |             |
+ * --------------- stack base (address of current_thread_info)
+ * | thread info |
+ * .             .
+ * |    stack    |
+ * --------------- saved regs->ebp value if valid (frame_head address)
+ * .             .
+ * --------------- saved regs->rsp value if x86_64
+ * |             |
+ * --------------- struct pt_regs * stored on stack if 32-bit
+ * |             |
+ * .             .
+ * |             |
+ * --------------- %esp
+ * |             |
+ * |             | \/ Lower addresses
+ *
+ * Thus, regs (or regs->rsp for x86_64) <-> stack base restricts the
+ * valid(ish) ebp values. Note: (1) for x86_64, NMI and several other
+ * exceptions use special stacks, maintained by the interrupt stack table
+ * (IST). These stacks are set up in trap_init() in
+ * arch/x86_64/kernel/traps.c. Thus, for x86_64, regs now does not point
+ * to the kernel stack; instead, it points to some location on the NMI
+ * stack. On the other hand, regs->rsp is the stack pointer saved when the
+ * NMI occurred. (2) For 32-bit, regs->esp is not valid because the
+ * processor does not save %esp on the kernel stack when interrupts occur
+ * in the kernel mode.
+ */
+#ifdef CONFIG_FRAME_POINTER
+static int valid_hypervisor_stack(struct frame_head * head, 
+				  struct cpu_user_regs * regs)
+{
+	unsigned long headaddr = (unsigned long)head;
+#ifdef CONFIG_X86_64
+	unsigned long stack = (unsigned long)regs->rsp;
+#else
+	unsigned long stack = (unsigned long)regs;
+#endif
+	unsigned long stack_base = (stack & ~(STACK_SIZE - 1)) + STACK_SIZE;
+
+	return headaddr > stack && headaddr < stack_base;
+}
+#else
+/* without fp, it's just junk */
+static int valid_hypervisor_stack(struct frame_head * head, 
+				  struct cpu_user_regs * regs)
+{
+	return 0;
+}
+#endif
+
+
+void
+backtrace(struct domain *d, struct vcpu *vcpu, 
+	  struct cpu_user_regs * const regs, unsigned long depth, 
+	  int mode)
+{
+	struct frame_head *head;
+
+#ifdef CONFIG_X86_64
+	head = (struct frame_head *)regs->rbp;
+#else
+	head = (struct frame_head *)regs->ebp;
+#endif
+
+	if (mode > 1) {
+		while (depth-- && valid_hypervisor_stack(head, regs))
+		    head = dump_hypervisor_backtrace(d, vcpu, head, mode);
+		return;
+	}
+
+	while (depth-- && head)
+	    head = dump_guest_backtrace(d, vcpu, head, mode);
+}

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Add callgraph support to Xenoprofile
  2007-06-07 11:45       ` Amitabha Roy
@ 2007-06-07 11:46         ` Amitabha Roy
  0 siblings, 0 replies; 6+ messages in thread
From: Amitabha Roy @ 2007-06-07 11:46 UTC (permalink / raw)
  To: Keir Fraser; +Cc: Xen developers mailing list, Santos, Jose Renato G

Forgot to mention, the CONFIG_FRAME_POINTER is needed by the
backtrace.c file I pulled from linux.

On 6/7/07, Amitabha Roy <amitabha.roy@gmail.com> wrote:
> I've moved the frame pointer code into the xen specific makefile.
> I've also fixed the per file inconsistencies. I noticed that some
> files already have a few inconsistencies within themselves in places
> other than my code.
>
> Perhaps you could accept this patch and I can send a separate one
> later fixing those ?
> One of the suggestions I had from Renato was to minimize any diffs of
> files based off linux versions so that pulling in updates will be
> easier. So I can look into those on a case by case basis with him.
>
> -Amitabha
>
>
> On 6/7/07, Keir Fraser <keir@xensource.com> wrote:
> > On 7/6/07 10:20, "Amitabha Roy" <amitabha.roy@gmail.com> wrote:
> >
> > > Coding style is likely because I've preserved the formatting of the
> > > original files (esp. of backtrace.c from Linux for simple diffs).
> > > There isnt a consistent style across the files that I could follow.
> >
> > Linux-derived files follow Linux style (this will apply to many of the files
> > under arch/x86/oprofile). Xen-specific files follow Xen style as in e.g.,
> > page_alloc.c, xmalloc.c, xenoprof.c).
> >
> > If any of the files you edit don't follow this, please fix them first, and
> > send a separate patch as a prerequisite for your own.
> >
> > > CONFIG_FRAME_POINTER gets used in config/StdGNU.mk.
> > > I simply followed whatever was done for XEN_TARGET_X86_PAE. However
> > > unlike the PAE case I haven't ensured that frame pointers are turned
> > > on both in the kernel and Xen. If you want I can move all the frame
> > > pointer related stuff into xen/Rules.mk.
> >
> > Yes, please. Call the option frame_pointer, in line with other Xen-specific
> > options which are also lower case.
> >
> >  -- Keir
> >
> >
>
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-06-07 11:46 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-06-07  3:34 [PATCH] Add callgraph support to Xenoprofile Amitabha Roy
2007-06-07  9:01 ` Keir Fraser
2007-06-07  9:20   ` Amitabha Roy
2007-06-07  9:30     ` Keir Fraser
2007-06-07 11:45       ` Amitabha Roy
2007-06-07 11:46         ` Amitabha Roy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.