[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC v2 1/4] target/riscv: add RNMI cpu feature
From: |
frank . chang |
Subject: |
[RFC v2 1/4] target/riscv: add RNMI cpu feature |
Date: |
Thu, 1 Apr 2021 17:26:48 +0800 |
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