Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kselftest/arm64: Add basic FPMR test

Verify that a FPMR frame is generated on systems that support FPMR and not
generated otherwise.

Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20240306-arm64-2023-dpisa-v5-8-c568edc8ed7f@kernel.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Mark Brown and committed by
Catalin Marinas
7bcebadd f4dcccdd

+83
+1
tools/testing/selftests/arm64/signal/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 mangle_* 3 3 fake_sigreturn_* 4 + fpmr_* 4 5 sme_* 5 6 ssve_* 6 7 sve_*
+82
tools/testing/selftests/arm64/signal/testcases/fpmr_siginfo.c
··· 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 + };