1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2023 ARM Limited 4 * 5 * Verify that the FPMR register context in signal frames is set up as 6 * expected. 7 */ 8 9 #include <signal.h> 10 #include <ucontext.h> 11 #include <sys/auxv.h> 12 #include <sys/prctl.h> 13 #include <unistd.h> 14 #include <asm/sigcontext.h> 15 16 #include "test_signals_utils.h" 17 #include "testcases.h" 18 19 static union { 20 ucontext_t uc; 21 char buf[1024 * 128]; 22 } context; 23 24 #define SYS_FPMR "S3_3_C4_C4_2" 25 26 static uint64_t get_fpmr(void) 27 { 28 uint64_t val; 29 30 asm volatile ( 31 "mrs %0, " SYS_FPMR "\n" 32 : "=r"(val) 33 : 34 : "cc"); 35 36 return val; 37 } 38 39 int fpmr_present(struct tdescr *td, siginfo_t *si, ucontext_t *uc) 40 { 41 struct _aarch64_ctx *head = GET_BUF_RESV_HEAD(context); 42 struct fpmr_context *fpmr_ctx; 43 size_t offset; 44 bool in_sigframe; 45 bool have_fpmr; 46 __u64 orig_fpmr; 47 48 have_fpmr = getauxval(AT_HWCAP2) & HWCAP2_FPMR; 49 if (have_fpmr) 50 orig_fpmr = get_fpmr(); 51 52 if (!get_current_context(td, &context.uc, sizeof(context))) 53 return 1; 54 55 fpmr_ctx = (struct fpmr_context *) 56 get_header(head, FPMR_MAGIC, td->live_sz, &offset); 57 58 in_sigframe = fpmr_ctx != NULL; 59 60 fprintf(stderr, "FPMR sigframe %s on system %s FPMR\n", 61 in_sigframe ? "present" : "absent", 62 have_fpmr ? "with" : "without"); 63 64 td->pass = (in_sigframe == have_fpmr); 65 66 if (have_fpmr && fpmr_ctx) { 67 if (fpmr_ctx->fpmr != orig_fpmr) { 68 fprintf(stderr, "FPMR in frame is %llx, was %llx\n", 69 fpmr_ctx->fpmr, orig_fpmr); 70 td->pass = false; 71 } 72 } 73 74 return 0; 75 } 76 77 struct tdescr tde = { 78 .name = "FPMR", 79 .descr = "Validate that FPMR is present as expected", 80 .timeout = 3, 81 .run = fpmr_present, 82 }; 83