kernel: Handle IPC properly at live update time.
Change-Id: I2dfc6c6cf4d2bfe198e159d3e4b7c50d0bb499c8
This commit is contained in:
parent
56e56d2af2
commit
062400c0e2
4 changed files with 60 additions and 1 deletions
|
@ -30,6 +30,7 @@ struct priv {
|
||||||
size_t s_asynsize; /* number of elements in table. 0 when not in
|
size_t s_asynsize; /* number of elements in table. 0 when not in
|
||||||
* use
|
* use
|
||||||
*/
|
*/
|
||||||
|
endpoint_t s_asynendpoint; /* the endpoint the asyn table belongs to. */
|
||||||
|
|
||||||
short s_trap_mask; /* allowed system call traps */
|
short s_trap_mask; /* allowed system call traps */
|
||||||
sys_map_t s_ipc_to; /* allowed destination processes */
|
sys_map_t s_ipc_to; /* allowed destination processes */
|
||||||
|
|
|
@ -1153,6 +1153,7 @@ int try_deliver_senda(struct proc *caller_ptr,
|
||||||
/* Clear table */
|
/* Clear table */
|
||||||
privp->s_asyntab = -1;
|
privp->s_asyntab = -1;
|
||||||
privp->s_asynsize = 0;
|
privp->s_asynsize = 0;
|
||||||
|
privp->s_asynendpoint = caller_ptr->p_endpoint;
|
||||||
|
|
||||||
if (size == 0) return(OK); /* Nothing to do, just return */
|
if (size == 0) return(OK); /* Nothing to do, just return */
|
||||||
|
|
||||||
|
@ -1346,6 +1347,7 @@ static int try_one(endpoint_t receive_e, struct proc *src_ptr,
|
||||||
unset_sys_bit(priv(dst_ptr)->s_asyn_pending, privp->s_id);
|
unset_sys_bit(priv(dst_ptr)->s_asyn_pending, privp->s_id);
|
||||||
|
|
||||||
if (size == 0) return(EAGAIN);
|
if (size == 0) return(EAGAIN);
|
||||||
|
if (privp->s_asynendpoint != src_ptr->p_endpoint) return EAGAIN;
|
||||||
if (!may_asynsend_to(src_ptr, proc_nr(dst_ptr))) return (ECALLDENIED);
|
if (!may_asynsend_to(src_ptr, proc_nr(dst_ptr))) return (ECALLDENIED);
|
||||||
|
|
||||||
caller_ptr = src_ptr; /* Needed for A_ macros later on */
|
caller_ptr = src_ptr; /* Needed for A_ macros later on */
|
||||||
|
|
|
@ -126,6 +126,7 @@ int do_privctl(struct proc * caller, message * m_ptr)
|
||||||
reset_kernel_timer(&priv(rp)->s_alarm_timer); /* - alarm */
|
reset_kernel_timer(&priv(rp)->s_alarm_timer); /* - alarm */
|
||||||
priv(rp)->s_asyntab= -1; /* - asynsends */
|
priv(rp)->s_asyntab= -1; /* - asynsends */
|
||||||
priv(rp)->s_asynsize= 0;
|
priv(rp)->s_asynsize= 0;
|
||||||
|
priv(rp)->s_asynendpoint = rp->p_endpoint;
|
||||||
priv(rp)->s_diag_sig = FALSE; /* no request for diag sigs */
|
priv(rp)->s_diag_sig = FALSE; /* no request for diag sigs */
|
||||||
|
|
||||||
/* Set defaults for privilege bitmaps. */
|
/* Set defaults for privilege bitmaps. */
|
||||||
|
|
|
@ -23,9 +23,11 @@
|
||||||
static int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp);
|
static int inherit_priv_irq(struct proc *src_rp, struct proc *dst_rp);
|
||||||
static int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp);
|
static int inherit_priv_io(struct proc *src_rp, struct proc *dst_rp);
|
||||||
static int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp);
|
static int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp);
|
||||||
|
static void abort_proc_ipc_send(struct proc *rp);
|
||||||
static void adjust_proc_slot(struct proc *rp, struct proc *from_rp);
|
static void adjust_proc_slot(struct proc *rp, struct proc *from_rp);
|
||||||
static void adjust_priv_slot(struct priv *privp, struct priv
|
static void adjust_priv_slot(struct priv *privp, struct priv
|
||||||
*from_privp);
|
*from_privp);
|
||||||
|
static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp);
|
||||||
static void swap_proc_slot_pointer(struct proc **rpp, struct proc
|
static void swap_proc_slot_pointer(struct proc **rpp, struct proc
|
||||||
*src_rp, struct proc *dst_rp);
|
*src_rp, struct proc *dst_rp);
|
||||||
|
|
||||||
|
@ -38,7 +40,7 @@ int do_update(struct proc * caller, message * m_ptr)
|
||||||
* slots.
|
* slots.
|
||||||
*/
|
*/
|
||||||
endpoint_t src_e, dst_e;
|
endpoint_t src_e, dst_e;
|
||||||
int src_p, dst_p;
|
int src_p, dst_p, flags;
|
||||||
struct proc *src_rp, *dst_rp;
|
struct proc *src_rp, *dst_rp;
|
||||||
struct priv *src_privp, *dst_privp;
|
struct priv *src_privp, *dst_privp;
|
||||||
struct proc orig_src_proc;
|
struct proc orig_src_proc;
|
||||||
|
@ -48,6 +50,7 @@ int do_update(struct proc * caller, message * m_ptr)
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
/* Lookup slots for source and destination process. */
|
/* Lookup slots for source and destination process. */
|
||||||
|
flags = m_ptr->SYS_UPD_FLAGS;
|
||||||
src_e = m_ptr->SYS_UPD_SRC_ENDPT;
|
src_e = m_ptr->SYS_UPD_SRC_ENDPT;
|
||||||
if(!isokendpt(src_e, &src_p)) {
|
if(!isokendpt(src_e, &src_p)) {
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
@ -112,6 +115,15 @@ int do_update(struct proc * caller, message * m_ptr)
|
||||||
orig_dst_proc = *dst_rp;
|
orig_dst_proc = *dst_rp;
|
||||||
orig_dst_priv = *(priv(dst_rp));
|
orig_dst_priv = *(priv(dst_rp));
|
||||||
|
|
||||||
|
/* Adjust asyn tables. */
|
||||||
|
adjust_asyn_table(priv(src_rp), priv(dst_rp));
|
||||||
|
adjust_asyn_table(priv(dst_rp), priv(src_rp));
|
||||||
|
|
||||||
|
/* Abort any pending send() on rollback. */
|
||||||
|
if(flags & SYS_UPD_ROLLBACK) {
|
||||||
|
abort_proc_ipc_send(src_rp);
|
||||||
|
}
|
||||||
|
|
||||||
/* Swap slots. */
|
/* Swap slots. */
|
||||||
*src_rp = orig_dst_proc;
|
*src_rp = orig_dst_proc;
|
||||||
*src_privp = orig_dst_priv;
|
*src_privp = orig_dst_priv;
|
||||||
|
@ -195,6 +207,27 @@ int inherit_priv_mem(struct proc *src_rp, struct proc *dst_rp)
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* abort_proc_ipc_send *
|
||||||
|
*===========================================================================*/
|
||||||
|
void abort_proc_ipc_send(struct proc *rp)
|
||||||
|
{
|
||||||
|
if(RTS_ISSET(rp, RTS_SENDING)) {
|
||||||
|
struct proc **xpp;
|
||||||
|
RTS_UNSET(rp, RTS_SENDING);
|
||||||
|
rp->p_misc_flags &= ~MF_SENDING_FROM_KERNEL;
|
||||||
|
xpp = &(proc_addr(_ENDPOINT_P(rp->p_sendto_e))->p_caller_q);
|
||||||
|
while (*xpp) {
|
||||||
|
if(*xpp == rp) {
|
||||||
|
*xpp = rp->p_q_link;
|
||||||
|
rp->p_q_link = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xpp = &(*xpp)->p_q_link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* adjust_proc_slot *
|
* adjust_proc_slot *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -205,6 +238,7 @@ static void adjust_proc_slot(struct proc *rp, struct proc *from_rp)
|
||||||
rp->p_nr = from_rp->p_nr;
|
rp->p_nr = from_rp->p_nr;
|
||||||
rp->p_priv = from_rp->p_priv;
|
rp->p_priv = from_rp->p_priv;
|
||||||
priv(rp)->s_proc_nr = from_rp->p_nr;
|
priv(rp)->s_proc_nr = from_rp->p_nr;
|
||||||
|
|
||||||
rp->p_caller_q = from_rp->p_caller_q;
|
rp->p_caller_q = from_rp->p_caller_q;
|
||||||
|
|
||||||
/* preserve scheduling */
|
/* preserve scheduling */
|
||||||
|
@ -216,6 +250,27 @@ static void adjust_proc_slot(struct proc *rp, struct proc *from_rp)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* adjust_asyn_table *
|
||||||
|
*===========================================================================*/
|
||||||
|
static void adjust_asyn_table(struct priv *src_privp, struct priv *dst_privp)
|
||||||
|
{
|
||||||
|
/* Transfer the asyn table if source's table belongs to the destination. */
|
||||||
|
endpoint_t src_e = proc_addr(src_privp->s_proc_nr)->p_endpoint;
|
||||||
|
endpoint_t dst_e = proc_addr(dst_privp->s_proc_nr)->p_endpoint;
|
||||||
|
|
||||||
|
if(src_privp->s_asynsize > 0 && dst_privp->s_asynsize > 0 && src_privp->s_asynendpoint == dst_e) {
|
||||||
|
if(data_copy(src_e, src_privp->s_asyntab, dst_e, dst_privp->s_asyntab,
|
||||||
|
src_privp->s_asynsize*sizeof(asynmsg_t)) != OK) {
|
||||||
|
printf("Warning: unable to transfer asyn table from ep %d to ep %d\n",
|
||||||
|
src_e, dst_e);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dst_privp->s_asynsize = src_privp->s_asynsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* adjust_priv_slot *
|
* adjust_priv_slot *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
Loading…
Reference in a new issue