Commit 57a96356 authored by Yicong Yang's avatar Yicong Yang Committed by Will Deacon
Browse files

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: default avatarArnd Bergmann <arnd@arndb.de>
Acked-by: default avatarOliver Upton <oupton@kernel.org>
Signed-off-by: default avatarYicong Yang <yangyicong@hisilicon.com>
Signed-off-by: default avatarZhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 2a369c49
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -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 *);