From: Frank Chang <frank.ch...@sifive.com> Signed-off-by: Frank Chang <frank.ch...@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