* [PATCH v6 1/5] target/riscv: Add `ext_smrnmi` in the RISCVCPUConfig.
2024-09-02 7:13 [PATCH v6 0/5] target/riscv: Add Smrnmi support Tommy Wu
@ 2024-09-02 7:13 ` Tommy Wu
2024-09-02 7:13 ` [PATCH v6 2/5] target/riscv: Handle Smrnmi interrupt and exception Tommy Wu
` (5 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Tommy Wu @ 2024-09-02 7:13 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, dbarboza, ajones, Tommy Wu
The boolean variable `ext_smrnmi` is used to determine whether the
Smrnmi extension exists.
Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
target/riscv/cpu_cfg.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 8b272fb826..ae2a945b5f 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -125,6 +125,7 @@ struct RISCVCPUConfig {
bool ext_ssaia;
bool ext_sscofpmf;
bool ext_smepmp;
+ bool ext_smrnmi;
bool rvv_ta_all_1s;
bool rvv_ma_all_1s;
--
2.39.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v6 2/5] target/riscv: Handle Smrnmi interrupt and exception.
2024-09-02 7:13 [PATCH v6 0/5] target/riscv: Add Smrnmi support Tommy Wu
2024-09-02 7:13 ` [PATCH v6 1/5] target/riscv: Add `ext_smrnmi` in the RISCVCPUConfig Tommy Wu
@ 2024-09-02 7:13 ` Tommy Wu
2024-09-02 10:34 ` Clément Léger
2024-09-02 7:13 ` [PATCH v6 3/5] target/riscv: Add Smrnmi CSRs Tommy Wu
` (4 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Tommy Wu @ 2024-09-02 7:13 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, dbarboza, ajones, Tommy Wu
Because the RNMI interrupt trap handler address is implementation defined.
We add the `rnmi-interrupt-vector` and `rnmi-exception-vector` as the property
of the harts. It’s very easy for users to set the address based on their
expectation. This patch also adds the functionality to handle the RNMI signals.
Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
---
hw/riscv/riscv_hart.c | 18 ++++++++
include/hw/riscv/riscv_hart.h | 4 ++
target/riscv/cpu.c | 11 +++++
target/riscv/cpu.h | 6 +++
target/riscv/cpu_bits.h | 12 ++++++
target/riscv/cpu_helper.c | 80 ++++++++++++++++++++++++++++++++---
6 files changed, 126 insertions(+), 5 deletions(-)
diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
index 613ea2aaa0..b7d73f7a82 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,18 @@ 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 912b4a2682..a6ed73a195 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 a90808a3ba..2f64b3df22 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1309,6 +1309,11 @@ 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)
+{
+ riscv_cpu_set_rnmi(RISCV_CPU(opaque), irq, level);
+}
#endif /* CONFIG_USER_ONLY */
static bool riscv_cpu_is_dynamic(Object *cpu_obj)
@@ -1332,6 +1337,8 @@ static void riscv_cpu_init(Object *obj)
#ifndef CONFIG_USER_ONLY
qdev_init_gpio_in(DEVICE(obj), 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 */
general_user_opts = g_hash_table_new(g_str_hash, g_str_equal);
@@ -2681,6 +2688,10 @@ static Property riscv_cpu_properties[] = {
#ifndef CONFIG_USER_ONLY
DEFINE_PROP_UINT64("resetvec", RISCVCPU, env.resetvec, DEFAULT_RSTVEC),
+ 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),
#endif
DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 1619c3acb6..d8ad04ec31 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -472,6 +472,11 @@ struct CPUArchState {
uint64_t kvm_timer_state;
uint64_t kvm_timer_frequency;
#endif /* CONFIG_KVM */
+
+ /* RNMI */
+ target_ulong rnmip;
+ uint64_t rnmi_irqvec;
+ uint64_t rnmi_excpvec;
};
/*
@@ -568,6 +573,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);
void riscv_cpu_interrupt(CPURISCVState *env);
#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 *),
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 32b068f18a..e14b654c35 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -662,6 +662,12 @@ typedef enum {
/* Default Reset Vector address */
#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 */
@@ -711,6 +717,9 @@ typedef enum RISCVException {
/* -1 is due to bit zero of hgeip and hgeie being ROZ. */
#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)
@@ -942,6 +951,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 395a1d9140..9d0400035f 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -434,6 +434,18 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
uint64_t vsbits, irq_delegated;
int virq;
+ /* 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) {
mie = 1;
@@ -496,7 +508,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);
@@ -619,6 +633,30 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen)
env->geilen = geilen;
}
+void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level)
+{
+ CPURISCVState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
+ bool release_lock = false;
+
+ if (!bql_locked()) {
+ release_lock = true;
+ bql_lock();
+ }
+
+ 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 (release_lock) {
+ bql_unlock();
+ }
+}
+
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
{
CPURISCVState *env = &cpu->env;
@@ -1654,6 +1692,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
bool virt = env->virt_enabled;
bool write_gva = false;
uint64_t s;
+ int mode;
/*
* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
@@ -1670,6 +1709,20 @@ 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 && 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, virt);
+ return;
+ }
if (!async) {
/* set tval to badaddr for traps with address information */
@@ -1755,8 +1808,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 < 64 &&
- (((deleg >> cause) & 1) || s_injected || vs_injected)) {
+ mode = env->priv <= PRV_S && cause < 64 &&
+ (((deleg >> cause) & 1) || s_injected || vs_injected) ? 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;
@@ -1832,8 +1897,13 @@ 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, virt);
}
--
2.39.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v6 2/5] target/riscv: Handle Smrnmi interrupt and exception.
2024-09-02 7:13 ` [PATCH v6 2/5] target/riscv: Handle Smrnmi interrupt and exception Tommy Wu
@ 2024-09-02 10:34 ` Clément Léger
2024-09-02 12:49 ` Clément Léger
0 siblings, 1 reply; 15+ messages in thread
From: Clément Léger @ 2024-09-02 10:34 UTC (permalink / raw)
To: Tommy Wu, qemu-devel, qemu-riscv
Cc: frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, dbarboza, ajones
On 02/09/2024 09:13, Tommy Wu wrote:
> Because the RNMI interrupt trap handler address is implementation defined.
> We add the `rnmi-interrupt-vector` and `rnmi-exception-vector` as the property
> of the harts. It’s very easy for users to set the address based on their
> expectation. This patch also adds the functionality to handle the RNMI signals.
>
> Signed-off-by: Frank Chang <frank.chang@sifive.com>
> Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
> ---
> hw/riscv/riscv_hart.c | 18 ++++++++
> include/hw/riscv/riscv_hart.h | 4 ++
> target/riscv/cpu.c | 11 +++++
> target/riscv/cpu.h | 6 +++
> target/riscv/cpu_bits.h | 12 ++++++
> target/riscv/cpu_helper.c | 80 ++++++++++++++++++++++++++++++++---
> 6 files changed, 126 insertions(+), 5 deletions(-)
>
> diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
> index 613ea2aaa0..b7d73f7a82 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,18 @@ 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 912b4a2682..a6ed73a195 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 a90808a3ba..2f64b3df22 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1309,6 +1309,11 @@ 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)
> +{
> + riscv_cpu_set_rnmi(RISCV_CPU(opaque), irq, level);
> +}
> #endif /* CONFIG_USER_ONLY */
>
> static bool riscv_cpu_is_dynamic(Object *cpu_obj)
> @@ -1332,6 +1337,8 @@ static void riscv_cpu_init(Object *obj)
> #ifndef CONFIG_USER_ONLY
> qdev_init_gpio_in(DEVICE(obj), 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 */
>
> general_user_opts = g_hash_table_new(g_str_hash, g_str_equal);
> @@ -2681,6 +2688,10 @@ static Property riscv_cpu_properties[] = {
>
> #ifndef CONFIG_USER_ONLY
> DEFINE_PROP_UINT64("resetvec", RISCVCPU, env.resetvec, DEFAULT_RSTVEC),
> + 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),
> #endif
>
> DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false),
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 1619c3acb6..d8ad04ec31 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -472,6 +472,11 @@ struct CPUArchState {
> uint64_t kvm_timer_state;
> uint64_t kvm_timer_frequency;
> #endif /* CONFIG_KVM */
> +
> + /* RNMI */
> + target_ulong rnmip;
> + uint64_t rnmi_irqvec;
> + uint64_t rnmi_excpvec;
> };
>
> /*
> @@ -568,6 +573,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);
> void riscv_cpu_interrupt(CPURISCVState *env);
> #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 *),
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 32b068f18a..e14b654c35 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -662,6 +662,12 @@ typedef enum {
> /* Default Reset Vector address */
> #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 */
> @@ -711,6 +717,9 @@ typedef enum RISCVException {
> /* -1 is due to bit zero of hgeip and hgeie being ROZ. */
> #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)
> @@ -942,6 +951,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 395a1d9140..9d0400035f 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -434,6 +434,18 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> uint64_t vsbits, irq_delegated;
> int virq;
>
> + /* 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) {
> mie = 1;
> @@ -496,7 +508,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);
> @@ -619,6 +633,30 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen)
> env->geilen = geilen;
> }
>
> +void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level)
> +{
> + CPURISCVState *env = &cpu->env;
> + CPUState *cs = CPU(cpu);
> + bool release_lock = false;
> +
> + if (!bql_locked()) {
> + release_lock = true;
> + bql_lock();
> + }
> +
> + 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 (release_lock) {
> + bql_unlock();
> + }
> +}
> +
> int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
> {
> CPURISCVState *env = &cpu->env;
> @@ -1654,6 +1692,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> bool virt = env->virt_enabled;
> bool write_gva = false;
> uint64_t s;
> + int mode;
>
> /*
> * cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
> @@ -1670,6 +1709,20 @@ 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 && 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, virt);
> + return;
> + }
>
> if (!async) {
> /* set tval to badaddr for traps with address information */
> @@ -1755,8 +1808,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 < 64 &&
> - (((deleg >> cause) & 1) || s_injected || vs_injected)) {
> + mode = env->priv <= PRV_S && cause < 64 &&
> + (((deleg >> cause) & 1) || s_injected || vs_injected) ? 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;
Since nmi_excep is only use in the else statement (mode == PRV_M), maybe
it would be better to move the computation there. And it will also allow
to get rid of the mode == PRV_M check in the boolean expression.
BTW, I think the variable should be named "nnmi_excep" rather than
"nmi_execp".
Thanks,
Clément
> +
> + if (mode == PRV_S) {
> /* handle the trap in S-mode */
> if (riscv_has_ext(env, RVH)) {
> uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
> @@ -1832,8 +1897,13 @@ 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, virt);
> }
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 2/5] target/riscv: Handle Smrnmi interrupt and exception.
2024-09-02 10:34 ` Clément Léger
@ 2024-09-02 12:49 ` Clément Léger
0 siblings, 0 replies; 15+ messages in thread
From: Clément Léger @ 2024-09-02 12:49 UTC (permalink / raw)
To: Tommy Wu, qemu-devel, qemu-riscv
Cc: frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, dbarboza, ajones
On 02/09/2024 12:34, Clément Léger wrote:
>
>
> On 02/09/2024 09:13, Tommy Wu wrote:
>> Because the RNMI interrupt trap handler address is implementation defined.
>> We add the `rnmi-interrupt-vector` and `rnmi-exception-vector` as the property
>> of the harts. It’s very easy for users to set the address based on their
>> expectation. This patch also adds the functionality to handle the RNMI signals.
>>
>> Signed-off-by: Frank Chang <frank.chang@sifive.com>
>> Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
>> ---
>> hw/riscv/riscv_hart.c | 18 ++++++++
>> include/hw/riscv/riscv_hart.h | 4 ++
>> target/riscv/cpu.c | 11 +++++
>> target/riscv/cpu.h | 6 +++
>> target/riscv/cpu_bits.h | 12 ++++++
>> target/riscv/cpu_helper.c | 80 ++++++++++++++++++++++++++++++++---
>> 6 files changed, 126 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
>> index 613ea2aaa0..b7d73f7a82 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,18 @@ 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 912b4a2682..a6ed73a195 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 a90808a3ba..2f64b3df22 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -1309,6 +1309,11 @@ 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)
>> +{
>> + riscv_cpu_set_rnmi(RISCV_CPU(opaque), irq, level);
>> +}
>> #endif /* CONFIG_USER_ONLY */
>>
>> static bool riscv_cpu_is_dynamic(Object *cpu_obj)
>> @@ -1332,6 +1337,8 @@ static void riscv_cpu_init(Object *obj)
>> #ifndef CONFIG_USER_ONLY
>> qdev_init_gpio_in(DEVICE(obj), 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 */
>>
>> general_user_opts = g_hash_table_new(g_str_hash, g_str_equal);
>> @@ -2681,6 +2688,10 @@ static Property riscv_cpu_properties[] = {
>>
>> #ifndef CONFIG_USER_ONLY
>> DEFINE_PROP_UINT64("resetvec", RISCVCPU, env.resetvec, DEFAULT_RSTVEC),
>> + 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),
>> #endif
>>
>> DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false),
>> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> index 1619c3acb6..d8ad04ec31 100644
>> --- a/target/riscv/cpu.h
>> +++ b/target/riscv/cpu.h
>> @@ -472,6 +472,11 @@ struct CPUArchState {
>> uint64_t kvm_timer_state;
>> uint64_t kvm_timer_frequency;
>> #endif /* CONFIG_KVM */
>> +
>> + /* RNMI */
>> + target_ulong rnmip;
>> + uint64_t rnmi_irqvec;
>> + uint64_t rnmi_excpvec;
>> };
>>
>> /*
>> @@ -568,6 +573,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);
>> void riscv_cpu_interrupt(CPURISCVState *env);
>> #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 *),
>> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
>> index 32b068f18a..e14b654c35 100644
>> --- a/target/riscv/cpu_bits.h
>> +++ b/target/riscv/cpu_bits.h
>> @@ -662,6 +662,12 @@ typedef enum {
>> /* Default Reset Vector address */
>> #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 */
>> @@ -711,6 +717,9 @@ typedef enum RISCVException {
>> /* -1 is due to bit zero of hgeip and hgeie being ROZ. */
>> #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)
>> @@ -942,6 +951,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 395a1d9140..9d0400035f 100644
>> --- a/target/riscv/cpu_helper.c
>> +++ b/target/riscv/cpu_helper.c
>> @@ -434,6 +434,18 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
>> uint64_t vsbits, irq_delegated;
>> int virq;
>>
>> + /* 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) {
>> mie = 1;
>> @@ -496,7 +508,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);
>> @@ -619,6 +633,30 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen)
>> env->geilen = geilen;
>> }
>>
>> +void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level)
>> +{
>> + CPURISCVState *env = &cpu->env;
>> + CPUState *cs = CPU(cpu);
>> + bool release_lock = false;
>> +
>> + if (!bql_locked()) {
>> + release_lock = true;
>> + bql_lock();
>> + }
>> +
>> + 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 (release_lock) {
>> + bql_unlock();
>> + }
>> +}
>> +
>> int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
>> {
>> CPURISCVState *env = &cpu->env;
>> @@ -1654,6 +1692,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>> bool virt = env->virt_enabled;
>> bool write_gva = false;
>> uint64_t s;
>> + int mode;
>>
>> /*
>> * cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
>> @@ -1670,6 +1709,20 @@ 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 && 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, virt);
>> + return;
>> + }
>>
>> if (!async) {
>> /* set tval to badaddr for traps with address information */
>> @@ -1755,8 +1808,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 < 64 &&
>> - (((deleg >> cause) & 1) || s_injected || vs_injected)) {
>> + mode = env->priv <= PRV_S && cause < 64 &&
>> + (((deleg >> cause) & 1) || s_injected || vs_injected) ? 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;
>
> Since nmi_excep is only use in the else statement (mode == PRV_M), maybe
> it would be better to move the computation there. And it will also allow
> to get rid of the mode == PRV_M check in the boolean expression.
>
> BTW, I think the variable should be named "nnmi_excep" rather than
> "nmi_execp".
>
> Thanks,
>
> Clément
>
>> +
>> + if (mode == PRV_S) {
>> /* handle the trap in S-mode */
>> if (riscv_has_ext(env, RVH)) {
>> uint64_t hdeleg = async ? env->hideleg : env->hedeleg;
>> @@ -1832,8 +1897,13 @@ 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) {
BTW, since cpu->cfg.ext_smrnmi is already part of nmi_execp boolean
expression, you can remove it from there.
Thanks,
Clément
>> + 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, virt);
>> }
>>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v6 3/5] target/riscv: Add Smrnmi CSRs.
2024-09-02 7:13 [PATCH v6 0/5] target/riscv: Add Smrnmi support Tommy Wu
2024-09-02 7:13 ` [PATCH v6 1/5] target/riscv: Add `ext_smrnmi` in the RISCVCPUConfig Tommy Wu
2024-09-02 7:13 ` [PATCH v6 2/5] target/riscv: Handle Smrnmi interrupt and exception Tommy Wu
@ 2024-09-02 7:13 ` Tommy Wu
2024-09-02 7:13 ` [PATCH v6 4/5] target/riscv: Add Smrnmi mnret instruction Tommy Wu
` (3 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Tommy Wu @ 2024-09-02 7:13 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, dbarboza, ajones, Tommy Wu
The Smrnmi extension adds the `MNSCRATCH`, `MNEPC`, `MNCAUSE`,
`MNSTATUS` CSRs.
Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.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 2f64b3df22..98e6940e93 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1024,6 +1024,11 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
riscv_trigger_reset_hold(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 d8ad04ec31..a84e719d3f 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -474,6 +474,10 @@ struct CPUArchState {
#endif /* CONFIG_KVM */
/* 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 e14b654c35..da1723496c 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -350,6 +350,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
@@ -627,6 +633,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 ea3560342c..e5de72453c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -578,6 +578,17 @@ 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)
@@ -4566,6 +4577,67 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
+static RISCVException 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;
+}
+
#endif
/* Crypto Extension */
@@ -5070,6 +5142,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.39.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v6 4/5] target/riscv: Add Smrnmi mnret instruction.
2024-09-02 7:13 [PATCH v6 0/5] target/riscv: Add Smrnmi support Tommy Wu
` (2 preceding siblings ...)
2024-09-02 7:13 ` [PATCH v6 3/5] target/riscv: Add Smrnmi CSRs Tommy Wu
@ 2024-09-02 7:13 ` Tommy Wu
2024-09-06 0:51 ` Alistair Francis
2024-09-02 7:13 ` [PATCH v6 5/5] target/riscv: Add Smrnmi cpu extension Tommy Wu
` (2 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Tommy Wu @ 2024-09-02 7:13 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, dbarboza, ajones, Tommy Wu
This patch adds a new instruction `mnret`. `mnret` is an M-mode-only
instruction that uses the values in `mnepc` and `mnstatus` to return to the
program counter, privilege mode, and virtualization mode of the
interrupted context.
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 | 49 +++++++++++++++++--
4 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 451261ce5a..16ea240d26 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -131,6 +131,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(wrs_nto, void, env)
DEF_HELPER_1(tlb_flush, void, env)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index c45b8fa1d8..d320631e8c 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -121,6 +121,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 bc5263a4e0..06bc20dda4 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -106,6 +106,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, tcg_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 25a5263573..6895c7596b 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -312,24 +312,30 @@ target_ulong helper_sret(CPURISCVState *env)
return retpc;
}
-target_ulong helper_mret(CPURISCVState *env)
+static void check_ret_from_m_mode(CPURISCVState *env, target_ulong retpc,
+ target_ulong prev_priv)
{
if (!(env->priv >= PRV_M)) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
- target_ulong retpc = env->mepc;
if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
}
- uint64_t mstatus = env->mstatus;
- target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
-
if (riscv_cpu_cfg(env)->pmp &&
!pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
riscv_raise_exception(env, RISCV_EXCP_INST_ACCESS_FAULT, GETPC());
}
+}
+
+target_ulong helper_mret(CPURISCVState *env)
+{
+ target_ulong retpc = env->mepc;
+ uint64_t mstatus = env->mstatus;
+ target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
+
+ check_ret_from_m_mode(env, retpc, prev_priv);
target_ulong prev_virt = get_field(env->mstatus, MSTATUS_MPV) &&
(prev_priv != PRV_M);
@@ -353,6 +359,39 @@ target_ulong helper_mret(CPURISCVState *env)
return retpc;
}
+target_ulong helper_mnret(CPURISCVState *env)
+{
+ if (!riscv_cpu_cfg(env)->ext_smrnmi) {
+ /* RNMI feature is not presented. */
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ }
+
+ target_ulong retpc = env->mnepc;
+ target_ulong prev_priv = get_field(env->mnstatus, MNSTATUS_MNPP);
+
+ check_ret_from_m_mode(env, retpc, prev_priv);
+
+ target_ulong prev_virt = get_field(env->mnstatus, MNSTATUS_MNPV) &&
+ (prev_priv != PRV_M);
+ env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, true);
+
+ /*
+ * 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) && prev_virt) {
+ riscv_cpu_swap_hypervisor_regs(env);
+ }
+
+ riscv_cpu_set_mode(env, prev_priv, prev_virt);
+
+ return retpc;
+}
+
void helper_wfi(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
--
2.39.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v6 4/5] target/riscv: Add Smrnmi mnret instruction.
2024-09-02 7:13 ` [PATCH v6 4/5] target/riscv: Add Smrnmi mnret instruction Tommy Wu
@ 2024-09-06 0:51 ` Alistair Francis
0 siblings, 0 replies; 15+ messages in thread
From: Alistair Francis @ 2024-09-06 0:51 UTC (permalink / raw)
To: Tommy Wu
Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
bin.meng, liweiwei, dbarboza, ajones
On Mon, Sep 2, 2024 at 5:14 PM Tommy Wu <tommy.wu@sifive.com> wrote:
>
> This patch adds a new instruction `mnret`. `mnret` is an M-mode-only
> instruction that uses the values in `mnepc` and `mnstatus` to return to the
> program counter, privilege mode, and virtualization mode of the
> interrupted context.
>
> 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 | 49 +++++++++++++++++--
> 4 files changed, 60 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index 451261ce5a..16ea240d26 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -131,6 +131,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(wrs_nto, void, env)
> DEF_HELPER_1(tlb_flush, void, env)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index c45b8fa1d8..d320631e8c 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -121,6 +121,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 bc5263a4e0..06bc20dda4 100644
> --- a/target/riscv/insn_trans/trans_privileged.c.inc
> +++ b/target/riscv/insn_trans/trans_privileged.c.inc
> @@ -106,6 +106,18 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
> #endif
> }
>
> +static bool trans_mnret(DisasContext *ctx, arg_mnret *a)
> +{
> +#ifndef CONFIG_USER_ONLY
You will want to include a REQUIRE_SMRNMI(ctx) function here. Have a
look at REQUIRE_A_OR_ZAAMO(ctx) for an example of what it should look
like.
> + gen_helper_mnret(cpu_pc, tcg_env);
> + tcg_gen_exit_tb(NULL, 0); /* no chaining */
> + ctx->base.is_jmp = DISAS_NORETURN;
This will need to be rebased on
https://github.com/alistair23/qemu/tree/riscv-to-apply.next
We will want to call decode_save_opc() and the other functions here
> + 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 25a5263573..6895c7596b 100644
> --- a/target/riscv/op_helper.c
> +++ b/target/riscv/op_helper.c
> @@ -312,24 +312,30 @@ target_ulong helper_sret(CPURISCVState *env)
> return retpc;
> }
>
> -target_ulong helper_mret(CPURISCVState *env)
> +static void check_ret_from_m_mode(CPURISCVState *env, target_ulong retpc,
> + target_ulong prev_priv)
> {
> if (!(env->priv >= PRV_M)) {
> riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> }
>
> - target_ulong retpc = env->mepc;
> if (!riscv_has_ext(env, RVC) && (retpc & 0x3)) {
> riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
> }
>
> - uint64_t mstatus = env->mstatus;
> - target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
> -
> if (riscv_cpu_cfg(env)->pmp &&
> !pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
> riscv_raise_exception(env, RISCV_EXCP_INST_ACCESS_FAULT, GETPC());
> }
> +}
> +
> +target_ulong helper_mret(CPURISCVState *env)
> +{
> + target_ulong retpc = env->mepc;
> + uint64_t mstatus = env->mstatus;
> + target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
> +
> + check_ret_from_m_mode(env, retpc, prev_priv);
>
> target_ulong prev_virt = get_field(env->mstatus, MSTATUS_MPV) &&
> (prev_priv != PRV_M);
> @@ -353,6 +359,39 @@ target_ulong helper_mret(CPURISCVState *env)
> return retpc;
> }
>
> +target_ulong helper_mnret(CPURISCVState *env)
> +{
> + if (!riscv_cpu_cfg(env)->ext_smrnmi) {
> + /* RNMI feature is not presented. */
> + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
> + }
> +
> + target_ulong retpc = env->mnepc;
> + target_ulong prev_priv = get_field(env->mnstatus, MNSTATUS_MNPP);
Variables should be declared before any other code in a function.
With a REQUIRE_SMRNMI() you can drop the check above anyway.
Alistair
> +
> + check_ret_from_m_mode(env, retpc, prev_priv);
> +
> + target_ulong prev_virt = get_field(env->mnstatus, MNSTATUS_MNPV) &&
> + (prev_priv != PRV_M);
> + env->mnstatus = set_field(env->mnstatus, MNSTATUS_NMIE, true);
> +
> + /*
> + * 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) && prev_virt) {
> + riscv_cpu_swap_hypervisor_regs(env);
> + }
> +
> + riscv_cpu_set_mode(env, prev_priv, prev_virt);
> +
> + return retpc;
> +}
> +
> void helper_wfi(CPURISCVState *env)
> {
> CPUState *cs = env_cpu(env);
> --
> 2.39.3
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v6 5/5] target/riscv: Add Smrnmi cpu extension.
2024-09-02 7:13 [PATCH v6 0/5] target/riscv: Add Smrnmi support Tommy Wu
` (3 preceding siblings ...)
2024-09-02 7:13 ` [PATCH v6 4/5] target/riscv: Add Smrnmi mnret instruction Tommy Wu
@ 2024-09-02 7:13 ` Tommy Wu
2024-09-06 0:37 ` [PATCH v6 0/5] target/riscv: Add Smrnmi support Alistair Francis
2024-10-11 11:38 ` Daniel Henrique Barboza
6 siblings, 0 replies; 15+ messages in thread
From: Tommy Wu @ 2024-09-02 7:13 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, dbarboza, ajones, Tommy Wu
This adds the properties for ISA extension Smrnmi.
Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Tommy Wu <tommy.wu@sifive.com>
---
target/riscv/cpu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 98e6940e93..7ee7b9c4ee 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -184,6 +184,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf),
ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
+ ISA_EXT_DATA_ENTRY(smrnmi, PRIV_VERSION_1_12_0, ext_smrnmi),
ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
ISA_EXT_DATA_ENTRY(ssccptr, PRIV_VERSION_1_11_0, has_priv_1_11),
@@ -1514,6 +1515,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
MULTI_EXT_CFG_BOOL("smaia", ext_smaia, false),
MULTI_EXT_CFG_BOOL("smepmp", ext_smepmp, false),
+ MULTI_EXT_CFG_BOOL("smrnmi", ext_smrnmi, false),
MULTI_EXT_CFG_BOOL("smstateen", ext_smstateen, false),
MULTI_EXT_CFG_BOOL("ssaia", ext_ssaia, false),
MULTI_EXT_CFG_BOOL("svade", ext_svade, false),
--
2.39.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v6 0/5] target/riscv: Add Smrnmi support.
2024-09-02 7:13 [PATCH v6 0/5] target/riscv: Add Smrnmi support Tommy Wu
` (4 preceding siblings ...)
2024-09-02 7:13 ` [PATCH v6 5/5] target/riscv: Add Smrnmi cpu extension Tommy Wu
@ 2024-09-06 0:37 ` Alistair Francis
2024-10-11 11:38 ` Daniel Henrique Barboza
6 siblings, 0 replies; 15+ messages in thread
From: Alistair Francis @ 2024-09-06 0:37 UTC (permalink / raw)
To: Tommy Wu
Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
bin.meng, liweiwei, dbarboza, ajones
On Mon, Sep 2, 2024 at 5:14 PM Tommy Wu <tommy.wu@sifive.com> wrote:
>
> This patchset added support for Smrnmi Extension in RISC-V.
Thanks!
Can you please include a link to the exact spec version used for this?
We have had issues where there are multiple conflicting ratified
versions of a spec, so we are trying to be explicit in the cover
letter about exactly what version is supported
The exact commit from `src/rnmi.adoc` or ideally a tagged release of
the spec would be great
Alistair
>
> 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.
>
> If anyone wants to test the patches, we can use the customized OpenSBI[1],
> and the customized QEMU[2].
>
> We implemented a PoC RNMI trap handler in the customized OpenSBI.
> In the customized QEMU, we use the Smrnmi patches and the patch from
> Damien Hedde[3]. The patch from Damien Hedde can be used to inject
> the RNMI signal with the qmp command.
>
> [1] https://github.com/TommyWu-fdgkhdkgh/opensbi/tree/dev/twu/master
> [2] https://github.com/TommyWu-fdgkhdkgh/qemu/tree/dev/twu/master
> [3] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg06232.html
>
> Test commands :
> $ ./build/qemu-system-riscv64 -M virt -cpu rv64,smrnmi=true,
> rnmi-interrupt-vector={Offset of the RNMI handler in the customized
> OpenSBI.} -m 4G -smp 2 -serial mon:stdio -serial null -nographic
> -bios fw_jump.elf -kernel Image -initrd rootfs.cpio
> -qmp unix:/tmp/qmp-sock,server,wait=off
>
> Use qmp command to inject the RNMI interrupt.
> $ ./scripts/qmp/qmp-shell /tmp/qmp-sock
> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
> number=0 value=true
>
> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
> number=0 value=false
>
> Changelog:
>
> v6
> * Delete the redundant code in `riscv_cpu_do_interrupt`.
> ( Thank Alvin for the suggestion. )
> * Split the shared code in `helper_mret` and `helper_mnret` into a
> helper function `check_ret_from_m_mode`.
> ( Thank Alistair for the suggestion. )
>
> v5
> * Move the patch that adds the Smrnmi extension to the last patch.
> ( Thank Alistair for the suggestion. )
> * Implement an M-mode software PoC for this with implemented handlers.
> ( Thank Andrew Jones for the suggestion. )
> * Add a commit message to all patches of the series.
> ( Thank Andrew Jones for the suggestion. )
>
> v4
> * Fix some coding style issues.
> ( Thank Daniel for the suggestions. )
>
> 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 (5):
> target/riscv: Add `ext_smrnmi` in the RISCVCPUConfig.
> target/riscv: Handle Smrnmi interrupt and exception.
> target/riscv: Add Smrnmi CSRs.
> target/riscv: Add Smrnmi mnret instruction.
> target/riscv: Add Smrnmi cpu extension.
>
> hw/riscv/riscv_hart.c | 18 ++++
> include/hw/riscv/riscv_hart.h | 4 +
> target/riscv/cpu.c | 18 ++++
> target/riscv/cpu.h | 10 +++
> target/riscv/cpu_bits.h | 23 ++++++
> target/riscv/cpu_cfg.h | 1 +
> target/riscv/cpu_helper.c | 80 ++++++++++++++++--
> 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 | 49 +++++++++--
> 12 files changed, 291 insertions(+), 10 deletions(-)
>
> --
> 2.39.3
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 0/5] target/riscv: Add Smrnmi support.
2024-09-02 7:13 [PATCH v6 0/5] target/riscv: Add Smrnmi support Tommy Wu
` (5 preceding siblings ...)
2024-09-06 0:37 ` [PATCH v6 0/5] target/riscv: Add Smrnmi support Alistair Francis
@ 2024-10-11 11:38 ` Daniel Henrique Barboza
2024-10-14 1:54 ` Frank Chang
2024-10-14 7:35 ` Clément Léger
6 siblings, 2 replies; 15+ messages in thread
From: Daniel Henrique Barboza @ 2024-10-11 11:38 UTC (permalink / raw)
To: Tommy Wu, qemu-devel, qemu-riscv
Cc: frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, ajones, Clément Léger
Hi Tommy,
Do you plan to send a new version of this work soon? This series is a prerequisite
of "target/riscv: Add support for Smdbltrp and Ssdbltrp extensions" and we need
this series merged first. We have minor comments from Clément and Alistair so
hopefully it shouldn't be too much work.
The code freeze for 9.2 will happen in the first/second week of November, so if you
could send a new version to be merged in the next PR that would be great.
Thanks,
Daniel
On 9/2/24 4:13 AM, Tommy Wu wrote:
> 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.
>
> If anyone wants to test the patches, we can use the customized OpenSBI[1],
> and the customized QEMU[2].
>
> We implemented a PoC RNMI trap handler in the customized OpenSBI.
> In the customized QEMU, we use the Smrnmi patches and the patch from
> Damien Hedde[3]. The patch from Damien Hedde can be used to inject
> the RNMI signal with the qmp command.
>
> [1] https://github.com/TommyWu-fdgkhdkgh/opensbi/tree/dev/twu/master
> [2] https://github.com/TommyWu-fdgkhdkgh/qemu/tree/dev/twu/master
> [3] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg06232.html
>
> Test commands :
> $ ./build/qemu-system-riscv64 -M virt -cpu rv64,smrnmi=true,
> rnmi-interrupt-vector={Offset of the RNMI handler in the customized
> OpenSBI.} -m 4G -smp 2 -serial mon:stdio -serial null -nographic
> -bios fw_jump.elf -kernel Image -initrd rootfs.cpio
> -qmp unix:/tmp/qmp-sock,server,wait=off
>
> Use qmp command to inject the RNMI interrupt.
> $ ./scripts/qmp/qmp-shell /tmp/qmp-sock
> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
> number=0 value=true
>
> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
> number=0 value=false
>
> Changelog:
>
> v6
> * Delete the redundant code in `riscv_cpu_do_interrupt`.
> ( Thank Alvin for the suggestion. )
> * Split the shared code in `helper_mret` and `helper_mnret` into a
> helper function `check_ret_from_m_mode`.
> ( Thank Alistair for the suggestion. )
>
> v5
> * Move the patch that adds the Smrnmi extension to the last patch.
> ( Thank Alistair for the suggestion. )
> * Implement an M-mode software PoC for this with implemented handlers.
> ( Thank Andrew Jones for the suggestion. )
> * Add a commit message to all patches of the series.
> ( Thank Andrew Jones for the suggestion. )
>
> v4
> * Fix some coding style issues.
> ( Thank Daniel for the suggestions. )
>
> 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 (5):
> target/riscv: Add `ext_smrnmi` in the RISCVCPUConfig.
> target/riscv: Handle Smrnmi interrupt and exception.
> target/riscv: Add Smrnmi CSRs.
> target/riscv: Add Smrnmi mnret instruction.
> target/riscv: Add Smrnmi cpu extension.
>
> hw/riscv/riscv_hart.c | 18 ++++
> include/hw/riscv/riscv_hart.h | 4 +
> target/riscv/cpu.c | 18 ++++
> target/riscv/cpu.h | 10 +++
> target/riscv/cpu_bits.h | 23 ++++++
> target/riscv/cpu_cfg.h | 1 +
> target/riscv/cpu_helper.c | 80 ++++++++++++++++--
> 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 | 49 +++++++++--
> 12 files changed, 291 insertions(+), 10 deletions(-)
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 0/5] target/riscv: Add Smrnmi support.
2024-10-11 11:38 ` Daniel Henrique Barboza
@ 2024-10-14 1:54 ` Frank Chang
2024-10-14 7:35 ` Clément Léger
1 sibling, 0 replies; 15+ messages in thread
From: Frank Chang @ 2024-10-14 1:54 UTC (permalink / raw)
To: Daniel Henrique Barboza
Cc: Tommy Wu, qemu-devel, qemu-riscv, palmer, alistair.francis,
alistair23, bin.meng, liweiwei, ajones, Clément Léger
[-- Attachment #1: Type: text/plain, Size: 5142 bytes --]
Hi Daniel,
Thanks for the reminder.
I'll take over Tommy's work to send out the v7 patchset later this week.
Regards,
Frank Chang
On Fri, Oct 11, 2024 at 7:38 PM Daniel Henrique Barboza <
dbarboza@ventanamicro.com> wrote:
> Hi Tommy,
>
>
> Do you plan to send a new version of this work soon? This series is a
> prerequisite
> of "target/riscv: Add support for Smdbltrp and Ssdbltrp extensions" and we
> need
> this series merged first. We have minor comments from Clément and Alistair
> so
> hopefully it shouldn't be too much work.
>
> The code freeze for 9.2 will happen in the first/second week of November,
> so if you
> could send a new version to be merged in the next PR that would be great.
>
>
> Thanks,
>
> Daniel
>
>
>
> On 9/2/24 4:13 AM, Tommy Wu wrote:
> > 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.
> >
> > If anyone wants to test the patches, we can use the customized
> OpenSBI[1],
> > and the customized QEMU[2].
> >
> > We implemented a PoC RNMI trap handler in the customized OpenSBI.
> > In the customized QEMU, we use the Smrnmi patches and the patch from
> > Damien Hedde[3]. The patch from Damien Hedde can be used to inject
> > the RNMI signal with the qmp command.
> >
> > [1] https://github.com/TommyWu-fdgkhdkgh/opensbi/tree/dev/twu/master
> > [2] https://github.com/TommyWu-fdgkhdkgh/qemu/tree/dev/twu/master
> > [3] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg06232.html
> >
> > Test commands :
> > $ ./build/qemu-system-riscv64 -M virt -cpu rv64,smrnmi=true,
> > rnmi-interrupt-vector={Offset of the RNMI handler in the customized
> > OpenSBI.} -m 4G -smp 2 -serial mon:stdio -serial null -nographic
> > -bios fw_jump.elf -kernel Image -initrd rootfs.cpio
> > -qmp unix:/tmp/qmp-sock,server,wait=off
> >
> > Use qmp command to inject the RNMI interrupt.
> > $ ./scripts/qmp/qmp-shell /tmp/qmp-sock
> > (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
> > number=0 value=true
> >
> > (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
> > number=0 value=false
> >
> > Changelog:
> >
> > v6
> > * Delete the redundant code in `riscv_cpu_do_interrupt`.
> > ( Thank Alvin for the suggestion. )
> > * Split the shared code in `helper_mret` and `helper_mnret` into a
> > helper function `check_ret_from_m_mode`.
> > ( Thank Alistair for the suggestion. )
> >
> > v5
> > * Move the patch that adds the Smrnmi extension to the last patch.
> > ( Thank Alistair for the suggestion. )
> > * Implement an M-mode software PoC for this with implemented handlers.
> > ( Thank Andrew Jones for the suggestion. )
> > * Add a commit message to all patches of the series.
> > ( Thank Andrew Jones for the suggestion. )
> >
> > v4
> > * Fix some coding style issues.
> > ( Thank Daniel for the suggestions. )
> >
> > 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 (5):
> > target/riscv: Add `ext_smrnmi` in the RISCVCPUConfig.
> > target/riscv: Handle Smrnmi interrupt and exception.
> > target/riscv: Add Smrnmi CSRs.
> > target/riscv: Add Smrnmi mnret instruction.
> > target/riscv: Add Smrnmi cpu extension.
> >
> > hw/riscv/riscv_hart.c | 18 ++++
> > include/hw/riscv/riscv_hart.h | 4 +
> > target/riscv/cpu.c | 18 ++++
> > target/riscv/cpu.h | 10 +++
> > target/riscv/cpu_bits.h | 23 ++++++
> > target/riscv/cpu_cfg.h | 1 +
> > target/riscv/cpu_helper.c | 80 ++++++++++++++++--
> > 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 | 49 +++++++++--
> > 12 files changed, 291 insertions(+), 10 deletions(-)
> >
>
[-- Attachment #2: Type: text/html, Size: 6611 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 0/5] target/riscv: Add Smrnmi support.
2024-10-11 11:38 ` Daniel Henrique Barboza
2024-10-14 1:54 ` Frank Chang
@ 2024-10-14 7:35 ` Clément Léger
2024-10-14 9:04 ` Frank Chang
1 sibling, 1 reply; 15+ messages in thread
From: Clément Léger @ 2024-10-14 7:35 UTC (permalink / raw)
To: Daniel Henrique Barboza, Tommy Wu, qemu-devel, qemu-riscv
Cc: frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, ajones
On 11/10/2024 13:38, Daniel Henrique Barboza wrote:
> Hi Tommy,
>
>
> Do you plan to send a new version of this work soon? This series is a
> prerequisite
> of "target/riscv: Add support for Smdbltrp and Ssdbltrp extensions" and
> we need
> this series merged first. We have minor comments from Clément and
Hi Henrique,
If that's easier, I can still remove the dependency on Smrnmi and add
support for that later.
Clément
> Alistair so
> hopefully it shouldn't be too much work.
>
> The code freeze for 9.2 will happen in the first/second week of
> November, so if you
> could send a new version to be merged in the next PR that would be great.
>
>
> Thanks,
>
> Daniel
>
>
>
> On 9/2/24 4:13 AM, Tommy Wu wrote:
>> 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.
>>
>> If anyone wants to test the patches, we can use the customized
>> OpenSBI[1],
>> and the customized QEMU[2].
>>
>> We implemented a PoC RNMI trap handler in the customized OpenSBI.
>> In the customized QEMU, we use the Smrnmi patches and the patch from
>> Damien Hedde[3]. The patch from Damien Hedde can be used to inject
>> the RNMI signal with the qmp command.
>>
>> [1] https://github.com/TommyWu-fdgkhdkgh/opensbi/tree/dev/twu/master
>> [2] https://github.com/TommyWu-fdgkhdkgh/qemu/tree/dev/twu/master
>> [3] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg06232.html
>>
>> Test commands :
>> $ ./build/qemu-system-riscv64 -M virt -cpu rv64,smrnmi=true,
>> rnmi-interrupt-vector={Offset of the RNMI handler in the customized
>> OpenSBI.} -m 4G -smp 2 -serial mon:stdio -serial null -nographic
>> -bios fw_jump.elf -kernel Image -initrd rootfs.cpio
>> -qmp unix:/tmp/qmp-sock,server,wait=off
>>
>> Use qmp command to inject the RNMI interrupt.
>> $ ./scripts/qmp/qmp-shell /tmp/qmp-sock
>> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
>> number=0 value=true
>>
>> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
>> number=0 value=false
>>
>> Changelog:
>>
>> v6
>> * Delete the redundant code in `riscv_cpu_do_interrupt`.
>> ( Thank Alvin for the suggestion. )
>> * Split the shared code in `helper_mret` and `helper_mnret` into a
>> helper function `check_ret_from_m_mode`.
>> ( Thank Alistair for the suggestion. )
>>
>> v5
>> * Move the patch that adds the Smrnmi extension to the last patch.
>> ( Thank Alistair for the suggestion. )
>> * Implement an M-mode software PoC for this with implemented handlers.
>> ( Thank Andrew Jones for the suggestion. )
>> * Add a commit message to all patches of the series.
>> ( Thank Andrew Jones for the suggestion. )
>>
>> v4
>> * Fix some coding style issues.
>> ( Thank Daniel for the suggestions. )
>>
>> 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 (5):
>> target/riscv: Add `ext_smrnmi` in the RISCVCPUConfig.
>> target/riscv: Handle Smrnmi interrupt and exception.
>> target/riscv: Add Smrnmi CSRs.
>> target/riscv: Add Smrnmi mnret instruction.
>> target/riscv: Add Smrnmi cpu extension.
>>
>> hw/riscv/riscv_hart.c | 18 ++++
>> include/hw/riscv/riscv_hart.h | 4 +
>> target/riscv/cpu.c | 18 ++++
>> target/riscv/cpu.h | 10 +++
>> target/riscv/cpu_bits.h | 23 ++++++
>> target/riscv/cpu_cfg.h | 1 +
>> target/riscv/cpu_helper.c | 80 ++++++++++++++++--
>> 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 | 49 +++++++++--
>> 12 files changed, 291 insertions(+), 10 deletions(-)
>>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 0/5] target/riscv: Add Smrnmi support.
2024-10-14 7:35 ` Clément Léger
@ 2024-10-14 9:04 ` Frank Chang
2024-10-14 16:15 ` Daniel Henrique Barboza
0 siblings, 1 reply; 15+ messages in thread
From: Frank Chang @ 2024-10-14 9:04 UTC (permalink / raw)
To: Clément Léger
Cc: Daniel Henrique Barboza, Tommy Wu, qemu-devel, qemu-riscv,
frank.chang, palmer, alistair.francis, alistair23, bin.meng,
liweiwei, ajones
Clément Léger <cleger@rivosinc.com> 於 2024年10月14日 週一 下午3:36寫道:
>
>
>
> On 11/10/2024 13:38, Daniel Henrique Barboza wrote:
> > Hi Tommy,
> >
> >
> > Do you plan to send a new version of this work soon? This series is a
> > prerequisite
> > of "target/riscv: Add support for Smdbltrp and Ssdbltrp extensions" and
> > we need
> > this series merged first. We have minor comments from Clément and
>
> Hi Henrique,
>
> If that's easier, I can still remove the dependency on Smrnmi and add
> support for that later.
>
> Clément
Hi Clément,
Sorry for keeping you waiting. I've reviewed the comments from you and Alistair.
The comments should be straightforward to fix.
I will fix them and send out the patchset later today.
Hope that it makes things easier.
Regards,
Frank Chang
>
> > Alistair so
> > hopefully it shouldn't be too much work.
> >
> > The code freeze for 9.2 will happen in the first/second week of
> > November, so if you
> > could send a new version to be merged in the next PR that would be great.
> >
> >
> > Thanks,
> >
> > Daniel
> >
> >
> >
> > On 9/2/24 4:13 AM, Tommy Wu wrote:
> >> 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.
> >>
> >> If anyone wants to test the patches, we can use the customized
> >> OpenSBI[1],
> >> and the customized QEMU[2].
> >>
> >> We implemented a PoC RNMI trap handler in the customized OpenSBI.
> >> In the customized QEMU, we use the Smrnmi patches and the patch from
> >> Damien Hedde[3]. The patch from Damien Hedde can be used to inject
> >> the RNMI signal with the qmp command.
> >>
> >> [1] https://github.com/TommyWu-fdgkhdkgh/opensbi/tree/dev/twu/master
> >> [2] https://github.com/TommyWu-fdgkhdkgh/qemu/tree/dev/twu/master
> >> [3] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg06232.html
> >>
> >> Test commands :
> >> $ ./build/qemu-system-riscv64 -M virt -cpu rv64,smrnmi=true,
> >> rnmi-interrupt-vector={Offset of the RNMI handler in the customized
> >> OpenSBI.} -m 4G -smp 2 -serial mon:stdio -serial null -nographic
> >> -bios fw_jump.elf -kernel Image -initrd rootfs.cpio
> >> -qmp unix:/tmp/qmp-sock,server,wait=off
> >>
> >> Use qmp command to inject the RNMI interrupt.
> >> $ ./scripts/qmp/qmp-shell /tmp/qmp-sock
> >> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
> >> number=0 value=true
> >>
> >> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
> >> number=0 value=false
> >>
> >> Changelog:
> >>
> >> v6
> >> * Delete the redundant code in `riscv_cpu_do_interrupt`.
> >> ( Thank Alvin for the suggestion. )
> >> * Split the shared code in `helper_mret` and `helper_mnret` into a
> >> helper function `check_ret_from_m_mode`.
> >> ( Thank Alistair for the suggestion. )
> >>
> >> v5
> >> * Move the patch that adds the Smrnmi extension to the last patch.
> >> ( Thank Alistair for the suggestion. )
> >> * Implement an M-mode software PoC for this with implemented handlers.
> >> ( Thank Andrew Jones for the suggestion. )
> >> * Add a commit message to all patches of the series.
> >> ( Thank Andrew Jones for the suggestion. )
> >>
> >> v4
> >> * Fix some coding style issues.
> >> ( Thank Daniel for the suggestions. )
> >>
> >> 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 (5):
> >> target/riscv: Add `ext_smrnmi` in the RISCVCPUConfig.
> >> target/riscv: Handle Smrnmi interrupt and exception.
> >> target/riscv: Add Smrnmi CSRs.
> >> target/riscv: Add Smrnmi mnret instruction.
> >> target/riscv: Add Smrnmi cpu extension.
> >>
> >> hw/riscv/riscv_hart.c | 18 ++++
> >> include/hw/riscv/riscv_hart.h | 4 +
> >> target/riscv/cpu.c | 18 ++++
> >> target/riscv/cpu.h | 10 +++
> >> target/riscv/cpu_bits.h | 23 ++++++
> >> target/riscv/cpu_cfg.h | 1 +
> >> target/riscv/cpu_helper.c | 80 ++++++++++++++++--
> >> 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 | 49 +++++++++--
> >> 12 files changed, 291 insertions(+), 10 deletions(-)
> >>
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v6 0/5] target/riscv: Add Smrnmi support.
2024-10-14 9:04 ` Frank Chang
@ 2024-10-14 16:15 ` Daniel Henrique Barboza
0 siblings, 0 replies; 15+ messages in thread
From: Daniel Henrique Barboza @ 2024-10-14 16:15 UTC (permalink / raw)
To: Frank Chang, Clément Léger
Cc: Tommy Wu, qemu-devel, qemu-riscv, palmer, alistair.francis,
alistair23, bin.meng, liweiwei, ajones
On 10/14/24 6:04 AM, Frank Chang wrote:
> Clément Léger <cleger@rivosinc.com> 於 2024年10月14日 週一 下午3:36寫道:
>>
>>
>>
>> On 11/10/2024 13:38, Daniel Henrique Barboza wrote:
>>> Hi Tommy,
>>>
>>>
>>> Do you plan to send a new version of this work soon? This series is a
>>> prerequisite
>>> of "target/riscv: Add support for Smdbltrp and Ssdbltrp extensions" and
>>> we need
>>> this series merged first. We have minor comments from Clément and
>>
>> Hi Henrique,
>>
>> If that's easier, I can still remove the dependency on Smrnmi and add
>> support for that later.
>>
>> Clément
>
> Hi Clément,
>
> Sorry for keeping you waiting. I've reviewed the comments from you and Alistair.
> The comments should be straightforward to fix.
> I will fix them and send out the patchset later today.
> Hope that it makes things easier.
Thanks for taking care of this series Frank!
Daniel
>
>
> Regards,
> Frank Chang
>
>>
>>> Alistair so
>>> hopefully it shouldn't be too much work.
>>>
>>> The code freeze for 9.2 will happen in the first/second week of
>>> November, so if you
>>> could send a new version to be merged in the next PR that would be great.
>>>
>>>
>>> Thanks,
>>>
>>> Daniel
>>>
>>>
>>>
>>> On 9/2/24 4:13 AM, Tommy Wu wrote:
>>>> 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.
>>>>
>>>> If anyone wants to test the patches, we can use the customized
>>>> OpenSBI[1],
>>>> and the customized QEMU[2].
>>>>
>>>> We implemented a PoC RNMI trap handler in the customized OpenSBI.
>>>> In the customized QEMU, we use the Smrnmi patches and the patch from
>>>> Damien Hedde[3]. The patch from Damien Hedde can be used to inject
>>>> the RNMI signal with the qmp command.
>>>>
>>>> [1] https://github.com/TommyWu-fdgkhdkgh/opensbi/tree/dev/twu/master
>>>> [2] https://github.com/TommyWu-fdgkhdkgh/qemu/tree/dev/twu/master
>>>> [3] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg06232.html
>>>>
>>>> Test commands :
>>>> $ ./build/qemu-system-riscv64 -M virt -cpu rv64,smrnmi=true,
>>>> rnmi-interrupt-vector={Offset of the RNMI handler in the customized
>>>> OpenSBI.} -m 4G -smp 2 -serial mon:stdio -serial null -nographic
>>>> -bios fw_jump.elf -kernel Image -initrd rootfs.cpio
>>>> -qmp unix:/tmp/qmp-sock,server,wait=off
>>>>
>>>> Use qmp command to inject the RNMI interrupt.
>>>> $ ./scripts/qmp/qmp-shell /tmp/qmp-sock
>>>> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
>>>> number=0 value=true
>>>>
>>>> (QEMU) gpio-set path=/machine/soc0/harts[0] gpio=riscv.cpu.rnmi
>>>> number=0 value=false
>>>>
>>>> Changelog:
>>>>
>>>> v6
>>>> * Delete the redundant code in `riscv_cpu_do_interrupt`.
>>>> ( Thank Alvin for the suggestion. )
>>>> * Split the shared code in `helper_mret` and `helper_mnret` into a
>>>> helper function `check_ret_from_m_mode`.
>>>> ( Thank Alistair for the suggestion. )
>>>>
>>>> v5
>>>> * Move the patch that adds the Smrnmi extension to the last patch.
>>>> ( Thank Alistair for the suggestion. )
>>>> * Implement an M-mode software PoC for this with implemented handlers.
>>>> ( Thank Andrew Jones for the suggestion. )
>>>> * Add a commit message to all patches of the series.
>>>> ( Thank Andrew Jones for the suggestion. )
>>>>
>>>> v4
>>>> * Fix some coding style issues.
>>>> ( Thank Daniel for the suggestions. )
>>>>
>>>> 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 (5):
>>>> target/riscv: Add `ext_smrnmi` in the RISCVCPUConfig.
>>>> target/riscv: Handle Smrnmi interrupt and exception.
>>>> target/riscv: Add Smrnmi CSRs.
>>>> target/riscv: Add Smrnmi mnret instruction.
>>>> target/riscv: Add Smrnmi cpu extension.
>>>>
>>>> hw/riscv/riscv_hart.c | 18 ++++
>>>> include/hw/riscv/riscv_hart.h | 4 +
>>>> target/riscv/cpu.c | 18 ++++
>>>> target/riscv/cpu.h | 10 +++
>>>> target/riscv/cpu_bits.h | 23 ++++++
>>>> target/riscv/cpu_cfg.h | 1 +
>>>> target/riscv/cpu_helper.c | 80 ++++++++++++++++--
>>>> 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 | 49 +++++++++--
>>>> 12 files changed, 291 insertions(+), 10 deletions(-)
>>>>
>>
>>
^ permalink raw reply [flat|nested] 15+ messages in thread