diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/lpar.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index cf79b46d8f88..568b503d68bd 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -680,6 +680,13 @@ EXPORT_SYMBOL(arch_free_page); | |||
680 | /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ | 680 | /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ |
681 | extern long hcall_tracepoint_refcount; | 681 | extern long hcall_tracepoint_refcount; |
682 | 682 | ||
683 | /* | ||
684 | * Since the tracing code might execute hcalls we need to guard against | ||
685 | * recursion. One example of this are spinlocks calling H_YIELD on | ||
686 | * shared processor partitions. | ||
687 | */ | ||
688 | static DEFINE_PER_CPU(unsigned int, hcall_trace_depth); | ||
689 | |||
683 | void hcall_tracepoint_regfunc(void) | 690 | void hcall_tracepoint_regfunc(void) |
684 | { | 691 | { |
685 | hcall_tracepoint_refcount++; | 692 | hcall_tracepoint_refcount++; |
@@ -692,12 +699,42 @@ void hcall_tracepoint_unregfunc(void) | |||
692 | 699 | ||
693 | void __trace_hcall_entry(unsigned long opcode, unsigned long *args) | 700 | void __trace_hcall_entry(unsigned long opcode, unsigned long *args) |
694 | { | 701 | { |
702 | unsigned long flags; | ||
703 | unsigned int *depth; | ||
704 | |||
705 | local_irq_save(flags); | ||
706 | |||
707 | depth = &__get_cpu_var(hcall_trace_depth); | ||
708 | |||
709 | if (*depth) | ||
710 | goto out; | ||
711 | |||
712 | (*depth)++; | ||
695 | trace_hcall_entry(opcode, args); | 713 | trace_hcall_entry(opcode, args); |
714 | (*depth)--; | ||
715 | |||
716 | out: | ||
717 | local_irq_restore(flags); | ||
696 | } | 718 | } |
697 | 719 | ||
698 | void __trace_hcall_exit(long opcode, unsigned long retval, | 720 | void __trace_hcall_exit(long opcode, unsigned long retval, |
699 | unsigned long *retbuf) | 721 | unsigned long *retbuf) |
700 | { | 722 | { |
723 | unsigned long flags; | ||
724 | unsigned int *depth; | ||
725 | |||
726 | local_irq_save(flags); | ||
727 | |||
728 | depth = &__get_cpu_var(hcall_trace_depth); | ||
729 | |||
730 | if (*depth) | ||
731 | goto out; | ||
732 | |||
733 | (*depth)++; | ||
701 | trace_hcall_exit(opcode, retval, retbuf); | 734 | trace_hcall_exit(opcode, retval, retbuf); |
735 | (*depth)--; | ||
736 | |||
737 | out: | ||
738 | local_irq_restore(flags); | ||
702 | } | 739 | } |
703 | #endif | 740 | #endif |