From: Jorrit Herder Date: Thu, 21 Jul 2005 18:36:40 +0000 (+0000) Subject: - Fixed comments in various system call handlers. Work in progress on new X-Git-Tag: v3.1.0~575 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/FAQ?a=commitdiff_plain;h=f0594a9e6d33d043dccb53523dd397dd1efc6c10;p=minix.git - Fixed comments in various system call handlers. Work in progress on new sys_privctl() call to dynamically start servers and drivers. - Shutdown sequence slightly adjusted: called as watchdog timer to let the busy sys_abort() call from the PM return first. - Changed umap_bios() to have more restrictive check: BIOS memory is now allowed in BIOS_MEM_BEGIN to END (interrupt vectors) and BASE_MEM_TOP to UPPER_MEM_END. Hopefully this keeps QEMU and Bochs happy. --- diff --git a/kernel/config.h b/kernel/config.h index eb5676b8e..82d27f936 100644 --- a/kernel/config.h +++ b/kernel/config.h @@ -33,7 +33,7 @@ #define USE_SDEVIO 1 /* perform I/O request on a buffer */ #define USE_IRQCTL 1 /* set an interrupt policy */ #define USE_SEGCTL 1 /* set up a remote segment */ -#define USE_SVRCTL 1 /* system server control */ +#define USE_PRIVCTL 1 /* system privileges control */ #define USE_NICE 1 /* change scheduling priority */ #define USE_UMAP 1 /* map virtual to physical address */ #define USE_VIRCOPY 1 /* copy using virtual addressing */ diff --git a/kernel/main.c b/kernel/main.c index 7f13a77c1..fe35ad6b0 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -76,18 +76,14 @@ PUBLIC void main() for (i=0; i < NR_BOOT_PROCS; ++i) { ip = &image[i]; /* process' attributes */ rp = proc_addr(ip->proc_nr); /* get process pointer */ - (void) init_proc(rp, NIL_SYS_PROC); -#if DEAD_CODE - (ip->flags & SYS_PROC) ? - NIL_SYS_PROC : NIL_PROC); /* initialize new process */ -#endif - strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set name */ rp->p_name[P_NAME_LEN-1] = '\0'; /* just for safety */ rp->p_max_priority = ip->priority; /* max scheduling priority */ rp->p_priority = ip->priority; /* current priority */ rp->p_quantum_size = ip->quantum; /* quantum size in ticks */ rp->p_sched_ticks = ip->quantum; /* current credit */ - rp->p_full_quantums = QUANTUMS(ip->priority); /* quantums left */ + rp->p_full_quantums = QUANTUMS(ip->priority); /* nr quantums left */ + strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */ + (void) set_priv(rp, (ip->flags & SYS_PROC)); /* assign structure */ rp->p_priv->s_flags = ip->flags; /* process flags */ rp->p_priv->s_call_mask = ip->call_mask;/* allowed system calls */ if (i-NR_TASKS < 0) { /* part of the kernel? */ @@ -188,14 +184,16 @@ PRIVATE void announce(void) /*==========================================================================* * prepare_shutdown * *==========================================================================*/ -PUBLIC void prepare_shutdown(how) -int how; /* reason to shut down */ +PUBLIC void prepare_shutdown(tp) +timer_t *tp; { -/* This function prepares to shutdown MINIX. It uses a global flag to make - * sure it is only executed once. Unless a CPU exception occurred, the +/* This function prepares to shutdown MINIX. It is called by a watchdog + * timer if this is a normal abort so that the sys_abort() call can return + * first. The timer structure passes the shutdown status as an argument. */ - static timer_t shutdown_timer; /* timer for watchdog function */ register struct proc *rp; + static timer_t shutdown_timer; + int how = tmr_arg(tp)->ta_int; message m; /* Show debugging dumps on panics. Make sure that the TTY task is still @@ -215,8 +213,9 @@ int how; /* reason to shut down */ * run their shutdown code, e.g, to synchronize the FS or to let the TTY * switch to the first console. */ + kprintf("Sending SIGKSTOP to system processes ...\n"); for (rp=BEG_PROC_ADDR; rps_flags & SYS_PROC) && ! iskernelp(rp)) + if (!isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && !iskernelp(rp)) send_sig(proc_nr(rp), SIGKSTOP); } @@ -224,9 +223,8 @@ int how; /* reason to shut down */ * scheduled by setting a watchog timer that calls shutdown(). The timer * argument passes the shutdown status. */ - kprintf("Informed system about upcoming shutdown with SIGKSTOP signal.\n"); - kprintf("Time for cleanup is allowed. MINIX will now be brought down.\n"); - tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */ + kprintf("MINIX will now be shut down ...\n"); + tmr_arg(&shutdown_timer)->ta_int = how; set_timer(&shutdown_timer, get_uptime() + SHUTDOWN_TICKS, shutdown); } diff --git a/kernel/proc.c b/kernel/proc.c index ca235b4ec..98db457eb 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -308,6 +308,7 @@ unsigned flags; /* system call flags */ return(OK); /* report success */ } +#if TEMP_CODE ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */ while (*ntf_q_pp != NULL) { if (src == ANY || src == (*ntf_q_pp)->n_source) { @@ -328,6 +329,7 @@ unsigned flags; /* system call flags */ ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */ } } +#endif /* Check caller queue. Use pointer pointers to keep code simple. */ xpp = &caller_ptr->p_caller_q; diff --git a/kernel/proc.h b/kernel/proc.h index 250157205..eb30a06ea 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -66,7 +66,6 @@ struct proc { #define SIGNALED 0x10 /* set when new kernel signal arrives */ #define SIG_PENDING 0x20 /* unready while signal being processed */ #define P_STOP 0x40 /* set when process is being traced */ -#define NO_PRIV 0x80 /* privilege structure not yet initialized */ /* Scheduling priorities for p_priority. Values must start at zero (highest * priority) and increment. Priorities of the processes in the boot image can diff --git a/kernel/proto.h b/kernel/proto.h index 74fd12509..6ead2fdd7 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -17,8 +17,7 @@ _PROTOTYPE( void reset_timer, (struct timer *tp) ); /* main.c */ _PROTOTYPE( void main, (void) ); -_PROTOTYPE( void prepare_shutdown, (int how) ); -_PROTOTYPE( void stop_sequence, (struct timer *tp) ); +_PROTOTYPE( void prepare_shutdown, (struct timer *tp) ); /* utility.c */ _PROTOTYPE( void kprintf, (const char *fmt, ...) ); @@ -41,8 +40,7 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds, /* system.c */ _PROTOTYPE( void send_sig, (int proc_nr, int sig_nr) ); _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) ); -_PROTOTYPE( int init_proc, (register struct proc *rc, struct proc *rp) ); -_PROTOTYPE( void clear_proc, (register struct proc *rc) ); +_PROTOTYPE( int set_priv, (register struct proc *rc,int sys_proc_flag) ); _PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr, vir_bytes bytes) ); _PROTOTYPE( void sys_task, (void) ); diff --git a/kernel/system.c b/kernel/system.c index ebd463a44..64237c301 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -11,10 +11,9 @@ * * In addition to the main sys_task() entry point, which starts the main loop, * there are several other minor entry points: - * send_sig: send signal directly to a system process + * set_priv: assign privilege structure to user or system process + * send_sig: send a signal directly to a system process * cause_sig: take action to cause a signal to occur via PM - * init_proc: initialize a process, during start up or fork - * clear_proc: clean up a process in the process table, e.g. on exit * umap_local: map virtual address in LOCAL_SEG to physical * umap_remote: map virtual address in REMOTE_SEG to physical * umap_bios: map virtual address in BIOS_SEG to physical @@ -24,9 +23,7 @@ * generic_handler: interrupt handler for user-level device drivers * * Changes: - * Apr 25, 2005 new init_proc() function (Jorrit N. Herder) * Apr 25, 2005 made mapping of call vector explicit (Jorrit N. Herder) - * Oct 29, 2004 new clear_proc() function (Jorrit N. Herder) * Oct 17, 2004 generic handler and IRQ policies (Jorrit N. Herder) * Oct 10, 2004 dispatch system calls from call vector (Jorrit N. Herder) * Sep 30, 2004 source code documentation updated (Jorrit N. Herder) @@ -40,7 +37,6 @@ #include #include #include -#include #if (CHIP == INTEL) #include #include "protect.h" @@ -127,7 +123,6 @@ PRIVATE void initialize(void) call_vec[i] = do_unused; } - /* Process management. */ map(SYS_FORK, do_fork); /* a process forked a new process */ map(SYS_NEWMAP, do_newmap); /* set up a process memory map */ map(SYS_EXEC, do_exec); /* update process after execute */ @@ -155,8 +150,8 @@ PRIVATE void initialize(void) /* System control. */ map(SYS_ABORT, do_abort); /* abort MINIX */ map(SYS_GETINFO, do_getinfo); /* request system information */ + map(SYS_PRIVCTL, do_privctl); /* system privileges control */ map(SYS_SEGCTL, do_segctl); /* add segment and get selector */ - map(SYS_SVRCTL, do_svrctl); /* kernel control functions */ /* Copying. */ map(SYS_UMAP, do_umap); /* map virtual to physical address */ @@ -169,93 +164,28 @@ PRIVATE void initialize(void) /*===========================================================================* - * init_proc * + * set_priv * *===========================================================================*/ -PUBLIC int init_proc(rc, rp) +PUBLIC int set_priv(rc, proc_type) register struct proc *rc; /* new (child) process pointer */ -struct proc *rp; /* prototype (parent) process */ +int proc_type; /* system or user process flag */ { - register struct priv *sp; /* process' privilege structure */ - int i; - - /* If there is a prototype process to initialize from, use it. Otherwise, - * assume the caller will take care of initialization, but make sure that - * the new process gets a pointer to a system properties structure. - */ - if (rp == NIL_PROC) { /* new user process */ - kprintf("init_proc() for new user proc %d\n", proc_nr(rc)); - sp = &priv[USER_PRIV_ID]; - sp->s_proc_nr = ANY; /* misuse for users */ - rc->p_priv = sp; /* assign to process */ - return(OK); - } else if (rp == NIL_SYS_PROC) { /* new system process */ - for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) { - if (sp->s_proc_nr == NONE) { /* found free slot */ - sp->s_proc_nr = proc_nr(rc); /* set association */ - rc->p_priv = sp; /* assign to process */ - return(OK); - } - } - kprintf("No free PRIV structure!\n", NO_NUM); - return(ENOSPC); /* out of resources */ - } else { /* forked process */ - - kprintf("init_proc() from prototype %d\n", proc_nr(rp)); - } -} - - -/*===========================================================================* - * clear_proc * - *===========================================================================*/ -PUBLIC void clear_proc(rc) -register struct proc *rc; /* slot of process to clean up */ -{ - register struct proc *rp; /* iterate over process table */ - register struct proc **xpp; /* iterate over caller queue */ - int i; - - /* Turn off any alarm timers at the clock. */ - reset_timer(&priv(rc)->s_alarm_timer); - - /* Make sure that the exiting process is no longer scheduled. */ - if (rc->p_rts_flags == 0) lock_unready(rc); - - /* If the process being terminated happens to be queued trying to send a - * message (e.g., the process was killed by a signal, rather than it doing - * a normal exit), then it must be removed from the message queues. - */ - if (rc->p_rts_flags & SENDING) { - /* Check all proc slots to see if the exiting process is queued. */ - for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) { - if (rp->p_caller_q == NIL_PROC) continue; - /* Make sure that the exiting process is not on the queue. */ - xpp = &rp->p_caller_q; - while (*xpp != NIL_PROC) { /* check entire queue */ - if (*xpp == rc) { /* process is on the queue */ - *xpp = (*xpp)->p_q_link; /* replace by next process */ - break; - } - xpp = &(*xpp)->p_q_link; /* proceed to next queued */ - } - } - } - - /* Check the table with IRQ hooks to see if hooks should be released. */ - for (i=0; i < NR_IRQ_HOOKS; i++) { - if (irq_hooks[i].proc_nr == proc_nr(rc)) { - rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */ - irq_hooks[i].proc_nr = NONE; /* mark hook as free */ - } +/* Get a privilege structure. All user processes share the same privilege + * structure. System processes get their own privilege structure. + */ + register struct priv *sp; /* privilege structure */ + + if (proc_type == SYS_PROC) { /* find a new slot */ + for (sp = BEG_PRIV_ADDR; sp < END_PRIV_ADDR; ++sp) + if (sp->s_proc_nr == NONE && sp->s_id != USER_PRIV_ID) break; + if (sp->s_proc_nr != NONE) return(ENOSPC); + rc->p_priv = sp; /* assign new slot */ + rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */ + } else { + rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */ + rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */ } - - /* Now it is safe to release the process table slot. If this is a system - * process, also release its privilege structure. Further cleanup is not - * needed at this point. All important fields are reinitialized when the - * slots are assigned to another, new process. - */ - rc->p_rts_flags = SLOT_FREE; - if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE; + return(OK); } @@ -390,12 +320,12 @@ vir_bytes bytes; /* # of bytes to be copied */ */ /* Check all acceptable ranges. */ -#if DEAD_CODE /* to be replaced by proper ranges, e.g. 640 - 1 KB */ if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= BIOS_MEM_END) return (phys_bytes) vir_addr; - else if (vir_addr >= UPPER_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END) + else if (vir_addr >= BASE_MEM_TOP && vir_addr + bytes <= UPPER_MEM_END) return (phys_bytes) vir_addr; -#else + +#if DEAD_CODE /* brutal fix for QEMU and Bochs, if above doesn't work */ if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END) return (phys_bytes) vir_addr; #endif diff --git a/kernel/system.h b/kernel/system.h index 099e81dfd..116f13e5b 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -82,9 +82,9 @@ _PROTOTYPE( int do_getinfo, (message *m_ptr) ); #define do_getinfo do_unused #endif -_PROTOTYPE( int do_svrctl, (message *m_ptr) ); -#if ! USE_SVRCTL -#define do_svrctl do_unused +_PROTOTYPE( int do_privctl, (message *m_ptr) ); +#if ! USE_PRIVCTL +#define do_privctl do_unused #endif _PROTOTYPE( int do_segctl, (message *m_ptr) ); diff --git a/kernel/system/Makefile b/kernel/system/Makefile index ac5d04984..4ad461921 100644 --- a/kernel/system/Makefile +++ b/kernel/system/Makefile @@ -34,7 +34,7 @@ OBJECTS = \ $(SYSTEM)(do_vcopy.o) \ $(SYSTEM)(do_umap.o) \ $(SYSTEM)(do_memset.o) \ - $(SYSTEM)(do_svrctl.o) \ + $(SYSTEM)(do_privctl.o) \ $(SYSTEM)(do_segctl.o) \ $(SYSTEM)(do_getksig.o) \ $(SYSTEM)(do_endksig.o) \ @@ -129,8 +129,8 @@ $(SYSTEM)(do_getinfo.o): do_getinfo.c $(SYSTEM)(do_abort.o): do_abort.c $(CC) do_abort.c -$(SYSTEM)(do_svrctl.o): do_svrctl.c - $(CC) do_svrctl.c +$(SYSTEM)(do_privctl.o): do_privctl.c + $(CC) do_privctl.c $(SYSTEM)(do_segctl.o): do_segctl.c $(CC) do_segctl.c diff --git a/kernel/system/do_abort.c b/kernel/system/do_abort.c index e34c2efca..0676a0ae5 100644 --- a/kernel/system/do_abort.c +++ b/kernel/system/do_abort.c @@ -24,9 +24,10 @@ message *m_ptr; /* pointer to request message */ * or ESC after debugging dumps). */ int how = m_ptr->ABRT_HOW; + timer_t *tp; + /* See if the monitor is to run the specified instructions. */ if (how == RBT_MONITOR) { - /* The monitor is to run the specified instructions. */ int proc_nr = m_ptr->ABRT_MON_PROC; int length = m_ptr->ABRT_MON_LEN + 1; vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR; @@ -38,7 +39,14 @@ message *m_ptr; /* pointer to request message */ else phys_copy(src_phys, kinfo.params_base, (phys_bytes) length); } - prepare_shutdown(how); + + /* Set a watchdog timer to shut down, so that this call returns first. + * The timer will expire at the next clock tick, which can be any moment. + * The CLOCK task is only scheduled when the SYSTEM task is done, though. + */ + tp = &priv(proc_addr(KERNEL))->s_alarm_timer; + tmr_arg(tp)->ta_int = how; /* pass status as timer argument */ + set_timer(tp, get_uptime(), prepare_shutdown); return(OK); /* pro-forma (really EDISASTER) */ } diff --git a/kernel/system/do_alarm.c b/kernel/system/do_alarm.c index 3f52e2e97..ee2de2d22 100644 --- a/kernel/system/do_alarm.c +++ b/kernel/system/do_alarm.c @@ -2,7 +2,6 @@ * m_type: SYS_SETALARM * * The parameters for this system call are: - * m2_i1: ALRM_PROC_NR (set alarm for this process) * m2_l1: ALRM_EXP_TIME (alarm's expiration time) * m2_i2: ALRM_ABS_TIME (expiration time is absolute?) * m2_l1: ALRM_TIME_LEFT (return seconds left of previous) @@ -31,9 +30,7 @@ message *m_ptr; /* pointer to request message */ clock_t uptime; /* placeholder for current uptime */ /* Extract shared parameters from the request message. */ - proc_nr = m_ptr->ALRM_PROC_NR; /* process to interrupt later */ - if (SELF == proc_nr) proc_nr = m_ptr->m_source; - if (! isokprocn(proc_nr)) return(EINVAL); + proc_nr = m_ptr->m_source; /* process to interrupt later */ exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */ use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */ @@ -50,7 +47,7 @@ message *m_ptr; /* pointer to request message */ m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime); } - /* Finally, (re)set the timer depending on 'exp_time'. */ + /* Finally, (re)set the timer depending on the expiration time. */ if (exp_time == 0) { reset_timer(tp); } else { diff --git a/kernel/system/do_copy.c b/kernel/system/do_copy.c index b2bce2c68..9212329cb 100644 --- a/kernel/system/do_copy.c +++ b/kernel/system/do_copy.c @@ -23,7 +23,8 @@ PUBLIC int do_copy(m_ptr) register message *m_ptr; /* pointer to request message */ { /* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or - * physical addressing. + * physical addressing. Although a single handler function is used, there + * are two different system calls so that permissions can be checked. */ struct vir_addr vir_addr[2]; /* virtual source and destination address */ vir_bytes bytes; /* number of bytes to copy */ diff --git a/kernel/system/do_devio.c b/kernel/system/do_devio.c index 26bf87a7f..03e6103c4 100644 --- a/kernel/system/do_devio.c +++ b/kernel/system/do_devio.c @@ -22,7 +22,7 @@ PUBLIC int do_devio(m_ptr) register message *m_ptr; /* pointer to request message */ { - /* Perform actual device I/O for byte, word, and long values. */ +/* Process a single I/O request for byte, word, and long values. */ if (m_ptr->DIO_REQUEST == DIO_INPUT) { switch (m_ptr->DIO_TYPE) { case DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break; diff --git a/kernel/system/do_exit.c b/kernel/system/do_exit.c index b17091639..3eac7891b 100644 --- a/kernel/system/do_exit.c +++ b/kernel/system/do_exit.c @@ -9,6 +9,8 @@ #if USE_EXIT +FORWARD _PROTOTYPE( void clear_proc, (register struct proc *rc)); + /*===========================================================================* * do_exit * *===========================================================================*/ @@ -37,6 +39,61 @@ message *m_ptr; /* pointer to request message */ clear_proc(proc_addr(m_ptr->m_source)); return(EDONTREPLY); } + + +/*===========================================================================* + * clear_proc * + *===========================================================================*/ +PRIVATE void clear_proc(rc) +register struct proc *rc; /* slot of process to clean up */ +{ + register struct proc *rp; /* iterate over process table */ + register struct proc **xpp; /* iterate over caller queue */ + int i; + + /* Turn off any alarm timers at the clock. */ + reset_timer(&priv(rc)->s_alarm_timer); + + /* Make sure that the exiting process is no longer scheduled. */ + if (rc->p_rts_flags == 0) lock_unready(rc); + + /* If the process being terminated happens to be queued trying to send a + * message (e.g., the process was killed by a signal, rather than it doing + * a normal exit), then it must be removed from the message queues. + */ + if (rc->p_rts_flags & SENDING) { + /* Check all proc slots to see if the exiting process is queued. */ + for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) { + if (rp->p_caller_q == NIL_PROC) continue; + /* Make sure that the exiting process is not on the queue. */ + xpp = &rp->p_caller_q; + while (*xpp != NIL_PROC) { /* check entire queue */ + if (*xpp == rc) { /* process is on the queue */ + *xpp = (*xpp)->p_q_link; /* replace by next process */ + break; + } + xpp = &(*xpp)->p_q_link; /* proceed to next queued */ + } + } + } + + /* Check the table with IRQ hooks to see if hooks should be released. */ + for (i=0; i < NR_IRQ_HOOKS; i++) { + if (irq_hooks[i].proc_nr == proc_nr(rc)) { + rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */ + irq_hooks[i].proc_nr = NONE; /* mark hook as free */ + } + } + + /* Now it is safe to release the process table slot. If this is a system + * process, also release its privilege structure. Further cleanup is not + * needed at this point. All important fields are reinitialized when the + * slots are assigned to another, new process. + */ + rc->p_rts_flags = SLOT_FREE; + if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE; +} + #endif /* USE_EXIT */ diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index baf722ba1..0c77771dc 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -22,7 +22,6 @@ PUBLIC int do_fork(m_ptr) register message *m_ptr; /* pointer to request message */ { /* Handle sys_fork(). PR_PPROC_NR has forked. The child is PR_PROC_NR. */ - #if (CHIP == INTEL) reg_t old_ldt_sel; #endif @@ -43,10 +42,6 @@ register message *m_ptr; /* pointer to request message */ #endif rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */ -#if TEMP_CODE - rpc->p_ntf_q = NULL; /* remove pending notifications */ -#endif - /* Only one in group should have SIGNALED, child doesn't inherit tracing. */ rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */ rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP); diff --git a/kernel/system/do_getinfo.c b/kernel/system/do_getinfo.c index 936ec2f06..90492f39c 100644 --- a/kernel/system/do_getinfo.c +++ b/kernel/system/do_getinfo.c @@ -23,7 +23,9 @@ PUBLIC int do_getinfo(m_ptr) register message *m_ptr; /* pointer to request message */ { -/* Request system information to be copied to caller's address space. */ +/* Request system information to be copied to caller's address space. This + * call simply copies entire data structures to the caller. + */ size_t length; phys_bytes src_phys; phys_bytes dst_phys; @@ -117,7 +119,7 @@ register message *m_ptr; /* pointer to request message */ /* Try to make the actual copy for the requested data. */ if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG); - proc_nr = m_ptr->m_source; /* only caller can request copy */ + proc_nr = m_ptr->m_source; /* only caller can request copy */ dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR, length); if (src_phys == 0 || dst_phys == 0) return(EFAULT); phys_copy(src_phys, dst_phys, length); diff --git a/kernel/system/do_memset.c b/kernel/system/do_memset.c index 65e825dc5..360fdc410 100644 --- a/kernel/system/do_memset.c +++ b/kernel/system/do_memset.c @@ -2,9 +2,9 @@ * m_type: SYS_MEMSET * * The parameters for this system call are: - * m5_l1: CP_SRC_ADDR (virtual address) - * m5_l2: CP_DST_ADDR (returns physical address) - * m5_l3: CP_NR_BYTES (size of datastructure) + * m1_p1: MEM_PTR (virtual address) + * m1_i1: MEM_COUNT (returns physical address) + * m1_i2: MEM_PATTERN (size of datastructure) */ #include "../system.h" @@ -17,9 +17,9 @@ PUBLIC int do_memset(m_ptr) register message *m_ptr; { -/* Handle sys_memset(). */ +/* Handle sys_memset(). This writes a pattern into the specified memory. */ unsigned long p; - unsigned char c = m_ptr->MEM_CHAR; + unsigned char c = m_ptr->MEM_PATTERN; p = c | (c << 8) | (c << 16) | (c << 24); phys_memset((phys_bytes) m_ptr->MEM_PTR, p, (phys_bytes) m_ptr->MEM_COUNT); return(OK); diff --git a/kernel/system/do_sigreturn.c b/kernel/system/do_sigreturn.c index 052b450df..576240cce 100644 --- a/kernel/system/do_sigreturn.c +++ b/kernel/system/do_sigreturn.c @@ -62,7 +62,7 @@ message *m_ptr; /* pointer to request message */ #endif /* Restore the registers. */ - memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs)); + memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct sigregs)); return(OK); } #endif /* USE_SIGRETURN */ diff --git a/kernel/system/do_sigsend.c b/kernel/system/do_sigsend.c index f298b948d..33bd85bad 100644 --- a/kernel/system/do_sigsend.c +++ b/kernel/system/do_sigsend.c @@ -41,7 +41,7 @@ message *m_ptr; /* pointer to request message */ scp = (struct sigcontext *) smsg.sm_stkptr - 1; /* Copy the registers to the sigcontext structure. */ - memcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs)); + memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs)); /* Finish the sigcontext initialization. */ sc.sc_flags = SC_SIGCONTEXT; diff --git a/kernel/system/do_vcopy.c b/kernel/system/do_vcopy.c index 42cef8620..26323afd6 100644 --- a/kernel/system/do_vcopy.c +++ b/kernel/system/do_vcopy.c @@ -25,7 +25,10 @@ PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE]; PUBLIC int do_vcopy(m_ptr) register message *m_ptr; /* pointer to request message */ { -/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */ +/* Handle sys_virvcopy() and sys_physvcopy() that pass a vector with copy + * requests. Although a single handler function is used, there are two + * different system calls so that permissions can be checked. + */ int nr_req; int caller_pid; vir_bytes caller_vir; diff --git a/kernel/system/do_vdevio.c b/kernel/system/do_vdevio.c index e7ecb2549..9c455fcb6 100644 --- a/kernel/system/do_vdevio.c +++ b/kernel/system/do_vdevio.c @@ -13,7 +13,6 @@ #if USE_VDEVIO - /* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */ PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE]; @@ -42,7 +41,7 @@ register message *m_ptr; /* pointer to request message */ pvw_pair_t *pvw_pairs; /* needed for word values */ pvl_pair_t *pvl_pairs; /* needed for long values */ int i; - pid_t caller_pid; /* process id of caller */ + int caller_proc; /* process number of caller */ size_t bytes; /* # bytes to be copied */ vir_bytes caller_vir; /* virtual address at caller */ phys_bytes caller_phys; /* physical address at caller */ @@ -69,9 +68,9 @@ register message *m_ptr; /* pointer to request message */ } /* Calculate physical addresses and copy (port,value)-pairs from user. */ - caller_pid = (pid_t) m_ptr->m_source; + caller_proc = m_ptr->m_source; caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR; - caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes); + caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes); if (0 == caller_phys) return EFAULT; kernel_phys = vir2phys(vdevio_pv_buf); phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes); diff --git a/kernel/table.c b/kernel/table.c index cbd5ed6b4..03b700f08 100755 --- a/kernel/table.c +++ b/kernel/table.c @@ -19,12 +19,12 @@ * or PRIVATE. The reason for this is that extern variables cannot have a * default initialization. If such variables are shared, they must also be * declared in one of the *.h files without the initialization. Examples - * include 'tasktab' (this file) and 'idt'/'gdt' (protect.c). + * include 'system_image' (this file) and 'idt' and 'gdt' (protect.c). * * Changes: * Nov 10, 2004 removed controller->driver mappings (Jorrit N. Herder) * Oct 17, 2004 updated above and tasktab comments (Jorrit N. Herder) - * May 01, 2004 included p_sendmask in tasktab (Jorrit N. Herder) + * May 01, 2004 changed struct for system image (Jorrit N. Herder) */ #define _TABLE @@ -59,22 +59,21 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)]; * mask, and a name for the process table. For kernel processes, the startup * routine and stack size is also provided. */ -#define IDLE_F (PREEMPTIBLE | BILLABLE) -#define USER_F (PREEMPTIBLE | RDY_Q_HEAD) +#define USER_F (PREEMPTIBLE | BILLABLE | RDY_Q_HEAD) #define SYS_F (PREEMPTIBLE | SYS_PROC) -#define TCB_F (SYS_PROC) /* trusted computing base */ +#define TASK_F (SYS_PROC) #define IDLE_T 32 /* ticks */ #define USER_T 8 /* ticks */ #define SYS_T 16 /* ticks */ PUBLIC struct system_image image[] = { - { IDLE, idle_task, IDLE_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_CALL_MASK, 0, "IDLE" }, - { CLOCK, clock_task, TCB_F, SYS_T, TASK_Q, CLOCK_S, SYSTEM_CALL_MASK, 0, "CLOCK" }, - { SYSTEM, sys_task, TCB_F, SYS_T, TASK_Q, SYSTEM_S, SYSTEM_CALL_MASK, 0, "SYS" }, - { HARDWARE, 0, 0, SYS_T, TASK_Q, HARDWARE_S, EMPTY_CALL_MASK, 0,"KERNEL" }, - { PM_PROC_NR, 0, TCB_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "PM" }, - { FS_PROC_NR, 0, TCB_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "FS" }, + { IDLE, idle_task, USER_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_CALL_MASK, 0, "IDLE" }, + { CLOCK, clock_task, TASK_F, SYS_T, TASK_Q, CLOCK_S, SYSTEM_CALL_MASK, 0, "CLOCK" }, + { SYSTEM, sys_task, TASK_F, SYS_T, TASK_Q, SYSTEM_S, SYSTEM_CALL_MASK, 0, "SYS" }, + { HARDWARE, 0, TASK_F, SYS_T, TASK_Q, HARDWARE_S, EMPTY_CALL_MASK, 0,"KERNEL" }, + { PM_PROC_NR, 0, SYS_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "PM" }, + { FS_PROC_NR, 0, SYS_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "FS" }, { IS_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "IS" }, { TTY, 0, SYS_F, SYS_T, 1, 0, SYSTEM_CALL_MASK, 0, "TTY" }, { MEMORY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "MEMORY" }, diff --git a/kernel/utility.c b/kernel/utility.c index f8b827941..ae772784f 100755 --- a/kernel/utility.c +++ b/kernel/utility.c @@ -19,6 +19,7 @@ #include #include #include +#include "proc.h" #define END_OF_KMESS -1 FORWARD _PROTOTYPE(void kputc, (int c)); @@ -33,6 +34,7 @@ int nr; { /* The system has run aground of a fatal kernel error. Terminate execution. */ static int panicking = 0; + timer_t *tp; if (panicking ++) return; /* prevent recursive panics */ if (mess != NULL) { @@ -40,7 +42,13 @@ int nr; if (nr != NO_NUM) kprintf(" %d", nr); kprintf("\n",NO_NUM); } - prepare_shutdown(RBT_PANIC); + + /* Make a direct call to shutdown. Interface requires to pass the shutdown + * status by means of a timer. + */ + tp = &priv(proc_addr(KERNEL))->s_alarm_timer; + tmr_arg(tp)->ta_int = RBT_PANIC; + prepare_shutdown(tp); }