@samitouri / QOSamiQemu / commits / a7410b601e

hw/misc/bcm2835_control.c: Don't assert on local timer zero reload value

The bcm2836 local timer has a basic "counts down, fires at zero, and reloads to programmed value to count down again" functionality, as documented in https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf The documentation is very sparse and doesn't say what actually happens if the guest programs the reload value to zero. Currently we trip an assert in this case. Instead, log this as a guest error and disable the timer (which seems a reasonable guess -- effectively the timer will stop counting). Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3395 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260508162013.2751001-2-peter.maydell@linaro.org

Peter Maydell committed May 8, 2026 at 17:20 UTC a7410b601ee2568c904aac862b947fb3dc22e1eb
1 file changed +13 -4
hw/intc/bcm2836_control.c
+13 -4
@@ -197,12 +197,21 @@ static void bcm2836_control_local_timer_set_next(void *opaque)
197 {
198 BCM2836ControlState *s = opaque;
199 uint64_t next_event;
200 -
201 - assert(LOCALTIMER_VALUE(s->local_timer_control) > 0);
200 + uint64_t reload_value = LOCALTIMER_VALUE(s->local_timer_control);
201 +
202 + if (reload_value == 0) {
203 + /*
204 + * Spec doesn't say what happens in this case; treat as a
205 + * guest error and stop the timer running.
206 + */
207 + qemu_log_mask(LOG_GUEST_ERROR, "%s: local timer reload value is 0\n",
208 + __func__);
209 + timer_del(&s->timer);
210 + return;
211 + }
212
213 next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
204 - muldiv64(LOCALTIMER_VALUE(s->local_timer_control),
205 - NANOSECONDS_PER_SECOND, LOCALTIMER_FREQ);
214 + muldiv64(reload_value, NANOSECONDS_PER_SECOND, LOCALTIMER_FREQ);
215 timer_mod(&s->timer, next_event);
216 }
217