// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2023 ARM Limited * * Verify that the TPIDR2 register context in signal frames is restored. */ #include <signal.h> #include <ucontext.h> #include <sys/auxv.h> #include <sys/prctl.h> #include <unistd.h> #include <asm/sigcontext.h> #include "test_signals_utils.h" #include "testcases.h" #define SYS_TPIDR2 "S3_3_C13_C0_5" static uint64_t get_tpidr2(void) { uint64_t val; asm volatile ( "mrs %0, " SYS_TPIDR2 "\n" : "=r"(val) : : "cc"); return val; } static void set_tpidr2(uint64_t val) { asm volatile ( "msr " SYS_TPIDR2 ", %0\n" : : "r"(val) : "cc"); } static uint64_t initial_tpidr2; static bool save_tpidr2(struct tdescr *td) { initial_tpidr2 = get_tpidr2(); fprintf(stderr, "Initial TPIDR2: %lx\n", initial_tpidr2); return true; } static int modify_tpidr2(struct tdescr *td, siginfo_t *si, ucontext_t *uc) { uint64_t my_tpidr2 = get_tpidr2(); my_tpidr2++; fprintf(stderr, "Setting TPIDR2 to %lx\n", my_tpidr2); set_tpidr2(my_tpidr2); return 0; } static void check_tpidr2(struct tdescr *td) { uint64_t tpidr2 = get_tpidr2(); td->pass = tpidr2 == initial_tpidr2; if (td->pass) fprintf(stderr, "TPIDR2 restored\n"); else fprintf(stderr, "TPIDR2 was %lx but is now %lx\n", initial_tpidr2, tpidr2); } struct tdescr tde = { .name = "TPIDR2 restore", .descr = "Validate that TPIDR2 is restored from the sigframe", .feats_required = FEAT_SME, .timeout = 3, .sig_trig = SIGUSR1, .init = save_tpidr2, .run = modify_tpidr2, .check_result = check_tpidr2, };