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