1 #include "syslib.h" 2 #include <assert.h> 3 #include <minix/sysutil.h> 4 #include <minix/rs.h> 5 #include <minix/timers.h> 6 #include <minix/endpoint.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <unistd.h> 10 #include <string.h> 11 12 /* Self variables. */ 13 #define SEF_SELF_NAME_MAXLEN 20 14 char sef_self_name[SEF_SELF_NAME_MAXLEN]; 15 endpoint_t sef_self_endpoint = NONE; 16 endpoint_t sef_self_proc_nr; 17 int sef_self_priv_flags; 18 int sef_self_init_flags; 19 int sef_self_receiving; 20 int sef_controlled_crash; 21 22 /* Extern variables. */ 23 EXTERN int sef_lu_state; 24 EXTERN int __sef_st_before_receive_enabled; 25 EXTERN __attribute__((weak)) int __vm_init_fresh; 26 27 /* Debug. */ 28 #if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG 29 #define SEF_DEBUG_HEADER_MAXLEN 50 30 static int sef_debug_init = 0; 31 static time_t sef_debug_boottime = 0; 32 static u32_t sef_debug_system_hz = 0; 33 static time_t sef_debug_time_sec = 0; 34 static time_t sef_debug_time_us = 0; 35 static char sef_debug_header_buff[SEF_DEBUG_HEADER_MAXLEN]; 36 static void sef_debug_refresh_params(void); 37 char* sef_debug_header(void); 38 #endif 39 40 /* SEF Init prototypes. */ 41 EXTERN int do_sef_rs_init(endpoint_t old_endpoint); 42 EXTERN int do_sef_init_request(message *m_ptr); 43 44 /* SEF Ping prototypes. */ 45 EXTERN int do_sef_ping_request(message *m_ptr); 46 47 /* SEF Live update prototypes. */ 48 EXTERN void do_sef_lu_before_receive(void); 49 EXTERN int do_sef_lu_request(message *m_ptr); 50 51 /* SEF Signal prototypes. */ 52 EXTERN int do_sef_signal_request(message *m_ptr); 53 54 /* State transfer prototypes. */ 55 EXTERN void do_sef_st_before_receive(void); 56 57 /* SEF GCOV prototypes. */ 58 #ifdef USE_COVERAGE 59 EXTERN int do_sef_gcov_request(message *m_ptr); 60 #endif 61 62 /* SEF Fault Injection prototypes. */ 63 EXTERN int do_sef_fi_request(message *m_ptr); 64 65 /*===========================================================================* 66 * sef_startup * 67 *===========================================================================*/ 68 void sef_startup() 69 { 70 /* SEF startup interface for system services. */ 71 int r, status; 72 endpoint_t old_endpoint; 73 int priv_flags; 74 int init_flags; 75 int sys_upd_flags = 0; 76 77 /* Get information about self. */ 78 r = sys_whoami(&sef_self_endpoint, sef_self_name, SEF_SELF_NAME_MAXLEN, 79 &priv_flags, &init_flags); 80 if ( r != OK) { 81 panic("sef_startup: sys_whoami failed: %d\n", r); 82 } 83 84 sef_self_proc_nr = _ENDPOINT_P(sef_self_endpoint); 85 sef_self_priv_flags = priv_flags; 86 sef_self_init_flags = init_flags; 87 sef_lu_state = SEF_LU_STATE_NULL; 88 sef_controlled_crash = FALSE; 89 old_endpoint = NONE; 90 if(init_flags & SEF_LU_NOMMAP) { 91 sys_upd_flags |= SF_VM_NOMMAP; 92 } 93 94 #if USE_LIVEUPDATE 95 /* RS may wake up with the wrong endpoint, perfom the update in that case. */ 96 if((sef_self_priv_flags & ROOT_SYS_PROC) && sef_self_endpoint != RS_PROC_NR) { 97 r = vm_update(RS_PROC_NR, sef_self_endpoint, sys_upd_flags); 98 if(r != OK) { 99 panic("unable to update RS from instance %d to %d: %d", 100 RS_PROC_NR, sef_self_endpoint, r); 101 } 102 old_endpoint = sef_self_endpoint; 103 sef_self_endpoint = RS_PROC_NR; 104 } 105 #endif /* USE_LIVEUPDATE */ 106 107 #if INTERCEPT_SEF_INIT_REQUESTS 108 /* Intercept SEF Init requests. */ 109 if(sef_self_priv_flags & ROOT_SYS_PROC) { 110 /* RS initialization is special. */ 111 if((r = do_sef_rs_init(old_endpoint)) != OK) { 112 panic("RS unable to complete init: %d", r); 113 } 114 } 115 else if(sef_self_endpoint == VM_PROC_NR && __vm_init_fresh) { 116 /* VM handles fresh initialization by RS later */ 117 } else { 118 message m; 119 120 /* Wait for an initialization message from RS. We need this to learn the 121 * initialization type and parameters. When restarting after a crash, we 122 * may get some spurious IPC messages from RS (e.g. update request) that 123 * were originally meant to be delivered to the old instance. We discard 124 * these messages and block till a proper initialization request arrives. 125 */ 126 do { 127 r = ipc_receive(RS_PROC_NR, &m, &status); 128 if(r != OK) { 129 panic("unable to ipc_receive from RS: %d", r); 130 } 131 } while(!IS_SEF_INIT_REQUEST(&m, status)); 132 133 /* Process initialization request for this system service. */ 134 if((r = do_sef_init_request(&m)) != OK) { 135 panic("unable to process init request: %d", r); 136 } 137 } 138 #endif 139 140 /* (Re)initialize SEF variables. */ 141 sef_self_priv_flags = priv_flags; 142 sef_self_init_flags = init_flags; 143 sef_lu_state = SEF_LU_STATE_NULL; 144 sef_controlled_crash = FALSE; 145 } 146 147 /*===========================================================================* 148 * sef_receive_status * 149 *===========================================================================*/ 150 int sef_receive_status(endpoint_t src, message *m_ptr, int *status_ptr) 151 { 152 /* SEF receive() interface for system services. */ 153 int r, status, m_type; 154 155 sef_self_receiving = TRUE; 156 157 while(TRUE) { 158 /* If the caller indicated that it no longer wants to receive a message, 159 * return now. 160 */ 161 if (!sef_self_receiving) 162 return EINTR; 163 164 #if INTERCEPT_SEF_LU_REQUESTS 165 /* Handle SEF Live update before receive events. */ 166 if(sef_lu_state != SEF_LU_STATE_NULL) { 167 do_sef_lu_before_receive(); 168 } 169 170 /* Handle State transfer before receive events. */ 171 if(__sef_st_before_receive_enabled) { 172 do_sef_st_before_receive(); 173 } 174 #endif 175 176 /* Receive and return in case of error. */ 177 r = ipc_receive(src, m_ptr, &status); 178 if(status_ptr) *status_ptr = status; 179 if(r != OK) { 180 return r; 181 } 182 183 m_type = m_ptr->m_type; 184 if (is_ipc_notify(status)) { 185 switch (m_ptr->m_source) { 186 case SYSTEM: 187 m_type = SEF_SIGNAL_REQUEST_TYPE; 188 break; 189 case RS_PROC_NR: 190 m_type = SEF_PING_REQUEST_TYPE; 191 break; 192 } 193 } 194 switch(m_type) { 195 196 #if INTERCEPT_SEF_INIT_REQUESTS 197 case SEF_INIT_REQUEST_TYPE: 198 /* Intercept SEF Init requests. */ 199 if(IS_SEF_INIT_REQUEST(m_ptr, status)) { 200 /* Ignore spurious init requests. */ 201 if (m_ptr->m_rs_init.type != SEF_INIT_FRESH 202 || sef_self_endpoint != VM_PROC_NR) 203 continue; 204 } 205 break; 206 #endif 207 208 #if INTERCEPT_SEF_PING_REQUESTS 209 case SEF_PING_REQUEST_TYPE: 210 /* Intercept SEF Ping requests. */ 211 if(IS_SEF_PING_REQUEST(m_ptr, status)) { 212 if(do_sef_ping_request(m_ptr) == OK) { 213 continue; 214 } 215 } 216 break; 217 #endif 218 219 #if INTERCEPT_SEF_LU_REQUESTS 220 case SEF_LU_REQUEST_TYPE: 221 /* Intercept SEF Live update requests. */ 222 if(IS_SEF_LU_REQUEST(m_ptr, status)) { 223 if(do_sef_lu_request(m_ptr) == OK) { 224 continue; 225 } 226 } 227 break; 228 #endif 229 230 #if INTERCEPT_SEF_SIGNAL_REQUESTS 231 case SEF_SIGNAL_REQUEST_TYPE: 232 /* Intercept SEF Signal requests. */ 233 if(IS_SEF_SIGNAL_REQUEST(m_ptr, status)) { 234 if(do_sef_signal_request(m_ptr) == OK) { 235 continue; 236 } 237 } 238 break; 239 #endif 240 241 #if INTERCEPT_SEF_GCOV_REQUESTS && USE_COVERAGE 242 case SEF_GCOV_REQUEST_TYPE: 243 /* Intercept GCOV data requests (sent by VFS in vfs/gcov.c). */ 244 if(IS_SEF_GCOV_REQUEST(m_ptr, status)) { 245 if(do_sef_gcov_request(m_ptr) == OK) { 246 continue; 247 } 248 } 249 break; 250 #endif 251 252 #if INTERCEPT_SEF_FI_REQUESTS 253 case SEF_FI_REQUEST_TYPE: 254 /* Intercept SEF Fault Injection requests. */ 255 if(IS_SEF_FI_REQUEST(m_ptr, status)) { 256 if(do_sef_fi_request(m_ptr) == OK) { 257 continue; 258 } 259 } 260 break; 261 #endif 262 263 default: 264 break; 265 } 266 267 /* If we get this far, this is not a valid SEF request, return and 268 * let the caller deal with that. 269 */ 270 break; 271 } 272 273 return r; 274 } 275 276 /*===========================================================================* 277 * sef_self * 278 *===========================================================================*/ 279 endpoint_t sef_self(void) 280 { 281 /* Return the process's own endpoint number. */ 282 283 if (sef_self_endpoint == NONE) 284 panic("sef_self called before initialization"); 285 286 return sef_self_endpoint; 287 } 288 289 /*===========================================================================* 290 * sef_cancel * 291 *===========================================================================*/ 292 void sef_cancel(void) 293 { 294 /* Cancel receiving a message. This function be called from a callback invoked 295 * from within sef_receive_status(), which will then return an EINTR error 296 * code. In particular, this function can be used to exit from the main receive 297 * loop when a signal handler causes the process to want to shut down. 298 */ 299 300 sef_self_receiving = FALSE; 301 } 302 303 /*===========================================================================* 304 * sef_getrndseed * 305 *===========================================================================*/ 306 int sef_getrndseed(void) 307 { 308 return (int)getticks(); 309 } 310 311 /*===========================================================================* 312 * sef_exit * 313 *===========================================================================*/ 314 void sef_exit(int status) 315 { 316 /* System services use a special version of exit() that generates a 317 * self-termination signal. 318 */ 319 320 /* Ask the kernel to exit. */ 321 sys_exit(); 322 323 /* If everything else fails, hang. */ 324 printf("Warning: system service %d couldn't exit\n", sef_self_endpoint); 325 for(;;) { } 326 } 327 328 #ifdef __weak_alias 329 __weak_alias(_exit, sef_exit); 330 __weak_alias(__exit, sef_exit); 331 #endif 332 333 /*===========================================================================* 334 * sef_munmap * 335 *===========================================================================*/ 336 int sef_munmap(void *addrstart, vir_bytes len, int type) 337 { 338 /* System services use a special version of munmap() to control implicit 339 * munmaps as startup and allow for asynchronous mnmap for VM. 340 */ 341 message m; 342 m.m_type = type; 343 m.VMUM_ADDR = addrstart; 344 m.VMUM_LEN = len; 345 if(sef_self_endpoint == VM_PROC_NR) { 346 return asynsend3(SELF, &m, AMF_NOREPLY); 347 } 348 return _syscall(VM_PROC_NR, type, &m); 349 } 350 351 #if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG 352 /*===========================================================================* 353 * sef_debug_refresh_params * 354 *===========================================================================*/ 355 static void sef_debug_refresh_params(void) 356 { 357 /* Refresh SEF debug params. */ 358 clock_t uptime; 359 360 /* Get boottime and system hz the first time. */ 361 if(!sef_debug_init) { 362 if (sys_times(NONE, NULL, NULL, NULL, &sef_debug_boottime) != OK) 363 sef_debug_init = -1; 364 else if (sys_getinfo(GET_HZ, &sef_debug_system_hz, 365 sizeof(sef_debug_system_hz), 0, 0) != OK) 366 sef_debug_init = -1; 367 else 368 sef_debug_init = 1; 369 } 370 371 /* Get uptime. */ 372 uptime = -1; 373 if (sef_debug_init < 1 || sys_times(NONE, NULL, NULL, &uptime, NULL) != OK) { 374 sef_debug_time_sec = 0; 375 sef_debug_time_us = 0; 376 } 377 else { 378 /* Compute current time. */ 379 sef_debug_time_sec = (time_t) (sef_debug_boottime 380 + (uptime/sef_debug_system_hz)); 381 sef_debug_time_us = (uptime%sef_debug_system_hz) 382 * 1000000/sef_debug_system_hz; 383 } 384 } 385 386 /*===========================================================================* 387 * sef_debug_header * 388 *===========================================================================*/ 389 char* sef_debug_header(void) 390 { 391 /* Build and return a SEF debug header. */ 392 sef_debug_refresh_params(); 393 snprintf(sef_debug_header_buff, sizeof(sef_debug_header_buff), 394 "%s: time = %ds %06dus", sef_self_name, (int) sef_debug_time_sec, 395 (int) sef_debug_time_us); 396 397 return sef_debug_header_buff; 398 } 399 #endif /*SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG*/ 400 401