* [RFC v2 1/4] target/riscv: add RNMI cpu feature
2021-04-01 9:26 [RFC v2 0/4] target/riscv: add RNMI support frank.chang
@ 2021-04-01 9:26 ` frank.chang
2021-04-01 9:26 ` frank.chang
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: frank.chang @ 2021-04-01 9:26 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Frank Chang, Alistair Francis, Palmer Dabbelt, Sagar Karandikar,
Bastian Koppelmann
From: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
hw/riscv/riscv_hart.c | 8 +++++++
include/hw/riscv/riscv_hart.h | 2 ++
target/riscv/cpu.c | 40 +++++++++++++++++++++++++++++++++++
target/riscv/cpu.h | 12 ++++++++++-
target/riscv/cpu_bits.h | 6 ++++++
5 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
index 613ea2aaa0b..b8cb5088638 100644
--- a/hw/riscv/riscv_hart.c
+++ b/hw/riscv/riscv_hart.c
@@ -33,6 +33,10 @@ static Property riscv_harts_props[] = {
DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type),
DEFINE_PROP_UINT64("resetvec", RISCVHartArrayState, resetvec,
DEFAULT_RSTVEC),
+ DEFINE_PROP_UINT64("rnmi_irqvec", RISCVHartArrayState, rnmi_irqvec,
+ DEFAULT_RNMI_IRQVEC),
+ DEFINE_PROP_UINT64("rnmi_excpvec", RISCVHartArrayState, rnmi_excpvec,
+ DEFAULT_RNMI_EXCPVEC),
DEFINE_PROP_END_OF_LIST(),
};
@@ -47,6 +51,10 @@ 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);
+ qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "rnmi_irqvec",
+ s->rnmi_irqvec);
+ qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "rnmi_excpvec",
+ s->rnmi_excpvec);
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 bbc21cdc9a6..48e6730d832 100644
--- a/include/hw/riscv/riscv_hart.h
+++ b/include/hw/riscv/riscv_hart.h
@@ -38,6 +38,8 @@ struct RISCVHartArrayState {
uint32_t hartid_base;
char *cpu_type;
uint64_t resetvec;
+ uint64_t rnmi_irqvec;
+ uint64_t rnmi_excpvec;
RISCVCPU *harts;
};
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7d6ed80f6b6..9fb6ceb0ad8 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -137,6 +137,14 @@ static void set_feature(CPURISCVState *env, int feature)
env->features |= (1ULL << feature);
}
+static void set_rnmi_vectors(CPURISCVState *env, int irqvec, int excpvec)
+{
+#ifndef CONFIG_USER_ONLY
+ env->rnmi_irqvec = irqvec;
+ env->rnmi_excpvec = excpvec;
+#endif
+}
+
static void set_resetvec(CPURISCVState *env, int resetvec)
{
#ifndef CONFIG_USER_ONLY
@@ -373,6 +381,23 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
}
}
+#ifndef CONFIG_USER_ONLY
+static void riscv_cpu_set_rnmi(void *opaque, int irq, int level)
+{
+ RISCVCPU *cpu = opaque;
+ CPURISCVState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
+
+ if (level) {
+ env->nmip |= 1 << irq;
+ cpu_interrupt(cs, CPU_INTERRUPT_RNMI);
+ } else {
+ env->nmip &= ~(1 << irq);
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_RNMI);
+ }
+}
+#endif
+
static void riscv_cpu_realize(DeviceState *dev, Error **errp)
{
CPUState *cs = CPU(dev);
@@ -416,6 +441,16 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_resetvec(env, cpu->cfg.resetvec);
+ if (cpu->cfg.rnmi) {
+ set_feature(env, RISCV_FEATURE_RNMI);
+ set_rnmi_vectors(env, cpu->cfg.rnmi_irqvec, cpu->cfg.rnmi_excpvec);
+#ifndef CONFIG_USER_ONLY
+ env->nmie = true;
+ qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_rnmi,
+ "rnmi", TARGET_LONG_BITS);
+#endif
+ }
+
/* If only XLEN is set for misa, then set misa from properties */
if (env->misa == RV32 || env->misa == RV64) {
/* Do some ISA extension error checking */
@@ -555,6 +590,11 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
+ DEFINE_PROP_BOOL("rnmi", RISCVCPU, cfg.rnmi, false),
+ DEFINE_PROP_UINT64("rnmi_irqvec", RISCVCPU, cfg.rnmi_irqvec,
+ DEFAULT_RNMI_IRQVEC),
+ DEFINE_PROP_UINT64("rnmi_excpvec", RISCVCPU, cfg.rnmi_excpvec,
+ DEFAULT_RNMI_EXCPVEC),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 0a33d387ba8..7d2bb7e7003 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -80,7 +80,8 @@
enum {
RISCV_FEATURE_MMU,
RISCV_FEATURE_PMP,
- RISCV_FEATURE_MISA
+ RISCV_FEATURE_MISA,
+ RISCV_FEATURE_RNMI,
};
#define PRIV_VERSION_1_10_0 0x00011000
@@ -178,6 +179,12 @@ struct CPURISCVState {
target_ulong mcause;
target_ulong mtval; /* since: priv-1.10.0 */
+ /* NMI */
+ bool nmie;
+ target_ulong nmip;
+ target_ulong rnmi_irqvec;
+ target_ulong rnmi_excpvec;
+
/* Hypervisor CSRs */
target_ulong hstatus;
target_ulong hedeleg;
@@ -304,6 +311,9 @@ struct RISCVCPU {
bool mmu;
bool pmp;
uint64_t resetvec;
+ bool rnmi;
+ uint64_t rnmi_irqvec;
+ uint64_t rnmi_excpvec;
} cfg;
};
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index caf45992070..8e5f0be599a 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -526,6 +526,12 @@
/* Default Reset Vector adress */
#define DEFAULT_RSTVEC 0x1000
+/* Default RNMI Interrupt Vector address */
+#define DEFAULT_RNMI_IRQVEC 0x1000
+
+/* Default RNMI Exception Vector address */
+#define DEFAULT_RNMI_EXCPVEC 0x1000
+
/* Exception causes */
#define EXCP_NONE -1 /* sentinel value */
#define RISCV_EXCP_INST_ADDR_MIS 0x0
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC v2 1/4] target/riscv: add RNMI cpu feature
@ 2021-04-01 9:26 ` frank.chang
0 siblings, 0 replies; 11+ messages in thread
From: frank.chang @ 2021-04-01 9:26 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Frank Chang, Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
Bastian Koppelmann
From: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
hw/riscv/riscv_hart.c | 8 +++++++
include/hw/riscv/riscv_hart.h | 2 ++
target/riscv/cpu.c | 40 +++++++++++++++++++++++++++++++++++
target/riscv/cpu.h | 12 ++++++++++-
target/riscv/cpu_bits.h | 6 ++++++
5 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
index 613ea2aaa0b..b8cb5088638 100644
--- a/hw/riscv/riscv_hart.c
+++ b/hw/riscv/riscv_hart.c
@@ -33,6 +33,10 @@ static Property riscv_harts_props[] = {
DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type),
DEFINE_PROP_UINT64("resetvec", RISCVHartArrayState, resetvec,
DEFAULT_RSTVEC),
+ DEFINE_PROP_UINT64("rnmi_irqvec", RISCVHartArrayState, rnmi_irqvec,
+ DEFAULT_RNMI_IRQVEC),
+ DEFINE_PROP_UINT64("rnmi_excpvec", RISCVHartArrayState, rnmi_excpvec,
+ DEFAULT_RNMI_EXCPVEC),
DEFINE_PROP_END_OF_LIST(),
};
@@ -47,6 +51,10 @@ 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);
+ qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "rnmi_irqvec",
+ s->rnmi_irqvec);
+ qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "rnmi_excpvec",
+ s->rnmi_excpvec);
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 bbc21cdc9a6..48e6730d832 100644
--- a/include/hw/riscv/riscv_hart.h
+++ b/include/hw/riscv/riscv_hart.h
@@ -38,6 +38,8 @@ struct RISCVHartArrayState {
uint32_t hartid_base;
char *cpu_type;
uint64_t resetvec;
+ uint64_t rnmi_irqvec;
+ uint64_t rnmi_excpvec;
RISCVCPU *harts;
};
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7d6ed80f6b6..9fb6ceb0ad8 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -137,6 +137,14 @@ static void set_feature(CPURISCVState *env, int feature)
env->features |= (1ULL << feature);
}
+static void set_rnmi_vectors(CPURISCVState *env, int irqvec, int excpvec)
+{
+#ifndef CONFIG_USER_ONLY
+ env->rnmi_irqvec = irqvec;
+ env->rnmi_excpvec = excpvec;
+#endif
+}
+
static void set_resetvec(CPURISCVState *env, int resetvec)
{
#ifndef CONFIG_USER_ONLY
@@ -373,6 +381,23 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
}
}
+#ifndef CONFIG_USER_ONLY
+static void riscv_cpu_set_rnmi(void *opaque, int irq, int level)
+{
+ RISCVCPU *cpu = opaque;
+ CPURISCVState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
+
+ if (level) {
+ env->nmip |= 1 << irq;
+ cpu_interrupt(cs, CPU_INTERRUPT_RNMI);
+ } else {
+ env->nmip &= ~(1 << irq);
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_RNMI);
+ }
+}
+#endif
+
static void riscv_cpu_realize(DeviceState *dev, Error **errp)
{
CPUState *cs = CPU(dev);
@@ -416,6 +441,16 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_resetvec(env, cpu->cfg.resetvec);
+ if (cpu->cfg.rnmi) {
+ set_feature(env, RISCV_FEATURE_RNMI);
+ set_rnmi_vectors(env, cpu->cfg.rnmi_irqvec, cpu->cfg.rnmi_excpvec);
+#ifndef CONFIG_USER_ONLY
+ env->nmie = true;
+ qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_rnmi,
+ "rnmi", TARGET_LONG_BITS);
+#endif
+ }
+
/* If only XLEN is set for misa, then set misa from properties */
if (env->misa == RV32 || env->misa == RV64) {
/* Do some ISA extension error checking */
@@ -555,6 +590,11 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
+ DEFINE_PROP_BOOL("rnmi", RISCVCPU, cfg.rnmi, false),
+ DEFINE_PROP_UINT64("rnmi_irqvec", RISCVCPU, cfg.rnmi_irqvec,
+ DEFAULT_RNMI_IRQVEC),
+ DEFINE_PROP_UINT64("rnmi_excpvec", RISCVCPU, cfg.rnmi_excpvec,
+ DEFAULT_RNMI_EXCPVEC),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 0a33d387ba8..7d2bb7e7003 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -80,7 +80,8 @@
enum {
RISCV_FEATURE_MMU,
RISCV_FEATURE_PMP,
- RISCV_FEATURE_MISA
+ RISCV_FEATURE_MISA,
+ RISCV_FEATURE_RNMI,
};
#define PRIV_VERSION_1_10_0 0x00011000
@@ -178,6 +179,12 @@ struct CPURISCVState {
target_ulong mcause;
target_ulong mtval; /* since: priv-1.10.0 */
+ /* NMI */
+ bool nmie;
+ target_ulong nmip;
+ target_ulong rnmi_irqvec;
+ target_ulong rnmi_excpvec;
+
/* Hypervisor CSRs */
target_ulong hstatus;
target_ulong hedeleg;
@@ -304,6 +311,9 @@ struct RISCVCPU {
bool mmu;
bool pmp;
uint64_t resetvec;
+ bool rnmi;
+ uint64_t rnmi_irqvec;
+ uint64_t rnmi_excpvec;
} cfg;
};
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index caf45992070..8e5f0be599a 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -526,6 +526,12 @@
/* Default Reset Vector adress */
#define DEFAULT_RSTVEC 0x1000
+/* Default RNMI Interrupt Vector address */
+#define DEFAULT_RNMI_IRQVEC 0x1000
+
+/* Default RNMI Exception Vector address */
+#define DEFAULT_RNMI_EXCPVEC 0x1000
+
/* Exception causes */
#define EXCP_NONE -1 /* sentinel value */
#define RISCV_EXCP_INST_ADDR_MIS 0x0
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC v2 2/4] target/riscv: add RNMI CSRs
2021-04-01 9:26 [RFC v2 0/4] target/riscv: add RNMI support frank.chang
@ 2021-04-01 9:26 ` frank.chang
2021-04-01 9:26 ` frank.chang
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: frank.chang @ 2021-04-01 9:26 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Frank Chang, Alistair Francis, Palmer Dabbelt, Sagar Karandikar,
Bastian Koppelmann
From: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
target/riscv/cpu.h | 4 +++
target/riscv/cpu_bits.h | 9 +++++++
target/riscv/csr.c | 59 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 72 insertions(+)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7d2bb7e7003..674ee4dc999 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -180,6 +180,10 @@ struct CPURISCVState {
target_ulong mtval; /* since: priv-1.10.0 */
/* NMI */
+ target_ulong mnscratch;
+ target_ulong mnepc;
+ target_ulong mncause; /* mncause without bit XLEN-1 set to 1 */
+ target_ulong mnstatus;
bool nmie;
target_ulong nmip;
target_ulong rnmi_irqvec;
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 8e5f0be599a..a376ede0cc5 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -166,6 +166,12 @@
#define CSR_MTVAL 0x343
#define CSR_MIP 0x344
+/* NMI */
+#define CSR_MNSCRATCH 0x350
+#define CSR_MNEPC 0x351
+#define CSR_MNCAUSE 0x352
+#define CSR_MNSTATUS 0x353
+
/* Legacy Machine Trap Handling (priv v1.9.1) */
#define CSR_MBADADDR 0x343
@@ -558,6 +564,9 @@
#define RISCV_EXCP_INT_FLAG 0x80000000
#define RISCV_EXCP_INT_MASK 0x7fffffff
+/* RNMI mnstatus CSR mask */
+#define MNSTATUS_MPP MSTATUS_MPP
+
/* Interrupt causes */
#define IRQ_U_SOFT 0
#define IRQ_S_SOFT 1
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d2585395bfb..489d6d90e68 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -188,6 +188,11 @@ static int pmp(CPURISCVState *env, int csrno)
{
return -!riscv_feature(env, RISCV_FEATURE_PMP);
}
+
+static int nmi(CPURISCVState *env, int csrno)
+{
+ return -!riscv_feature(env, RISCV_FEATURE_RNMI);
+}
#endif
/* User Floating-Point CSRs */
@@ -713,6 +718,54 @@ static int write_mbadaddr(CPURISCVState *env, int csrno, target_ulong val)
return 0;
}
+static int read_mnscratch(CPURISCVState *env, int csrno, target_ulong *val)
+{
+ *val = env->mnscratch;
+ return 0;
+}
+
+static int write_mnscratch(CPURISCVState *env, int csrno, target_ulong val)
+{
+ env->mnscratch = val;
+ return 0;
+}
+
+static int read_mnepc(CPURISCVState *env, int csrno, target_ulong *val)
+{
+ *val = env->mnepc;
+ return 0;
+}
+
+static int write_mnepc(CPURISCVState *env, int csrno, target_ulong val)
+{
+ env->mnepc = val;
+ return 0;
+}
+
+static int read_mncause(CPURISCVState *env, int csrno, target_ulong *val)
+{
+ *val = env->mncause;
+ return 0;
+}
+
+static int write_mncause(CPURISCVState *env, int csrno, target_ulong val)
+{
+ env->mncause = val;
+ return 0;
+}
+
+static int read_mnstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+ *val = env->mnstatus;
+ return 0;
+}
+
+static int write_mnstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+ env->mnstatus = val & MNSTATUS_MPP;
+ return 0;
+}
+
static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
{
@@ -1428,6 +1481,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_MBADADDR] = { "mbadaddr", any, read_mbadaddr, write_mbadaddr },
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
+ /* NMI */
+ [CSR_MNSCRATCH] = { "mnscratch", nmi, read_mnscratch, write_mnscratch },
+ [CSR_MNEPC] = { "mnepc", nmi, read_mnepc, write_mnepc },
+ [CSR_MNCAUSE] = { "mncause", nmi, read_mncause, write_mncause },
+ [CSR_MNSTATUS] = { "mnstatus", nmi, read_mnstatus, write_mnstatus },
+
/* Supervisor Trap Setup */
[CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus },
[CSR_SIE] = { "sie", smode, read_sie, write_sie },
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC v2 2/4] target/riscv: add RNMI CSRs
@ 2021-04-01 9:26 ` frank.chang
0 siblings, 0 replies; 11+ messages in thread
From: frank.chang @ 2021-04-01 9:26 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Frank Chang, Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
Bastian Koppelmann
From: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
target/riscv/cpu.h | 4 +++
target/riscv/cpu_bits.h | 9 +++++++
target/riscv/csr.c | 59 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 72 insertions(+)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7d2bb7e7003..674ee4dc999 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -180,6 +180,10 @@ struct CPURISCVState {
target_ulong mtval; /* since: priv-1.10.0 */
/* NMI */
+ target_ulong mnscratch;
+ target_ulong mnepc;
+ target_ulong mncause; /* mncause without bit XLEN-1 set to 1 */
+ target_ulong mnstatus;
bool nmie;
target_ulong nmip;
target_ulong rnmi_irqvec;
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 8e5f0be599a..a376ede0cc5 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -166,6 +166,12 @@
#define CSR_MTVAL 0x343
#define CSR_MIP 0x344
+/* NMI */
+#define CSR_MNSCRATCH 0x350
+#define CSR_MNEPC 0x351
+#define CSR_MNCAUSE 0x352
+#define CSR_MNSTATUS 0x353
+
/* Legacy Machine Trap Handling (priv v1.9.1) */
#define CSR_MBADADDR 0x343
@@ -558,6 +564,9 @@
#define RISCV_EXCP_INT_FLAG 0x80000000
#define RISCV_EXCP_INT_MASK 0x7fffffff
+/* RNMI mnstatus CSR mask */
+#define MNSTATUS_MPP MSTATUS_MPP
+
/* Interrupt causes */
#define IRQ_U_SOFT 0
#define IRQ_S_SOFT 1
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d2585395bfb..489d6d90e68 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -188,6 +188,11 @@ static int pmp(CPURISCVState *env, int csrno)
{
return -!riscv_feature(env, RISCV_FEATURE_PMP);
}
+
+static int nmi(CPURISCVState *env, int csrno)
+{
+ return -!riscv_feature(env, RISCV_FEATURE_RNMI);
+}
#endif
/* User Floating-Point CSRs */
@@ -713,6 +718,54 @@ static int write_mbadaddr(CPURISCVState *env, int csrno, target_ulong val)
return 0;
}
+static int read_mnscratch(CPURISCVState *env, int csrno, target_ulong *val)
+{
+ *val = env->mnscratch;
+ return 0;
+}
+
+static int write_mnscratch(CPURISCVState *env, int csrno, target_ulong val)
+{
+ env->mnscratch = val;
+ return 0;
+}
+
+static int read_mnepc(CPURISCVState *env, int csrno, target_ulong *val)
+{
+ *val = env->mnepc;
+ return 0;
+}
+
+static int write_mnepc(CPURISCVState *env, int csrno, target_ulong val)
+{
+ env->mnepc = val;
+ return 0;
+}
+
+static int read_mncause(CPURISCVState *env, int csrno, target_ulong *val)
+{
+ *val = env->mncause;
+ return 0;
+}
+
+static int write_mncause(CPURISCVState *env, int csrno, target_ulong val)
+{
+ env->mncause = val;
+ return 0;
+}
+
+static int read_mnstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+ *val = env->mnstatus;
+ return 0;
+}
+
+static int write_mnstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+ env->mnstatus = val & MNSTATUS_MPP;
+ return 0;
+}
+
static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
{
@@ -1428,6 +1481,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_MBADADDR] = { "mbadaddr", any, read_mbadaddr, write_mbadaddr },
[CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
+ /* NMI */
+ [CSR_MNSCRATCH] = { "mnscratch", nmi, read_mnscratch, write_mnscratch },
+ [CSR_MNEPC] = { "mnepc", nmi, read_mnepc, write_mnepc },
+ [CSR_MNCAUSE] = { "mncause", nmi, read_mncause, write_mncause },
+ [CSR_MNSTATUS] = { "mnstatus", nmi, read_mnstatus, write_mnstatus },
+
/* Supervisor Trap Setup */
[CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus },
[CSR_SIE] = { "sie", smode, read_sie, write_sie },
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC v2 3/4] target/riscv: handle RNMI interrupt and exception
2021-04-01 9:26 [RFC v2 0/4] target/riscv: add RNMI support frank.chang
@ 2021-04-01 9:26 ` frank.chang
2021-04-01 9:26 ` frank.chang
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: frank.chang @ 2021-04-01 9:26 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Frank Chang, Alistair Francis, Palmer Dabbelt, Sagar Karandikar,
Bastian Koppelmann
From: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
target/riscv/cpu_bits.h | 4 ++++
target/riscv/cpu_helper.c | 49 +++++++++++++++++++++++++++++++++++----
2 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index a376ede0cc5..937b1f28455 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -607,4 +607,8 @@
#define MIE_UTIE (1 << IRQ_U_TIMER)
#define MIE_SSIE (1 << IRQ_S_SOFT)
#define MIE_USIE (1 << IRQ_U_SOFT)
+
+/* RISC-V-specific interrupt pending bits. */
+#define CPU_INTERRUPT_RNMI CPU_INTERRUPT_TGT_EXT_0
+
#endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 21c54ef5613..67a633154a9 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -38,6 +38,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
#ifndef CONFIG_USER_ONLY
static int riscv_cpu_local_irq_pending(CPURISCVState *env)
{
+ if (riscv_feature(env, RISCV_FEATURE_RNMI)) {
+ /* Priority: RNMI > Other interrupt. */
+ if (env->nmip && env->nmie) {
+ return ctz64(env->nmip); /* since non-zero */
+ } else if (!env->nmie) {
+ /*
+ * We are already in RNMI handler,
+ * other interrupts cannot preempt.
+ */
+ return EXCP_NONE;
+ }
+ }
+
target_ulong irqs;
target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
@@ -80,7 +93,9 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
#if !defined(CONFIG_USER_ONLY)
- 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);
@@ -909,6 +924,23 @@ void riscv_cpu_do_interrupt(CPUState *cs)
target_ulong tval = 0;
target_ulong htval = 0;
target_ulong mtval2 = 0;
+ target_ulong nextpc;
+ bool nmi_execp = false;
+
+ if (riscv_feature(env, RISCV_FEATURE_RNMI)) {
+ nmi_execp = !env->nmie && !async;
+
+ if (env->nmip && async) {
+ env->nmie = false;
+ env->mnstatus = set_field(env->mnstatus, MSTATUS_MPP,
+ env->priv);
+ env->mncause = cause;
+ env->mnepc = env->pc;
+ env->pc = env->rnmi_irqvec;
+ riscv_cpu_set_mode(env, PRV_M);
+ goto handled;
+ }
+ }
if (cause == RISCV_EXCP_SEMIHOST) {
if (env->priv >= PRV_S) {
@@ -967,7 +999,7 @@ 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 &&
+ if (env->priv <= PRV_S && !nmi_execp &&
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
/* handle the trap in S-mode */
if (riscv_has_ext(env, RVH)) {
@@ -1056,8 +1088,15 @@ void riscv_cpu_do_interrupt(CPUState *cs)
env->mepc = env->pc;
env->mbadaddr = tval;
env->mtval2 = mtval2;
- env->pc = (env->mtvec >> 2 << 2) +
- ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+
+ if (nmi_execp) {
+ nextpc = env->rnmi_excpvec;
+ } else {
+ nextpc = (env->mtvec >> 2 << 2) +
+ ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+ }
+ env->pc = nextpc;
+
riscv_cpu_set_mode(env, PRV_M);
}
@@ -1068,6 +1107,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
*/
env->two_stage_lookup = false;
+
+handled:
#endif
cs->exception_index = EXCP_NONE; /* mark handled to qemu */
}
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC v2 3/4] target/riscv: handle RNMI interrupt and exception
@ 2021-04-01 9:26 ` frank.chang
0 siblings, 0 replies; 11+ messages in thread
From: frank.chang @ 2021-04-01 9:26 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Frank Chang, Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
Bastian Koppelmann
From: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
target/riscv/cpu_bits.h | 4 ++++
target/riscv/cpu_helper.c | 49 +++++++++++++++++++++++++++++++++++----
2 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index a376ede0cc5..937b1f28455 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -607,4 +607,8 @@
#define MIE_UTIE (1 << IRQ_U_TIMER)
#define MIE_SSIE (1 << IRQ_S_SOFT)
#define MIE_USIE (1 << IRQ_U_SOFT)
+
+/* RISC-V-specific interrupt pending bits. */
+#define CPU_INTERRUPT_RNMI CPU_INTERRUPT_TGT_EXT_0
+
#endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 21c54ef5613..67a633154a9 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -38,6 +38,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
#ifndef CONFIG_USER_ONLY
static int riscv_cpu_local_irq_pending(CPURISCVState *env)
{
+ if (riscv_feature(env, RISCV_FEATURE_RNMI)) {
+ /* Priority: RNMI > Other interrupt. */
+ if (env->nmip && env->nmie) {
+ return ctz64(env->nmip); /* since non-zero */
+ } else if (!env->nmie) {
+ /*
+ * We are already in RNMI handler,
+ * other interrupts cannot preempt.
+ */
+ return EXCP_NONE;
+ }
+ }
+
target_ulong irqs;
target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
@@ -80,7 +93,9 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
#if !defined(CONFIG_USER_ONLY)
- 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);
@@ -909,6 +924,23 @@ void riscv_cpu_do_interrupt(CPUState *cs)
target_ulong tval = 0;
target_ulong htval = 0;
target_ulong mtval2 = 0;
+ target_ulong nextpc;
+ bool nmi_execp = false;
+
+ if (riscv_feature(env, RISCV_FEATURE_RNMI)) {
+ nmi_execp = !env->nmie && !async;
+
+ if (env->nmip && async) {
+ env->nmie = false;
+ env->mnstatus = set_field(env->mnstatus, MSTATUS_MPP,
+ env->priv);
+ env->mncause = cause;
+ env->mnepc = env->pc;
+ env->pc = env->rnmi_irqvec;
+ riscv_cpu_set_mode(env, PRV_M);
+ goto handled;
+ }
+ }
if (cause == RISCV_EXCP_SEMIHOST) {
if (env->priv >= PRV_S) {
@@ -967,7 +999,7 @@ 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 &&
+ if (env->priv <= PRV_S && !nmi_execp &&
cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
/* handle the trap in S-mode */
if (riscv_has_ext(env, RVH)) {
@@ -1056,8 +1088,15 @@ void riscv_cpu_do_interrupt(CPUState *cs)
env->mepc = env->pc;
env->mbadaddr = tval;
env->mtval2 = mtval2;
- env->pc = (env->mtvec >> 2 << 2) +
- ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+
+ if (nmi_execp) {
+ nextpc = env->rnmi_excpvec;
+ } else {
+ nextpc = (env->mtvec >> 2 << 2) +
+ ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
+ }
+ env->pc = nextpc;
+
riscv_cpu_set_mode(env, PRV_M);
}
@@ -1068,6 +1107,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
*/
env->two_stage_lookup = false;
+
+handled:
#endif
cs->exception_index = EXCP_NONE; /* mark handled to qemu */
}
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC v2 4/4] target/riscv: add RNMI mnret instruction
2021-04-01 9:26 [RFC v2 0/4] target/riscv: add RNMI support frank.chang
@ 2021-04-01 9:26 ` frank.chang
2021-04-01 9:26 ` frank.chang
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: frank.chang @ 2021-04-01 9:26 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Keith Packard, Sagar Karandikar, Frank Chang, Bastian Koppelmann,
Bin Meng, Richard Henderson, Alistair Francis, Palmer Dabbelt,
Alex Bennée
From: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
target/riscv/helper.h | 1 +
target/riscv/insn32.decode | 3 ++
.../riscv/insn_trans/trans_privileged.c.inc | 13 ++++++++
target/riscv/op_helper.c | 31 +++++++++++++++++++
4 files changed, 48 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index e3f3f41e891..0914d777d6d 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -65,6 +65,7 @@ DEF_HELPER_4(csrrc, tl, env, tl, tl, tl)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_2(sret, tl, env, tl)
DEF_HELPER_2(mret, tl, env, tl)
+DEF_HELPER_2(mnret, tl, env, tl)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(tlb_flush, void, env)
#endif
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 84080dd18ca..557f3394276 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -97,6 +97,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 32312be2024..63c49dfe6fb 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -106,6 +106,19 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
#endif
}
+static bool trans_mnret(DisasContext *ctx, arg_mnret *a)
+{
+#ifndef CONFIG_USER_ONLY
+ tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+ gen_helper_mnret(cpu_pc, cpu_env, cpu_pc);
+ exit_tb(ctx); /* 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 1eddcb94de7..b9601776153 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -175,6 +175,37 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
return retpc;
}
+target_ulong helper_mnret(CPURISCVState *env, target_ulong cpu_pc_deb)
+{
+ if (!riscv_feature(env, RISCV_FEATURE_RNMI)) {
+ /* 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_MPP);
+
+ if (!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->nmie = true;
+
+ return retpc;
+}
+
void helper_wfi(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC v2 4/4] target/riscv: add RNMI mnret instruction
@ 2021-04-01 9:26 ` frank.chang
0 siblings, 0 replies; 11+ messages in thread
From: frank.chang @ 2021-04-01 9:26 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Frank Chang, Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
Bastian Koppelmann, Alex Bennée, Richard Henderson,
Bin Meng, Keith Packard
From: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Frank Chang <frank.chang@sifive.com>
---
target/riscv/helper.h | 1 +
target/riscv/insn32.decode | 3 ++
.../riscv/insn_trans/trans_privileged.c.inc | 13 ++++++++
target/riscv/op_helper.c | 31 +++++++++++++++++++
4 files changed, 48 insertions(+)
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index e3f3f41e891..0914d777d6d 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -65,6 +65,7 @@ DEF_HELPER_4(csrrc, tl, env, tl, tl, tl)
#ifndef CONFIG_USER_ONLY
DEF_HELPER_2(sret, tl, env, tl)
DEF_HELPER_2(mret, tl, env, tl)
+DEF_HELPER_2(mnret, tl, env, tl)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(tlb_flush, void, env)
#endif
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 84080dd18ca..557f3394276 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -97,6 +97,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 32312be2024..63c49dfe6fb 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -106,6 +106,19 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
#endif
}
+static bool trans_mnret(DisasContext *ctx, arg_mnret *a)
+{
+#ifndef CONFIG_USER_ONLY
+ tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+ gen_helper_mnret(cpu_pc, cpu_env, cpu_pc);
+ exit_tb(ctx); /* 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 1eddcb94de7..b9601776153 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -175,6 +175,37 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
return retpc;
}
+target_ulong helper_mnret(CPURISCVState *env, target_ulong cpu_pc_deb)
+{
+ if (!riscv_feature(env, RISCV_FEATURE_RNMI)) {
+ /* 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_MPP);
+
+ if (!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->nmie = true;
+
+ return retpc;
+}
+
void helper_wfi(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
--
2.17.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RFC v2 0/4] target/riscv: add RNMI support
2021-04-01 9:26 [RFC v2 0/4] target/riscv: add RNMI support frank.chang
@ 2021-04-01 9:36 ` Frank Chang
2021-04-01 9:26 ` frank.chang
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Frank Chang @ 2021-04-01 9:36 UTC (permalink / raw)
To: frank.chang; +Cc: qemu-riscv, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 4480 bytes --]
<frank.chang@sifive.com> 於 2021年4月1日 週四 下午5:27寫道:
> From: Frank Chang <frank.chang@sifive.com>
>
> This patchset add suport of Resumable NMI (RNMI) 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 (0x350)
> * mnepc (0x351)
> * mncause (0x352)
> * mnstatus (0x353)
> =============================================================
> * mnret: To return from RNMI interrupt/exception handler.
> =============================================================
>
> RNMI also has higher priority than any other interrupts or exceptions
> and cannot be disable 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.
>
> The technical proposal of RNMI can be found:
> https://lists.riscv.org/g/tech-privileged/message/421
>
> The port is available here:
> https://github.com/sifive/qemu/tree/nmi-upstream-v2
>
> To test RNMI, we have created another QEMU branch to have
> RNMI feature enabled and also both SiFive Bus Error Unit and
> Error Device included on sifive_e machine.
>
> Bus Error Unit (BEU) is routed to RNMI with mncause value set to 3.
> When any reads or writes to Error Device, it will drive BEU RNMI.
> A freedom-e-sdk RNMI example is also provided for testing.
> (We will also upstream BEU and Error Device in the near future.)
>
> Two -cpu options are added for RNMI and BEU:
> * rnmi=true to enable RNMI feature
> * beu=true to enable BEU feature
>
> Download and build freedom-e-sdk rnmi example:
>
> 1. git clone git@github.com:sifive/freedom-e-sdk.git
> 2. cd freedom-e-sdk
> 3. git checkout origin/dev/yihaoc/nmi -b nmi
> 4. git submodule init
> 5. git submodule update --recursive
> 6. Follow freedom-e-sdk guide to install freedom-e-sdk:
> https://sifive.github.io/freedom-e-sdk-docs/index.html
> 7. make PROGRAM=example-rnmi TARGET=qemu-sifive-e31 \
> CONFIGURATION=release software
>
freedom-e-sdk RNMI example code is available at:
https://github.com/sifive/freedom-e-sdk/tree/dev/yihaoc/nmi/software/example-rnmi
>
> Download, build and run freedom-e-sdk RNMI example on QEMU:
>
> 1. git clone git@github.com:sifive/qemu.git
> 2. cd qemu
> 3. git checkout origin/upstream-nmi-beu-error-device -b
> nmi-beu-error-device
> 4. git submodule init
> 5. git submodule update --recursive
> 6. ./configure --target-list=riscv32-softmmu
> 7. make -j
> 8. <path to qemu-system-riscv32> -nographic -M sifive_e \
> -cpu rv32,rnmi=true,beu=true \
> --bios none -kernel <path to example-rnmi.elf>
>
> Output example:
>
> RNMI Driver Example.
> Cleared accrued bus error
> Enter RNMI interrupt ISR.
> mnscratch: 0x00000000
> mnepc: 0x20401178
> mncause: 0x00000003
> mnstatus: 0x00001800
> Try to trigger illegal instruction exception.
> Enter RNMI exception ISR.
> mscratch: 0x00000000
> mepc: 0x20401208
> mcause: 0x00000002
> mstatus: 0x80007800
> Return from RNMI exception ISR.
> Handled TileLink bus error
> Return from RNMI interrupt ISR.
> Test passed!!
>
> Changelog:
>
> v2
> * split up the series into more commits for convenience of review.
> * add missing rnmi_irqvec and rnmi_excpvec properties to riscv_harts.
>
> Frank Chang (4):
> target/riscv: add RNMI cpu feature
> target/riscv: add RNMI CSRs
> target/riscv: handle RNMI interrupt and exception
> target/riscv: add RNMI mnret instruction
>
> hw/riscv/riscv_hart.c | 8 +++
> include/hw/riscv/riscv_hart.h | 2 +
> target/riscv/cpu.c | 40 +++++++++++++
> target/riscv/cpu.h | 16 ++++-
> target/riscv/cpu_bits.h | 19 ++++++
> target/riscv/cpu_helper.c | 49 +++++++++++++--
> target/riscv/csr.c | 59 +++++++++++++++++++
> target/riscv/helper.h | 1 +
> target/riscv/insn32.decode | 3 +
> .../riscv/insn_trans/trans_privileged.c.inc | 13 ++++
> target/riscv/op_helper.c | 31 ++++++++++
> 11 files changed, 236 insertions(+), 5 deletions(-)
>
> --
> 2.17.1
>
>
>
[-- Attachment #2: Type: text/html, Size: 5810 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC v2 0/4] target/riscv: add RNMI support
@ 2021-04-01 9:36 ` Frank Chang
0 siblings, 0 replies; 11+ messages in thread
From: Frank Chang @ 2021-04-01 9:36 UTC (permalink / raw)
To: frank.chang; +Cc: qemu-devel, qemu-riscv
[-- Attachment #1: Type: text/plain, Size: 4480 bytes --]
<frank.chang@sifive.com> 於 2021年4月1日 週四 下午5:27寫道:
> From: Frank Chang <frank.chang@sifive.com>
>
> This patchset add suport of Resumable NMI (RNMI) 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 (0x350)
> * mnepc (0x351)
> * mncause (0x352)
> * mnstatus (0x353)
> =============================================================
> * mnret: To return from RNMI interrupt/exception handler.
> =============================================================
>
> RNMI also has higher priority than any other interrupts or exceptions
> and cannot be disable 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.
>
> The technical proposal of RNMI can be found:
> https://lists.riscv.org/g/tech-privileged/message/421
>
> The port is available here:
> https://github.com/sifive/qemu/tree/nmi-upstream-v2
>
> To test RNMI, we have created another QEMU branch to have
> RNMI feature enabled and also both SiFive Bus Error Unit and
> Error Device included on sifive_e machine.
>
> Bus Error Unit (BEU) is routed to RNMI with mncause value set to 3.
> When any reads or writes to Error Device, it will drive BEU RNMI.
> A freedom-e-sdk RNMI example is also provided for testing.
> (We will also upstream BEU and Error Device in the near future.)
>
> Two -cpu options are added for RNMI and BEU:
> * rnmi=true to enable RNMI feature
> * beu=true to enable BEU feature
>
> Download and build freedom-e-sdk rnmi example:
>
> 1. git clone git@github.com:sifive/freedom-e-sdk.git
> 2. cd freedom-e-sdk
> 3. git checkout origin/dev/yihaoc/nmi -b nmi
> 4. git submodule init
> 5. git submodule update --recursive
> 6. Follow freedom-e-sdk guide to install freedom-e-sdk:
> https://sifive.github.io/freedom-e-sdk-docs/index.html
> 7. make PROGRAM=example-rnmi TARGET=qemu-sifive-e31 \
> CONFIGURATION=release software
>
freedom-e-sdk RNMI example code is available at:
https://github.com/sifive/freedom-e-sdk/tree/dev/yihaoc/nmi/software/example-rnmi
>
> Download, build and run freedom-e-sdk RNMI example on QEMU:
>
> 1. git clone git@github.com:sifive/qemu.git
> 2. cd qemu
> 3. git checkout origin/upstream-nmi-beu-error-device -b
> nmi-beu-error-device
> 4. git submodule init
> 5. git submodule update --recursive
> 6. ./configure --target-list=riscv32-softmmu
> 7. make -j
> 8. <path to qemu-system-riscv32> -nographic -M sifive_e \
> -cpu rv32,rnmi=true,beu=true \
> --bios none -kernel <path to example-rnmi.elf>
>
> Output example:
>
> RNMI Driver Example.
> Cleared accrued bus error
> Enter RNMI interrupt ISR.
> mnscratch: 0x00000000
> mnepc: 0x20401178
> mncause: 0x00000003
> mnstatus: 0x00001800
> Try to trigger illegal instruction exception.
> Enter RNMI exception ISR.
> mscratch: 0x00000000
> mepc: 0x20401208
> mcause: 0x00000002
> mstatus: 0x80007800
> Return from RNMI exception ISR.
> Handled TileLink bus error
> Return from RNMI interrupt ISR.
> Test passed!!
>
> Changelog:
>
> v2
> * split up the series into more commits for convenience of review.
> * add missing rnmi_irqvec and rnmi_excpvec properties to riscv_harts.
>
> Frank Chang (4):
> target/riscv: add RNMI cpu feature
> target/riscv: add RNMI CSRs
> target/riscv: handle RNMI interrupt and exception
> target/riscv: add RNMI mnret instruction
>
> hw/riscv/riscv_hart.c | 8 +++
> include/hw/riscv/riscv_hart.h | 2 +
> target/riscv/cpu.c | 40 +++++++++++++
> target/riscv/cpu.h | 16 ++++-
> target/riscv/cpu_bits.h | 19 ++++++
> target/riscv/cpu_helper.c | 49 +++++++++++++--
> target/riscv/csr.c | 59 +++++++++++++++++++
> target/riscv/helper.h | 1 +
> target/riscv/insn32.decode | 3 +
> .../riscv/insn_trans/trans_privileged.c.inc | 13 ++++
> target/riscv/op_helper.c | 31 ++++++++++
> 11 files changed, 236 insertions(+), 5 deletions(-)
>
> --
> 2.17.1
>
>
>
[-- Attachment #2: Type: text/html, Size: 5810 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread