1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2023 ARM Limited 4 * 5 * Verify that the TPIDR2 register context in signal frames is restored. 6 */ 7 8 #include <signal.h> 9 #include <ucontext.h> 10 #include <sys/auxv.h> 11 #include <sys/prctl.h> 12 #include <unistd.h> 13 #include <asm/sigcontext.h> 14 15 #include "test_signals_utils.h" 16 #include "testcases.h" 17 18 #define SYS_TPIDR2 "S3_3_C13_C0_5" 19 20 static uint64_t get_tpidr2(void) 21 { 22 uint64_t val; 23 24 asm volatile ( 25 "mrs %0, " SYS_TPIDR2 "\n" 26 : "=r"(val) 27 : 28 : "cc"); 29 30 return val; 31 } 32 33 static void set_tpidr2(uint64_t val) 34 { 35 asm volatile ( 36 "msr " SYS_TPIDR2 ", %0\n" 37 : 38 : "r"(val) 39 : "cc"); 40 } 41 42 43 static uint64_t initial_tpidr2; 44 45 static bool save_tpidr2(struct tdescr *td) 46 { 47 initial_tpidr2 = get_tpidr2(); 48 fprintf(stderr, "Initial TPIDR2: %lx\n", initial_tpidr2); 49 50 return true; 51 } 52 53 static int modify_tpidr2(struct tdescr *td, siginfo_t *si, ucontext_t *uc) 54 { 55 uint64_t my_tpidr2 = get_tpidr2(); 56 57 my_tpidr2++; 58 fprintf(stderr, "Setting TPIDR2 to %lx\n", my_tpidr2); 59 set_tpidr2(my_tpidr2); 60 61 return 0; 62 } 63 64 static void check_tpidr2(struct tdescr *td) 65 { 66 uint64_t tpidr2 = get_tpidr2(); 67 68 td->pass = tpidr2 == initial_tpidr2; 69 70 if (td->pass) 71 fprintf(stderr, "TPIDR2 restored\n"); 72 else 73 fprintf(stderr, "TPIDR2 was %lx but is now %lx\n", 74 initial_tpidr2, tpidr2); 75 } 76 77 struct tdescr tde = { 78 .name = "TPIDR2 restore", 79 .descr = "Validate that TPIDR2 is restored from the sigframe", 80 .feats_required = FEAT_SME, 81 .timeout = 3, 82 .sig_trig = SIGUSR1, 83 .init = save_tpidr2, 84 .run = modify_tpidr2, 85 .check_result = check_tpidr2, 86 }; 87