From: Emmanuel Blot <[email protected]>
Signed-off-by: Emmanuel Blot <[email protected]>
Includes existing MIT licenced code (already published elsewhere)
---
target/riscv/cpu.c | 2 +-
target/riscv/cpu.h | 7 ++++
target/riscv/ibex_csr.c | 85 ++++++++++++++++++++++++++++++++++++++++
target/riscv/meson.build | 1 +
4 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 target/riscv/ibex_csr.c
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 24a4c2fd3f..dd30b21dd2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -3056,7 +3056,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.ext_zba = true,
.cfg.ext_zbb = true,
.cfg.ext_zbc = true,
- .cfg.ext_zbs = true
+ .cfg.ext_zbs = true,
),
DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E31, TYPE_RISCV_CPU_SIFIVE_E,
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 35d1f6362c..faf55e8b5e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -481,6 +481,10 @@ struct CPUArchState {
uint64_t hstateen[SMSTATEEN_MAX_COUNT];
uint64_t sstateen[SMSTATEEN_MAX_COUNT];
uint64_t henvcfg;
+
+ /* Ibex custom CSRs */
+ target_ulong cpuctrlsts;
+ target_ulong secureseed;
#endif
/* Fields from here on are preserved across CPU reset. */
@@ -988,5 +992,8 @@ extern const RISCVCSR th_csr_list[];
/* Implemented in mips_csr.c */
extern const RISCVCSR mips_csr_list[];
+/* Implemented in ibex_csr.c */
+extern const RISCVCSR ibex_csr_list[];
+
const char *priv_spec_to_str(int priv_version);
#endif /* RISCV_CPU_H */
diff --git a/target/riscv/ibex_csr.c b/target/riscv/ibex_csr.c
new file mode 100644
index 0000000000..d62638bbfb
--- /dev/null
+++ b/target/riscv/ibex_csr.c
@@ -0,0 +1,85 @@
+/*
+ * QEMU LowRisc Ibex core features
+ *
+ * Copyright (c) 2023 Rivos, Inc.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "cpu.h"
+
+/* Custom CSRs */
+#define CSR_CPUCTRLSTS 0x7c0
+#define CSR_SECURESEED 0x7c1
+
+#define CPUCTRLSTS_ICACHE_ENABLE 0x000
+#define CPUCTRLSTS_DATA_IND_TIMING 0x001
+#define CPUCTRLSTS_DUMMY_INSTR_EN 0x002
+#define CPUCTRLSTS_DUMMY_INSTR_MASK 0x038
+#define CPUCTRLSTS_SYNC_EXC_SEEN 0x040
+#define CPUCTRLSTS_DOUBLE_FAULT_SEEN 0x080
+#define CPUCTRLSTS_IC_SCR_KEY_VALID 0x100
+
+#if !defined(CONFIG_USER_ONLY)
+
+static RISCVException read_cpuctrlsts(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = CPUCTRLSTS_IC_SCR_KEY_VALID | env->cpuctrlsts;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_cpuctrlsts(CPURISCVState *env, int csrno,
+ target_ulong val, uintptr_t a)
+{
+ /* b7 can only be cleared */
+ env->cpuctrlsts &= ~0xbf;
+ /* b6 should be cleared on mret */
+ env->cpuctrlsts |= val & 0x3f;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_secureseed(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ /*
+ * "Seed values are not actually stored in a register and so reads to this
+ * register will always return zero."
+ */
+ *val = 0;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_secureseed(CPURISCVState *env, int csrno,
+ target_ulong val, uintptr_t a)
+{
+ (void)val;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException any(CPURISCVState *env, int csrno)
+{
+ /*
+ * unfortunately, this predicate is not public, so duplicate the standard
+ * implementation
+ */
+ return RISCV_EXCP_NONE;
+}
+
+const RISCVCSR ibex_csr_list[] = {
+ {
+ .csrno = CSR_CPUCTRLSTS,
+ .csr_ops = { "cpuctrlsts", any, &read_cpuctrlsts, &write_cpuctrlsts },
+ },
+ {
+ .csrno = CSR_SECURESEED,
+ .csr_ops = { "secureseed", any, &read_secureseed, &write_secureseed },
+ },
+ {}
+};
+
+#endif /* !defined(CONFIG_USER_ONLY) */
+
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index 3842c7c1a8..5a174a6feb 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -17,6 +17,7 @@ riscv_ss.add(files(
'cpu.c',
'cpu_helper.c',
'csr.c',
+ 'ibex_csr.c',
'fpu_helper.c',
'gdbstub.c',
'op_helper.c',
--
2.49.1