xref: /minix3/minix/lib/libsys/sef_liveupdate.c (revision b5e2faaaaf60a8b9a02f8d72f64caa56a87eb312)
1 #include "syslib.h"
2 #include <assert.h>
3 #include <minix/sysutil.h>
4 #include <minix/rs.h>
5 
6 /* SEF Live update variables. */
7 int sef_lu_state;
8 int __sef_st_before_receive_enabled;
9 char sef_lu_state_eval[SEF_LU_STATE_EVAL_MAX_LEN];
10 static int sef_lu_flags;
11 
12 /* SEF Live update callbacks. */
13 static struct sef_lu_cbs {
14     sef_cb_lu_prepare_t                 sef_cb_lu_prepare;
15     sef_cb_lu_state_isvalid_t           sef_cb_lu_state_isvalid;
16     sef_cb_lu_state_changed_t           sef_cb_lu_state_changed;
17     sef_cb_lu_state_dump_t              sef_cb_lu_state_dump;
18     sef_cb_lu_state_save_t              sef_cb_lu_state_save;
19     sef_cb_lu_response_t                sef_cb_lu_response;
20 } sef_lu_cbs = {
21     SEF_CB_LU_PREPARE_DEFAULT,
22     SEF_CB_LU_STATE_ISVALID_DEFAULT,
23     SEF_CB_LU_STATE_CHANGED_DEFAULT,
24     SEF_CB_LU_STATE_DUMP_DEFAULT,
25     SEF_CB_LU_STATE_SAVE_DEFAULT,
26     SEF_CB_LU_RESPONSE_DEFAULT
27 };
28 
29 /* SEF Live update prototypes for sef_receive(). */
30 void do_sef_lu_before_receive(void);
31 int do_sef_lu_request(message *m_ptr);
32 
33 /* SEF Live update helpers. */
34 static void sef_lu_ready(int result);
35 static void sef_lu_state_change(int state, int flags);
36 int sef_lu_handle_state_data(endpoint_t src_e, int state,
37     cp_grant_id_t state_data_gid);
38 
39 /* Debug. */
40 EXTERN char* sef_debug_header(void);
41 static int sef_lu_debug_cycle = 0;
42 
43 /* Information about SELF. */
44 EXTERN endpoint_t sef_self_endpoint;
45 
46 /*===========================================================================*
47  *                         do_sef_lu_before_receive             	     *
48  *===========================================================================*/
49 void do_sef_lu_before_receive(void)
50 {
51 /* Handle SEF Live update before receive events. */
52   int r;
53 
54   assert(sef_lu_state != SEF_LU_STATE_NULL);
55 
56   /* Debug. */
57 #if SEF_LU_DEBUG
58   sef_lu_debug_cycle++;
59   sef_lu_debug_begin();
60   sef_lu_dprint("%s, cycle=%d. Dumping state variables:\n",
61       sef_debug_header(), sef_lu_debug_cycle);
62   sef_lu_cbs.sef_cb_lu_state_dump(sef_lu_state);
63   sef_lu_debug_end();
64 #endif
65 
66   /* Check the state. For SEF_LU_STATE_WORK_FREE/SEF_LU_STATE_UNREACHABLE,
67    * we are always/never ready. For SEF_LU_STATE_EVAL, evaluate the expression.
68    * For other states, let the callback code handle the event.
69    */
70   switch(sef_lu_state) {
71       case SEF_LU_STATE_WORK_FREE:
72           r = OK;
73       break;
74       case SEF_LU_STATE_UNREACHABLE:
75           r = sef_cb_lu_prepare_never_ready(sef_lu_state);
76       break;
77       case SEF_LU_STATE_PREPARE_CRASH:
78           r = sef_cb_lu_prepare_crash(sef_lu_state);
79       break;
80       case SEF_LU_STATE_EVAL:
81           r = sef_cb_lu_prepare_eval(sef_lu_state);
82       break;
83       default:
84           r = sef_lu_cbs.sef_cb_lu_prepare(sef_lu_state);
85       break;
86   }
87   if(r == OK || r != ENOTREADY) {
88        sef_lu_ready(r);
89   }
90 }
91 
92 /*===========================================================================*
93  *                               do_sef_lu_request              	     *
94  *===========================================================================*/
95 int do_sef_lu_request(message *m_ptr)
96 {
97 /* Handle a SEF Live update request. */
98   int r, state, flags, is_valid_state;
99   cp_grant_id_t rs_state_data_gid;
100 
101   sef_lu_debug_cycle = 0;
102   state = m_ptr->m_rs_update.state;
103   flags = m_ptr->m_rs_update.flags;
104   rs_state_data_gid = m_ptr->m_rs_update.state_data_gid;
105 
106   /* Deal with prepare cancel requests first, where no reply is requested. */
107   if(state == SEF_LU_STATE_NULL) {
108       sef_lu_state_change(SEF_LU_STATE_NULL, 0);
109       return OK;
110   }
111 
112   /* Check if we are already busy. */
113   if(sef_lu_state != SEF_LU_STATE_NULL) {
114       sef_lu_ready(EBUSY);
115       return OK;
116   }
117 
118   /* Otherwise only accept live update requests with a valid state. */
119   is_valid_state = SEF_LU_ALWAYS_ALLOW_DEBUG_STATES && SEF_LU_STATE_IS_DEBUG(state);
120   is_valid_state = is_valid_state || sef_lu_cbs.sef_cb_lu_state_isvalid(state, flags);
121   if(!is_valid_state) {
122       if(sef_lu_cbs.sef_cb_lu_state_isvalid == SEF_CB_LU_STATE_ISVALID_DEFAULT) {
123           sef_lu_ready(ENOSYS);
124       }
125       else {
126           sef_lu_ready(EINVAL);
127       }
128       return OK;
129   }
130 
131   /* Handle additional state data (if any). */
132   r = sef_lu_handle_state_data(m_ptr->m_source, state, rs_state_data_gid);
133   if(r != OK) {
134       sef_lu_ready(r);
135       return OK;
136   }
137 
138   /* Set the new live update state. */
139   sef_lu_state_change(state, flags);
140 
141 
142   /* Return OK not to let anybody else intercept the request. */
143   return(OK);
144 }
145 
146 /*===========================================================================*
147  *				  sef_lu_ready				     *
148  *===========================================================================*/
149 static void sef_lu_ready(int result)
150 {
151   message m;
152   int r=EINVAL;
153 
154 #if SEF_LU_DEBUG
155   sef_lu_debug_begin();
156   sef_lu_dprint("%s, cycle=%d. Ready to update with result: %d%s\n",
157       sef_debug_header(), sef_lu_debug_cycle,
158       result, (result == OK ? "(OK)" : ""));
159   sef_lu_debug_end();
160 #endif
161 
162   /* If result is OK, let the callback code cleanup and save
163    * any state that must be carried over to the new version.
164    */
165   if(result == OK) {
166       r = sef_llvm_state_cleanup();
167       if(r == OK) {
168           r = sef_lu_cbs.sef_cb_lu_state_save(sef_lu_state, sef_lu_flags);
169       }
170       if(r != OK) {
171           /* Abort update in case of error. */
172           result = r;
173       }
174   }
175 
176   /* Let the callback code produce a live update response and block.
177    * We should get beyond this point only if either result is an error or
178    * something else goes wrong in the callback code.
179    */
180   m.m_source = sef_self_endpoint;
181   m.m_type = RS_LU_PREPARE;
182   m.m_rs_update.state = sef_lu_state;
183   m.m_rs_update.result = result;
184   r = sef_lu_cbs.sef_cb_lu_response(&m);
185 
186 #if SEF_LU_DEBUG
187   sef_lu_debug_begin();
188   sef_lu_dprint("%s, cycle=%d. The %s aborted the update with result %d!\n",
189       sef_debug_header(), sef_lu_debug_cycle,
190       (result == OK ? "server" : "client"),
191       (result == OK ? r : result)); /* EINTR if update was canceled. */
192   sef_lu_debug_end();
193 #endif
194 
195   /* Something went wrong. Update was aborted and we didn't get updated.
196    * Restore things back to normal and continue executing.
197    */
198   sef_lu_state_change(SEF_LU_STATE_NULL, 0);
199 }
200 
201 /*===========================================================================*
202  *                           sef_lu_state_change                	     *
203  *===========================================================================*/
204 static void sef_lu_state_change(int state, int flags)
205 {
206   int r, old_state;
207 
208   old_state = sef_lu_state;
209   sef_lu_state = state;
210   sef_lu_flags = flags;
211   if(sef_lu_state == SEF_LU_STATE_NULL) {
212       r = sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
213       assert(r == OK);
214   }
215   if(old_state != sef_lu_state) {
216       sef_lu_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
217   }
218 }
219 
220 /*===========================================================================*
221  *                         sef_lu_handle_state_data             	     *
222  *===========================================================================*/
223 int sef_lu_handle_state_data(endpoint_t src_e,
224     int state, cp_grant_id_t state_data_gid)
225 {
226     int r;
227     struct rs_state_data rs_state_data;
228 
229     if(state_data_gid == GRANT_INVALID) {
230         /* SEF_LU_STATE_EVAL requires an eval expression. */
231         return state == SEF_LU_STATE_EVAL ? EINVAL : OK;
232     }
233 
234     r = sys_safecopyfrom(src_e, state_data_gid, 0,
235         (vir_bytes) &rs_state_data, sizeof(rs_state_data));
236     if(r != OK) {
237         return r;
238     }
239     if(rs_state_data.size != sizeof(rs_state_data)) {
240         return E2BIG;
241     }
242     if(state == SEF_LU_STATE_EVAL) {
243         if(rs_state_data.eval_addr && rs_state_data.eval_len) {
244             if(rs_state_data.eval_len >= SEF_LU_STATE_EVAL_MAX_LEN) {
245                 return E2BIG;
246             }
247             r = sys_safecopyfrom(src_e, rs_state_data.eval_gid, 0,
248                 (vir_bytes) sef_lu_state_eval, rs_state_data.eval_len);
249             if(r != OK) {
250                 return r;
251             }
252             sef_lu_state_eval[rs_state_data.eval_len] = '\0';
253             r = sef_cb_lu_prepare_eval(SEF_LU_STATE_EVAL);
254             if(r != OK && r != ENOTREADY) {
255                 /* State expression could not be evaluated correctly. */
256                 return EINVAL;
257             }
258         }
259         else {
260             /* SEF_LU_STATE_EVAL requires a valid eval expression. */
261             return EINVAL;
262         }
263     }
264     if(rs_state_data.ipcf_els && rs_state_data.ipcf_els_size) {
265         ipc_filter_el_t ipc_filter[IPCF_MAX_ELEMENTS];
266         size_t ipc_filter_size = sizeof(ipc_filter);
267         int num_ipc_filters = rs_state_data.ipcf_els_size / ipc_filter_size;
268         int i;
269         if(rs_state_data.ipcf_els_size % ipc_filter_size) {
270             return E2BIG;
271         }
272         r = OK;
273         for(i=0;i<num_ipc_filters;i++) {
274             int num_elements=0;
275             r = sys_safecopyfrom(src_e, rs_state_data.ipcf_els_gid, i*ipc_filter_size,
276                 (vir_bytes) ipc_filter, ipc_filter_size);
277             if(r != OK) {
278                 break;
279             }
280 #if SEF_LU_DEBUG
281             sef_lu_debug_begin();
282             sef_lu_dprint("%s, Installing ipc filter:\n", sef_debug_header());
283 #endif
284             while(num_elements < IPCF_MAX_ELEMENTS && ipc_filter[num_elements].flags) {
285 #if SEF_LU_DEBUG
286                 sef_lu_dprint("el[%d]=(flags=%c%c%c%c, m_source=%d, m_type=%d)",
287                   num_elements,
288                   (ipc_filter[num_elements].flags & IPCF_MATCH_M_SOURCE) ? 'S' : '-',
289                   (ipc_filter[num_elements].flags & IPCF_MATCH_M_TYPE) ? 'T' : '-',
290                   (ipc_filter[num_elements].flags & IPCF_EL_BLACKLIST) ? 'B' : '-',
291                   (ipc_filter[num_elements].flags & IPCF_EL_WHITELIST) ? 'W' : '-',
292                   ipc_filter[num_elements].m_source, ipc_filter[num_elements].m_type);
293                 sef_lu_dprint("\n");
294 #endif
295                 num_elements++;
296             }
297 #if SEF_LU_DEBUG
298             sef_lu_debug_end();
299 #endif
300             if(num_elements == 0) {
301                 r = EINVAL;
302                 break;
303             }
304             r = sys_statectl(ipc_filter[0].flags & IPCF_EL_BLACKLIST ? SYS_STATE_ADD_IPC_BL_FILTER : SYS_STATE_ADD_IPC_WL_FILTER,
305                 ipc_filter, num_elements*sizeof(ipc_filter_el_t));
306             if(r != OK) {
307                 break;
308             }
309         }
310         if(r != OK) {
311             sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
312             return r;
313         }
314     }
315     return OK;
316 }
317 
318 /*===========================================================================*
319  *                            sef_setcb_lu_prepare                           *
320  *===========================================================================*/
321 void sef_setcb_lu_prepare(sef_cb_lu_prepare_t cb)
322 {
323   assert(cb != NULL);
324   sef_lu_cbs.sef_cb_lu_prepare = cb;
325 }
326 
327 /*===========================================================================*
328  *                         sef_setcb_lu_state_isvalid                        *
329  *===========================================================================*/
330 void sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_t cb)
331 {
332   assert(cb != NULL);
333   sef_lu_cbs.sef_cb_lu_state_isvalid = cb;
334 }
335 
336 /*===========================================================================*
337  *                         sef_setcb_lu_state_changed                        *
338  *===========================================================================*/
339 void sef_setcb_lu_state_changed(sef_cb_lu_state_changed_t cb)
340 {
341   assert(cb != NULL);
342   sef_lu_cbs.sef_cb_lu_state_changed = cb;
343 }
344 
345 /*===========================================================================*
346  *                          sef_setcb_lu_state_dump                          *
347  *===========================================================================*/
348 void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb)
349 {
350   assert(cb != NULL);
351   sef_lu_cbs.sef_cb_lu_state_dump = cb;
352 }
353 
354 /*===========================================================================*
355  *                          sef_setcb_lu_state_save                           *
356  *===========================================================================*/
357 void sef_setcb_lu_state_save(sef_cb_lu_state_save_t cb)
358 {
359   assert(cb != NULL);
360   sef_lu_cbs.sef_cb_lu_state_save = cb;
361 }
362 
363 /*===========================================================================*
364  *                          sef_setcb_lu_response                            *
365  *===========================================================================*/
366 void sef_setcb_lu_response(sef_cb_lu_response_t cb)
367 {
368   assert(cb != NULL);
369   sef_lu_cbs.sef_cb_lu_response = cb;
370 }
371 
372 /*===========================================================================*
373  *      	            sef_cb_lu_prepare_null 	 	             *
374  *===========================================================================*/
375 int sef_cb_lu_prepare_null(int UNUSED(state))
376 {
377   return ENOTREADY;
378 }
379 
380 /*===========================================================================*
381  *      	         sef_cb_lu_state_isvalid_null		             *
382  *===========================================================================*/
383 int sef_cb_lu_state_isvalid_null(int UNUSED(state), int UNUSED(flags))
384 {
385   return FALSE;
386 }
387 
388 /*===========================================================================*
389  *                       sef_cb_lu_state_changed_null        		     *
390  *===========================================================================*/
391 void sef_cb_lu_state_changed_null(int UNUSED(old_state),
392    int UNUSED(state))
393 {
394 }
395 
396 /*===========================================================================*
397  *                       sef_cb_lu_state_dump_null        		     *
398  *===========================================================================*/
399 void sef_cb_lu_state_dump_null(int UNUSED(state))
400 {
401   sef_lu_dprint("NULL\n");
402 }
403 
404 /*===========================================================================*
405  *                       sef_cb_lu_state_save_null        		     *
406  *===========================================================================*/
407 int sef_cb_lu_state_save_null(int UNUSED(result), int UNUSED(flags))
408 {
409   return OK;
410 }
411 
412 /*===========================================================================*
413  *                       sef_cb_lu_response_null        		     *
414  *===========================================================================*/
415 int sef_cb_lu_response_null(message * UNUSED(m_ptr))
416 {
417   return ENOSYS;
418 }
419 
420 /*===========================================================================*
421  *      	       sef_cb_lu_prepare_always_ready	                     *
422  *===========================================================================*/
423 int sef_cb_lu_prepare_always_ready(int UNUSED(state))
424 {
425   return OK;
426 }
427 
428 /*===========================================================================*
429  *      	       sef_cb_lu_prepare_never_ready	                     *
430  *===========================================================================*/
431 int sef_cb_lu_prepare_never_ready(int UNUSED(state))
432 {
433 #if SEF_LU_DEBUG
434   sef_lu_debug_begin();
435   sef_lu_dprint("%s, cycle=%d. Simulating a service never ready to update...\n",
436       sef_debug_header(), sef_lu_debug_cycle);
437   sef_lu_debug_end();
438 #endif
439 
440   return ENOTREADY;
441 }
442 
443 /*===========================================================================*
444  *      	         sef_cb_lu_prepare_crash	                     *
445  *===========================================================================*/
446 int sef_cb_lu_prepare_crash(int UNUSED(state))
447 {
448   panic("Simulating a crash at update prepare time...\n");
449 
450   return OK;
451 }
452 
453 /*===========================================================================*
454  *      	         sef_cb_lu_prepare_eval 	                     *
455  *===========================================================================*/
456 int sef_cb_lu_prepare_eval(int UNUSED(state))
457 {
458   char result = 0;
459   int ret = sef_llvm_eval_bool(sef_lu_state_eval, &result);
460 
461 #if SEF_LU_DEBUG
462   sef_lu_debug_begin();
463   sef_lu_dprint("%s, cycle=%d. Evaluated state expression '%s' with error code %d and result %d\n",
464       sef_debug_header(), sef_lu_debug_cycle, sef_lu_state_eval, ret, result);
465   sef_lu_debug_end();
466 #endif
467 
468   if(ret < 0) {
469       return ret == ENOTREADY ? EINTR : ret;
470   }
471   return result ? OK : ENOTREADY;
472 }
473 
474 /*===========================================================================*
475  *      	      sef_cb_lu_state_isvalid_standard                       *
476  *===========================================================================*/
477 int sef_cb_lu_state_isvalid_standard(int state, int UNUSED(flags))
478 {
479   return SEF_LU_STATE_IS_STANDARD(state);
480 }
481 
482 /*===========================================================================*
483  *      	      sef_cb_lu_state_isvalid_workfree                       *
484  *===========================================================================*/
485 int sef_cb_lu_state_isvalid_workfree(int state, int UNUSED(flags))
486 {
487   return (state == SEF_LU_STATE_WORK_FREE);
488 }
489 
490 /*===========================================================================*
491  *      	    sef_cb_lu_state_isvalid_workfree_self                    *
492  *===========================================================================*/
493 int sef_cb_lu_state_isvalid_workfree_self(int state, int flags)
494 {
495   return (state == SEF_LU_STATE_WORK_FREE) && (flags & (SEF_LU_SELF|SEF_LU_ASR));
496 }
497 
498 /*===========================================================================*
499  *      	       sef_cb_lu_state_isvalid_generic                       *
500  *===========================================================================*/
501 int sef_cb_lu_state_isvalid_generic(int state, int flags)
502 {
503   return (state == SEF_LU_STATE_EVAL) || sef_cb_lu_state_isvalid_workfree(state, flags);
504 }
505 
506 /*===========================================================================*
507  *                       sef_cb_lu_state_dump_eval        		     *
508  *===========================================================================*/
509 void sef_cb_lu_state_dump_eval(int state)
510 {
511   if(state == SEF_LU_STATE_EVAL) {
512       sef_llvm_dump_eval(sef_lu_state_eval);
513   }
514   else {
515       return sef_cb_lu_state_dump_null(state);
516   }
517 }
518 
519 /*===========================================================================*
520  *                       sef_cb_lu_response_rs_reply        		     *
521  *===========================================================================*/
522 int sef_cb_lu_response_rs_reply(message *m_ptr)
523 {
524   int r;
525 
526   /* Inform RS that we're ready with the given result. */
527   r = ipc_sendrec(RS_PROC_NR, m_ptr);
528   if ( r != OK) {
529       return r;
530   }
531 
532   return m_ptr->m_type == RS_LU_PREPARE ? EINTR : m_ptr->m_type;
533 }
534 
535