um: time: fix initialization in time-travel mode
authorJohannes Berg <johannes.berg@intel.com>
Fri, 15 Jan 2021 11:49:45 +0000 (12:49 +0100)
committerRichard Weinberger <richard@nod.at>
Tue, 26 Jan 2021 21:11:38 +0000 (22:11 +0100)
In time-travel mode, since my previous patch, the start time was
initialized too late, so that the system would read it before we
set it, thus always starting system time at 0 (1970-01-01). This
happens because timekeeping_init() reads the time and is called
before time_init().

Unfortunately, I didn't see this before because I was testing it
only with the RTC patch applied (and enabled), and then the time
is read again by the RTC a little - after time_init() this time.

Fix this by just doing the initialization whenever necessary.

Fixes: 2701c1bd91dd ("um: time: Fix read_persistent_clock64() in time-travel")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
arch/um/kernel/time.c

index f4db89b5b5a6f5a61675bee36f1646cb1a744038..315248b039414c9a3d93b754adb8abfed24c9e7e 100644 (file)
@@ -535,6 +535,31 @@ invalid_number:
 
        return 1;
 }
+
+static void time_travel_set_start(void)
+{
+       if (time_travel_start_set)
+               return;
+
+       switch (time_travel_mode) {
+       case TT_MODE_EXTERNAL:
+               time_travel_start = time_travel_ext_req(UM_TIMETRAVEL_GET_TOD, -1);
+               /* controller gave us the *current* time, so adjust by that */
+               time_travel_ext_get_time();
+               time_travel_start -= time_travel_time;
+               break;
+       case TT_MODE_INFCPU:
+       case TT_MODE_BASIC:
+               if (!time_travel_start_set)
+                       time_travel_start = os_persistent_clock_emulation();
+               break;
+       case TT_MODE_OFF:
+               /* we just read the host clock with os_persistent_clock_emulation() */
+               break;
+       }
+
+       time_travel_start_set = true;
+}
 #else /* CONFIG_UML_TIME_TRAVEL_SUPPORT */
 #define time_travel_start_set 0
 #define time_travel_start 0
@@ -553,6 +578,10 @@ static void time_travel_set_interval(unsigned long long interval)
 {
 }
 
+static inline void time_travel_set_start(void)
+{
+}
+
 /* fail link if this actually gets used */
 extern u64 time_travel_ext_req(u32 op, u64 time);
 
@@ -731,6 +760,8 @@ void read_persistent_clock64(struct timespec64 *ts)
 {
        long long nsecs;
 
+       time_travel_set_start();
+
        if (time_travel_mode != TT_MODE_OFF)
                nsecs = time_travel_start + time_travel_time;
        else
@@ -742,25 +773,6 @@ void read_persistent_clock64(struct timespec64 *ts)
 
 void __init time_init(void)
 {
-#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
-       switch (time_travel_mode) {
-       case TT_MODE_EXTERNAL:
-               time_travel_start = time_travel_ext_req(UM_TIMETRAVEL_GET_TOD, -1);
-               /* controller gave us the *current* time, so adjust by that */
-               time_travel_ext_get_time();
-               time_travel_start -= time_travel_time;
-               break;
-       case TT_MODE_INFCPU:
-       case TT_MODE_BASIC:
-               if (!time_travel_start_set)
-                       time_travel_start = os_persistent_clock_emulation();
-               break;
-       case TT_MODE_OFF:
-               /* we just read the host clock with os_persistent_clock_emulation() */
-               break;
-       }
-#endif
-
        timer_set_signal_handler();
        late_time_init = um_timer_setup;
 }