Implement the register_time_change_notifier method of the RISCVCPUTimeSrcIf interface in the ACLINT. Keep a notifier list and notify it upon `time' register modification. This effectively replaces the explicit calls to the internal riscv_timer_write_timecmp CPU functions as this is now done by the corresponding CPU notifier.
Signed-off-by: Luc Michel <[email protected]> --- include/hw/intc/riscv_aclint.h | 1 + hw/intc/riscv_aclint.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h index 4b7406eec00..3451aa1786b 100644 --- a/include/hw/intc/riscv_aclint.h +++ b/include/hw/intc/riscv_aclint.h @@ -32,10 +32,11 @@ typedef struct RISCVAclintMTimerState { /*< private >*/ SysBusDevice parent_obj; uint64_t time_delta; uint64_t *timecmp; QEMUTimer **timers; + NotifierList time_change_notifiers; /*< public >*/ MemoryRegion mmio; uint32_t hartid_base; uint32_t num_harts; diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index 014b733d72f..f5e120cc853 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -26,11 +26,10 @@ #include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" #include "hw/sysbus.h" #include "target/riscv/cpu.h" -#include "target/riscv/time_helper.h" #include "hw/qdev-properties.h" #include "hw/intc/riscv_aclint.h" #include "qemu/timer.h" #include "hw/irq.h" #include "migration/vmstate.h" @@ -239,15 +238,13 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, continue; } riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), mtimer->hartid_base + i, mtimer->timecmp[i]); - riscv_timer_write_timecmp(env, env->stimer, env->stimecmp, 0, MIP_STIP); - riscv_timer_write_timecmp(env, env->vstimer, env->vstimecmp, - env->htimedelta, MIP_VSTIP); - } + + notifier_list_notify(&mtimer->time_change_notifiers, NULL); return; } qemu_log_mask(LOG_UNIMP, "aclint-mtimer: invalid write: %08x", (uint32_t)addr); @@ -284,10 +281,11 @@ static const Property riscv_aclint_mtimer_properties[] = { static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp) { RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev); int i; + notifier_list_init(&s->time_change_notifiers); memory_region_init_io(&s->mmio, OBJECT(dev), &riscv_aclint_mtimer_ops, s, TYPE_RISCV_ACLINT_MTIMER, s->aperture_size); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); s->timer_irqs = g_new(qemu_irq, s->num_harts); @@ -338,10 +336,17 @@ static uint32_t riscv_aclint_mtimer_time_src_get_tick_freq(RISCVCPUTimeSrcIf *if RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(iface); return mtimer->timebase_freq; } +static void mtimer_time_src_register_change_notifier(RISCVCPUTimeSrcIf *iface, + Notifier *notifier) +{ + RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(iface); + + notifier_list_add(&mtimer->time_change_notifiers, notifier); +} static const VMStateDescription vmstate_riscv_mtimer = { .name = "riscv_mtimer", .version_id = 3, .minimum_version_id = 3, @@ -366,10 +371,11 @@ static void riscv_aclint_mtimer_class_init(ObjectClass *klass, const void *data) device_class_set_props(dc, riscv_aclint_mtimer_properties); rc->phases.enter = riscv_aclint_mtimer_reset_enter; dc->vmsd = &vmstate_riscv_mtimer; rctsc->get_ticks = riscv_aclint_mtimer_time_src_get_ticks; rctsc->get_tick_freq = riscv_aclint_mtimer_time_src_get_tick_freq; + rctsc->register_time_change_notifier = mtimer_time_src_register_change_notifier; } static const TypeInfo riscv_aclint_mtimer_info = { .name = TYPE_RISCV_ACLINT_MTIMER, .parent = TYPE_SYS_BUS_DEVICE, -- 2.51.0
