@@ -993,6 +993,9 @@ static void print_mmu_cache_stats(vm_t *vm)
993993 */
994994static uint64_t calc_ns_until_next_interrupt (emu_state_t * emu )
995995{
996+ /* Cap at 100ms to maintain responsiveness for UART and other events */
997+ const uint64_t MAX_WAIT_NS = 100000000ULL ; /* 100ms */
998+
996999 /* During boot, use fixed short timeout to avoid fake timer / real-time
9971000 * mismatch. The fake timer advances slowly (incremental), but host OS
9981001 * timers use wall clock time, which can cause large delays if we calculate
@@ -1004,20 +1007,42 @@ static uint64_t calc_ns_until_next_interrupt(emu_state_t *emu)
10041007 uint64_t current_time = semu_timer_get (& emu -> mtimer .mtime );
10051008 uint64_t next_int = emu -> mtimer .next_interrupt_at ;
10061009
1007- /* If interrupt is already due or very close, return immediately */
1010+ /* If timer is disabled (next_interrupt_at == UINT64_MAX), use maximum
1011+ * timeout to avoid arithmetic overflow.
1012+ */
1013+ if (next_int == UINT64_MAX )
1014+ return MAX_WAIT_NS ;
1015+
1016+ /* If interrupt is already due, return immediately. This must be checked
1017+ * before any subtraction to avoid unsigned underflow.
1018+ */
10081019 if (current_time >= next_int )
10091020 return 0 ;
10101021
10111022 /* Calculate ticks until interrupt */
10121023 uint64_t ticks_remaining = next_int - current_time ;
10131024
1014- /* Convert RISC-V timer ticks to nanoseconds:
1025+ /* If there's an unreasonably large gap, cap at maximum timeout to avoid
1026+ * arithmetic overflow in the nanosecond conversion below.
1027+ */
1028+ if (ticks_remaining > UINT64_MAX / 1000 )
1029+ return MAX_WAIT_NS ;
1030+
1031+ /* Convert RISC-V timer ticks to nanoseconds using overflow-safe arithmetic:
10151032 * ns = ticks * (1e9 / CLOCK_FREQ)
1033+ *
1034+ * To avoid overflow in (ticks_remaining * 1000000000ULL), we check if
1035+ * ticks_remaining would overflow. If it does, cap at MAX_WAIT_NS.
10161036 */
1017- uint64_t ns = (ticks_remaining * 1000000000ULL ) / emu -> mtimer .mtime .freq ;
1037+ uint64_t freq = emu -> mtimer .mtime .freq ;
1038+ if (ticks_remaining > UINT64_MAX / 1000000000ULL ) {
1039+ /* Would overflow - cap at maximum timeout */
1040+ return MAX_WAIT_NS ;
1041+ }
10181042
1019- /* Cap at 100ms to maintain responsiveness for UART and other events */
1020- const uint64_t MAX_WAIT_NS = 100000000ULL ; /* 100ms */
1043+ uint64_t ns = (ticks_remaining * 1000000000ULL ) / freq ;
1044+
1045+ /* Cap at maximum timeout */
10211046 if (ns > MAX_WAIT_NS )
10221047 ns = MAX_WAIT_NS ;
10231048
0 commit comments