[PATCH v7 7/7] kselftest/arm64: Add HWCAP test for FEAT_{LS64, LS64_V}
Zhou Wang
wangzhou1 at hisilicon.com
Thu Nov 6 23:21:27 PST 2025
From: Yicong Yang <yangyicong at hisilicon.com>
Add tests for FEAT_{LS64, LS64_V}. Issue related instructions
if feature presents, no SIGILL should be received. When such
instructions operate on Device memory or non-cacheable memory,
we may received a SIGBUS during the test (w/o FEAT_LS64WB).
Just ignore it since we only tested whether the instruction
itself can be issued as expected on platforms declaring the
support of such features.
Signed-off-by: Yicong Yang <yangyicong at hisilicon.com>
Signed-off-by: Zhou Wang <wangzhou1 at hisilicon.com>
---
tools/testing/selftests/arm64/abi/hwcap.c | 79 +++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/tools/testing/selftests/arm64/abi/hwcap.c b/tools/testing/selftests/arm64/abi/hwcap.c
index 3b96d090c5eb..4d41ab10988f 100644
--- a/tools/testing/selftests/arm64/abi/hwcap.c
+++ b/tools/testing/selftests/arm64/abi/hwcap.c
@@ -11,6 +11,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <linux/auxvec.h>
+#include <linux/compiler.h>
#include <sys/auxv.h>
#include <sys/prctl.h>
#include <asm/hwcap.h>
@@ -595,6 +597,67 @@ static void lrcpc3_sigill(void)
: "=r" (data0), "=r" (data1) : "r" (src) :);
}
+static void ignore_signal(int sig, siginfo_t *info, void *context)
+{
+ ucontext_t *uc = context;
+
+ uc->uc_mcontext.pc += 4;
+}
+
+static void ls64_sigill(void)
+{
+ struct sigaction ign, old;
+ char src[64] __aligned(64) = { 1 };
+
+ /*
+ * LS64, LS64_V require target memory to be Device/Non-cacheable (if
+ * FEAT_LS64WB not supported) and the completer supports these
+ * instructions, otherwise we'll receive a SIGBUS. Since we are only
+ * testing the ABI here, so just ignore the SIGBUS and see if we can
+ * execute the instructions without receiving a SIGILL. Restore the
+ * handler of SIGBUS after this test.
+ */
+ ign.sa_sigaction = ignore_signal;
+ ign.sa_flags = SA_SIGINFO | SA_RESTART;
+ sigemptyset(&ign.sa_mask);
+ sigaction(SIGBUS, &ign, &old);
+
+ register void *xn asm ("x8") = src;
+ register u64 xt_1 asm ("x0");
+
+ /* LD64B x0, [x8] */
+ asm volatile(".inst 0xf83fd100" : "=r" (xt_1) : "r" (xn)
+ : "x1", "x2", "x3", "x4", "x5", "x6", "x7");
+
+ /* ST64B x0, [x8] */
+ asm volatile(".inst 0xf83f9100" : : "r" (xt_1), "r" (xn)
+ : "x1", "x2", "x3", "x4", "x5", "x6", "x7");
+
+ sigaction(SIGBUS, &old, NULL);
+}
+
+static void ls64_v_sigill(void)
+{
+ struct sigaction ign, old;
+ char dst[64] __aligned(64);
+
+ /* See comment in ls64_sigill() */
+ ign.sa_sigaction = ignore_signal;
+ ign.sa_flags = SA_SIGINFO | SA_RESTART;
+ sigemptyset(&ign.sa_mask);
+ sigaction(SIGBUS, &ign, &old);
+
+ register void *xn asm ("x8") = dst;
+ register u64 xt_1 asm ("x0") = 1;
+ register u64 st asm ("x9");
+
+ /* ST64BV x9, x0, [x8] */
+ asm volatile(".inst 0xf829b100" : "=r" (st) : "r" (xt_1), "r" (xn)
+ : "x1", "x2", "x3", "x4", "x5", "x6", "x7");
+
+ sigaction(SIGBUS, &old, NULL);
+}
+
static const struct hwcap_data {
const char *name;
unsigned long at_hwcap;
@@ -1134,6 +1197,22 @@ static const struct hwcap_data {
.hwcap_bit = HWCAP3_MTE_STORE_ONLY,
.cpuinfo = "mtestoreonly",
},
+ {
+ .name = "LS64",
+ .at_hwcap = AT_HWCAP3,
+ .hwcap_bit = HWCAP3_LS64,
+ .cpuinfo = "ls64",
+ .sigill_fn = ls64_sigill,
+ .sigill_reliable = true,
+ },
+ {
+ .name = "LS64_V",
+ .at_hwcap = AT_HWCAP3,
+ .hwcap_bit = HWCAP3_LS64_V,
+ .cpuinfo = "ls64_v",
+ .sigill_fn = ls64_v_sigill,
+ .sigill_reliable = true,
+ },
};
typedef void (*sighandler_fn)(int, siginfo_t *, void *);
--
2.33.0
More information about the linux-arm-kernel
mailing list