Commit 32b48248 authored by Will Deacon's avatar Will Deacon
Browse files

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
parents 10162e78 c4e8720f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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
+93 −27
Original line number Diff line number Diff line
@@ -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]);

+6 −6
Original line number Diff line number Diff line
@@ -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;
+4 −5
Original line number Diff line number Diff line
@@ -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)
+0 −1
Original line number Diff line number Diff line
- Validate that register contents are saved and restored as expected.
- Support and validate extra_context.
Loading