mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 08:58:07 +00:00
aebd1fb45c
Introduce macros that operate on a (start, end) range of GPRs, which reduces lines of code and need to do mental arithmetic while reading the code. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Segher Boessenkool <segher@kernel.crashing.org> Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20211022061322.2671178-1-npiggin@gmail.com
136 lines
2.9 KiB
ArmAsm
136 lines
2.9 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Code to prepare detour buffer for optprobes in Kernel.
|
|
*
|
|
* Copyright 2017, Anju T, IBM Corp.
|
|
*/
|
|
|
|
#include <asm/ppc_asm.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/asm-offsets.h>
|
|
|
|
#ifdef CONFIG_PPC64
|
|
#define SAVE_30GPRS(base) SAVE_GPRS(2, 31, base)
|
|
#define REST_30GPRS(base) REST_GPRS(2, 31, 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
|
|
|
|
/*
|
|
* Reserve an area to allocate slots for detour buffer.
|
|
* This is part of .text section (rather than vmalloc area)
|
|
* as this needs to be within 32MB of the probed address.
|
|
*/
|
|
.global optinsn_slot
|
|
optinsn_slot:
|
|
.space OPT_SLOT_SIZE
|
|
|
|
/*
|
|
* Optprobe template:
|
|
* This template gets copied into one of the slots in optinsn_slot
|
|
* and gets fixed up with real optprobe structures et al.
|
|
*/
|
|
.global optprobe_template_entry
|
|
optprobe_template_entry:
|
|
/* Create an in-memory pt_regs */
|
|
PPC_STLU r1,-INT_FRAME_SIZE(r1)
|
|
SAVE_GPR(0,r1)
|
|
/* Save the previous SP into stack */
|
|
addi r0,r1,INT_FRAME_SIZE
|
|
PPC_STL r0,GPR1(r1)
|
|
SAVE_30GPRS(r1)
|
|
/* Save SPRS */
|
|
mfmsr r5
|
|
PPC_STL r5,_MSR(r1)
|
|
li r5,0x700
|
|
PPC_STL r5,_TRAP(r1)
|
|
li r5,0
|
|
PPC_STL r5,ORIG_GPR3(r1)
|
|
PPC_STL r5,RESULT(r1)
|
|
mfctr r5
|
|
PPC_STL r5,_CTR(r1)
|
|
mflr r5
|
|
PPC_STL r5,_LINK(r1)
|
|
mfspr r5,SPRN_XER
|
|
PPC_STL r5,_XER(r1)
|
|
mfcr r5
|
|
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:
|
|
/*
|
|
* Parameters to optimized_callback():
|
|
* 1. optimized_kprobe structure in r3
|
|
*/
|
|
TEMPLATE_FOR_IMM_LOAD_INSNS
|
|
|
|
/* 2. pt_regs pointer in r4 */
|
|
addi r4,r1,STACK_FRAME_OVERHEAD
|
|
|
|
.global optprobe_template_call_handler
|
|
optprobe_template_call_handler:
|
|
/* Branch to optimized_callback() */
|
|
nop
|
|
|
|
/*
|
|
* Parameters for instruction emulation:
|
|
* 1. Pass SP in register r3.
|
|
*/
|
|
addi r3,r1,STACK_FRAME_OVERHEAD
|
|
|
|
.global optprobe_template_insn
|
|
optprobe_template_insn:
|
|
/* 2, Pass instruction to be emulated in r4 */
|
|
TEMPLATE_FOR_IMM_LOAD_INSNS
|
|
|
|
.global optprobe_template_call_emulate
|
|
optprobe_template_call_emulate:
|
|
/* Branch to emulate_step() */
|
|
nop
|
|
|
|
/*
|
|
* All done.
|
|
* Now, restore the registers...
|
|
*/
|
|
PPC_LL r5,_MSR(r1)
|
|
mtmsr r5
|
|
PPC_LL r5,_CTR(r1)
|
|
mtctr r5
|
|
PPC_LL r5,_LINK(r1)
|
|
mtlr r5
|
|
PPC_LL r5,_XER(r1)
|
|
mtxer r5
|
|
PPC_LL r5,_CCR(r1)
|
|
mtcr r5
|
|
REST_GPR(0,r1)
|
|
REST_30GPRS(r1)
|
|
/* Restore the previous SP */
|
|
addi r1,r1,INT_FRAME_SIZE
|
|
|
|
.global optprobe_template_ret
|
|
optprobe_template_ret:
|
|
/* ... and jump back from trampoline */
|
|
nop
|
|
|
|
.global optprobe_template_end
|
|
optprobe_template_end:
|