All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Clément Léger" <cleger@rivosinc.com>
To: kvm@vger.kernel.org, kvm-riscv@lists.infradead.org
Cc: "Clément Léger" <cleger@rivosinc.com>,
	"Andrew Jones" <ajones@ventanamicro.com>,
	"Anup Patel" <apatel@ventanamicro.com>,
	"Atish Patra" <atishp@rivosinc.com>
Subject: [kvm-unit-tests PATCH 2/2] riscv: Add tests for SBI FWFT extension
Date: Mon,  6 Jan 2025 16:53:20 +0100	[thread overview]
Message-ID: <20250106155321.1109586-3-cleger@rivosinc.com> (raw)
In-Reply-To: <20250106155321.1109586-1-cleger@rivosinc.com>

This commit add tests for a the FWFT SBI extension. Currently, only
the reserved range as well as the misaligned exception delegation.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
 riscv/Makefile      |   2 +-
 lib/riscv/asm/sbi.h |  31 +++++++++
 riscv/sbi-fwft.c    | 153 ++++++++++++++++++++++++++++++++++++++++++++
 riscv/sbi.c         |   3 +
 4 files changed, 188 insertions(+), 1 deletion(-)
 create mode 100644 riscv/sbi-fwft.c

diff --git a/riscv/Makefile b/riscv/Makefile
index 5b5e157c..52718f3f 100644
--- a/riscv/Makefile
+++ b/riscv/Makefile
@@ -17,7 +17,7 @@ tests += $(TEST_DIR)/sieve.$(exe)
 
 all: $(tests)
 
-$(TEST_DIR)/sbi-deps = $(TEST_DIR)/sbi-asm.o
+$(TEST_DIR)/sbi-deps = $(TEST_DIR)/sbi-asm.o $(TEST_DIR)/sbi-fwft.o
 
 # When built for EFI sieve needs extra memory, run with e.g. '-m 256' on QEMU
 $(TEST_DIR)/sieve.$(exe): AUXFLAGS = 0x1
diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h
index 98a9b097..27e6fcdb 100644
--- a/lib/riscv/asm/sbi.h
+++ b/lib/riscv/asm/sbi.h
@@ -11,6 +11,9 @@
 #define SBI_ERR_ALREADY_AVAILABLE	-6
 #define SBI_ERR_ALREADY_STARTED		-7
 #define SBI_ERR_ALREADY_STOPPED		-8
+#define SBI_ERR_NO_SHMEM		-9
+#define SBI_ERR_INVALID_STATE		-10
+#define SBI_ERR_BAD_RANGE		-11
 
 #ifndef __ASSEMBLY__
 #include <cpumask.h>
