'proc number' is process slot, 'endpoint' are generation-aware process

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.
This commit is contained in:
Ben Gras 2006-03-03 10:00:02 +00:00
parent 5d7f5fccf5
commit 1335d5d700
37 changed files with 360 additions and 212 deletions

View file

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

View file

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

View file

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

View file

@ -19,6 +19,7 @@
#include <a.out.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/endpoint.h>
#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 */

View file

@ -38,6 +38,8 @@
#include <minix/com.h>
#include <minix/callnr.h>
#include <minix/endpoint.h>
#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;
}

View file

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

View file

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

View file

@ -28,12 +28,14 @@
* 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"
@ -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<<call_nr))) {
@ -113,7 +117,7 @@ PRIVATE void initialize(void)
/* 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. */
@ -238,19 +242,27 @@ int source;
/*===========================================================================*
* 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);
}
/*===========================================================================*
@ -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;

View file

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

View file

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

View file

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

View file

@ -10,6 +10,7 @@
#include "../system.h"
#include <minix/devio.h>
#include <minix/endpoint.h>
#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)
{

View file

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

View file

@ -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 <string.h>
#include <signal.h>
#include <minix/endpoint.h>
#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);

View file

@ -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 <minix/endpoint.h>
#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);

View file

@ -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 <minix/endpoint.h>
#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);
}

View file

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

View file

@ -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 <signal.h>
#include <sys/sigcontext.h>
#include <minix/endpoint.h>
#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 */

View file

@ -7,6 +7,7 @@
#include "../system.h"
#include <minix/type.h>
#include <minix/endpoint.h>
#include <ibm/int86.h>
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(&reg86);
phys_copy(caller_phys, kernel_phys, (phys_bytes) sizeof(reg86));

View file

@ -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 <jnherder@cs.vu.nl>
*/
#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

View file

@ -11,6 +11,8 @@
#include "../system.h"
#include <minix/endpoint.h>
#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<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;
}
@ -98,7 +100,7 @@ register message *m_ptr; /* pointer to request message */
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);
@ -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);
}

View file

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

View file

@ -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 <minix/endpoint.h>
#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));

View file

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

View file

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

View file

@ -12,6 +12,7 @@
#include "../system.h"
#include <minix/devio.h>
#include <minix/endpoint.h>
#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. */

View file

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

View file

@ -9,6 +9,8 @@
#include "../system.h"
#include <minix/endpoint.h>
#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 */

View file

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

View file

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

View file

@ -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 <minix/endpoint.h>
#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;
}

View file

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

View file

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

View file

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

View file

@ -10,6 +10,7 @@
#include "../system.h"
#include <minix/devio.h>
#include <minix/endpoint.h>
#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);

View file

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

View file

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