Commit eacf4c02 authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman

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: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/bad58c66859b2a475c0ad516b53164ae3b4853cd.1618927318.git.christophe.leroy@csgroup.eu
parent 693557eb
...@@ -229,7 +229,7 @@ config PPC ...@@ -229,7 +229,7 @@ config PPC
select HAVE_MOD_ARCH_SPECIFIC select HAVE_MOD_ARCH_SPECIFIC
select HAVE_NMI if PERF_EVENTS || (PPC64 && PPC_BOOK3S) select HAVE_NMI if PERF_EVENTS || (PPC64 && PPC_BOOK3S)
select HAVE_HARDLOCKUP_DETECTOR_ARCH if PPC64 && PPC_BOOK3S && SMP select HAVE_HARDLOCKUP_DETECTOR_ARCH if PPC64 && PPC_BOOK3S && SMP
select HAVE_OPTPROBES if PPC64 select HAVE_OPTPROBES
select HAVE_PERF_EVENTS select HAVE_PERF_EVENTS
select HAVE_PERF_EVENTS_NMI if PPC64 select HAVE_PERF_EVENTS_NMI if PPC64
select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH
......
...@@ -141,11 +141,21 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) ...@@ -141,11 +141,21 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
} }
} }
static void patch_imm32_load_insns(unsigned long val, int reg, kprobe_opcode_t *addr)
{
patch_instruction((struct ppc_inst *)addr,
ppc_inst(PPC_RAW_LIS(reg, IMM_H(val))));
addr++;
patch_instruction((struct ppc_inst *)addr,
ppc_inst(PPC_RAW_ORI(reg, reg, IMM_L(val))));
}
/* /*
* Generate instructions to load provided immediate 64-bit value * Generate instructions to load provided immediate 64-bit value
* to register 'reg' and patch these instructions at 'addr'. * to register 'reg' and patch these instructions at 'addr'.
*/ */
static void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t *addr) static void patch_imm64_load_insns(unsigned long long val, int reg, kprobe_opcode_t *addr)
{ {
/* lis reg,(op)@highest */ /* lis reg,(op)@highest */
patch_instruction((struct ppc_inst *)addr, patch_instruction((struct ppc_inst *)addr,
...@@ -177,6 +187,14 @@ static void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t * ...@@ -177,6 +187,14 @@ static void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t *
___PPC_RS(reg) | (val & 0xffff))); ___PPC_RS(reg) | (val & 0xffff)));
} }
static void patch_imm_load_insns(unsigned long val, int reg, kprobe_opcode_t *addr)
{
if (IS_ENABLED(CONFIG_PPC64))
patch_imm64_load_insns(val, reg, addr);
else
patch_imm32_load_insns(val, reg, addr);
}
int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p) int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
{ {
struct ppc_inst branch_op_callback, branch_emulate_step, temp; struct ppc_inst branch_op_callback, branch_emulate_step, temp;
...@@ -230,7 +248,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p) ...@@ -230,7 +248,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
* Fixup the template with instructions to: * Fixup the template with instructions to:
* 1. load the address of the actual probepoint * 1. load the address of the actual probepoint
*/ */
patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX); patch_imm_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
/* /*
* 2. branch to optimized_callback() and emulate_step() * 2. branch to optimized_callback() and emulate_step()
...@@ -264,7 +282,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p) ...@@ -264,7 +282,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
* 3. load instruction to be emulated into relevant register, and * 3. load instruction to be emulated into relevant register, and
*/ */
temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn); temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn);
patch_imm64_load_insns(ppc_inst_as_ulong(temp), 4, buff + TMPL_INSN_IDX); patch_imm_load_insns(ppc_inst_as_ulong(temp), 4, buff + TMPL_INSN_IDX);
/* /*
* 4. branch back from trampoline * 4. branch back from trampoline
......
...@@ -9,6 +9,16 @@ ...@@ -9,6 +9,16 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#ifdef CONFIG_PPC64
#define SAVE_30GPRS(base) SAVE_10GPRS(2,base); SAVE_10GPRS(12,base); SAVE_10GPRS(22,base)
#define REST_30GPRS(base) REST_10GPRS(2,base); REST_10GPRS(12,base); REST_10GPRS(22,base)
#define TEMPLATE_FOR_IMM_LOAD_INSNS nop; nop; nop; nop; nop
#else
#define SAVE_30GPRS(base) stmw r2, GPR2(base)
#define REST_30GPRS(base) lmw r2, GPR2(base)
#define TEMPLATE_FOR_IMM_LOAD_INSNS nop; nop; nop
#endif
#define OPT_SLOT_SIZE 65536 #define OPT_SLOT_SIZE 65536
.balign 4 .balign 4
...@@ -30,39 +40,41 @@ optinsn_slot: ...@@ -30,39 +40,41 @@ optinsn_slot:
.global optprobe_template_entry .global optprobe_template_entry
optprobe_template_entry: optprobe_template_entry:
/* Create an in-memory pt_regs */ /* Create an in-memory pt_regs */
stdu r1,-INT_FRAME_SIZE(r1) PPC_STLU r1,-INT_FRAME_SIZE(r1)
SAVE_GPR(0,r1) SAVE_GPR(0,r1)
/* Save the previous SP into stack */ /* Save the previous SP into stack */
addi r0,r1,INT_FRAME_SIZE addi r0,r1,INT_FRAME_SIZE
std r0,GPR1(r1) PPC_STL r0,GPR1(r1)
SAVE_10GPRS(2,r1) SAVE_30GPRS(r1)
SAVE_10GPRS(12,r1)
SAVE_10GPRS(22,r1)
/* Save SPRS */ /* Save SPRS */
mfmsr r5 mfmsr r5
std r5,_MSR(r1) PPC_STL r5,_MSR(r1)
li r5,0x700 li r5,0x700
std r5,_TRAP(r1) PPC_STL r5,_TRAP(r1)
li r5,0 li r5,0
std r5,ORIG_GPR3(r1) PPC_STL r5,ORIG_GPR3(r1)
std r5,RESULT(r1) PPC_STL r5,RESULT(r1)
mfctr r5 mfctr r5
std r5,_CTR(r1) PPC_STL r5,_CTR(r1)
mflr r5 mflr r5
std r5,_LINK(r1) PPC_STL r5,_LINK(r1)
mfspr r5,SPRN_XER mfspr r5,SPRN_XER
std r5,_XER(r1) PPC_STL r5,_XER(r1)
mfcr r5 mfcr r5
std r5,_CCR(r1) PPC_STL r5,_CCR(r1)
#ifdef CONFIG_PPC64
lbz r5,PACAIRQSOFTMASK(r13) lbz r5,PACAIRQSOFTMASK(r13)
std r5,SOFTE(r1) std r5,SOFTE(r1)
#endif
/* /*
* We may get here from a module, so load the kernel TOC in r2. * We may get here from a module, so load the kernel TOC in r2.
* The original TOC gets restored when pt_regs is restored * The original TOC gets restored when pt_regs is restored
* further below. * further below.
*/ */
#ifdef CONFIG_PPC64
ld r2,PACATOC(r13) ld r2,PACATOC(r13)
#endif
.global optprobe_template_op_address .global optprobe_template_op_address
optprobe_template_op_address: optprobe_template_op_address:
...@@ -70,11 +82,8 @@ optprobe_template_op_address: ...@@ -70,11 +82,8 @@ optprobe_template_op_address:
* Parameters to optimized_callback(): * Parameters to optimized_callback():
* 1. optimized_kprobe structure in r3 * 1. optimized_kprobe structure in r3
*/ */
nop TEMPLATE_FOR_IMM_LOAD_INSNS
nop
nop
nop
nop
/* 2. pt_regs pointer in r4 */ /* 2. pt_regs pointer in r4 */
addi r4,r1,STACK_FRAME_OVERHEAD addi r4,r1,STACK_FRAME_OVERHEAD
...@@ -92,11 +101,7 @@ optprobe_template_call_handler: ...@@ -92,11 +101,7 @@ optprobe_template_call_handler:
.global optprobe_template_insn .global optprobe_template_insn
optprobe_template_insn: optprobe_template_insn:
/* 2, Pass instruction to be emulated in r4 */ /* 2, Pass instruction to be emulated in r4 */
nop TEMPLATE_FOR_IMM_LOAD_INSNS
nop
nop
nop
nop
.global optprobe_template_call_emulate .global optprobe_template_call_emulate
optprobe_template_call_emulate: optprobe_template_call_emulate:
...@@ -107,20 +112,18 @@ optprobe_template_call_emulate: ...@@ -107,20 +112,18 @@ optprobe_template_call_emulate:
* All done. * All done.
* Now, restore the registers... * Now, restore the registers...
*/ */
ld r5,_MSR(r1) PPC_LL r5,_MSR(r1)
mtmsr r5 mtmsr r5
ld r5,_CTR(r1) PPC_LL r5,_CTR(r1)
mtctr r5 mtctr r5
ld r5,_LINK(r1) PPC_LL r5,_LINK(r1)
mtlr r5 mtlr r5
ld r5,_XER(r1) PPC_LL r5,_XER(r1)
mtxer r5 mtxer r5
ld r5,_CCR(r1) PPC_LL r5,_CCR(r1)
mtcr r5 mtcr r5
REST_GPR(0,r1) REST_GPR(0,r1)
REST_10GPRS(2,r1) REST_30GPRS(r1)
REST_10GPRS(12,r1)
REST_10GPRS(22,r1)
/* Restore the previous SP */ /* Restore the previous SP */
addi r1,r1,INT_FRAME_SIZE addi r1,r1,INT_FRAME_SIZE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment