1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Non-emulated single-stepping support (currently limited to basic integer 4 * computations) used to validate the instruction emulation infrastructure. 5 * 6 * Copyright (C) 2019 IBM Corporation 7 */ 8 9 #include <asm/asm-offsets.h> 10 #include <asm/ppc_asm.h> 11 #include <asm/code-patching-asm.h> 12 #include <linux/errno.h> 13 14 /* int exec_instr(struct pt_regs *regs) */ 15 _GLOBAL(exec_instr) 16 17 /* 18 * Stack frame layout (INT_FRAME_SIZE bytes) 19 * In-memory pt_regs (SP + STACK_INT_FRAME_REGS) 20 * Scratch space (SP + 8) 21 * Back chain (SP + 0) 22 */ 23 24 /* 25 * Allocate a new stack frame with enough space to hold the register 26 * states in an in-memory pt_regs and also create the back chain to 27 * the caller's stack frame. 28 */ 29 stdu r1, -INT_FRAME_SIZE(r1) 30 31 /* 32 * Save non-volatile GPRs on stack. This includes TOC pointer (GPR2) 33 * and local variables (GPR14 to GPR31). The register for the pt_regs 34 * parameter (GPR3) is saved additionally to ensure that the resulting 35 * register state can still be saved even if GPR3 gets overwritten 36 * when loading the initial register state for the test instruction. 37 * The stack pointer (GPR1) and the thread pointer (GPR13) are not 38 * saved as these should not be modified anyway. 39 */ 40 SAVE_GPRS(2, 3, r1) 41 SAVE_NVGPRS(r1) 42 43 /* 44 * Save LR on stack to ensure that the return address is available 45 * even if it gets overwritten by the test instruction. 46 */ 47 mflr r0 48 std r0, _LINK(r1) 49 50 /* 51 * Save CR on stack. For simplicity, the entire register is saved 52 * even though only fields 2 to 4 are non-volatile. 53 */ 54 mfcr r0 55 std r0, _CCR(r1) 56 57 /* 58 * Load register state for the test instruction without touching the 59 * critical non-volatile registers. The register state is passed as a 60 * pointer to a pt_regs instance. 61 */ 62 subi r31, r3, GPR0 63 64 /* Load LR from pt_regs */ 65 ld r0, _LINK(r31) 66 mtlr r0 67 68 /* Load CR from pt_regs */ 69 ld r0, _CCR(r31) 70 mtcr r0 71 72 /* Load XER from pt_regs */ 73 ld r0, _XER(r31) 74 mtxer r0 75 76 /* Load GPRs from pt_regs */ 77 REST_GPR(0, r31) 78 REST_GPRS(2, 12, r31) 79 REST_NVGPRS(r31) 80 81 /* Placeholder for the test instruction */ 82 .balign 64 83 1: nop 84 nop 85 patch_site 1b patch__exec_instr 86 87 /* 88 * Since GPR3 is overwritten, temporarily restore it back to its 89 * original state, i.e. the pointer to pt_regs, to ensure that the 90 * resulting register state can be saved. Before doing this, a copy 91 * of it is created in the scratch space which is used later on to 92 * save it to pt_regs. 93 */ 94 std r3, 8(r1) 95 REST_GPR(3, r1) 96 97 /* Save resulting GPR state to pt_regs */ 98 subi r3, r3, GPR0 99 SAVE_GPR(0, r3) 100 SAVE_GPR(2, r3) 101 SAVE_GPRS(4, 12, r3) 102 SAVE_NVGPRS(r3) 103 104 /* Save resulting LR to pt_regs */ 105 mflr r0 106 std r0, _LINK(r3) 107 108 /* Save resulting CR to pt_regs */ 109 mfcr r0 110 std r0, _CCR(r3) 111 112 /* Save resulting XER to pt_regs */ 113 mfxer r0 114 std r0, _XER(r3) 115 116 /* Restore resulting GPR3 from scratch space and save it to pt_regs */ 117 ld r0, 8(r1) 118 std r0, GPR3(r3) 119 120 /* Set return value to denote execution success */ 121 li r3, 0 122 123 /* Continue */ 124 b 3f 125 126 /* Set return value to denote execution failure */ 127 2: li r3, -EFAULT 128 129 /* Restore the non-volatile GPRs from stack */ 130 3: REST_GPR(2, r1) 131 REST_NVGPRS(r1) 132 133 /* Restore LR from stack to be able to return */ 134 ld r0, _LINK(r1) 135 mtlr r0 136 137 /* Restore CR from stack */ 138 ld r0, _CCR(r1) 139 mtcr r0 140 141 /* Tear down stack frame */ 142 addi r1, r1, INT_FRAME_SIZE 143 144 /* Return */ 145 blr 146 147 /* Setup exception table */ 148 EX_TABLE(1b, 2b) 149 150 _ASM_NOKPROBE_SYMBOL(exec_instr)
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.