sef: Extensions for new RS.
Change-Id: I89b6f8015b1f9c46bf98694450bdaa80b7777940
This commit is contained in:
parent
006d6e94f9
commit
d196e2c333
9 changed files with 836 additions and 66 deletions
|
@ -11,6 +11,8 @@ int sef_receive_status(endpoint_t src, message *m_ptr, int *status_ptr);
|
|||
endpoint_t sef_self(void);
|
||||
void sef_cancel(void);
|
||||
void __dead sef_exit(int status);
|
||||
int sef_getrndseed (void);
|
||||
int sef_munmap(void *addrstart, vir_bytes len, int type);
|
||||
#define sef_receive(src, m_ptr) sef_receive_status(src, m_ptr, NULL)
|
||||
|
||||
/* SEF global definitions. */
|
||||
|
@ -46,6 +48,7 @@ typedef struct {
|
|||
void* init_buff_start;
|
||||
void* init_buff_cleanup_start;
|
||||
size_t init_buff_len;
|
||||
int copy_flags;
|
||||
} sef_init_info_t;
|
||||
|
||||
/* Callback type definitions. */
|
||||
|
@ -65,6 +68,10 @@ int sef_cb_init_response_null(message *m_ptr);
|
|||
int sef_cb_init_fail(int type, sef_init_info_t *info);
|
||||
int sef_cb_init_reset(int type, sef_init_info_t *info);
|
||||
int sef_cb_init_crash(int type, sef_init_info_t *info);
|
||||
int sef_cb_init_timeout(int type, sef_init_info_t *info);
|
||||
int sef_cb_init_identity_state_transfer(int type, sef_init_info_t *info);
|
||||
int sef_cb_init_lu_identity_as_restart(int type, sef_init_info_t *info);
|
||||
int sef_cb_init_lu_generic(int type, sef_init_info_t *info);
|
||||
int sef_cb_init_response_rs_reply(message *m_ptr);
|
||||
|
||||
/* Macros for predefined callback implementations. */
|
||||
|
@ -175,10 +182,12 @@ int sef_cb_lu_response_null(message *m_ptr);
|
|||
int sef_cb_lu_prepare_always_ready(int state);
|
||||
int sef_cb_lu_prepare_never_ready(int state);
|
||||
int sef_cb_lu_prepare_crash(int state);
|
||||
int sef_cb_lu_prepare_eval(int state);
|
||||
int sef_cb_lu_state_isvalid_standard(int state, int flags);
|
||||
int sef_cb_lu_state_isvalid_workfree(int state, int flags);
|
||||
int sef_cb_lu_state_isvalid_workfree_self(int state, int flags);
|
||||
int sef_cb_lu_state_isvalid_generic(int state, int flags);
|
||||
void sef_cb_lu_state_dump_eval(int state);
|
||||
int sef_cb_lu_response_rs_reply(message *m_ptr);
|
||||
|
||||
/* Macros for predefined callback implementations. */
|
||||
|
@ -316,6 +325,49 @@ void sef_setcb_gcov(sef_cb_gcov_t cb);
|
|||
/* Fault injection tool support. */
|
||||
#define SEF_FI_ALLOW_EDFI 1
|
||||
|
||||
/*===========================================================================*
|
||||
* SEF State Transfer *
|
||||
*===========================================================================*/
|
||||
#define SEF_LU_STATE_EVAL_MAX_LEN 512
|
||||
|
||||
/* State transfer helpers. */
|
||||
int sef_copy_state_region_ctl(sef_init_info_t *info,
|
||||
vir_bytes *src_address, vir_bytes *dst_address);
|
||||
int sef_copy_state_region(sef_init_info_t *info,
|
||||
vir_bytes address, size_t size, vir_bytes dst_address);
|
||||
int sef_st_state_transfer(sef_init_info_t *info);
|
||||
|
||||
/* Callback prototypes to be passed to the State Transfer framwork. */
|
||||
int sef_old_state_table_lookup(sef_init_info_t *info, void *addr);
|
||||
int sef_old_state_table_lookup_opaque(void *info_opaque, void *addr);
|
||||
int sef_copy_state_region_opaque(void *info_opaque, uint32_t address,
|
||||
size_t size, uint32_t dst_address);
|
||||
|
||||
/* Debug. */
|
||||
#define SEF_ST_DEBUG_DEFAULT 0
|
||||
|
||||
#ifndef SEF_ST_DEBUG
|
||||
#define SEF_ST_DEBUG SEF_ST_DEBUG_DEFAULT
|
||||
#endif
|
||||
|
||||
/*===========================================================================*
|
||||
* SEF LLVM *
|
||||
*===========================================================================*/
|
||||
/* LLVM helpers. */
|
||||
int sef_llvm_magic_enabled(void);
|
||||
int sef_llvm_real_brk(char *newbrk);
|
||||
int sef_llvm_state_cleanup(void);
|
||||
void sef_llvm_dump_eval(char *expr);
|
||||
int sef_llvm_eval_bool(char *expr, char *result);
|
||||
void *sef_llvm_state_table_addr(void);
|
||||
size_t sef_llvm_state_table_size(void);
|
||||
void sef_llvm_stack_refs_save(char *stack_buff);
|
||||
void sef_llvm_stack_refs_restore(char *stack_buff);
|
||||
int sef_llvm_state_transfer(sef_init_info_t *info);
|
||||
|
||||
int sef_llvm_ltckpt_enabled(void);
|
||||
int sef_llvm_get_ltckpt_offset(void);
|
||||
|
||||
#if !defined(USE_LIVEUPDATE)
|
||||
#undef INTERCEPT_SEF_LU_REQUESTS
|
||||
#undef SEF_LU_DEBUG
|
||||
|
|
|
@ -43,8 +43,10 @@ SRCS+= \
|
|||
sef_fi.c \
|
||||
sef_init.c \
|
||||
sef_liveupdate.c \
|
||||
sef_llvm.c \
|
||||
sef_ping.c \
|
||||
sef_signal.c \
|
||||
sef_st.c \
|
||||
sqrt_approx.c \
|
||||
srv_fork.c \
|
||||
srv_kill.c \
|
||||
|
@ -139,5 +141,6 @@ CPPFLAGS+= -DUSE_SYSDEBUG
|
|||
.endif
|
||||
|
||||
CPPFLAGS.sched_start.c+= -I${NETBSDSRCDIR}/minix
|
||||
CPPFLAGS.sef_st.c+= -I${NETBSDSRCDIR}/minix
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "syslib.h"
|
||||
#include <assert.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <minix/rs.h>
|
||||
#include <minix/timers.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
@ -10,13 +13,18 @@
|
|||
#define SEF_SELF_NAME_MAXLEN 20
|
||||
char sef_self_name[SEF_SELF_NAME_MAXLEN];
|
||||
endpoint_t sef_self_endpoint = NONE;
|
||||
endpoint_t sef_self_proc_nr;
|
||||
int sef_self_priv_flags;
|
||||
int sef_self_first_receive_done;
|
||||
int sef_self_init_flags;
|
||||
int sef_self_receiving;
|
||||
|
||||
/* Extern variables. */
|
||||
EXTERN int sef_lu_state;
|
||||
EXTERN int __sef_st_before_receive_enabled;
|
||||
|
||||
/* Debug. */
|
||||
#if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG
|
||||
#define SEF_DEBUG_HEADER_MAXLEN 32
|
||||
#define SEF_DEBUG_HEADER_MAXLEN 50
|
||||
static int sef_debug_init = 0;
|
||||
static time_t sef_debug_boottime = 0;
|
||||
static u32_t sef_debug_system_hz = 0;
|
||||
|
@ -41,6 +49,9 @@ EXTERN int do_sef_lu_request(message *m_ptr);
|
|||
/* SEF Signal prototypes. */
|
||||
EXTERN int do_sef_signal_request(message *m_ptr);
|
||||
|
||||
/* State transfer prototypes. */
|
||||
EXTERN void do_sef_st_before_receive(void);
|
||||
|
||||
/* SEF GCOV prototypes. */
|
||||
#ifdef USE_COVERAGE
|
||||
EXTERN int do_sef_gcov_request(message *m_ptr);
|
||||
|
@ -67,8 +78,15 @@ void sef_startup()
|
|||
if ( r != OK) {
|
||||
panic("sef_startup: sys_whoami failed: %d\n", r);
|
||||
}
|
||||
|
||||
sef_self_proc_nr = _ENDPOINT_P(sef_self_endpoint);
|
||||
sef_self_priv_flags = priv_flags;
|
||||
sef_self_init_flags = init_flags;
|
||||
sef_lu_state = SEF_LU_STATE_NULL;
|
||||
old_endpoint = NONE;
|
||||
if(init_flags & SEF_LU_NOMMAP) {
|
||||
sys_upd_flags |= SF_VM_NOMMAP;
|
||||
}
|
||||
|
||||
#if USE_LIVEUPDATE
|
||||
/* RS may wake up with the wrong endpoint, perfom the update in that case. */
|
||||
|
@ -117,8 +135,9 @@ void sef_startup()
|
|||
#endif
|
||||
|
||||
/* (Re)initialize SEF variables. */
|
||||
sef_self_first_receive_done = FALSE;
|
||||
sef_self_priv_flags = priv_flags;
|
||||
sef_self_init_flags = init_flags;
|
||||
sef_lu_state = SEF_LU_STATE_NULL;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -140,13 +159,19 @@ int sef_receive_status(endpoint_t src, message *m_ptr, int *status_ptr)
|
|||
|
||||
#if INTERCEPT_SEF_LU_REQUESTS
|
||||
/* Handle SEF Live update before receive events. */
|
||||
if(sef_lu_state != SEF_LU_STATE_NULL) {
|
||||
do_sef_lu_before_receive();
|
||||
}
|
||||
|
||||
/* Handle State transfer before receive events. */
|
||||
if(__sef_st_before_receive_enabled) {
|
||||
do_sef_st_before_receive();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Receive and return in case of error. */
|
||||
r = ipc_receive(src, m_ptr, &status);
|
||||
if(status_ptr) *status_ptr = status;
|
||||
if(!sef_self_first_receive_done) sef_self_first_receive_done = TRUE;
|
||||
if(r != OK) {
|
||||
return r;
|
||||
}
|
||||
|
@ -271,6 +296,16 @@ void sef_cancel(void)
|
|||
sef_self_receiving = FALSE;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_getrndseed *
|
||||
*===========================================================================*/
|
||||
int sef_getrndseed(void)
|
||||
{
|
||||
clock_t uptime;
|
||||
sys_times(SELF, NULL, NULL, &uptime, NULL);
|
||||
return (int) uptime;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_exit *
|
||||
*===========================================================================*/
|
||||
|
@ -293,6 +328,24 @@ __weak_alias(_exit, sef_exit);
|
|||
__weak_alias(__exit, sef_exit);
|
||||
#endif
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_munmap *
|
||||
*===========================================================================*/
|
||||
int sef_munmap(void *addrstart, vir_bytes len, int type)
|
||||
{
|
||||
/* System services use a special version of munmap() to control implicit
|
||||
* munmaps as startup and allow for asynchronous mnmap for VM.
|
||||
*/
|
||||
message m;
|
||||
m.m_type = type;
|
||||
m.VMUM_ADDR = addrstart;
|
||||
m.VMUM_LEN = len;
|
||||
if(sef_self_endpoint == VM_PROC_NR) {
|
||||
return asynsend3(SELF, &m, AMF_NOREPLY);
|
||||
}
|
||||
return _syscall(VM_PROC_NR, type, &m);
|
||||
}
|
||||
|
||||
#if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG
|
||||
/*===========================================================================*
|
||||
* sef_debug_refresh_params *
|
||||
|
|
|
@ -27,6 +27,11 @@ EXTERN char* sef_debug_header(void);
|
|||
/* Information about SELF. */
|
||||
EXTERN endpoint_t sef_self_endpoint;
|
||||
EXTERN endpoint_t sef_self_priv_flags;
|
||||
EXTERN endpoint_t sef_self_init_flags;
|
||||
|
||||
#ifndef ST_STACK_REFS_BUFF_SIZE
|
||||
#define ST_STACK_REFS_BUFF_SIZE 1024
|
||||
#endif
|
||||
|
||||
/*===========================================================================*
|
||||
* process_init *
|
||||
|
@ -34,27 +39,64 @@ EXTERN endpoint_t sef_self_priv_flags;
|
|||
static int process_init(int type, sef_init_info_t *info)
|
||||
{
|
||||
/* Process initialization. */
|
||||
int r, result;
|
||||
int r, result, debug_result_found, is_def_cb;
|
||||
cp_grant_id_t gid;
|
||||
message m;
|
||||
|
||||
/* Debug. */
|
||||
#if SEF_INIT_DEBUG
|
||||
sef_init_debug_begin();
|
||||
sef_init_dprint("%s. Got a SEF Init request of type: %d. About to init.\n",
|
||||
sef_debug_header(), type);
|
||||
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",
|
||||
sef_debug_header(), type, info->flags, info->rproctab_gid, info->endpoint, info->old_endpoint, info->restarts);
|
||||
sef_init_debug_end();
|
||||
#endif
|
||||
|
||||
/* Clear any IPC filter. */
|
||||
r = sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
|
||||
assert(r == OK);
|
||||
|
||||
/* Create grant for state transfer. */
|
||||
gid = cpf_grant_direct(sef_self_endpoint, 0, ULONG_MAX, CPF_READ);
|
||||
if(!GRANT_VALID(gid)) {
|
||||
panic("unable to create grant for state transfer");
|
||||
}
|
||||
if(gid != SEF_STATE_TRANSFER_GID) {
|
||||
panic("bad state transfer gid");
|
||||
}
|
||||
|
||||
/* If debug init flags are allowed, process them first. */
|
||||
debug_result_found = 0;
|
||||
if(SEF_INIT_ALLOW_DEBUG_INIT_FLAGS) {
|
||||
int flags = info->flags;
|
||||
if(flags & SEF_INIT_CRASH) {
|
||||
result = sef_cb_init_crash(type, info);
|
||||
debug_result_found = 1;
|
||||
}
|
||||
else if(flags & SEF_INIT_FAIL) {
|
||||
result = sef_cb_init_fail(type, info);
|
||||
debug_result_found = 1;
|
||||
}
|
||||
else if(flags & SEF_INIT_TIMEOUT) {
|
||||
result = sef_cb_init_timeout(type, info);
|
||||
debug_result_found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!debug_result_found) {
|
||||
/* Let the callback code handle the specific initialization type. */
|
||||
is_def_cb = info->flags & SEF_INIT_DEFCB;
|
||||
switch(type) {
|
||||
case SEF_INIT_FRESH:
|
||||
result = sef_init_cbs.sef_cb_init_fresh(type, info);
|
||||
result = is_def_cb ? SEF_CB_INIT_FRESH_DEFAULT(type, info)
|
||||
: sef_init_cbs.sef_cb_init_fresh(type, info);
|
||||
break;
|
||||
case SEF_INIT_LU:
|
||||
result = sef_init_cbs.sef_cb_init_lu(type, info);
|
||||
result = is_def_cb ? SEF_CB_INIT_LU_DEFAULT(type, info)
|
||||
: sef_init_cbs.sef_cb_init_lu(type, info);
|
||||
break;
|
||||
case SEF_INIT_RESTART:
|
||||
result = sef_init_cbs.sef_cb_init_restart(type, info);
|
||||
result = is_def_cb ? SEF_CB_INIT_RESTART_DEFAULT(type, info)
|
||||
: sef_init_cbs.sef_cb_init_restart(type, info);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -62,12 +104,38 @@ static int process_init(int type, sef_init_info_t *info)
|
|||
result = EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.m_source = sef_self_endpoint;
|
||||
m.m_type = RS_INIT;
|
||||
m.m_rs_init.result = result;
|
||||
r = sef_init_cbs.sef_cb_init_response(&m);
|
||||
if (r != OK) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* See if we need to unmap the initialization buffer. */
|
||||
if(info->init_buff_cleanup_start) {
|
||||
void *addrstart = info->init_buff_cleanup_start;
|
||||
size_t len = info->init_buff_len - (size_t)((char*)info->init_buff_cleanup_start - (char*)info->init_buff_start);
|
||||
r = sef_munmap(addrstart, len, VM_MUNMAP);
|
||||
if(r != OK) {
|
||||
printf("process_init: warning: munmap failed for init buffer\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell the kernel about the grant table. */
|
||||
cpf_reload();
|
||||
|
||||
/* Tell the kernel about the senda table. */
|
||||
r = senda_reload();
|
||||
if(r != OK) {
|
||||
printf("process_init: warning: senda_reload failed\n");
|
||||
}
|
||||
|
||||
/* Tell the kernel about the state table. */
|
||||
sys_statectl(SYS_STATE_SET_STATE_TABLE, sef_llvm_state_table_addr(), 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -81,6 +149,7 @@ int do_sef_rs_init(endpoint_t old_endpoint)
|
|||
int r;
|
||||
int type;
|
||||
sef_init_info_t info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
/* Get init parameters from SEF. */
|
||||
type = SEF_INIT_FRESH;
|
||||
|
@ -90,9 +159,23 @@ int do_sef_rs_init(endpoint_t old_endpoint)
|
|||
else if(sef_self_priv_flags & RST_SYS_PROC) {
|
||||
type = SEF_INIT_RESTART;
|
||||
}
|
||||
info.rproctab_gid = -1;
|
||||
info.flags = sef_self_init_flags;
|
||||
info.rproctab_gid = GRANT_INVALID;
|
||||
info.endpoint = sef_self_endpoint;
|
||||
info.old_endpoint = old_endpoint;
|
||||
info.restarts = 0;
|
||||
|
||||
/* Get init buffer details from VM. */
|
||||
info.init_buff_start = NULL;
|
||||
info.init_buff_len = 0;
|
||||
if(type != SEF_INIT_FRESH) {
|
||||
r = vm_memctl(RS_PROC_NR, VM_RS_MEM_GET_PREALLOC_MAP,
|
||||
&info.init_buff_start, &info.init_buff_len);
|
||||
if(r != OK) {
|
||||
printf("do_sef_rs_init: vm_memctl failed\n");
|
||||
}
|
||||
}
|
||||
info.init_buff_cleanup_start = info.init_buff_start;
|
||||
|
||||
/* Peform initialization. */
|
||||
r = process_init(type, &info);
|
||||
|
@ -109,12 +192,18 @@ int do_sef_init_request(message *m_ptr)
|
|||
int r;
|
||||
int type;
|
||||
sef_init_info_t info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
/* Get init parameters from message. */
|
||||
type = m_ptr->m_rs_init.type;
|
||||
info.flags = m_ptr->m_rs_init.flags;
|
||||
info.rproctab_gid = m_ptr->m_rs_init.rproctab_gid;
|
||||
info.endpoint = sef_self_endpoint;
|
||||
info.old_endpoint = m_ptr->m_rs_init.old_endpoint;
|
||||
info.restarts = m_ptr->m_rs_init.restarts;
|
||||
info.init_buff_start = (void*) m_ptr->m_rs_init.buff_addr;
|
||||
info.init_buff_cleanup_start = info.init_buff_start;
|
||||
info.init_buff_len = m_ptr->m_rs_init.buff_len;
|
||||
|
||||
/* Peform initialization. */
|
||||
r = process_init(type, &info);
|
||||
|
@ -202,6 +291,136 @@ int sef_cb_init_crash(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_init_timeout *
|
||||
*===========================================================================*/
|
||||
int sef_cb_init_timeout(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||
{
|
||||
message m;
|
||||
int status;
|
||||
|
||||
printf("Simulating a timeout at initialization time...\n");
|
||||
|
||||
ipc_receive(IDLE, &m, &status);
|
||||
|
||||
return EBADCALL;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_init_identity_state_transfer *
|
||||
*===========================================================================*/
|
||||
int sef_cb_init_identity_state_transfer(int type, sef_init_info_t *info)
|
||||
{
|
||||
extern char *_brksize;
|
||||
extern char *_etext;
|
||||
int r;
|
||||
char *old_brksize, *new_brksize;
|
||||
char stack_buff[ST_STACK_REFS_BUFF_SIZE];
|
||||
vir_bytes data_start;
|
||||
size_t size;
|
||||
|
||||
/* Identity state transfer is for crash recovery and self update only. */
|
||||
if(type != SEF_INIT_RESTART && (type != SEF_INIT_LU || !(info->flags & SEF_LU_SELF))) {
|
||||
printf("sef_cb_init_identity_state_transfer: state transfer failed\n");
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
/* Save stack refs. */
|
||||
sef_llvm_stack_refs_save(stack_buff);
|
||||
|
||||
old_brksize = _brksize;
|
||||
data_start = (vir_bytes)&_etext;
|
||||
#if SEF_ST_DEBUG
|
||||
printf("sef_cb_init_identity_state_transfer: _brksize = 0x%08x, _etext = 0x%08x, data_start = 0x%08x\n",
|
||||
_brksize, &_etext, data_start);
|
||||
#endif
|
||||
|
||||
/* Transfer data. */
|
||||
size = (size_t)(_brksize - data_start);
|
||||
r = sef_copy_state_region(info, data_start, size, data_start);
|
||||
if(r != OK) {
|
||||
printf("sef_cb_init_identity_state_transfer: data transfer failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
new_brksize = _brksize;
|
||||
|
||||
/* Transfer heap if necessary. */
|
||||
if(old_brksize != new_brksize) {
|
||||
|
||||
#if SEF_ST_DEBUG
|
||||
printf("sef_cb_init_identity_state_transfer: brk() for new_brksize = 0x%08x\n",
|
||||
new_brksize);
|
||||
#endif
|
||||
|
||||
/* Extend heap first. */
|
||||
_brksize = old_brksize;
|
||||
r = sef_llvm_real_brk(new_brksize);
|
||||
if(r != OK) {
|
||||
printf("sef_cb_init_identity_state_transfer: brk failed\n");
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
/* Transfer state on the heap. */
|
||||
assert(_brksize == new_brksize);
|
||||
size = (size_t)(_brksize - old_brksize);
|
||||
r = sef_copy_state_region(info, (vir_bytes) old_brksize, size,
|
||||
(vir_bytes) old_brksize);
|
||||
if(r != OK) {
|
||||
printf("sef_cb_init_identity_state_transfer: extended heap transfer failed\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore stack refs. */
|
||||
sef_llvm_stack_refs_restore(stack_buff);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_init_lu_identity_as_restart *
|
||||
*===========================================================================*/
|
||||
int sef_cb_init_lu_identity_as_restart(int type, sef_init_info_t *info)
|
||||
{
|
||||
/* Can only handle live update. */
|
||||
if(type != SEF_INIT_LU) {
|
||||
printf("sef_cb_init_lu_identity_as_restart: init failed\n");
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
/* Resort to restart callback only for identity updates, ignore other cases. */
|
||||
if(SEF_LU_IS_IDENTITY_UPDATE(info->flags)) {
|
||||
if(info->flags & (SEF_INIT_DEFCB|SEF_INIT_SCRIPT_RESTART)) {
|
||||
/* Use default callback when requested or when using a script.*/
|
||||
return SEF_CB_INIT_RESTART_DEFAULT(type, info);
|
||||
}
|
||||
return sef_init_cbs.sef_cb_init_restart(type, info);
|
||||
}
|
||||
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_init_lu_generic *
|
||||
*===========================================================================*/
|
||||
int sef_cb_init_lu_generic(int type, sef_init_info_t *info)
|
||||
{
|
||||
/* Can only handle live update. */
|
||||
if(type != SEF_INIT_LU) {
|
||||
printf("sef_cb_init_lu_generic: init failed\n");
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
/* Resort to restart callback for identity updates. */
|
||||
if(SEF_LU_IS_IDENTITY_UPDATE(info->flags)) {
|
||||
return sef_cb_init_lu_identity_as_restart(type, info);
|
||||
}
|
||||
|
||||
/* Perform state transfer updates in all the other cases. */
|
||||
return sef_st_state_transfer(info);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_init_response_rs_reply *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include "syslib.h"
|
||||
#include <assert.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <minix/rs.h>
|
||||
|
||||
/* SEF Live update variables. */
|
||||
static int sef_lu_state;
|
||||
int sef_lu_state;
|
||||
int __sef_st_before_receive_enabled;
|
||||
char sef_lu_state_eval[SEF_LU_STATE_EVAL_MAX_LEN];
|
||||
static int sef_lu_flags;
|
||||
|
||||
extern __attribute__((weak)) int st_do_state_cleanup(void);
|
||||
|
||||
/* SEF Live update callbacks. */
|
||||
static struct sef_lu_cbs {
|
||||
sef_cb_lu_prepare_t sef_cb_lu_prepare;
|
||||
|
@ -31,6 +32,9 @@ int do_sef_lu_request(message *m_ptr);
|
|||
|
||||
/* SEF Live update helpers. */
|
||||
static void sef_lu_ready(int result);
|
||||
static void sef_lu_state_change(int state, int flags);
|
||||
int sef_lu_handle_state_data(endpoint_t src_e, int state,
|
||||
cp_grant_id_t state_data_gid);
|
||||
|
||||
/* Debug. */
|
||||
EXTERN char* sef_debug_header(void);
|
||||
|
@ -38,7 +42,6 @@ static int sef_lu_debug_cycle = 0;
|
|||
|
||||
/* Information about SELF. */
|
||||
EXTERN endpoint_t sef_self_endpoint;
|
||||
EXTERN int sef_self_first_receive_done;
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sef_lu_before_receive *
|
||||
|
@ -48,15 +51,7 @@ void do_sef_lu_before_receive(void)
|
|||
/* Handle SEF Live update before receive events. */
|
||||
int r;
|
||||
|
||||
/* Initialize on first receive. */
|
||||
if(!sef_self_first_receive_done) {
|
||||
sef_lu_state = SEF_LU_STATE_NULL;
|
||||
}
|
||||
|
||||
/* Nothing to do if we are not preparing for a live update. */
|
||||
if(sef_lu_state == SEF_LU_STATE_NULL) {
|
||||
return;
|
||||
}
|
||||
assert(sef_lu_state != SEF_LU_STATE_NULL);
|
||||
|
||||
/* Debug. */
|
||||
#if SEF_LU_DEBUG
|
||||
|
@ -68,15 +63,29 @@ void do_sef_lu_before_receive(void)
|
|||
sef_lu_debug_end();
|
||||
#endif
|
||||
|
||||
/* Let the callback code handle the event.
|
||||
* For SEF_LU_STATE_WORK_FREE, we're always ready, tell immediately.
|
||||
/* Check the state. For SEF_LU_STATE_WORK_FREE/SEF_LU_STATE_UNREACHABLE,
|
||||
* we are always/never ready. For SEF_LU_STATE_EVAL, evaluate the expression.
|
||||
* For other states, let the callback code handle the event.
|
||||
*/
|
||||
switch(sef_lu_state) {
|
||||
case SEF_LU_STATE_WORK_FREE:
|
||||
r = OK;
|
||||
if(sef_lu_state != SEF_LU_STATE_WORK_FREE) {
|
||||
break;
|
||||
case SEF_LU_STATE_UNREACHABLE:
|
||||
r = sef_cb_lu_prepare_never_ready(sef_lu_state);
|
||||
break;
|
||||
case SEF_LU_STATE_PREPARE_CRASH:
|
||||
r = sef_cb_lu_prepare_crash(sef_lu_state);
|
||||
break;
|
||||
case SEF_LU_STATE_EVAL:
|
||||
r = sef_cb_lu_prepare_eval(sef_lu_state);
|
||||
break;
|
||||
default:
|
||||
r = sef_lu_cbs.sef_cb_lu_prepare(sef_lu_state);
|
||||
break;
|
||||
}
|
||||
if(r == OK) {
|
||||
sef_lu_ready(OK);
|
||||
if(r == OK || r != ENOTREADY) {
|
||||
sef_lu_ready(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,15 +95,25 @@ void do_sef_lu_before_receive(void)
|
|||
int do_sef_lu_request(message *m_ptr)
|
||||
{
|
||||
/* Handle a SEF Live update request. */
|
||||
int state, old_state, flags, is_valid_state;
|
||||
int r, state, flags, is_valid_state;
|
||||
cp_grant_id_t rs_state_data_gid;
|
||||
|
||||
sef_lu_debug_cycle = 0;
|
||||
old_state = sef_lu_state;
|
||||
state = m_ptr->m_rs_update.state;
|
||||
flags = m_ptr->m_rs_update.flags;
|
||||
rs_state_data_gid = m_ptr->m_rs_update.state_data_gid;
|
||||
|
||||
/* Deal with prepare cancel requests first. */
|
||||
is_valid_state = (state == SEF_LU_STATE_NULL);
|
||||
/* Deal with prepare cancel requests first, where no reply is requested. */
|
||||
if(state == SEF_LU_STATE_NULL) {
|
||||
sef_lu_state_change(SEF_LU_STATE_NULL, 0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Check if we are already busy. */
|
||||
if(sef_lu_state != SEF_LU_STATE_NULL) {
|
||||
sef_lu_ready(EBUSY);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Otherwise only accept live update requests with a valid state. */
|
||||
is_valid_state = SEF_LU_ALWAYS_ALLOW_DEBUG_STATES && SEF_LU_STATE_IS_DEBUG(state);
|
||||
|
@ -106,19 +125,20 @@ int do_sef_lu_request(message *m_ptr)
|
|||
else {
|
||||
sef_lu_ready(EINVAL);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
else {
|
||||
/* Set the new live update state. */
|
||||
sef_lu_state = state;
|
||||
|
||||
/* If the live update state changed, let the callback code
|
||||
* handle the rest.
|
||||
*/
|
||||
if(old_state != sef_lu_state) {
|
||||
sef_lu_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
|
||||
}
|
||||
/* Handle additional state data (if any). */
|
||||
r = sef_lu_handle_state_data(m_ptr->m_source, state, rs_state_data_gid);
|
||||
if(r != OK) {
|
||||
sef_lu_ready(r);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Set the new live update state. */
|
||||
sef_lu_state_change(state, flags);
|
||||
|
||||
|
||||
/* Return OK not to let anybody else intercept the request. */
|
||||
return(OK);
|
||||
}
|
||||
|
@ -129,7 +149,7 @@ int do_sef_lu_request(message *m_ptr)
|
|||
static void sef_lu_ready(int result)
|
||||
{
|
||||
message m;
|
||||
int old_state, r=EINVAL;
|
||||
int r=EINVAL;
|
||||
|
||||
#if SEF_LU_DEBUG
|
||||
sef_lu_debug_begin();
|
||||
|
@ -143,10 +163,7 @@ static void sef_lu_ready(int result)
|
|||
* any state that must be carried over to the new version.
|
||||
*/
|
||||
if(result == OK) {
|
||||
/* st_do_state_cleanup is a weak symbol. It is only defined if
|
||||
* we are linked against magic */
|
||||
if (st_do_state_cleanup)
|
||||
r = st_do_state_cleanup();
|
||||
r = sef_llvm_state_cleanup();
|
||||
if(r == OK) {
|
||||
r = sef_lu_cbs.sef_cb_lu_state_save(sef_lu_state, sef_lu_flags);
|
||||
}
|
||||
|
@ -178,13 +195,126 @@ static void sef_lu_ready(int result)
|
|||
/* Something went wrong. Update was aborted and we didn't get updated.
|
||||
* Restore things back to normal and continue executing.
|
||||
*/
|
||||
sef_lu_state_change(SEF_LU_STATE_NULL, 0);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_lu_state_change *
|
||||
*===========================================================================*/
|
||||
static void sef_lu_state_change(int state, int flags)
|
||||
{
|
||||
int r, old_state;
|
||||
|
||||
old_state = sef_lu_state;
|
||||
sef_lu_state = SEF_LU_STATE_NULL;
|
||||
sef_lu_state = state;
|
||||
sef_lu_flags = flags;
|
||||
if(sef_lu_state == SEF_LU_STATE_NULL) {
|
||||
r = sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
|
||||
assert(r == OK);
|
||||
}
|
||||
if(old_state != sef_lu_state) {
|
||||
sef_lu_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_lu_handle_state_data *
|
||||
*===========================================================================*/
|
||||
int sef_lu_handle_state_data(endpoint_t src_e,
|
||||
int state, cp_grant_id_t state_data_gid)
|
||||
{
|
||||
int r;
|
||||
struct rs_state_data rs_state_data;
|
||||
|
||||
if(state_data_gid == GRANT_INVALID) {
|
||||
/* SEF_LU_STATE_EVAL requires an eval expression. */
|
||||
return state == SEF_LU_STATE_EVAL ? EINVAL : OK;
|
||||
}
|
||||
|
||||
r = sys_safecopyfrom(src_e, state_data_gid, 0,
|
||||
(vir_bytes) &rs_state_data, sizeof(rs_state_data));
|
||||
if(r != OK) {
|
||||
return r;
|
||||
}
|
||||
if(rs_state_data.size != sizeof(rs_state_data)) {
|
||||
return E2BIG;
|
||||
}
|
||||
if(state == SEF_LU_STATE_EVAL) {
|
||||
if(rs_state_data.eval_addr && rs_state_data.eval_len) {
|
||||
if(rs_state_data.eval_len >= SEF_LU_STATE_EVAL_MAX_LEN) {
|
||||
return E2BIG;
|
||||
}
|
||||
r = sys_safecopyfrom(src_e, rs_state_data.eval_gid, 0,
|
||||
(vir_bytes) sef_lu_state_eval, rs_state_data.eval_len);
|
||||
if(r != OK) {
|
||||
return r;
|
||||
}
|
||||
sef_lu_state_eval[rs_state_data.eval_len] = '\0';
|
||||
r = sef_cb_lu_prepare_eval(SEF_LU_STATE_EVAL);
|
||||
if(r != OK && r != ENOTREADY) {
|
||||
/* State expression could not be evaluated correctly. */
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* SEF_LU_STATE_EVAL requires a valid eval expression. */
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
if(rs_state_data.ipcf_els && rs_state_data.ipcf_els_size) {
|
||||
ipc_filter_el_t ipc_filter[IPCF_MAX_ELEMENTS];
|
||||
size_t ipc_filter_size = sizeof(ipc_filter);
|
||||
int num_ipc_filters = rs_state_data.ipcf_els_size / ipc_filter_size;
|
||||
int i;
|
||||
if(rs_state_data.ipcf_els_size % ipc_filter_size) {
|
||||
return E2BIG;
|
||||
}
|
||||
r = OK;
|
||||
for(i=0;i<num_ipc_filters;i++) {
|
||||
int num_elements=0;
|
||||
r = sys_safecopyfrom(src_e, rs_state_data.ipcf_els_gid, i*ipc_filter_size,
|
||||
(vir_bytes) ipc_filter, ipc_filter_size);
|
||||
if(r != OK) {
|
||||
break;
|
||||
}
|
||||
#if SEF_LU_DEBUG
|
||||
sef_lu_debug_begin();
|
||||
sef_lu_dprint("%s, Installing ipc filter:\n", sef_debug_header());
|
||||
#endif
|
||||
while(num_elements < IPCF_MAX_ELEMENTS && ipc_filter[num_elements].flags) {
|
||||
#if SEF_LU_DEBUG
|
||||
sef_lu_dprint("el[%d]=(flags=%c%c%c%c, m_source=%d, m_type=%d)",
|
||||
num_elements,
|
||||
(ipc_filter[num_elements].flags & IPCF_MATCH_M_SOURCE) ? 'S' : '-',
|
||||
(ipc_filter[num_elements].flags & IPCF_MATCH_M_TYPE) ? 'T' : '-',
|
||||
(ipc_filter[num_elements].flags & IPCF_EL_BLACKLIST) ? 'B' : '-',
|
||||
(ipc_filter[num_elements].flags & IPCF_EL_WHITELIST) ? 'W' : '-',
|
||||
ipc_filter[num_elements].m_source, ipc_filter[num_elements].m_type);
|
||||
sef_lu_dprint("\n");
|
||||
#endif
|
||||
num_elements++;
|
||||
}
|
||||
#if SEF_LU_DEBUG
|
||||
sef_lu_debug_end();
|
||||
#endif
|
||||
if(num_elements == 0) {
|
||||
r = EINVAL;
|
||||
break;
|
||||
}
|
||||
r = sys_statectl(ipc_filter[0].flags & IPCF_EL_BLACKLIST ? SYS_STATE_ADD_IPC_BL_FILTER : SYS_STATE_ADD_IPC_WL_FILTER,
|
||||
ipc_filter, num_elements*sizeof(ipc_filter_el_t));
|
||||
if(r != OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(r != OK) {
|
||||
sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_setcb_lu_prepare *
|
||||
*===========================================================================*/
|
||||
|
@ -320,6 +450,27 @@ int sef_cb_lu_prepare_crash(int UNUSED(state))
|
|||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_lu_prepare_eval *
|
||||
*===========================================================================*/
|
||||
int sef_cb_lu_prepare_eval(int UNUSED(state))
|
||||
{
|
||||
char result = 0;
|
||||
int ret = sef_llvm_eval_bool(sef_lu_state_eval, &result);
|
||||
|
||||
#if SEF_LU_DEBUG
|
||||
sef_lu_debug_begin();
|
||||
sef_lu_dprint("%s, cycle=%d. Evaluated state expression '%s' with error code %d and result %d\n",
|
||||
sef_debug_header(), sef_lu_debug_cycle, sef_lu_state_eval, ret, result);
|
||||
sef_lu_debug_end();
|
||||
#endif
|
||||
|
||||
if(ret < 0) {
|
||||
return ret == ENOTREADY ? EINTR : ret;
|
||||
}
|
||||
return result ? OK : ENOTREADY;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_lu_state_isvalid_standard *
|
||||
*===========================================================================*/
|
||||
|
@ -352,6 +503,19 @@ int sef_cb_lu_state_isvalid_generic(int state, int flags)
|
|||
return (state == SEF_LU_STATE_EVAL) || sef_cb_lu_state_isvalid_workfree(state, flags);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_lu_state_dump_eval *
|
||||
*===========================================================================*/
|
||||
void sef_cb_lu_state_dump_eval(int state)
|
||||
{
|
||||
if(state == SEF_LU_STATE_EVAL) {
|
||||
sef_llvm_dump_eval(sef_lu_state_eval);
|
||||
}
|
||||
else {
|
||||
return sef_cb_lu_state_dump_null(state);
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_lu_response_rs_reply *
|
||||
*===========================================================================*/
|
||||
|
|
152
minix/lib/libsys/sef_llvm.c
Normal file
152
minix/lib/libsys/sef_llvm.c
Normal file
|
@ -0,0 +1,152 @@
|
|||
#include "syslib.h"
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <minix/sysutil.h>
|
||||
|
||||
/* Stack refs definitions. */
|
||||
extern char **environ;
|
||||
extern char **env_argv;
|
||||
extern int env_argc;
|
||||
|
||||
#define sef_llvm_stack_refs_save_one(P, T, R) { *((T*)P) = R; P += sizeof(T); }
|
||||
#define sef_llvm_stack_refs_restore_one(P, T, R) { R = *((T*)P); P += sizeof(T); }
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_magic_enabled *
|
||||
*===========================================================================*/
|
||||
int sef_llvm_magic_enabled()
|
||||
{
|
||||
extern void __attribute__((weak)) magic_init();
|
||||
if (!magic_init)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_real_brk *
|
||||
*===========================================================================*/
|
||||
int sef_llvm_real_brk(char *newbrk)
|
||||
{
|
||||
extern int __attribute__((weak)) _magic_real_brk(char*);
|
||||
if (!_magic_real_brk)
|
||||
return brk(newbrk);
|
||||
return _magic_real_brk(newbrk);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_state_cleanup *
|
||||
*===========================================================================*/
|
||||
int sef_llvm_state_cleanup()
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_dump_eval *
|
||||
*===========================================================================*/
|
||||
void sef_llvm_dump_eval(char *expr)
|
||||
{
|
||||
extern void __attribute__((weak)) _magic_dump_eval_bool(char*);
|
||||
if (!_magic_dump_eval_bool)
|
||||
return;
|
||||
return _magic_dump_eval_bool(expr);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_eval_bool *
|
||||
*===========================================================================*/
|
||||
int sef_llvm_eval_bool(char *expr, char *result)
|
||||
{
|
||||
extern int __attribute__((weak)) magic_eval_bool(char*, char*);
|
||||
if (!magic_eval_bool)
|
||||
return 0;
|
||||
return magic_eval_bool(expr, result);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_state_table_addr *
|
||||
*===========================================================================*/
|
||||
void *sef_llvm_state_table_addr()
|
||||
{
|
||||
extern void* __attribute__((weak)) _magic_vars_addr(void);
|
||||
if (!_magic_vars_addr)
|
||||
return NULL;
|
||||
return _magic_vars_addr();
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_state_table_size *
|
||||
*===========================================================================*/
|
||||
size_t sef_llvm_state_table_size()
|
||||
{
|
||||
extern size_t __attribute__((weak)) _magic_vars_size(void);
|
||||
if (!_magic_vars_size)
|
||||
return 0;
|
||||
return _magic_vars_size();
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_stack_refs_save *
|
||||
*===========================================================================*/
|
||||
void sef_llvm_stack_refs_save(char *stack_buff)
|
||||
{
|
||||
extern void __attribute__((weak)) st_stack_refs_save_restore(char*, int);
|
||||
char *p = stack_buff;
|
||||
|
||||
sef_llvm_stack_refs_save_one(p, char**, environ);
|
||||
sef_llvm_stack_refs_save_one(p, char**, env_argv);
|
||||
sef_llvm_stack_refs_save_one(p, int, env_argc);
|
||||
|
||||
if (st_stack_refs_save_restore)
|
||||
st_stack_refs_save_restore(p, 1);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_stack_refs_restore *
|
||||
*===========================================================================*/
|
||||
void sef_llvm_stack_refs_restore(char *stack_buff)
|
||||
{
|
||||
extern void __attribute__((weak)) st_stack_refs_save_restore(char*, int);
|
||||
char *p = stack_buff;
|
||||
|
||||
sef_llvm_stack_refs_restore_one(p, char**, environ);
|
||||
sef_llvm_stack_refs_restore_one(p, char**, env_argv);
|
||||
sef_llvm_stack_refs_restore_one(p, int, env_argc);
|
||||
|
||||
if (st_stack_refs_save_restore)
|
||||
st_stack_refs_save_restore(p, 0);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_state_transfer *
|
||||
*===========================================================================*/
|
||||
int sef_llvm_state_transfer(sef_init_info_t *info)
|
||||
{
|
||||
extern int __attribute__((weak)) _magic_state_transfer(sef_init_info_t *info);
|
||||
if (!_magic_state_transfer)
|
||||
return ENOSYS;
|
||||
return _magic_state_transfer(info);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_ltckpt_enabled *
|
||||
*===========================================================================*/
|
||||
int sef_llvm_ltckpt_enabled()
|
||||
{
|
||||
extern int __attribute__((weak)) ltckpt_get_offset();
|
||||
if (!ltckpt_get_offset)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_llvm_ltckpt_get_offset *
|
||||
*===========================================================================*/
|
||||
int sef_llvm_get_ltckpt_offset()
|
||||
{
|
||||
extern int __attribute__((weak)) ltckpt_get_offset();
|
||||
if (!ltckpt_get_offset)
|
||||
return 0;
|
||||
return ltckpt_get_offset();
|
||||
}
|
||||
|
124
minix/lib/libsys/sef_st.c
Normal file
124
minix/lib/libsys/sef_st.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
#include "syslib.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <machine/archtypes.h>
|
||||
#include <minix/timers.h>
|
||||
#include <minix/sysutil.h>
|
||||
|
||||
#include "kernel/config.h"
|
||||
#include "kernel/const.h"
|
||||
#include "kernel/type.h"
|
||||
#include "kernel/proc.h"
|
||||
|
||||
/* SEF Live update prototypes for sef_receive(). */
|
||||
void do_sef_st_before_receive(void);
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sef_st_before_receive *
|
||||
*===========================================================================*/
|
||||
void do_sef_st_before_receive(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_copy_state_region_ctl *
|
||||
*===========================================================================*/
|
||||
int sef_copy_state_region_ctl(sef_init_info_t *info, vir_bytes *src_address, vir_bytes *dst_address) {
|
||||
if(info->copy_flags & SEF_COPY_DEST_OFFSET) {
|
||||
*dst_address += sef_llvm_get_ltckpt_offset();
|
||||
}
|
||||
if(info->copy_flags & SEF_COPY_SRC_OFFSET) {
|
||||
*src_address += sef_llvm_get_ltckpt_offset();
|
||||
}
|
||||
#if STATE_TRANS_DEBUG
|
||||
printf("sef_copy_state_region_ctl. copy_flags:\nSEF_COPY_DEST_OFFSET\t%d\nSEF_COPY_SRC_OFFSET\t%d\nSEF_COPY_NEW_TO_NEW\t%d\nSEF_COPY_OLD_TO_NEW\t%d\n", info->copy_flags & SEF_COPY_DEST_OFFSET ? 1 : 0,
|
||||
info->copy_flags & SEF_COPY_SRC_OFFSET ? 1 : 0, info->copy_flags & SEF_COPY_NEW_TO_NEW ? 1 : 0, info->copy_flags & SEF_COPY_OLD_TO_NEW ? 1 : 0);
|
||||
#endif
|
||||
if(info->copy_flags & SEF_COPY_NEW_TO_NEW)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_copy_state_region *
|
||||
*===========================================================================*/
|
||||
int sef_copy_state_region(sef_init_info_t *info,
|
||||
vir_bytes address, size_t size, vir_bytes dst_address)
|
||||
{
|
||||
int r;
|
||||
if(sef_copy_state_region_ctl(info, &address, &dst_address)) {
|
||||
#if STATE_TRANS_DEBUG
|
||||
printf("sef_copy_state_region: memcpy %d bytes, addr = 0x%08x -> 0x%08x...\n",
|
||||
size, address, dst_address);
|
||||
#endif
|
||||
/* memcpy region from current state */
|
||||
memcpy((void*) dst_address, (void *)address, size);
|
||||
} else {
|
||||
#if STATE_TRANS_DEBUG
|
||||
printf("sef_copy_state_region: copying %d bytes, addr = 0x%08x -> 0x%08x, gid = %d, source = %d...\n",
|
||||
size, address, dst_address, SEF_STATE_TRANSFER_GID, info->old_endpoint);
|
||||
#endif
|
||||
/* Perform a safe copy of a region of the old state. */
|
||||
if((r = sys_safecopyfrom(info->old_endpoint, SEF_STATE_TRANSFER_GID, address,
|
||||
dst_address, size)) != OK) {
|
||||
#if STATE_TRANS_DEBUG
|
||||
printf("sef_copy_state_region: sys_safecopyfrom failed\n");
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_old_state_table_lookup *
|
||||
*===========================================================================*/
|
||||
int sef_old_state_table_lookup(sef_init_info_t *info, void *addr)
|
||||
{
|
||||
struct priv old_priv;
|
||||
int r;
|
||||
|
||||
if ((r = sys_getpriv(&old_priv, info->old_endpoint)) != OK) {
|
||||
printf("ERROR. sys_getpriv() failed.\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
if (sef_copy_state_region(info, old_priv.s_state_table
|
||||
, sef_llvm_state_table_size(), (vir_bytes) addr))
|
||||
{
|
||||
printf("ERROR. state table transfer failed\n");
|
||||
return EGENERIC;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_old_state_table_lookup_opaque *
|
||||
*===========================================================================*/
|
||||
int sef_old_state_table_lookup_opaque(void *info_opaque, void *addr)
|
||||
{
|
||||
assert(info_opaque != NULL && "Invalid info_opaque pointer.");
|
||||
return sef_old_state_table_lookup((sef_init_info_t *)(info_opaque), addr);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_copy_state_region_opaque *
|
||||
*===========================================================================*/
|
||||
int sef_copy_state_region_opaque(void *info_opaque, uint32_t address,
|
||||
size_t size, uint32_t dst_address)
|
||||
{
|
||||
assert(info_opaque != NULL && "Invalid info_opaque pointer.");
|
||||
return sef_copy_state_region((sef_init_info_t *)(info_opaque),
|
||||
(vir_bytes) address, size, (vir_bytes) dst_address);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_st_state_transfer *
|
||||
*===========================================================================*/
|
||||
int sef_st_state_transfer(sef_init_info_t *info)
|
||||
{
|
||||
return sef_llvm_state_transfer(info);
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ int type; /* type of initialization */
|
|||
}
|
||||
|
||||
/* Send initialization message. */
|
||||
memset(&m, 0, sizeof(message));
|
||||
m.m_type = RS_INIT;
|
||||
m.m_rs_init.type = type;
|
||||
m.m_rs_init.rproctab_gid = rinit.rproctab_gid;
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#define _SYSTEM 1
|
||||
|
||||
#define brk _brk /* get rid of no previous prototype warning */
|
||||
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/config.h>
|
||||
|
@ -24,6 +22,7 @@
|
|||
#include <env.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
|
@ -305,7 +304,10 @@ int munmap(void * addr, size_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int brk(void *addr)
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(brk, _brk)
|
||||
#endif
|
||||
int _brk(void *addr)
|
||||
{
|
||||
/* brk is a special case function to allow vm itself to
|
||||
allocate memory in it's own (cacheable) HEAP */
|
||||
|
|
Loading…
Reference in a new issue