target/riscv/cpu.c | 3 +
target/riscv/cpu.h | 3 +
target/riscv/meson.build | 1 +
target/riscv/mips_csr.c | 226 +++++++++++++++++++++++++++++++++++++++
4 files changed, 233 insertions(+)
create mode 100644 target/riscv/mips_csr.c
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 672e30378e..9a11a994c4 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -3180,6 +3180,9 @@ static const TypeInfo riscv_cpu_type_infos[] = {
.cfg.ext_zbb = true,
.cfg.marchid = 0x8000000000000201,
.cfg.mvendorid = MIPS_VENDOR_ID,
+#ifndef CONFIG_USER_ONLY
+ .custom_csrs = mips_csr_list,
+#endif
),
#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index fba0b0506b..ed10709a65 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -972,5 +972,8 @@ const char *satp_mode_str(uint8_t satp_mode, bool
is_32_bit);
/* In th_csr.c */
extern const RISCVCSR th_csr_list[];
+/* Implemented in mips_csr.c */
+extern const RISCVCSR mips_csr_list[];
+
const char *priv_spec_to_str(int priv_version);
#endif /* RISCV_CPU_H */
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index a4bd61e52a..fbb6c8fb45 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -32,6 +32,7 @@ riscv_system_ss.add(files(
'debug.c',
'monitor.c',
'machine.c',
+ 'mips_csr.c',
'pmu.c',
'th_csr.c',
'time_helper.c',
diff --git a/target/riscv/mips_csr.c b/target/riscv/mips_csr.c
new file mode 100644
index 0000000000..759d5e6a67
--- /dev/null
+++ b/target/riscv/mips_csr.c
@@ -0,0 +1,226 @@
+/*
+ * MIPS-specific CSRs.
+ *
+ * Copyright (c) 2025 MIPS
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "cpu_vendorid.h"
+
+/* Static MIPS CSR state storage */
+static struct {
+ uint64_t tvec;
+ uint64_t config[12];
+ uint64_t pmacfg[16]; /* Fixed: was 15, should be 16 */
+} mips_csr_state;
+
+/* MIPS CSR */
+#define CSR_MIPSTVEC 0x7c0
+#define CSR_MIPSCONFIG0 0x7d0
+#define CSR_MIPSCONFIG1 0x7d1
+#define CSR_MIPSCONFIG2 0x7d2
+#define CSR_MIPSCONFIG3 0x7d3
+#define CSR_MIPSCONFIG4 0x7d4
+#define CSR_MIPSCONFIG5 0x7d5
+#define CSR_MIPSCONFIG6 0x7d6
+#define CSR_MIPSCONFIG7 0x7d7
+#define CSR_MIPSCONFIG8 0x7d8
+#define CSR_MIPSCONFIG9 0x7d9
+#define CSR_MIPSCONFIG10 0x7da
+#define CSR_MIPSCONFIG11 0x7db
+#define CSR_MIPSPMACFG0 0x7e0
+#define CSR_MIPSPMACFG1 0x7e1
+#define CSR_MIPSPMACFG2 0x7e2
+#define CSR_MIPSPMACFG3 0x7e3
+#define CSR_MIPSPMACFG4 0x7e4
+#define CSR_MIPSPMACFG5 0x7e5
+#define CSR_MIPSPMACFG6 0x7e6
+#define CSR_MIPSPMACFG7 0x7e7
+#define CSR_MIPSPMACFG8 0x7e8
+#define CSR_MIPSPMACFG9 0x7e9
+#define CSR_MIPSPMACFG10 0x7ea
+#define CSR_MIPSPMACFG11 0x7eb
+#define CSR_MIPSPMACFG12 0x7ec
+#define CSR_MIPSPMACFG13 0x7ed
+#define CSR_MIPSPMACFG14 0x7ee
+#define CSR_MIPSPMACFG15 0x7ef
+
+static RISCVException any(CPURISCVState *env, int csrno)
+{
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_mipstvec(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = mips_csr_state.tvec;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mipstvec(CPURISCVState *env, int csrno,
+ target_ulong val, uintptr_t ra)
+{
+ mips_csr_state.tvec = val;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_mipsconfig(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = mips_csr_state.config[csrno - CSR_MIPSCONFIG0];
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mipsconfig(CPURISCVState *env, int csrno,
+ target_ulong val, uintptr_t ra)
+{
+ mips_csr_state.config[csrno - CSR_MIPSCONFIG0] = val;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_mipspmacfg(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = mips_csr_state.pmacfg[csrno - CSR_MIPSPMACFG0];
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mipspmacfg(CPURISCVState *env, int csrno,
+ target_ulong val, uintptr_t ra)
+{
+ mips_csr_state.pmacfg[csrno - CSR_MIPSPMACFG0] = val;
+ return RISCV_EXCP_NONE;
+}
+
+const RISCVCSR mips_csr_list[] = {
+ {
+ .csrno = CSR_MIPSTVEC,
+ .csr_ops = { "mipstvec", any, read_mipstvec, write_mipstvec }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG0,
+ .csr_ops = { "mipsconfig0", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG1,
+ .csr_ops = { "mipsconfig1", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG2,
+ .csr_ops = { "mipsconfig2", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG3,
+ .csr_ops = { "mipsconfig3", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG4,
+ .csr_ops = { "mipsconfig4", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG5,
+ .csr_ops = { "mipsconfig5", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG6,
+ .csr_ops = { "mipsconfig6", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG7,
+ .csr_ops = { "mipsconfig7", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG8,
+ .csr_ops = { "mipsconfig8", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG9,
+ .csr_ops = { "mipsconfig9", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG10,
+ .csr_ops = { "mipsconfig10", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSCONFIG11,
+ .csr_ops = { "mipsconfig11", any, read_mipsconfig, write_mipsconfig }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG0,
+ .csr_ops = { "mipspmacfg0", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG1,
+ .csr_ops = { "mipspmacfg1", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG2,
+ .csr_ops = { "mipspmacfg2", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG3,
+ .csr_ops = { "mipspmacfg3", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG4,
+ .csr_ops = { "mipspmacfg4", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG5,
+ .csr_ops = { "mipspmacfg5", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG6,
+ .csr_ops = { "mipspmacfg6", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG7,
+ .csr_ops = { "mipspmacfg7", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG8,
+ .csr_ops = { "mipspmacfg8", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG9,
+ .csr_ops = { "mipspmacfg9", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG10,
+ .csr_ops = { "mipspmacfg10", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG11,
+ .csr_ops = { "mipspmacfg11", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG12,
+ .csr_ops = { "mipspmacfg12", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG13,
+ .csr_ops = { "mipspmacfg13", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG14,
+ .csr_ops = { "mipspmacfg14", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ {
+ .csrno = CSR_MIPSPMACFG15,
+ .csr_ops = { "mipspmacfg15", any, read_mipspmacfg, write_mipspmacfg }
+ },
+ { },
+};