@@ -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,35 @@ 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
1010+ /* If timer is disabled (next_interrupt_at == UINT64_MAX), or if there's
1011+ * an unreasonably large gap, use maximum timeout to avoid arithmetic
1012+ * overflow in the conversion below.
1013+ */
1014+ if (next_int == UINT64_MAX || next_int - current_time > UINT64_MAX / 1000 )
1015+ return MAX_WAIT_NS ;
1016+
10071017 /* If interrupt is already due or very close, return immediately */
10081018 if (current_time >= next_int )
10091019 return 0 ;
10101020
10111021 /* Calculate ticks until interrupt */
10121022 uint64_t ticks_remaining = next_int - current_time ;
10131023
1014- /* Convert RISC-V timer ticks to nanoseconds:
1024+ /* Convert RISC-V timer ticks to nanoseconds using overflow-safe arithmetic :
10151025 * ns = ticks * (1e9 / CLOCK_FREQ)
1026+ *
1027+ * To avoid overflow in (ticks_remaining * 1000000000ULL), we check if
1028+ * ticks_remaining would overflow. If it does, cap at MAX_WAIT_NS.
10161029 */
1017- uint64_t ns = (ticks_remaining * 1000000000ULL ) / emu -> mtimer .mtime .freq ;
1030+ uint64_t freq = emu -> mtimer .mtime .freq ;
1031+ if (ticks_remaining > UINT64_MAX / 1000000000ULL ) {
1032+ /* Would overflow - cap at maximum timeout */
1033+ return MAX_WAIT_NS ;
1034+ }
10181035
1019- /* Cap at 100ms to maintain responsiveness for UART and other events */
1020- const uint64_t MAX_WAIT_NS = 100000000ULL ; /* 100ms */
1036+ uint64_t ns = (ticks_remaining * 1000000000ULL ) / freq ;
1037+
1038+ /* Cap at maximum timeout */
10211039 if (ns > MAX_WAIT_NS )
10221040 ns = MAX_WAIT_NS ;
10231041
0 commit comments