Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

kselftest/arm64: add test item that support to capturing the SIGBUS signal

Some enhanced features, such as the LSE2 feature, do not result in
SILLILL if LSE2 is missing and LSE is present, but will generate a
SIGBUS exception when atomic access unaligned.

Therefore, we add test item to test this type of features.

Notice that testing for SIGBUS only makes sense after make sure that
the instruction does not cause a SIGILL signal.

Signed-off-by: Zeng Heng <zengheng4@huawei.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20230808134036.668954-5-zengheng4@huawei.com
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Zeng Heng and committed by
Will Deacon
fd49cf08 71b634ab

+23 -10
+23 -10
tools/testing/selftests/arm64/abi/hwcap.c
··· 19 19 20 20 #include "../../kselftest.h" 21 21 22 - #define TESTS_PER_HWCAP 2 22 + #define TESTS_PER_HWCAP 3 23 23 24 24 /* 25 - * Function expected to generate SIGILL when the feature is not 26 - * supported and return when it is supported. If SIGILL is generated 27 - * then the handler must be able to skip over the instruction safely. 25 + * Function expected to generate exception when the feature is not 26 + * supported and return when it is supported. If the specific exception 27 + * is generated then the handler must be able to skip over the 28 + * instruction safely. 28 29 * 29 30 * Note that it is expected that for many architecture extensions 30 31 * there are no specific traps due to no architecture state being 31 32 * added so we may not fault if running on a kernel which doesn't know 32 33 * to add the hwcap. 33 34 */ 34 - typedef void (*sigill_fn)(void); 35 + typedef void (*sig_fn)(void); 35 36 36 37 static void crc32_sigill(void) 37 38 { ··· 236 235 unsigned long at_hwcap; 237 236 unsigned long hwcap_bit; 238 237 const char *cpuinfo; 239 - sigill_fn sigill_fn; 238 + sig_fn sigill_fn; 240 239 bool sigill_reliable; 240 + sig_fn sigbus_fn; 241 + bool sigbus_reliable; 241 242 } hwcaps[] = { 242 243 { 243 244 .name = "CRC32", ··· 455 452 } 456 453 457 454 DEF_SIGHANDLER_FUNC(sigill, SIGILL); 455 + DEF_SIGHANDLER_FUNC(sigbus, SIGBUS); 458 456 459 457 bool cpuinfo_present(const char *name) 460 458 { ··· 510 506 sigemptyset(&sa.sa_mask); 511 507 ret = sigaction(signum, &sa, NULL); 512 508 if (ret < 0) 513 - ksft_exit_fail_msg("Failed to install SIGILL handler: %s (%d)\n", 509 + ksft_exit_fail_msg("Failed to install SIGNAL handler: %s (%d)\n", 514 510 strerror(errno), errno); 515 511 516 512 return ret; ··· 519 515 static void uninstall_sigaction(int signum) 520 516 { 521 517 if (sigaction(signum, NULL, NULL) < 0) 522 - ksft_exit_fail_msg("Failed to uninstall SIGILL handler: %s (%d)\n", 518 + ksft_exit_fail_msg("Failed to uninstall SIGNAL handler: %s (%d)\n", 523 519 strerror(errno), errno); 524 520 } 525 521 ··· 560 556 } 561 557 562 558 DEF_INST_RAISE_SIG(sigill, SIGILL); 559 + DEF_INST_RAISE_SIG(sigbus, SIGBUS); 563 560 564 561 int main(void) 565 562 { 566 563 int i; 567 564 const struct hwcap_data *hwcap; 568 - bool have_cpuinfo, have_hwcap; 565 + bool have_cpuinfo, have_hwcap, raise_sigill; 569 566 570 567 ksft_print_header(); 571 568 ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP); ··· 583 578 ksft_test_result(have_hwcap == have_cpuinfo, 584 579 "cpuinfo_match_%s\n", hwcap->name); 585 580 586 - inst_raise_sigill(hwcap, have_hwcap); 581 + /* 582 + * Testing for SIGBUS only makes sense after make sure 583 + * that the instruction does not cause a SIGILL signal. 584 + */ 585 + raise_sigill = inst_raise_sigill(hwcap, have_hwcap); 586 + if (!raise_sigill) 587 + inst_raise_sigbus(hwcap, have_hwcap); 588 + else 589 + ksft_test_result_skip("sigbus_%s\n", hwcap->name); 587 590 } 588 591 589 592 ksft_print_cnts();