xref: /linux/tools/testing/selftests/arm64/gcs/gcsstr.S (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright 2024 Arm Limited
4//
5// Give ourselves GCS write permissions then use them
6
7#include <asm/unistd.h>
8
9/* Shadow Stack/Guarded Control Stack interface */
10#define PR_GET_SHADOW_STACK_STATUS	74
11#define PR_SET_SHADOW_STACK_STATUS      75
12#define PR_LOCK_SHADOW_STACK_STATUS     76
13
14# define PR_SHADOW_STACK_ENABLE         (1UL << 0)
15# define PR_SHADOW_STACK_WRITE		(1UL << 1)
16# define PR_SHADOW_STACK_PUSH		(1UL << 2)
17
18#define	GCSPR_EL0 S3_3_C2_C5_1
19
20#define KSFT_SKIP 4
21
22.macro function name
23	.macro endfunction
24		.type \name, @function
25		.purgem endfunction
26	.endm
27\name:
28.endm
29
30// Print a single character x0 to stdout
31// Clobbers x0-x2,x8
32function putc
33	str	x0, [sp, #-16]!
34
35	mov	x0, #1			// STDOUT_FILENO
36	mov	x1, sp
37	mov	x2, #1
38	mov	x8, #__NR_write
39	svc	#0
40
41	add	sp, sp, #16
42	ret
43endfunction
44.globl	putc
45
46// Print a NUL-terminated string starting at address x0 to stdout
47// Clobbers x0-x3,x8
48function puts
49	mov	x1, x0
50
51	mov	x2, #0
520:	ldrb	w3, [x0], #1
53	cbz	w3, 1f
54	add	x2, x2, #1
55	b	0b
56
571:	mov	w0, #1			// STDOUT_FILENO
58	mov	x8, #__NR_write
59	svc	#0
60
61	ret
62endfunction
63.globl	puts
64
65// Utility macro to print a literal string
66// Clobbers x0-x4,x8
67.macro puts string
68	.pushsection .rodata.str1.1, "aMS", @progbits, 1
69.L__puts_literal\@: .string "\string"
70	.popsection
71
72	ldr	x0, =.L__puts_literal\@
73	bl	puts
74.endm
75
76.globl _start
77function _start
78	// Run with GCS
79	mov	x0, PR_SET_SHADOW_STACK_STATUS
80	mov	x1, PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE
81	mov	x2, xzr
82	mov	x3, xzr
83	mov	x4, xzr
84	mov	x5, xzr
85	mov	x8, #__NR_prctl
86	svc	#0
87	cbz	x0, 1f
88	puts	"Failed to enable GCS with write permission\n"
89	mov	x0, #KSFT_SKIP
90	b	2f
911:
92	mrs	x0, GCSPR_EL0
93	sub	x0, x0, #8
94	.inst	0xd91f1c01	// GCSSTR x1, x0
95
96	mov	x0, #0
972:
98	mov	x8, #__NR_exit
99	svc	#0
100