1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2023 Arm Limited 4 * 5 * Verify that the POR_EL0 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_POR_EL0 "S3_3_C10_C2_4" 25 26 static uint64_t get_por_el0(void) 27 { 28 uint64_t val; 29 30 asm volatile( 31 "mrs %0, " SYS_POR_EL0 "\n" 32 : "=r"(val) 33 : 34 : ); 35 36 return val; 37 } 38 39 int poe_present(struct tdescr *td, siginfo_t *si, ucontext_t *uc) 40 { 41 struct _aarch64_ctx *head = GET_BUF_RESV_HEAD(context); 42 struct poe_context *poe_ctx; 43 size_t offset; 44 bool in_sigframe; 45 bool have_poe; 46 __u64 orig_poe; 47 48 have_poe = getauxval(AT_HWCAP2) & HWCAP2_POE; 49 if (have_poe) 50 orig_poe = get_por_el0(); 51 52 if (!get_current_context(td, &context.uc, sizeof(context))) 53 return 1; 54 55 poe_ctx = (struct poe_context *) 56 get_header(head, POE_MAGIC, td->live_sz, &offset); 57 58 in_sigframe = poe_ctx != NULL; 59 60 fprintf(stderr, "POR_EL0 sigframe %s on system %s POE\n", 61 in_sigframe ? "present" : "absent", 62 have_poe ? "with" : "without"); 63 64 td->pass = (in_sigframe == have_poe); 65 66 /* 67 * Check that the value we read back was the one present at 68 * the time that the signal was triggered. 69 */ 70 if (have_poe && poe_ctx) { 71 if (poe_ctx->por_el0 != orig_poe) { 72 fprintf(stderr, "POR_EL0 in frame is %llx, was %llx\n", 73 poe_ctx->por_el0, orig_poe); 74 td->pass = false; 75 } 76 } 77 78 return 0; 79 } 80 81 struct tdescr tde = { 82 .name = "POR_EL0", 83 .descr = "Validate that POR_EL0 is present as expected", 84 .timeout = 3, 85 .run = poe_present, 86 }; 87