RS crash recovery support.
This commit is contained in:
@@ -162,40 +162,87 @@ schedulerstr(struct proc *scheduler)
|
||||
return "KERNEL";
|
||||
}
|
||||
|
||||
PRIVATE void
|
||||
print_proc_name(struct proc *pp)
|
||||
{
|
||||
char *name = pp->p_name;
|
||||
endpoint_t ep = pp->p_endpoint;
|
||||
|
||||
if(name) {
|
||||
printf("%s(%d)", name, ep);
|
||||
}
|
||||
else {
|
||||
printf("%d", ep);
|
||||
}
|
||||
}
|
||||
|
||||
PRIVATE void
|
||||
print_endpoint(endpoint_t ep)
|
||||
{
|
||||
int proc_nr;
|
||||
struct proc *pp = NULL;
|
||||
|
||||
switch(ep) {
|
||||
case ANY:
|
||||
printf("ANY");
|
||||
break;
|
||||
case SELF:
|
||||
printf("SELF");
|
||||
break;
|
||||
case NONE:
|
||||
printf("NONE");
|
||||
break;
|
||||
default:
|
||||
if(!isokendpt(ep, &proc_nr)) {
|
||||
printf("??? %d\n", ep);
|
||||
}
|
||||
else {
|
||||
pp = proc_addr(proc_nr);
|
||||
if(isemptyp(pp)) {
|
||||
printf("??? empty slot %d\n", proc_nr);
|
||||
}
|
||||
else {
|
||||
print_proc_name(pp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PRIVATE void
|
||||
print_sigmgr(struct proc *pp)
|
||||
{
|
||||
endpoint_t sig_mgr, bak_sig_mgr;
|
||||
sig_mgr = priv(pp)->s_sig_mgr;
|
||||
bak_sig_mgr = priv(pp)->s_bak_sig_mgr;
|
||||
printf("sigmgr ");
|
||||
print_endpoint(sig_mgr);
|
||||
if(bak_sig_mgr != NONE) {
|
||||
printf(" / ");
|
||||
print_endpoint(bak_sig_mgr);
|
||||
}
|
||||
}
|
||||
|
||||
PUBLIC void print_proc(struct proc *pp)
|
||||
{
|
||||
struct proc *depproc = NULL;
|
||||
endpoint_t dep;
|
||||
|
||||
printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cr3 0x%lx rts %s misc %s sched %s",
|
||||
printf("%d: %s %d prio %d time %d/%d cycles 0x%x%08x cr3 0x%lx rts %s misc %s sched %s ",
|
||||
proc_nr(pp), pp->p_name, pp->p_endpoint,
|
||||
pp->p_priority, pp->p_user_time,
|
||||
pp->p_sys_time, pp->p_cycles.hi, pp->p_cycles.lo, pp->p_seg.p_cr3,
|
||||
rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
|
||||
schedulerstr(pp->p_scheduler));
|
||||
|
||||
print_sigmgr(pp);
|
||||
|
||||
dep = P_BLOCKEDON(pp);
|
||||
if(dep != NONE) {
|
||||
printf(" blocked on: ");
|
||||
if(dep == ANY) {
|
||||
printf(" ANY\n");
|
||||
} else {
|
||||
int procno;
|
||||
if(!isokendpt(dep, &procno)) {
|
||||
printf(" ??? %d\n", dep);
|
||||
} else {
|
||||
depproc = proc_addr(procno);
|
||||
if(isemptyp(depproc)) {
|
||||
printf(" empty slot %d???\n", procno);
|
||||
depproc = NULL;
|
||||
} else {
|
||||
printf(" %s\n", depproc->p_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("\n");
|
||||
print_endpoint(dep);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
PRIVATE void print_proc_depends(struct proc *pp, const int level)
|
||||
|
||||
@@ -58,6 +58,8 @@ PUBLIC int main(void)
|
||||
sp->s_proc_nr = NONE; /* initialize as free */
|
||||
sp->s_id = (sys_id_t) i; /* priv structure index */
|
||||
ppriv_addr[i] = sp; /* priv ptr from number */
|
||||
sp->s_sig_mgr = NONE; /* clear signal managers */
|
||||
sp->s_bak_sig_mgr = NONE;
|
||||
}
|
||||
|
||||
/* Set up proc table entries for processes in boot image. The stacks of the
|
||||
@@ -116,6 +118,7 @@ PUBLIC int main(void)
|
||||
ipc_to_m = RSYS_M; /* allowed targets */
|
||||
kcalls = RSYS_KC; /* allowed kernel calls */
|
||||
priv(rp)->s_sig_mgr = RSYS_SM; /* signal manager */
|
||||
priv(rp)->s_bak_sig_mgr = NONE; /* backup signal manager */
|
||||
}
|
||||
/* Priviliges for ordinary process. */
|
||||
else {
|
||||
@@ -123,12 +126,7 @@ PUBLIC int main(void)
|
||||
}
|
||||
|
||||
/* Fill in target mask. */
|
||||
for (j=0; j < NR_SYS_PROCS; j++) {
|
||||
if (ipc_to_m & (1 << j))
|
||||
set_sendto_bit(rp, j);
|
||||
else
|
||||
unset_sendto_bit(rp, j);
|
||||
}
|
||||
fill_sendto_mask(rp, ipc_to_m);
|
||||
|
||||
/* Fill in kernel call mask. */
|
||||
for(j = 0; j < SYS_CALL_MASK_SIZE; j++) {
|
||||
|
||||
@@ -44,6 +44,7 @@ struct priv {
|
||||
bitchunk_t s_k_call_mask[SYS_CALL_MASK_SIZE];
|
||||
|
||||
endpoint_t s_sig_mgr; /* signal manager for system signals */
|
||||
endpoint_t s_bak_sig_mgr; /* backup signal manager for system signals */
|
||||
sys_map_t s_notify_pending; /* bit map with pending notifications */
|
||||
irq_id_t s_int_pending; /* pending hardware interrupts */
|
||||
sigset_t s_sig_pending; /* pending signals */
|
||||
@@ -130,7 +131,7 @@ EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */
|
||||
* and there is another runnable process
|
||||
*/
|
||||
#define TSK_F (SYS_PROC) /* other kernel tasks */
|
||||
#define RSYS_F (SYS_PROC | PREEMPTIBLE) /* root system proc */
|
||||
#define RSYS_F (SYS_PROC | PREEMPTIBLE | ROOT_SYS_PROC) /* root sys proc */
|
||||
#define DEF_SYS_F (RSYS_F | DYN_PRIV_ID) /* default sys proc */
|
||||
|
||||
/* allowed traps */
|
||||
@@ -152,7 +153,7 @@ EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */
|
||||
#define DEF_SYS_KC RSYS_KC /* default sys proc */
|
||||
|
||||
/* signal manager */
|
||||
#define RSYS_SM ROOT_SYS_PROC_NR /* root system proc */
|
||||
#define RSYS_SM SELF /* root system proc */
|
||||
#define DEF_SYS_SM ROOT_SYS_PROC_NR /* default sys proc */
|
||||
|
||||
/* scheduler */
|
||||
|
||||
@@ -65,6 +65,7 @@ _PROTOTYPE( char *env_get, (const char *key));
|
||||
_PROTOTYPE( int get_priv, (register struct proc *rc, int proc_type) );
|
||||
_PROTOTYPE( void set_sendto_bit, (const struct proc *rc, int id) );
|
||||
_PROTOTYPE( void unset_sendto_bit, (const struct proc *rc, int id) );
|
||||
_PROTOTYPE( void fill_sendto_mask, (const struct proc *rc, int mask) );
|
||||
_PROTOTYPE( void send_sig, (endpoint_t proc_nr, int sig_nr) );
|
||||
_PROTOTYPE( void cause_sig, (proc_nr_t proc_nr, int sig_nr) );
|
||||
_PROTOTYPE( void sig_delay_done, (struct proc *rp) );
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* get_priv: assign privilege structure to user or system process
|
||||
* set_sendto_bit: allow a process to send messages to a new target
|
||||
* unset_sendto_bit: disallow a process from sending messages to a target
|
||||
* fill_sendto_mask: fill the target mask of a given process
|
||||
* send_sig: send a signal directly to a system process
|
||||
* cause_sig: take action to cause a signal to occur via a signal mgr
|
||||
* sig_delay_done: tell PM that a process is not sending
|
||||
@@ -333,19 +334,35 @@ PUBLIC void unset_sendto_bit(const struct proc *rp, int id)
|
||||
unset_sys_bit(priv_addr(id)->s_ipc_to, priv_id(rp));
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* fill_sendto_mask *
|
||||
*===========================================================================*/
|
||||
PUBLIC void fill_sendto_mask(const struct proc *rp, int mask)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < NR_SYS_PROCS; i++) {
|
||||
if (mask & (1 << i))
|
||||
set_sendto_bit(rp, i);
|
||||
else
|
||||
unset_sendto_bit(rp, i);
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* send_sig *
|
||||
*===========================================================================*/
|
||||
PUBLIC void send_sig(endpoint_t proc_nr, int sig_nr)
|
||||
PUBLIC void send_sig(endpoint_t ep, int sig_nr)
|
||||
{
|
||||
/* Notify a system process about a signal. This is straightforward. Simply
|
||||
* set the signal that is to be delivered in the pending signals map and
|
||||
* send a notification with source SYSTEM.
|
||||
*/
|
||||
register struct proc *rp;
|
||||
int proc_nr;
|
||||
|
||||
if(!isokprocn(proc_nr) || isemptyn(proc_nr))
|
||||
panic("send_sig to empty process: %d", proc_nr);
|
||||
if(!isokendpt(ep, &proc_nr) || isemptyn(proc_nr))
|
||||
panic("send_sig to empty process: %d", ep);
|
||||
|
||||
rp = proc_addr(proc_nr);
|
||||
(void) sigaddset(&priv(rp)->s_sig_pending, sig_nr);
|
||||
@@ -372,19 +389,32 @@ int sig_nr; /* signal to be sent */
|
||||
* only called when a user process causes a CPU exception and from the kernel
|
||||
* process level, which runs to completion.
|
||||
*/
|
||||
register struct proc *rp;
|
||||
register struct proc *rp, *sig_mgr_rp;
|
||||
endpoint_t sig_mgr;
|
||||
int sig_mgr_proc_nr;
|
||||
|
||||
/* Lookup signal manager. */
|
||||
rp = proc_addr(proc_nr);
|
||||
sig_mgr = priv(rp)->s_sig_mgr;
|
||||
if(sig_mgr == SELF) sig_mgr = rp->p_endpoint;
|
||||
|
||||
/* If the target is the signal manager of itself, send the signal directly. */
|
||||
if(rp->p_endpoint == sig_mgr) {
|
||||
if(SIGS_IS_LETHAL(sig_nr)) {
|
||||
/* If the signal is lethal, see if a backup signal manager exists. */
|
||||
sig_mgr = priv(rp)->s_bak_sig_mgr;
|
||||
if(sig_mgr != NONE && isokendpt(sig_mgr, &sig_mgr_proc_nr)) {
|
||||
priv(rp)->s_sig_mgr = sig_mgr;
|
||||
priv(rp)->s_bak_sig_mgr = NONE;
|
||||
sig_mgr_rp = proc_addr(sig_mgr_proc_nr);
|
||||
RTS_UNSET(sig_mgr_rp, RTS_NO_PRIV);
|
||||
cause_sig(proc_nr, sig_nr); /* try again with the new sig mgr. */
|
||||
return;
|
||||
}
|
||||
/* We are out of luck. Time to panic. */
|
||||
proc_stacktrace(rp);
|
||||
panic("cause_sig: signal manager gets lethal signal %d for itself",
|
||||
sig_nr);
|
||||
panic("cause_sig: sig manager %d gets lethal signal %d for itself",
|
||||
rp->p_endpoint, sig_nr);
|
||||
}
|
||||
(void) sigaddset(&priv(rp)->s_sig_pending, sig_nr);
|
||||
send_sig(rp->p_endpoint, SIGKSIGSM);
|
||||
|
||||
@@ -96,6 +96,7 @@ PUBLIC int do_getinfo(struct proc * caller, message * m_ptr)
|
||||
len = MIN(sizeof(m_ptr->GIWHO_NAME), sizeof(caller->p_name))-1;
|
||||
strncpy(m_ptr->GIWHO_NAME, caller->p_name, len);
|
||||
m_ptr->GIWHO_NAME[len] = '\0';
|
||||
m_ptr->GIWHO_PRIVFLAGS = priv(caller)->s_flags;
|
||||
return OK;
|
||||
}
|
||||
case GET_MONPARAMS: {
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
|
||||
#if USE_PRIVCTL
|
||||
|
||||
#define PRIV_DEBUG 0
|
||||
|
||||
FORWARD _PROTOTYPE(int update_priv, (struct proc *rp, struct priv *priv));
|
||||
|
||||
/*===========================================================================*
|
||||
* do_privctl *
|
||||
*===========================================================================*/
|
||||
@@ -107,13 +111,15 @@ PUBLIC int do_privctl(struct proc * caller, message * m_ptr)
|
||||
priv(rp)->s_flags= DEF_SYS_F; /* privilege flags */
|
||||
priv(rp)->s_trap_mask= DEF_SYS_T; /* allowed traps */
|
||||
ipc_to_m = DEF_SYS_M; /* allowed targets */
|
||||
fill_sendto_mask(rp, ipc_to_m);
|
||||
kcalls = DEF_SYS_KC; /* allowed kernel calls */
|
||||
for(i = 0; i < SYS_CALL_MASK_SIZE; i++) {
|
||||
priv(rp)->s_k_call_mask[i] = (kcalls == NO_C ? 0 : (~0));
|
||||
}
|
||||
|
||||
/* Set the default signal manager. */
|
||||
/* Set the default signal managers. */
|
||||
priv(rp)->s_sig_mgr = DEF_SYS_SM;
|
||||
priv(rp)->s_bak_sig_mgr = NONE;
|
||||
|
||||
/* Set defaults for resources: no I/O resources, no memory resources,
|
||||
* no IRQs, no grant table
|
||||
@@ -127,76 +133,9 @@ PUBLIC int do_privctl(struct proc * caller, message * m_ptr)
|
||||
/* Override defaults if the caller has supplied a privilege structure. */
|
||||
if (m_ptr->CTL_ARG_PTR)
|
||||
{
|
||||
/* Copy s_flags and signal manager. */
|
||||
priv(rp)->s_flags = priv.s_flags;
|
||||
priv(rp)->s_sig_mgr = priv.s_sig_mgr;
|
||||
|
||||
/* Copy IRQs */
|
||||
if(priv.s_flags & CHECK_IRQ) {
|
||||
if (priv.s_nr_irq < 0 || priv.s_nr_irq > NR_IRQ)
|
||||
return EINVAL;
|
||||
priv(rp)->s_nr_irq= priv.s_nr_irq;
|
||||
for (i= 0; i<priv.s_nr_irq; i++)
|
||||
{
|
||||
priv(rp)->s_irq_tab[i]= priv.s_irq_tab[i];
|
||||
#if 0
|
||||
printf("do_privctl: adding IRQ %d for %d\n",
|
||||
priv(rp)->s_irq_tab[i], rp->p_endpoint);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy I/O ranges */
|
||||
if(priv.s_flags & CHECK_IO_PORT) {
|
||||
if (priv.s_nr_io_range < 0 || priv.s_nr_io_range > NR_IO_RANGE)
|
||||
return EINVAL;
|
||||
priv(rp)->s_nr_io_range= priv.s_nr_io_range;
|
||||
for (i= 0; i<priv.s_nr_io_range; i++)
|
||||
{
|
||||
priv(rp)->s_io_tab[i]= priv.s_io_tab[i];
|
||||
#if 0
|
||||
printf("do_privctl: adding I/O range [%x..%x] for %d\n",
|
||||
priv(rp)->s_io_tab[i].ior_base,
|
||||
priv(rp)->s_io_tab[i].ior_limit,
|
||||
rp->p_endpoint);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy memory ranges */
|
||||
if(priv.s_flags & CHECK_MEM) {
|
||||
if (priv.s_nr_mem_range < 0 || priv.s_nr_mem_range > NR_MEM_RANGE)
|
||||
return EINVAL;
|
||||
priv(rp)->s_nr_mem_range= priv.s_nr_mem_range;
|
||||
for (i= 0; i<priv.s_nr_mem_range; i++)
|
||||
{
|
||||
priv(rp)->s_mem_tab[i]= priv.s_mem_tab[i];
|
||||
#if 0
|
||||
printf("do_privctl: adding mem range [%x..%x] for %d\n",
|
||||
priv(rp)->s_mem_tab[i].mr_base,
|
||||
priv(rp)->s_mem_tab[i].mr_limit,
|
||||
rp->p_endpoint);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy trap mask. */
|
||||
priv(rp)->s_trap_mask = priv.s_trap_mask;
|
||||
|
||||
/* Copy target mask. */
|
||||
memcpy(&ipc_to_m, &priv.s_ipc_to, sizeof(ipc_to_m));
|
||||
|
||||
/* Copy kernel call mask. */
|
||||
memcpy(priv(rp)->s_k_call_mask, priv.s_k_call_mask,
|
||||
sizeof(priv(rp)->s_k_call_mask));
|
||||
}
|
||||
|
||||
/* Fill in target mask. */
|
||||
for (i=0; i < NR_SYS_PROCS; i++) {
|
||||
if (ipc_to_m & (1 << i))
|
||||
set_sendto_bit(rp, i);
|
||||
else
|
||||
unset_sendto_bit(rp, i);
|
||||
if((r = update_priv(rp, &priv)) != OK) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return(OK);
|
||||
@@ -316,11 +255,105 @@ PUBLIC int do_privctl(struct proc * caller, message * m_ptr)
|
||||
}
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
case SYS_PRIV_UPDATE_SYS:
|
||||
/* Update the privilege structure of a system process. */
|
||||
if(!m_ptr->CTL_ARG_PTR) return EINVAL;
|
||||
|
||||
/* Copy privilege structure from caller */
|
||||
if((r=data_copy(caller->p_endpoint, (vir_bytes) m_ptr->CTL_ARG_PTR,
|
||||
KERNEL, (vir_bytes) &priv, sizeof(priv))) != OK)
|
||||
return r;
|
||||
|
||||
/* Override settings in existing privilege structure. */
|
||||
if((r = update_priv(rp, &priv)) != OK) {
|
||||
return r;
|
||||
}
|
||||
|
||||
return(OK);
|
||||
|
||||
default:
|
||||
printf("do_privctl: bad request %d\n", m_ptr->CTL_REQUEST);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* update_priv *
|
||||
*===========================================================================*/
|
||||
PRIVATE int update_priv(struct proc *rp, struct priv *priv)
|
||||
{
|
||||
/* Update the privilege structure of a given process. */
|
||||
|
||||
int ipc_to_m, i;
|
||||
|
||||
/* Copy s_flags and signal managers. */
|
||||
priv(rp)->s_flags = priv->s_flags;
|
||||
priv(rp)->s_sig_mgr = priv->s_sig_mgr;
|
||||
priv(rp)->s_bak_sig_mgr = priv->s_bak_sig_mgr;
|
||||
|
||||
/* Copy IRQs. */
|
||||
if(priv->s_flags & CHECK_IRQ) {
|
||||
if (priv->s_nr_irq < 0 || priv->s_nr_irq > NR_IRQ)
|
||||
return EINVAL;
|
||||
priv(rp)->s_nr_irq= priv->s_nr_irq;
|
||||
for (i= 0; i<priv->s_nr_irq; i++)
|
||||
{
|
||||
priv(rp)->s_irq_tab[i]= priv->s_irq_tab[i];
|
||||
#if PRIV_DEBUG
|
||||
printf("do_privctl: adding IRQ %d for %d\n",
|
||||
priv(rp)->s_irq_tab[i], rp->p_endpoint);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy I/O ranges. */
|
||||
if(priv->s_flags & CHECK_IO_PORT) {
|
||||
if (priv->s_nr_io_range < 0 || priv->s_nr_io_range > NR_IO_RANGE)
|
||||
return EINVAL;
|
||||
priv(rp)->s_nr_io_range= priv->s_nr_io_range;
|
||||
for (i= 0; i<priv->s_nr_io_range; i++)
|
||||
{
|
||||
priv(rp)->s_io_tab[i]= priv->s_io_tab[i];
|
||||
#if PRIV_DEBUG
|
||||
printf("do_privctl: adding I/O range [%x..%x] for %d\n",
|
||||
priv(rp)->s_io_tab[i].ior_base,
|
||||
priv(rp)->s_io_tab[i].ior_limit,
|
||||
rp->p_endpoint);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy memory ranges. */
|
||||
if(priv->s_flags & CHECK_MEM) {
|
||||
if (priv->s_nr_mem_range < 0 || priv->s_nr_mem_range > NR_MEM_RANGE)
|
||||
return EINVAL;
|
||||
priv(rp)->s_nr_mem_range= priv->s_nr_mem_range;
|
||||
for (i= 0; i<priv->s_nr_mem_range; i++)
|
||||
{
|
||||
priv(rp)->s_mem_tab[i]= priv->s_mem_tab[i];
|
||||
#if PRIV_DEBUG
|
||||
printf("do_privctl: adding mem range [%x..%x] for %d\n",
|
||||
priv(rp)->s_mem_tab[i].mr_base,
|
||||
priv(rp)->s_mem_tab[i].mr_limit,
|
||||
rp->p_endpoint);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy trap mask. */
|
||||
priv(rp)->s_trap_mask = priv->s_trap_mask;
|
||||
|
||||
/* Copy target mask. */
|
||||
memcpy(&ipc_to_m, &priv->s_ipc_to, sizeof(ipc_to_m));
|
||||
fill_sendto_mask(rp, ipc_to_m);
|
||||
|
||||
/* Copy kernel call mask. */
|
||||
memcpy(priv(rp)->s_k_call_mask, priv->s_k_call_mask,
|
||||
sizeof(priv(rp)->s_k_call_mask));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* USE_PRIVCTL */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user