kselftest/arm64: Add HWCAP test for FEAT_LS64

Add tests for FEAT_LS64. 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.

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Oliver Upton <oupton@kernel.org>
Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
Yicong Yang 2026-01-19 10:29:28 +08:00 committed by Will Deacon
parent 2a369c4942
commit 57a96356bb

View File

@ -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,45 @@ 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 requires 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 const struct hwcap_data {
const char *name;
unsigned long at_hwcap;
@ -1134,6 +1175,14 @@ 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,
},
};
typedef void (*sighandler_fn)(int, siginfo_t *, void *);