Re: [PATCH] powerpc: Fix hcall tracepoint recursion
From: Steven Rostedt <rostedt@goodmis.org>
Date: 2010-10-22 14:14:21
Also in:
lkml, ltp
On Thu, 2010-10-21 at 21:52 +1100, Anton Blanchard wrote:
quoted hunk ↗ jump to hunk
Anton -- Subject: [PATCH] powerpc: Fix hcall tracepoint recursion Spinlocks on shared processor partitions use H_YIELD to notify the hypervisor we are waiting on another virtual CPU. Unfortunately this means the hcall tracepoints can recurse. The patch below adds a percpu depth and checks it on both the entry and exit hcall tracepoints. Signed-off-by: Anton Blanchard <redacted> --- Index: powerpc.git/arch/powerpc/platforms/pseries/lpar.c ===================================================================--- powerpc.git.orig/arch/powerpc/platforms/pseries/lpar.c 2010-10-21 17:32:00.980003644 +1100 +++ powerpc.git/arch/powerpc/platforms/pseries/lpar.c 2010-10-21 17:34:54.942681273 +1100@@ -701,6 +701,13 @@ EXPORT_SYMBOL(arch_free_page); /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ extern long hcall_tracepoint_refcount; +/* + * Since the tracing code might execute hcalls we need to guard against + * recursion. One example of this are spinlocks calling H_YIELD on + * shared processor partitions. + */ +static DEFINE_PER_CPU(unsigned int, hcall_trace_depth); + void hcall_tracepoint_regfunc(void) { hcall_tracepoint_refcount++;@@ -713,12 +720,42 @@ void hcall_tracepoint_unregfunc(void) void __trace_hcall_entry(unsigned long opcode, unsigned long *args) { + unsigned long flags; + unsigned int *depth; + + local_irq_save(flags); + + depth = &__get_cpu_var(hcall_trace_depth); + + if (*depth) + goto out; + + (*depth)++; trace_hcall_entry(opcode, args); + (*depth)--; + +out: + local_irq_restore(flags); } void __trace_hcall_exit(long opcode, unsigned long retval, unsigned long *retbuf) { + unsigned long flags; + unsigned int *depth; + + local_irq_save(flags); + + depth = &__get_cpu_var(hcall_trace_depth); + + if (*depth) + goto out; + + (*depth)++; trace_hcall_exit(opcode, retval, retbuf); + (*depth)--; + +out: + local_irq_restore(flags); } #endif
That's similar to the example that I wrote, but without the encapsulated code and with disabling interrupts for the reasons you gave. Acked-by: Steven Rostedt <rostedt@goodmis.org> -- Steve