Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / tools / testing / selftests / arm64 / gcs / gcs-stress-thread.S
blobb88b25217da50e9cf30c47e87dc49aea39f7086b
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
6 #include <asm/unistd.h>
8 #define sa_sz 32
9 #define sa_flags 8
10 #define sa_handler 0
11 #define sa_mask_sz 8
13 #define si_code 8
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
23 #define SA_NODEFER 1073741824
24 #define SA_SIGINFO 4
25 #define ucontext_regs 184
27 #define PR_SET_SHADOW_STACK_STATUS      75
28 # define PR_SHADOW_STACK_ENABLE         (1UL << 0)
30 #define GCSPR_EL0 S3_3_C2_C5_1
32 .macro function name
33         .macro endfunction
34                 .type \name, @function
35                 .purgem endfunction
36         .endm
37 \name:
38 .endm
40 // Print a single character x0 to stdout
41 // Clobbers x0-x2,x8
42 function putc
43         str     x0, [sp, #-16]!
45         mov     x0, #1                  // STDOUT_FILENO
46         mov     x1, sp
47         mov     x2, #1
48         mov     x8, #__NR_write
49         svc     #0
51         add     sp, sp, #16
52         ret
53 endfunction
54 .globl  putc
56 // Print a NUL-terminated string starting at address x0 to stdout
57 // Clobbers x0-x3,x8
58 function puts
59         mov     x1, x0
61         mov     x2, #0
62 0:      ldrb    w3, [x0], #1
63         cbz     w3, 1f
64         add     x2, x2, #1
65         b       0b
67 1:      mov     w0, #1                  // STDOUT_FILENO
68         mov     x8, #__NR_write
69         svc     #0
71         ret
72 endfunction
73 .globl  puts
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
82         ldr     x0, =.L__puts_literal\@
83         bl      puts
84 .endm
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
92         mov     x2, #0
93         strb    w2, [x1, #-1]!          // Write the NUL terminator
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
103         ldrb    w0, [x1]
104         cbnz    w0, 1f
105         mov     w0, #'0'                // Print "0" for 0, not ""
106         strb    w0, [x1, #-1]!
108 1:      mov     x0, x1
109         bl      puts
111         ldr     x30, [sp], #32
112         ret
113 endfunction
114 .globl  putdec
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
121         bl      putdec
122         mov     x0, #'\n'
123         bl      putc
125         ret     x5
126 endfunction
127 .globl  putdecn
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
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
143 0:      strb    w2, [x0], #1
144         subs    x1, x1, #1
145         b.ne    0b
147 1:      ret
148 endfunction
149 .globl  memfill
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)]!
158         mov     w4, w0
159         mov     x5, x1
160         mov     w6, w2
162         add     x0, sp, #16
163         mov     x1, #sa_sz
164         bl      memclr
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
175         cbz     w0, 1f
177         puts    "sigaction failure\n"
178         b       abort
180 1:      ldr     x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)
181         ret
182 endfunction
185 function tickle_handler
186         // Perhaps collect GCSPR_EL0 here in future?
187         ret
188 endfunction
190 function terminate_handler
191         mov     w21, w0
192         mov     x20, x2
194         puts    "Terminated by signal "
195         mov     w0, w21
196         bl      putdec
197         puts    ", no error\n"
199         mov     x0, #0
200         mov     x8, #__NR_exit
201         svc     #0
202 endfunction
204 function segv_handler
205         // stash the siginfo_t *
206         mov     x20, x1
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
218         puts    "Got SIGSEGV code "
220         ldr     x21, [x20, #si_code]
221         mov     x0, x21
222         bl      putdec
224         // GCS faults should have si_code SEGV_CPERR
225         cmp     x21, #SEGV_CPERR
226         bne     1f
228         puts    " (GCS violation)"
230         mov     x0, '\n'
231         bl      putc
232         b       abort
233 endfunction
235 // Recurse x20 times
236 .macro recurse id
237 function recurse\id
238         stp     x29, x30, [sp, #-16]!
239         mov     x29, sp
241         cmp     x20, 0
242         beq     1f
243         sub     x20, x20, 1
244         bl      recurse\id
247         ldp     x29, x30, [sp], #16
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
255         ret
256 endfunction
257 .endm
259 // Generate and use two copies so we're changing the GCS contents
260 recurse 1
261 recurse 2
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
279         mov     w0, #SIGTERM
280         adr     x1, terminate_handler
281         mov     w2, #SA_SIGINFO
282         bl      setsignal
284         mov     w0, #SIGUSR1
285         adr     x1, tickle_handler
286         mov     w2, #SA_SIGINFO
287         orr     w2, w2, #SA_NODEFER
288         bl      setsignal
290         mov     w0, #SIGSEGV
291         adr     x1, segv_handler
292         mov     w2, #SA_SIGINFO
293         orr     w2, w2, #SA_NODEFER
294         bl      setsignal
296         puts    "Running\n"
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
308 abort:
309         mov     x0, #255
310         mov     x8, #__NR_exit
311         svc     #0