x86/APIC: handle overflow in TMICT calculation

With an expiry value on the order of 10 hours, and with a bus scale value
of 256k (as supplied by qemu), the (signed) multiplication will be UB. As
we've checked that the value is positive, we mean unsigned multiplication
anyway. Yet let's play safe against even larger expiry and bus scale
values, leveraging the compiler builtin that there is for this purpose.

While there also drop the stray cast from the actual TMICT write.

Fixes: 9062553a0d ("added time and accurate timer support")
Fixes: b95beb1858 ("x86: Clean up APIC local timer handling")
Reported-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Tested-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
master commit: 4f14d97a62
master date: 2026-04-16 10:29:54 +0200
This commit is contained in:
Jan Beulich committed 2026-04-20 12:28:16 +02:00
1 parent 9c79644d35
commit 76b359a878
1 file changed
+9 -3
+9 -3
View File
@@ -1224,10 +1224,16 @@ int reprogram_timer(s_time_t timeout)
}
if ( timeout && ((expire = timeout - NOW()) > 0) )
apic_tmict = min_t(uint64_t, (bus_scale * expire) >> BUS_SCALE_SHIFT,
UINT32_MAX);
{
unsigned long product;
apic_write(APIC_TMICT, (unsigned long)apic_tmict);
apic_tmict = UINT32_MAX;
if ( !__builtin_umull_overflow(bus_scale, expire, &product) &&
(product >>= BUS_SCALE_SHIFT) < apic_tmict )
apic_tmict = product;
}
apic_write(APIC_TMICT, apic_tmict);
return apic_tmict || !timeout;
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.