DF-5330 / fix.diff
--- a/sys/platform/pc64/isa/clock.c +++ b/sys/platform/pc64/isa/clock.c @@ -1166,6 +1166,22 @@ tm -= tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); + /* + * DF-5330: a wall clock set before the epoch (or pushed before + * it by the timezone / adjkerntz adjustment) wraps the unsigned + * long tm to a huge value. The year loop below would then spin + * for ~5e16 iterations with preemption/interrupts deferred + * (crit_enter at the top of resettodr) and masterclock_lock held, + * hanging the kernel permanently. Sanity-bound the conversion to + * year 9999 and leave the RTC untouched if the time is out of + * range. + */ + if (tm > (unsigned long)86400 * 366 * (9999 - 1970 + 1)) { + writertc(RTC_STATUSB, rtc_statusb); + crit_exit(); + return; + } + writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */ writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */ writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24; /* Write back Hours */ |