[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