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 <luc.michel@amd.com>
---
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