Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/arm64/gcs/gcs-stress-thread.S
26292 views
1
// Program that loops for ever doing lots of recursions and system calls,
2
// intended to be used as part of a stress test for GCS context switching.
3
//
4
// Copyright 2015-2023 Arm Ltd
5
6
#include <asm/unistd.h>
7
8
#define sa_sz 32
9
#define sa_flags 8
10
#define sa_handler 0
11
#define sa_mask_sz 8
12
13
#define si_code 8
14
15
#define SIGINT 2
16
#define SIGABRT 6
17
#define SIGUSR1 10
18
#define SIGSEGV 11
19
#define SIGUSR2 12
20
#define SIGTERM 15
21
#define SEGV_CPERR 10
22
23
#define SA_NODEFER 1073741824
24
#define SA_SIGINFO 4
25
#define ucontext_regs 184
26
27
#define PR_SET_SHADOW_STACK_STATUS 75
28
# define PR_SHADOW_STACK_ENABLE (1UL << 0)
29
30
#define GCSPR_EL0 S3_3_C2_C5_1
31
32
.macro function name
33
.macro endfunction
34
.type \name, @function
35
.purgem endfunction
36
.endm
37
\name:
38
.endm
39
40
// Print a single character x0 to stdout
41
// Clobbers x0-x2,x8
42
function putc
43
str x0, [sp, #-16]!
44
45
mov x0, #1 // STDOUT_FILENO
46
mov x1, sp
47
mov x2, #1
48
mov x8, #__NR_write
49
svc #0
50
51
add sp, sp, #16
52
ret
53
endfunction
54
.globl putc
55
56
// Print a NUL-terminated string starting at address x0 to stdout
57
// Clobbers x0-x3,x8
58
function puts
59
mov x1, x0
60
61
mov x2, #0
62
0: ldrb w3, [x0], #1
63
cbz w3, 1f
64
add x2, x2, #1
65
b 0b
66
67
1: mov w0, #1 // STDOUT_FILENO
68
mov x8, #__NR_write
69
svc #0
70
71
ret
72
endfunction
73
.globl puts
74
75
// Utility macro to print a literal string
76
// Clobbers x0-x4,x8
77
.macro puts string
78
.pushsection .rodata.str1.1, "aMS", @progbits, 1
79
.L__puts_literal\@: .string "\string"
80
.popsection
81
82
ldr x0, =.L__puts_literal\@
83
bl puts
84
.endm
85
86
// Print an unsigned decimal number x0 to stdout
87
// Clobbers x0-x4,x8
88
function putdec
89
mov x1, sp
90
str x30, [sp, #-32]! // Result can't be > 20 digits
91
92
mov x2, #0
93
strb w2, [x1, #-1]! // Write the NUL terminator
94
95
mov x2, #10
96
0: udiv x3, x0, x2 // div-mod loop to generate the digits
97
msub x0, x3, x2, x0
98
add w0, w0, #'0'
99
strb w0, [x1, #-1]!
100
mov x0, x3
101
cbnz x3, 0b
102
103
ldrb w0, [x1]
104
cbnz w0, 1f
105
mov w0, #'0' // Print "0" for 0, not ""
106
strb w0, [x1, #-1]!
107
108
1: mov x0, x1
109
bl puts
110
111
ldr x30, [sp], #32
112
ret
113
endfunction
114
.globl putdec
115
116
// Print an unsigned decimal number x0 to stdout, followed by a newline
117
// Clobbers x0-x5,x8
118
function putdecn
119
mov x5, x30
120
121
bl putdec
122
mov x0, #'\n'
123
bl putc
124
125
ret x5
126
endfunction
127
.globl putdecn
128
129
// Fill x1 bytes starting at x0 with 0.
130
// Clobbers x1, x2.
131
function memclr
132
mov w2, #0
133
endfunction
134
.globl memclr
135
// fall through to memfill
136
137
// Trivial memory fill: fill x1 bytes starting at address x0 with byte w2
138
// Clobbers x1
139
function memfill
140
cmp x1, #0
141
b.eq 1f
142
143
0: strb w2, [x0], #1
144
subs x1, x1, #1
145
b.ne 0b
146
147
1: ret
148
endfunction
149
.globl memfill
150
151
// w0: signal number
152
// x1: sa_action
153
// w2: sa_flags
154
// Clobbers x0-x6,x8
155
function setsignal
156
str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!
157
158
mov w4, w0
159
mov x5, x1
160
mov w6, w2
161
162
add x0, sp, #16
163
mov x1, #sa_sz
164
bl memclr
165
166
mov w0, w4
167
add x1, sp, #16
168
str w6, [x1, #sa_flags]
169
str x5, [x1, #sa_handler]
170
mov x2, #0
171
mov x3, #sa_mask_sz
172
mov x8, #__NR_rt_sigaction
173
svc #0
174
175
cbz w0, 1f
176
177
puts "sigaction failure\n"
178
b abort
179
180
1: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
181
ret
182
endfunction
183
184
185
function tickle_handler
186
// Perhaps collect GCSPR_EL0 here in future?
187
ret
188
endfunction
189
190
function terminate_handler
191
mov w21, w0
192
mov x20, x2
193
194
puts "Terminated by signal "
195
mov w0, w21
196
bl putdec
197
puts ", no error\n"
198
199
mov x0, #0
200
mov x8, #__NR_exit
201
svc #0
202
endfunction
203
204
function segv_handler
205
// stash the siginfo_t *
206
mov x20, x1
207
208
// Disable GCS, we don't want additional faults logging things
209
mov x0, PR_SET_SHADOW_STACK_STATUS
210
mov x1, xzr
211
mov x2, xzr
212
mov x3, xzr
213
mov x4, xzr
214
mov x5, xzr
215
mov x8, #__NR_prctl
216
svc #0
217
218
puts "Got SIGSEGV code "
219
220
ldr x21, [x20, #si_code]
221
mov x0, x21
222
bl putdec
223
224
// GCS faults should have si_code SEGV_CPERR
225
cmp x21, #SEGV_CPERR
226
bne 1f
227
228
puts " (GCS violation)"
229
1:
230
mov x0, '\n'
231
bl putc
232
b abort
233
endfunction
234
235
// Recurse x20 times
236
.macro recurse id
237
function recurse\id
238
stp x29, x30, [sp, #-16]!
239
mov x29, sp
240
241
cmp x20, 0
242
beq 1f
243
sub x20, x20, 1
244
bl recurse\id
245
246
1:
247
ldp x29, x30, [sp], #16
248
249
// Do a syscall immediately prior to returning to try to provoke
250
// scheduling and migration at a point where coherency issues
251
// might trigger.
252
mov x8, #__NR_getpid
253
svc #0
254
255
ret
256
endfunction
257
.endm
258
259
// Generate and use two copies so we're changing the GCS contents
260
recurse 1
261
recurse 2
262
263
.globl _start
264
function _start
265
// Run with GCS
266
mov x0, PR_SET_SHADOW_STACK_STATUS
267
mov x1, PR_SHADOW_STACK_ENABLE
268
mov x2, xzr
269
mov x3, xzr
270
mov x4, xzr
271
mov x5, xzr
272
mov x8, #__NR_prctl
273
svc #0
274
cbz x0, 1f
275
puts "Failed to enable GCS\n"
276
b abort
277
1:
278
279
mov w0, #SIGTERM
280
adr x1, terminate_handler
281
mov w2, #SA_SIGINFO
282
bl setsignal
283
284
mov w0, #SIGUSR1
285
adr x1, tickle_handler
286
mov w2, #SA_SIGINFO
287
orr w2, w2, #SA_NODEFER
288
bl setsignal
289
290
mov w0, #SIGSEGV
291
adr x1, segv_handler
292
mov w2, #SA_SIGINFO
293
orr w2, w2, #SA_NODEFER
294
bl setsignal
295
296
puts "Running\n"
297
298
loop:
299
// Small recursion depth so we're frequently flipping between
300
// the two recursors and changing what's on the stack
301
mov x20, #5
302
bl recurse1
303
mov x20, #5
304
bl recurse2
305
b loop
306
endfunction
307
308
abort:
309
mov x0, #255
310
mov x8, #__NR_exit
311
svc #0
312
313