RS crash recovery support.

This commit is contained in:
Cristiano Giuffrida
2010-07-06 22:05:21 +00:00
parent e920c1e1df
commit 1f8dbed029
21 changed files with 429 additions and 200 deletions

View File

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

View File

@@ -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++) {

View File

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

View File

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

View File

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

View File

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

View File

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