diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index 7c0e32d9d41a2..2fd1bd688ea49 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -361,12 +361,29 @@ static void parse_hart_config(SiFivePLICState *plic) static void sifive_plic_irq_request(void *opaque, int irq, int level) { - SiFivePLICState *s = opaque; + SiFivePLICState *plic = opaque; - assert(irq < s->num_sources); + assert(irq < plic->num_sources); - sifive_plic_set_pending(s, irq, level > 0); - sifive_plic_update(s); + /* + * In OpenTitan (or more generally when we have a system with support for + * NMIs), we only want to clear a pending IRQ at the PLIC when it has + * been claimed. Normally this is not a problem - the IRQ will cause + * software to acknowledge the pending IRQ at the peripheral, which will + * propagate to the PLIC, which has already been serviced. But with NMIs, + * we have the case where (a) a peripheral generates an NMI and IRQ, (b) + * the NMI handler disables the IRQ at the peripheral, as part of + * acknowleding the NMI, (c) this would cause the PLIC to de-assert the + * IRQ, but since we haven't claimed it yet we still want it to call our + * ISR handler as normal after the NMI handler exits. So, we should only + * de-assert a pending IRQ when it is claimed. + */ + bool is_claimed = (plic->claimed[irq >> 5] & (1u << (irq & 31))); + bool is_pending = (plic->pending[irq >> 5] & (1u << (irq & 31))); + if (level || (!is_pending || is_claimed)) { + sifive_plic_set_pending(plic, irq, level > 0); + } + sifive_plic_update(plic); } static void sifive_plic_realize(DeviceState *dev, Error **errp) diff --git a/hw/misc/pulp_rv_dm.c b/hw/misc/pulp_rv_dm.c index 637957bb10edc..0632763f7b0f9 100644 --- a/hw/misc/pulp_rv_dm.c +++ b/hw/misc/pulp_rv_dm.c @@ -133,7 +133,7 @@ struct PulpRVDMState { MemoryRegion rom; /* ROM */ qemu_irq *ack_out; - IbexIRQ alert; + qemu_irq alert; uint32_t dmflag_regs[PULP_RV_DM_DMFLAG_SIZE / sizeof(uint32_t)]; @@ -259,7 +259,7 @@ static void pulp_rv_dm_regs_write(void *opaque, hwaddr addr, uint64_t val64, switch (R32_OFF(addr)) { case R_ALERT_TEST: val32 &= R_ALERT_TEST_FATAL_FAULT_MASK; - ibex_irq_set(&s->alert, (int)(bool)val32); + qemu_set_irq(s->alert, (int)(bool)val32); break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", @@ -477,7 +477,7 @@ static void pulp_rv_dm_reset(DeviceState *dev) { PulpRVDMState *s = PULP_RV_DM(dev); - ibex_irq_set(&s->alert, false); + qemu_set_irq(s->alert, false); memset(memory_region_get_ram_ptr(&s->prog), 0, PULP_RV_DM_PROG_SIZE); memset(s->dmflag_regs, 0, sizeof(s->dmflag_regs)); @@ -524,7 +524,7 @@ static void pulp_rv_dm_init(Object *obj) pulp_rv_dm_load_rom(s); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); } static void pulp_rv_dm_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_aes.c b/hw/opentitan/ot_aes.c index 2120ff6308a13..6cd1d0246c9de 100644 --- a/hw/opentitan/ot_aes.c +++ b/hw/opentitan/ot_aes.c @@ -237,7 +237,7 @@ enum OtAESMode { struct OtAESState { SysBusDevice parent_obj; MemoryRegion mmio; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + qemu_irq alerts[PARAM_NUM_ALERTS]; IbexIRQ clkmgr; QEMUBH *process_bh; QEMUTimer *retard_timer; /* only used with disabled fast-mode */ @@ -328,7 +328,7 @@ static void ot_aes_update_alert(OtAESState *s) { for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { bool level = (bool)(s->regs->status & (1u << ix)); - ibex_irq_set(&s->alerts[ix], (int)level); + qemu_set_irq(s->alerts[ix], (int)level); } } @@ -1269,7 +1269,7 @@ static void ot_aes_reset(DeviceState *dev) ot_aes_load_reseed_rate(s); for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], 0); + qemu_set_irq(s->alerts[ix], 0); } trace_ot_aes_reseed("reset"); @@ -1294,7 +1294,8 @@ static void ot_aes_init(Object *obj) } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } ibex_qdev_init_irq(obj, &s->clkmgr, OT_CLOCK_ACTIVE); diff --git a/hw/opentitan/ot_alert.c b/hw/opentitan/ot_alert.c index 16d2c419f6fd4..dd3f5aeb0c7d4 100644 --- a/hw/opentitan/ot_alert.c +++ b/hw/opentitan/ot_alert.c @@ -220,6 +220,7 @@ struct OtAlertState { MemoryRegion mmio; IbexIRQ *irqs; IbexIRQ *esc_txs; + IbexIRQ nmi_alert; OtAlertScheduler *schedulers; OtAlertRegs regs; /* not ordered by register index */ @@ -571,6 +572,7 @@ static void ot_alert_clear_alert(OtAlertState *s, unsigned nclass) trace_ot_alert_escalation(s->ot_id, ACLASS(nclass), ix, "release"); } ibex_irq_set(esc_tx, 0); + ibex_irq_set(&s->nmi_alert, 0u); } /* * "Software can clear CLASSn_ACCUM_CNT with a write to CLASSA_CLR_SHADOWED" @@ -741,6 +743,10 @@ static void ot_alert_signal_tx(void *opaque, int n, int level) trace_ot_alert_signal_tx(s->ot_id, alert, (bool)level, alert_en); + if (alert_en && level) { + ibex_irq_set(&s->nmi_alert, 1u); + } + if (!alert_en || !level) { /* releasing the alert does not clear it */ return; @@ -1034,6 +1040,7 @@ static void ot_alert_realize(DeviceState *dev, Error **errp) s->esc_txs = g_new0(IbexIRQ, PARAM_N_ESC_SEV); ibex_qdev_init_irqs(OBJECT(dev), s->esc_txs, OT_ALERT_ESCALATE, PARAM_N_ESC_SEV); + ibex_qdev_init_irq(OBJECT(dev), &s->nmi_alert, OT_ALERT_NMI); qdev_init_gpio_in_named(dev, &ot_alert_signal_tx, OT_DEVICE_ALERT, s->n_alerts); diff --git a/hw/opentitan/ot_aon_timer.c b/hw/opentitan/ot_aon_timer.c index e8c0ee29b9e2a..5b81882738d86 100644 --- a/hw/opentitan/ot_aon_timer.c +++ b/hw/opentitan/ot_aon_timer.c @@ -47,21 +47,23 @@ REG32(ALERT_TEST, 0x00u) REG32(WKUP_CTRL, 0x04u) FIELD(WKUP_CTRL, ENABLE, 0u, 1u) FIELD(WKUP_CTRL, PRESCALER, 1u, 12u) -REG32(WKUP_THOLD, 0x08) -REG32(WKUP_COUNT, 0x0cu) -REG32(WDOG_REGWEN, 0x10u) +REG32(WKUP_THOLD_HI, 0x08u) +REG32(WKUP_THOLD_LO, 0x0cu) +REG32(WKUP_COUNT_HI, 0x10u) +REG32(WKUP_COUNT_LO, 0x14u) +REG32(WDOG_REGWEN, 0x18u) FIELD(WDOG_REGWEN, REGWEN, 0u, 1u) -REG32(WDOG_CTRL, 0x14u) +REG32(WDOG_CTRL, 0x1cu) FIELD(WDOG_CTRL, ENABLE, 0u, 1u) - FIELD(WDOG_CTRL, PAUSE_IN_SLEEP, 0u, 1u) -REG32(WDOG_BARK_THOLD, 0x18u) -REG32(WDOG_BITE_THOLD, 0x1cu) -REG32(WDOG_COUNT, 0x20u) -REG32(INTR_STATE, 0x24u) + FIELD(WDOG_CTRL, PAUSE_IN_SLEEP, 1u, 1u) +REG32(WDOG_BARK_THOLD, 0x20u) +REG32(WDOG_BITE_THOLD, 0x24u) +REG32(WDOG_COUNT, 0x28u) +REG32(INTR_STATE, 0x2cu) SHARED_FIELD(INTR_WKUP_TIMER_EXPIRED, 0u, 1u) SHARED_FIELD(INTR_WDOG_TIMER_BARK, 1u, 1u) -REG32(INTR_TEST, 0x28u) -REG32(WKUP_CAUSE, 0x2cu) +REG32(INTR_TEST, 0x30u) +REG32(WKUP_CAUSE, 0x34u) FIELD(WKUP_CAUSE, CAUSE, 0u, 1u) /* clang-format on */ @@ -80,8 +82,10 @@ static const char REG_NAMES[REGS_COUNT][20u] = { /* clang-format off */ REG_NAME_ENTRY(ALERT_TEST), REG_NAME_ENTRY(WKUP_CTRL), - REG_NAME_ENTRY(WKUP_THOLD), - REG_NAME_ENTRY(WKUP_COUNT), + REG_NAME_ENTRY(WKUP_THOLD_HI), + REG_NAME_ENTRY(WKUP_THOLD_LO), + REG_NAME_ENTRY(WKUP_COUNT_HI), + REG_NAME_ENTRY(WKUP_COUNT_LO), REG_NAME_ENTRY(WDOG_REGWEN), REG_NAME_ENTRY(WDOG_CTRL), REG_NAME_ENTRY(WDOG_BARK_THOLD), @@ -104,7 +108,7 @@ struct OtAonTimerState { IbexIRQ nmi_bark; IbexIRQ pwrmgr_wkup; IbexIRQ pwrmgr_bite; - IbexIRQ alert; + qemu_irq alert; QEMUTimer *wkup_timer; QEMUTimer *wdog_timer; @@ -119,28 +123,30 @@ struct OtAonTimerState { uint32_t pclk; }; -static uint32_t +static uint64_t ot_aon_timer_ns_to_ticks(OtAonTimerState *s, uint32_t prescaler, int64_t ns) { uint64_t ticks = muldiv64((uint64_t)ns, s->pclk, NANOSECONDS_PER_SECOND); - return (uint32_t)(ticks / (prescaler + 1u)); + return ticks / (prescaler + 1u); } static int64_t -ot_aon_timer_ticks_to_ns(OtAonTimerState *s, uint32_t prescaler, uint32_t ticks) +ot_aon_timer_ticks_to_ns(OtAonTimerState *s, uint32_t prescaler, uint64_t ticks) { - uint64_t ns = muldiv64((uint64_t)ticks * (prescaler + 1u), - NANOSECONDS_PER_SECOND, s->pclk); + uint64_t ns = + muldiv64(ticks * (prescaler + 1u), NANOSECONDS_PER_SECOND, s->pclk); if (ns > INT64_MAX) { return INT64_MAX; } return (int64_t)ns; } -static uint32_t ot_aon_timer_get_wkup_count(OtAonTimerState *s, uint64_t now) +static uint64_t ot_aon_timer_get_wkup_count(OtAonTimerState *s, uint64_t now) { uint32_t prescaler = FIELD_EX32(s->regs[R_WKUP_CTRL], WKUP_CTRL, PRESCALER); - return s->regs[R_WKUP_COUNT] + + uint64_t wkup_count = + ((uint64_t)s->regs[R_WKUP_COUNT_HI] << 32u) | s->regs[R_WKUP_COUNT_LO]; + return wkup_count + ot_aon_timer_ns_to_ticks(s, prescaler, (int64_t)(now - s->wkup_origin_ns)); } @@ -148,7 +154,9 @@ static uint32_t ot_aon_timer_get_wkup_count(OtAonTimerState *s, uint64_t now) static uint32_t ot_aon_timer_get_wdog_count(OtAonTimerState *s, uint64_t now) { return s->regs[R_WDOG_COUNT] + - ot_aon_timer_ns_to_ticks(s, 0u, (int64_t)(now - s->wdog_origin_ns)); + (uint32_t) + ot_aon_timer_ns_to_ticks(s, 0u, + (int64_t)(now - s->wdog_origin_ns)); } static int64_t ot_aon_timer_compute_next_timeout(OtAonTimerState *s, @@ -185,19 +193,18 @@ static inline bool ot_aon_timer_wdog_register_write_enabled(OtAonTimerState *s) static void ot_aon_timer_update_alert(OtAonTimerState *s) { bool level = s->regs[R_ALERT_TEST] & R_ALERT_TEST_FATAL_FAULT_MASK; - ibex_irq_set(&s->alert, level); + qemu_set_irq(s->alert, level); } static void ot_aon_timer_update_irqs(OtAonTimerState *s) { bool wkup = (bool)(s->regs[R_INTR_STATE] & INTR_WKUP_TIMER_EXPIRED_MASK); bool bark = (bool)(s->regs[R_INTR_STATE] & INTR_WDOG_TIMER_BARK_MASK); - trace_ot_aon_timer_irqs(s->ot_id, wkup, bark, s->wdog_bite); ibex_irq_set(&s->irq_wkup, wkup); - ibex_irq_set(&s->irq_bark, bark); ibex_irq_set(&s->nmi_bark, bark); + ibex_irq_set(&s->irq_bark, bark); ibex_irq_set(&s->pwrmgr_wkup, wkup); ibex_irq_set(&s->pwrmgr_bite, s->wdog_bite); } @@ -218,8 +225,9 @@ static void ot_aon_timer_rearm_wkup(OtAonTimerState *s, bool reset_origin) return; } - uint32_t count = ot_aon_timer_get_wkup_count(s, now); - uint32_t threshold = s->regs[R_WKUP_THOLD]; + uint64_t count = ot_aon_timer_get_wkup_count(s, now); + uint64_t threshold = + ((uint64_t)s->regs[R_WKUP_THOLD_HI] << 32u) | s->regs[R_WKUP_THOLD_LO]; if (count >= threshold) { s->regs[R_INTR_STATE] |= INTR_WKUP_TIMER_EXPIRED_MASK; @@ -309,7 +317,8 @@ static uint64_t ot_aon_timer_read(void *opaque, hwaddr addr, unsigned size) hwaddr reg = R32_OFF(addr); switch (reg) { case R_WKUP_CTRL: - case R_WKUP_THOLD: + case R_WKUP_THOLD_HI: + case R_WKUP_THOLD_LO: case R_WDOG_REGWEN: case R_WDOG_CTRL: case R_WDOG_BARK_THOLD: @@ -318,11 +327,18 @@ static uint64_t ot_aon_timer_read(void *opaque, hwaddr addr, unsigned size) case R_WKUP_CAUSE: val32 = s->regs[reg]; break; - case R_WKUP_COUNT: { + case R_WKUP_COUNT_HI: { + uint64_t now = ot_aon_timer_is_wkup_enabled(s) ? + qemu_clock_get_ns(OT_VIRTUAL_CLOCK) : + s->wkup_origin_ns; + val32 = (uint32_t)(ot_aon_timer_get_wkup_count(s, now) >> 32u); + break; + } + case R_WKUP_COUNT_LO: { uint64_t now = ot_aon_timer_is_wkup_enabled(s) ? qemu_clock_get_ns(OT_VIRTUAL_CLOCK) : s->wkup_origin_ns; - val32 = ot_aon_timer_get_wkup_count(s, now); + val32 = (uint32_t)ot_aon_timer_get_wkup_count(s, now); break; } case R_WDOG_COUNT: { @@ -384,19 +400,23 @@ static void ot_aon_timer_write(void *opaque, hwaddr addr, uint64_t value, /* stop timer */ timer_del(s->wkup_timer); /* save current count */ - uint32_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); - s->regs[R_WKUP_COUNT] = ot_aon_timer_get_wkup_count(s, now); + int64_t now = qemu_clock_get_ns(OT_VIRTUAL_CLOCK); + uint64_t count = ot_aon_timer_get_wkup_count(s, now); + s->regs[R_WKUP_COUNT_HI] = (uint32_t)(count >> 32u); + s->regs[R_WKUP_COUNT_LO] = (uint32_t)count; s->wkup_origin_ns = now; } } break; } - case R_WKUP_THOLD: - s->regs[R_WKUP_THOLD] = val32; + case R_WKUP_THOLD_HI: + case R_WKUP_THOLD_LO: + s->regs[reg] = val32; ot_aon_timer_rearm_wkup(s, false); break; - case R_WKUP_COUNT: - s->regs[R_WKUP_COUNT] = val32; + case R_WKUP_COUNT_HI: + case R_WKUP_COUNT_LO: + s->regs[reg] = val32; ot_aon_timer_rearm_wkup(s, true); break; case R_WDOG_REGWEN: @@ -525,7 +545,7 @@ static void ot_aon_timer_init(Object *obj) ibex_qdev_init_irq(obj, &s->nmi_bark, OT_AON_TIMER_BARK); ibex_qdev_init_irq(obj, &s->pwrmgr_wkup, OT_AON_TIMER_WKUP); ibex_qdev_init_irq(obj, &s->pwrmgr_bite, OT_AON_TIMER_BITE); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); memory_region_init_io(&s->mmio, obj, &ot_aon_timer_ops, s, TYPE_OT_AON_TIMER, REGS_SIZE); diff --git a/hw/opentitan/ot_clkmgr.c b/hw/opentitan/ot_clkmgr.c index c36bfaebb5115..575bce0091bcf 100644 --- a/hw/opentitan/ot_clkmgr.c +++ b/hw/opentitan/ot_clkmgr.c @@ -190,7 +190,7 @@ struct OtClkMgrState { SysBusDevice parent_obj; MemoryRegion mmio; IbexIRQ hints[OT_CLKMGR_HINT_COUNT]; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + qemu_irq alerts[PARAM_NUM_ALERTS]; uint32_t clock_states; /* bit set: active, reset: clock is idle */ uint32_t regs[REGS_COUNT]; /* shadowed slots are not used */ @@ -210,7 +210,7 @@ static void ot_clkmgr_update_alerts(OtClkMgrState *s) { bool recov = (bool)(s->regs[R_RECOV_ERR_CODE] & R_RECOV_ERR_CODE_SHADOW_UPDATE_ERR_MASK); - ibex_irq_set(&s->alerts[ALERT_RECOVERABLE], recov); + qemu_set_irq(s->alerts[ALERT_RECOVERABLE], recov); } static void ot_clkmgr_clock_hint(void *opaque, int irq, int level) @@ -320,7 +320,7 @@ static void ot_clkmgr_write(void *opaque, hwaddr addr, uint64_t val64, case R_ALERT_TEST: val32 &= ALERT_TEST_MASK; for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], (int)((val32 >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((val32 >> ix) & 0x1u)); } break; case R_EXTCLK_CTRL_REGWEN: @@ -565,7 +565,7 @@ static void ot_clkmgr_reset(DeviceState *dev) ot_shadow_reg_init(&s->sdw_regs.usb_meas_ctrl, 0x1ccfau); for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], 0); + qemu_set_irq(s->alerts[ix], 0); } } @@ -578,7 +578,8 @@ static void ot_clkmgr_init(Object *obj) sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } qdev_init_gpio_in_named(DEVICE(obj), &ot_clkmgr_clock_hint, OT_CLKMGR_HINT, diff --git a/hw/opentitan/ot_csrng.c b/hw/opentitan/ot_csrng.c index 144c4dccef0d6..444922486b139 100644 --- a/hw/opentitan/ot_csrng.c +++ b/hw/opentitan/ot_csrng.c @@ -311,7 +311,7 @@ struct OtCSRNGState { MemoryRegion mmio; IbexIRQ irqs[PARAM_NUM_IRQS]; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + qemu_irq alerts[PARAM_NUM_ALERTS]; QEMUBH *cmd_scheduler; QEMUTimer *entropy_scheduler; @@ -781,7 +781,7 @@ static void ot_csrng_update_alerts(OtCSRNGState *s) } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -1848,7 +1848,7 @@ static void ot_csrng_reset(DeviceState *dev) } ot_csrng_update_irqs(s); for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], 0); + qemu_set_irq(s->alerts[ix], 0); } while (!QSIMPLEQ_EMPTY(&s->cmd_requests)) { @@ -1875,7 +1875,8 @@ static void ot_csrng_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irqs[ix]); } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } qdev_init_gpio_in_named_with_opaque(DEVICE(s), &ot_csrng_hwapp_ready_irq, s, diff --git a/hw/opentitan/ot_edn.c b/hw/opentitan/ot_edn.c index 8c28d9a3c53c4..b868287d510e6 100644 --- a/hw/opentitan/ot_edn.c +++ b/hw/opentitan/ot_edn.c @@ -237,7 +237,7 @@ struct OtEDNState { MemoryRegion mmio; IbexIRQ irqs[PARAM_NUM_IRQS]; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + qemu_irq alerts[PARAM_NUM_ALERTS]; QEMUBH *ep_bh; /**< Endpoint requests */ uint32_t *regs; @@ -377,7 +377,7 @@ static void ot_edn_update_alerts(OtEDNState *s) level |= 1u << ALERT_RECOVERABLE; } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -1338,7 +1338,8 @@ static void ot_edn_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irqs[ix]); } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } qdev_init_gpio_in_named_with_opaque(DEVICE(s), &ot_edn_csrng_ack_irq, s, TYPE_OT_EDN "-req_sts", 1); diff --git a/hw/opentitan/ot_entropy_src.c b/hw/opentitan/ot_entropy_src.c index 78971f58b7927..dbf3920d7acf8 100644 --- a/hw/opentitan/ot_entropy_src.c +++ b/hw/opentitan/ot_entropy_src.c @@ -365,7 +365,7 @@ struct OtEntropySrcState { MemoryRegion mmio; IbexIRQ irqs[PARAM_NUM_IRQS]; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + qemu_irq alerts[PARAM_NUM_ALERTS]; QEMUTimer *scheduler; uint32_t *regs; @@ -728,7 +728,7 @@ static void ot_entropy_src_update_alerts(OtEntropySrcState *s) } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -1588,7 +1588,7 @@ static void ot_entropy_src_reset(DeviceState *dev) ot_entropy_src_update_irqs(s); for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], 0); + qemu_set_irq(s->alerts[ix], 0); } OtOTPStateClass *oc = @@ -1614,7 +1614,8 @@ static void ot_entropy_src_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irqs[ix]); } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } ot_fifo32_create(&s->input_fifo, OT_ENTROPY_SRC_FILL_WORD_COUNT * 2u); diff --git a/hw/opentitan/ot_flash.c b/hw/opentitan/ot_flash.c index 8c98b0eeedda8..34c4d933a074e 100644 --- a/hw/opentitan/ot_flash.c +++ b/hw/opentitan/ot_flash.c @@ -645,7 +645,7 @@ struct OtFlashState { } mmio; QEMUTimer *op_delay; /* simulated long lasting operation */ IbexIRQ irqs[PARAM_NUM_IRQS]; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + qemu_irq alerts[PARAM_NUM_ALERTS]; uint32_t *regs; uint32_t *csrs; @@ -677,7 +677,7 @@ static void ot_flash_update_alerts(OtFlashState *s) uint32_t level = s->regs[R_ALERT_TEST]; for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -1827,7 +1827,8 @@ static void ot_flash_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irqs[ix]); } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } s->op_delay = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_flash_op_signal, s); } diff --git a/hw/opentitan/ot_gpio_eg.c b/hw/opentitan/ot_gpio_eg.c index 7decec51e10f9..87efbfc6b956b 100644 --- a/hw/opentitan/ot_gpio_eg.c +++ b/hw/opentitan/ot_gpio_eg.c @@ -112,7 +112,7 @@ struct OtGpioEgState { IbexIRQ *irqs; IbexIRQ *gpos; - IbexIRQ alert; + qemu_irq alert; MemoryRegion mmio; @@ -407,7 +407,7 @@ static void ot_gpio_eg_write(void *opaque, hwaddr addr, uint64_t val64, break; case R_ALERT_TEST: val32 &= ALERT_TEST_MASK; - ibex_irq_set(&s->alert, (int)(bool)val32); + qemu_set_irq(s->alert, (int)(bool)val32); break; case R_DIRECT_OUT: s->regs[reg] = val32; @@ -729,7 +729,7 @@ static void ot_gpio_eg_reset(DeviceState *dev) s->regs[R_DIRECT_OE] = s->reset_oe; ot_gpio_eg_update_irqs(s); - ibex_irq_set(&s->alert, 0); + qemu_set_irq(s->alert, 0); ot_gpio_eg_init_backend(s); ot_gpio_eg_update_data_out(s); @@ -766,7 +766,7 @@ static void ot_gpio_eg_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irqs[ix]); } ibex_qdev_init_irqs_default(obj, s->gpos, OT_GPIO_OUT, PARAM_NUM_IO, -1); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); qdev_init_gpio_in_named(DEVICE(obj), &ot_gpio_eg_in_change, OT_GPIO_IN, PARAM_NUM_IO); diff --git a/hw/opentitan/ot_hmac.c b/hw/opentitan/ot_hmac.c index 7c276e11179c5..d464ed807428e 100644 --- a/hw/opentitan/ot_hmac.c +++ b/hw/opentitan/ot_hmac.c @@ -274,7 +274,7 @@ struct OtHMACState { MemoryRegion fifo_mmio; IbexIRQ irqs[PARAM_NUM_IRQS]; - IbexIRQ alert; + qemu_irq alert; IbexIRQ clkmgr; OtHMACRegisters *regs; @@ -401,7 +401,7 @@ static void ot_hmac_update_irqs(OtHMACState *s) static void ot_hmac_update_alert(OtHMACState *s) { bool level = s->regs->alert_test & R_ALERT_TEST_FATAL_FAULT_MASK; - ibex_irq_set(&s->alert, level); + qemu_set_irq(s->alert, level); } static void ot_hmac_report_error(OtHMACState *s, uint32_t error) @@ -1206,7 +1206,7 @@ static void ot_hmac_init(Object *obj) for (unsigned ix = 0; ix < PARAM_NUM_IRQS; ix++) { ibex_sysbus_init_irq(obj, &s->irqs[ix]); } - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); ibex_qdev_init_irq(obj, &s->clkmgr, OT_CLOCK_ACTIVE); memory_region_init(&s->mmio, OBJECT(s), TYPE_OT_HMAC, OT_HMAC_WHOLE_SIZE); diff --git a/hw/opentitan/ot_ibex_wrapper_eg.c b/hw/opentitan/ot_ibex_wrapper_eg.c index 1827e9d1f8416..32d1caab8302a 100644 --- a/hw/opentitan/ot_ibex_wrapper_eg.c +++ b/hw/opentitan/ot_ibex_wrapper_eg.c @@ -83,8 +83,8 @@ REG32(DBUS_ADDR_MATCHING_1, 0x40u) REG32(DBUS_REMAP_ADDR_0, 0x44u) REG32(DBUS_REMAP_ADDR_1, 0x48u) REG32(NMI_ENABLE, 0x4cu) - SHARED_FIELD(NMI_ALERT_EN_BIT, 0u, 1u) - SHARED_FIELD(NMI_WDOG_EN_BIT, 1u, 1u) + SHARED_FIELD(NMI_ALERT_EN_BIT, OT_IBEX_NMI_ALERT, 1u) + SHARED_FIELD(NMI_WDOG_EN_BIT, OT_IBEX_NMI_WDOG, 1u) REG32(NMI_STATE, 0x50u) REG32(ERR_STATUS, 0x54u) FIELD(ERR_STATUS, REG_INTG, 0u, 1u) @@ -224,7 +224,8 @@ struct OtIbexWrapperEgState { MemoryRegion mmio; MemoryRegion remappers[PARAM_NUM_REGIONS]; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + qemu_irq alerts[PARAM_NUM_ALERTS]; + IbexIRQ nmi_irq; uint32_t *regs; OtIbexTestLogEngine *log_engine; @@ -254,7 +255,7 @@ static void ot_ibex_wrapper_eg_update_alerts(OtIbexWrapperEgState *s) } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -770,6 +771,24 @@ static void ot_ibex_wrapper_eg_cpu_enable_recv(void *opaque, int n, int level) ot_ibex_wrapper_eg_update_exec(s); } +static void ot_ibex_wrapper_eg_nmi_recv(void *opaque, int n, int level) +{ + OtIbexWrapperEgState *s = opaque; + + g_assert((unsigned)n < OT_IBEX_NMI_COUNT); + + /* NMI_STATE is rw1c, so must be cleared with a register write. */ + if (level) { + s->regs[R_NMI_STATE] |= 1u << (unsigned)n; + } + + trace_ot_ibex_wrapper_nmi_recv(s->ot_id ?: "", n ? "WDOG" : "ALERT", + (bool)level); + + uint32_t nmi_active = s->regs[R_NMI_ENABLE] & s->regs[R_NMI_STATE]; + ibex_irq_set(&s->nmi_irq, (bool)nmi_active); +} + static void ot_ibex_wrapper_eg_escalate_rx(void *opaque, int n, int level) { OtIbexWrapperEgState *s = opaque; @@ -910,6 +929,12 @@ static void ot_ibex_wrapper_eg_regs_write(void *opaque, hwaddr addr, } ot_ibex_wrapper_eg_update_remap(s, true, reg - R_DBUS_REMAP_ADDR_0); break; + case R_NMI_ENABLE: + s->regs[reg] |= val32; /* rw1s */ + break; + case R_NMI_STATE: + s->regs[reg] &= ~val32; /* rw1c */ + break; case R_DV_SIM_STATUS: ot_ibex_wrapper_eg_status_report(s, val32); switch (val32) { @@ -1014,14 +1039,19 @@ static void ot_ibex_wrapper_eg_init(Object *obj) TYPE_OT_IBEX_WRAPPER_EG, REGS_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } qdev_init_gpio_in_named(DEVICE(obj), &ot_ibex_wrapper_eg_cpu_enable_recv, OT_IBEX_WRAPPER_CPU_EN, OT_IBEX_CPU_EN_COUNT); + qdev_init_gpio_in_named(DEVICE(obj), &ot_ibex_wrapper_eg_nmi_recv, + OT_IBEX_WRAPPER_NMI, OT_IBEX_NMI_COUNT); qdev_init_gpio_in_named(DEVICE(obj), &ot_ibex_wrapper_eg_escalate_rx, OT_ALERT_ESCALATE, 1); + ibex_qdev_init_irq(obj, &s->nmi_irq, NULL); + s->regs = g_new0(uint32_t, REGS_COUNT); s->log_engine = g_new0(OtIbexTestLogEngine, 1u); } diff --git a/hw/opentitan/ot_kmac.c b/hw/opentitan/ot_kmac.c index 013dcc1f49bb3..d82f5fa0ea3f0 100644 --- a/hw/opentitan/ot_kmac.c +++ b/hw/opentitan/ot_kmac.c @@ -379,7 +379,7 @@ struct OtKMACState { MemoryRegion state_mmio; MemoryRegion msgfifo_mmio; IbexIRQ irqs[3u]; - IbexIRQ alerts[KMAC_PARAM_NUM_ALERTS]; + qemu_irq alerts[KMAC_PARAM_NUM_ALERTS]; uint32_t *regs; OtShadowReg cfg; @@ -467,7 +467,7 @@ static void ot_kmac_update_alert(OtKMACState *s) } for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -1618,7 +1618,8 @@ static void ot_kmac_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irqs[ix]); } for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } memory_region_init(&s->mmio, OBJECT(s), TYPE_OT_KMAC, OT_KMAC_WHOLE_SIZE); diff --git a/hw/opentitan/ot_lc_ctrl.c b/hw/opentitan/ot_lc_ctrl.c index 47ebb9f8b1c80..1ae867979e410 100644 --- a/hw/opentitan/ot_lc_ctrl.c +++ b/hw/opentitan/ot_lc_ctrl.c @@ -368,7 +368,7 @@ struct OtLcCtrlState { MemoryRegion dmi_mmio; QEMUBH *pwc_lc_bh; QEMUBH *escalate_bh; - IbexIRQ alerts[NUM_ALERTS]; + qemu_irq alerts[NUM_ALERTS]; IbexIRQ broadcasts[OT_LC_BROADCAST_COUNT]; IbexIRQ pwc_lc_rsp; IbexIRQ socdbg_tx; @@ -718,7 +718,7 @@ static void ot_lc_ctrl_update_alerts(OtLcCtrlState *s) uint32_t level = s->regs[R_ALERT_TEST]; for (unsigned ix = 0; ix < NUM_ALERTS; ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -2216,7 +2216,8 @@ static void ot_lc_ctrl_init(Object *obj) s->hashed_tokens = g_new0(OtOTPTokenValue, LC_TK_COUNT); for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } for (unsigned ix = 0; ix < ARRAY_SIZE(s->broadcasts); ix++) { diff --git a/hw/opentitan/ot_otbn.c b/hw/opentitan/ot_otbn.c index afcb297ba47c3..6810fd32c1e30 100644 --- a/hw/opentitan/ot_otbn.c +++ b/hw/opentitan/ot_otbn.c @@ -148,7 +148,7 @@ struct OtOTBNState { MemoryRegion dmem; IbexIRQ irq_done; - IbexIRQ alerts[ALERT_COUNT]; + qemu_irq alerts[ALERT_COUNT]; IbexIRQ clkmgr; QEMUBH *proxy_completion_bh; @@ -194,7 +194,7 @@ static void ot_otbn_update_alert(OtOTBNState *s) if (ix == ALERT_FATAL) { level |= (bool)s->fatal_alert_cause; } - ibex_irq_set(&s->alerts[ix], level); + qemu_set_irq(s->alerts[ix], level); } } @@ -634,7 +634,7 @@ static void ot_otbn_reset(DeviceState *dev) s->last_cmd = OT_OTBN_CMD_NONE; ibex_irq_set(&s->irq_done, 0); for (unsigned ix = 0; ix < ALERT_COUNT; ix++) { - ibex_irq_set(&s->alerts[ix], 0); + qemu_set_irq(s->alerts[ix], 0); } for (unsigned rix = 0; rix < (unsigned)OT_OTBN_RND_COUNT; rix++) { @@ -677,7 +677,8 @@ static void ot_otbn_init(Object *obj) memory_region_add_subregion(&s->mmio, OT_OTBN_DMEM_BASE, &s->dmem); ibex_sysbus_init_irq(obj, &s->irq_done); - ibex_qdev_init_irqs(obj, s->alerts, OT_DEVICE_ALERT, ALERT_COUNT); + qdev_init_gpio_out_named(DEVICE(obj), s->alerts, OT_DEVICE_ALERT, + ALERT_COUNT); ibex_qdev_init_irq(obj, &s->clkmgr, OT_CLOCK_ACTIVE); for (unsigned rix = 0; rix < (unsigned)OT_OTBN_RND_COUNT; rix++) { diff --git a/hw/opentitan/ot_otp_eg.c b/hw/opentitan/ot_otp_eg.c index 905e99b4330e1..47f76198b9bb5 100644 --- a/hw/opentitan/ot_otp_eg.c +++ b/hw/opentitan/ot_otp_eg.c @@ -472,7 +472,7 @@ struct OtOTPEgState { } sub; } mmio; IbexIRQ irqs[NUM_IRQS]; - IbexIRQ alerts[NUM_ALERTS]; + qemu_irq alerts[NUM_ALERTS]; QEMUTimer *dai_delay; /**< Simulate delayed access completion */ @@ -528,7 +528,7 @@ static void ot_otp_eg_update_alerts(OtOTPEgState *s) uint32_t level = s->regs[R_ALERT_TEST]; for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -1385,7 +1385,8 @@ static void ot_otp_eg_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irqs[ix]); } for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } s->hw_cfg = g_new0(OtOTPHWCfg, 1u); diff --git a/hw/opentitan/ot_pinmux_eg.c b/hw/opentitan/ot_pinmux_eg.c index 9db1720df9fa7..9a61ec8adbd9f 100644 --- a/hw/opentitan/ot_pinmux_eg.c +++ b/hw/opentitan/ot_pinmux_eg.c @@ -194,7 +194,7 @@ struct OtPinmuxEgState { SysBusDevice parent_obj; MemoryRegion mmio; - IbexIRQ alert; + qemu_irq alert; IbexIRQ *dios; IbexIRQ *mios; @@ -319,7 +319,7 @@ static void ot_pinmux_eg_regs_write(void *opaque, hwaddr addr, uint64_t val64, case R_ALERT_TEST: val32 &= R_ALERT_TEST_FATAL_FAULT_MASK; if (val32) { - ibex_irq_set(&s->alert, (int)val32); + qemu_set_irq(s->alert, (int)val32); } break; case CASE_RANGE(MIO_PERIPH_INSEL_REGWEN, PARAM_N_MIO_PERIPH_IN): @@ -523,7 +523,7 @@ static void ot_pinmux_eg_reset(DeviceState *dev) regs->wkup_detector_regwen[ix] = 0x1u; } - ibex_irq_set(&s->alert, 0); + qemu_set_irq(s->alert, 0); } static void ot_pinmux_eg_init(Object *obj) @@ -535,7 +535,7 @@ static void ot_pinmux_eg_init(Object *obj) sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); s->regs = g_new0(OtPinmuxEgStateRegs, 1u); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); s->dios = g_new(IbexIRQ, PARAM_N_DIO_PADS); s->mios = g_new(IbexIRQ, PARAM_N_MIO_PADS); diff --git a/hw/opentitan/ot_plic_ext.c b/hw/opentitan/ot_plic_ext.c index 9f714c5c55c12..aed8d0fe6496b 100644 --- a/hw/opentitan/ot_plic_ext.c +++ b/hw/opentitan/ot_plic_ext.c @@ -58,7 +58,7 @@ struct OtPlicExtState { MemoryRegion mmio; IbexIRQ irq; - IbexIRQ alert; + qemu_irq alert; uint32_t regs[REGS_COUNT]; @@ -127,7 +127,7 @@ static void ot_plic_ext_regs_write(void *opaque, hwaddr addr, uint64_t val64, case R_ALERT_TEST: val32 &= R_ALERT_TEST_FATAL_FAULT_MASK; s->regs[reg] = val32; - ibex_irq_set(&s->alert, (int)(bool)val32); + qemu_set_irq(s->alert, (int)(bool)val32); break; default: qemu_log_mask(LOG_GUEST_ERROR, @@ -155,7 +155,7 @@ static void ot_plic_ext_reset(DeviceState *dev) OtPlicExtState *s = OT_PLIC_EXT(dev); ibex_irq_set(&s->irq, 0); - ibex_irq_set(&s->alert, 0); + qemu_set_irq(s->alert, 0); } static void ot_plic_ext_realize(DeviceState *dev, Error **errp) @@ -179,7 +179,7 @@ static void ot_plic_ext_init(Object *obj) sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); ibex_qdev_init_irq(obj, &s->irq, NULL); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); } static void ot_plic_ext_class_init(ObjectClass *klass, void *data) diff --git a/hw/opentitan/ot_pwrmgr.c b/hw/opentitan/ot_pwrmgr.c index 9adc7967c6eee..52e9bd65e89d0 100644 --- a/hw/opentitan/ot_pwrmgr.c +++ b/hw/opentitan/ot_pwrmgr.c @@ -235,13 +235,13 @@ struct OtPwrMgrState { QEMUTimer *cdc_sync; QEMUBH *fsm_tick_bh; IbexIRQ irq; /* wake from low power */ - IbexIRQ alert; IbexIRQ strap; IbexIRQ cpu_enable; IbexIRQ pwr_lc_req; IbexIRQ pwr_otp_req; IbexIRQ reset_req; IbexIRQ boot_st; + qemu_irq alert; OtPwrMgrFastState f_state; OtPwrMgrSlowState s_state; @@ -831,8 +831,7 @@ static void ot_pwrmgr_regs_write(void *opaque, hwaddr addr, uint64_t val64, break; case R_ALERT_TEST: val32 &= R_ALERT_TEST_FATAL_FAULT_MASK; - s->regs[reg] = val32; - ibex_irq_set(&s->alert, (int)(bool)val32); + qemu_set_irq(s->alert, (int)(bool)val32); break; case R_CONTROL: /* TODO: clear LOW_POWER_HINT on next WFI? */ @@ -958,9 +957,9 @@ static void ot_pwrmgr_reset_enter(Object *obj, ResetType type) ibex_irq_set(&s->cpu_enable, 0); ibex_irq_set(&s->pwr_otp_req, 0); ibex_irq_set(&s->pwr_lc_req, 0); - ibex_irq_set(&s->alert, 0); ibex_irq_set(&s->reset_req, 0); ibex_irq_set(&s->boot_st, s->boot_status.i32); + qemu_set_irq(s->alert, 0); } static void ot_pwrmgr_reset_exit(Object *obj, ResetType type) @@ -1009,7 +1008,6 @@ static void ot_pwrmgr_init(Object *obj) s->regs = g_new0(uint32_t, REGS_COUNT); ibex_sysbus_init_irq(obj, &s->irq); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); ibex_qdev_init_irq(obj, &s->pwr_lc_req, OT_PWRMGR_LC_REQ); ibex_qdev_init_irq(obj, &s->pwr_otp_req, OT_PWRMGR_OTP_REQ); ibex_qdev_init_irq(obj, &s->cpu_enable, OT_PWRMGR_CPU_EN); @@ -1017,6 +1015,8 @@ static void ot_pwrmgr_init(Object *obj) ibex_qdev_init_irq(obj, &s->reset_req, OT_PWRMGR_RST_REQ); ibex_qdev_init_irq(obj, &s->boot_st, OT_PWRMGR_BOOT_STATUS); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); + s->cdc_sync = timer_new_ns(OT_VIRTUAL_CLOCK, &ot_pwrmgr_cdc_sync, s); qdev_init_gpio_in_named(DEVICE(obj), &ot_pwrmgr_wkup, OT_PWRMGR_WKUP, diff --git a/hw/opentitan/ot_rom_ctrl.c b/hw/opentitan/ot_rom_ctrl.c index ca1a1540acab7..aac11dc71abba 100644 --- a/hw/opentitan/ot_rom_ctrl.c +++ b/hw/opentitan/ot_rom_ctrl.c @@ -139,7 +139,7 @@ struct OtRomCtrlState { MemoryRegion mmio; IbexIRQ pwrmgr_good; IbexIRQ pwrmgr_done; - IbexIRQ alert; + qemu_irq alert; uint32_t regs[REGS_COUNT]; @@ -933,7 +933,7 @@ static void ot_rom_ctrl_regs_write(void *opaque, hwaddr addr, uint64_t val64, case R_ALERT_TEST: val32 &= R_ALERT_TEST_FATAL_ERROR_MASK; s->regs[reg] = val32; - ibex_irq_set(&s->alert, (int)(bool)val32); + qemu_set_irq(s->alert, (int)(bool)val32); break; case R_FATAL_ALERT_CAUSE: case R_DIGEST_0: @@ -1194,7 +1194,7 @@ static void ot_rom_ctrl_init(Object *obj) TYPE_OT_ROM_CTRL ".regs", REGS_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); fifo8_create(&s->hash_fifo, OT_KMAC_APP_MSG_BYTES); } diff --git a/hw/opentitan/ot_rstmgr.c b/hw/opentitan/ot_rstmgr.c index bd6f740ce32e4..e5e9878c07881 100644 --- a/hw/opentitan/ot_rstmgr.c +++ b/hw/opentitan/ot_rstmgr.c @@ -148,7 +148,7 @@ struct OtRstMgrState { MemoryRegion mmio; IbexIRQ soc_reset; IbexIRQ sw_reset; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + qemu_irq alerts[PARAM_NUM_ALERTS]; QEMUBH *bus_reset_bh; CPUState *cpu; @@ -209,7 +209,7 @@ static void ot_rstmgr_update_alerts(OtRstMgrState *s) uint32_t level = s->regs[R_ALERT_TEST]; for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -556,7 +556,8 @@ static void ot_rstmgr_init(Object *obj) ibex_qdev_init_irq(obj, &s->soc_reset, OT_RSTMGR_SOC_RST); ibex_qdev_init_irq(obj, &s->sw_reset, OT_RSTMGR_SW_RST); - ibex_qdev_init_irqs(obj, s->alerts, OT_DEVICE_ALERT, PARAM_NUM_ALERTS); + qdev_init_gpio_out_named(DEVICE(obj), s->alerts, OT_DEVICE_ALERT, + PARAM_NUM_ALERTS); qdev_init_gpio_in_named(DEVICE(obj), &ot_rstmgr_reset_req, OT_RSTMGR_RST_REQ, 1); diff --git a/hw/opentitan/ot_sensor.c b/hw/opentitan/ot_sensor.c index 16d5ca6dcc164..84f9fc95a2756 100644 --- a/hw/opentitan/ot_sensor.c +++ b/hw/opentitan/ot_sensor.c @@ -136,7 +136,7 @@ struct OtSensorState { MemoryRegion mmio; IbexIRQ irqs[2u]; - IbexIRQ alerts[NUM_ALERTS]; + qemu_irq alerts[NUM_ALERTS]; uint32_t *regs; }; @@ -156,7 +156,7 @@ static void ot_sensor_update_alerts(OtSensorState *s) uint32_t level = s->regs[R_ALERT_TEST]; for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -296,7 +296,8 @@ static void ot_sensor_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irqs[ix]); } for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } } diff --git a/hw/opentitan/ot_spi_device.c b/hw/opentitan/ot_spi_device.c index 5eeb3e03f26c9..8efd77d7ab0be 100644 --- a/hw/opentitan/ot_spi_device.c +++ b/hw/opentitan/ot_spi_device.c @@ -447,7 +447,7 @@ struct OtSPIDeviceState { MemoryRegion buf; } mmio; IbexIRQ irqs[PARAM_NUM_IRQS]; - IbexIRQ alerts[PARAM_NUM_ALERTS]; + qemu_irq alerts[PARAM_NUM_ALERTS]; SpiDeviceBus bus; SpiDeviceFlash flash; @@ -753,7 +753,7 @@ static void ot_spi_device_update_alerts(OtSPIDeviceState *s) uint32_t level = s->spi_regs[R_ALERT_TEST]; for (unsigned ix = 0; ix < ARRAY_SIZE(s->alerts); ix++) { - ibex_irq_set(&s->alerts[ix], (int)((level >> ix) & 0x1u)); + qemu_set_irq(s->alerts[ix], (int)((level >> ix) & 0x1u)); } } @@ -2185,7 +2185,8 @@ static void ot_spi_device_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irqs[ix]); } for (unsigned ix = 0; ix < PARAM_NUM_ALERTS; ix++) { - ibex_qdev_init_irq(obj, &s->alerts[ix], OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alerts[ix], OT_DEVICE_ALERT, + 1); } /* diff --git a/hw/opentitan/ot_spi_host.c b/hw/opentitan/ot_spi_host.c index 0d20bd33e3da0..83061b17e902a 100644 --- a/hw/opentitan/ot_spi_host.c +++ b/hw/opentitan/ot_spi_host.c @@ -322,7 +322,7 @@ struct OtSPIHostState { QEMUTimer *fsm_delay; /**< Simulate delayed SPI transfer completion */ IbexIRQ irqs[2u]; /**< System bus IRQs */ - IbexIRQ alert; /**< OpenTitan alert */ + qemu_irq alert; /**< OpenTitan alert */ uint32_t events; /**< Active events */ uint32_t last_events; /**< Last detected events */ @@ -690,7 +690,7 @@ static void ot_spi_host_update_alert(OtSPIHostState *s) * register in QEMU */ bool alert = (bool)s->regs[R_ALERT_TEST]; - ibex_irq_set(&s->alert, alert); + qemu_set_irq(s->alert, alert); } /* ------------------------------------------------------------------------ */ @@ -733,7 +733,7 @@ static void ot_spi_host_reset(OtSPIHostState *s) for (unsigned ix = 0u; ix < ARRAY_SIZE(s->irqs); ix++) { ibex_irq_set(&s->irqs[ix], 0); } - ibex_irq_set(&s->alert, 0); + qemu_set_irq(s->alert, 0); ot_spi_host_update_regs(s); ot_spi_host_update_alert(s); @@ -1288,7 +1288,7 @@ static void ot_spi_host_instance_init(Object *obj) ibex_qdev_init_irqs(obj, &s->irqs[0u], SYSBUS_DEVICE_GPIO_IRQ, ARRAY_SIZE(s->irqs)); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); s->regs = g_new0(uint32_t, REGS_COUNT); s->config_opts = g_new0(uint32_t, (size_t)s->num_cs); diff --git a/hw/opentitan/ot_sram_ctrl.c b/hw/opentitan/ot_sram_ctrl.c index f93e6e334ab6a..653c28b17dd52 100644 --- a/hw/opentitan/ot_sram_ctrl.c +++ b/hw/opentitan/ot_sram_ctrl.c @@ -116,7 +116,7 @@ struct OtSramCtrlState { MemoryRegion mmio; /* SRAM controller registers */ OtSramCtrlMem *mem; /* SRAM memory */ - IbexIRQ alert; + qemu_irq alert; QEMUBH *switch_mr_bh; /* switch memory region */ QEMUTimer *init_timer; /* SRAM initialization timer */ @@ -395,7 +395,7 @@ static void ot_sram_ctrl_regs_write(void *opaque, hwaddr addr, uint64_t val64, switch (reg) { case R_ALERT_TEST: val32 &= R_ALERT_TEST_FATAL_ERROR_MASK; - ibex_irq_set(&s->alert, (int)(bool)val32); + qemu_set_irq(s->alert, (int)(bool)val32); break; case R_EXEC_REGWEN: val32 &= R_EXEC_REGWEN_EN_MASK; @@ -679,7 +679,7 @@ static void ot_sram_ctrl_reset(DeviceState *dev) } s->cfg_ifetch = 0u; /* not used for now */ - ibex_irq_set(&s->alert, (int)(bool)s->regs[R_ALERT_TEST]); + qemu_set_irq(s->alert, (int)(bool)s->regs[R_ALERT_TEST]); int64_t now = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); ot_prng_reseed(s->prng, (uint32_t)now); @@ -790,7 +790,7 @@ static void ot_sram_ctrl_init(Object *obj) TYPE_OT_SRAM_CTRL ".regs", REGS_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); s->mem = g_new0(OtSramCtrlMem, 1u); s->switch_mr_bh = qemu_bh_new(&ot_sram_ctrl_mem_switch_to_ram_fn, s); diff --git a/hw/opentitan/ot_timer.c b/hw/opentitan/ot_timer.c index 0e85cb0596556..0d9a2e1cbc880 100644 --- a/hw/opentitan/ot_timer.c +++ b/hw/opentitan/ot_timer.c @@ -85,7 +85,7 @@ struct OtTimerState { MemoryRegion mmio; IbexIRQ m_timer_irq; IbexIRQ irq; - IbexIRQ alert; + qemu_irq alert; QEMUTimer *timer; uint32_t regs[REGS_COUNT]; @@ -147,7 +147,7 @@ static inline bool ot_timer_is_active(OtTimerState *s) static void ot_timer_update_alert(OtTimerState *s) { bool level = (bool)(s->regs[R_ALERT_TEST] & R_ALERT_TEST_FATAL_FAULT_MASK); - ibex_irq_set(&s->alert, level); + qemu_set_irq(s->alert, level); } static void ot_timer_update_irqs(OtTimerState *s) @@ -390,7 +390,7 @@ static void ot_timer_init(Object *obj) ibex_sysbus_init_irq(obj, &s->irq); ibex_qdev_init_irq(obj, &s->m_timer_irq, NULL); - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); memory_region_init_io(&s->mmio, obj, &ot_timer_ops, s, TYPE_OT_TIMER, REGS_SIZE); diff --git a/hw/opentitan/ot_uart.c b/hw/opentitan/ot_uart.c index a271acdf0529d..821d25f3d5b47 100644 --- a/hw/opentitan/ot_uart.c +++ b/hw/opentitan/ot_uart.c @@ -147,7 +147,7 @@ struct OtUARTState { SysBusDevice parent_obj; MemoryRegion mmio; IbexIRQ irqs[OT_UART_IRQ_NUM]; - IbexIRQ alert; + qemu_irq alert; uint32_t regs[REGS_COUNT]; @@ -486,8 +486,7 @@ static void ot_uart_write(void *opaque, hwaddr addr, uint64_t val64, break; case R_ALERT_TEST: val32 &= R_ALERT_TEST_FATAL_FAULT_MASK; - s->regs[reg] = val32; - ibex_irq_set(&s->alert, (int)(bool)val32); + qemu_set_irq(s->alert, (int)(bool)val32); break; case R_CTRL: if (val32 & ~CTRL_SUP_MASK) { @@ -605,7 +604,7 @@ static void ot_uart_reset(DeviceState *dev) ot_uart_reset_rx_fifo(s); ot_uart_update_irqs(s); - ibex_irq_set(&s->alert, 0); + qemu_set_irq(s->alert, 0); } static void ot_uart_init(Object *obj) @@ -615,7 +614,7 @@ static void ot_uart_init(Object *obj) for (unsigned index = 0; index < OT_UART_IRQ_NUM; index++) { ibex_sysbus_init_irq(obj, &s->irqs[index]); } - ibex_qdev_init_irq(obj, &s->alert, OT_DEVICE_ALERT); + qdev_init_gpio_out_named(DEVICE(obj), &s->alert, OT_DEVICE_ALERT, 1); memory_region_init_io(&s->mmio, obj, &ot_uart_ops, s, TYPE_OT_UART, REGS_SIZE); diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index 238d023a8db7d..ba5279a1026d8 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -228,6 +228,7 @@ ot_i2c_update_irqs(const char *id, uint32_t active, uint32_t mask, uint32_t eff) # ot_ibex_wrapper.c ot_ibex_wrapper_cpu_enable(const char *id, const char *ch, bool level) "%s: %s:%u" +ot_ibex_wrapper_nmi_recv(const char *id, const char *ch, bool level) "%s: %s:%u" ot_ibex_wrapper_error(const char *id, const char *func, int line, const char *msg) "%s: %s:%d %s" ot_ibex_wrapper_escalate_rx(const char *id, bool level) "%s: %u" ot_ibex_wrapper_exit(const char *id, const char *msg, int val) "%s: %s (%d)" diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index cd379d6cb6686..e262fd0946d47 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -212,6 +212,14 @@ static const uint32_t ot_eg_pmp_addrs[] = { #define OT_EG_SOC_GPIO_SYSBUS_IRQ(_irq_, _target_, _num_) \ IBEX_GPIO_SYSBUS_IRQ(_irq_, OT_EG_SOC_DEV_##_target_, _num_) +#define OT_EG_SOC_GPIO_ALERT(_snum_, _tnum_) \ + OT_EG_SOC_SIGNAL(OT_DEVICE_ALERT, _snum_, ALERT_HANDLER, OT_DEVICE_ALERT, \ + _tnum_) + +#define OT_EG_SOC_GPIO_ESCALATE(_snum_, _tgt_, _tnum_) \ + OT_EG_SOC_SIGNAL(OT_ALERT_ESCALATE, _snum_, _tgt_, OT_ALERT_ESCALATE, \ + _tnum_) + #define OT_EG_SOC_DEVLINK(_pname_, _target_) \ IBEX_DEVLINK(_pname_, OT_EG_SOC_DEV_##_target_) @@ -340,7 +348,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 6), OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 7), OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 8), - OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 9) + OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 9), + OT_EG_SOC_GPIO_ALERT(0, 0) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) @@ -362,7 +371,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 15), OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 16), OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 17), - OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 18) + OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 18), + OT_EG_SOC_GPIO_ALERT(0, 1) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) @@ -384,7 +394,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 24), OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 25), OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 26), - OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 27) + OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 27), + OT_EG_SOC_GPIO_ALERT(0, 2) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) @@ -406,7 +417,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 33), OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 34), OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 35), - OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 36) + OT_EG_SOC_GPIO_SYSBUS_IRQ(8, PLIC, 36), + OT_EG_SOC_GPIO_ALERT(0, 3) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) @@ -449,7 +461,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(28, PLIC, 65), OT_EG_SOC_GPIO_SYSBUS_IRQ(29, PLIC, 66), OT_EG_SOC_GPIO_SYSBUS_IRQ(30, PLIC, 67), - OT_EG_SOC_GPIO_SYSBUS_IRQ(31, PLIC, 68) + OT_EG_SOC_GPIO_SYSBUS_IRQ(31, PLIC, 68), + OT_EG_SOC_GPIO_ALERT(0, 4) ) }, [OT_EG_SOC_DEV_SPI_DEVICE] = { @@ -466,7 +479,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 73), OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 74), OT_EG_SOC_GPIO_SYSBUS_IRQ(6, PLIC, 75), - OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 76) + OT_EG_SOC_GPIO_SYSBUS_IRQ(7, PLIC, 76), + OT_EG_SOC_GPIO_ALERT(0, 5) ), }, [OT_EG_SOC_DEV_I2C0] = { @@ -520,7 +534,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .gpio = IBEXGPIOCONNDEFS( OT_EG_SOC_GPIO(0, HART, IRQ_M_TIMER), - OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 124) + OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 124), + OT_EG_SOC_GPIO_ALERT(0, 10) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("pclk", OT_EG_PERIPHERAL_CLK_HZ) @@ -534,7 +549,12 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .gpio = IBEXGPIOCONNDEFS( OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 125), - OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 126) + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 126), + OT_EG_SOC_GPIO_ALERT(0, 11), + OT_EG_SOC_GPIO_ALERT(1, 12), + OT_EG_SOC_GPIO_ALERT(2, 13), + OT_EG_SOC_GPIO_ALERT(3, 14), + OT_EG_SOC_GPIO_ALERT(4, 15) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("edn", EDN0), @@ -573,7 +593,10 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { { .base = 0x40140000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EG_SOC_RSP(OT_PWRMGR_LC, PWRMGR) + OT_EG_SOC_RSP(OT_PWRMGR_LC, PWRMGR), + OT_EG_SOC_GPIO_ALERT(0, 16), + OT_EG_SOC_GPIO_ALERT(1, 17), + OT_EG_SOC_GPIO_ALERT(2, 18) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL), @@ -613,7 +636,13 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 127), OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 128), OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 129), - OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 130) + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 130), + OT_EG_SOC_GPIO_ESCALATE(0, IBEX_WRAPPER, 0), + OT_EG_SOC_GPIO_ESCALATE(1, LC_CTRL, 0), + OT_EG_SOC_GPIO_ESCALATE(1, LC_CTRL, 1), + OT_EG_SOC_GPIO_ESCALATE(3, PWRMGR, 0), + OT_EG_SOC_SIGNAL(OT_ALERT_NMI, 0, IBEX_WRAPPER, \ + OT_IBEX_WRAPPER_NMI, OT_IBEX_NMI_ALERT) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("edn", EDN0) @@ -633,7 +662,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .gpio = IBEXGPIOCONNDEFS( OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 131), - OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 132) + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 132), + OT_EG_SOC_GPIO_ALERT(0, 19) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("bus-num", 0) @@ -646,7 +676,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .gpio = IBEXGPIOCONNDEFS( OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 133), - OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 134) + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 134), + OT_EG_SOC_GPIO_ALERT(0, 20) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("bus-num", 1) @@ -678,7 +709,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_IBEX_WRAPPER_CPU_EN, OT_IBEX_PWRMGR_CPU_EN), OT_EG_SOC_SIGNAL(OT_PWRMGR_RST_REQ, 0, RSTMGR, - OT_RSTMGR_RST_REQ, 0) + OT_RSTMGR_RST_REQ, 0), + OT_EG_SOC_GPIO_ALERT(0, 22) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("num-rom", 1u), @@ -692,7 +724,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .gpio = IBEXGPIOCONNDEFS( OT_EG_SOC_SIGNAL(OT_RSTMGR_SW_RST, 0, PWRMGR, \ - OT_PWRMGR_SW_RST, 0) + OT_PWRMGR_SW_RST, 0), + OT_EG_SOC_GPIO_ALERT(0, 23), + OT_EG_SOC_GPIO_ALERT(1, 24) ), }, [OT_EG_SOC_DEV_CLKMGR] = { @@ -700,6 +734,10 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { .memmap = MEMMAPENTRIES( { .base = 0x40420000u } ), + .gpio = IBEXGPIOCONNDEFS( + OT_EG_SOC_GPIO_ALERT(0, 25), + OT_EG_SOC_GPIO_ALERT(1, 26) + ) }, [OT_EG_SOC_DEV_SYSRST_CTRL] = { .type = TYPE_UNIMPLEMENTED_DEVICE, @@ -739,6 +777,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { .memmap = MEMMAPENTRIES( { .base = 0x40460000u } ), + .gpio = IBEXGPIOCONNDEFS( + OT_EG_SOC_GPIO_ALERT(0, 30) + ) }, [OT_EG_SOC_DEV_AON_TIMER] = { .type = TYPE_OT_AON_TIMER, @@ -751,7 +792,10 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_SIGNAL(OT_AON_TIMER_WKUP, 0, PWRMGR, \ OT_PWRMGR_WKUP, OT_PWRMGR_WAKEUP_AON_TIMER), OT_EG_SOC_SIGNAL(OT_AON_TIMER_BITE, 0, PWRMGR, \ - OT_PWRMGR_RST, OT_EG_RESET_AON_TIMER) + OT_PWRMGR_RST, OT_EG_RESET_AON_TIMER), + OT_EG_SOC_SIGNAL(OT_AON_TIMER_BARK, 0, IBEX_WRAPPER, \ + OT_IBEX_WRAPPER_NMI, OT_IBEX_NMI_WDOG), + OT_EG_SOC_GPIO_ALERT(0, 31) ), .prop = IBEXDEVICEPROPDEFS( IBEX_DEV_UINT_PROP("pclk", OT_EG_AON_CLK_HZ) @@ -768,6 +812,10 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { .memmap = MEMMAPENTRIES( { .base = 0x40490000u } ), + .gpio = IBEXGPIOCONNDEFS( + OT_EG_SOC_GPIO_ALERT(0, 32), + OT_EG_SOC_GPIO_ALERT(1, 33) + ) }, [OT_EG_SOC_DEV_SRAM_RET_CTRL] = { .type = TYPE_OT_SRAM_CTRL, @@ -775,6 +823,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { { .base = 0x40500000u }, { .base = 0x40600000u } ), + .gpio = IBEXGPIOCONNDEFS( + OT_EG_SOC_GPIO_ALERT(0, 34) + ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), @@ -797,7 +848,12 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 162), OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 163), OT_EG_SOC_GPIO_SYSBUS_IRQ(4, PLIC, 164), - OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 165) + OT_EG_SOC_GPIO_SYSBUS_IRQ(5, PLIC, 165), + OT_EG_SOC_GPIO_ALERT(0, 35), + OT_EG_SOC_GPIO_ALERT(1, 36), + OT_EG_SOC_GPIO_ALERT(2, 37), + OT_EG_SOC_GPIO_ALERT(3, 38), + OT_EG_SOC_GPIO_ALERT(4, 39) ), }, [OT_EG_SOC_DEV_AES] = { @@ -806,7 +862,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { { .base = 0x41100000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EG_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_AES) + OT_EG_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_AES), + OT_EG_SOC_GPIO_ALERT(0, 42), + OT_EG_SOC_GPIO_ALERT(1, 43) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("edn", EDN0) @@ -824,7 +882,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 166), OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 167), OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 168), - OT_EG_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_HMAC) + OT_EG_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_HMAC), + OT_EG_SOC_GPIO_ALERT(0, 44) ), }, [OT_EG_SOC_DEV_KMAC] = { @@ -835,7 +894,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { .gpio = IBEXGPIOCONNDEFS( OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 169), OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 170), - OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 171) + OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 171), + OT_EG_SOC_GPIO_ALERT(0, 45), + OT_EG_SOC_GPIO_ALERT(1, 46) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("edn", EDN0) @@ -852,7 +913,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .gpio = IBEXGPIOCONNDEFS( OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 172), - OT_EG_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_OTBN) + OT_EG_SOC_CLKMGR_HINT(OT_CLKMGR_HINT_OTBN), + OT_EG_SOC_GPIO_ALERT(0, 47), + OT_EG_SOC_GPIO_ALERT(1, 48) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("edn-u", EDN0), @@ -884,7 +947,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 174), OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 175), OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 176), - OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 177) + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 177), + OT_EG_SOC_GPIO_ALERT(0, 51), + OT_EG_SOC_GPIO_ALERT(1, 52) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("random_src", ENTROPY_SRC), @@ -900,7 +965,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 178), OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 179), OT_EG_SOC_GPIO_SYSBUS_IRQ(2, PLIC, 180), - OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 181) + OT_EG_SOC_GPIO_SYSBUS_IRQ(3, PLIC, 181), + OT_EG_SOC_GPIO_ALERT(0, 53), + OT_EG_SOC_GPIO_ALERT(1, 54) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("ast", AST), @@ -914,7 +981,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .gpio = IBEXGPIOCONNDEFS( OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 182), - OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 183) + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 183), + OT_EG_SOC_GPIO_ALERT(0, 55), + OT_EG_SOC_GPIO_ALERT(1, 56) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("csrng", CSRNG) @@ -930,7 +999,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { ), .gpio = IBEXGPIOCONNDEFS( OT_EG_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 184), - OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 185) + OT_EG_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 185), + OT_EG_SOC_GPIO_ALERT(0, 57), + OT_EG_SOC_GPIO_ALERT(1, 58) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("csrng", CSRNG) @@ -945,6 +1016,9 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { { .base = 0x411c0000u }, { .base = 0x10000000u } ), + .gpio = IBEXGPIOCONNDEFS( + OT_EG_SOC_GPIO_ALERT(0, 59) + ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("otp_ctrl", OTP_CTRL) ), @@ -964,7 +1038,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_SIGNAL(OT_ROM_CTRL_GOOD, 0, PWRMGR, \ OT_PWRMGR_ROM_GOOD, 0), OT_EG_SOC_SIGNAL(OT_ROM_CTRL_DONE, 0, PWRMGR, \ - OT_PWRMGR_ROM_DONE, 0) + OT_PWRMGR_ROM_DONE, 0), + OT_EG_SOC_GPIO_ALERT(0, 60) ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("kmac", KMAC) @@ -983,6 +1058,13 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { .memmap = MEMMAPENTRIES( { .base = 0x411f0000u } ), + .gpio = IBEXGPIOCONNDEFS( + OT_EG_SOC_GPIO(0, HART, IRQ_NMI), + OT_EG_SOC_GPIO_ALERT(0, 61), + OT_EG_SOC_GPIO_ALERT(1, 62), + OT_EG_SOC_GPIO_ALERT(2, 63), + OT_EG_SOC_GPIO_ALERT(3, 64) + ), .link = IBEXDEVICELINKDEFS( OT_EG_SOC_DEVLINK("edn", EDN0) ), @@ -1000,7 +1082,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { OT_EG_SOC_DM_CONNECTION(OT_EG_SOC_DEV_DM, 0), OT_EG_SOC_DM_CONNECTION(OT_EG_SOC_DEV_DM, 1), OT_EG_SOC_DM_CONNECTION(OT_EG_SOC_DEV_DM, 2), - OT_EG_SOC_DM_CONNECTION(OT_EG_SOC_DEV_DM, 3) + OT_EG_SOC_DM_CONNECTION(OT_EG_SOC_DEV_DM, 3), + OT_EG_SOC_GPIO_ALERT(0, 40) ), }, [OT_EG_SOC_DEV_PLIC] = { @@ -1032,7 +1115,8 @@ static const IbexDeviceDef ot_eg_soc_devices[] = { { .base = 0x2c000000u } ), .gpio = IBEXGPIOCONNDEFS( - OT_EG_SOC_GPIO(0, HART, IRQ_M_SOFT) + OT_EG_SOC_GPIO(0, HART, IRQ_M_SOFT), + OT_EG_SOC_GPIO_ALERT(0, 41) ), }, /* clang-format on */ @@ -1134,6 +1218,11 @@ static void ot_eg_soc_hart_configure(DeviceState *dev, const IbexDeviceDef *def, qdev_prop_set_array(dev, "pmp_addr", pmp_addr); qdev_prop_set_uint64(dev, "mseccfg", (uint64_t)OT_EG_MSECCFG); + + /* NMIs are defined in Ibex to all have a mcause of 31 */ + RISCVCPU *cpu = RISCV_CPU(dev); + CPURISCVState *env = &cpu->env; + env->nmi_cause = 31u; } static void ot_eg_soc_otp_ctrl_configure( diff --git a/include/hw/opentitan/ot_alert.h b/include/hw/opentitan/ot_alert.h index 8f93ed4c88194..ed84549375a33 100644 --- a/include/hw/opentitan/ot_alert.h +++ b/include/hw/opentitan/ot_alert.h @@ -37,5 +37,6 @@ OBJECT_DECLARE_TYPE(OtAlertState, OtAlertStateClass, OT_ALERT) #define OT_DEVICE_ALERT TYPE_OT_ALERT "-sig" #define OT_ALERT_ESCALATE TYPE_OT_ALERT "-esc" +#define OT_ALERT_NMI TYPE_OT_ALERT "-nmi" #endif /* HW_OPENTITAN_OT_ALERT_H */ diff --git a/include/hw/opentitan/ot_ibex_wrapper.h b/include/hw/opentitan/ot_ibex_wrapper.h index baf862448d6d4..e8849903636cf 100644 --- a/include/hw/opentitan/ot_ibex_wrapper.h +++ b/include/hw/opentitan/ot_ibex_wrapper.h @@ -45,6 +45,7 @@ struct OtIbexWrapperStateClass { }; #define OT_IBEX_WRAPPER_CPU_EN TYPE_OT_IBEX_WRAPPER "-cpu-en" +#define OT_IBEX_WRAPPER_NMI TYPE_OT_IBEX_WRAPPER "-nmi" typedef enum { OT_IBEX_LC_CTRL_CPU_EN, @@ -52,4 +53,10 @@ typedef enum { OT_IBEX_CPU_EN_COUNT } OtIbexWrapperCpuEnable; +typedef enum { + OT_IBEX_NMI_ALERT, + OT_IBEX_NMI_WDOG, + OT_IBEX_NMI_COUNT +} OtIbexWrapperNmi; + #endif /* HW_OPENTITAN_OT_IBEX_WRAPPER_H */ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 02d86bca6341e..b6ceaf41a8b2d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -954,7 +954,9 @@ bool riscv_cpu_has_work(CPUState *cs) return riscv_cpu_all_pending(env) != 0 || riscv_cpu_sirq_pending(env) != RISCV_EXCP_NONE || riscv_cpu_vsirq_pending(env) != RISCV_EXCP_NONE || - env->debug_cs; + env->debug_cs || + env->pending_nmi || + env->processing_nmi; #else return true; #endif @@ -1403,6 +1405,11 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level) BOOL_TO_MASK(level | env->software_seip)); } break; + case IRQ_NMI: + /* NMIs do not need to update mip */ + env->pending_nmi = true; + riscv_cpu_interrupt(env); + break; default: /* Handle platform / custom local interrupts */ riscv_cpu_update_mip(env, 1ULL << irq, BOOL_TO_MASK(level)); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 466ccc9356abd..53824159e7878 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -447,6 +447,13 @@ struct CPUArchState { uint64_t dmhaltvec; /* Address of halt handler */ uint64_t dmexcpvec; /* Address of exception handler */ + /* + * NMI support + */ + bool pending_nmi; /* True if an NMI is pending, and must be handled */ + bool processing_nmi; /* True if currently in an NMI handler */ + unsigned nmi_cause; /* Reason for entering NMI */ + /* * CSRs for PointerMasking extension */ diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index cabc22e084ea8..ff1007720af0f 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -731,6 +731,7 @@ typedef enum RISCVException { #define IRQ_M_EXT 11 #define IRQ_S_GEXT 12 #define IRQ_PMU_OVF 13 +#define IRQ_NMI 14 #define IRQ_LOCAL_MAX 64 /* -1 is due to bit zero of hgeip and hgeie being ROZ. */ #define IRQ_LOCAL_GUEST_MAX (TARGET_LONG_BITS - 1) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 6b231a3813316..74ee1af21ffda 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -504,6 +504,18 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request) if (unlikely(env->debug_dm && (env->debugger || get_field(env->dcsr, DCSR_STEP)))) { return false; + } else if (unlikely(env->pending_nmi && !env->processing_nmi)) { + /* + * NMIs are handled in the same way as machine traps, but have an + * implementation-defined cause, and must be signalled via + * additional flags, since they are implementation-specific, and + * not visible through the mip register. + */ + cs->exception_index = RISCV_EXCP_INT_FLAG | env->nmi_cause; + env->pending_nmi = false; + env->processing_nmi = true; + riscv_cpu_do_interrupt(cs); + return true; } int interruptno = riscv_cpu_local_irq_pending(env); if (interruptno >= 0) { @@ -653,7 +665,7 @@ void riscv_cpu_interrupt(CPURISCVState *env) vstip = env->vstime_irq ? MIP_VSTIP : 0; - if (env->mip | vsgein | vstip | irqf) { + if (env->mip | vsgein | vstip | irqf | env->pending_nmi) { cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 8c51292795136..2b1a485100cdc 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -343,6 +343,7 @@ target_ulong helper_mret(CPURISCVState *env) mstatus = set_field(mstatus, MSTATUS_MPRV, 0); } env->mstatus = mstatus; + env->processing_nmi = false; if (riscv_has_ext(env, RVH) && prev_virt) { riscv_cpu_swap_hypervisor_regs(env);