| 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 |
| 32 | optinsn_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 |
| 41 | optprobe_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 |
| 80 | optprobe_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 |
| 91 | optprobe_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 |
| 102 | optprobe_template_insn: |
| 103 | /* 2, Pass instruction to be emulated in r4 */ |
| 104 | TEMPLATE_FOR_IMM_LOAD_INSNS |
| 105 | |
| 106 | .global optprobe_template_call_emulate |
| 107 | optprobe_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 |
| 131 | optprobe_template_ret: |
| 132 | /* ... and jump back from trampoline */ |
| 133 | nop |
| 134 | |
| 135 | .global optprobe_template_end |
| 136 | optprobe_template_end: |
| 137 | |