Merge branch 'for-next/selftests' into for-next/core

* for-next/selftests:
  kselftest/arm64: Set default OUTPUT path when undefined
  kselftest/arm64: fp-ptrace: Adjust to new inactive mode behaviour
  kselftest/arm64: fp-ptrace: Adjust to new VL change behaviour
  kselftest/arm64: tpidr2: Adjust to new clone() behaviour
  kselftest/arm64: fp-ptrace: Fix expected FPMR value when PSTATE.SM is changed
This commit is contained in:
Will Deacon
2025-05-27 12:26:30 +01:00
3 changed files with 40 additions and 38 deletions

View File

@@ -21,6 +21,8 @@ CFLAGS += $(KHDR_INCLUDES)
CFLAGS += -I$(top_srcdir)/tools/include
OUTPUT ?= $(CURDIR)
export CFLAGS
export top_srcdir

View File

@@ -169,8 +169,10 @@ static int sys_clone(unsigned long clone_flags, unsigned long newsp,
child_tidptr);
}
#define __STACK_SIZE (8 * 1024 * 1024)
/*
* If we clone with CLONE_SETTLS then the value in the parent should
* If we clone with CLONE_VM then the value in the parent should
* be unchanged and the child should start with zero and be able to
* set its own value.
*/
@@ -179,11 +181,19 @@ static int write_clone_read(void)
int parent_tid, child_tid;
pid_t parent, waiting;
int ret, status;
void *stack;
parent = getpid();
set_tpidr2(parent);
ret = sys_clone(CLONE_SETTLS, 0, &parent_tid, 0, &child_tid);
stack = malloc(__STACK_SIZE);
if (!stack) {
putstr("# malloc() failed\n");
return 0;
}
ret = sys_clone(CLONE_VM, (unsigned long)stack + __STACK_SIZE,
&parent_tid, 0, &child_tid);
if (ret == -1) {
putstr("# clone() failed\n");
putnum(errno);

View File

@@ -439,10 +439,17 @@ static bool check_ptrace_values_sve(pid_t child, struct test_config *config)
pass = false;
}
if (sve->size != SVE_PT_SIZE(vq, sve->flags)) {
ksft_print_msg("Mismatch in SVE header size: %d != %lu\n",
sve->size, SVE_PT_SIZE(vq, sve->flags));
pass = false;
if (svcr_in & SVCR_SM) {
if (sve->size != sizeof(sve)) {
ksft_print_msg("NT_ARM_SVE reports data with PSTATE.SM\n");
pass = false;
}
} else {
if (sve->size != SVE_PT_SIZE(vq, sve->flags)) {
ksft_print_msg("Mismatch in SVE header size: %d != %lu\n",
sve->size, SVE_PT_SIZE(vq, sve->flags));
pass = false;
}
}
/* The registers might be in completely different formats! */
@@ -515,10 +522,17 @@ static bool check_ptrace_values_ssve(pid_t child, struct test_config *config)
pass = false;
}
if (sve->size != SVE_PT_SIZE(vq, sve->flags)) {
ksft_print_msg("Mismatch in SSVE header size: %d != %lu\n",
sve->size, SVE_PT_SIZE(vq, sve->flags));
pass = false;
if (!(svcr_in & SVCR_SM)) {
if (sve->size != sizeof(sve)) {
ksft_print_msg("NT_ARM_SSVE reports data without PSTATE.SM\n");
pass = false;
}
} else {
if (sve->size != SVE_PT_SIZE(vq, sve->flags)) {
ksft_print_msg("Mismatch in SSVE header size: %d != %lu\n",
sve->size, SVE_PT_SIZE(vq, sve->flags));
pass = false;
}
}
/* The registers might be in completely different formats! */
@@ -891,18 +905,11 @@ static void set_initial_values(struct test_config *config)
{
int vq = __sve_vq_from_vl(vl_in(config));
int sme_vq = __sve_vq_from_vl(config->sme_vl_in);
bool sm_change;
svcr_in = config->svcr_in;
svcr_expected = config->svcr_expected;
svcr_out = 0;
if (sme_supported() &&
(svcr_in & SVCR_SM) != (svcr_expected & SVCR_SM))
sm_change = true;
else
sm_change = false;
fill_random(&v_in, sizeof(v_in));
memcpy(v_expected, v_in, sizeof(v_in));
memset(v_out, 0, sizeof(v_out));
@@ -953,12 +960,7 @@ static void set_initial_values(struct test_config *config)
if (fpmr_supported()) {
fill_random(&fpmr_in, sizeof(fpmr_in));
fpmr_in &= FPMR_SAFE_BITS;
/* Entering or exiting streaming mode clears FPMR */
if (sm_change)
fpmr_expected = 0;
else
fpmr_expected = fpmr_in;
fpmr_expected = fpmr_in;
} else {
fpmr_in = 0;
fpmr_expected = 0;
@@ -1195,18 +1197,8 @@ static void sve_write(pid_t child, struct test_config *config)
static bool za_write_supported(struct test_config *config)
{
if (config->sme_vl_in != config->sme_vl_expected) {
/* Changing the SME VL exits streaming mode. */
if (config->svcr_expected & SVCR_SM) {
return false;
}
} else {
/* Otherwise we can't change streaming mode */
if ((config->svcr_in & SVCR_SM) !=
(config->svcr_expected & SVCR_SM)) {
return false;
}
}
if ((config->svcr_in & SVCR_SM) != (config->svcr_expected & SVCR_SM))
return false;
return true;
}
@@ -1224,10 +1216,8 @@ static void za_write_expected(struct test_config *config)
memset(zt_expected, 0, sizeof(zt_expected));
}
/* Changing the SME VL flushes ZT, SVE state and exits SM */
/* Changing the SME VL flushes ZT, SVE state */
if (config->sme_vl_in != config->sme_vl_expected) {
svcr_expected &= ~SVCR_SM;
sve_vq = __sve_vq_from_vl(vl_expected(config));
memset(z_expected, 0, __SVE_ZREGS_SIZE(sve_vq));
memset(p_expected, 0, __SVE_PREGS_SIZE(sve_vq));