[PATCH 3/5] lib: utils: Add SiFive feature-configuration driver

Leo Yu-Chi Liang leo.liang at sifive.com
Tue Sep 29 22:42:08 PDT 2026


Add the SiFive driver, which maps core identity (marchid and mimpid)
onto the feature-configuration CSR values that core needs and caches
them via sbi_hart_feature_config_set().

marchid and mimpid are read per hart rather than once, since a
heterogeneous or AMP system can mix cores. Cores not in the table are
left untouched.

A platform that licenses a SiFive core but needs different values does
not have to modify this table or write its own driver: it can override
individual values with its own sbi_hart_feature_config_set() call from
its feature_config_init operation, after delegating to the generic
probe for the vendor defaults.

Signed-off-by: Leo Yu-Chi Liang <leo.liang at sifive.com>
Assisted-by: LLM
---
 .../sbi_utils/feature/sifive_feature_config.h |  32 ++++++
 lib/utils/feature/Kconfig                     |  17 +++
 lib/utils/feature/objects.mk                  |   3 +
 lib/utils/feature/sifive_feature_config.c     | 101 ++++++++++++++++++
 4 files changed, 153 insertions(+)
 create mode 100644 include/sbi_utils/feature/sifive_feature_config.h
 create mode 100644 lib/utils/feature/sifive_feature_config.c

diff --git a/include/sbi_utils/feature/sifive_feature_config.h b/include/sbi_utils/feature/sifive_feature_config.h
new file mode 100644
index 00000000..8e36b967
--- /dev/null
+++ b/include/sbi_utils/feature/sifive_feature_config.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * sifive_feature_config.h - SiFive per-hart feature-configuration CSRs.
+ *
+ * Copyright (c) 2026 SiFive Inc.
+ */
+
+#ifndef __SIFIVE_FEATURE_CONFIG_H__
+#define __SIFIVE_FEATURE_CONFIG_H__
+
+#include <sbi_utils/feature/feature_config.h>
+
+#define SIFIVE_MVENDORID			0x489
+
+/*
+ * SiFive per-hart machine-mode feature-configuration CSRs.
+ */
+
+#define SIFIVE_CSR_BPM				0x7c0
+#define SIFIVE_CSR_FEATURE_CONFIG		0x7c1
+#define SIFIVE_CSR_LSU_CONFIG			0x7c2
+#define SIFIVE_CSR_HWPF_CONFIG			0x7c3
+#define SIFIVE_CSR_HWPF2_CONFIG			0x7c4
+#define SIFIVE_CSR_VEC_CONFIG			0x7c5
+#define SIFIVE_CSR_IMSIC_CONFIG			0x7c6
+#define SIFIVE_CSR_TUNING			0x7c7
+#define SIFIVE_CSR_INT_POWER_DIAL		0x7c8
+#define SIFIVE_CSR_VEC_POWER_DIAL		0x7c9
+
+extern const struct feature_config_driver sifive_feature_config_driver;
+
+#endif /* __SIFIVE_FEATURE_CONFIG_H__ */
diff --git a/lib/utils/feature/Kconfig b/lib/utils/feature/Kconfig
index f6760564..acf5f1cd 100644
--- a/lib/utils/feature/Kconfig
+++ b/lib/utils/feature/Kconfig
@@ -2,4 +2,21 @@
 
 menu "Feature Configuration Support"
 
+config FEATURE_CONFIG_SIFIVE
+	bool "SiFive feature-configuration CSRs"
+	depends on FEATURE_CONFIG
+	default n
+	help
+	  Program the SiFive per-hart feature-configuration CSRs in the
+	  machine-mode custom CSR range starting at 0x7c0.
+
+	  Selected at runtime by mvendorid, then by core identity
+	  (marchid and mimpid), so one firmware covers every integration
+	  of a given core. Harts not in the table are left untouched.
+
+	  A platform needing different values can override them with its
+	  own sbi_hart_feature_config_set() call from its
+	  feature_config_init operation, after delegating to the generic
+	  probe for the vendor defaults.
+
 endmenu
diff --git a/lib/utils/feature/objects.mk b/lib/utils/feature/objects.mk
index 4ed7a97b..90c9dcee 100644
--- a/lib/utils/feature/objects.mk
+++ b/lib/utils/feature/objects.mk
@@ -6,3 +6,6 @@
 
 libsbiutils-objs-$(CONFIG_FEATURE_CONFIG) += feature/feature_config.o
 libsbiutils-objs-$(CONFIG_FEATURE_CONFIG) += feature/feature_config_drivers.carray.o
