parisc/ftrace: Add KPROBES_ON_FTRACE
Allow KPROBES to use the ftrace infrastructure on PA-RISC. Signed-off-by: Sven Schnelle <svens@stackframe.org> Signed-off-by: Helge Deller <deller@gmx.de>
This commit is contained in:
parent
d562aca37a
commit
52a22e6c27
|
@ -21,7 +21,7 @@
|
||||||
| nds32: | TODO |
|
| nds32: | TODO |
|
||||||
| nios2: | TODO |
|
| nios2: | TODO |
|
||||||
| openrisc: | TODO |
|
| openrisc: | TODO |
|
||||||
| parisc: | TODO |
|
| parisc: | ok |
|
||||||
| powerpc: | ok |
|
| powerpc: | ok |
|
||||||
| riscv: | TODO |
|
| riscv: | TODO |
|
||||||
| s390: | TODO |
|
| s390: | TODO |
|
||||||
|
|
|
@ -61,6 +61,8 @@ config PARISC
|
||||||
select HAVE_KRETPROBES
|
select HAVE_KRETPROBES
|
||||||
select HAVE_DYNAMIC_FTRACE if $(cc-option,-fpatchable-function-entry=1,1)
|
select HAVE_DYNAMIC_FTRACE if $(cc-option,-fpatchable-function-entry=1,1)
|
||||||
select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE
|
select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE
|
||||||
|
select HAVE_KPROBES_ON_FTRACE
|
||||||
|
select HAVE_DYNAMIC_FTRACE_WITH_REGS
|
||||||
|
|
||||||
help
|
help
|
||||||
The PA-RISC microprocessor is designed by Hewlett-Packard and used
|
The PA-RISC microprocessor is designed by Hewlett-Packard and used
|
||||||
|
|
|
@ -1996,6 +1996,7 @@ _mcount:
|
||||||
* calling mcount(), and 2 instructions for ftrace_stub(). That way we
|
* calling mcount(), and 2 instructions for ftrace_stub(). That way we
|
||||||
* have all on one L1 cacheline.
|
* have all on one L1 cacheline.
|
||||||
*/
|
*/
|
||||||
|
ldi 0, %arg3
|
||||||
b ftrace_function_trampoline
|
b ftrace_function_trampoline
|
||||||
copy %r3, %arg2 /* caller original %sp */
|
copy %r3, %arg2 /* caller original %sp */
|
||||||
ftrace_stub:
|
ftrace_stub:
|
||||||
|
@ -2048,6 +2049,7 @@ ftrace_caller:
|
||||||
LDREG 0(%r3), %r25
|
LDREG 0(%r3), %r25
|
||||||
copy %rp, %r26
|
copy %rp, %r26
|
||||||
ldo -8(%r25), %r25
|
ldo -8(%r25), %r25
|
||||||
|
ldi 0, %r23 /* no pt_regs */
|
||||||
b,l ftrace_function_trampoline, %rp
|
b,l ftrace_function_trampoline, %rp
|
||||||
copy %r3, %r24
|
copy %r3, %r24
|
||||||
|
|
||||||
|
@ -2075,6 +2077,103 @@ ftrace_caller:
|
||||||
|
|
||||||
ENDPROC_CFI(ftrace_caller)
|
ENDPROC_CFI(ftrace_caller)
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS
|
||||||
|
ENTRY_CFI(ftrace_regs_caller,caller,frame=FTRACE_FRAME_SIZE+PT_SZ_ALGN,
|
||||||
|
CALLS,SAVE_RP,SAVE_SP)
|
||||||
|
ftrace_regs_caller:
|
||||||
|
.global ftrace_regs_caller
|
||||||
|
|
||||||
|
ldo -FTRACE_FRAME_SIZE(%sp), %r1
|
||||||
|
STREG %rp, -RP_OFFSET(%r1)
|
||||||
|
|
||||||
|
copy %sp, %r1
|
||||||
|
ldo PT_SZ_ALGN(%sp), %sp
|
||||||
|
|
||||||
|
STREG %rp, PT_GR2(%r1)
|
||||||
|
STREG %r3, PT_GR3(%r1)
|
||||||
|
STREG %r4, PT_GR4(%r1)
|
||||||
|
STREG %r5, PT_GR5(%r1)
|
||||||
|
STREG %r6, PT_GR6(%r1)
|
||||||
|
STREG %r7, PT_GR7(%r1)
|
||||||
|
STREG %r8, PT_GR8(%r1)
|
||||||
|
STREG %r9, PT_GR9(%r1)
|
||||||
|
STREG %r10, PT_GR10(%r1)
|
||||||
|
STREG %r11, PT_GR11(%r1)
|
||||||
|
STREG %r12, PT_GR12(%r1)
|
||||||
|
STREG %r13, PT_GR13(%r1)
|
||||||
|
STREG %r14, PT_GR14(%r1)
|
||||||
|
STREG %r15, PT_GR15(%r1)
|
||||||
|
STREG %r16, PT_GR16(%r1)
|
||||||
|
STREG %r17, PT_GR17(%r1)
|
||||||
|
STREG %r18, PT_GR18(%r1)
|
||||||
|
STREG %r19, PT_GR19(%r1)
|
||||||
|
STREG %r20, PT_GR20(%r1)
|
||||||
|
STREG %r21, PT_GR21(%r1)
|
||||||
|
STREG %r22, PT_GR22(%r1)
|
||||||
|
STREG %r23, PT_GR23(%r1)
|
||||||
|
STREG %r24, PT_GR24(%r1)
|
||||||
|
STREG %r25, PT_GR25(%r1)
|
||||||
|
STREG %r26, PT_GR26(%r1)
|
||||||
|
STREG %r27, PT_GR27(%r1)
|
||||||
|
STREG %r28, PT_GR28(%r1)
|
||||||
|
STREG %r29, PT_GR29(%r1)
|
||||||
|
STREG %r30, PT_GR30(%r1)
|
||||||
|
STREG %r31, PT_GR31(%r1)
|
||||||
|
mfctl %cr11, %r26
|
||||||
|
STREG %r26, PT_SAR(%r1)
|
||||||
|
|
||||||
|
copy %rp, %r26
|
||||||
|
LDREG -FTRACE_FRAME_SIZE-PT_SZ_ALGN(%sp), %r25
|
||||||
|
ldo -8(%r25), %r25
|
||||||
|
copy %r3, %arg2
|
||||||
|
b,l ftrace_function_trampoline, %rp
|
||||||
|
copy %r1, %arg3 /* struct pt_regs */
|
||||||
|
|
||||||
|
ldo -PT_SZ_ALGN(%sp), %r1
|
||||||
|
|
||||||
|
LDREG PT_SAR(%r1), %rp
|
||||||
|
mtctl %rp, %cr11
|
||||||
|
|
||||||
|
LDREG PT_GR2(%r1), %rp
|
||||||
|
LDREG PT_GR3(%r1), %r3
|
||||||
|
LDREG PT_GR4(%r1), %r4
|
||||||
|
LDREG PT_GR5(%r1), %r5
|
||||||
|
LDREG PT_GR6(%r1), %r6
|
||||||
|
LDREG PT_GR7(%r1), %r7
|
||||||
|
LDREG PT_GR8(%r1), %r8
|
||||||
|
LDREG PT_GR9(%r1), %r9
|
||||||
|
LDREG PT_GR10(%r1),%r10
|
||||||
|
LDREG PT_GR11(%r1),%r11
|
||||||
|
LDREG PT_GR12(%r1),%r12
|
||||||
|
LDREG PT_GR13(%r1),%r13
|
||||||
|
LDREG PT_GR14(%r1),%r14
|
||||||
|
LDREG PT_GR15(%r1),%r15
|
||||||
|
LDREG PT_GR16(%r1),%r16
|
||||||
|
LDREG PT_GR17(%r1),%r17
|
||||||
|
LDREG PT_GR18(%r1),%r18
|
||||||
|
LDREG PT_GR19(%r1),%r19
|
||||||
|
LDREG PT_GR20(%r1),%r20
|
||||||
|
LDREG PT_GR21(%r1),%r21
|
||||||
|
LDREG PT_GR22(%r1),%r22
|
||||||
|
LDREG PT_GR23(%r1),%r23
|
||||||
|
LDREG PT_GR24(%r1),%r24
|
||||||
|
LDREG PT_GR25(%r1),%r25
|
||||||
|
LDREG PT_GR26(%r1),%r26
|
||||||
|
LDREG PT_GR27(%r1),%r27
|
||||||
|
LDREG PT_GR28(%r1),%r28
|
||||||
|
LDREG PT_GR29(%r1),%r29
|
||||||
|
LDREG PT_GR30(%r1),%r30
|
||||||
|
LDREG PT_GR31(%r1),%r31
|
||||||
|
|
||||||
|
ldo -PT_SZ_ALGN(%sp), %sp
|
||||||
|
LDREGM -FTRACE_FRAME_SIZE(%sp), %r1
|
||||||
|
/* Adjust return point to jump back to beginning of traced function */
|
||||||
|
ldo -4(%r1), %r1
|
||||||
|
bv,n (%r1)
|
||||||
|
|
||||||
|
ENDPROC_CFI(ftrace_regs_caller)
|
||||||
|
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/ftrace.h>
|
#include <linux/ftrace.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/kprobes.h>
|
||||||
|
#include <linux/ptrace.h>
|
||||||
|
|
||||||
#include <asm/assembly.h>
|
#include <asm/assembly.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
|
@ -48,7 +50,8 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
|
||||||
|
|
||||||
void notrace __hot ftrace_function_trampoline(unsigned long parent,
|
void notrace __hot ftrace_function_trampoline(unsigned long parent,
|
||||||
unsigned long self_addr,
|
unsigned long self_addr,
|
||||||
unsigned long org_sp_gr3)
|
unsigned long org_sp_gr3,
|
||||||
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_DYNAMIC_FTRACE
|
#ifndef CONFIG_DYNAMIC_FTRACE
|
||||||
extern ftrace_func_t ftrace_trace_function;
|
extern ftrace_func_t ftrace_trace_function;
|
||||||
|
@ -58,11 +61,11 @@ void notrace __hot ftrace_function_trampoline(unsigned long parent,
|
||||||
if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED &&
|
if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED &&
|
||||||
ftrace_trace_function != ftrace_stub)
|
ftrace_trace_function != ftrace_stub)
|
||||||
ftrace_trace_function(self_addr, parent,
|
ftrace_trace_function(self_addr, parent,
|
||||||
function_trace_op, NULL);
|
function_trace_op, regs);
|
||||||
|
|
||||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||||
if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub ||
|
if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub ||
|
||||||
ftrace_graph_entry != ftrace_graph_entry_stub) {
|
ftrace_graph_entry != ftrace_graph_entry_stub) {
|
||||||
unsigned long *parent_rp;
|
unsigned long *parent_rp;
|
||||||
|
|
||||||
/* calculate pointer to %rp in stack */
|
/* calculate pointer to %rp in stack */
|
||||||
|
@ -100,6 +103,12 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
|
||||||
|
unsigned long addr)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long ftrace_call_adjust(unsigned long addr)
|
unsigned long ftrace_call_adjust(unsigned long addr)
|
||||||
{
|
{
|
||||||
return addr+(FTRACE_PATCHABLE_FUNCTION_SIZE-1)*4;
|
return addr+(FTRACE_PATCHABLE_FUNCTION_SIZE-1)*4;
|
||||||
|
@ -191,3 +200,46 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KPROBES_ON_FTRACE
|
||||||
|
void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||||
|
struct ftrace_ops *ops, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
struct kprobe_ctlblk *kcb;
|
||||||
|
struct kprobe *p = get_kprobe((kprobe_opcode_t *)ip);
|
||||||
|
|
||||||
|
if (unlikely(!p) || kprobe_disabled(p))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (kprobe_running()) {
|
||||||
|
kprobes_inc_nmissed_count(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__this_cpu_write(current_kprobe, p);
|
||||||
|
|
||||||
|
kcb = get_kprobe_ctlblk();
|
||||||
|
kcb->kprobe_status = KPROBE_HIT_ACTIVE;
|
||||||
|
|
||||||
|
regs->iaoq[0] = ip;
|
||||||
|
regs->iaoq[1] = ip + 4;
|
||||||
|
|
||||||
|
if (!p->pre_handler || !p->pre_handler(p, regs)) {
|
||||||
|
regs->iaoq[0] = ip + 4;
|
||||||
|
regs->iaoq[1] = ip + 8;
|
||||||
|
|
||||||
|
if (unlikely(p->post_handler)) {
|
||||||
|
kcb->kprobe_status = KPROBE_HIT_SSDONE;
|
||||||
|
p->post_handler(p, regs, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__this_cpu_write(current_kprobe, NULL);
|
||||||
|
}
|
||||||
|
NOKPROBE_SYMBOL(kprobe_ftrace_handler);
|
||||||
|
|
||||||
|
int arch_prepare_kprobe_ftrace(struct kprobe *p)
|
||||||
|
{
|
||||||
|
p->ainsn.insn = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue