qemu-riscv.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/4] target/riscv: Add Smrnmi support.
@ 2023-05-22 13:11 Tommy Wu
  2023-05-22 13:11 ` [PATCH v3 1/4] target/riscv: Add Smrnmi cpu extension Tommy Wu
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Tommy Wu @ 2023-05-22 13:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv
  Cc: frank.chang, palmer, alistair.francis, bin.meng, liweiwei,
	dbarboza, zhiwei_liu, richard.henderson, Tommy Wu

This patchset added support for Smrnmi Extension in RISC-V.

There are four new CSRs and one new instruction added to allow NMI to be
resumable in RISC-V, which are:

=============================================================
  * mnscratch (0x740)
  * mnepc     (0x741)
  * mncause   (0x742)
  * mnstatus  (0x744)
=============================================================
  * mnret: To return from RNMI interrupt/exception handler.
=============================================================

RNMI also has higher priority than any other interrupts or exceptions
and cannot be disabled by software.

RNMI may be used to route to other devices such as Bus Error Unit or
Watchdog Timer in the future.

The interrupt/exception trap handler addresses of RNMI are
implementation defined.

Changelog:

v3
  * Update to the newest version of Smrnmi extension specification.

v2
  * split up the series into more commits for convenience of review.
  * add missing rnmi_irqvec and rnmi_excpvec properties to riscv_harts.

Tommy Wu (4):
  target/riscv: Add Smrnmi cpu extension.
  target/riscv: Add Smrnmi CSRs.
  target/riscv: Handle Smrnmi interrupt and exception.
  target/riscv: Add Smrnmi mnret instruction.

 hw/riscv/riscv_hart.c                         | 21 +++++
 include/hw/riscv/riscv_hart.h                 |  4 +
 target/riscv/cpu.c                            | 19 +++++
 target/riscv/cpu.h                            | 11 +++
 target/riscv/cpu_bits.h                       | 23 +++++
 target/riscv/cpu_helper.c                     | 84 +++++++++++++++++--
 target/riscv/csr.c                            | 82 ++++++++++++++++++
 target/riscv/helper.h                         |  1 +
 target/riscv/insn32.decode                    |  3 +
 .../riscv/insn_trans/trans_privileged.c.inc   | 12 +++
 target/riscv/op_helper.c                      | 51 +++++++++++
 11 files changed, 306 insertions(+), 5 deletions(-)

-- 
2.31.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 1/4] target/riscv: Add Smrnmi cpu extension.
  2023-05-22 13:11 [PATCH v3 0/4] target/riscv: Add Smrnmi support Tommy Wu
@ 2023-05-22 13:11 ` Tommy Wu
  2023-05-25 12:29   ` Daniel Henrique Barboza
  2023-05-22 13:11 ` [PATCH v3 2/4] target/riscv: Add Smrnmi CSRs Tommy Wu
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Tommy Wu @ 2023-05-22 13:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv
  Cc: frank.chang, palmer, alistair.francis, bin.meng, liweiwei,
	dbarboza, zhiwei_liu, richard.henderson, Tommy Wu

Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
---
 hw/riscv/riscv_hart.c         | 21 +++++++++++++++++++++
 include/hw/riscv/riscv_hart.h |  4 ++++
 target/riscv/cpu.c            | 14 ++++++++++++++
 target/riscv/cpu.h            |  7 +++++++
 target/riscv/cpu_bits.h       | 12 ++++++++++++
 target/riscv/cpu_helper.c     | 24 ++++++++++++++++++++++++
 6 files changed, 82 insertions(+)

diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
index 613ea2aaa0..eac18f8c29 100644
--- a/hw/riscv/riscv_hart.c
+++ b/hw/riscv/riscv_hart.c
@@ -33,6 +33,12 @@ static Property riscv_harts_props[] = {
     DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type),
     DEFINE_PROP_UINT64("resetvec", RISCVHartArrayState, resetvec,
                        DEFAULT_RSTVEC),
+    DEFINE_PROP_ARRAY("rnmi-interrupt-vector", RISCVHartArrayState,
+                      num_rnmi_irqvec, rnmi_irqvec, qdev_prop_uint64,
+                      uint64_t),
+    DEFINE_PROP_ARRAY("rnmi-exception-vector", RISCVHartArrayState,
+                      num_rnmi_excpvec, rnmi_excpvec, qdev_prop_uint64,
+                      uint64_t),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -47,6 +53,21 @@ static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
 {
     object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], cpu_type);
     qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec", s->resetvec);
+
+    if (s->harts[idx].cfg.ext_smrnmi) {
+        if (s->rnmi_irqvec) {
+            qdev_prop_set_uint64(DEVICE(&s->harts[idx]),
+                                 "rnmi-interrupt-vector",
+                                 s->rnmi_irqvec[idx]);
+        }
+
+        if (s->rnmi_excpvec) {
+            qdev_prop_set_uint64(DEVICE(&s->harts[idx]),
+                                 "rnmi-exception-vector",
+                                 s->rnmi_excpvec[idx]);
+        }
+    }
+
     s->harts[idx].env.mhartid = s->hartid_base + idx;
     qemu_register_reset(riscv_harts_cpu_reset, &s->harts[idx]);
     return qdev_realize(DEVICE(&s->harts[idx]), NULL, errp);
diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
index bbc21cdc9a..99c0ac5009 100644
--- a/include/hw/riscv/riscv_hart.h
+++ b/include/hw/riscv/riscv_hart.h
@@ -38,6 +38,10 @@ struct RISCVHartArrayState {
     uint32_t hartid_base;
     char *cpu_type;
     uint64_t resetvec;
+    uint32_t num_rnmi_irqvec;
+    uint64_t *rnmi_irqvec;
+    uint32_t num_rnmi_excpvec;
+    uint64_t *rnmi_excpvec;
     RISCVCPU *harts;
 };
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index db0875fb43..39b74569b1 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -119,6 +119,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
     ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
     ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
     ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
+    ISA_EXT_DATA_ENTRY(smrnmi, PRIV_VERSION_1_12_0, ext_smrnmi),
     ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
     ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
     ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc),
@@ -1404,6 +1405,12 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level)
         g_assert_not_reached();
     }
 }
+
+static void riscv_cpu_set_nmi(void *opaque, int irq, int level)
+{
+    RISCVCPU *cpu = RISCV_CPU(opaque);
+    riscv_cpu_set_rnmi(cpu, irq, level);
+}
 #endif /* CONFIG_USER_ONLY */
 
 static void riscv_cpu_init(Object *obj)
@@ -1420,6 +1427,8 @@ static void riscv_cpu_init(Object *obj)
 #ifndef CONFIG_USER_ONLY
     qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
                       IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
+    qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_nmi,
+                            "riscv.cpu.rnmi", RNMI_MAX);
 #endif /* CONFIG_USER_ONLY */
 }
 
@@ -1600,6 +1609,7 @@ static Property riscv_cpu_extensions[] = {
     DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
     DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
     DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
+    DEFINE_PROP_BOOL("x-smrnmi", RISCVCPU, cfg.ext_smrnmi, false),
 
     DEFINE_PROP_BOOL("x-zvfh", RISCVCPU, cfg.ext_zvfh, false),
     DEFINE_PROP_BOOL("x-zvfhmin", RISCVCPU, cfg.ext_zvfhmin, false),
@@ -1644,6 +1654,10 @@ static Property riscv_cpu_properties[] = {
 
     DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s, false),
     DEFINE_PROP_BOOL("rvv_ma_all_1s", RISCVCPU, cfg.rvv_ma_all_1s, false),
+    DEFINE_PROP_UINT64("rnmi-interrupt-vector", RISCVCPU, env.rnmi_irqvec,
+                       DEFAULT_RNMI_IRQVEC),
+    DEFINE_PROP_UINT64("rnmi-exception-vector", RISCVCPU, env.rnmi_excpvec,
+                       DEFAULT_RNMI_EXCPVEC),
 
     /*
      * write_misa() is marked as experimental for now so mark
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index de7e43126a..6c14b93cb5 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -366,6 +366,11 @@ struct CPUArchState {
     uint64_t kvm_timer_compare;
     uint64_t kvm_timer_state;
     uint64_t kvm_timer_frequency;
+
+    /* RNMI */
+    target_ulong rnmip;
+    uint64_t rnmi_irqvec;
+    uint64_t rnmi_excpvec;
 };
 
 /*
@@ -436,6 +441,7 @@ struct RISCVCPUConfig {
     bool ext_smaia;
     bool ext_ssaia;
     bool ext_sscofpmf;
+    bool ext_smrnmi;
     bool rvv_ta_all_1s;
     bool rvv_ma_all_1s;
 
@@ -562,6 +568,7 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts);
 uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask,
                               uint64_t value);
+void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level);
 #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
 void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
                              void *arg);
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 59f0ffd9e1..7cb43b88f3 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -659,6 +659,12 @@ typedef enum {
 /* Default Reset Vector adress */
 #define DEFAULT_RSTVEC      0x1000
 
+/* Default RNMI Interrupt Vector address */
+#define DEFAULT_RNMI_IRQVEC     0x0
+
+/* Default RNMI Exception Vector address */
+#define DEFAULT_RNMI_EXCPVEC    0x0
+
 /* Exception causes */
 typedef enum RISCVException {
     RISCV_EXCP_NONE = -1, /* sentinel value */
@@ -705,6 +711,9 @@ typedef enum RISCVException {
 #define IRQ_LOCAL_MAX                      16
 #define IRQ_LOCAL_GUEST_MAX                (TARGET_LONG_BITS - 1)
 
+/* RNMI causes */
+#define RNMI_MAX                           16
+
 /* mip masks */
 #define MIP_USIP                           (1 << IRQ_U_SOFT)
 #define MIP_SSIP                           (1 << IRQ_S_SOFT)
@@ -896,6 +905,9 @@ typedef enum RISCVException {
 #define MHPMEVENT_IDX_MASK                 0xFFFFF
 #define MHPMEVENT_SSCOF_RESVD              16
 
+/* RISC-V-specific interrupt pending bits. */
+#define CPU_INTERRUPT_RNMI                 CPU_INTERRUPT_TGT_EXT_0
+
 /* JVT CSR bits */
 #define JVT_MODE                           0x3F
 #define JVT_BASE                           (~0x3F)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 57d04385f1..cc7898f103 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -635,6 +635,30 @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask,
     return old;
 }
 
+void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level)
+{
+    CPURISCVState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
+    bool locked = false;
+
+    if (!qemu_mutex_iothread_locked()) {
+        locked = true;
+        qemu_mutex_lock_iothread();
+    }
+
+    if (level) {
+        env->rnmip |= 1 << irq;
+        cpu_interrupt(cs, CPU_INTERRUPT_RNMI);
+    } else {
+        env->rnmip &= ~(1 << irq);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_RNMI);
+    }
+
+    if (locked) {
+        qemu_mutex_unlock_iothread();
+    }
+}
+
 void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
                              void *arg)
 {
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 2/4] target/riscv: Add Smrnmi CSRs.
  2023-05-22 13:11 [PATCH v3 0/4] target/riscv: Add Smrnmi support Tommy Wu
  2023-05-22 13:11 ` [PATCH v3 1/4] target/riscv: Add Smrnmi cpu extension Tommy Wu
@ 2023-05-22 13:11 ` Tommy Wu
  2023-05-25 12:30   ` Daniel Henrique Barboza
  2023-05-22 13:11 ` [PATCH v3 3/4] target/riscv: Handle Smrnmi interrupt and exception Tommy Wu
  2023-05-22 13:11 ` [PATCH v3 4/4] target/riscv: Add Smrnmi mnret instruction Tommy Wu
  3 siblings, 1 reply; 10+ messages in thread
From: Tommy Wu @ 2023-05-22 13:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv
  Cc: frank.chang, palmer, alistair.francis, bin.meng, liweiwei,
	dbarboza, zhiwei_liu, richard.henderson, Tommy Wu

Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
---
 target/riscv/cpu.c      |  5 +++
 target/riscv/cpu.h      |  4 ++
 target/riscv/cpu_bits.h | 11 ++++++
 target/riscv/csr.c      | 82 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 39b74569b1..1b645c5485 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -810,6 +810,11 @@ static void riscv_cpu_reset_hold(Object *obj)
         riscv_trigger_init(env);
     }
 
+    if (cpu->cfg.ext_smrnmi) {
+        env->rnmip = 0;
+        env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false);
+    }
+
     if (kvm_enabled()) {
         kvm_riscv_reset_vcpu(cpu);
     }
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6c14b93cb5..f44fd95f16 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -368,6 +368,10 @@ struct CPUArchState {
     uint64_t kvm_timer_frequency;
 
     /* RNMI */
+    target_ulong mnscratch;
+    target_ulong mnepc;
+    target_ulong mncause; /* mncause without bit XLEN-1 set to 1 */
+    target_ulong mnstatus;
     target_ulong rnmip;
     uint64_t rnmi_irqvec;
     uint64_t rnmi_excpvec;
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 7cb43b88f3..d7bd4538ab 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -355,6 +355,12 @@
 #define CSR_PMPADDR14       0x3be
 #define CSR_PMPADDR15       0x3bf
 
+/* RNMI */
+#define CSR_MNSCRATCH       0x740
+#define CSR_MNEPC           0x741
+#define CSR_MNCAUSE         0x742
+#define CSR_MNSTATUS        0x744
+
 /* Debug/Trace Registers (shared with Debug Mode) */
 #define CSR_TSELECT         0x7a0
 #define CSR_TDATA1          0x7a1
@@ -624,6 +630,11 @@ typedef enum {
 #define SATP64_ASID         0x0FFFF00000000000ULL
 #define SATP64_PPN          0x00000FFFFFFFFFFFULL
 
+/* RNMI mnstatus CSR mask */
+#define MNSTATUS_NMIE       0x00000008
+#define MNSTATUS_MNPV       0x00000080
+#define MNSTATUS_MNPP       0x00001800
+
 /* VM modes (satp.mode) privileged ISA 1.10 */
 #define VM_1_10_MBARE       0
 #define VM_1_10_SV32        1
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 4451bd1263..a1d39fc116 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -536,6 +536,18 @@ static RISCVException debug(CPURISCVState *env, int csrno)
 
     return RISCV_EXCP_ILLEGAL_INST;
 }
+
+static RISCVException rnmi(CPURISCVState *env, int csrno)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+
+    if (cpu->cfg.ext_smrnmi) {
+        return RISCV_EXCP_NONE;
+    }
+
+    return RISCV_EXCP_ILLEGAL_INST;
+}
+
 #endif
 
 static RISCVException seed(CPURISCVState *env, int csrno)
@@ -2336,6 +2348,66 @@ static RISCVException rmw_miph(CPURISCVState *env, int csrno,
     return ret;
 }
 
+static int read_mnscratch(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mnscratch;
+    return RISCV_EXCP_NONE;
+}
+
+static int write_mnscratch(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mnscratch = val;
+    return RISCV_EXCP_NONE;
+}
+
+static int read_mnepc(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mnepc;
+    return RISCV_EXCP_NONE;
+}
+
+static int write_mnepc(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mnepc = val;
+    return RISCV_EXCP_NONE;
+}
+
+static int read_mncause(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mncause;
+    return RISCV_EXCP_NONE;
+}
+
+static int write_mncause(CPURISCVState *env, int csrno, target_ulong val)
+{
+    env->mncause = val;
+    return RISCV_EXCP_NONE;
+}
+
+static int read_mnstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    *val = env->mnstatus;
+    return RISCV_EXCP_NONE;
+}
+
+static int write_mnstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+    target_ulong mask = (MNSTATUS_NMIE | MNSTATUS_MNPP);
+
+    if (riscv_has_ext(env, RVH)) {
+        /* Flush tlb on mnstatus fields that affect VM. */
+        if ((val ^ env->mnstatus) & MNSTATUS_MNPV) {
+            tlb_flush(env_cpu(env));
+        }
+
+        mask |= MNSTATUS_MNPV;
+    }
+
+    /* mnstatus.mnie can only be cleared by hardware. */
+    env->mnstatus = (env->mnstatus & MNSTATUS_NMIE) | (val & mask);
+    return RISCV_EXCP_NONE;
+}
+
 /* Supervisor Trap Setup */
 static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno,
                                         Int128 *val)
@@ -4204,6 +4276,16 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
                         write_sstateen_1_3,
                         .min_priv_ver = PRIV_VERSION_1_12_0 },
 
+    /* RNMI */
+    [CSR_MNSCRATCH] = { "mnscratch", rnmi, read_mnscratch, write_mnscratch,
+                        .min_priv_ver = PRIV_VERSION_1_12_0               },
+    [CSR_MNEPC]     = { "mnepc",     rnmi, read_mnepc,     write_mnepc,
+                        .min_priv_ver = PRIV_VERSION_1_12_0               },
+    [CSR_MNCAUSE]   = { "mncause",   rnmi, read_mncause,   write_mncause,
+                        .min_priv_ver = PRIV_VERSION_1_12_0               },
+    [CSR_MNSTATUS]  = { "mnstatus",  rnmi, read_mnstatus,  write_mnstatus,
+                        .min_priv_ver = PRIV_VERSION_1_12_0               },
+
     /* Supervisor Trap Setup */
     [CSR_SSTATUS]    = { "sstatus",    smode, read_sstatus,    write_sstatus,
                          NULL,                read_sstatus_i128              },
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 3/4] target/riscv: Handle Smrnmi interrupt and exception.
  2023-05-22 13:11 [PATCH v3 0/4] target/riscv: Add Smrnmi support Tommy Wu
  2023-05-22 13:11 ` [PATCH v3 1/4] target/riscv: Add Smrnmi cpu extension Tommy Wu
  2023-05-22 13:11 ` [PATCH v3 2/4] target/riscv: Add Smrnmi CSRs Tommy Wu
@ 2023-05-22 13:11 ` Tommy Wu
  2023-05-25 12:41   ` Daniel Henrique Barboza
  2023-05-22 13:11 ` [PATCH v3 4/4] target/riscv: Add Smrnmi mnret instruction Tommy Wu
  3 siblings, 1 reply; 10+ messages in thread
