Some userspace programs use the current timestamp as a looping condition (directly or indirectly), which can lead to infinite loops in TT-mode since the timestamp doesn't change until the next time step.
Commit 065038706f77 ("um: Support time travel mode") introduced a workaround by always inserting a time step when the current timestamp is read. However, this introduces delays, even in cases where such a loop doesn't exist, for example, in filesystem code that updates access timestamps. This slows down external TT-mode as more simulation roundtrips are required, and it unnecessarily affects the determinism and accuracy of the simulation. This patch attempts to detect potential busy loops by identifying the currently executed syscall that would return a timestamp. If 10 consecutive calls at the same timestamp occur, the timer_read is delayed. Since the patch does not consider the PID of the caller, it might be fooled by legitimate processes that take a single timestamp. However, the result is no worse than the original behavior. Signed-off-by: Benjamin Beichler <benjamin.beich...@uni-rostock.de> --- arch/um/kernel/time.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index f76237cfc1ea..1782f1ed140e 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -22,6 +22,7 @@ #include <linux/time-internal.h> #include <linux/um_timetravel.h> #include <shared/init.h> +#include <asm/syscall-generic.h> #ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT enum time_travel_mode time_travel_mode; @@ -721,6 +722,27 @@ static irqreturn_t um_timer(int irq, void *dev) return IRQ_HANDLED; } +static const int suspicious_busy_loop_syscalls[] = { + 36, //sys_getitimer + 96, //sys_gettimeofday + 201, //sys_time + 224, //sys_timer_gettime + 228, //sys_clock_gettime + 287, //sys_timerfd_gettime +}; + +static bool suspicious_busy_loop(void) +{ + int i; + int syscall = syscall_get_nr(current, task_pt_regs(current)); + + for (i = 0; i < ARRAY_SIZE(suspicious_busy_loop_syscalls); i++) { + if (suspicious_busy_loop_syscalls[i] == syscall) + return true; + } + return false; +}; + static u64 timer_read(struct clocksource *cs) { static unsigned long long last_timer_read; @@ -742,11 +764,12 @@ static u64 timer_read(struct clocksource *cs) if (last_timer_read != time_travel_time) { last_timer_read = time_travel_time; consecutive_calls_at_same_time = 0; - } else { + } else if (suspicious_busy_loop()) { consecutive_calls_at_same_time++; } if (!irqs_disabled() && !in_interrupt() && !in_softirq() && - !time_travel_ext_waiting && consecutive_calls_at_same_time > 10) + !time_travel_ext_waiting && consecutive_calls_at_same_time > 10 && + suspicious_busy_loop()) time_travel_update_time(time_travel_time + TIMER_MULTIPLIER, false); -- 2.34.1 _______________________________________________ linux-um mailing list linux-um@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-um