12874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */ 251c9c084SAnju T/* 351c9c084SAnju T * Code to prepare detour buffer for optprobes in Kernel. 451c9c084SAnju T * 551c9c084SAnju T * Copyright 2017, Anju T, IBM Corp. 651c9c084SAnju T */ 751c9c084SAnju T 851c9c084SAnju T#include <asm/ppc_asm.h> 951c9c084SAnju T#include <asm/ptrace.h> 1051c9c084SAnju T#include <asm/asm-offsets.h> 1151c9c084SAnju T 12eacf4c02SChristophe Leroy#ifdef CONFIG_PPC64 13aebd1fb4SNicholas Piggin#define SAVE_30GPRS(base) SAVE_GPRS(2, 31, base) 14aebd1fb4SNicholas Piggin#define REST_30GPRS(base) REST_GPRS(2, 31, base) 15eacf4c02SChristophe Leroy#define TEMPLATE_FOR_IMM_LOAD_INSNS nop; nop; nop; nop; nop 16eacf4c02SChristophe Leroy#else 17eacf4c02SChristophe Leroy#define SAVE_30GPRS(base) stmw r2, GPR2(base) 18eacf4c02SChristophe Leroy#define REST_30GPRS(base) lmw r2, GPR2(base) 19eacf4c02SChristophe Leroy#define TEMPLATE_FOR_IMM_LOAD_INSNS nop; nop; nop 20eacf4c02SChristophe Leroy#endif 21eacf4c02SChristophe Leroy 2251c9c084SAnju T#define OPT_SLOT_SIZE 65536 2351c9c084SAnju T 2451c9c084SAnju T .balign 4 2551c9c084SAnju T 2651c9c084SAnju T /* 2751c9c084SAnju T * Reserve an area to allocate slots for detour buffer. 2851c9c084SAnju T * This is part of .text section (rather than vmalloc area) 2951c9c084SAnju T * as this needs to be within 32MB of the probed address. 3051c9c084SAnju T */ 3151c9c084SAnju T .global optinsn_slot 3251c9c084SAnju Toptinsn_slot: 3351c9c084SAnju T .space OPT_SLOT_SIZE 3451c9c084SAnju T 3551c9c084SAnju T /* 3651c9c084SAnju T * Optprobe template: 3751c9c084SAnju T * This template gets copied into one of the slots in optinsn_slot 3851c9c084SAnju T * and gets fixed up with real optprobe structures et al. 3951c9c084SAnju T */ 4051c9c084SAnju T .global optprobe_template_entry 4151c9c084SAnju Toptprobe_template_entry: 4251c9c084SAnju T /* Create an in-memory pt_regs */ 43eacf4c02SChristophe Leroy PPC_STLU r1,-INT_FRAME_SIZE(r1) 4451c9c084SAnju T SAVE_GPR(0,r1) 4551c9c084SAnju T /* Save the previous SP into stack */ 4651c9c084SAnju T addi r0,r1,INT_FRAME_SIZE 47eacf4c02SChristophe Leroy PPC_STL r0,GPR1(r1) 48eacf4c02SChristophe Leroy SAVE_30GPRS(r1) 4951c9c084SAnju T /* Save SPRS */ 5051c9c084SAnju T mfmsr r5 51eacf4c02SChristophe Leroy PPC_STL r5,_MSR(r1) 5251c9c084SAnju T li r5,0x700 53eacf4c02SChristophe Leroy PPC_STL r5,_TRAP(r1) 5451c9c084SAnju T li r5,0 55eacf4c02SChristophe Leroy PPC_STL r5,ORIG_GPR3(r1) 56eacf4c02SChristophe Leroy PPC_STL r5,RESULT(r1) 5751c9c084SAnju T mfctr r5 58eacf4c02SChristophe Leroy PPC_STL r5,_CTR(r1) 5951c9c084SAnju T mflr r5 60eacf4c02SChristophe Leroy PPC_STL r5,_LINK(r1) 6151c9c084SAnju T mfspr r5,SPRN_XER 62eacf4c02SChristophe Leroy PPC_STL r5,_XER(r1) 6351c9c084SAnju T mfcr r5 64eacf4c02SChristophe Leroy PPC_STL r5,_CCR(r1) 65eacf4c02SChristophe Leroy#ifdef CONFIG_PPC64 664e26bc4aSMadhavan Srinivasan lbz r5,PACAIRQSOFTMASK(r13) 6751c9c084SAnju T std r5,SOFTE(r1) 68eacf4c02SChristophe Leroy#endif 6951c9c084SAnju T 70f558b37bSNaveen N. Rao /* 71f558b37bSNaveen N. Rao * We may get here from a module, so load the kernel TOC in r2. 72f558b37bSNaveen N. Rao * The original TOC gets restored when pt_regs is restored 73f558b37bSNaveen N. Rao * further below. 74f558b37bSNaveen N. Rao */ 75eacf4c02SChristophe Leroy#ifdef CONFIG_PPC64 768e93fb33SNicholas Piggin LOAD_PACA_TOC() 77eacf4c02SChristophe Leroy#endif 78f558b37bSNaveen N. Rao 7951c9c084SAnju T .global optprobe_template_op_address 8051c9c084SAnju Toptprobe_template_op_address: 8151c9c084SAnju T /* 8251c9c084SAnju T * Parameters to optimized_callback(): 8351c9c084SAnju T * 1. optimized_kprobe structure in r3 8451c9c084SAnju T */ 85eacf4c02SChristophe Leroy TEMPLATE_FOR_IMM_LOAD_INSNS 86eacf4c02SChristophe Leroy 8751c9c084SAnju T /* 2. pt_regs pointer in r4 */ 88*c03be0a3SNicholas Piggin addi r4,r1,STACK_INT_FRAME_REGS 8951c9c084SAnju T 9051c9c084SAnju T .global optprobe_template_call_handler 9151c9c084SAnju Toptprobe_template_call_handler: 9251c9c084SAnju T /* Branch to optimized_callback() */ 9351c9c084SAnju T nop 9451c9c084SAnju T 9551c9c084SAnju T /* 9651c9c084SAnju T * Parameters for instruction emulation: 9751c9c084SAnju T * 1. Pass SP in register r3. 9851c9c084SAnju T */ 99*c03be0a3SNicholas Piggin addi r3,r1,STACK_INT_FRAME_REGS 10051c9c084SAnju T 10151c9c084SAnju T .global optprobe_template_insn 10251c9c084SAnju Toptprobe_template_insn: 10351c9c084SAnju T /* 2, Pass instruction to be emulated in r4 */ 104eacf4c02SChristophe Leroy TEMPLATE_FOR_IMM_LOAD_INSNS 10551c9c084SAnju T 10651c9c084SAnju T .global optprobe_template_call_emulate 10751c9c084SAnju Toptprobe_template_call_emulate: 10851c9c084SAnju T /* Branch to emulate_step() */ 10951c9c084SAnju T nop 11051c9c084SAnju T 11151c9c084SAnju T /* 11251c9c084SAnju T * All done. 11351c9c084SAnju T * Now, restore the registers... 11451c9c084SAnju T */ 115eacf4c02SChristophe Leroy PPC_LL r5,_MSR(r1) 11651c9c084SAnju T mtmsr r5 117eacf4c02SChristophe Leroy PPC_LL r5,_CTR(r1) 11851c9c084SAnju T mtctr r5 119eacf4c02SChristophe Leroy PPC_LL r5,_LINK(r1) 12051c9c084SAnju T mtlr r5 121eacf4c02SChristophe Leroy PPC_LL r5,_XER(r1) 12251c9c084SAnju T mtxer r5 123eacf4c02SChristophe Leroy PPC_LL r5,_CCR(r1) 12451c9c084SAnju T mtcr r5 12551c9c084SAnju T REST_GPR(0,r1) 126eacf4c02SChristophe Leroy REST_30GPRS(r1) 12751c9c084SAnju T /* Restore the previous SP */ 12851c9c084SAnju T addi r1,r1,INT_FRAME_SIZE 12951c9c084SAnju T 13051c9c084SAnju T .global optprobe_template_ret 13151c9c084SAnju Toptprobe_template_ret: 13251c9c084SAnju T /* ... and jump back from trampoline */ 13351c9c084SAnju T nop 13451c9c084SAnju T 13551c9c084SAnju T .global optprobe_template_end 13651c9c084SAnju Toptprobe_template_end: 137