From 07fdbd0ab01b821f362d9b5bfe0cfba675255328 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 21 Oct 2010 00:52:12 +0000 Subject: [PATCH] --- yaml --- r: 232977 b: refs/heads/master c: 57cdfdf829a850a317425ed93c6a576c9ee6329c h: refs/heads/master i: 232975: c80321a493e035114c5aa63678500c7ebecf7e0a v: v3 --- [refs] | 2 +- trunk/arch/powerpc/platforms/pseries/lpar.c | 37 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 02e63ee4a490..743d4dece6b0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 429f4d8d20b91e4a6c239f951c06a56a6ac22957 +refs/heads/master: 57cdfdf829a850a317425ed93c6a576c9ee6329c diff --git a/trunk/arch/powerpc/platforms/pseries/lpar.c b/trunk/arch/powerpc/platforms/pseries/lpar.c index 5d3ea9f60dd7..ca5d5898d320 100644 --- a/trunk/arch/powerpc/platforms/pseries/lpar.c +++ b/trunk/arch/powerpc/platforms/pseries/lpar.c @@ -713,6 +713,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++; @@ -725,12 +732,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