powerpc/pseries: Use jump labels for hcall tracepoints
hcall tracepoints add quite a few instructions to our hcall path: plpar_hcall: mr r2,r2 mfcr r0 stw r0,8(r1) b 164 <---- start ld r12,0(r2) std r12,32(r1) cmpdi r12,0 beq 164 <---- end ... We have an unconditional branch that gets noped out during boot and a load/compare/branch. We also store the tracepoint value to the stack for the hcall_exit path to use. By using jump labels we can simplify this to just a single nop that gets replaced with a branch when the tracepoint is enabled: plpar_hcall: mr r2,r2 mfcr r0 stw r0,8(r1) nop <---- ... If jump labels are not enabled, we fall back to the old method. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:

committed by
Benjamin Herrenschmidt

parent
8fa5d4547e
commit
cc1adb5f32
@@ -26,6 +26,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/static_key.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/page.h>
|
||||
@@ -649,6 +650,19 @@ EXPORT_SYMBOL(arch_free_page);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TRACEPOINTS
|
||||
#ifdef CONFIG_JUMP_LABEL
|
||||
struct static_key hcall_tracepoint_key = STATIC_KEY_INIT;
|
||||
|
||||
void hcall_tracepoint_regfunc(void)
|
||||
{
|
||||
static_key_slow_inc(&hcall_tracepoint_key);
|
||||
}
|
||||
|
||||
void hcall_tracepoint_unregfunc(void)
|
||||
{
|
||||
static_key_slow_dec(&hcall_tracepoint_key);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* We optimise our hcall path by placing hcall_tracepoint_refcount
|
||||
* directly in the TOC so we can check if the hcall tracepoints are
|
||||
@@ -658,13 +672,6 @@ 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++;
|
||||
@@ -674,6 +681,15 @@ void hcall_tracepoint_unregfunc(void)
|
||||
{
|
||||
hcall_tracepoint_refcount--;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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 __trace_hcall_entry(unsigned long opcode, unsigned long *args)
|
||||
{
|
||||
|
Reference in New Issue
Block a user