* [PATCH 0/9] RISC-V CPU time source interface
@ 2025-11-07 10:23 Luc Michel
2025-11-07 10:23 ` [PATCH 1/9] target/riscv: drop unused include directive in time_helper.c Luc Michel
` (9 more replies)
0 siblings, 10 replies; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
Hello,
By working locally on a RISC-V CPU with the sstc extension, I noticed
that the sstc code (the `riscv_timer_write_timecmp' function) was
implicitly assuming that the object behind the env->rdtime_fn callback
was a ACLINT. This is not a correct assumption from the point of view of
the riscv_cpu_set_rdtime_fn function API since env->rdtime_fn_arg is a
`void *' and is not required to be a ACLINT.
I reworked this and ended up with this series. It introduces the
RISCVCPUTimeSrcIf interface to replace the env->rdtime_fn callback and
break this dependency. This interface provides a mean to retrieve the
number of ticks (same as the rdtime_fn callback), and the tick frequency
that `riscv_timer_write_timecmp' needs.
This will effectively allow other platforms with CPUs and the sstc
extension but no ACLINT to provide their own time source. For now only
the ACLINT implements this interface.
The last two patches enhance the interface with a tick change notifier
registering mechanism. This allows the time source user (the CPU) to get
notified when the time source tick counter gets asynchronously modified
(reset to 0, ...), i.e., when the time register is written to. This is
then implemented in the ACLINT so that it does not have to include
time_helper.h and tinker with the CPU internals. This again will allow
new sources to be implemented more easily. It also ease maintenance by
keeping internal CPU mechanics contained into the RISC-V target code and
avoid potential duplication.
Note that I would have liked to put the time_src interface as a qdev
link property on the CPU but given the current state of the various
RISC-V machines, this is not easy to do. Most of the time the CPU gets
realized before the ACLINT so it is too late to set the link property.
This would require further refactoring.
Tested using `make check' and by booting Linux v6.17.6 in the virt
machine with 4 CPUs. I can see an initial `time' register write
(probably initial reset or OpenSBI) that correctly notifies the CPUs.
Thanks
Luc
Luc Michel (9):
target/riscv: drop unused include directive in time_helper.c
hw/intc/riscv_aclint: fix coding style
hw/intc/riscv_aclint: rename cpu_riscv_read_rtc to
riscv_aclint_mtimer_get_ticks
target/riscv: add the RISCVCPUTimeSrcIf interface
hw/intc/riscv_aclint: implement the RISCVCPUTimeSrcIf interface
target/riscv: replace env->rdtime_fn with a time source
hw/intc/riscv_aclint: riscv_aclint_mtimer_get_ticks: get rid of void*
argument
target/riscv: RISCVCPUTimeSrcIf: add register_time_change_notifier
hw/intc/riscv_aclint: implement the register_time_change_notifier
method
include/hw/intc/riscv_aclint.h | 1 +
target/riscv/cpu-qom.h | 41 ++++++++++++++++++
target/riscv/cpu.h | 9 ++--
target/riscv/time_helper.h | 27 ++++++++++++
hw/intc/riscv_aclint.c | 76 ++++++++++++++++++++++++----------
target/riscv/cpu_helper.c | 7 ----
target/riscv/csr.c | 24 +++++------
target/riscv/time_helper.c | 42 +++++++++++++++----
8 files changed, 173 insertions(+), 54 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/9] target/riscv: drop unused include directive in time_helper.c
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
@ 2025-11-07 10:23 ` Luc Michel
2025-11-09 14:03 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 2/9] hw/intc/riscv_aclint: fix coding style Luc Michel
` (8 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
Drop the unused qemu/log.h include directive in time_helper.c
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
target/riscv/time_helper.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 400e9173542..d2ec8a94166 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -15,11 +15,10 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
-#include "qemu/log.h"
#include "cpu_bits.h"
#include "time_helper.h"
#include "hw/intc/riscv_aclint.h"
static void riscv_vstimer_cb(void *opaque)
--
2.51.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 2/9] hw/intc/riscv_aclint: fix coding style
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
2025-11-07 10:23 ` [PATCH 1/9] target/riscv: drop unused include directive in time_helper.c Luc Michel
@ 2025-11-07 10:23 ` Luc Michel
2025-11-09 13:56 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 3/9] hw/intc/riscv_aclint: rename cpu_riscv_read_rtc to riscv_aclint_mtimer_get_ticks Luc Michel
` (7 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
Fix coding style in `riscv_aclint_mtimer_class_init' and
`riscv_aclint_swi_class_init' functions.
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
hw/intc/riscv_aclint.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index c6f13f647ec..5f5ffc61e80 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -342,13 +342,14 @@ static const VMStateDescription vmstate_riscv_mtimer = {
};
static void riscv_aclint_mtimer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
dc->realize = riscv_aclint_mtimer_realize;
device_class_set_props(dc, riscv_aclint_mtimer_properties);
- ResettableClass *rc = RESETTABLE_CLASS(klass);
rc->phases.enter = riscv_aclint_mtimer_reset_enter;
dc->vmsd = &vmstate_riscv_mtimer;
}
static const TypeInfo riscv_aclint_mtimer_info = {
@@ -528,13 +529,14 @@ static void riscv_aclint_swi_reset_enter(Object *obj, ResetType type)
}
static void riscv_aclint_swi_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
dc->realize = riscv_aclint_swi_realize;
device_class_set_props(dc, riscv_aclint_swi_properties);
- ResettableClass *rc = RESETTABLE_CLASS(klass);
rc->phases.enter = riscv_aclint_swi_reset_enter;
}
static const TypeInfo riscv_aclint_swi_info = {
.name = TYPE_RISCV_ACLINT_SWI,
--
2.51.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 3/9] hw/intc/riscv_aclint: rename cpu_riscv_read_rtc to riscv_aclint_mtimer_get_ticks
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
2025-11-07 10:23 ` [PATCH 1/9] target/riscv: drop unused include directive in time_helper.c Luc Michel
2025-11-07 10:23 ` [PATCH 2/9] hw/intc/riscv_aclint: fix coding style Luc Michel
@ 2025-11-07 10:23 ` Luc Michel
2025-11-09 13:56 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 4/9] target/riscv: add the RISCVCPUTimeSrcIf interface Luc Michel
` (6 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
For more clarity, rename the cpu_riscv_read_rtc function to
riscv_aclint_mtimer_get_ticks:
- The ACLINT is the time source here, not the CPU,
- This function returns a number of ticks based on the timer
frequency.
Rename the _raw version of this function as well and the local variables
storing the result of those function.
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
hw/intc/riscv_aclint.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index 5f5ffc61e80..95398e48821 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -38,20 +38,21 @@
typedef struct riscv_aclint_mtimer_callback {
RISCVAclintMTimerState *s;
int num;
} riscv_aclint_mtimer_callback;
-static uint64_t cpu_riscv_read_rtc_raw(uint32_t timebase_freq)
+static uint64_t riscv_aclint_mtimer_get_ticks_raw(uint32_t timebase_freq)
{
return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
timebase_freq, NANOSECONDS_PER_SECOND);
}
-static uint64_t cpu_riscv_read_rtc(void *opaque)
+static uint64_t riscv_aclint_mtimer_get_ticks(void *opaque)
{
RISCVAclintMTimerState *mtimer = opaque;
- return cpu_riscv_read_rtc_raw(mtimer->timebase_freq) + mtimer->time_delta;
+ return riscv_aclint_mtimer_get_ticks_raw(mtimer->timebase_freq) +
+ mtimer->time_delta;
}
/*
* Called when timecmp is written to update the QEMU timer or immediately
* trigger timer interrupt if mtimecmp <= current timer value.
@@ -63,28 +64,28 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
{
uint32_t timebase_freq = mtimer->timebase_freq;
uint64_t next;
uint64_t diff;
- uint64_t rtc = cpu_riscv_read_rtc(mtimer);
+ uint64_t ticks = riscv_aclint_mtimer_get_ticks(mtimer);
/* Compute the relative hartid w.r.t the socket */
hartid = hartid - mtimer->hartid_base;
mtimer->timecmp[hartid] = value;
- if (mtimer->timecmp[hartid] <= rtc) {
+ if (mtimer->timecmp[hartid] <= ticks) {
/*
* If we're setting an MTIMECMP value in the "past",
* immediately raise the timer interrupt
*/
qemu_irq_raise(mtimer->timer_irqs[hartid]);
return;
}
/* otherwise, set up the future timer interrupt */
qemu_irq_lower(mtimer->timer_irqs[hartid]);
- diff = mtimer->timecmp[hartid] - rtc;
+ diff = mtimer->timecmp[hartid] - ticks;
/* back to ns (note args switched in muldiv64) */
uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
/*
* check if ns_diff overflowed and check if the addition would potentially
@@ -149,15 +150,15 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr,
"aclint-mtimer: invalid read: %08x", (uint32_t)addr);
return 0;
}
} else if (addr == mtimer->time_base) {
/* time_lo for RV32/RV64 or timecmp for RV64 */
- uint64_t rtc = cpu_riscv_read_rtc(mtimer);
- return (size == 4) ? (rtc & 0xFFFFFFFF) : rtc;
+ uint64_t ticks = riscv_aclint_mtimer_get_ticks(mtimer);
+ return (size == 4) ? (ticks & 0xFFFFFFFF) : ticks;
} else if (addr == mtimer->time_base + 4) {
/* time_hi */
- return (cpu_riscv_read_rtc(mtimer) >> 32) & 0xFFFFFFFF;
+ return (riscv_aclint_mtimer_get_ticks(mtimer) >> 32) & 0xFFFFFFFF;
}
qemu_log_mask(LOG_UNIMP,
"aclint-mtimer: invalid read: %08x", (uint32_t)addr);
return 0;
@@ -206,25 +207,25 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
"aclint-mtimer: invalid timecmp write: %08x",
(uint32_t)addr);
}
return;
} else if (addr == mtimer->time_base || addr == mtimer->time_base + 4) {
- uint64_t rtc_r = cpu_riscv_read_rtc_raw(mtimer->timebase_freq);
- uint64_t rtc = cpu_riscv_read_rtc(mtimer);
+ uint64_t ticks_r = riscv_aclint_mtimer_get_ticks_raw(mtimer->timebase_freq);
+ uint64_t ticks = riscv_aclint_mtimer_get_ticks(mtimer);
if (addr == mtimer->time_base) {
if (size == 4) {
/* time_lo for RV32/RV64 */
- mtimer->time_delta = ((rtc & ~0xFFFFFFFFULL) | value) - rtc_r;
+ mtimer->time_delta = ((ticks & ~0xFFFFFFFFULL) | value) - ticks_r;
} else {
/* time for RV64 */
- mtimer->time_delta = value - rtc_r;
+ mtimer->time_delta = value - ticks_r;
}
} else {
if (size == 4) {
/* time_hi for RV32/RV64 */
- mtimer->time_delta = (value << 32 | (rtc & 0xFFFFFFFF)) - rtc_r;
+ mtimer->time_delta = (value << 32 | (ticks & 0xFFFFFFFF)) - ticks_r;
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"aclint-mtimer: invalid time_hi write: %08x",
(uint32_t)addr);
return;
@@ -395,11 +396,11 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
if (!env) {
g_free(cb);
continue;
}
if (provide_rdtime) {
- riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, dev);
+ riscv_cpu_set_rdtime_fn(env, riscv_aclint_mtimer_get_ticks, dev);
}
cb->s = s;
cb->num = i;
s->timers[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
--
2.51.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 4/9] target/riscv: add the RISCVCPUTimeSrcIf interface
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
` (2 preceding siblings ...)
2025-11-07 10:23 ` [PATCH 3/9] hw/intc/riscv_aclint: rename cpu_riscv_read_rtc to riscv_aclint_mtimer_get_ticks Luc Michel
@ 2025-11-07 10:23 ` Luc Michel
2025-11-09 14:02 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 5/9] hw/intc/riscv_aclint: implement " Luc Michel
` (5 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
Add the RISCVCPUTimeSrcIf QOM interface to the RISC-V target. This
interface aims at replacing the existing env->rdtime_fn callback in the
RISC-V CPU env. It allows to query the current number of ticks, and the
tick frequency.
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
target/riscv/cpu-qom.h | 34 ++++++++++++++++++++++++++++++++++
target/riscv/time_helper.h | 16 ++++++++++++++++
target/riscv/time_helper.c | 13 +++++++++++++
3 files changed, 63 insertions(+)
diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index 75f4e434085..e5bc23b2ef5 100644
--- a/target/riscv/cpu-qom.h
+++ b/target/riscv/cpu-qom.h
@@ -58,6 +58,40 @@
#define TYPE_RISCV_CPU_XIANGSHAN_KMH RISCV_CPU_TYPE_NAME("xiangshan-kunminghu")
#define TYPE_RISCV_CPU_HOST RISCV_CPU_TYPE_NAME("host")
OBJECT_DECLARE_CPU_TYPE(RISCVCPU, RISCVCPUClass, RISCV_CPU)
+#define TYPE_RISCV_CPU_TIME_SRC_IF "riscv-cpu-time-src-if"
+
+typedef struct RISCVCPUTimeSrcIfClass RISCVCPUTimeSrcIfClass;
+DECLARE_CLASS_CHECKERS(RISCVCPUTimeSrcIfClass, RISCV_CPU_TIME_SRC_IF,
+ TYPE_RISCV_CPU_TIME_SRC_IF)
+#define RISCV_CPU_TIME_SRC_IF(obj) \
+ INTERFACE_CHECK(RISCVCPUTimeSrcIf, (obj), TYPE_RISCV_CPU_TIME_SRC_IF)
+
+typedef struct RISCVCPUTimeSrcIf RISCVCPUTimeSrcIf;
+
+/**
+ * RISCVCPUTimeSrcIf interface
+ *
+ * This interface is used by CPUs implementing the sstc extension. When the CPU
+ * implements this extension, it must have a time source to implement the sstc
+ * timers. Devices implementing this interface provide a monotonic tick counter
+ * and the associated tick frequency so that the CPU code can compute timer
+ * deadlines.
+ */
+struct RISCVCPUTimeSrcIfClass {
+ InterfaceClass parent_class;
+
+ /**
+ * get_ticks: get the current value of the free running counter associated
+ * with this time source.
+ */
+ uint64_t (*get_ticks)(RISCVCPUTimeSrcIf *);
+
+ /**
+ * get_tick_freq: get the tick frequency of this time source.
+ */
+ uint32_t (*get_tick_freq)(RISCVCPUTimeSrcIf *);
+};
+
#endif /* RISCV_CPU_QOM_H */
diff --git a/target/riscv/time_helper.h b/target/riscv/time_helper.h
index af1f634f890..b51fdd96570 100644
--- a/target/riscv/time_helper.h
+++ b/target/riscv/time_helper.h
@@ -26,6 +26,22 @@ void riscv_timer_write_timecmp(CPURISCVState *env, QEMUTimer *timer,
uint64_t timecmp, uint64_t delta,
uint32_t timer_irq);
void riscv_timer_stce_changed(CPURISCVState *env, bool is_m_mode, bool enable);
void riscv_timer_init(RISCVCPU *cpu);
+static inline uint64_t riscv_cpu_time_src_get_ticks(RISCVCPUTimeSrcIf *src)
+{
+ RISCVCPUTimeSrcIfClass *rctsc = RISCV_CPU_TIME_SRC_IF_GET_CLASS(src);
+
+ g_assert(rctsc->get_ticks != NULL);
+ return rctsc->get_ticks(src);
+}
+
+static inline uint32_t riscv_cpu_time_src_get_tick_freq(RISCVCPUTimeSrcIf *src)
+{
+ RISCVCPUTimeSrcIfClass *rctsc = RISCV_CPU_TIME_SRC_IF_GET_CLASS(src);
+
+ g_assert(rctsc->get_tick_freq != NULL);
+ return rctsc->get_tick_freq(src);
+}
+
#endif
diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index d2ec8a94166..dc0777607ab 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -198,5 +198,18 @@ void riscv_timer_init(RISCVCPU *cpu)
env->stimecmp = 0;
env->vstimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_vstimer_cb, cpu);
env->vstimecmp = 0;
}
+
+static const TypeInfo riscv_cpu_time_src_if_info = {
+ .name = TYPE_RISCV_CPU_TIME_SRC_IF,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(RISCVCPUTimeSrcIfClass),
+};
+
+static void riscv_cpu_time_src_if_register_types(void)
+{
+ type_register_static(&riscv_cpu_time_src_if_info);
+}
+
+type_init(riscv_cpu_time_src_if_register_types)
--
2.51.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 5/9] hw/intc/riscv_aclint: implement the RISCVCPUTimeSrcIf interface
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
` (3 preceding siblings ...)
2025-11-07 10:23 ` [PATCH 4/9] target/riscv: add the RISCVCPUTimeSrcIf interface Luc Michel
@ 2025-11-07 10:23 ` Luc Michel
2025-11-09 14:01 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 6/9] target/riscv: replace env->rdtime_fn with a time source Luc Michel
` (4 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
Implement the RISCVCPUTimeSrcIf QOM interface in the ACLINT mtimer device
model.
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
hw/intc/riscv_aclint.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index 95398e48821..4a4449d9d2f 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -325,10 +325,25 @@ static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type)
* Pending mtime interrupts will also be cleared at the same time.
*/
riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8);
}
+static uint64_t riscv_aclint_mtimer_time_src_get_ticks(RISCVCPUTimeSrcIf *iface)
+{
+ RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(iface);
+
+ return riscv_aclint_mtimer_get_ticks(mtimer);
+}
+
+static uint32_t riscv_aclint_mtimer_time_src_get_tick_freq(RISCVCPUTimeSrcIf *iface)
+{
+ RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(iface);
+
+ return mtimer->timebase_freq;
+}
+
+
static const VMStateDescription vmstate_riscv_mtimer = {
.name = "riscv_mtimer",
.version_id = 3,
.minimum_version_id = 3,
.fields = (const VMStateField[]) {
@@ -344,22 +359,29 @@ static const VMStateDescription vmstate_riscv_mtimer = {
static void riscv_aclint_mtimer_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
+ RISCVCPUTimeSrcIfClass *rctsc = RISCV_CPU_TIME_SRC_IF_CLASS(klass);
dc->realize = riscv_aclint_mtimer_realize;
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;
}
static const TypeInfo riscv_aclint_mtimer_info = {
.name = TYPE_RISCV_ACLINT_MTIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(RISCVAclintMTimerState),
.class_init = riscv_aclint_mtimer_class_init,
+ .interfaces = (const InterfaceInfo []) {
+ { TYPE_RISCV_CPU_TIME_SRC_IF },
+ { },
+ },
};
/*
* Create ACLINT MTIMER device.
*/
--
2.51.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 6/9] target/riscv: replace env->rdtime_fn with a time source
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
` (4 preceding siblings ...)
2025-11-07 10:23 ` [PATCH 5/9] hw/intc/riscv_aclint: implement " Luc Michel
@ 2025-11-07 10:23 ` Luc Michel
2025-11-09 13:59 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 7/9] hw/intc/riscv_aclint: riscv_aclint_mtimer_get_ticks: get rid of void* argument Luc Michel
` (3 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
Replace the env->rdtime_fn function pointer with an instance of the
RISCVCPUTimeSrcIf QOM interface.
This allows to remove the dependency on the ACLINT in the
riscv_timer_write_timecmp function:
- This dependency was buggy because env->rdtime_fn_arg was an opaque
pointer and was converted in riscv_timer_write_timecmp to a ACLINT
without dynamic type check.
- This will allow to have time sources provided by other devices than
an ACLINT.
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
target/riscv/cpu.h | 8 +++-----
hw/intc/riscv_aclint.c | 2 +-
target/riscv/cpu_helper.c | 7 -------
target/riscv/csr.c | 24 ++++++++++++------------
target/riscv/time_helper.c | 15 +++++++++------
5 files changed, 25 insertions(+), 31 deletions(-)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 36e7f100374..368b9e2532d 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -458,13 +458,12 @@ struct CPUArchState {
struct CPUWatchpoint *cpu_watchpoint[RV_MAX_TRIGGERS];
QEMUTimer *itrigger_timer[RV_MAX_TRIGGERS];
int64_t last_icount;
bool itrigger_enabled;
- /* machine specific rdtime callback */
- uint64_t (*rdtime_fn)(void *);
- void *rdtime_fn_arg;
+ /* machine specific time source interface */
+ RISCVCPUTimeSrcIf *time_src;
/* machine specific AIA ireg read-modify-write callback */
#define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \
((((__xlen) & 0xff) << 24) | \
(((__vgein) & 0x3f) << 20) | \
@@ -642,12 +641,11 @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts);
uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask,
uint64_t value);
void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level);
void riscv_cpu_interrupt(CPURISCVState *env);
#define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
-void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
- void *arg);
+void riscv_cpu_set_time_src(CPURISCVState *env, RISCVCPUTimeSrcIf *src);
void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
int (*rmw_fn)(void *arg,
target_ulong reg,
target_ulong *val,
target_ulong new_val,
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index 4a4449d9d2f..8d001a5eb20 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -418,11 +418,11 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
if (!env) {
g_free(cb);
continue;
}
if (provide_rdtime) {
- riscv_cpu_set_rdtime_fn(env, riscv_aclint_mtimer_get_ticks, dev);
+ riscv_cpu_set_time_src(env, RISCV_CPU_TIME_SRC_IF(dev));
}
cb->s = s;
cb->num = i;
s->timers[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index c4fb68b5de8..f642ec80b31 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -757,17 +757,10 @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, uint64_t value)
riscv_cpu_interrupt(env);
return old;
}
-void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *),
- void *arg)
-{
- env->rdtime_fn = fn;
- env->rdtime_fn_arg = arg;
-}
-
void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
int (*rmw_fn)(void *arg,
target_ulong reg,
target_ulong *val,
target_ulong new_val,
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 5c91658c3dc..583f646460c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -572,11 +572,11 @@ static RISCVException sstateen(CPURISCVState *env, int csrno)
static RISCVException sstc(CPURISCVState *env, int csrno)
{
bool hmode_check = false;
- if (!riscv_cpu_cfg(env)->ext_sstc || !env->rdtime_fn) {
+ if (!riscv_cpu_cfg(env)->ext_sstc || !env->time_src) {
return RISCV_EXCP_ILLEGAL_INST;
}
if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) {
hmode_check = true;
@@ -1634,28 +1634,28 @@ static RISCVException read_scountovf(CPURISCVState *env, int csrno,
static RISCVException read_time(CPURISCVState *env, int csrno,
target_ulong *val)
{
uint64_t delta = env->virt_enabled ? env->htimedelta : 0;
- if (!env->rdtime_fn) {
+ if (!env->time_src) {
return RISCV_EXCP_ILLEGAL_INST;
}
- *val = env->rdtime_fn(env->rdtime_fn_arg) + delta;
+ *val = riscv_cpu_time_src_get_ticks(env->time_src) + delta;
return RISCV_EXCP_NONE;
}
static RISCVException read_timeh(CPURISCVState *env, int csrno,
target_ulong *val)
{
uint64_t delta = env->virt_enabled ? env->htimedelta : 0;
- if (!env->rdtime_fn) {
+ if (!env->time_src) {
return RISCV_EXCP_ILLEGAL_INST;
}
- *val = (env->rdtime_fn(env->rdtime_fn_arg) + delta) >> 32;
+ *val = (riscv_cpu_time_src_get_ticks(env->time_src) + delta) >> 32;
return RISCV_EXCP_NONE;
}
static RISCVException read_vstimecmp(CPURISCVState *env, int csrno,
target_ulong *val)
@@ -4965,60 +4965,60 @@ static RISCVException write_hgatp(CPURISCVState *env, int csrno,
}
static RISCVException read_htimedelta(CPURISCVState *env, int csrno,
target_ulong *val)
{
- if (!env->rdtime_fn) {
+ if (!env->time_src) {
return RISCV_EXCP_ILLEGAL_INST;
}
*val = env->htimedelta;
return RISCV_EXCP_NONE;
}
static RISCVException write_htimedelta(CPURISCVState *env, int csrno,
target_ulong val, uintptr_t ra)
{
- if (!env->rdtime_fn) {
+ if (!env->time_src) {
return RISCV_EXCP_ILLEGAL_INST;
}
if (riscv_cpu_mxl(env) == MXL_RV32) {
env->htimedelta = deposit64(env->htimedelta, 0, 32, (uint64_t)val);
} else {
env->htimedelta = val;
}
- if (riscv_cpu_cfg(env)->ext_sstc && env->rdtime_fn) {
+ if (riscv_cpu_cfg(env)->ext_sstc) {
riscv_timer_write_timecmp(env, env->vstimer, env->vstimecmp,
env->htimedelta, MIP_VSTIP);
}
return RISCV_EXCP_NONE;
}
static RISCVException read_htimedeltah(CPURISCVState *env, int csrno,
target_ulong *val)
{
- if (!env->rdtime_fn) {
+ if (!env->time_src) {
return RISCV_EXCP_ILLEGAL_INST;
}
*val = env->htimedelta >> 32;
return RISCV_EXCP_NONE;
}
static RISCVException write_htimedeltah(CPURISCVState *env, int csrno,
target_ulong val, uintptr_t ra)
{
- if (!env->rdtime_fn) {
+ if (!env->time_src) {
return RISCV_EXCP_ILLEGAL_INST;
}
env->htimedelta = deposit64(env->htimedelta, 32, 32, (uint64_t)val);
- if (riscv_cpu_cfg(env)->ext_sstc && env->rdtime_fn) {
+ if (riscv_cpu_cfg(env)->ext_sstc) {
riscv_timer_write_timecmp(env, env->vstimer, env->vstimecmp,
env->htimedelta, MIP_VSTIP);
}
return RISCV_EXCP_NONE;
@@ -5825,11 +5825,11 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_CYCLEH] = { "cycleh", ctr32, read_hpmcounterh },
[CSR_INSTRETH] = { "instreth", ctr32, read_hpmcounterh },
/*
* In privileged mode, the monitor will have to emulate TIME CSRs only if
- * rdtime callback is not provided by machine/platform emulation.
+ * CPU time source interface is not provided by machine/platform emulation.
*/
[CSR_TIME] = { "time", ctr, read_time },
[CSR_TIMEH] = { "timeh", ctr32, read_timeh },
/* Crypto Extension */
diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index dc0777607ab..7b493b7a233 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -17,11 +17,10 @@
*/
#include "qemu/osdep.h"
#include "cpu_bits.h"
#include "time_helper.h"
-#include "hw/intc/riscv_aclint.h"
static void riscv_vstimer_cb(void *opaque)
{
RISCVCPU *cpu = opaque;
CPURISCVState *env = &cpu->env;
@@ -42,28 +41,27 @@ static void riscv_stimer_cb(void *opaque)
void riscv_timer_write_timecmp(CPURISCVState *env, QEMUTimer *timer,
uint64_t timecmp, uint64_t delta,
uint32_t timer_irq)
{
uint64_t diff, ns_diff, next;
- RISCVAclintMTimerState *mtimer = env->rdtime_fn_arg;
uint32_t timebase_freq;
uint64_t rtc_r;
- if (!riscv_cpu_cfg(env)->ext_sstc || !env->rdtime_fn ||
- !env->rdtime_fn_arg || !get_field(env->menvcfg, MENVCFG_STCE)) {
+ if (!riscv_cpu_cfg(env)->ext_sstc || !env->time_src ||
+ !get_field(env->menvcfg, MENVCFG_STCE)) {
/* S/VS Timer IRQ depends on sstc extension, rdtime_fn(), and STCE. */
return;
}
if (timer_irq == MIP_VSTIP &&
(!riscv_has_ext(env, RVH) || !get_field(env->henvcfg, HENVCFG_STCE))) {
/* VS Timer IRQ also depends on RVH and henvcfg.STCE. */
return;
}
- timebase_freq = mtimer->timebase_freq;
- rtc_r = env->rdtime_fn(env->rdtime_fn_arg) + delta;
+ timebase_freq = riscv_cpu_time_src_get_tick_freq(env->time_src);
+ rtc_r = riscv_cpu_time_src_get_ticks(env->time_src) + delta;
if (timecmp <= rtc_r) {
/*
* If we're setting an stimecmp value in the "past",
* immediately raise the timer interrupt
@@ -199,10 +197,15 @@ void riscv_timer_init(RISCVCPU *cpu)
env->vstimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_vstimer_cb, cpu);
env->vstimecmp = 0;
}
+void riscv_cpu_set_time_src(CPURISCVState *env, RISCVCPUTimeSrcIf *src)
+{
+ env->time_src = src;
+}
+
static const TypeInfo riscv_cpu_time_src_if_info = {
.name = TYPE_RISCV_CPU_TIME_SRC_IF,
.parent = TYPE_INTERFACE,
.class_size = sizeof(RISCVCPUTimeSrcIfClass),
};
--
2.51.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 7/9] hw/intc/riscv_aclint: riscv_aclint_mtimer_get_ticks: get rid of void* argument
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
` (5 preceding siblings ...)
2025-11-07 10:23 ` [PATCH 6/9] target/riscv: replace env->rdtime_fn with a time source Luc Michel
@ 2025-11-07 10:23 ` Luc Michel
2025-11-09 13:59 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 8/9] target/riscv: RISCVCPUTimeSrcIf: add register_time_change_notifier Luc Michel
` (2 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
Now that the riscv_aclint_mtimer_get_ticks is only used internally,
replace its void* argument with the proper RISCVAclintMTimerState type.
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
hw/intc/riscv_aclint.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index 8d001a5eb20..014b733d72f 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -44,13 +44,12 @@ static uint64_t riscv_aclint_mtimer_get_ticks_raw(uint32_t timebase_freq)
{
return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
timebase_freq, NANOSECONDS_PER_SECOND);
}
-static uint64_t riscv_aclint_mtimer_get_ticks(void *opaque)
+static uint64_t riscv_aclint_mtimer_get_ticks(RISCVAclintMTimerState *mtimer)
{
- RISCVAclintMTimerState *mtimer = opaque;
return riscv_aclint_mtimer_get_ticks_raw(mtimer->timebase_freq) +
mtimer->time_delta;
}
/*
--
2.51.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 8/9] target/riscv: RISCVCPUTimeSrcIf: add register_time_change_notifier
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
` (6 preceding siblings ...)
2025-11-07 10:23 ` [PATCH 7/9] hw/intc/riscv_aclint: riscv_aclint_mtimer_get_ticks: get rid of void* argument Luc Michel
@ 2025-11-07 10:23 ` Luc Michel
2025-11-20 17:20 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 9/9] hw/intc/riscv_aclint: implement the register_time_change_notifier method Luc Michel
2025-11-14 9:25 ` [PATCH 0/9] RISC-V CPU time source interface Luc Michel
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
Add the register_time_change_notifier method to the RISCVCPUTimeSrcIf
interface. This method allows the time source user to register a
notifier on tick counter asynchronous modification (i.e., a modification
that is not due to the monotonic nature of the counter). This can happen
if the time source counter is writable, which is the case of the `time'
register of the ACLINT.
Use this mechanism in time_helper.c to recompute the sstc timers
deadlines.
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
target/riscv/cpu-qom.h | 7 +++++++
target/riscv/cpu.h | 1 +
target/riscv/time_helper.h | 11 +++++++++++
target/riscv/time_helper.c | 13 +++++++++++++
4 files changed, 32 insertions(+)
diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index e5bc23b2ef5..29cb30d23a9 100644
--- a/target/riscv/cpu-qom.h
+++ b/target/riscv/cpu-qom.h
@@ -90,8 +90,15 @@ struct RISCVCPUTimeSrcIfClass {
/**
* get_tick_freq: get the tick frequency of this time source.
*/
uint32_t (*get_tick_freq)(RISCVCPUTimeSrcIf *);
+
+ /*
+ * register_time_change_notifier: register a notifier which get notified
+ * when the value of the free running counter observes a discontinuity
+ * (e.g., the counter value gets reset to 0).
+ */
+ void (*register_time_change_notifier)(RISCVCPUTimeSrcIf *, Notifier *);
};
#endif /* RISCV_CPU_QOM_H */
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 368b9e2532d..40b198d8d4a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -460,10 +460,11 @@ struct CPUArchState {
int64_t last_icount;
bool itrigger_enabled;
/* machine specific time source interface */
RISCVCPUTimeSrcIf *time_src;
+ Notifier time_change_notifier;
/* machine specific AIA ireg read-modify-write callback */
#define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \
((((__xlen) & 0xff) << 24) | \
(((__vgein) & 0x3f) << 20) | \
diff --git a/target/riscv/time_helper.h b/target/riscv/time_helper.h
index b51fdd96570..074b516f4ad 100644
--- a/target/riscv/time_helper.h
+++ b/target/riscv/time_helper.h
@@ -42,6 +42,17 @@ static inline uint32_t riscv_cpu_time_src_get_tick_freq(RISCVCPUTimeSrcIf *src)
g_assert(rctsc->get_tick_freq != NULL);
return rctsc->get_tick_freq(src);
}
+static inline void
+riscv_cpu_time_src_register_time_change_notifier(RISCVCPUTimeSrcIf *src,
+ Notifier *notifier)
+{
+ RISCVCPUTimeSrcIfClass *rctsc = RISCV_CPU_TIME_SRC_IF_GET_CLASS(src);
+
+ if (rctsc->register_time_change_notifier) {
+ rctsc->register_time_change_notifier(src, notifier);
+ }
+}
+
#endif
diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 7b493b7a233..b1d7bba1afe 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -181,10 +181,19 @@ void riscv_timer_stce_changed(CPURISCVState *env, bool is_m_mode, bool enable)
riscv_timer_disable_timecmp(env, env->stimer, MIP_STIP);
}
}
}
+static void time_src_ticks_change_cb(Notifier *notifier, void *opaque)
+{
+ CPURISCVState *env = container_of(notifier, CPURISCVState, time_change_notifier);
+
+ 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);
+}
+
void riscv_timer_init(RISCVCPU *cpu)
{
CPURISCVState *env;
if (!cpu) {
@@ -200,10 +209,14 @@ void riscv_timer_init(RISCVCPU *cpu)
}
void riscv_cpu_set_time_src(CPURISCVState *env, RISCVCPUTimeSrcIf *src)
{
env->time_src = src;
+ env->time_change_notifier.notify = time_src_ticks_change_cb;
+
+ riscv_cpu_time_src_register_time_change_notifier(src,
+ &env->time_change_notifier);
}
static const TypeInfo riscv_cpu_time_src_if_info = {
.name = TYPE_RISCV_CPU_TIME_SRC_IF,
.parent = TYPE_INTERFACE,
--
2.51.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 9/9] hw/intc/riscv_aclint: implement the register_time_change_notifier method
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
` (7 preceding siblings ...)
2025-11-07 10:23 ` [PATCH 8/9] target/riscv: RISCVCPUTimeSrcIf: add register_time_change_notifier Luc Michel
@ 2025-11-07 10:23 ` Luc Michel
2025-11-20 17:22 ` Philippe Mathieu-Daudé
2025-11-14 9:25 ` [PATCH 0/9] RISC-V CPU time source interface Luc Michel
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-07 10:23 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Luc Michel, Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
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
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 2/9] hw/intc/riscv_aclint: fix coding style
2025-11-07 10:23 ` [PATCH 2/9] hw/intc/riscv_aclint: fix coding style Luc Michel
@ 2025-11-09 13:56 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-09 13:56 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 7/11/25 11:23, Luc Michel wrote:
> Fix coding style in `riscv_aclint_mtimer_class_init' and
> `riscv_aclint_swi_class_init' functions.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
> hw/intc/riscv_aclint.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/9] hw/intc/riscv_aclint: rename cpu_riscv_read_rtc to riscv_aclint_mtimer_get_ticks
2025-11-07 10:23 ` [PATCH 3/9] hw/intc/riscv_aclint: rename cpu_riscv_read_rtc to riscv_aclint_mtimer_get_ticks Luc Michel
@ 2025-11-09 13:56 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-09 13:56 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 7/11/25 11:23, Luc Michel wrote:
> For more clarity, rename the cpu_riscv_read_rtc function to
> riscv_aclint_mtimer_get_ticks:
> - The ACLINT is the time source here, not the CPU,
> - This function returns a number of ticks based on the timer
> frequency.
>
> Rename the _raw version of this function as well and the local variables
> storing the result of those function.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
> hw/intc/riscv_aclint.c | 31 ++++++++++++++++---------------
> 1 file changed, 16 insertions(+), 15 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 6/9] target/riscv: replace env->rdtime_fn with a time source
2025-11-07 10:23 ` [PATCH 6/9] target/riscv: replace env->rdtime_fn with a time source Luc Michel
@ 2025-11-09 13:59 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-09 13:59 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 7/11/25 11:23, Luc Michel wrote:
> Replace the env->rdtime_fn function pointer with an instance of the
> RISCVCPUTimeSrcIf QOM interface.
>
> This allows to remove the dependency on the ACLINT in the
> riscv_timer_write_timecmp function:
> - This dependency was buggy because env->rdtime_fn_arg was an opaque
> pointer and was converted in riscv_timer_write_timecmp to a ACLINT
> without dynamic type check.
> - This will allow to have time sources provided by other devices than
> an ACLINT.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
> target/riscv/cpu.h | 8 +++-----
> hw/intc/riscv_aclint.c | 2 +-
> target/riscv/cpu_helper.c | 7 -------
> target/riscv/csr.c | 24 ++++++++++++------------
> target/riscv/time_helper.c | 15 +++++++++------
> 5 files changed, 25 insertions(+), 31 deletions(-)
> +void riscv_cpu_set_time_src(CPURISCVState *env, RISCVCPUTimeSrcIf *src)
> +{
> + env->time_src = src;
Worth asserting time_src is NULL? Regardless, good cleanup:
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> +}
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/9] hw/intc/riscv_aclint: riscv_aclint_mtimer_get_ticks: get rid of void* argument
2025-11-07 10:23 ` [PATCH 7/9] hw/intc/riscv_aclint: riscv_aclint_mtimer_get_ticks: get rid of void* argument Luc Michel
@ 2025-11-09 13:59 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-09 13:59 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 7/11/25 11:23, Luc Michel wrote:
> Now that the riscv_aclint_mtimer_get_ticks is only used internally,
> replace its void* argument with the proper RISCVAclintMTimerState type.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
> hw/intc/riscv_aclint.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 5/9] hw/intc/riscv_aclint: implement the RISCVCPUTimeSrcIf interface
2025-11-07 10:23 ` [PATCH 5/9] hw/intc/riscv_aclint: implement " Luc Michel
@ 2025-11-09 14:01 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-09 14:01 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 7/11/25 11:23, Luc Michel wrote:
> Implement the RISCVCPUTimeSrcIf QOM interface in the ACLINT mtimer device
> model.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
> hw/intc/riscv_aclint.c | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 4/9] target/riscv: add the RISCVCPUTimeSrcIf interface
2025-11-07 10:23 ` [PATCH 4/9] target/riscv: add the RISCVCPUTimeSrcIf interface Luc Michel
@ 2025-11-09 14:02 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-09 14:02 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 7/11/25 11:23, Luc Michel wrote:
> Add the RISCVCPUTimeSrcIf QOM interface to the RISC-V target. This
> interface aims at replacing the existing env->rdtime_fn callback in the
> RISC-V CPU env. It allows to query the current number of ticks, and the
> tick frequency.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
> target/riscv/cpu-qom.h | 34 ++++++++++++++++++++++++++++++++++
> target/riscv/time_helper.h | 16 ++++++++++++++++
> target/riscv/time_helper.c | 13 +++++++++++++
> 3 files changed, 63 insertions(+)
>
> diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
> index 75f4e434085..e5bc23b2ef5 100644
> --- a/target/riscv/cpu-qom.h
> +++ b/target/riscv/cpu-qom.h
> @@ -58,6 +58,40 @@
> #define TYPE_RISCV_CPU_XIANGSHAN_KMH RISCV_CPU_TYPE_NAME("xiangshan-kunminghu")
> #define TYPE_RISCV_CPU_HOST RISCV_CPU_TYPE_NAME("host")
>
> OBJECT_DECLARE_CPU_TYPE(RISCVCPU, RISCVCPUClass, RISCV_CPU)
>
> +#define TYPE_RISCV_CPU_TIME_SRC_IF "riscv-cpu-time-src-if"
> +
> +typedef struct RISCVCPUTimeSrcIfClass RISCVCPUTimeSrcIfClass;
> +DECLARE_CLASS_CHECKERS(RISCVCPUTimeSrcIfClass, RISCV_CPU_TIME_SRC_IF,
> + TYPE_RISCV_CPU_TIME_SRC_IF)
> +#define RISCV_CPU_TIME_SRC_IF(obj) \
> + INTERFACE_CHECK(RISCVCPUTimeSrcIf, (obj), TYPE_RISCV_CPU_TIME_SRC_IF)
> +
> +typedef struct RISCVCPUTimeSrcIf RISCVCPUTimeSrcIf;
> +
> +/**
> + * RISCVCPUTimeSrcIf interface
> + *
> + * This interface is used by CPUs implementing the sstc extension. When the CPU
> + * implements this extension, it must have a time source to implement the sstc
> + * timers. Devices implementing this interface provide a monotonic tick counter
> + * and the associated tick frequency so that the CPU code can compute timer
> + * deadlines.
> + */
> +struct RISCVCPUTimeSrcIfClass {
> + InterfaceClass parent_class;
> +
> + /**
> + * get_ticks: get the current value of the free running counter associated
> + * with this time source.
> + */
> + uint64_t (*get_ticks)(RISCVCPUTimeSrcIf *);
> +
> + /**
> + * get_tick_freq: get the tick frequency of this time source.
> + */
> + uint32_t (*get_tick_freq)(RISCVCPUTimeSrcIf *);
> +};
Thanks for the documentation :)
> diff --git a/target/riscv/time_helper.h b/target/riscv/time_helper.h
> index af1f634f890..b51fdd96570 100644
> --- a/target/riscv/time_helper.h
> +++ b/target/riscv/time_helper.h
> @@ -26,6 +26,22 @@ void riscv_timer_write_timecmp(CPURISCVState *env, QEMUTimer *timer,
> uint64_t timecmp, uint64_t delta,
> uint32_t timer_irq);
> void riscv_timer_stce_changed(CPURISCVState *env, bool is_m_mode, bool enable);
> void riscv_timer_init(RISCVCPU *cpu);
>
> +static inline uint64_t riscv_cpu_time_src_get_ticks(RISCVCPUTimeSrcIf *src)
> +{
> + RISCVCPUTimeSrcIfClass *rctsc = RISCV_CPU_TIME_SRC_IF_GET_CLASS(src);
> +
> + g_assert(rctsc->get_ticks != NULL);
> + return rctsc->get_ticks(src);
> +}
> +
> +static inline uint32_t riscv_cpu_time_src_get_tick_freq(RISCVCPUTimeSrcIf *src)
> +{
> + RISCVCPUTimeSrcIfClass *rctsc = RISCV_CPU_TIME_SRC_IF_GET_CLASS(src);
> +
> + g_assert(rctsc->get_tick_freq != NULL);
> + return rctsc->get_tick_freq(src);
> +}
Why inlining these functions? Otherwise,
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/9] target/riscv: drop unused include directive in time_helper.c
2025-11-07 10:23 ` [PATCH 1/9] target/riscv: drop unused include directive in time_helper.c Luc Michel
@ 2025-11-09 14:03 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-09 14:03 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 7/11/25 11:23, Luc Michel wrote:
> Drop the unused qemu/log.h include directive in time_helper.c
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
> target/riscv/time_helper.c | 1 -
> 1 file changed, 1 deletion(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/9] RISC-V CPU time source interface
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
` (8 preceding siblings ...)
2025-11-07 10:23 ` [PATCH 9/9] hw/intc/riscv_aclint: implement the register_time_change_notifier method Luc Michel
@ 2025-11-14 9:25 ` Luc Michel
2025-11-20 17:16 ` Philippe Mathieu-Daudé
9 siblings, 1 reply; 21+ messages in thread
From: Luc Michel @ 2025-11-14 9:25 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 11:23 Fri 07 Nov , Luc Michel wrote:
> Hello,
>
> By working locally on a RISC-V CPU with the sstc extension, I noticed
> that the sstc code (the `riscv_timer_write_timecmp' function) was
> implicitly assuming that the object behind the env->rdtime_fn callback
> was a ACLINT. This is not a correct assumption from the point of view of
> the riscv_cpu_set_rdtime_fn function API since env->rdtime_fn_arg is a
> `void *' and is not required to be a ACLINT.
>
> I reworked this and ended up with this series. It introduces the
> RISCVCPUTimeSrcIf interface to replace the env->rdtime_fn callback and
> break this dependency. This interface provides a mean to retrieve the
> number of ticks (same as the rdtime_fn callback), and the tick frequency
> that `riscv_timer_write_timecmp' needs.
>
> This will effectively allow other platforms with CPUs and the sstc
> extension but no ACLINT to provide their own time source. For now only
> the ACLINT implements this interface.
>
> The last two patches enhance the interface with a tick change notifier
> registering mechanism. This allows the time source user (the CPU) to get
> notified when the time source tick counter gets asynchronously modified
> (reset to 0, ...), i.e., when the time register is written to. This is
> then implemented in the ACLINT so that it does not have to include
> time_helper.h and tinker with the CPU internals. This again will allow
> new sources to be implemented more easily. It also ease maintenance by
> keeping internal CPU mechanics contained into the RISC-V target code and
> avoid potential duplication.
>
> Note that I would have liked to put the time_src interface as a qdev
> link property on the CPU but given the current state of the various
> RISC-V machines, this is not easy to do. Most of the time the CPU gets
> realized before the ACLINT so it is too late to set the link property.
> This would require further refactoring.
>
> Tested using `make check' and by booting Linux v6.17.6 in the virt
> machine with 4 CPUs. I can see an initial `time' register write
> (probably initial reset or OpenSBI) that correctly notifies the CPUs.
>
> Thanks
>
> Luc
Hi,
Ping, patches missing review: 8 and 9.
Thanks
--
Luc
>
> Luc Michel (9):
> target/riscv: drop unused include directive in time_helper.c
> hw/intc/riscv_aclint: fix coding style
> hw/intc/riscv_aclint: rename cpu_riscv_read_rtc to
> riscv_aclint_mtimer_get_ticks
> target/riscv: add the RISCVCPUTimeSrcIf interface
> hw/intc/riscv_aclint: implement the RISCVCPUTimeSrcIf interface
> target/riscv: replace env->rdtime_fn with a time source
> hw/intc/riscv_aclint: riscv_aclint_mtimer_get_ticks: get rid of void*
> argument
> target/riscv: RISCVCPUTimeSrcIf: add register_time_change_notifier
> hw/intc/riscv_aclint: implement the register_time_change_notifier
> method
>
> include/hw/intc/riscv_aclint.h | 1 +
> target/riscv/cpu-qom.h | 41 ++++++++++++++++++
> target/riscv/cpu.h | 9 ++--
> target/riscv/time_helper.h | 27 ++++++++++++
> hw/intc/riscv_aclint.c | 76 ++++++++++++++++++++++++----------
> target/riscv/cpu_helper.c | 7 ----
> target/riscv/csr.c | 24 +++++------
> target/riscv/time_helper.c | 42 +++++++++++++++----
> 8 files changed, 173 insertions(+), 54 deletions(-)
>
> --
> 2.51.0
>
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/9] RISC-V CPU time source interface
2025-11-14 9:25 ` [PATCH 0/9] RISC-V CPU time source interface Luc Michel
@ 2025-11-20 17:16 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-20 17:16 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 14/11/25 10:25, Luc Michel wrote:
> Hi,
>
> Ping, patches missing review: 8 and 9.
Doh sorry, I don't remember why I stopped... I suppose I got interrupted
and forgot. Too bad this missed the soft-freeze, now we'll have to wait
after Xmas :/
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 8/9] target/riscv: RISCVCPUTimeSrcIf: add register_time_change_notifier
2025-11-07 10:23 ` [PATCH 8/9] target/riscv: RISCVCPUTimeSrcIf: add register_time_change_notifier Luc Michel
@ 2025-11-20 17:20 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-20 17:20 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 7/11/25 11:23, Luc Michel wrote:
> Add the register_time_change_notifier method to the RISCVCPUTimeSrcIf
> interface. This method allows the time source user to register a
> notifier on tick counter asynchronous modification (i.e., a modification
> that is not due to the monotonic nature of the counter). This can happen
> if the time source counter is writable, which is the case of the `time'
> register of the ACLINT.
>
> Use this mechanism in time_helper.c to recompute the sstc timers
> deadlines.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>
> ---
> target/riscv/cpu-qom.h | 7 +++++++
> target/riscv/cpu.h | 1 +
> target/riscv/time_helper.h | 11 +++++++++++
> target/riscv/time_helper.c | 13 +++++++++++++
> 4 files changed, 32 insertions(+)
> diff --git a/target/riscv/time_helper.h b/target/riscv/time_helper.h
> index b51fdd96570..074b516f4ad 100644
> --- a/target/riscv/time_helper.h
> +++ b/target/riscv/time_helper.h
> @@ -42,6 +42,17 @@ static inline uint32_t riscv_cpu_time_src_get_tick_freq(RISCVCPUTimeSrcIf *src)
>
> g_assert(rctsc->get_tick_freq != NULL);
> return rctsc->get_tick_freq(src);
> }
>
> +static inline void
> +riscv_cpu_time_src_register_time_change_notifier(RISCVCPUTimeSrcIf *src,
> + Notifier *notifier)
> +{
> + RISCVCPUTimeSrcIfClass *rctsc = RISCV_CPU_TIME_SRC_IF_GET_CLASS(src);
> +
> + if (rctsc->register_time_change_notifier) {
> + rctsc->register_time_change_notifier(src, notifier);
> + }
What about some trace event to help developers? I.e.:
if (!rctsc->register_time_change_notifier) {
trace_riscv_cpu_time_src_register_time_change_without_notifier();
return;
}
rctsc->register_time_change_notifier(src, notifier);
> +}
Anyhow:
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 9/9] hw/intc/riscv_aclint: implement the register_time_change_notifier method
2025-11-07 10:23 ` [PATCH 9/9] hw/intc/riscv_aclint: implement the register_time_change_notifier method Luc Michel
@ 2025-11-20 17:22 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-11-20 17:22 UTC (permalink / raw)
To: Luc Michel, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Francisco Iglesias
On 7/11/25 11:23, Luc Michel wrote:
> 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(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2025-11-20 17:23 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-07 10:23 [PATCH 0/9] RISC-V CPU time source interface Luc Michel
2025-11-07 10:23 ` [PATCH 1/9] target/riscv: drop unused include directive in time_helper.c Luc Michel
2025-11-09 14:03 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 2/9] hw/intc/riscv_aclint: fix coding style Luc Michel
2025-11-09 13:56 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 3/9] hw/intc/riscv_aclint: rename cpu_riscv_read_rtc to riscv_aclint_mtimer_get_ticks Luc Michel
2025-11-09 13:56 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 4/9] target/riscv: add the RISCVCPUTimeSrcIf interface Luc Michel
2025-11-09 14:02 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 5/9] hw/intc/riscv_aclint: implement " Luc Michel
2025-11-09 14:01 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 6/9] target/riscv: replace env->rdtime_fn with a time source Luc Michel
2025-11-09 13:59 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 7/9] hw/intc/riscv_aclint: riscv_aclint_mtimer_get_ticks: get rid of void* argument Luc Michel
2025-11-09 13:59 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 8/9] target/riscv: RISCVCPUTimeSrcIf: add register_time_change_notifier Luc Michel
2025-11-20 17:20 ` Philippe Mathieu-Daudé
2025-11-07 10:23 ` [PATCH 9/9] hw/intc/riscv_aclint: implement the register_time_change_notifier method Luc Michel
2025-11-20 17:22 ` Philippe Mathieu-Daudé
2025-11-14 9:25 ` [PATCH 0/9] RISC-V CPU time source interface Luc Michel
2025-11-20 17:16 ` Philippe Mathieu-Daudé
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).