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