Path: blob/master/tools/testing/selftests/arm64/gcs/gcs-stress-thread.S
26292 views
// Program that loops for ever doing lots of recursions and system calls,1// intended to be used as part of a stress test for GCS context switching.2//3// Copyright 2015-2023 Arm Ltd45#include <asm/unistd.h>67#define sa_sz 328#define sa_flags 89#define sa_handler 010#define sa_mask_sz 81112#define si_code 81314#define SIGINT 215#define SIGABRT 616#define SIGUSR1 1017#define SIGSEGV 1118#define SIGUSR2 1219#define SIGTERM 1520#define SEGV_CPERR 102122#define SA_NODEFER 107374182423#define SA_SIGINFO 424#define ucontext_regs 1842526#define PR_SET_SHADOW_STACK_STATUS 7527# define PR_SHADOW_STACK_ENABLE (1UL << 0)2829#define GCSPR_EL0 S3_3_C2_C5_13031.macro function name32.macro endfunction33.type \name, @function34.purgem endfunction35.endm36\name:37.endm3839// Print a single character x0 to stdout40// Clobbers x0-x2,x841function putc42str x0, [sp, #-16]!4344mov x0, #1 // STDOUT_FILENO45mov x1, sp46mov x2, #147mov x8, #__NR_write48svc #04950add sp, sp, #1651ret52endfunction53.globl putc5455// Print a NUL-terminated string starting at address x0 to stdout56// Clobbers x0-x3,x857function puts58mov x1, x05960mov x2, #0610: ldrb w3, [x0], #162cbz w3, 1f63add x2, x2, #164b 0b65661: mov w0, #1 // STDOUT_FILENO67mov x8, #__NR_write68svc #06970ret71endfunction72.globl puts7374// Utility macro to print a literal string75// Clobbers x0-x4,x876.macro puts string77.pushsection .rodata.str1.1, "aMS", @progbits, 178.L__puts_literal\@: .string "\string"79.popsection8081ldr x0, =.L__puts_literal\@82bl puts83.endm8485// Print an unsigned decimal number x0 to stdout86// Clobbers x0-x4,x887function putdec88mov x1, sp89str x30, [sp, #-32]! // Result can't be > 20 digits9091mov x2, #092strb w2, [x1, #-1]! // Write the NUL terminator9394mov x2, #10950: udiv x3, x0, x2 // div-mod loop to generate the digits96msub x0, x3, x2, x097add w0, w0, #'0'98strb w0, [x1, #-1]!99mov x0, x3100cbnz x3, 0b101102ldrb w0, [x1]103cbnz w0, 1f104mov w0, #'0' // Print "0" for 0, not ""105strb w0, [x1, #-1]!1061071: mov x0, x1108bl puts109110ldr x30, [sp], #32111ret112endfunction113.globl putdec114115// Print an unsigned decimal number x0 to stdout, followed by a newline116// Clobbers x0-x5,x8117function putdecn118mov x5, x30119120bl putdec121mov x0, #'\n'122bl putc123124ret x5125endfunction126.globl putdecn127128// Fill x1 bytes starting at x0 with 0.129// Clobbers x1, x2.130function memclr131mov w2, #0132endfunction133.globl memclr134// fall through to memfill135136// Trivial memory fill: fill x1 bytes starting at address x0 with byte w2137// Clobbers x1138function memfill139cmp x1, #0140b.eq 1f1411420: strb w2, [x0], #1143subs x1, x1, #1144b.ne 0b1451461: ret147endfunction148.globl memfill149150// w0: signal number151// x1: sa_action152// w2: sa_flags153// Clobbers x0-x6,x8154function setsignal155str x30, [sp, #-((sa_sz + 15) / 16 * 16 + 16)]!156157mov w4, w0158mov x5, x1159mov w6, w2160161add x0, sp, #16162mov x1, #sa_sz163bl memclr164165mov w0, w4166add x1, sp, #16167str w6, [x1, #sa_flags]168str x5, [x1, #sa_handler]169mov x2, #0170mov x3, #sa_mask_sz171mov x8, #__NR_rt_sigaction172svc #0173174cbz w0, 1f175176puts "sigaction failure\n"177b abort1781791: ldr x30, [sp], #((sa_sz + 15) / 16 * 16 + 16)180ret181endfunction182183184function tickle_handler185// Perhaps collect GCSPR_EL0 here in future?186ret187endfunction188189function terminate_handler190mov w21, w0191mov x20, x2192193puts "Terminated by signal "194mov w0, w21195bl putdec196puts ", no error\n"197198mov x0, #0199mov x8, #__NR_exit200svc #0201endfunction202203function segv_handler204// stash the siginfo_t *205mov x20, x1206207// Disable GCS, we don't want additional faults logging things208mov x0, PR_SET_SHADOW_STACK_STATUS209mov x1, xzr210mov x2, xzr211mov x3, xzr212mov x4, xzr213mov x5, xzr214mov x8, #__NR_prctl215svc #0216217puts "Got SIGSEGV code "218219ldr x21, [x20, #si_code]220mov x0, x21221bl putdec222223// GCS faults should have si_code SEGV_CPERR224cmp x21, #SEGV_CPERR225bne 1f226227puts " (GCS violation)"2281:229mov x0, '\n'230bl putc231b abort232endfunction233234// Recurse x20 times235.macro recurse id236function recurse\id237stp x29, x30, [sp, #-16]!238mov x29, sp239240cmp x20, 0241beq 1f242sub x20, x20, 1243bl recurse\id2442451:246ldp x29, x30, [sp], #16247248// Do a syscall immediately prior to returning to try to provoke249// scheduling and migration at a point where coherency issues250// might trigger.251mov x8, #__NR_getpid252svc #0253254ret255endfunction256.endm257258// Generate and use two copies so we're changing the GCS contents259recurse 1260recurse 2261262.globl _start263function _start264// Run with GCS265mov x0, PR_SET_SHADOW_STACK_STATUS266mov x1, PR_SHADOW_STACK_ENABLE267mov x2, xzr268mov x3, xzr269mov x4, xzr270mov x5, xzr271mov x8, #__NR_prctl272svc #0273cbz x0, 1f274puts "Failed to enable GCS\n"275b abort2761:277278mov w0, #SIGTERM279adr x1, terminate_handler280mov w2, #SA_SIGINFO281bl setsignal282283mov w0, #SIGUSR1284adr x1, tickle_handler285mov w2, #SA_SIGINFO286orr w2, w2, #SA_NODEFER287bl setsignal288289mov w0, #SIGSEGV290adr x1, segv_handler291mov w2, #SA_SIGINFO292orr w2, w2, #SA_NODEFER293bl setsignal294295puts "Running\n"296297loop:298// Small recursion depth so we're frequently flipping between299// the two recursors and changing what's on the stack300mov x20, #5301bl recurse1302mov x20, #5303bl recurse2304b loop305endfunction306307abort:308mov x0, #255309mov x8, #__NR_exit310svc #0311312313