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)
|
static int do_child(void)
|
||||||
{
|
{
|
||||||
if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
|
if (ptrace(PTRACE_TRACEME, -1, NULL, NULL))
|
||||||
ksft_exit_fail_msg("PTRACE_TRACEME", strerror(errno));
|
ksft_exit_fail_perror("PTRACE_TRACEME");
|
||||||
|
|
||||||
if (raise(SIGSTOP))
|
if (raise(SIGSTOP))
|
||||||
ksft_exit_fail_msg("raise(SIGSTOP)", strerror(errno));
|
ksft_exit_fail_perror("raise(SIGSTOP)");
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ $(TEST_GEN_PROGS): $(PROGS)
|
||||||
# Common test-unit targets to build common-layout test-cases executables
|
# Common test-unit targets to build common-layout test-cases executables
|
||||||
# Needs secondary expansion to properly include the testcase c-file in pre-reqs
|
# 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 \
|
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
|
COMMON_HEADERS := test_signals.h test_signals_utils.h testcases/testcases.h
|
||||||
|
|
||||||
.SECONDEXPANSION:
|
.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.
|
* handler, this is not supported and is expected to segfault.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <kselftest.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include "test_signals_utils.h"
|
#include "test_signals_utils.h"
|
||||||
|
#include "sve_helpers.h"
|
||||||
#include "testcases.h"
|
#include "testcases.h"
|
||||||
|
|
||||||
struct fake_sigframe sf;
|
struct fake_sigframe sf;
|
||||||
static unsigned int vls[SVE_VQ_MAX];
|
|
||||||
unsigned int nvls = 0;
|
|
||||||
|
|
||||||
static bool sme_get_vls(struct tdescr *td)
|
static bool sme_get_vls(struct tdescr *td)
|
||||||
{
|
{
|
||||||
int vq, vl;
|
int res = sve_fill_vls(VLS_USE_SME, 2);
|
||||||
|
|
||||||
/*
|
if (!res)
|
||||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
return true;
|
||||||
*/
|
|
||||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
|
||||||
vl = prctl(PR_SVE_SET_VL, vq * 16);
|
|
||||||
if (vl == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
vl &= PR_SME_VL_LEN_MASK;
|
if (res == KSFT_SKIP)
|
||||||
|
td->result = KSFT_SKIP;
|
||||||
|
|
||||||
/* Skip missing VLs */
|
return false;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fake_sigreturn_ssve_change_vl(struct tdescr *td,
|
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;
|
size_t resv_sz, offset;
|
||||||
struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
|
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 */
|
/* Get a signal context with a SME ZA frame in it */
|
||||||
if (!get_current_context(td, &sf.uc, sizeof(sf.uc)))
|
if (!get_current_context(td, &sf.uc, sizeof(sf.uc)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
resv_sz = GET_SF_RESV_SIZE(sf);
|
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) {
|
if (!head) {
|
||||||
fprintf(stderr, "No SVE context\n");
|
fprintf(stderr, "No ZA context\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head->size != sizeof(struct sve_context)) {
|
if (head->size != sizeof(struct za_context)) {
|
||||||
fprintf(stderr, "Register data present, aborting\n");
|
fprintf(stderr, "Register data present, aborting\n");
|
||||||
return 1;
|
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 */
|
/* 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",
|
fprintf(stderr, "Attempting to change VL from %d to %d\n",
|
||||||
sve->vl, vls[0]);
|
za->vl, vls[0]);
|
||||||
sve->vl = vls[0];
|
za->vl = vls[0];
|
||||||
|
|
||||||
fake_sigreturn(&sf, sizeof(sf), 0);
|
fake_sigreturn(&sf, sizeof(sf), 0);
|
||||||
|
|
||||||
|
|
|
@ -12,40 +12,22 @@
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include "test_signals_utils.h"
|
#include "test_signals_utils.h"
|
||||||
|
#include "sve_helpers.h"
|
||||||
#include "testcases.h"
|
#include "testcases.h"
|
||||||
|
|
||||||
struct fake_sigframe sf;
|
struct fake_sigframe sf;
|
||||||
static unsigned int vls[SVE_VQ_MAX];
|
|
||||||
unsigned int nvls = 0;
|
|
||||||
|
|
||||||
static bool sve_get_vls(struct tdescr *td)
|
static bool sve_get_vls(struct tdescr *td)
|
||||||
{
|
{
|
||||||
int vq, vl;
|
int res = sve_fill_vls(VLS_USE_SVE, 2);
|
||||||
|
|
||||||
/*
|
if (!res)
|
||||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
return true;
|
||||||
*/
|
|
||||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
|
||||||
vl = prctl(PR_SVE_SET_VL, vq * 16);
|
|
||||||
if (vl == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
vl &= PR_SVE_VL_LEN_MASK;
|
if (res == 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);
|
|
||||||
td->result = KSFT_SKIP;
|
td->result = KSFT_SKIP;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fake_sigreturn_sve_change_vl(struct tdescr *td,
|
static int fake_sigreturn_sve_change_vl(struct tdescr *td,
|
||||||
|
|
|
@ -6,51 +6,31 @@
|
||||||
* set up as expected.
|
* set up as expected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <kselftest.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include "test_signals_utils.h"
|
#include "test_signals_utils.h"
|
||||||
|
#include "sve_helpers.h"
|
||||||
#include "testcases.h"
|
#include "testcases.h"
|
||||||
|
|
||||||
static union {
|
static union {
|
||||||
ucontext_t uc;
|
ucontext_t uc;
|
||||||
char buf[1024 * 64];
|
char buf[1024 * 64];
|
||||||
} context;
|
} context;
|
||||||
static unsigned int vls[SVE_VQ_MAX];
|
|
||||||
unsigned int nvls = 0;
|
|
||||||
|
|
||||||
static bool sme_get_vls(struct tdescr *td)
|
static bool sme_get_vls(struct tdescr *td)
|
||||||
{
|
{
|
||||||
int vq, vl;
|
int res = sve_fill_vls(VLS_USE_SME, 1);
|
||||||
|
|
||||||
/*
|
if (!res)
|
||||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
return true;
|
||||||
*/
|
|
||||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
|
||||||
vl = prctl(PR_SME_SET_VL, vq * 16);
|
|
||||||
if (vl == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
vl &= PR_SME_VL_LEN_MASK;
|
if (res == KSFT_SKIP)
|
||||||
|
td->result = KSFT_SKIP;
|
||||||
|
|
||||||
/* Did we find the lowest supported VL? */
|
return false;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_ssve_regs(void)
|
static void setup_ssve_regs(void)
|
||||||
|
|
|
@ -6,51 +6,31 @@
|
||||||
* signal frames is set up as expected when enabled simultaneously.
|
* signal frames is set up as expected when enabled simultaneously.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <kselftest.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include "test_signals_utils.h"
|
#include "test_signals_utils.h"
|
||||||
|
#include "sve_helpers.h"
|
||||||
#include "testcases.h"
|
#include "testcases.h"
|
||||||
|
|
||||||
static union {
|
static union {
|
||||||
ucontext_t uc;
|
ucontext_t uc;
|
||||||
char buf[1024 * 128];
|
char buf[1024 * 128];
|
||||||
} context;
|
} context;
|
||||||
static unsigned int vls[SVE_VQ_MAX];
|
|
||||||
unsigned int nvls = 0;
|
|
||||||
|
|
||||||
static bool sme_get_vls(struct tdescr *td)
|
static bool sme_get_vls(struct tdescr *td)
|
||||||
{
|
{
|
||||||
int vq, vl;
|
int res = sve_fill_vls(VLS_USE_SME, 1);
|
||||||
|
|
||||||
/*
|
if (!res)
|
||||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
return true;
|
||||||
*/
|
|
||||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
|
||||||
vl = prctl(PR_SME_SET_VL, vq * 16);
|
|
||||||
if (vl == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
vl &= PR_SME_VL_LEN_MASK;
|
if (res == KSFT_SKIP)
|
||||||
|
td->result = KSFT_SKIP;
|
||||||
|
|
||||||
/* Did we find the lowest supported VL? */
|
return false;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_regs(void)
|
static void setup_regs(void)
|
||||||
|
|
|
@ -6,47 +6,31 @@
|
||||||
* expected.
|
* expected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <kselftest.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include "test_signals_utils.h"
|
#include "test_signals_utils.h"
|
||||||
|
#include "sve_helpers.h"
|
||||||
#include "testcases.h"
|
#include "testcases.h"
|
||||||
|
|
||||||
static union {
|
static union {
|
||||||
ucontext_t uc;
|
ucontext_t uc;
|
||||||
char buf[1024 * 64];
|
char buf[1024 * 64];
|
||||||
} context;
|
} context;
|
||||||
static unsigned int vls[SVE_VQ_MAX];
|
|
||||||
unsigned int nvls = 0;
|
|
||||||
|
|
||||||
static bool sve_get_vls(struct tdescr *td)
|
static bool sve_get_vls(struct tdescr *td)
|
||||||
{
|
{
|
||||||
int vq, vl;
|
int res = sve_fill_vls(VLS_USE_SVE, 1);
|
||||||
|
|
||||||
/*
|
if (!res)
|
||||||
* Enumerate up to SVE_VQ_MAX vector lengths
|
return true;
|
||||||
*/
|
|
||||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
|
||||||
vl = prctl(PR_SVE_SET_VL, vq * 16);
|
|
||||||
if (vl == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
vl &= PR_SVE_VL_LEN_MASK;
|
if (res == KSFT_SKIP)
|
||||||
|
td->result = KSFT_SKIP;
|
||||||
|
|
||||||
/* Skip missing VLs */
|
return false;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_sve_regs(void)
|
static void setup_sve_regs(void)
|
||||||
|
|
|
@ -6,47 +6,31 @@
|
||||||
* expected.
|
* expected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <kselftest.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include "test_signals_utils.h"
|
#include "test_signals_utils.h"
|
||||||
|
#include "sve_helpers.h"
|
||||||
#include "testcases.h"
|
#include "testcases.h"
|
||||||
|
|
||||||
static union {
|
static union {
|
||||||
ucontext_t uc;
|
ucontext_t uc;
|
||||||
char buf[1024 * 128];
|
char buf[1024 * 128];
|
||||||
} context;
|
} context;
|
||||||
static unsigned int vls[SVE_VQ_MAX];
|
|
||||||
unsigned int nvls = 0;
|
|
||||||
|
|
||||||
static bool sme_get_vls(struct tdescr *td)
|
static bool sme_get_vls(struct tdescr *td)
|
||||||
{
|
{
|
||||||
int vq, vl;
|
int res = sve_fill_vls(VLS_USE_SME, 1);
|
||||||
|
|
||||||
/*
|
if (!res)
|
||||||
* Enumerate up to SME_VQ_MAX vector lengths
|
return true;
|
||||||
*/
|
|
||||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
|
||||||
vl = prctl(PR_SME_SET_VL, vq * 16);
|
|
||||||
if (vl == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
vl &= PR_SME_VL_LEN_MASK;
|
if (res == KSFT_SKIP)
|
||||||
|
td->result = KSFT_SKIP;
|
||||||
|
|
||||||
/* Skip missing VLs */
|
return false;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_one_sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc,
|
static int do_one_sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc,
|
||||||
|
|
|
@ -6,51 +6,31 @@
|
||||||
* expected.
|
* expected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <kselftest.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ucontext.h>
|
#include <ucontext.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include "test_signals_utils.h"
|
#include "test_signals_utils.h"
|
||||||
|
#include "sve_helpers.h"
|
||||||
#include "testcases.h"
|
#include "testcases.h"
|
||||||
|
|
||||||
static union {
|
static union {
|
||||||
ucontext_t uc;
|
ucontext_t uc;
|
||||||
char buf[1024 * 128];
|
char buf[1024 * 128];
|
||||||
} context;
|
} context;
|
||||||
static unsigned int vls[SVE_VQ_MAX];
|
|
||||||
unsigned int nvls = 0;
|
|
||||||
|
|
||||||
static bool sme_get_vls(struct tdescr *td)
|
static bool sme_get_vls(struct tdescr *td)
|
||||||
{
|
{
|
||||||
int vq, vl;
|
int res = sve_fill_vls(VLS_USE_SME, 1);
|
||||||
|
|
||||||
/*
|
if (!res)
|
||||||
* Enumerate up to SME_VQ_MAX vector lengths
|
return true;
|
||||||
*/
|
|
||||||
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
|
|
||||||
vl = prctl(PR_SME_SET_VL, vq * 16);
|
|
||||||
if (vl == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
vl &= PR_SME_VL_LEN_MASK;
|
if (res == KSFT_SKIP)
|
||||||
|
td->result = KSFT_SKIP;
|
||||||
|
|
||||||
/* Did we find the lowest supported VL? */
|
return false;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_za_regs(void)
|
static void setup_za_regs(void)
|
||||||
|
|
Loading…
Add table
Reference in a new issue