1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * Code to prepare detour buffer for optprobes in Kernel. 4 * 5 * Copyright 2017, Anju T, IBM Corp. 6 */ 7 8#include <asm/ppc_asm.h> 9#include <asm/ptrace.h> 10#include <asm/asm-offsets.h> 11 12#ifdef CONFIG_PPC64 13#define SAVE_30GPRS(base) SAVE_GPRS(2, 31, base) 14#define REST_30GPRS(base) REST_GPRS(2, 31, 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 22#define OPT_SLOT_SIZE 65536 23 24 .balign 4 25 26 /* 27 * Reserve an area to allocate slots for detour buffer. 28 * This is part of .text section (rather than vmalloc area) 29 * as this needs to be within 32MB of the probed address. 30 */ 31 .global optinsn_slot 32optinsn_slot: 33 .space OPT_SLOT_SIZE 34 35 /* 36 * Optprobe template: 37 * This template gets copied into one of the slots in optinsn_slot 38 * and gets fixed up with real optprobe structures et al. 39 */ 40 .global optprobe_template_entry 41optprobe_template_entry: 42 /* Create an in-memory pt_regs */ 43 PPC_STLU r1,-INT_FRAME_SIZE(r1) 44 SAVE_GPR(0,r1) 45 /* Save the previous SP into stack */ 46 addi r0,r1,INT_FRAME_SIZE 47 PPC_STL r0,GPR1(r1) 48 SAVE_30GPRS(r1) 49 /* Save SPRS */ 50 mfmsr r5 51 PPC_STL r5,_MSR(r1) 52 li r5,0x700 53 PPC_STL r5,_TRAP(r1) 54 li r5,0 55 PPC_STL r5,ORIG_GPR3(r1) 56 PPC_STL r5,RESULT(r1) 57 mfctr r5 58 PPC_STL r5,_CTR(r1) 59 mflr r5 60 PPC_STL r5,_LINK(r1) 61 mfspr r5,SPRN_XER 62 PPC_STL r5,_XER(r1) 63 mfcr r5 64 PPC_STL r5,_CCR(r1) 65#ifdef CONFIG_PPC64 66 lbz r5,PACAIRQSOFTMASK(r13) 67 std r5,SOFTE(r1) 68#endif 69 70 /* 71 * We may get here from a module, so load the kernel TOC in r2. 72 * The original TOC gets restored when pt_regs is restored 73 * further below. 74 */ 75#ifdef CONFIG_PPC64 76 LOAD_PACA_TOC() 77#endif 78 79 .global optprobe_template_op_address 80optprobe_template_op_address: 81 /* 82 * Parameters to optimized_callback(): 83 * 1. optimized_kprobe structure in r3 84 */ 85 TEMPLATE_FOR_IMM_LOAD_INSNS 86 87 /* 2. pt_regs pointer in r4 */ 88 addi r4,r1,STACK_INT_FRAME_REGS 89 90 .global optprobe_template_call_handler 91optprobe_template_call_handler: 92 /* Branch to optimized_callback() */ 93 nop 94 95 /* 96 * Parameters for instruction emulation: 97 * 1. Pass SP in register r3. 98 */ 99 addi r3,r1,STACK_INT_FRAME_REGS 100 101 .global optprobe_template_insn 102optprobe_template_insn: 103 /* 2, Pass instruction to be emulated in r4 */ 104 TEMPLATE_FOR_IMM_LOAD_INSNS 105 106 .global optprobe_template_call_emulate 107optprobe_template_call_emulate: 108 /* Branch to emulate_step() */ 109 nop 110 111 /* 112 * All done. 113 * Now, restore the registers... 114 */ 115 PPC_LL r5,_MSR(r1) 116 mtmsr r5 117 PPC_LL r5,_CTR(r1) 118 mtctr r5 119 PPC_LL r5,_LINK(r1) 120 mtlr r5 121 PPC_LL r5,_XER(r1) 122 mtxer r5 123 PPC_LL r5,_CCR(r1) 124 mtcr r5 125 REST_GPR(0,r1) 126 REST_30GPRS(r1) 127 /* Restore the previous SP */ 128 addi r1,r1,INT_FRAME_SIZE 129 130 .global optprobe_template_ret 131optprobe_template_ret: 132 /* ... and jump back from trampoline */ 133 nop 134 135 .global optprobe_template_end 136optprobe_template_end: 137