instance numbers, encoded and decoded using macros in <minix/endpoint.h>.
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.
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 */
#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
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;
#include <a.out.h>
#include <minix/callnr.h>
#include <minix/com.h>
+#include <minix/endpoint.h>
#include "proc.h"
/* Prototype declarations for PRIVATE functions. */
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) {
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 */
#include <minix/com.h>
#include <minix/callnr.h>
+#include <minix/endpoint.h>
+#include "debug.h"
#include "kernel.h"
#include "proc.h"
* 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));
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) { \
#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)
/*===========================================================================*
* 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.
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
*/
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
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);
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
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 */
* 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 */
}
/*===========================================================================*
* 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 */
{
* 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);
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 */
/*===========================================================================*
* 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 */
{
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
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. */
/* 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);
* 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;
*/
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
/*===========================================================================*
* 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
* 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) {
/*===========================================================================*
* 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);
}
}
}
+/*===========================================================================*
+ * 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;
+}
+
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
_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,
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
*/
+#include "debug.h"
#include "kernel.h"
#include "system.h"
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/sigcontext.h>
+#include <minix/endpoint.h>
#if (CHIP == INTEL)
#include <ibm/memory.h>
#include "protect.h"
/* 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<<call_nr))) {
/* Initialize IRQ handler hooks. Mark all hooks available. */
for (i=0; i<NR_IRQ_HOOKS; i++) {
- irq_hooks[i].proc_nr = NONE;
+ irq_hooks[i].proc_nr_e = NONE;
}
/* Initialize all alarm timers for all processes. */
/*===========================================================================*
* send_sig *
*===========================================================================*/
-PUBLIC void send_sig(proc_nr, sig_nr)
-int proc_nr; /* system process to be signalled */
-int sig_nr; /* signal to be sent, 1 to _NSIG */
+PUBLIC void send_sig(int proc_nr, 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;
+ static int n;
+
+ if(!isokprocn(proc_nr)) {
+ panic("Bogus send_sig", proc_nr);
+ return;
+ }
+ if(isemptyn(proc_nr)) {
+ kprintf("kernel send_sig: ignoring sig for empty proc %d\n", proc_nr);
+ return;
+ }
rp = proc_addr(proc_nr);
sigaddset(&priv(rp)->s_sig_pending, sig_nr);
- lock_notify(SYSTEM, proc_nr);
+ lock_notify(SYSTEM, rp->p_endpoint);
}
/*===========================================================================*
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;
#define SYSTEM_H
/* Common includes for the system library. */
+#include "debug.h"
#include "kernel.h"
#include "proto.h"
#include "proc.h"
/* 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);
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;
* 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. */
#include "../system.h"
#include <minix/devio.h>
+#include <minix/endpoint.h>
#if USE_DEVIO
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)
{
* 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"
* 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? */
* 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)
#include "../system.h"
#include <string.h>
#include <signal.h>
+#include <minix/endpoint.h>
#if USE_EXEC
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)
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);
* 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 <minix/endpoint.h>
+
#if USE_EXIT
FORWARD _PROTOTYPE( void clear_proc, (register struct proc *rc));
* 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);
}
/* 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
* 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 */
}
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
#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
}
}
- /* 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);
* 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"
#include "../protect.h"
#endif
+#include <minix/endpoint.h>
+
#if USE_FORK
/*===========================================================================*
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 */
#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 */
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);
}
* 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"
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) {
*/
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);
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;
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);
/* 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);
* 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 <signal.h>
#include <sys/sigcontext.h>
+#include <minix/endpoint.h>
#if USE_GETKSIG
/* 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 */
}
/* No process with pending signals was found. */
- m_ptr->SIG_PROC = NONE;
+ m_ptr->SIG_ENDPT = NONE;
return(OK);
}
#endif /* USE_GETKSIG */
#include "../system.h"
#include <minix/type.h>
+#include <minix/endpoint.h>
#include <ibm/int86.h>
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));
* 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 <jnherder@cs.vu.nl>
*/
-#include "../kernel.h"
#include "../system.h"
+#include "../kernel.h"
/*===========================================================================*
* do_iopenable *
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
#include "../system.h"
+#include <minix/endpoint.h>
+
#if USE_IRQCTL
FORWARD _PROTOTYPE(int generic_handler, (irq_hook_t *hook));
/* 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
/* 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)
{
/* Find a free IRQ hook for this mapping. */
hook_ptr = NULL;
for (irq_hook_id=0; irq_hook_id<NR_IRQ_HOOKS; irq_hook_id++) {
- if (irq_hooks[irq_hook_id].proc_nr == NONE) {
+ if (irq_hooks[irq_hook_id].proc_nr_e == NONE) {
hook_ptr = &irq_hooks[irq_hook_id]; /* free hook */
break;
}
if (notify_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);
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. */
* 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);
}
* 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
*/
* 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) {
* 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 <minix/endpoint.h>
#if USE_NEWMAP
{
/* 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));
* 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
*/
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);
* 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"
* 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)
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:
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:
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:
#include "../system.h"
#include <minix/devio.h>
+#include <minix/endpoint.h>
#if USE_SDEVIO
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. */
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) {
#include "../system.h"
+#include <minix/endpoint.h>
+
#if USE_SETALARM
FORWARD _PROTOTYPE( void cause_alarm, (timer_t *tp) );
{
/* 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 */
/* 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. */
* 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 */
* 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
*
*/
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,
* 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
*
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)
* 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
#include "../system.h"
+#include <minix/endpoint.h>
+
#if USE_TIMES
/*===========================================================================*
{
/* 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;
}
* 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
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);
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) {
* 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;
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);
#include "../system.h"
#include <minix/devio.h>
+#include <minix/endpoint.h>
#if USE_VDEVIO
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;
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);
* 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"
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);
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 {
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;