@@ -23,6 +26,7 @@ enum sbi_ext_id {
 	SBI_EXT_SRST = 0x53525354,
 	SBI_EXT_DBCN = 0x4442434E,
 	SBI_EXT_SUSP = 0x53555350,
+	SBI_EXT_FWFT = 0x46574654,
 };
 
 enum sbi_ext_base_fid {
@@ -71,6 +75,33 @@ enum sbi_ext_dbcn_fid {
 	SBI_EXT_DBCN_CONSOLE_WRITE_BYTE,
 };
 
+/* SBI function IDs for FW feature extension */
+#define SBI_EXT_FWFT_SET		0x0
+#define SBI_EXT_FWFT_GET		0x1
+
+enum sbi_fwft_feature_t {
+	SBI_FWFT_MISALIGNED_EXC_DELEG		= 0x0,
+	SBI_FWFT_LANDING_PAD			= 0x1,
+	SBI_FWFT_SHADOW_STACK			= 0x2,
+	SBI_FWFT_DOUBLE_TRAP			= 0x3,
+	SBI_FWFT_PTE_AD_HARDWARE_UPDATE		= 0x4,
+	SBI_FWFT_POINTER_MASKING_PMLEN		= 0x5,
+	SBI_FWFT_LOCAL_RESERVED_START		= 0x6,
+	SBI_FWFT_LOCAL_RESERVED_END		= 0x3fffffff,
+	SBI_FWFT_LOCAL_PLATFORM_START		= 0x40000000,
+	SBI_FWFT_LOCAL_PLATFORM_END		= 0x7fffffff,
+
+	SBI_FWFT_GLOBAL_RESERVED_START		= 0x80000000,
+	SBI_FWFT_GLOBAL_RESERVED_END		= 0xbfffffff,
+	SBI_FWFT_GLOBAL_PLATFORM_START		= 0xc0000000,
+	SBI_FWFT_GLOBAL_PLATFORM_END		= 0xffffffff,
+};
+
+#define SBI_FWFT_PLATFORM_FEATURE_BIT		(1 << 30)
+#define SBI_FWFT_GLOBAL_FEATURE_BIT		(1 << 31)
+
+#define SBI_FWFT_SET_FLAG_LOCK			(1 << 0)
+
 struct sbiret {
 	long error;
 	long value;
diff --git a/riscv/sbi-fwft.c b/riscv/sbi-fwft.c
new file mode 100644
index 00000000..8a7f2070
--- /dev/null
+++ b/riscv/sbi-fwft.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SBI verification
+ *
+ * Copyright (C) 2024, Rivos Inc., Clément Léger <cleger@rivosinc.com>
+ */
+#include <libcflat.h>
+#include <stdlib.h>
+
+#include <asm/csr.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/sbi.h>
+
+void check_fwft(void);
+
+static int fwft_set(unsigned long feature_id, unsigned long value,
+		       unsigned long flags)
+{
+	struct sbiret ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_SET,
+				      feature_id, value, flags, 0, 0, 0);
+
+	return ret.error;
+}
+
+static int fwft_get(unsigned long feature_id, unsigned long *value)
+{
+	struct sbiret ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_GET,
+				      feature_id, 0, 0, 0, 0, 0);
+
+	*value = ret.value;
+
+	return ret.error;
+}
+
+static void fwft_check_reserved(unsigned long id)
+{
+	int ret;
+	bool pass = true;
+	unsigned long value;
+
+	ret = fwft_get(id, &value);
+	if (ret != SBI_ERR_DENIED)
+		pass = false;
+
+	ret = fwft_set(id, 1, 0);
+	if (ret != SBI_ERR_DENIED)
+		pass = false;
+
+	report(pass, "get/set reserved feature 0x%lx error == SBI_ERR_DENIED", id);
+}
+
+static void fwft_check_denied(void)
+{
+	fwft_check_reserved(SBI_FWFT_LOCAL_RESERVED_START);
+	fwft_check_reserved(SBI_FWFT_LOCAL_RESERVED_END);
+	fwft_check_reserved(SBI_FWFT_GLOBAL_RESERVED_START);
+	fwft_check_reserved(SBI_FWFT_GLOBAL_RESERVED_END);
+}
+
+static bool misaligned_handled;
+
+static void misaligned_handler(struct pt_regs *regs)
+{
+	misaligned_handled = true;
+	regs->epc += 4;
+}
+
+static void fwft_check_misaligned(void)
+{
+	int ret;
+	unsigned long value;
+
+	report_prefix_push("misaligned_deleg");
+
+	ret = fwft_get(SBI_FWFT_MISALIGNED_EXC_DELEG, &value);
+	if (ret == SBI_ERR_NOT_SUPPORTED) {
+		report_skip("SBI_FWFT_MISALIGNED_EXC_DELEG is not supported");
+		return;
+	}
+	report(!ret, "Get misaligned deleg feature no error");
+	if (ret)
+		return;
+
+	ret = fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 2, 0);
+	report(ret == SBI_ERR_INVALID_PARAM, "Set misaligned deleg feature invalid value error");
+	ret = fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 0xFFFFFFFF, 0);
+	report(ret == SBI_ERR_INVALID_PARAM, "Set misaligned deleg feature invalid value error");
+
+	/* Set to 0 and check after with get */
+	ret = fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 0, 0);
+	report(!ret, "Set misaligned deleg feature value no error");
+	ret = fwft_get(SBI_FWFT_MISALIGNED_EXC_DELEG, &value);
+	if (ret)
+		report_fail("Get misaligned deleg feature after set");
+	else
+		report(value == 0, "Set misaligned deleg feature value 0");
+
+	/* Set to 1 and check after with get */
+	ret = fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 1, 0);
+	report(!ret, "Set misaligned deleg feature value no error");
+	ret = fwft_get(SBI_FWFT_MISALIGNED_EXC_DELEG, &value);
+	if (ret)
+		report_fail("Get misaligned deleg feature after set");
+	else
+		report(value == 1, "Set misaligned deleg feature value 1");
+
+	install_exception_handler(EXC_LOAD_MISALIGNED, misaligned_handler);
+
+	asm volatile (
+		".option norvc\n"
+		"lw %[val], 1(%[val_addr])"
+		: [val] "+r" (value)
+		: [val_addr] "r" (&value)
+		: "memory");
+
+	if (!misaligned_handled)
+		report_skip("Verify misaligned load exception trap in supervisor");
+	else
+		report_pass("Verify misaligned load exception trap in supervisor");
+
+	install_exception_handler(EXC_LOAD_MISALIGNED, NULL);
+
+	report_prefix_pop();
+}
+
+void check_fwft(void)
+{
+	struct sbiret ret;
+
+	report_prefix_push("fwft");
+
+	if (!sbi_probe(SBI_EXT_FWFT)) {
+		report_skip("FWFT extension not available");
+		report_prefix_pop();
+		return;
+	}
+
+	ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, SBI_EXT_FWFT, 0, 0, 0, 0, 0);
+	report(!ret.error, "FWFT extension probing no error");
+	if (ret.error)
+		goto done;
+
+	if (ret.value == 0) {
+		report_skip("FWFT extension is not present");
+		goto done;
+	}
+
+	fwft_check_denied();
+	fwft_check_misaligned();
+done:
+	report_prefix_pop();
+}
diff --git a/riscv/sbi.c b/riscv/sbi.c
index 6f4ddaf1..8600e38e 100644
--- a/riscv/sbi.c
+++ b/riscv/sbi.c
@@ -32,6 +32,8 @@
 
 #define	HIGH_ADDR_BOUNDARY	((phys_addr_t)1 << 32)
 