+
+carray-feature_config_drivers-$(CONFIG_FEATURE_CONFIG_SIFIVE) += sifive_feature_config_driver
+libsbiutils-objs-$(CONFIG_FEATURE_CONFIG_SIFIVE) += feature/sifive_feature_config.o
diff --git a/lib/utils/feature/sifive_feature_config.c b/lib/utils/feature/sifive_feature_config.c
new file mode 100644
index 00000000..aa2abb41
--- /dev/null
+++ b/lib/utils/feature/sifive_feature_config.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * sifive_feature_config.c - SiFive per-hart feature-configuration CSRs.
+ *
+ * Copyright (c) 2026 SiFive Inc.
+ *
+ * Maps hardware identity (marchid + mimpid) onto the custom CSR writes
+ * a core needs and caches them once matched. Actual writes, platform
+ * overrides, and resume replay live in sbi_hart_feature_config.c.
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_hart_feature_config.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_types.h>
+#include <sbi_utils/feature/sifive_feature_config.h>
+
+/**
+ * Feature-configuration entry for one core identity, matched by
+ * marchid and mimpid. First match wins.
+ */
+#define DEFINE_CSRS(...) \
+	((const struct feature_config_csr[]) { __VA_ARGS__, { 0 } })
+
+struct sifive_feature_entry {
+	const unsigned long marchid;
+	const unsigned long mimpid;
+	const struct feature_config_csr *csrs;
+};
+
+/*
+ * marchids for these entries are 64 bit, so these entries only
+ * make sense on rv64 harts; skip them entirely on rv32 rather than
+ * truncating the marchid literals.
+ */
+#if __riscv_xlen == 64
+static const struct sifive_feature_entry sifive_feature_entries[] = {
+	{
+		.marchid	= 0x8000000000000008,
+		.mimpid		= 0x6220425,
+		.csrs		= DEFINE_CSRS(
+			{ .csr_num = SIFIVE_CSR_FEATURE_CONFIG, .value = 0x4000 },
+			{ .csr_num = SIFIVE_CSR_LSU_CONFIG, .value = 0x80 },
+			{ .csr_num = SIFIVE_CSR_HWPF_CONFIG, .value = 0x5c1be649 },
+			{ .csr_num = SIFIVE_CSR_HWPF2_CONFIG, .value = 0x929f }
+		),
+	},
+	{
+		.marchid	= 0x8000000000000007,
+		.mimpid		= 0x20181004,
+		.csrs		= DEFINE_CSRS(
+			{ .csr_num = SIFIVE_CSR_FEATURE_CONFIG, .value = 0x0 }
+		),
+	},
+};
+#else
+static const struct sifive_feature_entry sifive_feature_entries[0];
+#endif
+
+
+/**
+ * Match the current hart's core identity and cache its CSR writes.
+ * marchid/mimpid are read per hart since an AMP system can mix cores.
+ */
+static int sifive_feature_config_init(void)
+{
+	unsigned long marchid = csr_read(CSR_MARCHID);
+	unsigned long mimpid = csr_read(CSR_MIMPID);
+	int rc;
+
+	for (unsigned int i = 0; i < array_size(sifive_feature_entries); i++) {
+		const struct sifive_feature_entry *e =
+			&sifive_feature_entries[i];
+
+		if (e->marchid != marchid || e->mimpid != mimpid)
+			continue;
+
+		for (const struct feature_config_csr *iter = e->csrs;
+						      iter->csr_num != 0; iter++) {
+			rc = sbi_hart_feature_config_set(current_hartindex(), iter->csr_num,
+							 iter->value, false);
+			if (rc)
+				return rc;
+		}
+
+		return 0;
+	}
+
+	sbi_dprintf("hart%lu: sifive-feature-config: no entry for marchid 0x%lx mimpid 0x%lx\n",
+		     current_hartindex(), marchid, mimpid);
+
+	return 0;
+}
+
+const struct feature_config_driver sifive_feature_config_driver = {
+	.name		= "sifive-feature-config",
+	.mvendorid	= SIFIVE_MVENDORID,
+	.init		= sifive_feature_config_init,
+};
-- 
2.43.7




More information about the opensbi mailing list