diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2016-07-21 04:44:17 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2016-07-21 06:47:52 -0400 |
commit | 3b7d14e9f3f1efd4c4348800e977fd1ce4ca660e (patch) | |
tree | 60fd0adbd3de143dc45d8fd6f8f2852b6ccd9019 /arch/arm64/kernel/probes | |
parent | ab4c1325d4bf111a590a1f773e3d93bde7f40201 (diff) |
arm64: kprobes: Cleanup jprobe_return
jprobe_return seems to have aged badly. Comments referring to
non-existent behaviours, and a dangerous habit of messing
with registers without telling the compiler.
This patches applies the following remedies:
- Fix the comments to describe the actual behaviour
- Tidy up the asm sequence to directly assign the
stack pointer without clobbering extra registers
- Mark the rest of the function as unreachable() so
that the compiler knows that there is no need for
an epilogue
- Stop making jprobe_return_break a global function
(you really don't want to call that guy, and it isn't
even a function).
Tested with tcp_probe.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64/kernel/probes')
-rw-r--r-- | arch/arm64/kernel/probes/kprobes.c | 22 |
1 files changed, 10 insertions, 12 deletions
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c index 09f8ae98da5a..973c15df5211 100644 --- a/arch/arm64/kernel/probes/kprobes.c +++ b/arch/arm64/kernel/probes/kprobes.c | |||
@@ -34,8 +34,6 @@ | |||
34 | 34 | ||
35 | #include "decode-insn.h" | 35 | #include "decode-insn.h" |
36 | 36 | ||
37 | void jprobe_return_break(void); | ||
38 | |||
39 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 37 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
40 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 38 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
41 | 39 | ||
@@ -516,18 +514,17 @@ void __kprobes jprobe_return(void) | |||
516 | /* | 514 | /* |
517 | * Jprobe handler return by entering break exception, | 515 | * Jprobe handler return by entering break exception, |
518 | * encoded same as kprobe, but with following conditions | 516 | * encoded same as kprobe, but with following conditions |
519 | * -a magic number in x0 to identify from rest of other kprobes. | 517 | * -a special PC to identify it from the other kprobes. |
520 | * -restore stack addr to original saved pt_regs | 518 | * -restore stack addr to original saved pt_regs |
521 | */ | 519 | */ |
522 | asm volatile ("ldr x0, [%0]\n\t" | 520 | asm volatile(" mov sp, %0 \n" |
523 | "mov sp, x0\n\t" | 521 | "jprobe_return_break: brk %1 \n" |
524 | ".globl jprobe_return_break\n\t" | 522 | : |
525 | "jprobe_return_break:\n\t" | 523 | : "r" (kcb->jprobe_saved_regs.sp), |
526 | "brk %1\n\t" | 524 | "I" (BRK64_ESR_KPROBES) |
527 | : | 525 | : "memory"); |
528 | : "r"(&kcb->jprobe_saved_regs.sp), | 526 | |
529 | "I"(BRK64_ESR_KPROBES) | 527 | unreachable(); |
530 | : "memory"); | ||
531 | } | 528 | } |
532 | 529 | ||
533 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 530 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
@@ -536,6 +533,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
536 | long stack_addr = kcb->jprobe_saved_regs.sp; | 533 | long stack_addr = kcb->jprobe_saved_regs.sp; |
537 | long orig_sp = kernel_stack_pointer(regs); | 534 | long orig_sp = kernel_stack_pointer(regs); |
538 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 535 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
536 | extern const char jprobe_return_break[]; | ||
539 | 537 | ||
540 | if (instruction_pointer(regs) != (u64) jprobe_return_break) | 538 | if (instruction_pointer(regs) != (u64) jprobe_return_break) |
541 | return 0; | 539 | return 0; |