1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * arch/parisc/kernel/kprobes.c |
4 | * |
5 | * PA-RISC kprobes implementation |
6 | * |
7 | * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> |
8 | * Copyright (c) 2022 Helge Deller <deller@gmx.de> |
9 | */ |
10 | |
11 | #include <linux/types.h> |
12 | #include <linux/kprobes.h> |
13 | #include <linux/slab.h> |
14 | #include <asm/cacheflush.h> |
15 | #include <asm/patch.h> |
16 | |
17 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
18 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
19 | |
20 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
21 | { |
22 | if ((unsigned long)p->addr & 3UL) |
23 | return -EINVAL; |
24 | |
25 | p->ainsn.insn = get_insn_slot(); |
26 | if (!p->ainsn.insn) |
27 | return -ENOMEM; |
28 | |
29 | /* |
30 | * Set up new instructions. Second break instruction will |
31 | * trigger call of parisc_kprobe_ss_handler(). |
32 | */ |
33 | p->opcode = *p->addr; |
34 | p->ainsn.insn[0] = p->opcode; |
35 | p->ainsn.insn[1] = PARISC_KPROBES_BREAK_INSN2; |
36 | |
37 | flush_insn_slot(p); |
38 | return 0; |
39 | } |
40 | |
41 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
42 | { |
43 | if (!p->ainsn.insn) |
44 | return; |
45 | |
46 | free_insn_slot(slot: p->ainsn.insn, dirty: 0); |
47 | p->ainsn.insn = NULL; |
48 | } |
49 | |
50 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
51 | { |
52 | patch_text(p->addr, PARISC_KPROBES_BREAK_INSN); |
53 | } |
54 | |
55 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
56 | { |
57 | patch_text(p->addr, p->opcode); |
58 | } |
59 | |
60 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) |
61 | { |
62 | kcb->prev_kprobe.kp = kprobe_running(); |
63 | kcb->prev_kprobe.status = kcb->kprobe_status; |
64 | } |
65 | |
66 | static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) |
67 | { |
68 | __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); |
69 | kcb->kprobe_status = kcb->prev_kprobe.status; |
70 | } |
71 | |
72 | static inline void __kprobes set_current_kprobe(struct kprobe *p) |
73 | { |
74 | __this_cpu_write(current_kprobe, p); |
75 | } |
76 | |
77 | static void __kprobes setup_singlestep(struct kprobe *p, |
78 | struct kprobe_ctlblk *kcb, struct pt_regs *regs) |
79 | { |
80 | kcb->iaoq[0] = regs->iaoq[0]; |
81 | kcb->iaoq[1] = regs->iaoq[1]; |
82 | instruction_pointer_set(regs, val: (unsigned long)p->ainsn.insn); |
83 | } |
84 | |
85 | int __kprobes parisc_kprobe_break_handler(struct pt_regs *regs) |
86 | { |
87 | struct kprobe *p; |
88 | struct kprobe_ctlblk *kcb; |
89 | |
90 | preempt_disable(); |
91 | |
92 | kcb = get_kprobe_ctlblk(); |
93 | p = get_kprobe(addr: (unsigned long *)regs->iaoq[0]); |
94 | |
95 | if (!p) { |
96 | preempt_enable_no_resched(); |
97 | return 0; |
98 | } |
99 | |
100 | if (kprobe_running()) { |
101 | /* |
102 | * We have reentered the kprobe_handler, since another kprobe |
103 | * was hit while within the handler, we save the original |
104 | * kprobes and single step on the instruction of the new probe |
105 | * without calling any user handlers to avoid recursive |
106 | * kprobes. |
107 | */ |
108 | save_previous_kprobe(kcb); |
109 | set_current_kprobe(p); |
110 | kprobes_inc_nmissed_count(p); |
111 | setup_singlestep(p, kcb, regs); |
112 | kcb->kprobe_status = KPROBE_REENTER; |
113 | return 1; |
114 | } |
115 | |
116 | set_current_kprobe(p); |
117 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; |
118 | |
119 | /* If we have no pre-handler or it returned 0, we continue with |
120 | * normal processing. If we have a pre-handler and it returned |
121 | * non-zero - which means user handler setup registers to exit |
122 | * to another instruction, we must skip the single stepping. |
123 | */ |
124 | |
125 | if (!p->pre_handler || !p->pre_handler(p, regs)) { |
126 | setup_singlestep(p, kcb, regs); |
127 | kcb->kprobe_status = KPROBE_HIT_SS; |
128 | } else { |
129 | reset_current_kprobe(); |
130 | preempt_enable_no_resched(); |
131 | } |
132 | return 1; |
133 | } |
134 | |
135 | int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs) |
136 | { |
137 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
138 | struct kprobe *p = kprobe_running(); |
139 | |
140 | if (!p) |
141 | return 0; |
142 | |
143 | if (regs->iaoq[0] != (unsigned long)p->ainsn.insn+4) |
144 | return 0; |
145 | |
146 | /* restore back original saved kprobe variables and continue */ |
147 | if (kcb->kprobe_status == KPROBE_REENTER) { |
148 | restore_previous_kprobe(kcb); |
149 | return 1; |
150 | } |
151 | |
152 | /* for absolute branch instructions we can copy iaoq_b. for relative |
153 | * branch instructions we need to calculate the new address based on the |
154 | * difference between iaoq_f and iaoq_b. We cannot use iaoq_b without |
155 | * modifications because it's based on our ainsn.insn address. |
156 | */ |
157 | |
158 | if (p->post_handler) |
159 | p->post_handler(p, regs, 0); |
160 | |
161 | switch (regs->iir >> 26) { |
162 | case 0x38: /* BE */ |
163 | case 0x39: /* BE,L */ |
164 | case 0x3a: /* BV */ |
165 | case 0x3b: /* BVE */ |
166 | /* for absolute branches, regs->iaoq[1] has already the right |
167 | * address |
168 | */ |
169 | regs->iaoq[0] = kcb->iaoq[1]; |
170 | break; |
171 | default: |
172 | regs->iaoq[0] = kcb->iaoq[1]; |
173 | regs->iaoq[1] = regs->iaoq[0] + 4; |
174 | break; |
175 | } |
176 | kcb->kprobe_status = KPROBE_HIT_SSDONE; |
177 | reset_current_kprobe(); |
178 | return 1; |
179 | } |
180 | |
181 | void __kretprobe_trampoline(void) |
182 | { |
183 | asm volatile("nop" ); |
184 | asm volatile("nop" ); |
185 | } |
186 | |
187 | static int __kprobes trampoline_probe_handler(struct kprobe *p, |
188 | struct pt_regs *regs); |
189 | |
190 | static struct kprobe trampoline_p = { |
191 | .pre_handler = trampoline_probe_handler |
192 | }; |
193 | |
194 | static int __kprobes trampoline_probe_handler(struct kprobe *p, |
195 | struct pt_regs *regs) |
196 | { |
197 | __kretprobe_trampoline_handler(regs, NULL); |
198 | |
199 | return 1; |
200 | } |
201 | |
202 | void arch_kretprobe_fixup_return(struct pt_regs *regs, |
203 | kprobe_opcode_t *correct_ret_addr) |
204 | { |
205 | regs->gr[2] = (unsigned long)correct_ret_addr; |
206 | } |
207 | |
208 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
209 | struct pt_regs *regs) |
210 | { |
211 | ri->ret_addr = (kprobe_opcode_t *)regs->gr[2]; |
212 | ri->fp = NULL; |
213 | |
214 | /* Replace the return addr with trampoline addr. */ |
215 | regs->gr[2] = (unsigned long)trampoline_p.addr; |
216 | } |
217 | |
218 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) |
219 | { |
220 | return p->addr == trampoline_p.addr; |
221 | } |
222 | |
223 | int __init arch_init_kprobes(void) |
224 | { |
225 | trampoline_p.addr = (kprobe_opcode_t *) |
226 | dereference_function_descriptor(__kretprobe_trampoline); |
227 | return register_kprobe(p: &trampoline_p); |
228 | } |
229 | |