From 3a38ef2b3cb6b63c105247b5ea4a9cf600e673f0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 17 Oct 2022 15:45:52 +0100 Subject: kselftest/arm64: Check that all children are producing output in fp-stress Currently we don't have an explicit check that when it's been a second since we have seen output produced from the test programs starting up that means all of them are running and we should start both sending signals and timing out. This is not reliable, especially on very heavily loaded systems where the test programs might take longer than a second to run. We do skip sending signals to children that have not produced output yet so we won't cause them to exit unexpectedly by sending a signal but this can create confusion when interpreting output, for example appearing to show the tests running for less time than expected or appearing to show missed signal deliveries. Avoid issues by explicitly checking that we have seen output from all the child processes before we start sending signals or counting test run time. This is especially likely on virtual platforms with large numbers of vector lengths supported since the platforms are slow and there will be a lot of tasks per CPU. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221017144553.773176-2-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/fp/fp-stress.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c index 4e62a9199f97..35dc07648d52 100644 --- a/tools/testing/selftests/arm64/fp/fp-stress.c +++ b/tools/testing/selftests/arm64/fp/fp-stress.c @@ -403,6 +403,8 @@ int main(int argc, char **argv) int timeout = 10; int cpus, tests, 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; @@ -526,6 +528,27 @@ int main(int argc, char **argv) /* 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; + } + for (i = 0; i < num_children; i++) child_tickle(&children[i]); -- cgit v1.2.3-70-g09d2 From 3e02f57bcc6a34ab992c4027b6ef3f2916b20924 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 17 Oct 2022 15:45:53 +0100 Subject: kselftest/arm64: Provide progress messages when signalling children Especially when the test is configured to run for a longer time it can be reassuring to users to see that the supervising program is running OK so provide a message every second when the output timer expires. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221017144553.773176-3-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/fp/fp-stress.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c index 35dc07648d52..ccbfcf847d96 100644 --- a/tools/testing/selftests/arm64/fp/fp-stress.c +++ b/tools/testing/selftests/arm64/fp/fp-stress.c @@ -549,6 +549,9 @@ int main(int argc, char **argv) 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]); -- cgit v1.2.3-70-g09d2 From 2004734fb3fe088873ad4c5276cc92ee956e640d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 27 Oct 2022 12:03:24 +0100 Subject: kselftest/arm64: Remove validation of extra_context from TODO When fixing up support for extra_context in the signal handling tests I didn't notice that there is a TODO file in the directory which lists this as a thing to be done. Since it's been done remove it from the list. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221027110324.33802-1-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/signal/testcases/TODO | 1 - 1 file changed, 1 deletion(-) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/signal/testcases/TODO b/tools/testing/selftests/arm64/signal/testcases/TODO index 110ff9fd195d..1f7fba8194fe 100644 --- a/tools/testing/selftests/arm64/signal/testcases/TODO +++ b/tools/testing/selftests/arm64/signal/testcases/TODO @@ -1,2 +1 @@ - Validate that register contents are saved and restored as expected. -- Support and validate extra_context. -- cgit v1.2.3-70-g09d2 From 9b283888a6d5d0e413fd9bf097fd74c27a9b9948 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 2 Nov 2022 14:05:43 +0000 Subject: kselftest/arm64: Print ASCII version of unknown signal frame magic values The signal magic values are supposed to be allocated as somewhat meaningful ASCII so if we encounter a bad magic value print the any alphanumeric characters we find in it as well as the hex value to aid debuggability. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221102140543.98193-1-broonie@kernel.org Signed-off-by: Will Deacon --- .../selftests/arm64/signal/testcases/testcases.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.c b/tools/testing/selftests/arm64/signal/testcases/testcases.c index e1c625b20ac4..d2eda7b5de26 100644 --- a/tools/testing/selftests/arm64/signal/testcases/testcases.c +++ b/tools/testing/selftests/arm64/signal/testcases/testcases.c @@ -1,5 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (C) 2019 ARM Limited */ + +#include +#include + #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; } -- cgit v1.2.3-70-g09d2 From a0fa0b63131b0d8f4eff22d5b66e796ecb064dfe Mon Sep 17 00:00:00 2001 From: Kang Minchul Date: Sat, 5 Nov 2022 16:31:43 +0900 Subject: kselftest/arm64: fix array_size.cocci warning Use ARRAY_SIZE to fix the following coccicheck warnings: tools/testing/selftests/arm64/mte/check_buffer_fill.c:341:20-21: WARNING: Use ARRAY_SIZE tools/testing/selftests/arm64/mte/check_buffer_fill.c:35:20-21: WARNING: Use ARRAY_SIZE tools/testing/selftests/arm64/mte/check_buffer_fill.c:168:20-21: WARNING: Use ARRAY_SIZE tools/testing/selftests/arm64/mte/check_buffer_fill.c:72:20-21: WARNING: Use ARRAY_SIZE tools/testing/selftests/arm64/mte/check_buffer_fill.c:369:25-26: WARNING: Use ARRAY_SIZE Signed-off-by: Kang Minchul Link: https://lore.kernel.org/r/20221105073143.78521-1-tegongkang@gmail.com Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/mte/check_buffer_fill.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/mte/check_buffer_fill.c b/tools/testing/selftests/arm64/mte/check_buffer_fill.c index 75fc482d63b6..1dbbbd47dd50 100644 --- a/tools/testing/selftests/arm64/mte/check_buffer_fill.c +++ b/tools/testing/selftests/arm64/mte/check_buffer_fill.c @@ -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; -- cgit v1.2.3-70-g09d2 From b0ab73a5479fdf6b42babaccf22b4fa88f5a20a6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 17 Oct 2022 16:25:16 +0100 Subject: kselftest/arm64: Add FEAT_CSSC to the hwcap selftest Add FEAT_CSSC to the set of features checked by the hwcap selftest. Signed-off-by: Mark Brown Reviewed-by: Catalin Marinas Link: https://lore.kernel.org/r/20221017152520.1039165-3-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/abi/hwcap.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/abi/hwcap.c b/tools/testing/selftests/arm64/abi/hwcap.c index 9f1a7b5c6193..c7a6b327a7d0 100644 --- a/tools/testing/selftests/arm64/abi/hwcap.c +++ b/tools/testing/selftests/arm64/abi/hwcap.c @@ -33,6 +33,12 @@ */ typedef void (*sigill_fn)(void); +static void cssc_sigill(void) +{ + /* CNT x0, x0 */ + asm volatile(".inst 0xdac01c00" : : : "x0"); +} + static void rng_sigill(void) { asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0"); @@ -118,6 +124,13 @@ static const struct hwcap_data { sigill_fn sigill_fn; bool sigill_reliable; } hwcaps[] = { + { + .name = "CSSC", + .at_hwcap = AT_HWCAP2, + .hwcap_bit = HWCAP2_CSSC, + .cpuinfo = "cssc", + .sigill_fn = cssc_sigill, + }, { .name = "RNG", .at_hwcap = AT_HWCAP2, -- cgit v1.2.3-70-g09d2 From 989d37fc3d976f6bfa3f1da484f8f22c57c21c0c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 17 Oct 2022 16:25:18 +0100 Subject: kselftest/arm64: Add FEAT_RPRFM to the hwcap test Since the newly added instruction is in the HINT space we can't reasonably test for it actually being present. Signed-off-by: Mark Brown Reviewed-by: Catalin Marinas Link: https://lore.kernel.org/r/20221017152520.1039165-5-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/abi/hwcap.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/abi/hwcap.c b/tools/testing/selftests/arm64/abi/hwcap.c index c7a6b327a7d0..30f87dfd634e 100644 --- a/tools/testing/selftests/arm64/abi/hwcap.c +++ b/tools/testing/selftests/arm64/abi/hwcap.c @@ -138,6 +138,12 @@ static const struct hwcap_data { .cpuinfo = "rng", .sigill_fn = rng_sigill, }, + { + .name = "RPRFM", + .at_hwcap = AT_HWCAP2, + .hwcap_bit = HWCAP2_RPRFM, + .cpuinfo = "rprfm", + }, { .name = "SME", .at_hwcap = AT_HWCAP2, -- cgit v1.2.3-70-g09d2 From c5195b027d29bbaae0c9668704ab996773788d23 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 17 Oct 2022 16:25:20 +0100 Subject: kselftest/arm64: Add SVE 2.1 to hwcap test Add coverage for FEAT_SVE2p1. Signed-off-by: Mark Brown Reviewed-by: Catalin Marinas Link: https://lore.kernel.org/r/20221017152520.1039165-7-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/abi/hwcap.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/abi/hwcap.c b/tools/testing/selftests/arm64/abi/hwcap.c index 30f87dfd634e..9f255bc5f31c 100644 --- a/tools/testing/selftests/arm64/abi/hwcap.c +++ b/tools/testing/selftests/arm64/abi/hwcap.c @@ -62,6 +62,12 @@ static void sve2_sigill(void) asm volatile(".inst 0x4408A000" : : : "z0"); } +static void sve2p1_sigill(void) +{ + /* BFADD Z0.H, Z0.H, Z0.H */ + asm volatile(".inst 0x65000000" : : : "z0"); +} + static void sveaes_sigill(void) { /* AESD z0.b, z0.b, z0.b */ @@ -167,6 +173,13 @@ static const struct hwcap_data { .cpuinfo = "sve2", .sigill_fn = sve2_sigill, }, + { + .name = "SVE 2.1", + .at_hwcap = AT_HWCAP2, + .hwcap_bit = HWCAP2_SVE2P1, + .cpuinfo = "sve2p1", + .sigill_fn = sve2p1_sigill, + }, { .name = "SVE AES", .at_hwcap = AT_HWCAP2, -- cgit v1.2.3-70-g09d2 From a75df5be8e7b0ecfb413b7c02a2599be17d2721b Mon Sep 17 00:00:00 2001 From: "wangkailong@jari.cn" Date: Sun, 13 Nov 2022 17:41:10 +0800 Subject: kselftest/arm64: fix array_size.cocci warning Fix following coccicheck warning: tools/testing/selftests/arm64/mte/check_mmap_options.c:64:24-25: WARNING: Use ARRAY_SIZE tools/testing/selftests/arm64/mte/check_mmap_options.c:66:20-21: WARNING: Use ARRAY_SIZE tools/testing/selftests/arm64/mte/check_mmap_options.c:135:25-26: WARNING: Use ARRAY_SIZE tools/testing/selftests/arm64/mte/check_mmap_options.c:96:25-26: WARNING: Use ARRAY_SIZE tools/testing/selftests/arm64/mte/check_mmap_options.c:190:24-25: WARNING: Use ARRAY_SIZE Signed-off-by: KaiLong Wang Link: https://lore.kernel.org/r/777ce8ba.12e.184705d4211.Coremail.wangkailong@jari.cn Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/mte/check_mmap_options.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/mte/check_mmap_options.c b/tools/testing/selftests/arm64/mte/check_mmap_options.c index a04b12c21ac9..17694caaff53 100644 --- a/tools/testing/selftests/arm64/mte/check_mmap_options.c +++ b/tools/testing/selftests/arm64/mte/check_mmap_options.c @@ -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) -- cgit v1.2.3-70-g09d2 From 284d2b44a8cc0df8ed25596092fa864bc57b5bab Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 17 Nov 2022 11:41:30 +0000 Subject: kselftest/arm64: Use preferred form for predicate load/stores The preferred form of the str/ldr for predicate registers with an immediate of zero is to omit the zero, and the clang built in assembler rejects the zero immediate. Drop the immediate. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221117114130.687261-1-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/abi/syscall-abi-asm.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/abi/syscall-abi-asm.S b/tools/testing/selftests/arm64/abi/syscall-abi-asm.S index b523c21c2278..acd5e9f3bc0b 100644 --- a/tools/testing/selftests/arm64/abi/syscall-abi-asm.S +++ b/tools/testing/selftests/arm64/abi/syscall-abi-asm.S @@ -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 -- cgit v1.2.3-70-g09d2 From 642978981ec8a79da00828c696c58b3732b993a6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 24 Nov 2022 12:07:22 +0000 Subject: kselftest/arm64: Set test names prior to starting children Since we now flush output immediately on starting children we should ensure that the child name is set beforehand so that any output that does get flushed from the newly created child has the name of the child attached. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221124120722.150988-1-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/fp/fp-stress.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c index ccbfcf847d96..69ca4a5f7e6e 100644 --- a/tools/testing/selftests/arm64/fp/fp-stress.c +++ b/tools/testing/selftests/arm64/fp/fp-stress.c @@ -290,12 +290,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 +307,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 +320,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 +341,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); } -- cgit v1.2.3-70-g09d2 From 98102a2cb7860b4d8226d6c2996f068fb4da5ed5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Nov 2022 21:59:23 +0000 Subject: kselftest/arm64: Hold fp-stress children until they're all spawned At present fp-stress has a bit of a thundering herd problem since the children it spawns start running immediately, meaning that they can start starving the parent process of CPU before it has even started all the children. This is much more severe on virtual platforms since they tend to support far more SVE and SME vector lengths, be slower in general and for some have issues with performance when simulating multiple CPUs. We can mitigate this problem by having all the child processes block before starting the test program, meaning that we at least have all the child processes started before we start heavily using CPU. We still have the same load issues while waiting for the actual stress test programs to start up and produce output but they're at least all ready to go before that kicks in, resulting in substantial reductions in overall runtime on some of the severely affected systems. One test was showing about 20% improvement. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221129215926.442895-2-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/fp/fp-stress.c | 41 +++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c index 69ca4a5f7e6e..7c04f5001648 100644 --- a/tools/testing/selftests/arm64/fp/fp-stress.c +++ b/tools/testing/selftests/arm64/fp/fp-stress.c @@ -44,6 +44,8 @@ static bool terminate; static void drain_output(bool flush); +static int startup_pipe[2]; + static int num_processors(void) { long nproc = sysconf(_SC_NPROCESSORS_CONF); @@ -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)); @@ -467,6 +493,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; @@ -499,6 +531,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) -- cgit v1.2.3-70-g09d2 From 92145d88ce0b216c1b99aaac92fec1f6a7d6ddde Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Nov 2022 21:59:24 +0000 Subject: kselftest/arm64: Don't drain output while spawning children Now we hold execution of the stress test programs until all children are started there is no need to drain output while that is happening. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221129215926.442895-3-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/fp/fp-stress.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c index 7c04f5001648..b3bbfe8d9f56 100644 --- a/tools/testing/selftests/arm64/fp/fp-stress.c +++ b/tools/testing/selftests/arm64/fp/fp-stress.c @@ -42,8 +42,6 @@ static struct child_data *children; static int num_children; static bool terminate; -static void drain_output(bool flush); - static int startup_pipe[2]; static int num_processors(void) @@ -138,12 +136,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); } } -- cgit v1.2.3-70-g09d2 From c4e8720f2eb0c7f59082f41ad73b82e5d3f19f69 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Nov 2022 21:59:25 +0000 Subject: kselftest/arm64: Allow epoll_wait() to return more than one result When everything is starting up we are likely to have a lot of child processes producing output at once. This means that we can reduce overhead a bit by allowing epoll_wait() to return more than one descriptor at once, it cuts down on the number of system calls we need to do which on virtual platforms where the syscall overhead is a bit more noticable and we're likely to have a lot more children active can make a small but noticable difference. On physical platforms the relatively small number of processes being run and vastly improved speeds push the effects of this change into the noise. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20221129215926.442895-4-broonie@kernel.org Signed-off-by: Will Deacon --- tools/testing/selftests/arm64/fp/fp-stress.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/arm64/fp/fp-stress.c b/tools/testing/selftests/arm64/fp/fp-stress.c index b3bbfe8d9f56..f8b2f41aac36 100644 --- a/tools/testing/selftests/arm64/fp/fp-stress.c +++ b/tools/testing/selftests/arm64/fp/fp-stress.c @@ -39,6 +39,8 @@ 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; @@ -393,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; @@ -405,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); } } @@ -419,12 +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) { @@ -510,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); @@ -543,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; @@ -552,8 +558,11 @@ 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; } -- cgit v1.2.3-70-g09d2