@@ -31,6 +31,7 @@ EXPORT_SYMBOL_GPL(time_travel_mode);
3131static bool time_travel_start_set ;
3232static unsigned long long time_travel_start ;
3333static unsigned long long time_travel_time ;
34+ static unsigned long long time_travel_shm_offset ;
3435static LIST_HEAD (time_travel_events );
3536static LIST_HEAD (time_travel_irqs );
3637static unsigned long long time_travel_timer_interval ;
@@ -40,8 +41,11 @@ static int time_travel_ext_fd = -1;
4041static unsigned int time_travel_ext_waiting ;
4142static bool time_travel_ext_prev_request_valid ;
4243static 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 ;
4549
4650static void time_travel_set_time (unsigned long long ns )
4751{
@@ -58,6 +62,7 @@ enum time_travel_message_handling {
5862 TTMH_IDLE ,
5963 TTMH_POLL ,
6064 TTMH_READ ,
65+ TTMH_READ_START_ACK ,
6166};
6267
6368static u64 bc_message ;
@@ -69,6 +74,40 @@ void _time_travel_print_bc_msg(void)
6974 printk (KERN_INFO "time-travel: received broadcast 0x%llx\n" , bc_message );
7075}
7176
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+
72111static void time_travel_handle_message (struct um_timetravel_msg * msg ,
73112 enum time_travel_message_handling mode )
74113{
@@ -89,7 +128,20 @@ static void time_travel_handle_message(struct um_timetravel_msg *msg,
89128 }
90129 }
91130
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+ }
93145
94146 if (ret == 0 )
95147 panic ("time-travel external link is broken\n" );
@@ -105,10 +157,20 @@ static void time_travel_handle_message(struct um_timetravel_msg *msg,
105157 return ;
106158 case UM_TIMETRAVEL_RUN :
107159 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+ }
108167 break ;
109168 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 ;
112174 break ;
113175 case UM_TIMETRAVEL_BROADCAST :
114176 bc_message = msg -> time ;
@@ -149,15 +211,23 @@ static u64 time_travel_ext_req(u32 op, u64 time)
149211 block_signals_hard ();
150212 os_write_file (time_travel_ext_fd , & msg , sizeof (msg ));
151213
214+ /* no ACK expected for WAIT in shared memory mode */
215+ if (msg .op == UM_TIMETRAVEL_WAIT && time_travel_shm )
216+ goto done ;
217+
152218 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 );
154223
155224 if (msg .seq != mseq )
156225 panic ("time-travel: ACK message has different seqno! op=%d, seq=%d != %d time=%lld\n" ,
157226 msg .op , msg .seq , mseq , msg .time );
158227
159228 if (op == UM_TIMETRAVEL_GET )
160229 time_travel_set_time (msg .time );
230+ done :
161231 unblock_signals_hard ();
162232
163233 return msg .time ;
@@ -193,20 +263,48 @@ static void time_travel_ext_update_request(unsigned long long time)
193263 /*
194264 * if we're running and are allowed to run past the request
195265 * 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.
196269 */
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 ) )
199272 return ;
200273
201274 time_travel_ext_prev_request = time ;
202275 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+
203293 time_travel_ext_req (UM_TIMETRAVEL_REQUEST , time );
204294}
205295
206296void __time_travel_propagate_time (void )
207297{
208298 static unsigned long long last_propagated ;
209299
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+
210308 if (last_propagated == time_travel_time )
211309 return ;
212310
@@ -222,9 +320,12 @@ static bool time_travel_ext_request(unsigned long long time)
222320 * If we received an external sync point ("free until") then we
223321 * don't have to request/wait for anything until then, unless
224322 * 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.
225326 */
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 ) )
228329 return false;
229330
230331 time_travel_ext_update_request (time );
@@ -238,7 +339,8 @@ static void time_travel_ext_wait(bool idle)
238339 };
239340
240341 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 ;
242344 time_travel_ext_waiting ++ ;
243345
244346 time_travel_ext_req (UM_TIMETRAVEL_WAIT , -1 );
@@ -261,7 +363,11 @@ static void time_travel_ext_wait(bool idle)
261363
262364static void time_travel_ext_get_time (void )
263365{
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 );
265371}
266372
267373static void __time_travel_update_time (unsigned long long ns , bool idle )
0 commit comments