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
This commit is contained in:
Родитель
693557ebf4
Коммит
eacf4c0202
|
@ -229,7 +229,7 @@ config PPC
|
|||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select HAVE_NMI if PERF_EVENTS || (PPC64 && PPC_BOOK3S)
|
||||
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_NMI if PPC64
|
||||
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)
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
* 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 */
|
||||
patch_instruction((struct ppc_inst *)addr,
|
||||
|
@ -177,6 +187,14 @@ static void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t *
|
|||
___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)
|
||||
{
|
||||
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)
|
|||
* Fixup the template with instructions to:
|
||||
* 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()
|
||||
|
@ -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
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -9,6 +9,16 @@
|
|||
#include <asm/ptrace.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
|
||||
|
||||
.balign 4
|
||||
|
@ -30,39 +40,41 @@ optinsn_slot:
|
|||
.global optprobe_template_entry
|
||||
optprobe_template_entry:
|
||||
/* Create an in-memory pt_regs */
|
||||
stdu r1,-INT_FRAME_SIZE(r1)
|
||||
PPC_STLU r1,-INT_FRAME_SIZE(r1)
|
||||
SAVE_GPR(0,r1)
|
||||
/* Save the previous SP into stack */
|
||||
addi r0,r1,INT_FRAME_SIZE
|
||||
std r0,GPR1(r1)
|
||||
SAVE_10GPRS(2,r1)
|
||||
SAVE_10GPRS(12,r1)
|
||||
SAVE_10GPRS(22,r1)
|
||||
PPC_STL r0,GPR1(r1)
|
||||
SAVE_30GPRS(r1)
|
||||
/* Save SPRS */
|
||||
mfmsr r5
|
||||
std r5,_MSR(r1)
|
||||
PPC_STL r5,_MSR(r1)
|
||||
li r5,0x700
|
||||
std r5,_TRAP(r1)
|
||||
PPC_STL r5,_TRAP(r1)
|
||||
li r5,0
|
||||
std r5,ORIG_GPR3(r1)
|
||||
std r5,RESULT(r1)
|
||||
PPC_STL r5,ORIG_GPR3(r1)
|
||||
PPC_STL r5,RESULT(r1)
|
||||
mfctr r5
|
||||
std r5,_CTR(r1)
|
||||
PPC_STL r5,_CTR(r1)
|
||||
mflr r5
|
||||
std r5,_LINK(r1)
|
||||
PPC_STL r5,_LINK(r1)
|
||||
mfspr r5,SPRN_XER
|
||||
std r5,_XER(r1)
|
||||
PPC_STL r5,_XER(r1)
|
||||
mfcr r5
|
||||
std r5,_CCR(r1)
|
||||
PPC_STL r5,_CCR(r1)
|
||||
#ifdef CONFIG_PPC64
|
||||
lbz r5,PACAIRQSOFTMASK(r13)
|
||||
std r5,SOFTE(r1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We may get here from a module, so load the kernel TOC in r2.
|
||||
* The original TOC gets restored when pt_regs is restored
|
||||
* further below.
|
||||
*/
|
||||
#ifdef CONFIG_PPC64
|
||||
ld r2,PACATOC(r13)
|
||||
#endif
|
||||
|
||||
.global optprobe_template_op_address
|
||||
optprobe_template_op_address:
|
||||
|
@ -70,11 +82,8 @@ optprobe_template_op_address:
|
|||
* Parameters to optimized_callback():
|
||||
* 1. optimized_kprobe structure in r3
|
||||
*/
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
TEMPLATE_FOR_IMM_LOAD_INSNS
|
||||
|
||||
/* 2. pt_regs pointer in r4 */
|
||||
addi r4,r1,STACK_FRAME_OVERHEAD
|
||||
|
||||
|
@ -92,11 +101,7 @@ optprobe_template_call_handler:
|
|||
.global optprobe_template_insn
|
||||
optprobe_template_insn:
|
||||
/* 2, Pass instruction to be emulated in r4 */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
TEMPLATE_FOR_IMM_LOAD_INSNS
|
||||
|
||||
.global optprobe_template_call_emulate
|
||||
optprobe_template_call_emulate:
|
||||
|
@ -107,20 +112,18 @@ optprobe_template_call_emulate:
|
|||
* All done.
|
||||
* Now, restore the registers...
|
||||
*/
|
||||
ld r5,_MSR(r1)
|
||||
PPC_LL r5,_MSR(r1)
|
||||
mtmsr r5
|
||||
ld r5,_CTR(r1)
|
||||
PPC_LL r5,_CTR(r1)
|
||||
mtctr r5
|
||||
ld r5,_LINK(r1)
|
||||
PPC_LL r5,_LINK(r1)
|
||||
mtlr r5
|
||||
ld r5,_XER(r1)
|
||||
PPC_LL r5,_XER(r1)
|
||||
mtxer r5
|
||||
ld r5,_CCR(r1)
|
||||
PPC_LL r5,_CCR(r1)
|
||||
mtcr r5
|
||||
REST_GPR(0,r1)
|
||||
REST_10GPRS(2,r1)
|
||||
REST_10GPRS(12,r1)
|
||||
REST_10GPRS(22,r1)
|
||||
REST_30GPRS(r1)
|
||||
/* Restore the previous SP */
|
||||
addi r1,r1,INT_FRAME_SIZE
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче