sef: Extensions for new RS.

Change-Id: I89b6f8015b1f9c46bf98694450bdaa80b7777940
This commit is contained in:
Cristiano Giuffrida 2014-09-30 07:15:41 +02:00 committed by David van Moolenbroek
parent 006d6e94f9
commit d196e2c333
9 changed files with 836 additions and 66 deletions

View file

@ -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

View file

@ -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>

View file

@ -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. */
do_sef_lu_before_receive();
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 *

View file

@ -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,33 +39,71 @@ 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
/* Let the callback code handle the specific initialization type. */
switch(type) {
case SEF_INIT_FRESH:
result = sef_init_cbs.sef_cb_init_fresh(type, info);
break;
case SEF_INIT_LU:
result = sef_init_cbs.sef_cb_init_lu(type, info);
break;
case SEF_INIT_RESTART:
result = sef_init_cbs.sef_cb_init_restart(type, info);
break;
/* Clear any IPC filter. */
r = sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
assert(r == OK);
default:
/* Not a valid SEF init type. */
result = EINVAL;
break;
/* 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 = 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 = 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 = is_def_cb ? SEF_CB_INIT_RESTART_DEFAULT(type, info)
: sef_init_cbs.sef_cb_init_restart(type, info);
break;
default:
/* Not a valid SEF init type. */
result = EINVAL;
break;
}
}
memset(&m, 0, sizeof(m));
@ -68,6 +111,31 @@ static int process_init(int type, sef_init_info_t *info)
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 *
*===========================================================================*/

View file

@ -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.
*/
r = OK;
if(sef_lu_state != SEF_LU_STATE_WORK_FREE) {
r = sef_lu_cbs.sef_cb_lu_prepare(sef_lu_state);
switch(sef_lu_state) {
case SEF_LU_STATE_WORK_FREE:
r = OK;
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
View 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
View 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);
}

View file

@ -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;

View file

@ -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 */