From: Tommy Wu @ 2023-05-22 13:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv
  Cc: frank.chang, palmer, alistair.francis, bin.meng, liweiwei,
	dbarboza, zhiwei_liu, richard.henderson, Tommy Wu

Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
---
 target/riscv/cpu_helper.c | 60 +++++++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index cc7898f103..7bdea0d2ca 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -405,6 +405,19 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
     int virq;
     uint64_t irqs, pending, mie, hsie, vsie;
+    RISCVCPU *cpu = env_archcpu(env);
+
+    /* Priority: RNMI > Other interrupt. */
+    if (cpu->cfg.ext_smrnmi) {
+        /* If mnstatus.NMIE == 0, all interrupts are disabled. */
+        if (!get_field(env->mnstatus, MNSTATUS_NMIE)) {
+            return RISCV_EXCP_NONE;
+        }
+
+        if (env->rnmip) {
+            return ctz64(env->rnmip); /* since non-zero */
+        }
+    }
 
     /* Determine interrupt enable state of all privilege modes */
     if (env->virt_enabled) {
@@ -451,7 +464,9 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 
 bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 {
-    if (interrupt_request & CPU_INTERRUPT_HARD) {
+    uint32_t mask = CPU_INTERRUPT_HARD | CPU_INTERRUPT_RNMI;
+
+    if (interrupt_request & mask) {
         RISCVCPU *cpu = RISCV_CPU(cs);
         CPURISCVState *env = &cpu->env;
         int interruptno = riscv_cpu_local_irq_pending(env);
@@ -1613,6 +1628,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     CPURISCVState *env = &cpu->env;
     bool write_gva = false;
     uint64_t s;
+    int mode;
 
     /*
      * cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
@@ -1625,6 +1641,22 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     target_ulong tinst = 0;
     target_ulong htval = 0;
     target_ulong mtval2 = 0;
+    bool nmi_execp = false;
+
+    if (cpu->cfg.ext_smrnmi) {
+        if (env->rnmip && async) {
+            env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false);
+            env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPV,
+                                      env->virt_enabled);
+            env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPP,
+                                      env->priv);
+            env->mncause = cause | ((target_ulong)1U << (TARGET_LONG_BITS - 1));
+            env->mnepc = env->pc;
+            env->pc = env->rnmi_irqvec;
+            riscv_cpu_set_mode(env, PRV_M);
+            goto handled;
+        }
+    }
 
     if  (cause == RISCV_EXCP_SEMIHOST) {
         do_common_semihosting(cs);
@@ -1711,8 +1743,20 @@ void riscv_cpu_do_interrupt(CPUState *cs)
                   __func__, env->mhartid, async, cause, env->pc, tval,
                   riscv_cpu_get_trap_name(cause, async));
 
-    if (env->priv <= PRV_S &&
-            cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
+    mode = env->priv <= PRV_S &&
+        cause < TARGET_LONG_BITS && ((deleg >> cause) & 1) ? PRV_S : PRV_M;
+
+    /*
+     * If the hart encounters an exception while executing in M-mode,
+     * with the mnstatus.NMIE bit clear, the program counter is set to
+     * the RNMI exception trap handler address.
+     */
+    nmi_execp = cpu->cfg.ext_smrnmi &&
+                !get_field(env->mnstatus, MNSTATUS_NMIE) &&
+                !async &&
+                mode == PRV_M;
+
+    if (mode == PRV_S) {
         /* handle the trap in S-mode */
         if (riscv_has_ext(env, RVH)) {
             uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
@@ -1787,8 +1831,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
         env->mtval = tval;
         env->mtval2 = mtval2;
         env->mtinst = tinst;
-        env->pc = (env->mtvec >> 2 << 2) +
-                  ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+        if (cpu->cfg.ext_smrnmi && nmi_execp) {
+            env->pc = env->rnmi_excpvec;
+        } else {
+            env->pc = (env->mtvec >> 2 << 2) +
+                      ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+        }
         riscv_cpu_set_mode(env, PRV_M);
     }
 
@@ -1801,6 +1849,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
     env->two_stage_lookup = false;
     env->two_stage_indirect_lookup = false;
+
+handled:
 #endif
     cs->exception_index = RISCV_EXCP_NONE; /* mark handled to qemu */
 }
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 4/4] target/riscv: Add Smrnmi mnret instruction.
  2023-05-22 13:11 [PATCH v3 0/4] target/riscv: Add Smrnmi support Tommy Wu
                   ` (2 preceding siblings ...)
  2023-05-22 13:11 ` [PATCH v3 3/4] target/riscv: Handle Smrnmi interrupt and exception Tommy Wu
@ 2023-05-22 13:11 ` Tommy Wu
  2023-05-25 12:50   ` Daniel Henrique Barboza
  3 siblings, 1 reply; 10+ messages in thread
From: Tommy Wu @ 2023-05-22 13:11 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv
  Cc: frank.chang, palmer, alistair.francis, bin.meng, liweiwei,
	dbarboza, zhiwei_liu, richard.henderson, Tommy Wu

Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
---
 target/riscv/helper.h                         |  1 +
 target/riscv/insn32.decode                    |  3 ++
 .../riscv/insn_trans/trans_privileged.c.inc   | 12 +++++
 target/riscv/op_helper.c                      | 51 +++++++++++++++++++
 4 files changed, 67 insertions(+)

diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 98e97810fd..00f1032086 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -112,6 +112,7 @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_1(sret, tl, env)
 DEF_HELPER_1(mret, tl, env)
+DEF_HELPER_1(mnret, tl, env)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(tlb_flush, void, env)
 DEF_HELPER_1(tlb_flush_all, void, env)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 73d5d1b045..e0698f9dfb 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -111,6 +111,9 @@ wfi         0001000    00101 00000 000 00000 1110011
 sfence_vma  0001001    ..... ..... 000 00000 1110011 @sfence_vma
 sfence_vm   0001000    00100 ..... 000 00000 1110011 @sfence_vm
 
+# *** NMI ***
+mnret       0111000    00010 00000 000 00000 1110011
+
 # *** RV32I Base Instruction Set ***
 lui      ....................       ..... 0110111 @u
 auipc    ....................       ..... 0010111 @u
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
index 7c2837194c..0c1c2db5c6 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -108,6 +108,18 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
 #endif
 }
 
+static bool trans_mnret(DisasContext *ctx, arg_mnret *a)
+{
+#ifndef CONFIG_USER_ONLY
+    gen_helper_mnret(cpu_pc, cpu_env);
+    tcg_gen_exit_tb(NULL, 0); /* no chaining */
+    ctx->base.is_jmp = DISAS_NORETURN;
+    return true;
+#else
+    return false;
+#endif
+}
+
 static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
 {
 #ifndef CONFIG_USER_ONLY
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index f563dc3981..2de3f102b5 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -359,6 +359,57 @@ target_ulong helper_mret(CPURISCVState *env)
     return retpc;
 }
 
+target_ulong helper_mnret(CPURISCVState *env)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+
+    if (!cpu->cfg.ext_smrnmi) {
+        /* RNMI feature is not presented. */
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+    }
+
+    if (!(env->priv >= PRV_M)) {
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+    }
+
+    /* Get return PC from mnepc CSR. */
+    target_ulong retpc = env->mnepc;
+    if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
+        riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
+    }
+
+    /* Get previous privilege level from mnstatus CSR. */
+    target_ulong prev_priv = get_field(env->mnstatus, MNSTATUS_MNPP);
+
+    if (cpu->cfg.pmp &&
+        !pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
+        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+    }
+
+    riscv_cpu_set_mode(env, prev_priv);
+    env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, true);
+
+    target_ulong prev_virt = get_field(env->mnstatus, MNSTATUS_MNPV);
+
+    /*
+     * If MNRET changes the privilege mode to a mode
+     * less privileged than M, it also sets mstatus.MPRV to 0.
+     */
+    if (prev_priv < PRV_M) {
+        env->mstatus = set_field(env->mstatus, MSTATUS_MPRV, false);
+    }
+
+    if (riscv_has_ext(env, RVH)) {
+        if (prev_virt) {
+            riscv_cpu_swap_hypervisor_regs(env);
+        }
+
+        riscv_cpu_set_virt_enabled(env, prev_virt);
+    }
+
+    return retpc;
+}
+
 void helper_wfi(CPURISCVState *env)
 {
     CPUState *cs = env_cpu(env);
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 1/4] target/riscv: Add Smrnmi cpu extension.
  2023-05-22 13:11 ` [PATCH v3 1/4] target/riscv: Add Smrnmi cpu extension Tommy Wu
@ 2023-05-25 12:29   ` Daniel Henrique Barboza
  2023-06-08  7:12     ` Tommy Wu
  0 siblings, 1 reply; 10+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-25 12:29 UTC (permalink / raw)
  To: Tommy Wu, qemu-devel, qemu-riscv
  Cc: frank.chang, palmer, alistair.francis, bin.meng, liweiwei,
	zhiwei_liu, richard.henderson



On 5/22/23 10:11, Tommy Wu wrote:
> Signed-off-by: Frank Chang <frank.chang@sifive.com>
> Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
> ---
>   hw/riscv/riscv_hart.c         | 21 +++++++++++++++++++++
>   include/hw/riscv/riscv_hart.h |  4 ++++
>   target/riscv/cpu.c            | 14 ++++++++++++++
>   target/riscv/cpu.h            |  7 +++++++
>   target/riscv/cpu_bits.h       | 12 ++++++++++++
>   target/riscv/cpu_helper.c     | 24 ++++++++++++++++++++++++
>   6 files changed, 82 insertions(+)
> 
> diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
> index 613ea2aaa0..eac18f8c29 100644
> --- a/hw/riscv/riscv_hart.c
> +++ b/hw/riscv/riscv_hart.c
> @@ -33,6 +33,12 @@ static Property riscv_harts_props[] = {
>       DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type),
>       DEFINE_PROP_UINT64("resetvec", RISCVHartArrayState, resetvec,
>                          DEFAULT_RSTVEC),
> +    DEFINE_PROP_ARRAY("rnmi-interrupt-vector", RISCVHartArrayState,
> +                      num_rnmi_irqvec, rnmi_irqvec, qdev_prop_uint64,
> +                      uint64_t),
> +    DEFINE_PROP_ARRAY("rnmi-exception-vector", RISCVHartArrayState,
> +                      num_rnmi_excpvec, rnmi_excpvec, qdev_prop_uint64,
> +                      uint64_t),
>       DEFINE_PROP_END_OF_LIST(),
>   };
>   
> @@ -47,6 +53,21 @@ static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
>   {
>       object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], cpu_type);
>       qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec", s->resetvec);
> +
> +    if (s->harts[idx].cfg.ext_smrnmi) {
> +        if (s->rnmi_irqvec) {
> +            qdev_prop_set_uint64(DEVICE(&s->harts[idx]),
> +                                 "rnmi-interrupt-vector",
> +                                 s->rnmi_irqvec[idx]);
> +        }
> +
> +        if (s->rnmi_excpvec) {
> +            qdev_prop_set_uint64(DEVICE(&s->harts[idx]),
> +                                 "rnmi-exception-vector",
> +                                 s->rnmi_excpvec[idx]);
> +        }
> +    }
> +
>       s->harts[idx].env.mhartid = s->hartid_base + idx;
>       qemu_register_reset(riscv_harts_cpu_reset, &s->harts[idx]);
>       return qdev_realize(DEVICE(&s->harts[idx]), NULL, errp);
> diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
> index bbc21cdc9a..99c0ac5009 100644
> --- a/include/hw/riscv/riscv_hart.h
> +++ b/include/hw/riscv/riscv_hart.h
> @@ -38,6 +38,10 @@ struct RISCVHartArrayState {
>       uint32_t hartid_base;
>       char *cpu_type;
>       uint64_t resetvec;
> +    uint32_t num_rnmi_irqvec;
> +    uint64_t *rnmi_irqvec;
> +    uint32_t num_rnmi_excpvec;
> +    uint64_t *rnmi_excpvec;
>       RISCVCPU *harts;
>   };
>   
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index db0875fb43..39b74569b1 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -119,6 +119,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
>       ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
>       ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
>       ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
> +    ISA_EXT_DATA_ENTRY(smrnmi, PRIV_VERSION_1_12_0, ext_smrnmi),
>       ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
>       ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
>       ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc),
> @@ -1404,6 +1405,12 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level)
>           g_assert_not_reached();
>       }
>   }
> +
> +static void riscv_cpu_set_nmi(void *opaque, int irq, int level)
> +{
> +    RISCVCPU *cpu = RISCV_CPU(opaque);
> +    riscv_cpu_set_rnmi(cpu, irq, level);

Minor commennt/nit: you can do:

> +    riscv_cpu_set_rnmi(RISCV_CPU(opaque), irq, level);

And avoid the extra 'cpu' pointer.


> +}
>   #endif /* CONFIG_USER_ONLY */
>   
>   static void riscv_cpu_init(Object *obj)
> @@ -1420,6 +1427,8 @@ static void riscv_cpu_init(Object *obj)
>   #ifndef CONFIG_USER_ONLY
>       qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
>                         IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
> +    qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_nmi,
> +                            "riscv.cpu.rnmi", RNMI_MAX);
>   #endif /* CONFIG_USER_ONLY */
>   }
>   
> @@ -1600,6 +1609,7 @@ static Property riscv_cpu_extensions[] = {
>       DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
>       DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
>       DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
> +    DEFINE_PROP_BOOL("x-smrnmi", RISCVCPU, cfg.ext_smrnmi, false),
>   
>       DEFINE_PROP_BOOL("x-zvfh", RISCVCPU, cfg.ext_zvfh, false),
>       DEFINE_PROP_BOOL("x-zvfhmin", RISCVCPU, cfg.ext_zvfhmin, false),
> @@ -1644,6 +1654,10 @@ static Property riscv_cpu_properties[] = {
>   
>       DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s, false),
>       DEFINE_PROP_BOOL("rvv_ma_all_1s", RISCVCPU, cfg.rvv_ma_all_1s, false),
> +    DEFINE_PROP_UINT64("rnmi-interrupt-vector", RISCVCPU, env.rnmi_irqvec,
> +                       DEFAULT_RNMI_IRQVEC),
> +    DEFINE_PROP_UINT64("rnmi-exception-vector", RISCVCPU, env.rnmi_excpvec,
> +                       DEFAULT_RNMI_EXCPVEC),
>   
>       /*
>        * write_misa() is marked as experimental for now so mark
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index de7e43126a..6c14b93cb5 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -366,6 +366,11 @@ struct CPUArchState {
>       uint64_t kvm_timer_compare;
>       uint64_t kvm_timer_state;
>       uint64_t kvm_timer_frequency;
> +
> +    /* RNMI */
> +    target_ulong rnmip;
> +    uint64_t rnmi_irqvec;
> +    uint64_t rnmi_excpvec;
>   };
>   
>   /*
> @@ -436,6 +441,7 @@ struct RISCVCPUConfig {
>       bool ext_smaia;
>       bool ext_ssaia;
>       bool ext_sscofpmf;
> +    bool ext_smrnmi;
>       bool rvv_ta_all_1s;
>       bool rvv_ma_all_1s;
>   
> @@ -562,6 +568,7 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
>   int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts);
>   uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask,
>                                 uint64_t value);
> +void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level);
>   #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
>   void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
>                                void *arg);
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 59f0ffd9e1..7cb43b88f3 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -659,6 +659,12 @@ typedef enum {
>   /* Default Reset Vector adress */
>   #define DEFAULT_RSTVEC      0x1000
>   
> +/* Default RNMI Interrupt Vector address */
> +#define DEFAULT_RNMI_IRQVEC     0x0
> +
> +/* Default RNMI Exception Vector address */
> +#define DEFAULT_RNMI_EXCPVEC    0x0
> +
>   /* Exception causes */
>   typedef enum RISCVException {
>       RISCV_EXCP_NONE = -1, /* sentinel value */
> @@ -705,6 +711,9 @@ typedef enum RISCVException {
>   #define IRQ_LOCAL_MAX                      16
>   #define IRQ_LOCAL_GUEST_MAX                (TARGET_LONG_BITS - 1)
>   
> +/* RNMI causes */
> +#define RNMI_MAX                           16
> +
>   /* mip masks */
>   #define MIP_USIP                           (1 << IRQ_U_SOFT)
>   #define MIP_SSIP                           (1 << IRQ_S_SOFT)
> @@ -896,6 +905,9 @@ typedef enum RISCVException {
>   #define MHPMEVENT_IDX_MASK                 0xFFFFF
>   #define MHPMEVENT_SSCOF_RESVD              16
>   
> +/* RISC-V-specific interrupt pending bits. */
> +#define CPU_INTERRUPT_RNMI                 CPU_INTERRUPT_TGT_EXT_0
> +
>   /* JVT CSR bits */
>   #define JVT_MODE                           0x3F
>   #define JVT_BASE                           (~0x3F)
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 57d04385f1..cc7898f103 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -635,6 +635,30 @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask,
>       return old;
>   }
>   
> +void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level)
> +{
> +    CPURISCVState *env = &cpu->env;
> +    CPUState *cs = CPU(cpu);
> +    bool locked = false;
> +
> +    if (!qemu_mutex_iothread_locked()) {
> +        locked = true;
> +        qemu_mutex_lock_iothread();
> +    }
> +
> +    if (level) {
> +        env->rnmip |= 1 << irq;
> +        cpu_interrupt(cs, CPU_INTERRUPT_RNMI);
> +    } else {
> +        env->rnmip &= ~(1 << irq);
> +        cpu_reset_interrupt(cs, CPU_INTERRUPT_RNMI);
> +    }
> +
> +    if (locked) {
> +        qemu_mutex_unlock_iothread();
> +    }


'locked' is not a good named for this flag because you guaranteed that the iothread
will always be locked at this point. Questions is whether you locked it yourself,
and then you need to unlock it, or if it was locked beforehand.

I suggest renaming 'locked' to 'release_lock' for clarity. Asumming you agree:


Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>





> +}
> +
>   void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
>                                void *arg)
>   {


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 2/4] target/riscv: Add Smrnmi CSRs.
  2023-05-22 13:11 ` [PATCH v3 2/4] target/riscv: Add Smrnmi CSRs Tommy Wu
