forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch enable kprobes, kretprobes, ftrace interface. It utilized software breakpoint and single step debug exceptions, instructions simulation on csky. We use USR_BKPT replace origin instruction, and the kprobe handler prepares an excutable memory slot for out-of-line execution with a copy of the original instruction being probed. Most of instructions could be executed by single-step, but some instructions need origin pc value to execute and we need software simulate these instructions. Signed-off-by: Guo Ren <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Steven Rostedt (VMware) <[email protected]>
- Loading branch information
Showing
16 changed files
with
1,197 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-only */ | ||
|
||
#ifndef __ASM_CSKY_KPROBES_H | ||
#define __ASM_CSKY_KPROBES_H | ||
|
||
#include <asm-generic/kprobes.h> | ||
|
||
#ifdef CONFIG_KPROBES | ||
#include <linux/types.h> | ||
#include <linux/ptrace.h> | ||
#include <linux/percpu.h> | ||
|
||
#define __ARCH_WANT_KPROBES_INSN_SLOT | ||
#define MAX_INSN_SIZE 1 | ||
|
||
#define flush_insn_slot(p) do { } while (0) | ||
#define kretprobe_blacklist_size 0 | ||
|
||
#include <asm/probes.h> | ||
|
||
struct prev_kprobe { | ||
struct kprobe *kp; | ||
unsigned int status; | ||
}; | ||
|
||
/* Single step context for kprobe */ | ||
struct kprobe_step_ctx { | ||
unsigned long ss_pending; | ||
unsigned long match_addr; | ||
}; | ||
|
||
/* per-cpu kprobe control block */ | ||
struct kprobe_ctlblk { | ||
unsigned int kprobe_status; | ||
unsigned long saved_sr; | ||
struct prev_kprobe prev_kprobe; | ||
struct kprobe_step_ctx ss_ctx; | ||
}; | ||
|
||
void arch_remove_kprobe(struct kprobe *p); | ||
int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr); | ||
int kprobe_breakpoint_handler(struct pt_regs *regs); | ||
int kprobe_single_step_handler(struct pt_regs *regs); | ||
void kretprobe_trampoline(void); | ||
void __kprobes *trampoline_probe_handler(struct pt_regs *regs); | ||
|
||
#endif /* CONFIG_KPROBES */ | ||
#endif /* __ASM_CSKY_KPROBES_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
|
||
#ifndef __ASM_CSKY_PROBES_H | ||
#define __ASM_CSKY_PROBES_H | ||
|
||
typedef u32 probe_opcode_t; | ||
typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *); | ||
|
||
/* architecture specific copy of original instruction */ | ||
struct arch_probe_insn { | ||
probe_opcode_t *insn; | ||
probes_handler_t *handler; | ||
/* restore address after simulation */ | ||
unsigned long restore; | ||
}; | ||
|
||
#ifdef CONFIG_KPROBES | ||
typedef u32 kprobe_opcode_t; | ||
struct arch_specific_insn { | ||
struct arch_probe_insn api; | ||
}; | ||
#endif | ||
|
||
#endif /* __ASM_CSKY_PROBES_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# SPDX-License-Identifier: GPL-2.0 | ||
obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o simulate-insn.o | ||
obj-$(CONFIG_KPROBES) += kprobes_trampoline.o | ||
obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o | ||
|
||
CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// SPDX-License-Identifier: GPL-2.0+ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/kprobes.h> | ||
#include <linux/module.h> | ||
#include <linux/kallsyms.h> | ||
#include <asm/sections.h> | ||
|
||
#include "decode-insn.h" | ||
#include "simulate-insn.h" | ||
|
||
/* Return: | ||
* INSN_REJECTED If instruction is one not allowed to kprobe, | ||
* INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. | ||
*/ | ||
enum probe_insn __kprobes | ||
csky_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api) | ||
{ | ||
probe_opcode_t insn = le32_to_cpu(*addr); | ||
|
||
CSKY_INSN_SET_SIMULATE(br16, insn); | ||
CSKY_INSN_SET_SIMULATE(bt16, insn); | ||
CSKY_INSN_SET_SIMULATE(bf16, insn); | ||
CSKY_INSN_SET_SIMULATE(jmp16, insn); | ||
CSKY_INSN_SET_SIMULATE(jsr16, insn); | ||
CSKY_INSN_SET_SIMULATE(lrw16, insn); | ||
CSKY_INSN_SET_SIMULATE(pop16, insn); | ||
|
||
CSKY_INSN_SET_SIMULATE(br32, insn); | ||
CSKY_INSN_SET_SIMULATE(bt32, insn); | ||
CSKY_INSN_SET_SIMULATE(bf32, insn); | ||
CSKY_INSN_SET_SIMULATE(jmp32, insn); | ||
CSKY_INSN_SET_SIMULATE(jsr32, insn); | ||
CSKY_INSN_SET_SIMULATE(lrw32, insn); | ||
CSKY_INSN_SET_SIMULATE(pop32, insn); | ||
|
||
CSKY_INSN_SET_SIMULATE(bez32, insn); | ||
CSKY_INSN_SET_SIMULATE(bnez32, insn); | ||
CSKY_INSN_SET_SIMULATE(bnezad32, insn); | ||
CSKY_INSN_SET_SIMULATE(bhsz32, insn); | ||
CSKY_INSN_SET_SIMULATE(bhz32, insn); | ||
CSKY_INSN_SET_SIMULATE(blsz32, insn); | ||
CSKY_INSN_SET_SIMULATE(blz32, insn); | ||
CSKY_INSN_SET_SIMULATE(bsr32, insn); | ||
CSKY_INSN_SET_SIMULATE(jmpi32, insn); | ||
CSKY_INSN_SET_SIMULATE(jsri32, insn); | ||
|
||
return INSN_GOOD; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* SPDX-License-Identifier: GPL-2.0+ */ | ||
|
||
#ifndef __CSKY_KERNEL_KPROBES_DECODE_INSN_H | ||
#define __CSKY_KERNEL_KPROBES_DECODE_INSN_H | ||
|
||
#include <asm/sections.h> | ||
#include <asm/kprobes.h> | ||
|
||
enum probe_insn { | ||
INSN_REJECTED, | ||
INSN_GOOD_NO_SLOT, | ||
INSN_GOOD, | ||
}; | ||
|
||
#define is_insn32(insn) ((insn & 0xc000) == 0xc000) | ||
|
||
enum probe_insn __kprobes | ||
csky_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *asi); | ||
|
||
#endif /* __CSKY_KERNEL_KPROBES_DECODE_INSN_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
#include <linux/kprobes.h> | ||
|
||
int arch_check_ftrace_location(struct kprobe *p) | ||
{ | ||
if (ftrace_location((unsigned long)p->addr)) | ||
p->flags |= KPROBE_FLAG_FTRACE; | ||
return 0; | ||
} | ||
|
||
/* Ftrace callback handler for kprobes -- called under preepmt disabed */ | ||
void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, | ||
struct ftrace_ops *ops, struct pt_regs *regs) | ||
{ | ||
bool lr_saver = false; | ||
struct kprobe *p; | ||
struct kprobe_ctlblk *kcb; | ||
|
||
/* Preempt is disabled by ftrace */ | ||
p = get_kprobe((kprobe_opcode_t *)ip); | ||
if (!p) { | ||
p = get_kprobe((kprobe_opcode_t *)(ip - MCOUNT_INSN_SIZE)); | ||
if (unlikely(!p) || kprobe_disabled(p)) | ||
return; | ||
lr_saver = true; | ||
} | ||
|
||
kcb = get_kprobe_ctlblk(); | ||
if (kprobe_running()) { | ||
kprobes_inc_nmissed_count(p); | ||
} else { | ||
unsigned long orig_ip = instruction_pointer(regs); | ||
|
||
if (lr_saver) | ||
ip -= MCOUNT_INSN_SIZE; | ||
instruction_pointer_set(regs, ip); | ||
__this_cpu_write(current_kprobe, p); | ||
kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
if (!p->pre_handler || !p->pre_handler(p, regs)) { | ||
/* | ||
* Emulate singlestep (and also recover regs->pc) | ||
* as if there is a nop | ||
*/ | ||
instruction_pointer_set(regs, | ||
(unsigned long)p->addr + MCOUNT_INSN_SIZE); | ||
if (unlikely(p->post_handler)) { | ||
kcb->kprobe_status = KPROBE_HIT_SSDONE; | ||
p->post_handler(p, regs, 0); | ||
} | ||
instruction_pointer_set(regs, orig_ip); | ||
} | ||
/* | ||
* If pre_handler returns !0, it changes regs->pc. We have to | ||
* skip emulating post_handler. | ||
*/ | ||
__this_cpu_write(current_kprobe, NULL); | ||
} | ||
} | ||
NOKPROBE_SYMBOL(kprobe_ftrace_handler); | ||
|
||
int arch_prepare_kprobe_ftrace(struct kprobe *p) | ||
{ | ||
p->ainsn.api.insn = NULL; | ||
return 0; | ||
} |
Oops, something went wrong.