Skip to content
STIMSMITH

SOURCE ARCHIVE

SHA256: 1d6b77b87befb8b974f9abc28e3c1e78ccc898a5a1c61c4dd794fbc8182eea7c
TYPE: text/html
SIZE: 22.6 KB
FETCHED: 7/29/2026, 10:09:01 PM
EXTRACTOR: http-html
CHARS: 5,039

EXTRACTED CONTENT

5,039 chars
@@ -283,11 +283,13 @@  struct CPUArchState {
     target_ulong medeleg;

     target_ulong stvec;
+    target_ulong stvt; /* clic-spec */
     target_ulong sepc;
     target_ulong scause;
     target_ulong sintthresh; /* clic-spec */

     target_ulong mtvec;
+    target_ulong mtvt; /* clic-spec */
     target_ulong mepc;
     target_ulong mcause;
     target_ulong mtval;  /* since: priv-1.10.0 */

@@ -153,6 +153,7 @@
 #define CSR_MIE             0x304
 #define CSR_MTVEC           0x305
 #define CSR_MCOUNTEREN      0x306
+#define CSR_MTVT            0x307 /* clic-spec-draft */

 /* 32-bit only */
 #define CSR_MSTATUSH        0x310
@@ -192,6 +193,7 @@
 #define CSR_SIE             0x104
 #define CSR_STVEC           0x105
 #define CSR_SCOUNTEREN      0x106
+#define CSR_STVT            0x107 /* clic-spec-draft */

 /* Supervisor Configuration CSRs */
 #define CSR_SENVCFG         0x10A

@@ -2170,9 +2170,23 @@  static RISCVException read_mtvec(CPURISCVState *env, int csrno,
 static RISCVException write_mtvec(CPURISCVState *env, int csrno,
                                   target_ulong val)
 {
-    /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
-    if ((val & 3) < 2) {
+    /*
+     * bits [1:0] encode mode; 0 = direct, 1 = vectored, 3 = CLIC,
+     * others reserved
+     */
+    target_ulong mode = get_field(val, XTVEC_MODE);
+    target_ulong fullmode = val & XTVEC_FULL_MODE;
+    if (mode <= XTVEC_CLINT_VECTORED) {
         env->mtvec = val;
+    } else if (XTVEC_CLIC == fullmode && env->clic) {
+        /*
+         * CLIC mode hardwires xtvec bits 2-5 to zero.
+         * Layout:
+         *   XLEN-1:6   base (WARL)
+         *   5:2        submode (WARL)  - 0000 for CLIC
+         *   1:0        mode (WARL)     - 11 for CLIC
+         */
+        env->mtvec = (val & XTVEC_NBASE) | XTVEC_CLIC;
     } else {
         qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: reserved mode not supported\n");
     }
@@ -2271,6 +2285,18 @@  static RISCVException write_mcounteren(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }

+static int read_mtvt(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mtvt;
+    return RISCV_EXCP_NONE;
+}
+
+static int write_mtvt(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mtvt = val & XTVEC_NBASE;
+    return RISCV_EXCP_NONE;
+}
+
 /* Machine Trap Handling */
 static RISCVException read_mscratch_i128(CPURISCVState *env, int csrno,
                                          Int128 *val)
@@ -3122,9 +3148,24 @@  static RISCVException read_stvec(CPURISCVState *env, int csrno,
 static RISCVException write_stvec(CPURISCVState *env, int csrno,
                                   target_ulong val)
 {
-    /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
-    if ((val & 3) < 2) {
+    /*
+     * bits [1:0] encode mode; 0 = direct, 1 = vectored, 3 = CLIC,
+     * others reserved
+     */
+    target_ulong mode = val & XTVEC_MODE;
+    target_ulong fullmode = val & XTVEC_FULL_MODE;
+    if (mode <= XTVEC_CLINT_VECTORED) {
         env->stvec = val;
+    } else if (XTVEC_CLIC == fullmode && env->clic) {
+        /*
+         * If only CLIC mode is supported, writes to bit 1 are also ignored and
+         * it is always set to one. CLIC mode hardwires xtvec bits 2-5 to zero.
+         * Layout:
+         *   XLEN-1:6   base (WARL)
+         *   5:2        submode (WARL)  - 0000 for CLIC
+         *   1:0        mode (WARL)     - 11 for CLIC
+         */
+        env->stvec = (val & XTVEC_NBASE) | XTVEC_CLIC;
     } else {
         qemu_log_mask(LOG_UNIMP, "CSR_STVEC: reserved mode not supported\n");
     }
@@ -3149,6 +3190,18 @@  static RISCVException write_scounteren(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }

+static int read_stvt(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->stvt;
+    return RISCV_EXCP_NONE;
+}
+
+static int write_stvt(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->stvt = val & XTVEC_NBASE;
+    return RISCV_EXCP_NONE;
+}
+
 /* Supervisor Trap Handling */
 static RISCVException read_sscratch_i128(CPURISCVState *env, int csrno,
                                          Int128 *val)
@@ -5666,11 +5719,13 @@  riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
                              write_mhpmcounterh                         },

     /* Machine Mode Core Level Interrupt Controller */
+    [CSR_MTVT]           = { "mtvt",       clic,  read_mtvt, write_mtvt },
     [CSR_MINTSTATUS]     = { "mintstatus", clic,  read_mintstatus       },
     [CSR_MINTTHRESH]     = { "mintthresh", clic,  read_mintthresh,
                              write_mintthresh },

     /* Supervisor Mode Core Level Interrupt Controller */
+    [CSR_STVT]           = { "stvt",       clic,  read_stvt, write_stvt },
     [CSR_SINTSTATUS]     = { "sintstatus", clic,  read_sintstatus       },
     [CSR_SINTTHRESH]     = { "sintthresh", clic,  read_sintthresh,
                              write_sintthresh },