+void check_fwft(void);
+
 static long __labs(long a)
 {
 	return __builtin_labs(a);
@@ -1451,6 +1453,7 @@ int main(int argc, char **argv)
 	check_hsm();
 	check_dbcn();
 	check_susp();
+	check_fwft();
 
 	return report_summary();
 }
-- 
2.47.1


-- 
kvm-riscv mailing list
kvm-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kvm-riscv

WARNING: multiple messages have this Message-ID (diff)
From: "Clément Léger" <cleger@rivosinc.com>
To: kvm@vger.kernel.org, kvm-riscv@lists.infradead.org
Cc: "Clément Léger" <cleger@rivosinc.com>,
	"Andrew Jones" <ajones@ventanamicro.com>,
	"Anup Patel" <apatel@ventanamicro.com>,
	"Atish Patra" <atishp@rivosinc.com>
Subject: [kvm-unit-tests PATCH 2/2] riscv: Add tests for SBI FWFT extension
Date: Mon,  6 Jan 2025 16:53:20 +0100	[thread overview]
Message-ID: <20250106155321.1109586-3-cleger@rivosinc.com> (raw)
In-Reply-To: <20250106155321.1109586-1-cleger@rivosinc.com>

This commit add tests for a the FWFT SBI extension. Currently, only
the reserved range as well as the misaligned exception delegation.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
 riscv/Makefile      |   2 +-
 lib/riscv/asm/sbi.h |  31 +++++++++
 riscv/sbi-fwft.c    | 153 ++++++++++++++++++++++++++++++++++++++++++++
 riscv/sbi.c         |   3 +
 4 files changed, 188 insertions(+), 1 deletion(-)
 create mode 100644 riscv/sbi-fwft.c

diff --git a/riscv/Makefile b/riscv/Makefile
index 5b5e157c..52718f3f 100644
--- a/riscv/Makefile
+++ b/riscv/Makefile
@@ -17,7 +17,7 @@ tests += $(TEST_DIR)/sieve.$(exe)
 
 all: $(tests)
 
-$(TEST_DIR)/sbi-deps = $(TEST_DIR)/sbi-asm.o
+$(TEST_DIR)/sbi-deps = $(TEST_DIR)/sbi-asm.o $(TEST_DIR)/sbi-fwft.o
 
 # When built for EFI sieve needs extra memory, run with e.g. '-m 256' on QEMU
 $(TEST_DIR)/sieve.$(exe): AUXFLAGS = 0x1
diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h
index 98a9b097..27e6fcdb 100644
--- a/lib/riscv/asm/sbi.h
+++ b/lib/riscv/asm/sbi.h
@@ -11,6 +11,9 @@
 #define SBI_ERR_ALREADY_AVAILABLE	-6
 #define SBI_ERR_ALREADY_STARTED		-7
 #define SBI_ERR_ALREADY_STOPPED		-8
+#define SBI_ERR_NO_SHMEM		-9
+#define SBI_ERR_INVALID_STATE		-10
+#define SBI_ERR_BAD_RANGE		-11
 
 #ifndef __ASSEMBLY__
 #include <cpumask.h>