@ 2023-05-25 12:30   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-25 12:30 UTC (permalink / raw)
  To: Tommy Wu, qemu-devel, qemu-riscv
  Cc: frank.chang, palmer, alistair.francis, bin.meng, liweiwei,
	zhiwei_liu, richard.henderson



On 5/22/23 10:11, Tommy Wu wrote:
> Signed-off-by: Frank Chang <frank.chang@sifive.com>
> Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
> ---

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

>   target/riscv/cpu.c      |  5 +++
>   target/riscv/cpu.h      |  4 ++
>   target/riscv/cpu_bits.h | 11 ++++++
>   target/riscv/csr.c      | 82 +++++++++++++++++++++++++++++++++++++++++
>   4 files changed, 102 insertions(+)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 39b74569b1..1b645c5485 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -810,6 +810,11 @@ static void riscv_cpu_reset_hold(Object *obj)
>           riscv_trigger_init(env);
>       }
>   
> +    if (cpu->cfg.ext_smrnmi) {
> +        env->rnmip = 0;
> +        env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false);
> +    }
> +
>       if (kvm_enabled()) {
>           kvm_riscv_reset_vcpu(cpu);
>       }
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 6c14b93cb5..f44fd95f16 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -368,6 +368,10 @@ struct CPUArchState {
>       uint64_t kvm_timer_frequency;
>   
>       /* RNMI */
> +    target_ulong mnscratch;
> +    target_ulong mnepc;
> +    target_ulong mncause; /* mncause without bit XLEN-1 set to 1 */
> +    target_ulong mnstatus;
>       target_ulong rnmip;
>       uint64_t rnmi_irqvec;
>       uint64_t rnmi_excpvec;
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 7cb43b88f3..d7bd4538ab 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -355,6 +355,12 @@
>   #define CSR_PMPADDR14       0x3be
>   #define CSR_PMPADDR15       0x3bf
>   
> +/* RNMI */
> +#define CSR_MNSCRATCH       0x740
> +#define CSR_MNEPC           0x741
> +#define CSR_MNCAUSE         0x742
> +#define CSR_MNSTATUS        0x744
> +
>   /* Debug/Trace Registers (shared with Debug Mode) */
>   #define CSR_TSELECT         0x7a0
>   #define CSR_TDATA1          0x7a1
> @@ -624,6 +630,11 @@ typedef enum {
>   #define SATP64_ASID         0x0FFFF00000000000ULL
>   #define SATP64_PPN          0x00000FFFFFFFFFFFULL
>   
> +/* RNMI mnstatus CSR mask */
> +#define MNSTATUS_NMIE       0x00000008
> +#define MNSTATUS_MNPV       0x00000080
> +#define MNSTATUS_MNPP       0x00001800
> +
>   /* VM modes (satp.mode) privileged ISA 1.10 */
>   #define VM_1_10_MBARE       0
>   #define VM_1_10_SV32        1
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 4451bd1263..a1d39fc116 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -536,6 +536,18 @@ static RISCVException debug(CPURISCVState *env, int csrno)
>   
>       return RISCV_EXCP_ILLEGAL_INST;
>   }
> +
> +static RISCVException rnmi(CPURISCVState *env, int csrno)
> +{
> +    RISCVCPU *cpu = env_archcpu(env);
> +
> +    if (cpu->cfg.ext_smrnmi) {
> +        return RISCV_EXCP_NONE;
> +    }
> +
> +    return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
>   #endif
>   
>   static RISCVException seed(CPURISCVState *env, int csrno)
> @@ -2336,6 +2348,66 @@ static RISCVException rmw_miph(CPURISCVState *env, int csrno,
>       return ret;
>   }
>   
> +static int read_mnscratch(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->mnscratch;
> +    return RISCV_EXCP_NONE;
> +}
> +
> +static int write_mnscratch(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->mnscratch = val;
> +    return RISCV_EXCP_NONE;
> +}
> +
> +static int read_mnepc(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->mnepc;
> +    return RISCV_EXCP_NONE;
> +}
> +
> +static int write_mnepc(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->mnepc = val;
> +    return RISCV_EXCP_NONE;
> +}
> +
> +static int read_mncause(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->mncause;
> +    return RISCV_EXCP_NONE;
> +}
> +
> +static int write_mncause(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    env->mncause = val;
> +    return RISCV_EXCP_NONE;
> +}
> +
> +static int read_mnstatus(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +    *val = env->mnstatus;
> +    return RISCV_EXCP_NONE;
> +}
> +
> +static int write_mnstatus(CPURISCVState *env, int csrno, target_ulong val)
> +{
> +    target_ulong mask = (MNSTATUS_NMIE | MNSTATUS_MNPP);
> +
> +    if (riscv_has_ext(env, RVH)) {
> +        /* Flush tlb on mnstatus fields that affect VM. */
> +        if ((val ^ env->mnstatus) & MNSTATUS_MNPV) {
> +            tlb_flush(env_cpu(env));
> +        }
> +
> +        mask |= MNSTATUS_MNPV;
> +    }
> +
> +    /* mnstatus.mnie can only be cleared by hardware. */
> +    env->mnstatus = (env->mnstatus & MNSTATUS_NMIE) | (val & mask);
> +    return RISCV_EXCP_NONE;
> +}
> +
>   /* Supervisor Trap Setup */
>   static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno,
>                                           Int128 *val)
> @@ -4204,6 +4276,16 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>                           write_sstateen_1_3,
>                           .min_priv_ver = PRIV_VERSION_1_12_0 },
>   
> +    /* RNMI */
> +    [CSR_MNSCRATCH] = { "mnscratch", rnmi, read_mnscratch, write_mnscratch,
> +                        .min_priv_ver = PRIV_VERSION_1_12_0               },
> +    [CSR_MNEPC]     = { "mnepc",     rnmi, read_mnepc,     write_mnepc,
> +                        .min_priv_ver = PRIV_VERSION_1_12_0               },
> +    [CSR_MNCAUSE]   = { "mncause",   rnmi, read_mncause,   write_mncause,
> +                        .min_priv_ver = PRIV_VERSION_1_12_0               },
> +    [CSR_MNSTATUS]  = { "mnstatus",  rnmi, read_mnstatus,  write_mnstatus,
> +                        .min_priv_ver = PRIV_VERSION_1_12_0               },
> +
>       /* Supervisor Trap Setup */
>       [CSR_SSTATUS]    = { "sstatus",    smode, read_sstatus,    write_sstatus,
>                            NULL,                read_sstatus_i128              },


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 3/4] target/riscv: Handle Smrnmi interrupt and exception.
  2023-05-22 13:11 ` [PATCH v3 3/4] target/riscv: Handle Smrnmi interrupt and exception Tommy Wu
@ 2023-05-25 12:41   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-25 12:41 UTC (permalink / raw)
  To: Tommy Wu, qemu-devel, qemu-riscv
  Cc: frank.chang, palmer, alistair.francis, bin.meng, liweiwei,
	zhiwei_liu, richard.henderson



On 5/22/23 10:11, Tommy Wu wrote:
> Signed-off-by: Frank Chang <frank.chang@sifive.com>
> Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
> ---
>   target/riscv/cpu_helper.c | 60 +++++++++++++++++++++++++++++++++++----
>   1 file changed, 55 insertions(+), 5 deletions(-)
> 
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index cc7898f103..7bdea0d2ca 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -405,6 +405,19 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
>   {
>       int virq;
>       uint64_t irqs, pending, mie, hsie, vsie;
> +    RISCVCPU *cpu = env_archcpu(env);
> +
> +    /* Priority: RNMI > Other interrupt. */
> +    if (cpu->cfg.ext_smrnmi) {

Since you're using "cpu" just to read a cfg flag you can use the 'riscv_cpu_cfg(env)'
inline to avoid a call to env_archcpu():

>       int virq;
>       uint64_t irqs, pending, mie, hsie, vsie;
> +
> +    /* Priority: RNMI > Other interrupt. */
> +    if (riscv_cpu_cfg(env)->ext_smrnmi) {


> +        /* If mnstatus.NMIE == 0, all interrupts are disabled. */
> +        if (!get_field(env->mnstatus, MNSTATUS_NMIE)) {
> +            return RISCV_EXCP_NONE;
> +        }
> +
> +        if (env->rnmip) {
> +            return ctz64(env->rnmip); /* since non-zero */
> +        }
> +    }
>   
>       /* Determine interrupt enable state of all privilege modes */
>       if (env->virt_enabled) {
> @@ -451,7 +464,9 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
>   
>   bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
>   {
> -    if (interrupt_request & CPU_INTERRUPT_HARD) {
> +    uint32_t mask = CPU_INTERRUPT_HARD | CPU_INTERRUPT_RNMI;
> +
> +    if (interrupt_request & mask) {
>           RISCVCPU *cpu = RISCV_CPU(cs);
>           CPURISCVState *env = &cpu->env;
>           int interruptno = riscv_cpu_local_irq_pending(env);
> @@ -1613,6 +1628,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>       CPURISCVState *env = &cpu->env;
>       bool write_gva = false;
>       uint64_t s;
> +    int mode;
>   
>       /*
>        * cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
> @@ -1625,6 +1641,22 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>       target_ulong tinst = 0;
>       target_ulong htval = 0;
>       target_ulong mtval2 = 0;
> +    bool nmi_execp = false;
> +
> +    if (cpu->cfg.ext_smrnmi) {
> +        if (env->rnmip && async) {

You're not using an 'else' clause for this if, so I suggest avoiding this nested
'if' by doing everything in the same conditional:

> +    if (cpu->cfg.ext_smrnmi && env->rnmip && async) {

As a bonus you'll also avoid an extra indent level.


Thanks,


Daniel



> +            env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, false);
> +            env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPV,
> +                                      env->virt_enabled);
> +            env->mnstatus = set_field(env->mnstatus, MNSTATUS_MNPP,
> +                                      env->priv);
> +            env->mncause = cause | ((target_ulong)1U << (TARGET_LONG_BITS - 1));
> +            env->mnepc = env->pc;
> +            env->pc = env->rnmi_irqvec;
> +            riscv_cpu_set_mode(env, PRV_M);
> +            goto handled;
> +        }
> +    }
>   
>       if  (cause == RISCV_EXCP_SEMIHOST) {
>           do_common_semihosting(cs);
> @@ -1711,8 +1743,20 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>                     __func__, env->mhartid, async, cause, env->pc, tval,
>                     riscv_cpu_get_trap_name(cause, async));
>   
> -    if (env->priv <= PRV_S &&
> -            cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
> +    mode = env->priv <= PRV_S &&
> +        cause < TARGET_LONG_BITS && ((deleg >> cause) & 1) ? PRV_S : PRV_M;
> +
> +    /*
> +     * If the hart encounters an exception while executing in M-mode,
> +     * with the mnstatus.NMIE bit clear, the program counter is set to
> +     * the RNMI exception trap handler address.
> +     */
> +    nmi_execp = cpu->cfg.ext_smrnmi &&
> +                !get_field(env->mnstatus, MNSTATUS_NMIE) &&
> +                !async &&
> +                mode == PRV_M;
> +
> +    if (mode == PRV_S) {
>           /* handle the trap in S-mode */
>           if (riscv_has_ext(env, RVH)) {
>               uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
> @@ -1787,8 +1831,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>           env->mtval = tval;
>           env->mtval2 = mtval2;
>           env->mtinst = tinst;
> -        env->pc = (env->mtvec >> 2 << 2) +
> -                  ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
> +        if (cpu->cfg.ext_smrnmi && nmi_execp) {
> +            env->pc = env->rnmi_excpvec;
> +        } else {
> +            env->pc = (env->mtvec >> 2 << 2) +
> +                      ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
> +        }
>           riscv_cpu_set_mode(env, PRV_M);
>       }
>   
> @@ -1801,6 +1849,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>   
>       env->two_stage_lookup = false;
>       env->two_stage_indirect_lookup = false;
> +
> +handled:
>   #endif
>       cs->exception_index = RISCV_EXCP_NONE; /* mark handled to qemu */
>   }


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 4/4] target/riscv: Add Smrnmi mnret instruction.
  2023-05-22 13:11 ` [PATCH v3 4/4] target/riscv: Add Smrnmi mnret instruction Tommy Wu
