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

* for-next/selftests:
  kselftest/arm64: Allow epoll_wait() to return more than one result
  kselftest/arm64: Don't drain output while spawning children
  kselftest/arm64: Hold fp-stress children until they're all spawned
  kselftest/arm64: Set test names prior to starting children
  kselftest/arm64: Use preferred form for predicate load/stores
  kselftest/arm64: fix array_size.cocci warning
  kselftest/arm64: fix array_size.cocci warning
  kselftest/arm64: Print ASCII version of unknown signal frame magic values
  kselftest/arm64: Remove validation of extra_context from TODO
  kselftest/arm64: Provide progress messages when signalling children
  kselftest/arm64: Check that all children are producing output in fp-stress
This commit is contained in:
Will Deacon 2022-12-06 11:25:43 +00:00
commit 32b4824842
6 changed files with 122 additions and 45 deletions

View File

@ -153,7 +153,7 @@ do_syscall:
// Only set a non-zero FFR, test patterns must be zero since the
// syscall should clear it - this lets us handle FA64.
ldr x2, =ffr_in
ldr p0, [x2, #0]
ldr p0, [x2]
ldr x2, [x2, #0]
cbz x2, 2f
wrffr p0.b
@ -298,7 +298,7 @@ do_syscall:
cbz x2, 1f
ldr x2, =ffr_out
rdffr p0.b
str p0, [x2, #0]
str p0, [x2]
1:
// Restore callee saved registers x19-x30

View File

@ -39,10 +39,12 @@ struct child_data {
static int epoll_fd;
static struct child_data *children;
static struct epoll_event *evs;
static int tests;
static int num_children;
static bool terminate;
static void drain_output(bool flush);
static int startup_pipe[2];
static int num_processors(void)
{
@ -81,13 +83,37 @@ static void child_start(struct child_data *child, const char *program)
exit(EXIT_FAILURE);
}
/*
* Duplicate the read side of the startup pipe to
* FD 3 so we can close everything else.
*/
ret = dup2(startup_pipe[0], 3);
if (ret == -1) {
fprintf(stderr, "dup2() %d\n", errno);
exit(EXIT_FAILURE);
}
/*
* Very dumb mechanism to clean open FDs other than
* stdio. We don't want O_CLOEXEC for the pipes...
*/
for (i = 3; i < 8192; i++)
for (i = 4; i < 8192; i++)
close(i);
/*
* Read from the startup pipe, there should be no data
* and we should block until it is closed. We just
* carry on on error since this isn't super critical.
*/
ret = read(3, &i, sizeof(i));
if (ret < 0)
fprintf(stderr, "read(startp pipe) failed: %s (%d)\n",
strerror(errno), errno);
if (ret > 0)
fprintf(stderr, "%d bytes of data on startup pipe\n",
ret);
close(3);
ret = execl(program, program, NULL);
fprintf(stderr, "execl(%s) failed: %d (%s)\n",
program, errno, strerror(errno));
@ -112,12 +138,6 @@ static void child_start(struct child_data *child, const char *program)
ksft_exit_fail_msg("%s EPOLL_CTL_ADD failed: %s (%d)\n",
child->name, strerror(errno), errno);
}
/*
* Keep output flowing during child startup so logs
* are more timely, can help debugging.
*/
drain_output(false);
}
}
@ -290,12 +310,12 @@ static void start_fpsimd(struct child_data *child, int cpu, int copy)
{
int ret;
child_start(child, "./fpsimd-test");
ret = asprintf(&child->name, "FPSIMD-%d-%d", cpu, copy);
if (ret == -1)
ksft_exit_fail_msg("asprintf() failed\n");
child_start(child, "./fpsimd-test");
ksft_print_msg("Started %s\n", child->name);
}
@ -307,12 +327,12 @@ static void start_sve(struct child_data *child, int vl, int cpu)
if (ret < 0)
ksft_exit_fail_msg("Failed to set SVE VL %d\n", vl);
child_start(child, "./sve-test");
ret = asprintf(&child->name, "SVE-VL-%d-%d", vl, cpu);
if (ret == -1)
ksft_exit_fail_msg("asprintf() failed\n");
child_start(child, "./sve-test");
ksft_print_msg("Started %s\n", child->name);
}
@ -320,16 +340,16 @@ static void start_ssve(struct child_data *child, int vl, int cpu)
{
int ret;
ret = asprintf(&child->name, "SSVE-VL-%d-%d", vl, cpu);
if (ret == -1)
ksft_exit_fail_msg("asprintf() failed\n");
ret = prctl(PR_SME_SET_VL, vl | PR_SME_VL_INHERIT);
if (ret < 0)
ksft_exit_fail_msg("Failed to set SME VL %d\n", ret);
child_start(child, "./ssve-test");
ret = asprintf(&child->name, "SSVE-VL-%d-%d", vl, cpu);
if (ret == -1)
ksft_exit_fail_msg("asprintf() failed\n");
ksft_print_msg("Started %s\n", child->name);
}
@ -341,12 +361,12 @@ static void start_za(struct child_data *child, int vl, int cpu)
if (ret < 0)
ksft_exit_fail_msg("Failed to set SME VL %d\n", ret);
child_start(child, "./za-test");
ret = asprintf(&child->name, "ZA-VL-%d-%d", vl, cpu);
if (ret == -1)
ksft_exit_fail_msg("asprintf() failed\n");
child_start(child, "./za-test");
ksft_print_msg("Started %s\n", child->name);
}
@ -375,11 +395,11 @@ static void probe_vls(int vls[], int *vl_count, int set_vl)
/* Handle any pending output without blocking */
static void drain_output(bool flush)
{
struct epoll_event ev;
int ret = 1;
int i;
while (ret > 0) {
ret = epoll_wait(epoll_fd, &ev, 1, 0);
ret = epoll_wait(epoll_fd, evs, tests, 0);
if (ret < 0) {
if (errno == EINTR)
continue;
@ -387,8 +407,8 @@ static void drain_output(bool flush)
strerror(errno), errno);
}
if (ret == 1)
child_output(ev.data.ptr, ev.events, flush);
for (i = 0; i < ret; i++)
child_output(evs[i].data.ptr, evs[i].events, flush);
}
}
@ -401,10 +421,11 @@ int main(int argc, char **argv)
{
int ret;
int timeout = 10;
int cpus, tests, i, j, c;
int cpus, i, j, c;
int sve_vl_count, sme_vl_count, fpsimd_per_cpu;
bool all_children_started = false;
int seen_children;
int sve_vls[MAX_VLS], sme_vls[MAX_VLS];
struct epoll_event ev;
struct sigaction sa;
while ((c = getopt_long(argc, argv, "t:", options, NULL)) != -1) {
@ -465,6 +486,12 @@ int main(int argc, char **argv)
strerror(errno), ret);
epoll_fd = ret;
/* Create a pipe which children will block on before execing */
ret = pipe(startup_pipe);
if (ret != 0)
ksft_exit_fail_msg("Failed to create startup pipe: %s (%d)\n",
strerror(errno), errno);
/* Get signal handers ready before we start any children */
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = handle_exit_signal;
@ -484,6 +511,11 @@ int main(int argc, char **argv)
ksft_print_msg("Failed to install SIGCHLD handler: %s (%d)\n",
strerror(errno), errno);
evs = calloc(tests, sizeof(*evs));
if (!evs)
ksft_exit_fail_msg("Failed to allocated %d epoll events\n",
tests);
for (i = 0; i < cpus; i++) {
for (j = 0; j < fpsimd_per_cpu; j++)
start_fpsimd(&children[num_children++], i, j);
@ -497,6 +529,13 @@ int main(int argc, char **argv)
}
}
/*
* All children started, close the startup pipe and let them
* run.
*/
close(startup_pipe[0]);
close(startup_pipe[1]);
for (;;) {
/* Did we get a signal asking us to exit? */
if (terminate)
@ -510,7 +549,7 @@ int main(int argc, char **argv)
* useful in emulation where we will both be slow and
* likely to have a large set of VLs.
*/
ret = epoll_wait(epoll_fd, &ev, 1, 1000);
ret = epoll_wait(epoll_fd, evs, tests, 1000);
if (ret < 0) {
if (errno == EINTR)
continue;
@ -519,13 +558,40 @@ int main(int argc, char **argv)
}
/* Output? */
if (ret == 1) {
child_output(ev.data.ptr, ev.events, false);
if (ret > 0) {
for (i = 0; i < ret; i++) {
child_output(evs[i].data.ptr, evs[i].events,
false);
}
continue;
}
/* Otherwise epoll_wait() timed out */
/*
* If the child processes have not produced output they
* aren't actually running the tests yet .
*/
if (!all_children_started) {
seen_children = 0;
for (i = 0; i < num_children; i++)
if (children[i].output_seen ||
children[i].exited)
seen_children++;
if (seen_children != num_children) {
ksft_print_msg("Waiting for %d children\n",
num_children - seen_children);
continue;
}
all_children_started = true;
}
ksft_print_msg("Sending signals, timeout remaining: %d\n",
timeout);
for (i = 0; i < num_children; i++)
child_tickle(&children[i]);

View File

@ -32,7 +32,7 @@ static int check_buffer_by_byte(int mem_type, int mode)
bool err;
mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
item = sizeof(sizes)/sizeof(int);
item = ARRAY_SIZE(sizes);
for (i = 0; i < item; i++) {
ptr = (char *)mte_allocate_memory(sizes[i], mem_type, 0, true);
@ -69,7 +69,7 @@ static int check_buffer_underflow_by_byte(int mem_type, int mode,
char *und_ptr = NULL;
mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
item = sizeof(sizes)/sizeof(int);
item = ARRAY_SIZE(sizes);
for (i = 0; i < item; i++) {
ptr = (char *)mte_allocate_memory_tag_range(sizes[i], mem_type, 0,
underflow_range, 0);
@ -165,7 +165,7 @@ static int check_buffer_overflow_by_byte(int mem_type, int mode,
char *over_ptr = NULL;
mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
item = sizeof(sizes)/sizeof(int);
item = ARRAY_SIZE(sizes);
for (i = 0; i < item; i++) {
ptr = (char *)mte_allocate_memory_tag_range(sizes[i], mem_type, 0,
0, overflow_range);
@ -338,7 +338,7 @@ static int check_buffer_by_block(int mem_type, int mode)
int i, item, result = KSFT_PASS;
mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
item = sizeof(sizes)/sizeof(int);
item = ARRAY_SIZE(sizes);
cur_mte_cxt.fault_valid = false;
for (i = 0; i < item; i++) {
result = check_buffer_by_block_iterate(mem_type, mode, sizes[i]);
@ -366,7 +366,7 @@ static int check_memory_initial_tags(int mem_type, int mode, int mapping)
{
char *ptr;
int run, fd;
int total = sizeof(sizes)/sizeof(int);
int total = ARRAY_SIZE(sizes);
mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
for (run = 0; run < total; run++) {
@ -404,7 +404,7 @@ int main(int argc, char *argv[])
{
int err;
size_t page_size = getpagesize();
int item = sizeof(sizes)/sizeof(int);
int item = ARRAY_SIZE(sizes);
sizes[item - 3] = page_size - 1;
sizes[item - 2] = page_size;

View File

@ -61,9 +61,8 @@ static int check_anonymous_memory_mapping(int mem_type, int mode, int mapping, i
{
char *ptr, *map_ptr;
int run, result, map_size;
int item = sizeof(sizes)/sizeof(int);
int item = ARRAY_SIZE(sizes);
item = sizeof(sizes)/sizeof(int);
mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
for (run = 0; run < item; run++) {
map_size = sizes[run] + OVERFLOW + UNDERFLOW;
@ -93,7 +92,7 @@ static int check_file_memory_mapping(int mem_type, int mode, int mapping, int ta
{
char *ptr, *map_ptr;
int run, fd, map_size;
int total = sizeof(sizes)/sizeof(int);
int total = ARRAY_SIZE(sizes);
int result = KSFT_PASS;
mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
@ -132,7 +131,7 @@ static int check_clear_prot_mte_flag(int mem_type, int mode, int mapping)
{
char *ptr, *map_ptr;
int run, prot_flag, result, fd, map_size;
int total = sizeof(sizes)/sizeof(int);
int total = ARRAY_SIZE(sizes);
prot_flag = PROT_READ | PROT_WRITE;
mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
@ -187,7 +186,7 @@ static int check_clear_prot_mte_flag(int mem_type, int mode, int mapping)
int main(int argc, char *argv[])
{
int err;
int item = sizeof(sizes)/sizeof(int);
int item = ARRAY_SIZE(sizes);
err = mte_default_setup();
if (err)

View File

@ -1,2 +1 @@
- Validate that register contents are saved and restored as expected.
- Support and validate extra_context.

View File

@ -1,5 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019 ARM Limited */
#include <ctype.h>
#include <string.h>
#include "testcases.h"
struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
@ -109,7 +113,7 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
bool terminated = false;
size_t offs = 0;
int flags = 0;
int new_flags;
int new_flags, i;
struct extra_context *extra = NULL;
struct sve_context *sve = NULL;
struct za_context *za = NULL;
@ -117,6 +121,7 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
(struct _aarch64_ctx *)uc->uc_mcontext.__reserved;
void *extra_data = NULL;
size_t extra_sz = 0;
char magic[4];
if (!err)
return false;
@ -194,11 +199,19 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
/*
* A still unknown Magic: potentially freshly added
* to the Kernel code and still unknown to the
* tests.
* tests. Magic numbers are supposed to be allocated
* as somewhat meaningful ASCII strings so try to
* print as such as well as the raw number.
*/
memcpy(magic, &head->magic, sizeof(magic));
for (i = 0; i < sizeof(magic); i++)
if (!isalnum(magic[i]))
magic[i] = '?';
fprintf(stdout,
"SKIP Unknown MAGIC: 0x%X - Is KSFT arm64/signal up to date ?\n",
head->magic);
"SKIP Unknown MAGIC: 0x%X (%c%c%c%c) - Is KSFT arm64/signal up to date ?\n",
head->magic,
magic[3], magic[2], magic[1], magic[0]);
break;
}