@@ -23,6 +26,7 @@ enum sbi_ext_id {
 	SBI_EXT_SRST = 0x53525354,
 	SBI_EXT_DBCN = 0x4442434E,
 	SBI_EXT_SUSP = 0x53555350,
+	SBI_EXT_FWFT = 0x46574654,
 };
 
 enum sbi_ext_base_fid {
@@ -71,6 +75,33 @@ enum sbi_ext_dbcn_fid {
 	SBI_EXT_DBCN_CONSOLE_WRITE_BYTE,
 };
 
+/* SBI function IDs for FW feature extension */
+#define SBI_EXT_FWFT_SET		0x0
+#define SBI_EXT_FWFT_GET		0x1
+
+enum sbi_fwft_feature_t {
+	SBI_FWFT_MISALIGNED_EXC_DELEG		= 0x0,
+	SBI_FWFT_LANDING_PAD			= 0x1,
+	SBI_FWFT_SHADOW_STACK			= 0x2,
+	SBI_FWFT_DOUBLE_TRAP			= 0x3,
+	SBI_FWFT_PTE_AD_HARDWARE_UPDATE		= 0x4,
+	SBI_FWFT_POINTER_MASKING_PMLEN		= 0x5,
+	SBI_FWFT_LOCAL_RESERVED_START		= 0x6,
+	SBI_FWFT_LOCAL_RESERVED_END		= 0x3fffffff,
+	SBI_FWFT_LOCAL_PLATFORM_START		= 0x40000000,
+	SBI_FWFT_LOCAL_PLATFORM_END		= 0x7fffffff,
+
+	SBI_FWFT_GLOBAL_RESERVED_START		= 0x80000000,
+	SBI_FWFT_GLOBAL_RESERVED_END		= 0xbfffffff,
+	SBI_FWFT_GLOBAL_PLATFORM_START		= 0xc0000000,
+	SBI_FWFT_GLOBAL_PLATFORM_END		= 0xffffffff,
+};
+
+#define SBI_FWFT_PLATFORM_FEATURE_BIT		(1 << 30)
+#define SBI_FWFT_GLOBAL_FEATURE_BIT		(1 << 31)
+
+#define SBI_FWFT_SET_FLAG_LOCK			(1 << 0)
+
 struct sbiret {
 	long error;
 	long value;
diff --git a/riscv/sbi-fwft.c b/riscv/sbi-fwft.c
new file mode 100644
index 00000000..8a7f2070
--- /dev/null
+++ b/riscv/sbi-fwft.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SBI verification
+ *
+ * Copyright (C) 2024, Rivos Inc., Clément Léger <cleger@rivosinc.com>
+ */
+#include <libcflat.h>
+#include <stdlib.h>
+
+#include <asm/csr.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/sbi.h>
+
+void check_fwft(void);
+
+static int fwft_set(unsigned long feature_id, unsigned long value,
+		       unsigned long flags)
+{
+	struct sbiret ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_SET,
+				      feature_id, value, flags, 0, 0, 0);
+
+	return ret.error;
+}
+
+static int fwft_get(unsigned long feature_id, unsigned long *value)
+{
+	struct sbiret ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_GET,
+				      feature_id, 0, 0, 0, 0, 0);
+
+	*value = ret.value;
+
+	return ret.error;
+}
+
+static void fwft_check_reserved(unsigned long id)
+{
+	int ret;
+	bool pass = true;
+	unsigned long value;
+
+	ret = fwft_get(id, &value);
+	if (ret != SBI_ERR_DENIED)
+		pass = false;
+
+	ret = fwft_set(id, 1, 0);
+	if (ret != SBI_ERR_DENIED)
+		pass = false;
+
+	report(pass, "get/set reserved feature 0x%lx error == SBI_ERR_DENIED", id);
+}
+
+static void fwft_check_denied(void)
+{
+	fwft_check_reserved(SBI_FWFT_LOCAL_RESERVED_START);
+	fwft_check_reserved(SBI_FWFT_LOCAL_RESERVED_END);
+	fwft_check_reserved(SBI_FWFT_GLOBAL_RESERVED_START);
+	fwft_check_reserved(SBI_FWFT_GLOBAL_RESERVED_END);
+}
+
+static bool misaligned_handled;
+
+static void misaligned_handler(struct pt_regs *regs)
+{
+	misaligned_handled = true;
+	regs->epc += 4;
+}
+
+static void fwft_check_misaligned(void)
+{
+	int ret;
+	unsigned long value;
+
+	report_prefix_push("misaligned_deleg");
+
+	ret = fwft_get(SBI_FWFT_MISALIGNED_EXC_DELEG, &value);
+	if (ret == SBI_ERR_NOT_SUPPORTED) {
+		report_skip("SBI_FWFT_MISALIGNED_EXC_DELEG is not supported");
+		return;
+	}
+	report(!ret, "Get misaligned deleg feature no error");
+	if (ret)
+		return;
+
+	ret = fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 2, 0);
+	report(ret == SBI_ERR_INVALID_PARAM, "Set misaligned deleg feature invalid value error");
+	ret = fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 0xFFFFFFFF, 0);
+	report(ret == SBI_ERR_INVALID_PARAM, "Set misaligned deleg feature invalid value error");
+
+	/* Set to 0 and check after with get */
+	ret = fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 0, 0);
+	report(!ret, "Set misaligned deleg feature value no error");
+	ret = fwft_get(SBI_FWFT_MISALIGNED_EXC_DELEG, &value);
+	if (ret)
+		report_fail("Get misaligned deleg feature after set");
+	else
+		report(value == 0, "Set misaligned deleg feature value 0");
+
+	/* Set to 1 and check after with get */
+	ret = fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 1, 0);
+	report(!ret, "Set misaligned deleg feature value no error");
+	ret = fwft_get(SBI_FWFT_MISALIGNED_EXC_DELEG, &value);
+	if (ret)
+		report_fail("Get misaligned deleg feature after set");
+	else
+		report(value == 1, "Set misaligned deleg feature value 1");
+
+	install_exception_handler(EXC_LOAD_MISALIGNED, misaligned_handler);
+
+	asm volatile (
+		".option norvc\n"
+		"lw %[val], 1(%[val_addr])"
+		: [val] "+r" (value)
+		: [val_addr] "r" (&value)
+		: "memory");
+
+	if (!misaligned_handled)
+		report_skip("Verify misaligned load exception trap in supervisor");
+	else
+		report_pass("Verify misaligned load exception trap in supervisor");
+
+	install_exception_handler(EXC_LOAD_MISALIGNED, NULL);
+
+	report_prefix_pop();
+}
+
+void check_fwft(void)
+{
+	struct sbiret ret;
+
+	report_prefix_push("fwft");
+
+	if (!sbi_probe(SBI_EXT_FWFT)) {
+		report_skip("FWFT extension not available");
+		report_prefix_pop();
+		return;
+	}
+
+	ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, SBI_EXT_FWFT, 0, 0, 0, 0, 0);
+	report(!ret.error, "FWFT extension probing no error");
+	if (ret.error)
+		goto done;
+
+	if (ret.value == 0) {
+		report_skip("FWFT extension is not present");
+		goto done;
+	}
+
+	fwft_check_denied();
+	fwft_check_misaligned();
+done:
+	report_prefix_pop();
+}
diff --git a/riscv/sbi.c b/riscv/sbi.c
index 6f4ddaf1..8600e38e 100644
--- a/riscv/sbi.c
+++ b/riscv/sbi.c
@@ -32,6 +32,8 @@
 
 #define	HIGH_ADDR_BOUNDARY	((phys_addr_t)1 << 32)
 