@ 2023-05-25 12:50   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Henrique Barboza @ 2023-05-25 12:50 UTC (permalink / raw)
  To: Tommy Wu, qemu-devel, qemu-riscv
  Cc: frank.chang, palmer, alistair.francis, bin.meng, liweiwei,
	zhiwei_liu, richard.henderson



On 5/22/23 10:11, Tommy Wu wrote:
> Signed-off-by: Frank Chang <frank.chang@sifive.com>
> Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
> ---
>   target/riscv/helper.h                         |  1 +
>   target/riscv/insn32.decode                    |  3 ++
>   .../riscv/insn_trans/trans_privileged.c.inc   | 12 +++++
>   target/riscv/op_helper.c                      | 51 +++++++++++++++++++
>   4 files changed, 67 insertions(+)
> 
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index 98e97810fd..00f1032086 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -112,6 +112,7 @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
>   #ifndef CONFIG_USER_ONLY
>   DEF_HELPER_1(sret, tl, env)
>   DEF_HELPER_1(mret, tl, env)
> +DEF_HELPER_1(mnret, tl, env)
>   DEF_HELPER_1(wfi, void, env)
>   DEF_HELPER_1(tlb_flush, void, env)
>   DEF_HELPER_1(tlb_flush_all, void, env)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index 73d5d1b045..e0698f9dfb 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -111,6 +111,9 @@ wfi         0001000    00101 00000 000 00000 1110011
>   sfence_vma  0001001    ..... ..... 000 00000 1110011 @sfence_vma
>   sfence_vm   0001000    00100 ..... 000 00000 1110011 @sfence_vm
>   
> +# *** NMI ***
> +mnret       0111000    00010 00000 000 00000 1110011
> +
>   # *** RV32I Base Instruction Set ***
>   lui      ....................       ..... 0110111 @u
>   auipc    ....................       ..... 0010111 @u
> diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
> index 7c2837194c..0c1c2db5c6 100644
> --- a/target/riscv/insn_trans/trans_privileged.c.inc
> +++ b/target/riscv/insn_trans/trans_privileged.c.inc
> @@ -108,6 +108,18 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
>   #endif
>   }
>   
> +static bool trans_mnret(DisasContext *ctx, arg_mnret *a)
> +{
> +#ifndef CONFIG_USER_ONLY
> +    gen_helper_mnret(cpu_pc, cpu_env);
> +    tcg_gen_exit_tb(NULL, 0); /* no chaining */
> +    ctx->base.is_jmp = DISAS_NORETURN;
> +    return true;
> +#else
> +    return false;
> +#endif
> +}
> +
>   static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
>   {
>   #ifndef CONFIG_USER_ONLY
> diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
> index f563dc3981..2de3f102b5 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -359,6 +359,57 @@ target_ulong helper_mret(CPURISCVState *env)
>       return retpc;
>   }
>   
> +target_ulong helper_mnret(CPURISCVState *env)
> +{
> +    RISCVCPU *cpu = env_archcpu(env);

You're not using 'cpu' for anything other than reading cfg flags, so you can use the
riscv_cpu_cfg(env) inline nd avoid an env_archcpu() to get the 'cpu' pointer:

> +
> +    if (!cpu->cfg.ext_smrnmi) {

Here:

       if (!riscv_cpu_cfg(env)->ext_smrnmi) {



> +        /* RNMI feature is not presented. */
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +    }
> +
> +    if (!(env->priv >= PRV_M)) {
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +    }
> +
> +    /* Get return PC from mnepc CSR. */
> +    target_ulong retpc = env->mnepc;
> +    if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
> +        riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> +    }
> +
> +    /* Get previous privilege level from mnstatus CSR. */
> +    target_ulong prev_priv = get_field(env->mnstatus, MNSTATUS_MNPP);
> +
> +    if (cpu->cfg.pmp &&

And here:

     if (riscv_cpu_cfg(env)->pmp &&



Everything else LGTM.



Daniel

> +        !pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
> +        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> +    }
> +
> +    riscv_cpu_set_mode(env, prev_priv);
> +    env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, true);
> +
> +    target_ulong prev_virt = get_field(env->mnstatus, MNSTATUS_MNPV);
> +
> +    /*
> +     * If MNRET changes the privilege mode to a mode
> +     * less privileged than M, it also sets mstatus.MPRV to 0.
> +     */
> +    if (prev_priv < PRV_M) {
> +        env->mstatus = set_field(env->mstatus, MSTATUS_MPRV, false);
> +    }
> +
> +    if (riscv_has_ext(env, RVH)) {
> +        if (prev_virt) {
> +            riscv_cpu_swap_hypervisor_regs(env);
> +        }
> +
> +        riscv_cpu_set_virt_enabled(env, prev_virt);
> +    }
> +
> +    return retpc;
> +}
> +
>   void helper_wfi(CPURISCVState *env)
>   {
>       CPUState *cs = env_cpu(env);


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 1/4] target/riscv: Add Smrnmi cpu extension.
  2023-05-25 12:29   ` Daniel Henrique Barboza
@ 2023-06-08  7:12     ` Tommy Wu
  0 siblings, 0 replies; 10+ messages in thread
