@samitouri / QOSamiQemu / commits / ac9dde499e

hw/misc/sifive_e_aon: Don't leak timer

The sifive_e_aon watchdog creates a timer with timer_new_ns() in its instance_init method, but does not free it in instance_finalize. This means that QMP introspection of the device leaks it: Direct leak of 48 byte in 1 object allocated from: #0 in calloc #1 in g_malloc0 #2 in timer_new_full /home/pm215/qemu/include/qemu/timer.h:520:21 #3 in timer_new /home/pm215/qemu/include/qemu/timer.h:543:12 #4 in timer_new_ns /home/pm215/qemu/include/qemu/timer.h:563:12 #5 in sifive_e_aon_init /home/pm215/qemu/build/san/../../hw/misc/sifive_e_aon.c:286:21 #6 in object_initialize_with_type /home/pm215/qemu/build/san/../../qom/object.c:570:5 #7 in object_initialize /home/pm215/qemu/build/san/../../qom/object.c:578:5 #8 in object_initialize_child_with_propsv /home/pm215/qemu/build/san/../../qom/object.c:608:5 #9 in object_initialize_child_with_props /home/pm215/qemu/build/san/../../qom/object.c:591:10 #10 in object_initialize_child_internal /home/pm215/qemu/build/san/../../qom/object.c:645:5 #11 in object_initialize_with_type /home/pm215/qemu/build/san/../../qom/object.c:570:5 #12 in object_new_with_type /home/pm215/qemu/build/san/../../qom/object.c:774:5 #13 in qmp_device_list_properties /home/pm215/qemu/build/san/../../qom/qom-qmp-cmds.c:206:11 Allocating a separate QEMUTimer with timer_new() is not the preferred interface (per the comments in include/qemu/timer.h); switch to an inline struct initialized with timer_init(), which we can clean up with timer_del() in finalize. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20260309095129.1406506-1-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

Peter Maydell committed Mar 9, 2026 at 09:51 UTC ac9dde499effc2e25449cb4b87aca3f9f9cfbd0a
2 files changed +13 -5
hw/misc/sifive_e_aon.c
+12 -4
@@ -94,9 +94,9 @@ static void sifive_e_aon_wdt_update_state(SiFiveEAONState *r)
94 next += muldiv64((r->wdogcmp0 - wdogs) <<
95 FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, SCALE),
96 NANOSECONDS_PER_SECOND, r->wdogclk_freq);
97 - timer_mod(r->wdog_timer, next);
97 + timer_mod(&r->wdog_timer, next);
98 } else {
99 - timer_mod(r->wdog_timer, INT64_MAX);
99 + timer_mod(&r->wdog_timer, INT64_MAX);
100 }
101 }
102
@@ -283,12 +283,19 @@ static void sifive_e_aon_init(Object *obj)
283 sysbus_init_mmio(sbd, &r->mmio);
284
285 /* watchdog timer */
286 - r->wdog_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
287 - sifive_e_aon_wdt_expired_cb, r);
286 + timer_init_ns(&r->wdog_timer, QEMU_CLOCK_VIRTUAL,
287 + sifive_e_aon_wdt_expired_cb, r);
288 r->wdogclk_freq = SIFIVE_E_LFCLK_DEFAULT_FREQ;
289 sysbus_init_irq(sbd, &r->wdog_irq);
290 }
291
292 +static void sifive_e_aon_finalize(Object *obj)
293 +{
294 + SiFiveEAONState *r = SIFIVE_E_AON(obj);
295 +
296 + timer_del(&r->wdog_timer);
297 +}
298 +
299 static const Property sifive_e_aon_properties[] = {
300 DEFINE_PROP_UINT64("wdogclk-frequency", SiFiveEAONState, wdogclk_freq,
301 SIFIVE_E_LFCLK_DEFAULT_FREQ),
@@ -307,6 +314,7 @@ static const TypeInfo sifive_e_aon_info = {
314 .parent = TYPE_SYS_BUS_DEVICE,
315 .instance_size = sizeof(SiFiveEAONState),
316 .instance_init = sifive_e_aon_init,
317 + .instance_finalize = sifive_e_aon_finalize,
318 .class_init = sifive_e_aon_class_init,
319 };
320
include/hw/misc/sifive_e_aon.h
+1 -1
@@ -46,7 +46,7 @@ struct SiFiveEAONState {
46 MemoryRegion mmio;
47
48 /*< watchdog timer >*/
49 - QEMUTimer *wdog_timer;
49 + QEMUTimer wdog_timer;
50 qemu_irq wdog_irq;
51 uint64_t wdog_restart_time;
52 uint64_t wdogclk_freq;