* [PATCH v4 1/4] target/riscv: Add Smrnmi cpu extension.
2023-06-08 7:23 [PATCH v4 0/4] target/riscv: Add Smrnmi support Tommy Wu
@ 2023-06-08 7:23 ` Tommy Wu
2023-06-08 9:52 ` Andrew Jones
2023-06-12 5:03 ` Alistair Francis
2023-06-08 7:23 ` [PATCH v4 2/4] target/riscv: Add Smrnmi CSRs Tommy Wu
` (3 subsequent siblings)
4 siblings, 2 replies; 12+ messages in thread
From: Tommy Wu @ 2023-06-08 7:23 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 | 13 +++++++++++++
target/riscv/cpu.h | 7 +++++++
target/riscv/cpu_bits.h | 12 ++++++++++++
target/riscv/cpu_helper.c | 24 ++++++++++++++++++++++++
6 files changed, 81 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..c8dc0eaa87 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,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 void riscv_cpu_init(Object *obj)
@@ -1420,6 +1426,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 +1608,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 +1653,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 56381aaf26..da477b6c99 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -636,6 +636,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 release_lock = false;
+
+ if (!qemu_mutex_iothread_locked()) {
+ release_lock = 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 (release_lock) {
+ 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] 12+ messages in thread
* Re: [PATCH v4 1/4] target/riscv: Add Smrnmi cpu extension.
2023-06-08 7:23 ` [PATCH v4 1/4] target/riscv: Add Smrnmi cpu extension Tommy Wu
@ 2023-06-08 9:52 ` Andrew Jones
2024-08-09 5:49 ` Tommy Wu
2023-06-12 5:03 ` Alistair Francis
1 sibling, 1 reply; 12+ messages in thread
From: Andrew Jones @ 2023-06-08 9:52 UTC (permalink / raw)
To: Tommy Wu
Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
bin.meng, liweiwei, dbarboza, zhiwei_liu, richard.henderson
Please add a commit message to all patches of the series.
Another comment below.
On Thu, Jun 08, 2023 at 12:23:11AM -0700, 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 | 13 +++++++++++++
> target/riscv/cpu.h | 7 +++++++
> target/riscv/cpu_bits.h | 12 ++++++++++++
> target/riscv/cpu_helper.c | 24 ++++++++++++++++++++++++
> 6 files changed, 81 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..c8dc0eaa87 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,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 void riscv_cpu_init(Object *obj)
> @@ -1420,6 +1426,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 +1608,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 +1653,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),
Why are these addresses user configurable? Shouldn't each board set them
to whatever the real board uses and a generic board, like 'virt', set
them to whatever works for it, considering the rest of its memory map?
Also, looking ahead, I don't see where the addresses are described to the
M-mode software in the DT, which implies board-specific M-mode software
would hard code it, but generic M-mode software should get the addresses
from the DT. And, presumably, M-mode software should protect and reserve
these addresses from S-mode. It'd be nice to see an M-mode software PoC,
but I didn't see anything on the opensbi mailing list.
Thanks,
drew
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4 1/4] target/riscv: Add Smrnmi cpu extension.
2023-06-08 9:52 ` Andrew Jones
@ 2024-08-09 5:49 ` Tommy Wu
0 siblings, 0 replies; 12+ messages in thread
From: Tommy Wu @ 2024-08-09 5:49 UTC (permalink / raw)
To: Andrew Jones
Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
bin.meng, liweiwei, dbarboza, zhiwei_liu, richard.henderson
On Thu, Jun 8, 2023 at 5:52 PM Andrew Jones <ajones@ventanamicro.com> wrote:
>
>
> Please add a commit message to all patches of the series.
>
> Another comment below.
Thanks for the suggestion, I'll add commit messages to all patches in
the v5 patches.
>
> On Thu, Jun 08, 2023 at 12:23:11AM -0700, 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 | 13 +++++++++++++
> > target/riscv/cpu.h | 7 +++++++
> > target/riscv/cpu_bits.h | 12 ++++++++++++
> > target/riscv/cpu_helper.c | 24 ++++++++++++++++++++++++
> > 6 files changed, 81 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..c8dc0eaa87 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,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 void riscv_cpu_init(Object *obj)
> > @@ -1420,6 +1426,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 +1608,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 +1653,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),
>
> Why are these addresses user configurable? Shouldn't each board set them
> to whatever the real board uses and a generic board, like 'virt', set
> them to whatever works for it, considering the rest of its memory map?
> Also, looking ahead, I don't see where the addresses are described to the
> M-mode software in the DT, which implies board-specific M-mode software
> would hard code it, but generic M-mode software should get the addresses
> from the DT. And, presumably, M-mode software should protect and reserve
> these addresses from S-mode. It'd be nice to see an M-mode software PoC,
> but I didn't see anything on the opensbi mailing list.
>
> Thanks,
> drew
Because the RNMI interrupt trap handler address isn't software configurable,
it’s implementation-defined. Although the generic M-mode software get the
addresses from the DT, the generic M-mode software cannot configure it like
`mtvec`. I think making it configurable in the QEMU helps users to test the
functionality of their own RNMI trap handler.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4 1/4] target/riscv: Add Smrnmi cpu extension.
2023-06-08 7:23 ` [PATCH v4 1/4] target/riscv: Add Smrnmi cpu extension Tommy Wu
2023-06-08 9:52 ` Andrew Jones
@ 2023-06-12 5:03 ` Alistair Francis
2024-08-09 5:50 ` Tommy Wu
1 sibling, 1 reply; 12+ messages in thread
From: Alistair Francis @ 2023-06-12 5:03 UTC (permalink / raw)
To: Tommy Wu
Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
bin.meng, liweiwei, dbarboza, zhiwei_liu, richard.henderson
On Thu, Jun 8, 2023 at 5:25 PM Tommy Wu <tommy.wu@sifive.com> 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 | 13 +++++++++++++
> target/riscv/cpu.h | 7 +++++++
> target/riscv/cpu_bits.h | 12 ++++++++++++
> target/riscv/cpu_helper.c | 24 ++++++++++++++++++++++++
> 6 files changed, 81 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..c8dc0eaa87 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),
The extension should be added after the implementation, so this patch
should be the last patch.
Alistair
> 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,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 void riscv_cpu_init(Object *obj)
> @@ -1420,6 +1426,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 +1608,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 +1653,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 56381aaf26..da477b6c99 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -636,6 +636,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 release_lock = false;
> +
> + if (!qemu_mutex_iothread_locked()) {
> + release_lock = 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 (release_lock) {
> + qemu_mutex_unlock_iothread();
> + }
> +}
> +
> void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
> void *arg)
> {
> --
> 2.31.1
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4 1/4] target/riscv: Add Smrnmi cpu extension.
2023-06-12 5:03 ` Alistair Francis
@ 2024-08-09 5:50 ` Tommy Wu
0 siblings, 0 replies; 12+ messages in thread
From: Tommy Wu @ 2024-08-09 5:50 UTC (permalink / raw)
To: Alistair Francis
Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
bin.meng, liweiwei, dbarboza, zhiwei_liu, richard.henderson
On Mon, Jun 12, 2023 at 1:04 PM Alistair Francis <alistair23@gmail.com> wrote:
>
> On Thu, Jun 8, 2023 at 5:25 PM Tommy Wu <tommy.wu@sifive.com> 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 | 13 +++++++++++++
> > target/riscv/cpu.h | 7 +++++++
> > target/riscv/cpu_bits.h | 12 ++++++++++++
> > target/riscv/cpu_helper.c | 24 ++++++++++++++++++++++++
> > 6 files changed, 81 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..c8dc0eaa87 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),
>
> The extension should be added after the implementation, so this patch
> should be the last patch.
>
> Alistair
Thanks for the suggestion, I'll move this patch to the last patch.
>
> > 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,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 void riscv_cpu_init(Object *obj)
> > @@ -1420,6 +1426,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 +1608,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 +1653,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 56381aaf26..da477b6c99 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -636,6 +636,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 release_lock = false;
> > +
> > + if (!qemu_mutex_iothread_locked()) {
> > + release_lock = 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 (release_lock) {
> > + qemu_mutex_unlock_iothread();
> > + }
> > +}
> > +
> > void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
> > void *arg)
> > {
> > --
> > 2.31.1
> >
> >
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v4 2/4] target/riscv: Add Smrnmi CSRs.
2023-06-08 7:23 [PATCH v4 0/4] target/riscv: Add Smrnmi support Tommy Wu
2023-06-08 7:23 ` [PATCH v4 1/4] target/riscv: Add Smrnmi cpu extension Tommy Wu
@ 2023-06-08 7:23 ` Tommy Wu
2023-06-12 4:58 ` Alistair Francis
2023-06-08 7:23 ` [PATCH v4 3/4] target/riscv: Handle Smrnmi interrupt and exception Tommy Wu
` (2 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Tommy Wu @ 2023-06-08 7:23 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 c8dc0eaa87..ee0a4bf33f 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] 12+ messages in thread
* Re: [PATCH v4 2/4] target/riscv: Add Smrnmi CSRs.
2023-06-08 7:23 ` [PATCH v4 2/4] target/riscv: Add Smrnmi CSRs Tommy Wu
@ 2023-06-12 4:58 ` Alistair Francis
0 siblings, 0 replies; 12+ messages in thread
From: Alistair Francis @ 2023-06-12 4:58 UTC (permalink / raw)
To: Tommy Wu
Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
bin.meng, liweiwei, dbarboza, zhiwei_liu, richard.henderson
On Thu, Jun 8, 2023 at 5:25 PM Tommy Wu <tommy.wu@sifive.com> wrote:
>
> 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>
Alistair
> ---
> 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 c8dc0eaa87..ee0a4bf33f 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 [flat|nested] 12+ messages in thread
* [PATCH v4 3/4] target/riscv: Handle Smrnmi interrupt and exception.
2023-06-08 7:23 [PATCH v4 0/4] target/riscv: Add Smrnmi support Tommy Wu
2023-06-08 7:23 ` [PATCH v4 1/4] target/riscv: Add Smrnmi cpu extension Tommy Wu
2023-06-08 7:23 ` [PATCH v4 2/4] target/riscv: Add Smrnmi CSRs Tommy Wu
@ 2023-06-08 7:23 ` Tommy Wu
2023-06-08 7:23 ` [PATCH v4 4/4] target/riscv: Add Smrnmi mnret instruction Tommy Wu
2023-06-08 9:43 ` [PATCH v4 0/4] target/riscv: Add Smrnmi support Andrew Jones
4 siblings, 0 replies; 12+ messages in thread
From: Tommy Wu @ 2023-06-08 7:23 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 | 57 +++++++++++++++++++++++++++++++++++----
1 file changed, 52 insertions(+), 5 deletions(-)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index da477b6c99..1a926bb661 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -407,6 +407,18 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
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) {
mie = 1;
@@ -452,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);
@@ -1614,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
@@ -1626,6 +1641,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);
+ goto handled;
+ }
if (cause == RISCV_EXCP_SEMIHOST) {
do_common_semihosting(cs);
@@ -1712,8 +1741,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;
@@ -1788,8 +1829,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);
}
@@ -1802,6 +1847,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] 12+ messages in thread
* [PATCH v4 4/4] target/riscv: Add Smrnmi mnret instruction.
2023-06-08 7:23 [PATCH v4 0/4] target/riscv: Add Smrnmi support Tommy Wu
` (2 preceding siblings ...)
2023-06-08 7:23 ` [PATCH v4 3/4] target/riscv: Handle Smrnmi interrupt and exception Tommy Wu
@ 2023-06-08 7:23 ` Tommy Wu
2023-06-08 9:43 ` [PATCH v4 0/4] target/riscv: Add Smrnmi support Andrew Jones
4 siblings, 0 replies; 12+ messages in thread
From: Tommy Wu @ 2023-06-08 7:23 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 | 49 +++++++++++++++++++
4 files changed, 65 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 528baa1652..ef7f102069 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -104,6 +104,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..b27beec871 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -359,6 +359,55 @@ 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());
+ }
+
+ 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 (riscv_cpu_cfg(env)->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] 12+ messages in thread
* Re: [PATCH v4 0/4] target/riscv: Add Smrnmi support.
2023-06-08 7:23 [PATCH v4 0/4] target/riscv: Add Smrnmi support Tommy Wu
` (3 preceding siblings ...)
2023-06-08 7:23 ` [PATCH v4 4/4] target/riscv: Add Smrnmi mnret instruction Tommy Wu
@ 2023-06-08 9:43 ` Andrew Jones
2024-08-09 5:31 ` Tommy Wu
4 siblings, 1 reply; 12+ messages in thread
From: Andrew Jones @ 2023-06-08 9:43 UTC (permalink / raw)
To: Tommy Wu
Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
bin.meng, liweiwei, dbarboza, zhiwei_liu, richard.henderson
On Thu, Jun 08, 2023 at 12:23:10AM -0700, 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.
Is there an M-mode software PoC for this with implemented handlers?
Thanks,
drew
>
> Changelog:
>
> 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 (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 | 18 ++++
> target/riscv/cpu.h | 11 +++
> target/riscv/cpu_bits.h | 23 ++++++
> target/riscv/cpu_helper.c | 81 ++++++++++++++++--
> 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 +++++++++++
> 11 files changed, 300 insertions(+), 5 deletions(-)
>
> --
> 2.31.1
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4 0/4] target/riscv: Add Smrnmi support.
2023-06-08 9:43 ` [PATCH v4 0/4] target/riscv: Add Smrnmi support Andrew Jones
@ 2024-08-09 5:31 ` Tommy Wu
0 siblings, 0 replies; 12+ messages in thread
From: Tommy Wu @ 2024-08-09 5:31 UTC (permalink / raw)
To: Andrew Jones
Cc: qemu-devel, qemu-riscv, frank.chang, palmer, alistair.francis,
bin.meng, liweiwei, dbarboza, zhiwei_liu, richard.henderson
On Thu, Jun 8, 2023 at 5:43 PM Andrew Jones <ajones@ventanamicro.com> wrote:
>
> On Thu, Jun 08, 2023 at 12:23:10AM -0700, 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.
>
> Is there an M-mode software PoC for this with implemented handlers?
>
> Thanks,
> drew
>
Sorry for the late reply.
We implement a simple RNMI trap handler in the customized OpenSBI [1], and
use the work from Damien Hedde [2] to inject the RNMI interrupt. We can test
the RNMI functionality with the signal injection in the customized QEMU [3].
I’ll include the test case in the latest upstream email.
[1] https://github.com/TommyWu-fdgkhdkgh/opensbi/commits/dev/twu/master
[2] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg06232.html
[3] https://github.com/TommyWu-fdgkhdkgh/qemu/tree/dev/twu/master
> >
> > Changelog:
> >
> > 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 (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 | 18 ++++
> > target/riscv/cpu.h | 11 +++
> > target/riscv/cpu_bits.h | 23 ++++++
> > target/riscv/cpu_helper.c | 81 ++++++++++++++++--
> > 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 +++++++++++
> > 11 files changed, 300 insertions(+), 5 deletions(-)
> >
> > --
> > 2.31.1
> >
> >
^ permalink raw reply [flat|nested] 12+ messages in thread