From: Tommy Wu @ 2023-06-08  7:12 UTC (permalink / raw)
  To: Daniel Henrique Barboza
  Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
	bin.meng, liweiwei, zhiwei_liu, richard.henderson

[-- Attachment #1: Type: text/plain, Size: 10336 bytes --]

Hi  Daniel,
Thanks for all the suggestions ! I'll send patch v4 and fix all the issues.

On Thu, May 25, 2023 at 8:29 PM Daniel Henrique Barboza <
dbarboza@ventanamicro.com> wrote:

>
>
> On 5/22/23 10:11, Tommy Wu wrote:
> > Signed-off-by: Frank Chang <frank.chang@sifive.com>
> > Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
> > ---
> >   hw/riscv/riscv_hart.c         | 21 +++++++++++++++++++++
> >   include/hw/riscv/riscv_hart.h |  4 ++++
> >   target/riscv/cpu.c            | 14 ++++++++++++++
> >   target/riscv/cpu.h            |  7 +++++++
> >   target/riscv/cpu_bits.h       | 12 ++++++++++++
> >   target/riscv/cpu_helper.c     | 24 ++++++++++++++++++++++++
> >   6 files changed, 82 insertions(+)
> >
> > diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
> > index 613ea2aaa0..eac18f8c29 100644
> > --- a/hw/riscv/riscv_hart.c
> > +++ b/hw/riscv/riscv_hart.c
> > @@ -33,6 +33,12 @@ static Property riscv_harts_props[] = {
> >       DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type),
> >       DEFINE_PROP_UINT64("resetvec", RISCVHartArrayState, resetvec,
> >                          DEFAULT_RSTVEC),
> > +    DEFINE_PROP_ARRAY("rnmi-interrupt-vector", RISCVHartArrayState,
> > +                      num_rnmi_irqvec, rnmi_irqvec, qdev_prop_uint64,
> > +                      uint64_t),
> > +    DEFINE_PROP_ARRAY("rnmi-exception-vector", RISCVHartArrayState,
> > +                      num_rnmi_excpvec, rnmi_excpvec, qdev_prop_uint64,
> > +                      uint64_t),
> >       DEFINE_PROP_END_OF_LIST(),
> >   };
> >
> > @@ -47,6 +53,21 @@ static bool riscv_hart_realize(RISCVHartArrayState
> *s, int idx,
> >   {
> >       object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx],
> cpu_type);
> >       qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec",
> s->resetvec);
> > +
> > +    if (s->harts[idx].cfg.ext_smrnmi) {
> > +        if (s->rnmi_irqvec) {
> > +            qdev_prop_set_uint64(DEVICE(&s->harts[idx]),
> > +                                 "rnmi-interrupt-vector",
> > +                                 s->rnmi_irqvec[idx]);
> > +        }
> > +
> > +        if (s->rnmi_excpvec) {
> > +            qdev_prop_set_uint64(DEVICE(&s->harts[idx]),
> > +                                 "rnmi-exception-vector",
> > +                                 s->rnmi_excpvec[idx]);
> > +        }
> > +    }
> > +
> >       s->harts[idx].env.mhartid = s->hartid_base + idx;
> >       qemu_register_reset(riscv_harts_cpu_reset, &s->harts[idx]);
> >       return qdev_realize(DEVICE(&s->harts[idx]), NULL, errp);
> > diff --git a/include/hw/riscv/riscv_hart.h
> b/include/hw/riscv/riscv_hart.h
> > index bbc21cdc9a..99c0ac5009 100644
> > --- a/include/hw/riscv/riscv_hart.h
> > +++ b/include/hw/riscv/riscv_hart.h
> > @@ -38,6 +38,10 @@ struct RISCVHartArrayState {
> >       uint32_t hartid_base;
> >       char *cpu_type;
> >       uint64_t resetvec;
> > +    uint32_t num_rnmi_irqvec;
> > +    uint64_t *rnmi_irqvec;
> > +    uint32_t num_rnmi_excpvec;
> > +    uint64_t *rnmi_excpvec;
> >       RISCVCPU *harts;
> >   };
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index db0875fb43..39b74569b1 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -119,6 +119,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
> >       ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
> >       ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
> >       ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
> > +    ISA_EXT_DATA_ENTRY(smrnmi, PRIV_VERSION_1_12_0, ext_smrnmi),
> >       ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
> >       ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
> >       ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc),
> > @@ -1404,6 +1405,12 @@ static void riscv_cpu_set_irq(void *opaque, int
> irq, int level)
> >           g_assert_not_reached();
> >       }
> >   }
> > +
> > +static void riscv_cpu_set_nmi(void *opaque, int irq, int level)
> > +{
> > +    RISCVCPU *cpu = RISCV_CPU(opaque);
> > +    riscv_cpu_set_rnmi(cpu, irq, level);
>
> Minor commennt/nit: you can do:
>
> > +    riscv_cpu_set_rnmi(RISCV_CPU(opaque), irq, level);
>
> And avoid the extra 'cpu' pointer.
>
>
> > +}
> >   #endif /* CONFIG_USER_ONLY */
> >
> >   static void riscv_cpu_init(Object *obj)
> > @@ -1420,6 +1427,8 @@ static void riscv_cpu_init(Object *obj)
> >   #ifndef CONFIG_USER_ONLY
> >       qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
> >                         IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
> > +    qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_nmi,
> > +                            "riscv.cpu.rnmi", RNMI_MAX);
> >   #endif /* CONFIG_USER_ONLY */
> >   }
> >
> > @@ -1600,6 +1609,7 @@ static Property riscv_cpu_extensions[] = {
> >       DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
> >       DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
> >       DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
> > +    DEFINE_PROP_BOOL("x-smrnmi", RISCVCPU, cfg.ext_smrnmi, false),
> >
> >       DEFINE_PROP_BOOL("x-zvfh", RISCVCPU, cfg.ext_zvfh, false),
> >       DEFINE_PROP_BOOL("x-zvfhmin", RISCVCPU, cfg.ext_zvfhmin, false),
> > @@ -1644,6 +1654,10 @@ static Property riscv_cpu_properties[] = {
> >
> >       DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s,
> false),
> >       DEFINE_PROP_BOOL("rvv_ma_all_1s", RISCVCPU, cfg.rvv_ma_all_1s,
> false),
> > +    DEFINE_PROP_UINT64("rnmi-interrupt-vector", RISCVCPU,
> env.rnmi_irqvec,
> > +                       DEFAULT_RNMI_IRQVEC),
> > +    DEFINE_PROP_UINT64("rnmi-exception-vector", RISCVCPU,
> env.rnmi_excpvec,
> > +                       DEFAULT_RNMI_EXCPVEC),
> >
> >       /*
> >        * write_misa() is marked as experimental for now so mark
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index de7e43126a..6c14b93cb5 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -366,6 +366,11 @@ struct CPUArchState {
> >       uint64_t kvm_timer_compare;
> >       uint64_t kvm_timer_state;
> >       uint64_t kvm_timer_frequency;
> > +
> > +    /* RNMI */
> > +    target_ulong rnmip;
> > +    uint64_t rnmi_irqvec;
> > +    uint64_t rnmi_excpvec;
> >   };
> >
> >   /*
> > @@ -436,6 +441,7 @@ struct RISCVCPUConfig {
> >       bool ext_smaia;
> >       bool ext_ssaia;
> >       bool ext_sscofpmf;
> > +    bool ext_smrnmi;
> >       bool rvv_ta_all_1s;
> >       bool rvv_ma_all_1s;
> >
> > @@ -562,6 +568,7 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState
> *env);
> >   int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts);
> >   uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask,
> >                                 uint64_t value);
> > +void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level);
> >   #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip
> value */
> >   void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void
> *),
> >                                void *arg);
> > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> > index 59f0ffd9e1..7cb43b88f3 100644
> > --- a/target/riscv/cpu_bits.h
> > +++ b/target/riscv/cpu_bits.h
> > @@ -659,6 +659,12 @@ typedef enum {
> >   /* Default Reset Vector adress */
> >   #define DEFAULT_RSTVEC      0x1000
> >
> > +/* Default RNMI Interrupt Vector address */
> > +#define DEFAULT_RNMI_IRQVEC     0x0
> > +
> > +/* Default RNMI Exception Vector address */
> > +#define DEFAULT_RNMI_EXCPVEC    0x0
> > +
> >   /* Exception causes */
> >   typedef enum RISCVException {
> >       RISCV_EXCP_NONE = -1, /* sentinel value */
> > @@ -705,6 +711,9 @@ typedef enum RISCVException {
> >   #define IRQ_LOCAL_MAX                      16
> >   #define IRQ_LOCAL_GUEST_MAX                (TARGET_LONG_BITS - 1)
> >
> > +/* RNMI causes */
> > +#define RNMI_MAX                           16
> > +
> >   /* mip masks */
> >   #define MIP_USIP                           (1 << IRQ_U_SOFT)
> >   #define MIP_SSIP                           (1 << IRQ_S_SOFT)
> > @@ -896,6 +905,9 @@ typedef enum RISCVException {
> >   #define MHPMEVENT_IDX_MASK                 0xFFFFF
> >   #define MHPMEVENT_SSCOF_RESVD              16
> >
> > +/* RISC-V-specific interrupt pending bits. */
> > +#define CPU_INTERRUPT_RNMI                 CPU_INTERRUPT_TGT_EXT_0
> > +
> >   /* JVT CSR bits */
> >   #define JVT_MODE                           0x3F
> >   #define JVT_BASE                           (~0x3F)
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > index 57d04385f1..cc7898f103 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -635,6 +635,30 @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env,
> uint64_t mask,
> >       return old;
> >   }
> >
> > +void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level)
> > +{
> > +    CPURISCVState *env = &cpu->env;
> > +    CPUState *cs = CPU(cpu);
> > +    bool locked = false;
> > +
> > +    if (!qemu_mutex_iothread_locked()) {
> > +        locked = true;
> > +        qemu_mutex_lock_iothread();
> > +    }
> > +
> > +    if (level) {
> > +        env->rnmip |= 1 << irq;
> > +        cpu_interrupt(cs, CPU_INTERRUPT_RNMI);
> > +    } else {
> > +        env->rnmip &= ~(1 << irq);
> > +        cpu_reset_interrupt(cs, CPU_INTERRUPT_RNMI);
> > +    }
> > +
> > +    if (locked) {
> > +        qemu_mutex_unlock_iothread();
> > +    }
>
>
> 'locked' is not a good named for this flag because you guaranteed that the
> iothread
> will always be locked at this point. Questions is whether you locked it
> yourself,
> and then you need to unlock it, or if it was locked beforehand.
>
> I suggest renaming 'locked' to 'release_lock' for clarity. Asumming you
> agree:
>
>
> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>
>
>
>
>
> > +}
> > +
> >   void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void
> *),
> >                                void *arg)
> >   {
>

[-- Attachment #2: Type: text/html, Size: 13077 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-06-08  7:13 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-22 13:11 [PATCH v3 0/4] target/riscv: Add Smrnmi support Tommy Wu
2023-05-22 13:11 ` [PATCH v3 1/4] target/riscv: Add Smrnmi cpu extension Tommy Wu
2023-05-25 12:29   ` Daniel Henrique Barboza
2023-06-08  7:12     ` Tommy Wu
2023-05-22 13:11 ` [PATCH v3 2/4] target/riscv: Add Smrnmi CSRs Tommy Wu
2023-05-25 12:30   ` Daniel Henrique Barboza
2023-05-22 13:11 ` [PATCH v3 3/4] target/riscv: Handle Smrnmi interrupt and exception Tommy Wu
2023-05-25 12:41   ` Daniel Henrique Barboza
2023-05-22 13:11 ` [PATCH v3 4/4] target/riscv: Add Smrnmi mnret instruction Tommy Wu
2023-05-25 12:50   ` Daniel Henrique Barboza

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).