Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/lib/test_emulate_step_exec_instr.S
26439 views
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)
151
152