@@ -31,6 +31,7 @@ EXPORT_SYMBOL_GPL(time_travel_mode);
31
31
static bool time_travel_start_set ;
32
32
static unsigned long long time_travel_start ;
33
33
static unsigned long long time_travel_time ;
34
+ static unsigned long long time_travel_shm_offset ;
34
35
static LIST_HEAD (time_travel_events );
35
36
static LIST_HEAD (time_travel_irqs );
36
37
static unsigned long long time_travel_timer_interval ;
@@ -40,8 +41,11 @@ static int time_travel_ext_fd = -1;
40
41
static unsigned int time_travel_ext_waiting ;
41
42
static bool time_travel_ext_prev_request_valid ;
42
43
static unsigned long long time_travel_ext_prev_request ;
43
- static bool time_travel_ext_free_until_valid ;
44
- static unsigned long long time_travel_ext_free_until ;
44
+ static unsigned long long * time_travel_ext_free_until ;
45
+ static unsigned long long _time_travel_ext_free_until ;
46
+ static u16 time_travel_shm_id ;
47
+ static struct um_timetravel_schedshm * time_travel_shm ;
48
+ static union um_timetravel_schedshm_client * time_travel_shm_client ;
45
49
46
50
static void time_travel_set_time (unsigned long long ns )
47
51
{
@@ -58,6 +62,7 @@ enum time_travel_message_handling {
58
62
TTMH_IDLE ,
59
63
TTMH_POLL ,
60
64
TTMH_READ ,
65
+ TTMH_READ_START_ACK ,
61
66
};
62
67
63
68
static u64 bc_message ;
@@ -69,6 +74,40 @@ void _time_travel_print_bc_msg(void)
69
74
printk (KERN_INFO "time-travel: received broadcast 0x%llx\n" , bc_message );
70
75
}
71
76
77
+ static void time_travel_setup_shm (int fd , u16 id )
78
+ {
79
+ u32 len ;
80
+
81
+ time_travel_shm = os_mmap_rw_shared (fd , sizeof (* time_travel_shm ));
82
+
83
+ if (!time_travel_shm )
84
+ goto out ;
85
+
86
+ len = time_travel_shm -> len ;
87
+
88
+ if (time_travel_shm -> version != UM_TIMETRAVEL_SCHEDSHM_VERSION ||
89
+ len < struct_size (time_travel_shm , clients , id + 1 )) {
90
+ os_unmap_memory (time_travel_shm , sizeof (* time_travel_shm ));
91
+ time_travel_shm = NULL ;
92
+ goto out ;
93
+ }
94
+
95
+ time_travel_shm = os_mremap_rw_shared (time_travel_shm ,
96
+ sizeof (* time_travel_shm ),
97
+ len );
98
+ if (!time_travel_shm )
99
+ goto out ;
100
+
101
+ time_travel_shm_offset = time_travel_shm -> current_time ;
102
+ time_travel_shm_client = & time_travel_shm -> clients [id ];
103
+ time_travel_shm_client -> capa |= UM_TIMETRAVEL_SCHEDSHM_CAP_TIME_SHARE ;
104
+ time_travel_shm_id = id ;
105
+ /* always look at that free_until from now on */
106
+ time_travel_ext_free_until = & time_travel_shm -> free_until ;
107
+ out :
108
+ os_close_file (fd );
109
+ }
110
+
72
111
static void time_travel_handle_message (struct um_timetravel_msg * msg ,
73
112
enum time_travel_message_handling mode )
74
113
{
@@ -89,7 +128,20 @@ static void time_travel_handle_message(struct um_timetravel_msg *msg,
89
128
}
90
129
}
91
130
92
- ret = os_read_file (time_travel_ext_fd , msg , sizeof (* msg ));
131
+ if (unlikely (mode == TTMH_READ_START_ACK )) {
132
+ int fd [UM_TIMETRAVEL_SHARED_MAX_FDS ];
133
+
134
+ ret = os_rcv_fd_msg (time_travel_ext_fd , fd ,
135
+ ARRAY_SIZE (fd ), msg , sizeof (* msg ));
136
+ if (ret == sizeof (* msg )) {
137
+ time_travel_setup_shm (fd [UM_TIMETRAVEL_SHARED_MEMFD ],
138
+ msg -> time & UM_TIMETRAVEL_START_ACK_ID );
139
+ /* we don't use the logging for now */
140
+ os_close_file (fd [UM_TIMETRAVEL_SHARED_LOGFD ]);
141
+ }
142
+ } else {
143
+ ret = os_read_file (time_travel_ext_fd , msg , sizeof (* msg ));
144
+ }
93
145
94
146
if (ret == 0 )
95
147
panic ("time-travel external link is broken\n" );
@@ -105,10 +157,20 @@ static void time_travel_handle_message(struct um_timetravel_msg *msg,
105
157
return ;
106
158
case UM_TIMETRAVEL_RUN :
107
159
time_travel_set_time (msg -> time );
160
+ if (time_travel_shm ) {
161
+ /* no request right now since we're running */
162
+ time_travel_shm_client -> flags &=
163
+ ~UM_TIMETRAVEL_SCHEDSHM_FLAGS_REQ_RUN ;
164
+ /* no ack for shared memory RUN */
165
+ return ;
166
+ }
108
167
break ;
109
168
case UM_TIMETRAVEL_FREE_UNTIL :
110
- time_travel_ext_free_until_valid = true;
111
- time_travel_ext_free_until = msg -> time ;
169
+ /* not supposed to get this with shm, but ignore it */
170
+ if (time_travel_shm )
171
+ break ;
172
+ time_travel_ext_free_until = & _time_travel_ext_free_until ;
173
+ _time_travel_ext_free_until = msg -> time ;
112
174
break ;
113
175
case UM_TIMETRAVEL_BROADCAST :
114
176
bc_message = msg -> time ;
@@ -149,15 +211,23 @@ static u64 time_travel_ext_req(u32 op, u64 time)
149
211
block_signals_hard ();
150
212
os_write_file (time_travel_ext_fd , & msg , sizeof (msg ));
151
213
214
+ /* no ACK expected for WAIT in shared memory mode */
215
+ if (msg .op == UM_TIMETRAVEL_WAIT && time_travel_shm )
216
+ goto done ;
217
+
152
218
while (msg .op != UM_TIMETRAVEL_ACK )
153
- time_travel_handle_message (& msg , TTMH_READ );
219
+ time_travel_handle_message (& msg ,
220
+ op == UM_TIMETRAVEL_START ?
221
+ TTMH_READ_START_ACK :
222
+ TTMH_READ );
154
223
155
224
if (msg .seq != mseq )
156
225
panic ("time-travel: ACK message has different seqno! op=%d, seq=%d != %d time=%lld\n" ,
157
226
msg .op , msg .seq , mseq , msg .time );
158
227
159
228
if (op == UM_TIMETRAVEL_GET )
160
229
time_travel_set_time (msg .time );
230
+ done :
161
231
unblock_signals_hard ();
162
232
163
233
return msg .time ;
@@ -193,20 +263,48 @@ static void time_travel_ext_update_request(unsigned long long time)
193
263
/*
194
264
* if we're running and are allowed to run past the request
195
265
* then we don't need to update it either
266
+ *
267
+ * Note for shm we ignore FREE_UNTIL messages and leave the pointer
268
+ * to shared memory, and for non-shm the offset is 0.
196
269
*/
197
- if (!time_travel_ext_waiting && time_travel_ext_free_until_valid &&
198
- time < time_travel_ext_free_until )
270
+ if (!time_travel_ext_waiting && time_travel_ext_free_until &&
271
+ time < ( * time_travel_ext_free_until - time_travel_shm_offset ) )
199
272
return ;
200
273
201
274
time_travel_ext_prev_request = time ;
202
275
time_travel_ext_prev_request_valid = true;
276
+
277
+ if (time_travel_shm ) {
278
+ union um_timetravel_schedshm_client * running ;
279
+
280
+ running = & time_travel_shm -> clients [time_travel_shm -> running_id ];
281
+
282
+ if (running -> capa & UM_TIMETRAVEL_SCHEDSHM_CAP_TIME_SHARE ) {
283
+ time_travel_shm_client -> flags |=
284
+ UM_TIMETRAVEL_SCHEDSHM_FLAGS_REQ_RUN ;
285
+ time += time_travel_shm_offset ;
286
+ time_travel_shm_client -> req_time = time ;
287
+ if (time < time_travel_shm -> free_until )
288
+ time_travel_shm -> free_until = time ;
289
+ return ;
290
+ }
291
+ }
292
+
203
293
time_travel_ext_req (UM_TIMETRAVEL_REQUEST , time );
204
294
}
205
295
206
296
void __time_travel_propagate_time (void )
207
297
{
208
298
static unsigned long long last_propagated ;
209
299
300
+ if (time_travel_shm ) {
301
+ if (time_travel_shm -> running_id != time_travel_shm_id )
302
+ panic ("time-travel: setting time while not running\n" );
303
+ time_travel_shm -> current_time = time_travel_time +
304
+ time_travel_shm_offset ;
305
+ return ;
306
+ }
307
+
210
308
if (last_propagated == time_travel_time )
211
309
return ;
212
310
@@ -222,9 +320,12 @@ static bool time_travel_ext_request(unsigned long long time)
222
320
* If we received an external sync point ("free until") then we
223
321
* don't have to request/wait for anything until then, unless
224
322
* we're already waiting.
323
+ *
324
+ * Note for shm we ignore FREE_UNTIL messages and leave the pointer
325
+ * to shared memory, and for non-shm the offset is 0.
225
326
*/
226
- if (!time_travel_ext_waiting && time_travel_ext_free_until_valid &&
227
- time < time_travel_ext_free_until )
327
+ if (!time_travel_ext_waiting && time_travel_ext_free_until &&
328
+ time < ( * time_travel_ext_free_until - time_travel_shm_offset ) )
228
329
return false;
229
330
230
331
time_travel_ext_update_request (time );
@@ -238,7 +339,8 @@ static void time_travel_ext_wait(bool idle)
238
339
};
239
340
240
341
time_travel_ext_prev_request_valid = false;
241
- time_travel_ext_free_until_valid = false;
342
+ if (!time_travel_shm )
343
+ time_travel_ext_free_until = NULL ;
242
344
time_travel_ext_waiting ++ ;
243
345
244
346
time_travel_ext_req (UM_TIMETRAVEL_WAIT , -1 );
@@ -261,7 +363,11 @@ static void time_travel_ext_wait(bool idle)
261
363
262
364
static void time_travel_ext_get_time (void )
263
365
{
264
- time_travel_ext_req (UM_TIMETRAVEL_GET , -1 );
366
+ if (time_travel_shm )
367
+ time_travel_set_time (time_travel_shm -> current_time -
368
+ time_travel_shm_offset );
369
+ else
370
+ time_travel_ext_req (UM_TIMETRAVEL_GET , -1 );
265
371
}
266
372
267
373
static void __time_travel_update_time (unsigned long long ns , bool idle )
0 commit comments