]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
um: rtc: use RTC time when calculating the alarm
authorBenjamin Berg <benjamin.berg@intel.com>
Tue, 17 Dec 2024 20:49:06 +0000 (21:49 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 10 Jan 2025 12:50:00 +0000 (13:50 +0100)
The kernel realtime and the current RTC time may have a (small) offset.
Should the kernel time be slightly in the future, then the timeout is
zero. This is problematic in time-travel mode, as a zero timeout can be
correctly configured and time never advances.

Replace the kernel realtime read with a read of the actual persistent
RTC clock. Also, for time-travel, calculate the exact nanoseconds needed
for the clock to advance.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Co-developed-by: Avraham Stern <avraham.stern@intel.com>
Link: https://patch.msgid.link/20241217204906.1408011-1-benjamin@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
arch/um/drivers/rtc_kern.c

index 134a58f93c859d658dc2d9798037cac5de65b914..9158c936c1281441a4e5880e0fc9a22fc9e85212 100644 (file)
@@ -51,6 +51,7 @@ static int uml_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 static int uml_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
 {
+       struct timespec64 ts;
        unsigned long long secs;
 
        if (!enable && !uml_rtc_alarm_enabled)
@@ -58,7 +59,8 @@ static int uml_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
 
        uml_rtc_alarm_enabled = enable;
 
-       secs = uml_rtc_alarm_time - ktime_get_real_seconds();
+       read_persistent_clock64(&ts);
+       secs = uml_rtc_alarm_time - ts.tv_sec;
 
        if (time_travel_mode == TT_MODE_OFF) {
                if (!enable) {
@@ -73,7 +75,8 @@ static int uml_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
 
                if (enable)
                        time_travel_add_event_rel(&uml_rtc_alarm_event,
-                                                 secs * NSEC_PER_SEC);
+                                                 secs * NSEC_PER_SEC -
+                                                 ts.tv_nsec);
        }
 
        return 0;