5 #include <machine/vmparam.h>
7 #include <minix/sysutil.h>
10 /* SEF Init callbacks. */
11 static struct sef_init_cbs
{
12 sef_cb_init_t sef_cb_init_fresh
;
13 sef_cb_init_t sef_cb_init_lu
;
14 sef_cb_init_t sef_cb_init_restart
;
15 sef_cb_init_response_t sef_cb_init_response
;
17 SEF_CB_INIT_FRESH_DEFAULT
,
18 SEF_CB_INIT_LU_DEFAULT
,
19 SEF_CB_INIT_RESTART_DEFAULT
,
20 SEF_CB_INIT_RESPONSE_DEFAULT
23 /* SEF Init prototypes for sef_startup(). */
24 int do_sef_rs_init(endpoint_t old_endpoint
);
25 int do_sef_init_request(message
*m_ptr
);
28 EXTERN
char* sef_debug_header(void);
30 /* Information about SELF. */
31 EXTERN endpoint_t sef_self_endpoint
;
32 EXTERN endpoint_t sef_self_priv_flags
;
33 EXTERN endpoint_t sef_self_init_flags
;
34 EXTERN
int sef_controlled_crash
;
36 #ifndef ST_STACK_REFS_BUFF_SIZE
37 #define ST_STACK_REFS_BUFF_SIZE 1024
40 /*===========================================================================*
42 *===========================================================================*/
43 static int process_init(int type
, sef_init_info_t
*info
)
45 /* Process initialization. */
46 int r
, result
, debug_result_found
, is_def_cb
;
52 sef_init_debug_begin();
53 sef_init_dprint("%s. Got a SEF Init request of type %d, flags 0x%08x, rproctab_gid %d, ep %d, old ep %d, restarts %d. About to init.\n",
54 sef_debug_header(), type
, info
->flags
, info
->rproctab_gid
, info
->endpoint
, info
->old_endpoint
, info
->restarts
);
58 /* Clear any IPC filter. */
59 r
= sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS
, 0, 0);
62 /* Create grant for state transfer. */
63 gid
= cpf_grant_direct(sef_self_endpoint
, 0, ULONG_MAX
, CPF_READ
);
64 if(!GRANT_VALID(gid
)) {
65 panic("unable to create grant for state transfer");
67 if(gid
!= SEF_STATE_TRANSFER_GID
) {
68 panic("bad state transfer gid");
71 /* If debug init flags are allowed, process them first. */
72 debug_result_found
= 0;
73 if(SEF_INIT_ALLOW_DEBUG_INIT_FLAGS
) {
74 int flags
= info
->flags
;
75 if(flags
& SEF_INIT_CRASH
) {
76 result
= sef_cb_init_crash(type
, info
);
77 debug_result_found
= 1;
79 else if(flags
& SEF_INIT_FAIL
) {
80 result
= sef_cb_init_fail(type
, info
);
81 debug_result_found
= 1;
83 else if(flags
& SEF_INIT_TIMEOUT
) {
84 result
= sef_cb_init_timeout(type
, info
);
85 debug_result_found
= 1;
89 if(!debug_result_found
) {
90 /* Let the callback code handle the specific initialization type. */
91 is_def_cb
= info
->flags
& SEF_INIT_DEFCB
;
94 result
= is_def_cb
? SEF_CB_INIT_FRESH_DEFAULT(type
, info
)
95 : sef_init_cbs
.sef_cb_init_fresh(type
, info
);
98 result
= is_def_cb
? SEF_CB_INIT_LU_DEFAULT(type
, info
)
99 : sef_init_cbs
.sef_cb_init_lu(type
, info
);
101 case SEF_INIT_RESTART
:
102 result
= is_def_cb
? SEF_CB_INIT_RESTART_DEFAULT(type
, info
)
103 : sef_init_cbs
.sef_cb_init_restart(type
, info
);
107 /* Not a valid SEF init type. */
113 memset(&m
, 0, sizeof(m
));
114 m
.m_source
= sef_self_endpoint
;
116 m
.m_rs_init
.result
= result
;
117 r
= sef_init_cbs
.sef_cb_init_response(&m
);
122 /* See if we need to unmap the initialization buffer. */
123 if(info
->init_buff_cleanup_start
) {
124 void *addrstart
= info
->init_buff_cleanup_start
;
125 size_t len
= info
->init_buff_len
- (size_t)((char*)info
->init_buff_cleanup_start
- (char*)info
->init_buff_start
);
126 r
= sef_munmap(addrstart
, len
, VM_MUNMAP
);
128 printf("process_init: warning: munmap failed for init buffer\n");
132 /* Tell the kernel about the grant table. */
135 /* Tell the kernel about the senda table. */
138 printf("process_init: warning: senda_reload failed\n");
141 /* Tell the kernel about the state table. */
142 sys_statectl(SYS_STATE_SET_STATE_TABLE
, sef_llvm_state_table_addr(), 0);
147 /*===========================================================================*
149 *===========================================================================*/
150 int do_sef_rs_init(endpoint_t old_endpoint
)
152 /* Special SEF Init for RS. */
155 sef_init_info_t info
;
156 memset(&info
, 0, sizeof(info
));
158 /* Get init parameters from SEF. */
159 type
= SEF_INIT_FRESH
;
160 if(sef_self_priv_flags
& LU_SYS_PROC
) {
163 else if(sef_self_priv_flags
& RST_SYS_PROC
) {
164 type
= SEF_INIT_RESTART
;
166 info
.flags
= sef_self_init_flags
;
167 info
.rproctab_gid
= GRANT_INVALID
;
168 info
.endpoint
= sef_self_endpoint
;
169 info
.old_endpoint
= old_endpoint
;
172 /* Get init buffer details from VM. */
173 info
.init_buff_start
= NULL
;
174 info
.init_buff_len
= 0;
175 if(type
!= SEF_INIT_FRESH
) {
176 r
= vm_memctl(RS_PROC_NR
, VM_RS_MEM_GET_PREALLOC_MAP
,
177 &info
.init_buff_start
, &info
.init_buff_len
);
179 printf("do_sef_rs_init: vm_memctl failed\n");
182 info
.init_buff_cleanup_start
= info
.init_buff_start
;
184 /* Peform initialization. */
185 r
= process_init(type
, &info
);
190 /*===========================================================================*
191 * do_sef_init_request *
192 *===========================================================================*/
193 int do_sef_init_request(message
*m_ptr
)
195 /* Handle a SEF Init request. */
198 sef_init_info_t info
;
199 memset(&info
, 0, sizeof(info
));
201 /* Get init parameters from message. */
202 type
= m_ptr
->m_rs_init
.type
;
203 info
.flags
= m_ptr
->m_rs_init
.flags
;
204 info
.rproctab_gid
= m_ptr
->m_rs_init
.rproctab_gid
;
205 info
.endpoint
= sef_self_endpoint
;
206 info
.old_endpoint
= m_ptr
->m_rs_init
.old_endpoint
;
207 info
.restarts
= m_ptr
->m_rs_init
.restarts
;
208 info
.init_buff_start
= (void*) m_ptr
->m_rs_init
.buff_addr
;
209 info
.init_buff_cleanup_start
= info
.init_buff_start
;
210 info
.init_buff_len
= m_ptr
->m_rs_init
.buff_len
;
211 info
.prepare_state
= m_ptr
->m_rs_init
.prepare_state
;
213 /* Peform initialization. */
214 r
= process_init(type
, &info
);
219 /*===========================================================================*
220 * sef_setcb_init_fresh *
221 *===========================================================================*/
222 void sef_setcb_init_fresh(sef_cb_init_t cb
)
225 sef_init_cbs
.sef_cb_init_fresh
= cb
;
228 /*===========================================================================*
229 * sef_setcb_init_lu *
230 *===========================================================================*/
231 void sef_setcb_init_lu(sef_cb_init_t cb
)
234 sef_init_cbs
.sef_cb_init_lu
= cb
;
237 /*===========================================================================*
238 * sef_setcb_init_restart *
239 *===========================================================================*/
240 void sef_setcb_init_restart(sef_cb_init_t cb
)
243 sef_init_cbs
.sef_cb_init_restart
= cb
;
246 /*===========================================================================*
247 * sef_setcb_init_response *
248 *===========================================================================*/
249 void sef_setcb_init_response(sef_cb_init_response_t cb
)
252 sef_init_cbs
.sef_cb_init_response
= cb
;
255 /*===========================================================================*
257 *===========================================================================*/
258 int sef_cb_init_null(int UNUSED(type
),
259 sef_init_info_t
*UNUSED(info
))
264 /*===========================================================================*
265 * sef_cb_init_response_null *
266 *===========================================================================*/
267 int sef_cb_init_response_null(message
* UNUSED(m_ptr
))
272 /*===========================================================================*
274 *===========================================================================*/
275 int sef_cb_init_fail(int UNUSED(type
), sef_init_info_t
*UNUSED(info
))
280 /*===========================================================================*
281 * sef_cb_init_reset *
282 *===========================================================================*/
283 int sef_cb_init_reset(int UNUSED(type
), sef_init_info_t
*UNUSED(info
))
285 /* Tell RS to reincarnate us, with no old resources, and a new endpoint. */
289 /*===========================================================================*
290 * sef_cb_init_crash *
291 *===========================================================================*/
292 int sef_cb_init_crash(int UNUSED(type
), sef_init_info_t
*UNUSED(info
))
294 panic("Simulating a crash at initialization time...\n");
299 /*===========================================================================*
300 * sef_cb_init_timeout *
301 *===========================================================================*/
302 int sef_cb_init_timeout(int UNUSED(type
), sef_init_info_t
*UNUSED(info
))
307 printf("Simulating a timeout at initialization time...\n");
309 ipc_receive(IDLE
, &m
, &status
);
314 /*===========================================================================*
315 * sef_cb_init_restart_generic *
316 *===========================================================================*/
317 int sef_cb_init_restart_generic(int type
, sef_init_info_t
*info
)
319 /* Always resort to simple identity transfer for self updates. */
320 if (type
== SEF_INIT_LU
&& (info
->flags
& SEF_LU_SELF
))
321 return sef_cb_init_identity_state_transfer(type
, info
);
323 /* Can only handle restart otherwise. */
324 if(type
!= SEF_INIT_RESTART
) {
325 printf("sef_cb_init_restart_generic: init failed\n");
329 /* Perform instrumentation-supported checkpoint-restart. */
330 return sef_llvm_ltckpt_restart(type
, info
);
333 /*===========================================================================*
334 * sef_cb_init_identity_state_transfer *
335 *===========================================================================*/
336 int sef_cb_init_identity_state_transfer(int type
, sef_init_info_t
*info
)
338 extern char *_brksize
;
341 char *old_brksize
, *new_brksize
;
342 char stack_buff
[ST_STACK_REFS_BUFF_SIZE
];
343 vir_bytes data_start
;
346 /* Identity state transfer is for crash recovery and self update only. */
347 if(type
!= SEF_INIT_RESTART
&& (type
!= SEF_INIT_LU
|| !(info
->flags
& SEF_LU_SELF
))) {
348 printf("sef_cb_init_identity_state_transfer: state transfer failed\n");
352 /* Save stack refs. */
353 sef_llvm_stack_refs_save(stack_buff
);
355 old_brksize
= _brksize
;
356 data_start
= (vir_bytes
)&_etext
;
358 printf("sef_cb_init_identity_state_transfer: _brksize = 0x%08x, _etext = 0x%08x, data_start = 0x%08x\n",
359 _brksize
, &_etext
, data_start
);
363 size
= (size_t)(_brksize
- data_start
);
365 r
= sef_copy_state_region(info
, data_start
, size
, data_start
,
366 TRUE
/*may_have_holes*/);
370 new_brksize
= _brksize
;
372 /* Transfer heap if necessary. */
373 if(sef_self_endpoint
!= VM_PROC_NR
&& old_brksize
!= new_brksize
) {
376 printf("sef_cb_init_identity_state_transfer: brk() for new_brksize = 0x%08x\n",
380 /* Extend heap first. */
381 _brksize
= old_brksize
;
382 r
= sef_llvm_real_brk(new_brksize
);
384 printf("sef_cb_init_identity_state_transfer: brk failed\n");
388 /* Transfer state on the heap. */
389 assert(_brksize
== new_brksize
);
390 size
= (size_t)(_brksize
- old_brksize
);
391 r
= sef_copy_state_region(info
, (vir_bytes
) old_brksize
, size
,
392 (vir_bytes
) old_brksize
, FALSE
/*may_have_holes*/);
394 printf("sef_cb_init_identity_state_transfer: extended heap transfer failed\n");
399 /* Restore stack refs. */
400 sef_llvm_stack_refs_restore(stack_buff
);
402 if (sef_controlled_crash
== FALSE
) {
403 printf("SEF(%d): crash was not controlled, "
404 "aborting transparent restart\n", sef_self_endpoint
);
405 return EGENERIC
; /* actual error code does not matter */
411 /*===========================================================================*
412 * sef_cb_init_lu_identity_as_restart *
413 *===========================================================================*/
414 int sef_cb_init_lu_identity_as_restart(int type
, sef_init_info_t
*info
)
416 /* Can only handle live update. */
417 if(type
!= SEF_INIT_LU
) {
418 printf("sef_cb_init_lu_identity_as_restart: init failed\n");
422 /* Resort to restart callback only for identity updates, ignore other cases. */
423 if(SEF_LU_IS_IDENTITY_UPDATE(info
->flags
)) {
424 if((info
->flags
& (SEF_INIT_DEFCB
|SEF_INIT_SCRIPT_RESTART
))
425 || sef_init_cbs
.sef_cb_init_restart
== sef_cb_init_reset
) {
426 /* Use stateful restart callback when necessary. */
427 return SEF_CB_INIT_RESTART_STATEFUL(type
, info
);
429 return sef_init_cbs
.sef_cb_init_restart(type
, info
);
435 /*===========================================================================*
436 * sef_cb_init_lu_generic *
437 *===========================================================================*/
438 int sef_cb_init_lu_generic(int type
, sef_init_info_t
*info
)
440 /* Can only handle live update. */
441 if(type
!= SEF_INIT_LU
) {
442 printf("sef_cb_init_lu_generic: init failed\n");
446 /* Resort to restart callback for identity updates. */
447 if(SEF_LU_IS_IDENTITY_UPDATE(info
->flags
)) {
448 return sef_cb_init_lu_identity_as_restart(type
, info
);
451 /* Perform state transfer updates in all the other cases. */
452 return sef_st_state_transfer(info
);
455 /*===========================================================================*
456 * sef_cb_init_response_rs_reply *
457 *===========================================================================*/
458 int sef_cb_init_response_rs_reply(message
*m_ptr
)
462 /* Inform RS that we completed initialization with the given result. */
463 r
= ipc_sendrec(RS_PROC_NR
, m_ptr
);
468 /*===========================================================================*
469 * sef_cb_init_response_rs_asyn_once *
470 *===========================================================================*/
471 int sef_cb_init_response_rs_asyn_once(message
*m_ptr
)
473 /* This response function is used by VM to avoid a boot-time deadlock. */
476 /* Inform RS that we completed initialization, asynchronously. */
477 r
= asynsend3(RS_PROC_NR
, m_ptr
, AMF_NOREPLY
);
479 /* Use a blocking reply call next time. */
480 sef_setcb_init_response(SEF_CB_INIT_RESPONSE_DEFAULT
);