linux/arch/powerpc/kernel/optprobes_head.S
Jordan Niethe 650b55b707 powerpc: Add prefixed instructions to instruction data type
For powerpc64, redefine the ppc_inst type so both word and prefixed
instructions can be represented. On powerpc32 the type will remain the
same. Update places which had assumed instructions to be 4 bytes long.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
Reviewed-by: Alistair Popple <alistair@popple.id.au>
[mpe: Rework the get_user_inst() macros to be parameterised, and don't
      assign to the dest if an error occurred. Use CONFIG_PPC64 not
      __powerpc64__ in a few places. Address other comments from
      Christophe. Fix some sparse complaints.]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200506034050.24806-24-jniethe5@gmail.com
2020-05-19 00:10:39 +10:00

134 lines
2.6 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>
#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 */
stdu 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)
/* Save SPRS */
mfmsr r5
std r5,_MSR(r1)
li r5,0x700
std r5,_TRAP(r1)
li r5,0
std r5,ORIG_GPR3(r1)
std r5,RESULT(r1)
mfctr r5
std r5,_CTR(r1)
mflr r5
std r5,_LINK(r1)
mfspr r5,SPRN_XER
std r5,_XER(r1)
mfcr r5
std r5,_CCR(r1)
lbz r5,PACAIRQSOFTMASK(r13)
std r5,SOFTE(r1)
/*
* 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.
*/
ld r2,PACATOC(r13)
.global optprobe_template_op_address
optprobe_template_op_address:
/*
* Parameters to optimized_callback():
* 1. optimized_kprobe structure in r3
*/
nop
nop
nop
nop
nop
/* 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 */
nop
nop
nop
nop
nop
.global optprobe_template_call_emulate
optprobe_template_call_emulate:
/* Branch to emulate_step() */
nop
/*
* All done.
* Now, restore the registers...
*/
ld r5,_MSR(r1)
mtmsr r5
ld r5,_CTR(r1)
mtctr r5
ld r5,_LINK(r1)
mtlr r5
ld r5,_XER(r1)
mtxer r5
ld r5,_CCR(r1)
mtcr r5
REST_GPR(0,r1)
REST_10GPRS(2,r1)
REST_10GPRS(12,r1)
REST_10GPRS(22,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: