hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/arch/powerpc/kernel/optprobes.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Code for Kernel probes Jump optimization.
34 *
45 * Copyright 2017, Anju T, IBM Corp.
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 #include <linux/kprobes.h>
....@@ -20,6 +16,7 @@
2016 #include <asm/code-patching.h>
2117 #include <asm/sstep.h>
2218 #include <asm/ppc-opcode.h>
19
+#include <asm/inst.h>
2320
2421 #define TMPL_CALL_HDLR_IDX \
2522 (optprobe_template_call_handler - optprobe_template_entry)
....@@ -103,8 +100,9 @@
103100 * Ensure that the instruction is not a conditional branch,
104101 * and that can be emulated.
105102 */
106
- if (!is_conditional_branch(*p->ainsn.insn) &&
107
- analyse_instr(&op, &regs, *p->ainsn.insn) == 1) {
103
+ if (!is_conditional_branch(ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) &&
104
+ analyse_instr(&op, &regs,
105
+ ppc_inst_read((struct ppc_inst *)p->ainsn.insn)) == 1) {
108106 emulate_update_regs(&regs, &op);
109107 nip = regs.nip;
110108 }
....@@ -151,50 +149,57 @@
151149 void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
152150 {
153151 /* addis r4,0,(insn)@h */
154
- patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(4) |
155
- ((val >> 16) & 0xffff));
152
+ patch_instruction((struct ppc_inst *)addr,
153
+ ppc_inst(PPC_INST_ADDIS | ___PPC_RT(4) |
154
+ ((val >> 16) & 0xffff)));
156155 addr++;
157156
158157 /* ori r4,r4,(insn)@l */
159
- patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(4) |
160
- ___PPC_RS(4) | (val & 0xffff));
158
+ patch_instruction((struct ppc_inst *)addr,
159
+ ppc_inst(PPC_INST_ORI | ___PPC_RA(4) |
160
+ ___PPC_RS(4) | (val & 0xffff)));
161161 }
162162
163163 /*
164164 * Generate instructions to load provided immediate 64-bit value
165
- * to register 'r3' and patch these instructions at 'addr'.
165
+ * to register 'reg' and patch these instructions at 'addr'.
166166 */
167
-void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
167
+void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t *addr)
168168 {
169
- /* lis r3,(op)@highest */
170
- patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(3) |
171
- ((val >> 48) & 0xffff));
169
+ /* lis reg,(op)@highest */
170
+ patch_instruction((struct ppc_inst *)addr,
171
+ ppc_inst(PPC_INST_ADDIS | ___PPC_RT(reg) |
172
+ ((val >> 48) & 0xffff)));
172173 addr++;
173174
174
- /* ori r3,r3,(op)@higher */
175
- patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
176
- ___PPC_RS(3) | ((val >> 32) & 0xffff));
175
+ /* ori reg,reg,(op)@higher */
176
+ patch_instruction((struct ppc_inst *)addr,
177
+ ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
178
+ ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
177179 addr++;
178180
179
- /* rldicr r3,r3,32,31 */
180
- patch_instruction(addr, PPC_INST_RLDICR | ___PPC_RA(3) |
181
- ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31));
181
+ /* rldicr reg,reg,32,31 */
182
+ patch_instruction((struct ppc_inst *)addr,
183
+ ppc_inst(PPC_INST_RLDICR | ___PPC_RA(reg) |
184
+ ___PPC_RS(reg) | __PPC_SH64(32) | __PPC_ME64(31)));
182185 addr++;
183186
184
- /* oris r3,r3,(op)@h */
185
- patch_instruction(addr, PPC_INST_ORIS | ___PPC_RA(3) |
186
- ___PPC_RS(3) | ((val >> 16) & 0xffff));
187
+ /* oris reg,reg,(op)@h */
188
+ patch_instruction((struct ppc_inst *)addr,
189
+ ppc_inst(PPC_INST_ORIS | ___PPC_RA(reg) |
190
+ ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
187191 addr++;
188192
189
- /* ori r3,r3,(op)@l */
190
- patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
191
- ___PPC_RS(3) | (val & 0xffff));
193
+ /* ori reg,reg,(op)@l */
194
+ patch_instruction((struct ppc_inst *)addr,
195
+ ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
196
+ ___PPC_RS(reg) | (val & 0xffff)));
192197 }
193198
194199 int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
195200 {
196
- kprobe_opcode_t *buff, branch_op_callback, branch_emulate_step;
197
- kprobe_opcode_t *op_callback_addr, *emulate_step_addr;
201
+ struct ppc_inst branch_op_callback, branch_emulate_step, temp;
202
+ kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
198203 long b_offset;
199204 unsigned long nip, size;
200205 int rc, i;
....@@ -234,7 +239,8 @@
234239 size = (TMPL_END_IDX * sizeof(kprobe_opcode_t)) / sizeof(int);
235240 pr_devel("Copying template to %p, size %lu\n", buff, size);
236241 for (i = 0; i < size; i++) {
237
- rc = patch_instruction(buff + i, *(optprobe_template_entry + i));
242
+ rc = patch_instruction((struct ppc_inst *)(buff + i),
243
+ ppc_inst(*(optprobe_template_entry + i)));
238244 if (rc < 0)
239245 goto error;
240246 }
....@@ -243,7 +249,7 @@
243249 * Fixup the template with instructions to:
244250 * 1. load the address of the actual probepoint
245251 */
246
- patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
252
+ patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
247253
248254 /*
249255 * 2. branch to optimized_callback() and emulate_step()
....@@ -255,29 +261,34 @@
255261 goto error;
256262 }
257263
258
- branch_op_callback = create_branch((unsigned int *)buff + TMPL_CALL_HDLR_IDX,
259
- (unsigned long)op_callback_addr,
260
- BRANCH_SET_LINK);
264
+ rc = create_branch(&branch_op_callback,
265
+ (struct ppc_inst *)(buff + TMPL_CALL_HDLR_IDX),
266
+ (unsigned long)op_callback_addr,
267
+ BRANCH_SET_LINK);
261268
262
- branch_emulate_step = create_branch((unsigned int *)buff + TMPL_EMULATE_IDX,
263
- (unsigned long)emulate_step_addr,
264
- BRANCH_SET_LINK);
269
+ rc |= create_branch(&branch_emulate_step,
270
+ (struct ppc_inst *)(buff + TMPL_EMULATE_IDX),
271
+ (unsigned long)emulate_step_addr,
272
+ BRANCH_SET_LINK);
265273
266
- if (!branch_op_callback || !branch_emulate_step)
274
+ if (rc)
267275 goto error;
268276
269
- patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
270
- patch_instruction(buff + TMPL_EMULATE_IDX, branch_emulate_step);
277
+ patch_instruction((struct ppc_inst *)(buff + TMPL_CALL_HDLR_IDX),
278
+ branch_op_callback);
279
+ patch_instruction((struct ppc_inst *)(buff + TMPL_EMULATE_IDX),
280
+ branch_emulate_step);
271281
272282 /*
273283 * 3. load instruction to be emulated into relevant register, and
274284 */
275
- patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
285
+ temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn);
286
+ patch_imm64_load_insns(ppc_inst_as_u64(temp), 4, buff + TMPL_INSN_IDX);
276287
277288 /*
278289 * 4. branch back from trampoline
279290 */
280
- patch_branch(buff + TMPL_RET_IDX, (unsigned long)nip, 0);
291
+ patch_branch((struct ppc_inst *)(buff + TMPL_RET_IDX), (unsigned long)nip, 0);
281292
282293 flush_icache_range((unsigned long)buff,
283294 (unsigned long)(&buff[TMPL_END_IDX]));
....@@ -309,6 +320,7 @@
309320
310321 void arch_optimize_kprobes(struct list_head *oplist)
311322 {
323
+ struct ppc_inst instr;
312324 struct optimized_kprobe *op;
313325 struct optimized_kprobe *tmp;
314326
....@@ -319,9 +331,10 @@
319331 */
320332 memcpy(op->optinsn.copied_insn, op->kp.addr,
321333 RELATIVEJUMP_SIZE);
322
- patch_instruction(op->kp.addr,
323
- create_branch((unsigned int *)op->kp.addr,
324
- (unsigned long)op->optinsn.insn, 0));
334
+ create_branch(&instr,
335
+ (struct ppc_inst *)op->kp.addr,
336
+ (unsigned long)op->optinsn.insn, 0);
337
+ patch_instruction((struct ppc_inst *)op->kp.addr, instr);
325338 list_del_init(&op->list);
326339 }
327340 }