summaryrefslogtreecommitdiff
path: root/arch/um/kernel/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/time.c')
-rw-r--r--arch/um/kernel/time.c67
1 files changed, 47 insertions, 20 deletions
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index f4db89b5b5a6..e0cdb9694fb8 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -278,6 +278,7 @@ static void __time_travel_add_event(struct time_travel_event *e,
{
struct time_travel_event *tmp;
bool inserted = false;
+ unsigned long flags;
if (e->pending)
return;
@@ -285,6 +286,7 @@ static void __time_travel_add_event(struct time_travel_event *e,
e->pending = true;
e->time = time;
+ local_irq_save(flags);
list_for_each_entry(tmp, &time_travel_events, list) {
/*
* Add the new entry before one with higher time,
@@ -307,6 +309,7 @@ static void __time_travel_add_event(struct time_travel_event *e,
tmp = time_travel_first_event();
time_travel_ext_update_request(tmp->time);
time_travel_next_event = tmp->time;
+ local_irq_restore(flags);
}
static void time_travel_add_event(struct time_travel_event *e,
@@ -318,6 +321,12 @@ static void time_travel_add_event(struct time_travel_event *e,
__time_travel_add_event(e, time);
}
+void time_travel_add_event_rel(struct time_travel_event *e,
+ unsigned long long delay_ns)
+{
+ time_travel_add_event(e, time_travel_time + delay_ns);
+}
+
void time_travel_periodic_timer(struct time_travel_event *e)
{
time_travel_add_event(&time_travel_timer_event,
@@ -381,12 +390,16 @@ static void time_travel_deliver_event(struct time_travel_event *e)
}
}
-static bool time_travel_del_event(struct time_travel_event *e)
+bool time_travel_del_event(struct time_travel_event *e)
{
+ unsigned long flags;
+
if (!e->pending)
return false;
+ local_irq_save(flags);
list_del(&e->list);
e->pending = false;
+ local_irq_restore(flags);
return true;
}
@@ -535,6 +548,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,11 +591,17 @@ 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);
/* these are empty macros so the struct/fn need not exist */
#define time_travel_add_event(e, time) do { } while (0)
+/* externally not usable - redefine here so we can */
+#undef time_travel_del_event
#define time_travel_del_event(e) do { } while (0)
#endif
@@ -731,6 +775,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 +788,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;
}