Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Enable OPTPROBES on PPC32

For that, create a 32 bits version of patch_imm64_load_insns()
and create a patch_imm_load_insns() which calls
patch_imm32_load_insns() on PPC32 and patch_imm64_load_insns()
on PPC64.

Adapt optprobes_head.S for PPC32. Use PPC_LL/PPC_STL macros instead
of raw ld/std, opt out things linked to paca and use stmw/lmw to
save/restore registers.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/bad58c66859b2a475c0ad516b53164ae3b4853cd.1618927318.git.christophe.leroy@csgroup.eu

authored by

Christophe Leroy and committed by
Michael Ellerman
eacf4c02 693557eb

+56 -35
+1 -1
arch/powerpc/Kconfig
··· 229 229 select HAVE_MOD_ARCH_SPECIFIC 230 230 select HAVE_NMI if PERF_EVENTS || (PPC64 && PPC_BOOK3S) 231 231 select HAVE_HARDLOCKUP_DETECTOR_ARCH if PPC64 && PPC_BOOK3S && SMP 232 - select HAVE_OPTPROBES if PPC64 232 + select HAVE_OPTPROBES 233 233 select HAVE_PERF_EVENTS 234 234 select HAVE_PERF_EVENTS_NMI if PPC64 235 235 select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH
+21 -3
arch/powerpc/kernel/optprobes.c
··· 141 141 } 142 142 } 143 143 144 + static void patch_imm32_load_insns(unsigned long val, int reg, kprobe_opcode_t *addr) 145 + { 146 + patch_instruction((struct ppc_inst *)addr, 147 + ppc_inst(PPC_RAW_LIS(reg, IMM_H(val)))); 148 + addr++; 149 + 150 + patch_instruction((struct ppc_inst *)addr, 151 + ppc_inst(PPC_RAW_ORI(reg, reg, IMM_L(val)))); 152 + } 153 + 144 154 /* 145 155 * Generate instructions to load provided immediate 64-bit value 146 156 * to register 'reg' and patch these instructions at 'addr'. 147 157 */ 148 - static void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t *addr) 158 + static void patch_imm64_load_insns(unsigned long long val, int reg, kprobe_opcode_t *addr) 149 159 { 150 160 /* lis reg,(op)@highest */ 151 161 patch_instruction((struct ppc_inst *)addr, ··· 185 175 patch_instruction((struct ppc_inst *)addr, 186 176 ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) | 187 177 ___PPC_RS(reg) | (val & 0xffff))); 178 + } 179 + 180 + static void patch_imm_load_insns(unsigned long val, int reg, kprobe_opcode_t *addr) 181 + { 182 + if (IS_ENABLED(CONFIG_PPC64)) 183 + patch_imm64_load_insns(val, reg, addr); 184 + else 185 + patch_imm32_load_insns(val, reg, addr); 188 186 } 189 187 190 188 int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p) ··· 248 230 * Fixup the template with instructions to: 249 231 * 1. load the address of the actual probepoint 250 232 */ 251 - patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX); 233 + patch_imm_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX); 252 234 253 235 /* 254 236 * 2. branch to optimized_callback() and emulate_step() ··· 282 264 * 3. load instruction to be emulated into relevant register, and 283 265 */ 284 266 temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn); 285 - patch_imm64_load_insns(ppc_inst_as_ulong(temp), 4, buff + TMPL_INSN_IDX); 267 + patch_imm_load_insns(ppc_inst_as_ulong(temp), 4, buff + TMPL_INSN_IDX); 286 268 287 269 /* 288 270 * 4. branch back from trampoline
+34 -31
arch/powerpc/kernel/optprobes_head.S
··· 9 9 #include <asm/ptrace.h> 10 10 #include <asm/asm-offsets.h> 11 11 12 + #ifdef CONFIG_PPC64 13 + #define SAVE_30GPRS(base) SAVE_10GPRS(2,base); SAVE_10GPRS(12,base); SAVE_10GPRS(22,base) 14 + #define REST_30GPRS(base) REST_10GPRS(2,base); REST_10GPRS(12,base); REST_10GPRS(22,base) 15 + #define TEMPLATE_FOR_IMM_LOAD_INSNS nop; nop; nop; nop; nop 16 + #else 17 + #define SAVE_30GPRS(base) stmw r2, GPR2(base) 18 + #define REST_30GPRS(base) lmw r2, GPR2(base) 19 + #define TEMPLATE_FOR_IMM_LOAD_INSNS nop; nop; nop 20 + #endif 21 + 12 22 #define OPT_SLOT_SIZE 65536 13 23 14 24 .balign 4 ··· 40 30 .global optprobe_template_entry 41 31 optprobe_template_entry: 42 32 /* Create an in-memory pt_regs */ 43 - stdu r1,-INT_FRAME_SIZE(r1) 33 + PPC_STLU r1,-INT_FRAME_SIZE(r1) 44 34 SAVE_GPR(0,r1) 45 35 /* Save the previous SP into stack */ 46 36 addi r0,r1,INT_FRAME_SIZE 47 - std r0,GPR1(r1) 48 - SAVE_10GPRS(2,r1) 49 - SAVE_10GPRS(12,r1) 50 - SAVE_10GPRS(22,r1) 37 + PPC_STL r0,GPR1(r1) 38 + SAVE_30GPRS(r1) 51 39 /* Save SPRS */ 52 40 mfmsr r5 53 - std r5,_MSR(r1) 41 + PPC_STL r5,_MSR(r1) 54 42 li r5,0x700 55 - std r5,_TRAP(r1) 43 + PPC_STL r5,_TRAP(r1) 56 44 li r5,0 57 - std r5,ORIG_GPR3(r1) 58 - std r5,RESULT(r1) 45 + PPC_STL r5,ORIG_GPR3(r1) 46 + PPC_STL r5,RESULT(r1) 59 47 mfctr r5 60 - std r5,_CTR(r1) 48 + PPC_STL r5,_CTR(r1) 61 49 mflr r5 62 - std r5,_LINK(r1) 50 + PPC_STL r5,_LINK(r1) 63 51 mfspr r5,SPRN_XER 64 - std r5,_XER(r1) 52 + PPC_STL r5,_XER(r1) 65 53 mfcr r5 66 - std r5,_CCR(r1) 54 + PPC_STL r5,_CCR(r1) 55 + #ifdef CONFIG_PPC64 67 56 lbz r5,PACAIRQSOFTMASK(r13) 68 57 std r5,SOFTE(r1) 58 + #endif 69 59 70 60 /* 71 61 * We may get here from a module, so load the kernel TOC in r2. 72 62 * The original TOC gets restored when pt_regs is restored 73 63 * further below. 74 64 */ 65 + #ifdef CONFIG_PPC64 75 66 ld r2,PACATOC(r13) 67 + #endif 76 68 77 69 .global optprobe_template_op_address 78 70 optprobe_template_op_address: ··· 82 70 * Parameters to optimized_callback(): 83 71 * 1. optimized_kprobe structure in r3 84 72 */ 85 - nop 86 - nop 87 - nop 88 - nop 89 - nop 73 + TEMPLATE_FOR_IMM_LOAD_INSNS 74 + 90 75 /* 2. pt_regs pointer in r4 */ 91 76 addi r4,r1,STACK_FRAME_OVERHEAD 92 77 ··· 101 92 .global optprobe_template_insn 102 93 optprobe_template_insn: 103 94 /* 2, Pass instruction to be emulated in r4 */ 104 - nop 105 - nop 106 - nop 107 - nop 108 - nop 95 + TEMPLATE_FOR_IMM_LOAD_INSNS 109 96 110 97 .global optprobe_template_call_emulate 111 98 optprobe_template_call_emulate: ··· 112 107 * All done. 113 108 * Now, restore the registers... 114 109 */ 115 - ld r5,_MSR(r1) 110 + PPC_LL r5,_MSR(r1) 116 111 mtmsr r5 117 - ld r5,_CTR(r1) 112 + PPC_LL r5,_CTR(r1) 118 113 mtctr r5 119 - ld r5,_LINK(r1) 114 + PPC_LL r5,_LINK(r1) 120 115 mtlr r5 121 - ld r5,_XER(r1) 116 + PPC_LL r5,_XER(r1) 122 117 mtxer r5 123 - ld r5,_CCR(r1) 118 + PPC_LL r5,_CCR(r1) 124 119 mtcr r5 125 120 REST_GPR(0,r1) 126 - REST_10GPRS(2,r1) 127 - REST_10GPRS(12,r1) 128 - REST_10GPRS(22,r1) 121 + REST_30GPRS(r1) 129 122 /* Restore the previous SP */ 130 123 addi r1,r1,INT_FRAME_SIZE 131 124