mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
Merge branch 'for-next/selftests' into for-next/core
* for-next/selftests: kselftest/arm64: Fix build warnings for ptrace kselftest/arm64: Actually test SME vector length changes via sigreturn kselftest/arm64: signal: fix/refactor SVE vector length enumeration
This commit is contained in:
commit
2ef52ca02c
11 changed files with 141 additions and 190 deletions
|
@ -163,10 +163,10 @@ static void test_hw_debug(pid_t child, int type, const char *type_name)
|
|||
static int do_child(void)
|
||||
{
|
||||
if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
|
||||
ksft_exit_fail_msg("PTRACE_TRACEME", strerror(errno));
|
||||
ksft_exit_fail_perror("PTRACE_TRACEME");
|
||||
|
||||
if (raise(SIGSTOP))
|
||||
ksft_exit_fail_msg("raise(SIGSTOP)", strerror(errno));
|
||||
ksft_exit_fail_perror("raise(SIGSTOP)");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ $(TEST_GEN_PROGS): $(PROGS)
|
|||
# Common test-unit targets to build common-layout test-cases executables
|
||||
# Needs secondary expansion to properly include the testcase c-file in pre-reqs
|
||||
COMMON_SOURCES := test_signals.c test_signals_utils.c testcases/testcases.c \
|
||||
signals.S
|
||||
signals.S sve_helpers.c
|
||||
COMMON_HEADERS := test_signals.h test_signals_utils.h testcases/testcases.h
|
||||
|
||||
.SECONDEXPANSION:
|
||||
|
|
56
tools/testing/selftests/arm64/signal/sve_helpers.c
Normal file
56
tools/testing/selftests/arm64/signal/sve_helpers.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2024 ARM Limited
|
||||
*
|
||||
* Common helper functions for SVE and SME functionality.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <kselftest.h>
|
||||
#include <asm/sigcontext.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
unsigned int vls[SVE_VQ_MAX];
|
||||
unsigned int nvls;
|
||||
|
||||
int sve_fill_vls(bool use_sme, int min_vls)
|
||||
{
|
||||
int vq, vl;
|
||||
int pr_set_vl = use_sme ? PR_SME_SET_VL : PR_SVE_SET_VL;
|
||||
int len_mask = use_sme ? PR_SME_VL_LEN_MASK : PR_SVE_VL_LEN_MASK;
|
||||
|
||||
/*
|
||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
||||
*/
|
||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
||||
vl = prctl(pr_set_vl, vq * 16);
|
||||
if (vl == -1)
|
||||
return KSFT_FAIL;
|
||||
|
||||
vl &= len_mask;
|
||||
|
||||
/*
|
||||
* Unlike SVE, SME does not require the minimum vector length
|
||||
* to be implemented, or the VLs to be consecutive, so any call
|
||||
* to the prctl might return the single implemented VL, which
|
||||
* might be larger than 16. So to avoid this loop never
|
||||
* terminating, bail out here when we find a higher VL than
|
||||
* we asked for.
|
||||
* See the ARM ARM, DDI 0487K.a, B1.4.2: I_QQRNR and I_NWYBP.
|
||||
*/
|
||||
if (vq < sve_vq_from_vl(vl))
|
||||
break;
|
||||
|
||||
/* Skip missing VLs */
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
||||
vls[nvls++] = vl;
|
||||
}
|
||||
|
||||
if (nvls < min_vls) {
|
||||
fprintf(stderr, "Only %d VL supported\n", nvls);
|
||||
return KSFT_SKIP;
|
||||
}
|
||||
|
||||
return KSFT_PASS;
|
||||
}
|
21
tools/testing/selftests/arm64/signal/sve_helpers.h
Normal file
21
tools/testing/selftests/arm64/signal/sve_helpers.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2024 ARM Limited
|
||||
*
|
||||
* Common helper functions for SVE and SME functionality.
|
||||
*/
|
||||
|
||||
#ifndef __SVE_HELPERS_H__
|
||||
#define __SVE_HELPERS_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define VLS_USE_SVE false
|
||||
#define VLS_USE_SME true
|
||||
|
||||
extern unsigned int vls[];
|
||||
extern unsigned int nvls;
|
||||
|
||||
int sve_fill_vls(bool use_sme, int min_vls);
|
||||
|
||||
#endif
|
|
@ -6,44 +6,28 @@
|
|||
* handler, this is not supported and is expected to segfault.
|
||||
*/
|
||||
|
||||
#include <kselftest.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include "test_signals_utils.h"
|
||||
#include "sve_helpers.h"
|
||||
#include "testcases.h"
|
||||
|
||||
struct fake_sigframe sf;
|
||||
static unsigned int vls[SVE_VQ_MAX];
|
||||
unsigned int nvls = 0;
|
||||
|
||||
static bool sme_get_vls(struct tdescr *td)
|
||||
{
|
||||
int vq, vl;
|
||||
int res = sve_fill_vls(VLS_USE_SME, 2);
|
||||
|
||||
/*
|
||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
||||
*/
|
||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
||||
vl = prctl(PR_SVE_SET_VL, vq * 16);
|
||||
if (vl == -1)
|
||||
return false;
|
||||
if (!res)
|
||||
return true;
|
||||
|
||||
vl &= PR_SME_VL_LEN_MASK;
|
||||
if (res == KSFT_SKIP)
|
||||
td->result = KSFT_SKIP;
|
||||
|
||||
/* Skip missing VLs */
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
||||
vls[nvls++] = vl;
|
||||
}
|
||||
|
||||
/* We need at least two VLs */
|
||||
if (nvls < 2) {
|
||||
fprintf(stderr, "Only %d VL supported\n", nvls);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int fake_sigreturn_ssve_change_vl(struct tdescr *td,
|
||||
|
@ -51,30 +35,30 @@ static int fake_sigreturn_ssve_change_vl(struct tdescr *td,
|
|||
{
|
||||
size_t resv_sz, offset;
|
||||
struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
|
||||
struct sve_context *sve;
|
||||
struct za_context *za;
|
||||
|
||||
/* Get a signal context with a SME ZA frame in it */
|
||||
if (!get_current_context(td, &sf.uc, sizeof(sf.uc)))
|
||||
return 1;
|
||||
|
||||
resv_sz = GET_SF_RESV_SIZE(sf);
|
||||
head = get_header(head, SVE_MAGIC, resv_sz, &offset);
|
||||
head = get_header(head, ZA_MAGIC, resv_sz, &offset);
|
||||
if (!head) {
|
||||
fprintf(stderr, "No SVE context\n");
|
||||
fprintf(stderr, "No ZA context\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (head->size != sizeof(struct sve_context)) {
|
||||
if (head->size != sizeof(struct za_context)) {
|
||||
fprintf(stderr, "Register data present, aborting\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sve = (struct sve_context *)head;
|
||||
za = (struct za_context *)head;
|
||||
|
||||
/* No changes are supported; init left us at minimum VL so go to max */
|
||||
fprintf(stderr, "Attempting to change VL from %d to %d\n",
|
||||
sve->vl, vls[0]);
|
||||
sve->vl = vls[0];
|
||||
za->vl, vls[0]);
|
||||
za->vl = vls[0];
|
||||
|
||||
fake_sigreturn(&sf, sizeof(sf), 0);
|
||||
|
||||
|
|
|
@ -12,40 +12,22 @@
|
|||
#include <sys/prctl.h>
|
||||
|
||||
#include "test_signals_utils.h"
|
||||
#include "sve_helpers.h"
|
||||
#include "testcases.h"
|
||||
|
||||
struct fake_sigframe sf;
|
||||
static unsigned int vls[SVE_VQ_MAX];
|
||||
unsigned int nvls = 0;
|
||||
|
||||
static bool sve_get_vls(struct tdescr *td)
|
||||
{
|
||||
int vq, vl;
|
||||
int res = sve_fill_vls(VLS_USE_SVE, 2);
|
||||
|
||||
/*
|
||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
||||
*/
|
||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
||||
vl = prctl(PR_SVE_SET_VL, vq * 16);
|
||||
if (vl == -1)
|
||||
return false;
|
||||
if (!res)
|
||||
return true;
|
||||
|
||||
vl &= PR_SVE_VL_LEN_MASK;
|
||||
|
||||
/* Skip missing VLs */
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
||||
vls[nvls++] = vl;
|
||||
}
|
||||
|
||||
/* We need at least two VLs */
|
||||
if (nvls < 2) {
|
||||
fprintf(stderr, "Only %d VL supported\n", nvls);
|
||||
if (res == KSFT_SKIP)
|
||||
td->result = KSFT_SKIP;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int fake_sigreturn_sve_change_vl(struct tdescr *td,
|
||||
|
|
|
@ -6,51 +6,31 @@
|
|||
* set up as expected.
|
||||
*/
|
||||
|
||||
#include <kselftest.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include "test_signals_utils.h"
|
||||
#include "sve_helpers.h"
|
||||
#include "testcases.h"
|
||||
|
||||
static union {
|
||||
ucontext_t uc;
|
||||
char buf[1024 * 64];
|
||||
} context;
|
||||
static unsigned int vls[SVE_VQ_MAX];
|
||||
unsigned int nvls = 0;
|
||||
|
||||
static bool sme_get_vls(struct tdescr *td)
|
||||
{
|
||||
int vq, vl;
|
||||
int res = sve_fill_vls(VLS_USE_SME, 1);
|
||||
|
||||
/*
|
||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
||||
*/
|
||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
||||
vl = prctl(PR_SME_SET_VL, vq * 16);
|
||||
if (vl == -1)
|
||||
return false;
|
||||
if (!res)
|
||||
return true;
|
||||
|
||||
vl &= PR_SME_VL_LEN_MASK;
|
||||
if (res == KSFT_SKIP)
|
||||
td->result = KSFT_SKIP;
|
||||
|
||||
/* Did we find the lowest supported VL? */
|
||||
if (vq < sve_vq_from_vl(vl))
|
||||
break;
|
||||
|
||||
/* Skip missing VLs */
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
||||
vls[nvls++] = vl;
|
||||
}
|
||||
|
||||
/* We need at least one VL */
|
||||
if (nvls < 1) {
|
||||
fprintf(stderr, "Only %d VL supported\n", nvls);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void setup_ssve_regs(void)
|
||||
|
|
|
@ -6,51 +6,31 @@
|
|||
* signal frames is set up as expected when enabled simultaneously.
|
||||
*/
|
||||
|
||||
#include <kselftest.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include "test_signals_utils.h"
|
||||
#include "sve_helpers.h"
|
||||
#include "testcases.h"
|
||||
|
||||
static union {
|
||||
ucontext_t uc;
|
||||
char buf[1024 * 128];
|
||||
} context;
|
||||
static unsigned int vls[SVE_VQ_MAX];
|
||||
unsigned int nvls = 0;
|
||||
|
||||
static bool sme_get_vls(struct tdescr *td)
|
||||
{
|
||||
int vq, vl;
|
||||
int res = sve_fill_vls(VLS_USE_SME, 1);
|
||||
|
||||
/*
|
||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
||||
*/
|
||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
||||
vl = prctl(PR_SME_SET_VL, vq * 16);
|
||||
if (vl == -1)
|
||||
return false;
|
||||
if (!res)
|
||||
return true;
|
||||
|
||||
vl &= PR_SME_VL_LEN_MASK;
|
||||
if (res == KSFT_SKIP)
|
||||
td->result = KSFT_SKIP;
|
||||
|
||||
/* Did we find the lowest supported VL? */
|
||||
if (vq < sve_vq_from_vl(vl))
|
||||
break;
|
||||
|
||||
/* Skip missing VLs */
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
||||
vls[nvls++] = vl;
|
||||
}
|
||||
|
||||
/* We need at least one VL */
|
||||
if (nvls < 1) {
|
||||
fprintf(stderr, "Only %d VL supported\n", nvls);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void setup_regs(void)
|
||||
|
|
|
@ -6,47 +6,31 @@
|
|||
* expected.
|
||||
*/
|
||||
|
||||
#include <kselftest.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include "test_signals_utils.h"
|
||||
#include "sve_helpers.h"
|
||||
#include "testcases.h"
|
||||
|
||||
static union {
|
||||
ucontext_t uc;
|
||||
char buf[1024 * 64];
|
||||
} context;
|
||||
static unsigned int vls[SVE_VQ_MAX];
|
||||
unsigned int nvls = 0;
|
||||
|
||||
static bool sve_get_vls(struct tdescr *td)
|
||||
{
|
||||
int vq, vl;
|
||||
int res = sve_fill_vls(VLS_USE_SVE, 1);
|
||||
|
||||
/*
|
||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
||||
*/
|
||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
||||
vl = prctl(PR_SVE_SET_VL, vq * 16);
|
||||
if (vl == -1)
|
||||
return false;
|
||||
if (!res)
|
||||
return true;
|
||||
|
||||
vl &= PR_SVE_VL_LEN_MASK;
|
||||
if (res == KSFT_SKIP)
|
||||
td->result = KSFT_SKIP;
|
||||
|
||||
/* Skip missing VLs */
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
||||
vls[nvls++] = vl;
|
||||
}
|
||||
|
||||
/* We need at least one VL */
|
||||
if (nvls < 1) {
|
||||
fprintf(stderr, "Only %d VL supported\n", nvls);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void setup_sve_regs(void)
|
||||
|
|
|
@ -6,47 +6,31 @@
|
|||
* expected.
|
||||
*/
|
||||
|
||||
#include <kselftest.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include "test_signals_utils.h"
|
||||
#include "sve_helpers.h"
|
||||
#include "testcases.h"
|
||||
|
||||
static union {
|
||||
ucontext_t uc;
|
||||
char buf[1024 * 128];
|
||||
} context;
|
||||
static unsigned int vls[SVE_VQ_MAX];
|
||||
unsigned int nvls = 0;
|
||||
|
||||
static bool sme_get_vls(struct tdescr *td)
|
||||
{
|
||||
int vq, vl;
|
||||
int res = sve_fill_vls(VLS_USE_SME, 1);
|
||||
|
||||
/*
|
||||
* Enumerate up to SME_VQ_MAX vector lengths
|
||||
*/
|
||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
||||
vl = prctl(PR_SME_SET_VL, vq * 16);
|
||||
if (vl == -1)
|
||||
return false;
|
||||
if (!res)
|
||||
return true;
|
||||
|
||||
vl &= PR_SME_VL_LEN_MASK;
|
||||
if (res == KSFT_SKIP)
|
||||
td->result = KSFT_SKIP;
|
||||
|
||||
/* Skip missing VLs */
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
||||
vls[nvls++] = vl;
|
||||
}
|
||||
|
||||
/* We need at least one VL */
|
||||
if (nvls < 1) {
|
||||
fprintf(stderr, "Only %d VL supported\n", nvls);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int do_one_sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc,
|
||||
|
|
|
@ -6,51 +6,31 @@
|
|||
* expected.
|
||||
*/
|
||||
|
||||
#include <kselftest.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include "test_signals_utils.h"
|
||||
#include "sve_helpers.h"
|
||||
#include "testcases.h"
|
||||
|
||||
static union {
|
||||
ucontext_t uc;
|
||||
char buf[1024 * 128];
|
||||
} context;
|
||||
static unsigned int vls[SVE_VQ_MAX];
|
||||
unsigned int nvls = 0;
|
||||
|
||||
static bool sme_get_vls(struct tdescr *td)
|
||||
{
|
||||
int vq, vl;
|
||||
int res = sve_fill_vls(VLS_USE_SME, 1);
|
||||
|
||||
/*
|
||||
* Enumerate up to SME_VQ_MAX vector lengths
|
||||
*/
|
||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
||||
vl = prctl(PR_SME_SET_VL, vq * 16);
|
||||
if (vl == -1)
|
||||
return false;
|
||||
if (!res)
|
||||
return true;
|
||||
|
||||
vl &= PR_SME_VL_LEN_MASK;
|
||||
if (res == KSFT_SKIP)
|
||||
td->result = KSFT_SKIP;
|
||||
|
||||
/* Did we find the lowest supported VL? */
|
||||
if (vq < sve_vq_from_vl(vl))
|
||||
break;
|
||||
|
||||
/* Skip missing VLs */
|
||||
vq = sve_vq_from_vl(vl);
|
||||
|
||||
vls[nvls++] = vl;
|
||||
}
|
||||
|
||||
/* We need at least one VL */
|
||||
if (nvls < 1) {
|
||||
fprintf(stderr, "Only %d VL supported\n", nvls);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void setup_za_regs(void)
|
||||
|
|
Loading…
Add table
Reference in a new issue