+void check_fwft(void);
+
 static long __labs(long a)
 {
 	return __builtin_labs(a);
@@ -1451,6 +1453,7 @@ int main(int argc, char **argv)
 	check_hsm();
 	check_dbcn();
 	check_susp();
+	check_fwft();
 
 	return report_summary();
 }
-- 
2.47.1


  parent reply	other threads:[~2025-01-06 15:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-06 15:53 [kvm-unit-tests PATCH 0/2] Add support for SBI FWFT extension testing Clément Léger
2025-01-06 15:53 ` Clément Léger
2025-01-06 15:53 ` [kvm-unit-tests PATCH 1/2] riscv: Add "-deps" handling for tests Clément Léger
2025-01-06 15:53   ` Clément Léger
2025-01-06 15:53 ` Clément Léger [this message]
2025-01-06 15:53   ` [kvm-unit-tests PATCH 2/2] riscv: Add tests for SBI FWFT extension Clément Léger
2025-01-15 12:58   ` Andrew Jones
2025-01-15 12:58     ` Andrew Jones
2025-01-21 10:59     ` Clément Léger
2025-01-21 10:59       ` Clément Léger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250106155321.1109586-3-cleger@rivosinc.com \
    --to=cleger@rivosinc.com \
    --cc=ajones@ventanamicro.com \
    --cc=apatel@ventanamicro.com \
    --cc=atishp@rivosinc.com \
    --cc=kvm-riscv@lists.infradead.org \
    --cc=kvm@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.