From: Ben Gras Date: Fri, 3 Mar 2006 10:00:02 +0000 (+0000) Subject: 'proc number' is process slot, 'endpoint' are generation-aware process X-Git-Tag: v3.1.2a~314 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch06.html?a=commitdiff_plain;h=1335d5d7006d4f87e323a3681a92ab500e618da2;p=minix.git 'proc number' is process slot, 'endpoint' are generation-aware process instance numbers, encoded and decoded using macros in . proc number -> endpoint migration . proc_nr in the interrupt hook is now an endpoint, proc_nr_e. . m_source for messages and notifies is now an endpoint, instead of proc number. . isokendpt() converts an endpoint to a process number, returns success (but fails if the process number is out of range, the process slot is not a living process, or the given endpoint number does not match the endpoint number in the process slot, indicating an old process). . okendpt() is the same as isokendpt(), but panic()s if the conversion fails. This is mainly used for decoding message.m_source endpoints, and other endpoint numbers in kernel data structures, which should always be correct. . if DEBUG_ENABLE_IPC_WARNINGS is enabled, isokendpt() and okendpt() get passed the __FILE__ and __LINE__ of the calling lines, and print messages about what is wrong with the endpoint number (out of range proc, empty proc, or inconsistent endpoint number), with the caller, making finding where the conversion failed easy without having to include code for every call to print where things went wrong. Sometimes this is harmless (wrong arg to a kernel call), sometimes it's a fatal internal inconsistency (bogus m_source). . some process table fields have been appended an _e to indicate it's become and endpoint. . process endpoint is stored in p_endpoint, without generation number. it turns out the kernel never needs the generation number, except when fork()ing, so it's decoded then. . kernel calls all take endpoints as arguments, not proc numbers. the one exception is sys_fork(), which needs to know in which slot to put the child. --- diff --git a/kernel/clock.c b/kernel/clock.c index d8dfb0d2c..6417d1921 100755 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -131,7 +131,7 @@ message *m_ptr; /* pointer to request message */ PRIVATE void init_clock() { /* Initialize the CLOCK's interrupt hook. */ - clock_hook.proc_nr = CLOCK; + clock_hook.proc_nr_e = CLOCK; /* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz. */ outb(TIMER_MODE, SQUARE_WAVE); /* set timer to run continuously */ diff --git a/kernel/const.h b/kernel/const.h index e1d040bef..1c5bc88ee 100755 --- a/kernel/const.h +++ b/kernel/const.h @@ -23,6 +23,10 @@ #define structof(type, field, ptr) \ ((type *) (((char *) (ptr)) - offsetof(type, field))) +/* Translate an endpoint number to a process number, return success. */ +#define isokendpt(e,p) isokendpt_d((e),(p),0) +#define okendpt(e,p) isokendpt_d((e),(p),1) + /* Constants used in virtual_copy(). Values must be 0 and 1, respectively. */ #define _SRC_ 0 #define _DST_ 1 diff --git a/kernel/glo.h b/kernel/glo.h index ada3607ed..2b6f270a0 100755 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -46,6 +46,7 @@ EXTERN int irq_use; /* map of all in-use irq's */ EXTERN reg_t mon_ss, mon_sp; /* boot monitor stack */ EXTERN int mon_return; /* true if we can return to monitor */ EXTERN int do_serial_debug; +EXTERN int who_e, who_p; /* message source endpoint and proc */ /* VM */ EXTERN phys_bytes vm_base; diff --git a/kernel/main.c b/kernel/main.c index 8295a7859..275fff8f0 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "proc.h" /* Prototype declarations for PRIVATE functions. */ @@ -51,6 +52,7 @@ PUBLIC void main() for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) { rp->p_rts_flags = SLOT_FREE; /* initialize free slot */ rp->p_nr = i; /* proc number from ptr */ + rp->p_endpoint = _ENDPOINT(0, rp->p_nr); /* generation no. 0 */ (pproc_addr + NR_TASKS)[i] = rp; /* proc ptr from number */ } for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) { @@ -73,6 +75,7 @@ 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 */ + ip->endpoint = rp->p_endpoint; /* ipc endpoint */ 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 */ diff --git a/kernel/proc.c b/kernel/proc.c index 1fa720864..98faab837 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -38,6 +38,8 @@ #include #include +#include +#include "debug.h" #include "kernel.h" #include "proc.h" @@ -45,7 +47,7 @@ * other parts of the kernel through lock_...(). The lock temporarily disables * interrupts to prevent race conditions. */ -FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst, +FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst_e, message *m_ptr, unsigned flags)); FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, int src, message *m_ptr, unsigned flags)); @@ -58,7 +60,7 @@ FORWARD _PROTOTYPE( void sched, (struct proc *rp, int *queue, int *front)); FORWARD _PROTOTYPE( void pick_proc, (void)); #define BuildMess(m_ptr, src, dst_ptr) \ - (m_ptr)->m_source = (src); \ + (m_ptr)->m_source = proc_addr(src)->p_endpoint; \ (m_ptr)->m_type = NOTIFY_FROM(src); \ (m_ptr)->NOTIFY_TIMESTAMP = get_uptime(); \ switch (src) { \ @@ -74,8 +76,9 @@ FORWARD _PROTOTYPE( void pick_proc, (void)); #if (CHIP == INTEL) #define CopyMess(s,sp,sm,dp,dm) \ - cp_mess(s, (sp)->p_memmap[D].mem_phys, \ - (vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm) + cp_mess(proc_addr(s)->p_endpoint, \ + (sp)->p_memmap[D].mem_phys, \ + (vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm) #endif /* (CHIP == INTEL) */ #if (CHIP == M68000) @@ -87,9 +90,9 @@ FORWARD _PROTOTYPE( void pick_proc, (void)); /*===========================================================================* * sys_call * *===========================================================================*/ -PUBLIC int sys_call(call_nr, src_dst, m_ptr) +PUBLIC int sys_call(call_nr, src_dst_e, m_ptr) int call_nr; /* system call number and flags */ -int src_dst; /* src to receive from or dst to send to */ +int src_dst_e; /* src to receive from or dst to send to */ message *m_ptr; /* pointer to message in the caller's space */ { /* System calls are done by trapping to the kernel with an INT instruction. @@ -102,7 +105,19 @@ message *m_ptr; /* pointer to message in the caller's space */ int mask_entry; /* bit to check in send mask */ int group_size; /* used for deadlock check */ int result; /* the system call's result */ + int src_dst; vir_clicks vlo, vhi; /* virtual clicks containing message to send */ + + /* Require a valid source and/ or destination process, unless echoing. */ + if (src_dst_e != ANY && function != ECHO) { + if(!isokendpt(src_dst_e, &src_dst)) { +#if DEBUG_ENABLE_IPC_WARNINGS + kprintf("sys_call: trap %d by %d with bad endpoint %d\n", + function, proc_nr(caller_ptr), src_dst_e); +#endif + return EDEADSRCDST; + } + } else src_dst = src_dst_e; /* Check if the process has privileges for the requested call. Calls to the * kernel may only be SENDREC, because tasks always reply and may not block @@ -110,31 +125,13 @@ message *m_ptr; /* pointer to message in the caller's space */ */ if (! (priv(caller_ptr)->s_trap_mask & (1 << function)) || (iskerneln(src_dst) && function != SENDREC - && function != RECEIVE)) { + && function != RECEIVE)) { #if DEBUG_ENABLE_IPC_WARNINGS kprintf("sys_call: trap %d not allowed, caller %d, src_dst %d\n", function, proc_nr(caller_ptr), src_dst); #endif return(ETRAPDENIED); /* trap denied by mask or kernel */ } - - /* Require a valid source and/ or destination process, unless echoing. */ - if (src_dst != ANY && function != ECHO) { - if (! isokprocn(src_dst)) { -#if DEBUG_ENABLE_IPC_WARNINGS - kprintf("sys_call: invalid src_dst, src_dst %d, caller %d\n", - src_dst, proc_nr(caller_ptr)); -#endif - return(EBADSRCDST); /* invalid process number */ - } - if (isemptyn(src_dst)) { -#if DEBUG_ENABLE_IPC_WARNINGS - kprintf("sys_call: dead src_dst; trap %d, from %d, to %d\n", - function, proc_nr(caller_ptr), src_dst); -#endif - return(EDEADSRCDST); - } - } /* If the call involves a message buffer, i.e., for SEND, RECEIVE, SENDREC, * or ECHO, check the message pointer. This check allows a message to be @@ -193,14 +190,14 @@ message *m_ptr; /* pointer to message in the caller's space */ priv(caller_ptr)->s_flags |= SENDREC_BUSY; /* fall through */ case SEND: - result = mini_send(caller_ptr, src_dst, m_ptr, flags); + result = mini_send(caller_ptr, src_dst_e, m_ptr, flags); if (function == SEND || result != OK) { break; /* done, or SEND failed */ } /* fall through for SENDREC */ case RECEIVE: if (function == RECEIVE) priv(caller_ptr)->s_flags &= ~SENDREC_BUSY; - result = mini_receive(caller_ptr, src_dst, m_ptr, flags); + result = mini_receive(caller_ptr, src_dst_e, m_ptr, flags); break; case NOTIFY: result = mini_notify(caller_ptr, src_dst); @@ -223,7 +220,7 @@ message *m_ptr; /* pointer to message in the caller's space */ PRIVATE int deadlock(function, cp, src_dst) int function; /* trap number */ register struct proc *cp; /* pointer to caller */ -register int src_dst; /* src or dst process */ +int src_dst; /* src or dst process */ { /* Check for deadlock. This can happen if 'caller_ptr' and 'src_dst' have * a cyclic dependency of blocking send and receive calls. The only cyclic @@ -236,6 +233,7 @@ register int src_dst; /* src or dst process */ int trap_flags; while (src_dst != ANY) { /* check while process nr */ + int src_dst_e; xp = proc_addr(src_dst); /* follow chain of processes */ group_size ++; /* extra process in group */ @@ -243,9 +241,10 @@ register int src_dst; /* src or dst process */ * has not, the cycle cannot be closed and we are done. */ if (xp->p_rts_flags & RECEIVING) { /* xp has dependency */ - src_dst = xp->p_getfrom; /* get xp's source */ + if(xp->p_getfrom_e == ANY) src_dst = ANY; + else okendpt(xp->p_getfrom_e, &src_dst); } else if (xp->p_rts_flags & SENDING) { /* xp has dependency */ - src_dst = xp->p_sendto; /* get xp's destination */ + okendpt(xp->p_sendto_e, &src_dst); } else { return(0); /* not a deadlock */ } @@ -270,9 +269,9 @@ register int src_dst; /* src or dst process */ /*===========================================================================* * mini_send * *===========================================================================*/ -PRIVATE int mini_send(caller_ptr, dst, m_ptr, flags) +PRIVATE int mini_send(caller_ptr, dst_e, m_ptr, flags) register struct proc *caller_ptr; /* who is trying to send a message? */ -int dst; /* to whom is message being sent? */ +int dst_e; /* to whom is message being sent? */ message *m_ptr; /* pointer to message buffer */ unsigned flags; /* system call flags */ { @@ -280,14 +279,19 @@ unsigned flags; /* system call flags */ * for this message, copy the message to it and unblock 'dst'. If 'dst' is * not waiting at all, or is waiting for another source, queue 'caller_ptr'. */ - register struct proc *dst_ptr = proc_addr(dst); + register struct proc *dst_ptr; register struct proc **xpp; + int dst_p; + + dst_p = _ENDPOINT_P(dst_e); + dst_ptr = proc_addr(dst_p); /* Check if 'dst' is blocked waiting for this message. The destination's * SENDING flag may be set when its SENDREC call blocked while sending. */ if ( (dst_ptr->p_rts_flags & (RECEIVING | SENDING)) == RECEIVING && - (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) { + (dst_ptr->p_getfrom_e == ANY + || dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) { /* Destination is indeed waiting for this message. */ CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr, dst_ptr->p_messbuf); @@ -297,7 +301,7 @@ unsigned flags; /* system call flags */ caller_ptr->p_messbuf = m_ptr; if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr); caller_ptr->p_rts_flags |= SENDING; - caller_ptr->p_sendto = dst; + caller_ptr->p_sendto_e = dst_e; /* Process is now blocked. Put in on the destination's queue. */ xpp = &dst_ptr->p_caller_q; /* find end of list */ @@ -313,9 +317,9 @@ unsigned flags; /* system call flags */ /*===========================================================================* * mini_receive * *===========================================================================*/ -PRIVATE int mini_receive(caller_ptr, src, m_ptr, flags) +PRIVATE int mini_receive(caller_ptr, src_e, m_ptr, flags) register struct proc *caller_ptr; /* process trying to get message */ -int src; /* which message source is wanted */ +int src_e; /* which message source is wanted */ message *m_ptr; /* pointer to message buffer */ unsigned flags; /* system call flags */ { @@ -329,7 +333,10 @@ unsigned flags; /* system call flags */ int bit_nr; sys_map_t *map; bitchunk_t *chunk; - int i, src_id, src_proc_nr; + int i, src_id, src_proc_nr, src_p; + + if(src_e == ANY) src_p = ANY; + else okendpt(src_e, &src_p); /* Check to see if a message from desired source is already available. * The caller's SENDING flag may be set if SENDREC couldn't send. If it is @@ -354,7 +361,7 @@ unsigned flags; /* system call flags */ kprintf("mini_receive: sending notify from NONE\n"); } #endif - if (src!=ANY && src!=src_proc_nr) continue; /* source not ok */ + if (src_e!=ANY && src_p != src_proc_nr) continue;/* source not ok */ *chunk &= ~(1 << i); /* no longer pending */ /* Found a suitable source, deliver the notification message. */ @@ -367,7 +374,7 @@ unsigned flags; /* system call flags */ /* Check caller queue. Use pointer pointers to keep code simple. */ xpp = &caller_ptr->p_caller_q; while (*xpp != NIL_PROC) { - if (src == ANY || src == proc_nr(*xpp)) { + if (src_e == ANY || src_p == proc_nr(*xpp)) { /* Found acceptable message. Copy it and update status. */ CopyMess((*xpp)->p_nr, *xpp, (*xpp)->p_messbuf, caller_ptr, m_ptr); if (((*xpp)->p_rts_flags &= ~SENDING) == 0) enqueue(*xpp); @@ -382,7 +389,7 @@ unsigned flags; /* system call flags */ * Block the process trying to receive, unless the flags tell otherwise. */ if ( ! (flags & NON_BLOCKING)) { - caller_ptr->p_getfrom = src; + caller_ptr->p_getfrom_e = src_e; caller_ptr->p_messbuf = m_ptr; if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr); caller_ptr->p_rts_flags |= RECEIVING; @@ -408,7 +415,8 @@ int dst; /* which process to notify */ */ if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING && ! (priv(dst_ptr)->s_flags & SENDREC_BUSY) && - (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) { + (dst_ptr->p_getfrom_e == ANY + || dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) { /* Destination is indeed waiting for a message. Assemble a notification * message and deliver it. Copy from pseudo-source HARDWARE, since the @@ -434,9 +442,9 @@ int dst; /* which process to notify */ /*===========================================================================* * lock_notify * *===========================================================================*/ -PUBLIC int lock_notify(src, dst) -int src; /* sender of the notification */ -int dst; /* who is to be notified */ +PUBLIC int lock_notify(src_e, dst_e) +int src_e; /* (endpoint) sender of the notification */ +int dst_e; /* (endpoint) who is to be notified */ { /* Safe gateway to mini_notify() for tasks and interrupt handlers. The sender * is explicitely given to prevent confusion where the call comes from. MINIX @@ -444,7 +452,10 @@ int dst; /* who is to be notified */ * the first kernel entry (hardware interrupt, trap, or exception). Locking * is done by temporarily disabling interrupts. */ - int result; + int result, src, dst; + + if(!isokendpt(src_e, &src) || !isokendpt(dst_e, &dst)) + return EDEADSRCDST; /* Exception or interrupt occurred, thus already locked. */ if (k_reenter >= 0) { @@ -638,14 +649,14 @@ PRIVATE void pick_proc() /*===========================================================================* * lock_send * *===========================================================================*/ -PUBLIC int lock_send(dst, m_ptr) -int dst; /* to whom is message being sent? */ +PUBLIC int lock_send(dst_e, m_ptr) +int dst_e; /* to whom is message being sent? */ message *m_ptr; /* pointer to message buffer */ { /* Safe gateway to mini_send() for tasks. */ int result; lock(2, "send"); - result = mini_send(proc_ptr, dst, m_ptr, NON_BLOCKING); + result = mini_send(proc_ptr, dst_e, m_ptr, NON_BLOCKING); unlock(2); return(result); } @@ -681,3 +692,52 @@ struct proc *rp; /* this process is no longer runnable */ } } +/*===========================================================================* + * isokendpt_f * + *===========================================================================*/ +#if DEBUG_ENABLE_IPC_WARNINGS +PUBLIC int isokendpt_f(file, line, e, p, fatalflag) +char *file; +int line; +#else +PUBLIC int isokendpt_f(e, p, fatalflag) +#endif +int e, *p, fatalflag; +{ + int ok = 0; + /* Convert an endpoint number into a process number. + * Return nonzero if the process is alive with the corresponding + * generation number, zero otherwise. + * + * This function is called with file and line number by the + * isokendpt_d macro if DEBUG_ENABLE_IPC_WARNINGS is defined, + * otherwise without. This allows us to print the where the + * conversion was attempted, making the errors verbose without + * adding code for that at every call. + * + * If fatalflag is nonzero, we must panic if the conversion doesn't + * succeed. + */ + *p = _ENDPOINT_P(e); + if(!isokprocn(*p)) { +#if DEBUG_ENABLE_IPC_WARNINGS + kprintf("kernel:%s:%d: bad endpoint %d: proc %d out of range\n", + file, line, e, *p); +#endif + } else if(isemptyn(*p)) { +#if DEBUG_ENABLE_IPC_WARNINGS + kprintf("kernel:%s:%d: bad endpoint %d: proc %d empty\n", file, line, e, *p); +#endif + } else if(proc_addr(*p)->p_endpoint != e) { +#if DEBUG_ENABLE_IPC_WARNINGS + kprintf("kernel:%s:%d: bad endpoint %d: proc %d has ept %d (generation %d vs. %d)\n", file, line, + e, *p, proc_addr(*p)->p_endpoint, + _ENDPOINT_G(e), _ENDPOINT_G(proc_addr(*p)->p_endpoint)); +#endif + } else ok = 1; + if(!ok && fatalflag) { + panic("invalid endpoint ", e); + } + return ok; +} + diff --git a/kernel/proc.h b/kernel/proc.h index 7f6a32780..2c57e039d 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -46,13 +46,15 @@ struct proc { struct proc *p_caller_q; /* head of list of procs wishing to send */ struct proc *p_q_link; /* link to next proc wishing to send */ message *p_messbuf; /* pointer to passed message buffer */ - proc_nr_t p_getfrom; /* from whom does process want to receive? */ - proc_nr_t p_sendto; /* to whom does process want to send? */ + int p_getfrom_e; /* from whom does process want to receive? */ + int p_sendto_e; /* to whom does process want to send? */ sigset_t p_pending; /* bit map for pending kernel signals */ char p_name[P_NAME_LEN]; /* name of the process, including \0 */ + int p_endpoint; /* endpoint number, generation-aware */ + #if DEBUG_SCHED_CHECK int p_ready, p_found; #endif diff --git a/kernel/proto.h b/kernel/proto.h index 1d69a9519..3bb1f413b 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -29,6 +29,13 @@ _PROTOTYPE( int lock_notify, (int src, int dst) ); _PROTOTYPE( int lock_send, (int dst, message *m_ptr) ); _PROTOTYPE( void lock_enqueue, (struct proc *rp) ); _PROTOTYPE( void lock_dequeue, (struct proc *rp) ); +#if DEBUG_ENABLE_IPC_WARNINGS +_PROTOTYPE( int isokendpt_f, (char *file, int line, int e, int *p, int f)); +#define isokendpt_d(e, p, f) isokendpt_f(__FILE__, __LINE__, (e), (p), (f)) +#else +_PROTOTYPE( int isokendpt_f, (int e, int *p, int f) ); +#define isokendpt_d(e, p, f) isokendpt_f((e), (p), (f)) +#endif /* start.c */ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds, diff --git a/kernel/system.c b/kernel/system.c index 410c40393..399b28309 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -28,12 +28,14 @@ * Sep 30, 2004 source code documentation updated (Jorrit N. Herder) */ +#include "debug.h" #include "kernel.h" #include "system.h" #include #include #include #include +#include #if (CHIP == INTEL) #include #include "protect.h" @@ -72,7 +74,9 @@ PUBLIC void sys_task() /* Get work. Block and wait until a request message arrives. */ receive(ANY, &m); call_nr = (unsigned) m.m_type - KERNEL_CALL; - caller_ptr = proc_addr(m.m_source); + who_e = m.m_source; + okendpt(who_e, &who_p); + caller_ptr = proc_addr(who_p); /* See if the caller made a valid request and try to handle it. */ if (! (priv(caller_ptr)->s_call_mask & (1<s_sig_pending, sig_nr); - lock_notify(SYSTEM, proc_nr); + lock_notify(SYSTEM, rp->p_endpoint); } /*===========================================================================* @@ -420,22 +432,30 @@ vir_bytes bytes; /* # of bytes to copy */ vir_addr[_SRC_] = src_addr; vir_addr[_DST_] = dst_addr; for (i=_SRC_; i<=_DST_; i++) { + int proc_nr, type; + struct proc *p; + + type = vir_addr[i]->segment & SEGMENT_TYPE; + if(type != PHYS_SEG && isokendpt(vir_addr[i]->proc_nr_e, &proc_nr)) + p = proc_addr(proc_nr); + else + p = NULL; /* Get physical address. */ - switch((vir_addr[i]->segment & SEGMENT_TYPE)) { + switch(type) { case LOCAL_SEG: + if(!p) return EDEADSRCDST; seg_index = vir_addr[i]->segment & SEGMENT_INDEX; - phys_addr[i] = umap_local( proc_addr(vir_addr[i]->proc_nr), - seg_index, vir_addr[i]->offset, bytes ); + phys_addr[i] = umap_local(p, seg_index, vir_addr[i]->offset, bytes); break; case REMOTE_SEG: + if(!p) return EDEADSRCDST; seg_index = vir_addr[i]->segment & SEGMENT_INDEX; - phys_addr[i] = umap_remote( proc_addr(vir_addr[i]->proc_nr), - seg_index, vir_addr[i]->offset, bytes ); + phys_addr[i] = umap_remote(p, seg_index, vir_addr[i]->offset, bytes); break; case BIOS_SEG: - phys_addr[i] = umap_bios( proc_addr(vir_addr[i]->proc_nr), - vir_addr[i]->offset, bytes ); + if(!p) return EDEADSRCDST; + phys_addr[i] = umap_bios(p, vir_addr[i]->offset, bytes ); break; case PHYS_SEG: phys_addr[i] = vir_addr[i]->offset; diff --git a/kernel/system.h b/kernel/system.h index 4c884b6d8..78ca0ed7d 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -31,6 +31,7 @@ #define SYSTEM_H /* Common includes for the system library. */ +#include "debug.h" #include "kernel.h" #include "proto.h" #include "proc.h" diff --git a/kernel/system/do_abort.c b/kernel/system/do_abort.c index 9130ac059..d0b32b516 100644 --- a/kernel/system/do_abort.c +++ b/kernel/system/do_abort.c @@ -30,8 +30,7 @@ message *m_ptr; /* pointer to request message */ /* See if the monitor is to run the specified instructions. */ if (how == RBT_MONITOR) { - proc_nr = m_ptr->ABRT_MON_PROC; - if (! isokprocn(proc_nr)) return(EINVAL); + if(!isokendpt(m_ptr->ABRT_MON_ENDPT, &proc_nr)) return(EDEADSRCDST); length = m_ptr->ABRT_MON_LEN + 1; if (length > kinfo.params_size) return(E2BIG); src_phys = numap_local(proc_nr,(vir_bytes)m_ptr->ABRT_MON_ADDR,length); diff --git a/kernel/system/do_copy.c b/kernel/system/do_copy.c index 9c1431835..177cc610e 100644 --- a/kernel/system/do_copy.c +++ b/kernel/system/do_copy.c @@ -31,10 +31,10 @@ register message *m_ptr; /* pointer to request message */ int i; /* Dismember the command message. */ - vir_addr[_SRC_].proc_nr = m_ptr->CP_SRC_PROC_NR; + vir_addr[_SRC_].proc_nr_e = m_ptr->CP_SRC_ENDPT; vir_addr[_SRC_].segment = m_ptr->CP_SRC_SPACE; vir_addr[_SRC_].offset = (vir_bytes) m_ptr->CP_SRC_ADDR; - vir_addr[_DST_].proc_nr = m_ptr->CP_DST_PROC_NR; + vir_addr[_DST_].proc_nr_e = m_ptr->CP_DST_ENDPT; vir_addr[_DST_].segment = m_ptr->CP_DST_SPACE; vir_addr[_DST_].offset = (vir_bytes) m_ptr->CP_DST_ADDR; bytes = (phys_bytes) m_ptr->CP_NR_BYTES; @@ -43,10 +43,12 @@ register message *m_ptr; /* pointer to request message */ * This is done once for _SRC_, then once for _DST_. */ for (i=_SRC_; i<=_DST_; i++) { - + int p; /* Check if process number was given implictly with SELF and is valid. */ - if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source; - if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) + if (vir_addr[i].proc_nr_e == SELF) + vir_addr[i].proc_nr_e = m_ptr->m_source; + if (vir_addr[i].segment != PHYS_SEG && + ! isokendpt(vir_addr[i].proc_nr_e, &p)) return(EINVAL); /* Check if physical addressing is used without SYS_PHYSCOPY. */ diff --git a/kernel/system/do_devio.c b/kernel/system/do_devio.c index a5e48dc93..a1da1a274 100644 --- a/kernel/system/do_devio.c +++ b/kernel/system/do_devio.c @@ -10,6 +10,7 @@ #include "../system.h" #include +#include #if USE_DEVIO @@ -25,7 +26,7 @@ register message *m_ptr; /* pointer to request message */ struct io_range *iorp; int i, size, nr_io_range; - rp= proc_addr(m_ptr->m_source); + rp= proc_addr(who_p); privp= priv(rp); if (!privp) { diff --git a/kernel/system/do_endksig.c b/kernel/system/do_endksig.c index 7e8038649..63d4b20a6 100644 --- a/kernel/system/do_endksig.c +++ b/kernel/system/do_endksig.c @@ -2,7 +2,7 @@ * m_type: SYS_ENDKSIG * * The parameters for this kernel call are: - * m2_i1: SIG_PROC # process for which PM is done + * m2_i1: SIG_ENDPT # process for which PM is done */ #include "../system.h" @@ -22,11 +22,15 @@ message *m_ptr; /* pointer to request message */ * signal it got with SYS_GETKSIG. */ register struct proc *rp; + int proc; /* Get process pointer and verify that it had signals pending. If the * process is already dead its flags will be reset. */ - rp = proc_addr(m_ptr->SIG_PROC); + if(!isokendpt(m_ptr->SIG_ENDPT, &proc)) + return EINVAL; + + rp = proc_addr(proc); if (! (rp->p_rts_flags & SIG_PENDING)) return(EINVAL); /* PM has finished one kernel signal. Perhaps process is ready now? */ diff --git a/kernel/system/do_exec.c b/kernel/system/do_exec.c index 932d42eca..554819856 100644 --- a/kernel/system/do_exec.c +++ b/kernel/system/do_exec.c @@ -2,7 +2,7 @@ * m_type: SYS_EXEC * * The parameters for this kernel call are: - * m1_i1: PR_PROC_NR (process that did exec call) + * m1_i1: PR_ENDPT (process that did exec call) * m1_p1: PR_STACK_PTR (new stack pointer) * m1_p2: PR_NAME_PTR (pointer to program name) * m1_p3: PR_IP_PTR (new instruction pointer) @@ -10,6 +10,7 @@ #include "../system.h" #include #include +#include #if USE_EXEC @@ -24,8 +25,12 @@ register message *m_ptr; /* pointer to request message */ reg_t sp; /* new sp */ phys_bytes phys_name; char *np; + int proc; - rp = proc_addr(m_ptr->PR_PROC_NR); + if(!isokendpt(m_ptr->PR_ENDPT, &proc)) + return EINVAL; + + rp = proc_addr(proc); sp = (reg_t) m_ptr->PR_STACK_PTR; rp->p_reg.sp = sp; /* set the stack pointer */ #if (CHIP == M68000) @@ -42,9 +47,8 @@ register message *m_ptr; /* pointer to request message */ rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */ rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */ if (rp->p_rts_flags == 0) lock_enqueue(rp); - /* Save command name for debugging, ps(1) output, etc. */ - phys_name = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->PR_NAME_PTR, + phys_name = numap_local(who_p, (vir_bytes) m_ptr->PR_NAME_PTR, (vir_bytes) P_NAME_LEN - 1); if (phys_name != 0) { phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1); diff --git a/kernel/system/do_exit.c b/kernel/system/do_exit.c index 783d12c70..ecda123d9 100644 --- a/kernel/system/do_exit.c +++ b/kernel/system/do_exit.c @@ -2,11 +2,13 @@ * m_type: SYS_EXIT * * The parameters for this kernel call are: - * m1_i1: PR_PROC_NR (slot number of exiting process) + * m1_i1: PR_ENDPT (slot number of exiting process) */ #include "../system.h" +#include + #if USE_EXIT FORWARD _PROTOTYPE( void clear_proc, (register struct proc *rc)); @@ -23,20 +25,20 @@ message *m_ptr; /* pointer to request message */ * possibly removes the process from the message queues, and resets certain * process table fields to the default values. */ - int exit_proc_nr; + int exit_e; /* Determine what process exited. User processes are handled here. */ - if (PM_PROC_NR == m_ptr->m_source) { - exit_proc_nr = m_ptr->PR_PROC_NR; /* get exiting process */ - if (exit_proc_nr != SELF) { /* PM tries to exit self */ - if (! isokprocn(exit_proc_nr)) return(EINVAL); - clear_proc(proc_addr(exit_proc_nr)); /* exit a user process */ + if (PM_PROC_NR == who_p) { + if (m_ptr->PR_ENDPT != SELF) { /* PM tries to exit self */ + if(!isokendpt(m_ptr->PR_ENDPT, &exit_e)) /* get exiting process */ + return EINVAL; + clear_proc(proc_addr(exit_e)); /* exit a user process */ return(OK); /* report back to PM */ } } /* The PM or some other system process requested to be exited. */ - clear_proc(proc_addr(m_ptr->m_source)); + clear_proc(proc_addr(who_p)); return(EDONTREPLY); } @@ -61,6 +63,15 @@ register struct proc *rc; /* slot of process to clean up */ /* Make sure that the exiting process is no longer scheduled. */ if (rc->p_rts_flags == 0) lock_dequeue(rc); + /* Check the table with IRQ hooks to see if hooks should be released. */ + for (i=0; i < NR_IRQ_HOOKS; i++) { + int proc; + if (rc->p_endpoint == irq_hooks[i].proc_nr_e) { + rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */ + irq_hooks[i].proc_nr_e = NONE; /* mark hook as free */ + } + } + /* 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 @@ -75,13 +86,15 @@ register struct proc *rc; /* slot of process to clean up */ * a normal exit), then it must be removed from the message queues. */ if (saved_rts_flags & SENDING) { - xpp = &proc[rc->p_sendto].p_caller_q; /* destination's queue */ + int target_proc; + okendpt(rc->p_sendto_e, &target_proc); + xpp = &proc[target_proc].p_caller_q; /* destination's queue */ while (*xpp != NIL_PROC) { /* check entire queue */ if (*xpp == rc) { /* process is on the queue */ *xpp = (*xpp)->p_q_link; /* replace by next process */ #if DEBUG_ENABLE_IPC_WARNINGS kprintf("Proc %d removed from queue at %d\n", - proc_nr(rc), rc->p_sendto); + proc_nr(rc), rc->p_sendto_e); #endif break; /* can only be queued once */ } @@ -101,7 +114,7 @@ register struct proc *rc; /* slot of process to clean up */ unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id); /* Check if process is receiving from exiting process. */ - if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom == proc_nr(rc)) { + if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) { rp->p_reg.retreg = ESRCDIED; /* report source died */ rp->p_rts_flags &= ~RECEIVING; /* no longer receiving */ #if DEBUG_ENABLE_IPC_WARNINGS @@ -109,7 +122,7 @@ register struct proc *rc; /* slot of process to clean up */ #endif if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */ } - if ((rp->p_rts_flags & SENDING) && rp->p_sendto == proc_nr(rc)) { + if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) { rp->p_reg.retreg = EDSTDIED; /* report destination died */ rp->p_rts_flags &= ~SENDING; /* no longer sending */ #if DEBUG_ENABLE_IPC_WARNINGS @@ -119,14 +132,6 @@ register struct proc *rc; /* slot of process to clean up */ } } - /* 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 */ - } - } - /* Clean up virtual memory */ if (rc->p_misc_flags & MF_VM) vm_map_default(rc); diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index ec56cd919..aba2715ac 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -2,8 +2,8 @@ * m_type: SYS_FORK * * The parameters for this kernel call are: - * m1_i1: PR_PROC_NR (child's process table slot) - * m1_i2: PR_PPROC_NR (parent, process that forked) + * m1_i1: PR_SLOT (child's process table slot) + * m1_i2: PR_ENDPT (parent, process that forked) */ #include "../system.h" @@ -12,6 +12,8 @@ #include "../protect.h" #endif +#include + #if USE_FORK /*===========================================================================* @@ -20,19 +22,23 @@ 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. */ +/* Handle sys_fork(). PR_ENDPT has forked. The child is PR_SLOT. */ #if (CHIP == INTEL) reg_t old_ldt_sel; #endif register struct proc *rpc; /* child process pointer */ struct proc *rpp; /* parent process pointer */ - int i; + int i, gen; + int p_proc; - rpp = proc_addr(m_ptr->PR_PPROC_NR); - rpc = proc_addr(m_ptr->PR_PROC_NR); + if(!isokendpt(m_ptr->PR_ENDPT, &p_proc)) + return EINVAL; + rpp = proc_addr(p_proc); + rpc = proc_addr(m_ptr->PR_SLOT); if (isemptyp(rpp) || ! isemptyp(rpc)) return(EINVAL); /* Copy parent 'proc' struct to child. And reinitialize some fields. */ + gen = _ENDPOINT_G(rpc->p_endpoint); #if (CHIP == INTEL) old_ldt_sel = rpc->p_ldt_sel; /* backup local descriptors */ *rpc = *rpp; /* copy 'proc' struct */ @@ -40,7 +46,10 @@ register message *m_ptr; /* pointer to request message */ #else *rpc = *rpp; /* copy 'proc' struct */ #endif - rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */ + if(++gen >= _ENDPOINT_MAX_GENERATION) /* increase generation */ + gen = 1; /* generation number wraparound */ + rpc->p_nr = m_ptr->PR_SLOT; /* this was obliterated by copy */ + rpc->p_endpoint = _ENDPOINT(gen, rpc->p_nr); /* new endpoint of slot */ /* Only one in group should have SIGNALED, child doesn't inherit tracing. */ rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */ @@ -66,6 +75,10 @@ register message *m_ptr; /* pointer to request message */ rpc->p_priv = priv_addr(USER_PRIV_ID); rpc->p_rts_flags |= NO_PRIV; } + + /* Calculate endpoint identifier, so caller knows what it is. */ + m_ptr->PR_ENDPT = rpc->p_endpoint; + return(OK); } diff --git a/kernel/system/do_getinfo.c b/kernel/system/do_getinfo.c index a5791abbf..0017fb4de 100644 --- a/kernel/system/do_getinfo.c +++ b/kernel/system/do_getinfo.c @@ -6,7 +6,7 @@ * m1_p1: I_VAL_PTR (where to put it) * m1_i1: I_VAL_LEN (maximum length expected, optional) * m1_p2: I_VAL_PTR2 (second, optional pointer) - * m1_i2: I_VAL_LEN2 (second length or process nr) + * m1_i2: I_VAL_LEN2_E (second length or process nr) */ #include "../system.h" @@ -28,7 +28,7 @@ register message *m_ptr; /* pointer to request message */ size_t length; phys_bytes src_phys; phys_bytes dst_phys; - int proc_nr, nr; + int proc_nr, nr_e, nr; /* Set source address and length based on request type. */ switch (m_ptr->I_REQUEST) { @@ -64,7 +64,8 @@ register message *m_ptr; /* pointer to request message */ */ length = sizeof(struct proc *) * NR_SCHED_QUEUES; src_phys = vir2phys(rdy_head); - dst_phys = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->I_VAL_PTR2, + okendpt(m_ptr->m_source, &proc_nr); + dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR2, length); if (src_phys == 0 || dst_phys == 0) return(EFAULT); phys_copy(src_phys, dst_phys, length); @@ -81,8 +82,9 @@ register message *m_ptr; /* pointer to request message */ break; } case GET_PROC: { - nr = (m_ptr->I_VAL_LEN2 == SELF) ? m_ptr->m_source : m_ptr->I_VAL_LEN2; - if (! isokprocn(nr)) return(EINVAL); /* validate request */ + nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ? + m_ptr->m_source : m_ptr->I_VAL_LEN2_E; + if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */ length = sizeof(struct proc); src_phys = vir2phys(proc_addr(nr)); break; @@ -123,8 +125,9 @@ register message *m_ptr; /* pointer to request message */ length = sizeof(bios_buf_len); src_phys = vir2phys(&bios_buf_len); - if (length != m_ptr->I_VAL_LEN2) return (EINVAL); - proc_nr = m_ptr->m_source; /* only caller can request copy */ + if (length != m_ptr->I_VAL_LEN2_E) return (EINVAL); + if(!isokendpt(m_ptr->m_source, &proc_nr)) + panic("bogus source", m_ptr->m_source); dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR2, length); if (src_phys == 0 || dst_phys == 0) return(EFAULT); phys_copy(src_phys, dst_phys, length); @@ -145,7 +148,8 @@ 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 */ + if(!isokendpt(m_ptr->m_source, &proc_nr)) + panic("bogus source", m_ptr->m_source); 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_getksig.c b/kernel/system/do_getksig.c index 1910d7df0..95d85a507 100644 --- a/kernel/system/do_getksig.c +++ b/kernel/system/do_getksig.c @@ -2,13 +2,14 @@ * m_type: SYS_GETKSIG * * The parameters for this kernel call are: - * m2_i1: SIG_PROC # process with pending signals + * m2_i1: SIG_ENDPT # process with pending signals * m2_l1: SIG_MAP # bit map with pending signals */ #include "../system.h" #include #include +#include #if USE_GETKSIG @@ -29,7 +30,8 @@ message *m_ptr; /* pointer to request message */ /* Find the next process with pending signals. */ for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) { if (rp->p_rts_flags & SIGNALED) { - m_ptr->SIG_PROC = rp->p_nr; /* store signaled process */ + /* store signaled process' endpoint */ + m_ptr->SIG_ENDPT = rp->p_endpoint; m_ptr->SIG_MAP = rp->p_pending; /* pending signals map */ sigemptyset(&rp->p_pending); /* ball is in PM's court */ rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */ @@ -38,7 +40,7 @@ message *m_ptr; /* pointer to request message */ } /* No process with pending signals was found. */ - m_ptr->SIG_PROC = NONE; + m_ptr->SIG_ENDPT = NONE; return(OK); } #endif /* USE_GETKSIG */ diff --git a/kernel/system/do_int86.c b/kernel/system/do_int86.c index 36df4ecde..f669b7896 100644 --- a/kernel/system/do_int86.c +++ b/kernel/system/do_int86.c @@ -7,6 +7,7 @@ #include "../system.h" #include +#include #include struct reg86u reg86; @@ -17,13 +18,11 @@ struct reg86u reg86; PUBLIC int do_int86(m_ptr) register message *m_ptr; /* pointer to request message */ { - int caller; vir_bytes caller_vir; phys_bytes caller_phys, kernel_phys; - caller = (int) m_ptr->m_source; caller_vir = (vir_bytes) m_ptr->INT86_REG86; - caller_phys = umap_local(proc_addr(caller), D, caller_vir, sizeof(reg86)); + caller_phys = umap_local(proc_addr(who_p), D, caller_vir, sizeof(reg86)); if (0 == caller_phys) return(EFAULT); kernel_phys = vir2phys(®86); phys_copy(caller_phys, kernel_phys, (phys_bytes) sizeof(reg86)); diff --git a/kernel/system/do_iopenable.c b/kernel/system/do_iopenable.c index 71b33caf5..f37a46199 100644 --- a/kernel/system/do_iopenable.c +++ b/kernel/system/do_iopenable.c @@ -2,14 +2,14 @@ * m_type: SYS_IOPENABLE * * The parameters for this system call are: - * m2_i2: PROC_NR (process to give I/O Protection Level bits) + * m2_i2: IO_ENDPT (process to give I/O Protection Level bits) * * Author: * Jorrit N. Herder */ -#include "../kernel.h" #include "../system.h" +#include "../kernel.h" /*===========================================================================* * do_iopenable * @@ -20,9 +20,10 @@ register message *m_ptr; /* pointer to request message */ int proc_nr; #if 1 /* ENABLE_USERPRIV && ENABLE_USERIOPL */ - proc_nr= m_ptr->PROC_NR; - if (proc_nr == SELF) - proc_nr = m_ptr->m_source; + if (m_ptr->IO_ENDPT == SELF) { + proc_nr = who_p; + } else if(!isokendpt(m_ptr->IO_ENDPT, &proc_nr)) + return(EINVAL); enable_iop(proc_addr(proc_nr)); return(OK); #else diff --git a/kernel/system/do_irqctl.c b/kernel/system/do_irqctl.c index ec08aa3d5..260cc4cde 100644 --- a/kernel/system/do_irqctl.c +++ b/kernel/system/do_irqctl.c @@ -11,6 +11,8 @@ #include "../system.h" +#include + #if USE_IRQCTL FORWARD _PROTOTYPE(int generic_handler, (irq_hook_t *hook)); @@ -41,9 +43,9 @@ register message *m_ptr; /* pointer to request message */ /* Enable or disable IRQs. This is straightforward. */ case IRQ_ENABLE: case IRQ_DISABLE: - if (irq_hook_id >= NR_IRQ_HOOKS || - irq_hooks[irq_hook_id].proc_nr == NONE) return(EINVAL); - if (irq_hooks[irq_hook_id].proc_nr != m_ptr->m_source) return(EPERM); + if (irq_hook_id >= NR_IRQ_HOOKS || irq_hook_id < 0 || + irq_hooks[irq_hook_id].proc_nr_e == NONE) return(EINVAL); + if (irq_hooks[irq_hook_id].proc_nr_e != m_ptr->m_source) return(EPERM); if (m_ptr->IRQ_REQUEST == IRQ_ENABLE) enable_irq(&irq_hooks[irq_hook_id]); else @@ -58,7 +60,7 @@ register message *m_ptr; /* pointer to request message */ /* Check if IRQ line is acceptable. */ if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) return(EINVAL); - rp= proc_addr(m_ptr->m_source); + rp= proc_addr(who_p); privp= priv(rp); if (!privp) { @@ -84,7 +86,7 @@ register message *m_ptr; /* pointer to request message */ /* Find a free IRQ hook for this mapping. */ hook_ptr = NULL; for (irq_hook_id=0; irq_hook_id CHAR_BIT * sizeof(irq_id_t) - 1) return(EINVAL); /* Install the handler. */ - hook_ptr->proc_nr = m_ptr->m_source; /* process to notify */ + hook_ptr->proc_nr_e = m_ptr->m_source; /* process to notify */ hook_ptr->notify_id = notify_id; /* identifier to pass */ hook_ptr->policy = m_ptr->IRQ_POLICY; /* policy for interrupts */ put_irq_handler(hook_ptr, irq_vec, generic_handler); @@ -108,10 +110,10 @@ register message *m_ptr; /* pointer to request message */ break; case IRQ_RMPOLICY: - if (irq_hook_id >= NR_IRQ_HOOKS || - irq_hooks[irq_hook_id].proc_nr == NONE) { + if (irq_hook_id < 0 || irq_hook_id >= NR_IRQ_HOOKS || + irq_hooks[irq_hook_id].proc_nr_e == NONE) { return(EINVAL); - } else if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) { + } else if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr_e) { return(EPERM); } /* Remove the handler and return. */ @@ -134,20 +136,30 @@ irq_hook_t *hook; * interrupts are transformed into messages to a driver. The IRQ line will be * reenabled if the policy says so. */ + int proc; /* As a side-effect, the interrupt handler gathers random information by * timestamping the interrupt events. This is used for /dev/random. */ get_randomness(hook->irq); + /* Check if the handler is still alive. If not, forget about the + * interrupt. This should never happen, as processes that die + * automatically get their interrupt hooks unhooked. + */ + if(!isokendpt(hook->proc_nr_e, &proc)) { + hook->proc_nr_e = NONE; + return 0; + } + /* Add a bit for this interrupt to the process' pending interrupts. When * sending the notification message, this bit map will be magically set * as an argument. */ - priv(proc_addr(hook->proc_nr))->s_int_pending |= (1 << hook->notify_id); + priv(proc_addr(proc))->s_int_pending |= (1 << hook->notify_id); /* Build notification message and return. */ - lock_notify(HARDWARE, hook->proc_nr); + lock_notify(HARDWARE, hook->proc_nr_e); return(hook->policy & IRQ_REENABLE); } diff --git a/kernel/system/do_kill.c b/kernel/system/do_kill.c index 9b87a1fe7..1c6f99c32 100644 --- a/kernel/system/do_kill.c +++ b/kernel/system/do_kill.c @@ -2,7 +2,7 @@ * m_type: SYS_KILL * * The parameters for this kernel call are: - * m2_i1: SIG_PROC # process to signal/ pending + * m2_i1: SIG_ENDPT # process to signal/ pending * m2_i2: SIG_NUMBER # signal number to send to process */ @@ -26,10 +26,11 @@ message *m_ptr; /* pointer to request message */ * are usually blocked on a RECEIVE), they can request the PM to transform * signals into messages. This is done by the PM with a call to sys_kill(). */ - proc_nr_t proc_nr = m_ptr->SIG_PROC; + proc_nr_t proc_nr; int sig_nr = m_ptr->SIG_NUMBER; - if (! isokprocn(proc_nr) || sig_nr > _NSIG) return(EINVAL); + if (!isokendpt(m_ptr->SIG_ENDPT, &proc_nr)) return(EINVAL); + if (sig_nr > _NSIG) return(EINVAL); if (iskerneln(proc_nr)) return(EPERM); if (m_ptr->m_source == PM_PROC_NR) { diff --git a/kernel/system/do_newmap.c b/kernel/system/do_newmap.c index f99f65dec..1da7b80ca 100644 --- a/kernel/system/do_newmap.c +++ b/kernel/system/do_newmap.c @@ -2,10 +2,11 @@ * m_type: SYS_NEWMAP * * The parameters for this kernel call are: - * m1_i1: PR_PROC_NR (install new map for this process) + * m1_i1: PR_ENDPT (install new map for this process) * m1_p1: PR_MEM_PTR (pointer to the new memory map) */ #include "../system.h" +#include #if USE_NEWMAP @@ -17,20 +18,18 @@ message *m_ptr; /* pointer to request message */ { /* Handle sys_newmap(). Fetch the memory map from PM. */ register struct proc *rp; /* process whose map is to be loaded */ - int caller; /* whose space has the new map (usually PM) */ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ phys_bytes src_phys; /* physical address of map at the PM */ int old_flags; /* value of flags before modification */ + int proc; - /* Extract message parameters and copy new memory map from PM. */ - caller = m_ptr->m_source; map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR; - if (! isokprocn(m_ptr->PR_PROC_NR)) return(EINVAL); - if (iskerneln(m_ptr->PR_PROC_NR)) return(EPERM); - rp = proc_addr(m_ptr->PR_PROC_NR); + if (! isokendpt(m_ptr->PR_ENDPT, &proc)) return(EINVAL); + if (iskerneln(proc)) return(EPERM); + rp = proc_addr(proc); /* Copy the map from PM. */ - src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr, + src_phys = umap_local(proc_addr(who_p), D, (vir_bytes) map_ptr, sizeof(rp->p_memmap)); if (src_phys == 0) return(EFAULT); phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap)); diff --git a/kernel/system/do_nice.c b/kernel/system/do_nice.c index cb0ad6692..855e4e067 100644 --- a/kernel/system/do_nice.c +++ b/kernel/system/do_nice.c @@ -2,7 +2,7 @@ * m_type: SYS_NICE * * The parameters for this kernel call are: - * m1_i1: PR_PROC_NR process number to change priority + * m1_i1: PR_ENDPT process number to change priority * m1_i2: PR_PRIORITY the new priority */ @@ -21,8 +21,7 @@ PUBLIC int do_nice(message *m_ptr) register struct proc *rp; /* Extract the message parameters and do sanity checking. */ - proc_nr = m_ptr->PR_PROC_NR; - if (! isokprocn(proc_nr)) return(EINVAL); + if(!isokendpt(m_ptr->PR_ENDPT, &proc_nr)) return EINVAL; if (iskerneln(proc_nr)) return(EPERM); pri = m_ptr->PR_PRIORITY; if (pri < PRIO_MIN || pri > PRIO_MAX) return(EINVAL); diff --git a/kernel/system/do_privctl.c b/kernel/system/do_privctl.c index 49df7322b..e01ff2333 100644 --- a/kernel/system/do_privctl.c +++ b/kernel/system/do_privctl.c @@ -2,7 +2,7 @@ * m_type: SYS_PRIVCTL * * The parameters for this kernel call are: - * m1_i1: PR_PROC_NR (process number of caller) + * m1_i1: PR_ENDPT (process number of caller) */ #include "../system.h" @@ -38,10 +38,9 @@ message *m_ptr; /* pointer to request message */ * running by the NO_PRIV flag. This flag is set when a privileged process * forks. */ - caller_ptr = proc_addr(m_ptr->m_source); + caller_ptr = proc_addr(who_p); if (! (priv(caller_ptr)->s_flags & SYS_PROC)) return(EPERM); - proc_nr = m_ptr->PR_PROC_NR; - if (! isokprocn(proc_nr)) return(EINVAL); + if(!isokendpt(m_ptr->PR_ENDPT, &proc_nr)) return(EINVAL); rp = proc_addr(proc_nr); switch(m_ptr->CTL_REQUEST) @@ -114,9 +113,6 @@ message *m_ptr; /* pointer to request message */ priv(rp)->s_io_tab[i].ior_limit= io_range.ior_limit; priv(rp)->s_nr_io_range++; - kprintf("do_privctl: added I/O range [0x%x..0x%x]\n", - io_range.ior_base, io_range.ior_limit); - return OK; case SYS_PRIV_ADD_MEM: @@ -145,9 +141,6 @@ message *m_ptr; /* pointer to request message */ priv(rp)->s_nr_mem_range++; #endif - kprintf("do_privctl: should add memory range [0x%x..0x%x]\n", - mem_range.mr_base, mem_range.mr_limit); - return OK; case SYS_PRIV_ADD_IRQ: @@ -166,8 +159,6 @@ message *m_ptr; /* pointer to request message */ priv(rp)->s_irq_tab[i]= m_ptr->CTL_MM_PRIV; priv(rp)->s_nr_irq++; - kprintf("do_privctl: adding IRQ %d\n", m_ptr->CTL_MM_PRIV); - return OK; default: diff --git a/kernel/system/do_sdevio.c b/kernel/system/do_sdevio.c index 831a18b87..82a707f8e 100644 --- a/kernel/system/do_sdevio.c +++ b/kernel/system/do_sdevio.c @@ -12,6 +12,7 @@ #include "../system.h" #include +#include #if USE_SDEVIO @@ -21,17 +22,20 @@ PUBLIC int do_sdevio(m_ptr) register message *m_ptr; /* pointer to request message */ { - int proc_nr = m_ptr->DIO_VEC_PROC; + int proc_nr, proc_nr_e = m_ptr->DIO_VEC_ENDPT; int count = m_ptr->DIO_VEC_SIZE; long port = m_ptr->DIO_PORT; phys_bytes phys_buf; - /* Check if process number is OK. A process number is allowed here, because - * driver may directly provide a pointer to a buffer at the user-process + /* Check if process endpoint is OK. + * A driver may directly provide a pointer to a buffer at the user-process * that initiated the device I/O. Kernel processes, of course, are denied. */ - if (proc_nr == SELF) proc_nr = m_ptr->m_source; - if (! isokprocn(proc_nr)) return(EINVAL); + if (proc_nr_e == SELF) + proc_nr = who_p; + else + if(!isokendpt(proc_nr_e, &proc_nr)) + return(EINVAL); if (iskerneln(proc_nr)) return(EPERM); /* Get and check physical address. */ diff --git a/kernel/system/do_segctl.c b/kernel/system/do_segctl.c index b6bdd00f4..e1b5b5988 100644 --- a/kernel/system/do_segctl.c +++ b/kernel/system/do_segctl.c @@ -31,7 +31,7 @@ register message *m_ptr; /* pointer to request message */ int result; /* First check if there is a slot available for this segment. */ - rp = proc_addr(m_ptr->m_source); + rp = proc_addr(who_p); index = -1; for (i=0; i < NR_REMOTE_SEGS; i++) { if (! rp->p_priv->s_farmem[i].in_use) { diff --git a/kernel/system/do_setalarm.c b/kernel/system/do_setalarm.c index a20d32383..98f756028 100644 --- a/kernel/system/do_setalarm.c +++ b/kernel/system/do_setalarm.c @@ -9,6 +9,8 @@ #include "../system.h" +#include + #if USE_SETALARM FORWARD _PROTOTYPE( void cause_alarm, (timer_t *tp) ); @@ -21,7 +23,6 @@ message *m_ptr; /* pointer to request message */ { /* A process requests a synchronous alarm, or wants to cancel its alarm. */ register struct proc *rp; /* pointer to requesting process */ - int proc_nr; /* which process wants the alarm */ long exp_time; /* expiration time for this alarm */ int use_abs_time; /* use absolute or relative time */ timer_t *tp; /* the process' timer structure */ @@ -30,13 +31,12 @@ message *m_ptr; /* pointer to request message */ /* Extract shared parameters from the request message. */ exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */ use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */ - proc_nr = m_ptr->m_source; /* process to interrupt later */ - rp = proc_addr(proc_nr); + rp = proc_addr(who_p); if (! (priv(rp)->s_flags & SYS_PROC)) return(EPERM); /* Get the timer structure and set the parameters for this alarm. */ tp = &(priv(rp)->s_alarm_timer); - tmr_arg(tp)->ta_int = proc_nr; + tmr_arg(tp)->ta_int = m_ptr->m_source; tp->tmr_func = cause_alarm; /* Return the ticks left on the previous alarm. */ @@ -67,8 +67,8 @@ timer_t *tp; * alarm. The process number is stored in timer argument 'ta_int'. Notify that * process with a notification message from CLOCK. */ - int proc_nr = tmr_arg(tp)->ta_int; /* get process number */ - lock_notify(CLOCK, proc_nr); /* notify process */ + int proc_nr_e = tmr_arg(tp)->ta_int; /* get process number */ + lock_notify(CLOCK, proc_nr_e); /* notify process */ } #endif /* USE_SETALARM */ diff --git a/kernel/system/do_sigreturn.c b/kernel/system/do_sigreturn.c index a821d3b3c..f1b026d9e 100644 --- a/kernel/system/do_sigreturn.c +++ b/kernel/system/do_sigreturn.c @@ -2,7 +2,7 @@ * m_type: SYS_SIGRETURN * * The parameters for this kernel call are: - * m2_i1: SIG_PROC # process returning from handler + * m2_i1: SIG_ENDPT # process returning from handler * m2_p1: SIG_CTXT_PTR # pointer to sigcontext structure * */ @@ -26,10 +26,11 @@ message *m_ptr; /* pointer to request message */ struct sigcontext sc; register struct proc *rp; phys_bytes src_phys; + int proc; - if (! isokprocn(m_ptr->SIG_PROC)) return(EINVAL); - if (iskerneln(m_ptr->SIG_PROC)) return(EPERM); - rp = proc_addr(m_ptr->SIG_PROC); + if (! isokendpt(m_ptr->SIG_ENDPT, &proc)) return(EINVAL); + if (iskerneln(proc)) return(EPERM); + rp = proc_addr(proc); /* Copy in the sigcontext structure. */ src_phys = umap_local(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR, diff --git a/kernel/system/do_sigsend.c b/kernel/system/do_sigsend.c index 712152712..9e082b6f7 100644 --- a/kernel/system/do_sigsend.c +++ b/kernel/system/do_sigsend.c @@ -2,7 +2,7 @@ * m_type: SYS_SIGSEND * * The parameters for this kernel call are: - * m2_i1: SIG_PROC # process to call signal handler + * m2_i1: SIG_ENDPT # process to call signal handler * m2_p1: SIG_CTXT_PTR # pointer to sigcontext structure * m2_i3: SIG_FLAGS # flags for S_SIGRETURN call * @@ -28,10 +28,11 @@ message *m_ptr; /* pointer to request message */ phys_bytes src_phys, dst_phys; struct sigcontext sc, *scp; struct sigframe fr, *frp; + int proc; - if (! isokprocn(m_ptr->SIG_PROC)) return(EINVAL); - if (iskerneln(m_ptr->SIG_PROC)) return(EPERM); - rp = proc_addr(m_ptr->SIG_PROC); + if (!isokendpt(m_ptr->SIG_ENDPT, &proc)) return(EINVAL); + if (iskerneln(proc)) return(EPERM); + rp = proc_addr(proc); /* Get the sigmsg structure into our address space. */ src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes) diff --git a/kernel/system/do_times.c b/kernel/system/do_times.c index 53b9bec24..12846fd15 100644 --- a/kernel/system/do_times.c +++ b/kernel/system/do_times.c @@ -2,7 +2,7 @@ * m_type: SYS_TIMES * * The parameters for this kernel call are: - * m4_l1: T_PROC_NR (get info for this process) + * m4_l1: T_ENDPT (get info for this process) * m4_l1: T_USER_TIME (return values ...) * m4_l2: T_SYSTEM_TIME * m4_l5: T_BOOT_TICKS @@ -10,6 +10,8 @@ #include "../system.h" +#include + #if USE_TIMES /*===========================================================================* @@ -20,15 +22,15 @@ register message *m_ptr; /* pointer to request message */ { /* Handle sys_times(). Retrieve the accounting information. */ register struct proc *rp; - int proc_nr; + int proc_nr, e_proc_nr; /* Insert the times needed by the SYS_TIMES kernel call in the message. * The clock's interrupt handler may run to update the user or system time * while in this code, but that cannot do any harm. */ - proc_nr = (m_ptr->T_PROC_NR == SELF) ? m_ptr->m_source : m_ptr->T_PROC_NR; - if (isokprocn(proc_nr)) { - rp = proc_addr(m_ptr->T_PROC_NR); + e_proc_nr = (m_ptr->T_ENDPT == SELF) ? m_ptr->m_source : m_ptr->T_ENDPT; + if(e_proc_nr != NONE && isokendpt(e_proc_nr, &proc_nr)) { + rp = proc_addr(proc_nr); m_ptr->T_USER_TIME = rp->p_user_time; m_ptr->T_SYSTEM_TIME = rp->p_sys_time; } diff --git a/kernel/system/do_trace.c b/kernel/system/do_trace.c index 0e62842eb..0ff740470 100644 --- a/kernel/system/do_trace.c +++ b/kernel/system/do_trace.c @@ -2,7 +2,7 @@ * m_type: SYS_TRACE * * The parameters for this kernel call are: - * m2_i1: CTL_PROC_NR process that is traced + * m2_i1: CTL_ENDPT process that is traced * m2_i2: CTL_REQUEST trace request * m2_l1: CTL_ADDRESS address at traced process' space * m2_l2: CTL_DATA data to be written or returned here @@ -44,10 +44,10 @@ register message *m_ptr; vir_bytes tr_addr = (vir_bytes) m_ptr->CTL_ADDRESS; long tr_data = m_ptr->CTL_DATA; int tr_request = m_ptr->CTL_REQUEST; - int tr_proc_nr = m_ptr->CTL_PROC_NR; + int tr_proc_nr_e = m_ptr->CTL_ENDPT, tr_proc_nr; int i; - if (! isokprocn(tr_proc_nr)) return(EINVAL); + if(!isokendpt(tr_proc_nr_e, &tr_proc_nr)) return(EINVAL); if (iskerneln(tr_proc_nr)) return(EPERM); rp = proc_addr(tr_proc_nr); diff --git a/kernel/system/do_umap.c b/kernel/system/do_umap.c index 04c981e72..613549169 100644 --- a/kernel/system/do_umap.c +++ b/kernel/system/do_umap.c @@ -24,12 +24,16 @@ register message *m_ptr; /* pointer to request message */ int seg_index = m_ptr->CP_SRC_SPACE & SEGMENT_INDEX; vir_bytes offset = m_ptr->CP_SRC_ADDR; int count = m_ptr->CP_NR_BYTES; - int proc_nr = (int) m_ptr->CP_SRC_PROC_NR; + int endpt = (int) m_ptr->CP_SRC_ENDPT; + int proc_nr; phys_bytes phys_addr; /* Verify process number. */ - if (proc_nr == SELF) proc_nr = m_ptr->m_source; - if (! isokprocn(proc_nr)) return(EINVAL); + if (endpt == SELF) + proc_nr = who_p; + else + if (! isokendpt(endpt, &proc_nr)) + return(EINVAL); /* See which mapping should be made. */ switch(seg_type) { diff --git a/kernel/system/do_vcopy.c b/kernel/system/do_vcopy.c index 8db9e9526..f6db0fd67 100644 --- a/kernel/system/do_vcopy.c +++ b/kernel/system/do_vcopy.c @@ -26,7 +26,6 @@ register message *m_ptr; /* pointer to request message */ * different kernel calls so that permissions can be checked. */ int nr_req; - int caller_pid; vir_bytes caller_vir; phys_bytes caller_phys; phys_bytes kernel_phys; @@ -40,9 +39,8 @@ register message *m_ptr; /* pointer to request message */ bytes = nr_req * sizeof(struct vir_cp_req); /* Calculate physical addresses and copy (port,value)-pairs from user. */ - caller_pid = (int) m_ptr->m_source; caller_vir = (vir_bytes) m_ptr->VCP_VEC_ADDR; - caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes); + caller_phys = umap_local(proc_addr(who_p), D, caller_vir, bytes); if (0 == caller_phys) return(EFAULT); kernel_phys = vir2phys(vir_cp_req); phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes); diff --git a/kernel/system/do_vdevio.c b/kernel/system/do_vdevio.c index 54a5d65f2..94792bf7b 100644 --- a/kernel/system/do_vdevio.c +++ b/kernel/system/do_vdevio.c @@ -10,6 +10,7 @@ #include "../system.h" #include +#include #if USE_VDEVIO @@ -34,7 +35,6 @@ register message *m_ptr; /* pointer to request message */ int vec_size; /* size of vector */ int io_in; /* true if input */ size_t bytes; /* # bytes to be copied */ - int caller_proc; /* process number of caller */ vir_bytes caller_vir; /* virtual address at caller */ phys_bytes caller_phys; /* physical address at caller */ int i; @@ -53,9 +53,8 @@ register message *m_ptr; /* pointer to request message */ if (bytes > sizeof(vdevio_buf)) return(E2BIG); /* Calculate physical addresses and copy (port,value)-pairs from user. */ - caller_proc = m_ptr->m_source; caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR; - caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes); + caller_phys = umap_local(proc_addr(who_p), D, caller_vir, bytes); if (0 == caller_phys) return(EFAULT); phys_copy(caller_phys, vir2phys(vdevio_buf), (phys_bytes) bytes); diff --git a/kernel/system/do_vm.c b/kernel/system/do_vm.c index 4d2690bd8..0be63a9ee 100644 --- a/kernel/system/do_vm.c +++ b/kernel/system/do_vm.c @@ -2,11 +2,11 @@ * m_type: SYS_VM_MAP * * The parameters for this system call are: - * m4_l1: Process that requests map - * m4_l2: Map (TRUE) or unmap (FALSE) - * m4_l3: Base address - * m4_l4: Size - * m4_l5: Memory address + * m4_l1: Process that requests map (VM_MAP_ENDPT) + * m4_l2: Map (TRUE) or unmap (FALSE) (VM_MAP_MAPUNMAP) + * m4_l3: Base address (VM_MAP_BASE) + * m4_l4: Size (VM_MAP_SIZE) + * m4_l5: Memory address (VM_MAP_ADDR) */ #include "../system.h" @@ -42,13 +42,17 @@ message *m_ptr; /* pointer to request message */ vm_init(); } - proc_nr= m_ptr->m4_l1; - if (proc_nr == SELF) - proc_nr= m_ptr->m_source; - do_map= m_ptr->m4_l2; - base= m_ptr->m4_l3; - size= m_ptr->m4_l4; - offset= m_ptr->m4_l5; + if (m_ptr->VM_MAP_ENDPT == SELF) { + proc_nr = who_p; + } else { + if(!isokendpt(m_ptr->VM_MAP_ENDPT, &proc_nr)) + return EINVAL; + } + + do_map= m_ptr->VM_MAP_MAPUNMAP; + base= m_ptr->VM_MAP_BASE; + size= m_ptr->VM_MAP_SIZE; + offset= m_ptr->VM_MAP_ADDR; pp= proc_addr(proc_nr); p_phys= umap_local(pp, D, base, size); diff --git a/kernel/type.h b/kernel/type.h index 1d4a3b648..0d51f5527 100755 --- a/kernel/type.h +++ b/kernel/type.h @@ -21,6 +21,7 @@ struct boot_image { bitchunk_t ipc_to; /* send mask protection */ long call_mask; /* system call protection */ char proc_name[P_NAME_LEN]; /* name in process table */ + int endpoint; /* endpoint number when started */ }; struct memory { @@ -94,7 +95,7 @@ typedef struct irq_hook { int (*handler)(struct irq_hook *); /* interrupt handler */ int irq; /* IRQ vector number */ int id; /* id of this hook */ - int proc_nr; /* NONE if not in use */ + int proc_nr_e; /* (endpoint) NONE if not in use */ irq_id_t notify_id; /* id to return on interrupt */ irq_policy_t policy; /* bit mask for policy */ } irq_hook_t;