Reorganized system call library; uses separate file per call now.
New configuration header file to include/ exclude functionality. Extracted privileged features from struct proc and create new struct priv. Renamed various system calls for readability.
This commit is contained in:
@@ -5,20 +5,50 @@ u = /usr
|
||||
i = $u/include
|
||||
|
||||
# Programs, flags, etc.
|
||||
CC = exec cc
|
||||
CC = exec cc $(CFLAGS) -c
|
||||
CPP = $l/cpp
|
||||
LD = $(CC) -.o
|
||||
CFLAGS = -I$i
|
||||
LDFLAGS = -i
|
||||
|
||||
SYS = clock.o copying.o debugging.o devio.o irqctl.o proctl.o \
|
||||
sysctl.o misc.o sigctl.o tracing.o priority.o
|
||||
SYSTEM = ../system.a
|
||||
|
||||
# What to make.
|
||||
all build: $(SYS)
|
||||
all build install: $(SYSTEM)
|
||||
|
||||
OBJECTS = \
|
||||
$(SYSTEM)(do_unused.o) \
|
||||
$(SYSTEM)(do_fork.o) \
|
||||
$(SYSTEM)(do_exec.o) \
|
||||
$(SYSTEM)(do_newmap.o) \
|
||||
$(SYSTEM)(do_exit.o) \
|
||||
$(SYSTEM)(do_trace.o) \
|
||||
$(SYSTEM)(do_schedctl.o) \
|
||||
$(SYSTEM)(do_times.o) \
|
||||
$(SYSTEM)(do_alarm.o) \
|
||||
$(SYSTEM)(do_irqctl.o) \
|
||||
$(SYSTEM)(do_devio.o) \
|
||||
$(SYSTEM)(do_vdevio.o) \
|
||||
$(SYSTEM)(do_sdevio.o) \
|
||||
$(SYSTEM)(do_copy.o) \
|
||||
$(SYSTEM)(do_vcopy.o) \
|
||||
$(SYSTEM)(do_umap.o) \
|
||||
$(SYSTEM)(do_memset.o) \
|
||||
$(SYSTEM)(do_svrctl.o) \
|
||||
$(SYSTEM)(do_segctl.o) \
|
||||
$(SYSTEM)(do_getksig.o) \
|
||||
$(SYSTEM)(do_endksig.o) \
|
||||
$(SYSTEM)(do_kill.o) \
|
||||
$(SYSTEM)(do_sigsend.o) \
|
||||
$(SYSTEM)(do_sigreturn.o) \
|
||||
$(SYSTEM)(do_abort.o) \
|
||||
$(SYSTEM)(do_getinfo.o) \
|
||||
|
||||
$(SYSTEM): $(OBJECTS)
|
||||
aal cr $@ *.o
|
||||
|
||||
clean:
|
||||
rm -f *.a *.o *.bak
|
||||
rm -f $(SYSTEM) *.o *.bak
|
||||
|
||||
depend:
|
||||
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
|
||||
@@ -27,4 +57,81 @@ depend:
|
||||
include .depend
|
||||
|
||||
|
||||
$(SYSTEM)(do_unused.o): do_unused.c
|
||||
$(CC) do_unused.c
|
||||
|
||||
$(SYSTEM)(do_fork.o): do_fork.c
|
||||
$(CC) do_fork.c
|
||||
|
||||
$(SYSTEM)(do_exec.o): do_exec.c
|
||||
$(CC) do_exec.c
|
||||
|
||||
$(SYSTEM)(do_newmap.o): do_newmap.c
|
||||
$(CC) do_newmap.c
|
||||
|
||||
$(SYSTEM)(do_exit.o): do_exit.c
|
||||
$(CC) do_exit.c
|
||||
|
||||
$(SYSTEM)(do_trace.o): do_trace.c
|
||||
$(CC) do_trace.c
|
||||
|
||||
$(SYSTEM)(do_schedctl.o): do_schedctl.c
|
||||
$(CC) do_schedctl.c
|
||||
|
||||
$(SYSTEM)(do_times.o): do_times.c
|
||||
$(CC) do_times.c
|
||||
|
||||
$(SYSTEM)(do_alarm.o): do_alarm.c
|
||||
$(CC) do_alarm.c
|
||||
|
||||
$(SYSTEM)(do_irqctl.o): do_irqctl.c
|
||||
$(CC) do_irqctl.c
|
||||
|
||||
$(SYSTEM)(do_devio.o): do_devio.c
|
||||
$(CC) do_devio.c
|
||||
|
||||
$(SYSTEM)(do_sdevio.o): do_sdevio.c
|
||||
$(CC) do_sdevio.c
|
||||
|
||||
$(SYSTEM)(do_vdevio.o): do_vdevio.c
|
||||
$(CC) do_vdevio.c
|
||||
|
||||
$(SYSTEM)(do_copy.o): do_copy.c
|
||||
$(CC) do_copy.c
|
||||
|
||||
$(SYSTEM)(do_vcopy.o): do_vcopy.c
|
||||
$(CC) do_vcopy.c
|
||||
|
||||
$(SYSTEM)(do_umap.o): do_umap.c
|
||||
$(CC) do_umap.c
|
||||
|
||||
$(SYSTEM)(do_memset.o): do_memset.c
|
||||
$(CC) do_memset.c
|
||||
|
||||
$(SYSTEM)(do_getksig.o): do_getksig.c
|
||||
$(CC) do_getksig.c
|
||||
|
||||
$(SYSTEM)(do_endksig.o): do_endksig.c
|
||||
$(CC) do_endksig.c
|
||||
|
||||
$(SYSTEM)(do_kill.o): do_kill.c
|
||||
$(CC) do_kill.c
|
||||
|
||||
$(SYSTEM)(do_sigsend.o): do_sigsend.c
|
||||
$(CC) do_sigsend.c
|
||||
|
||||
$(SYSTEM)(do_sigreturn.o): do_sigreturn.c
|
||||
$(CC) do_sigreturn.c
|
||||
|
||||
$(SYSTEM)(do_getinfo.o): do_getinfo.c
|
||||
$(CC) do_getinfo.c
|
||||
|
||||
$(SYSTEM)(do_abort.o): do_abort.c
|
||||
$(CC) do_abort.c
|
||||
|
||||
$(SYSTEM)(do_svrctl.o): do_svrctl.c
|
||||
$(CC) do_svrctl.c
|
||||
|
||||
$(SYSTEM)(do_segctl.o): do_segctl.c
|
||||
$(CC) do_segctl.c
|
||||
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_TIMES
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l1: T_PROC_NR (get info for this process)
|
||||
* m4_l1: T_USER_TIME (return values ...)
|
||||
* m4_l2: T_SYSTEM_TIME
|
||||
* m4_l5: T_BOOT_TICKS
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include "../debug.h"
|
||||
#include <signal.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* do_times *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_times(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_times(). Retrieve the accounting information. */
|
||||
|
||||
register struct proc *rp;
|
||||
int proc_nr;
|
||||
|
||||
/* Insert the times needed by the SYS_TIMES system call in the message. */
|
||||
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);
|
||||
lock(11, "do_times"); /* halt the volatile time counters in rp */
|
||||
m_ptr->T_USER_TIME = rp->p_user_time;
|
||||
m_ptr->T_SYSTEM_TIME = rp->p_sys_time;
|
||||
unlock(11);
|
||||
}
|
||||
m_ptr->T_BOOT_TICKS = get_uptime();
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SIGNALRM, SYS_SYNCALRM
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i1: ALRM_PROC_NR (set alarm for this process)
|
||||
* m2_l1: ALRM_EXP_TIME (alarm's expiration time)
|
||||
* m2_i2: ALRM_ABS_TIME (expiration time is absolute?)
|
||||
* m2_l1: ALRM_SEC_LEFT (return seconds left of previous)
|
||||
*
|
||||
* Changes:
|
||||
* Aug 25, 2004 fully rewritten to clean up code (Jorrit N. Herder)
|
||||
*/
|
||||
|
||||
FORWARD _PROTOTYPE( void cause_syncalrm, (timer_t *tp) );
|
||||
FORWARD _PROTOTYPE( void cause_signalrm, (timer_t *tp) );
|
||||
|
||||
/*===========================================================================*
|
||||
* do_setalarm *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_setalarm(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* A process requests an alarm, or wants to cancel its alarm. This function
|
||||
* is shared used for both the SYS_SIGNALRM and SYS_SYNCALRM.
|
||||
*/
|
||||
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 */
|
||||
clock_t uptime; /* placeholder for current uptime */
|
||||
|
||||
/* Extract shared parameters from the request message. */
|
||||
proc_nr = m_ptr->ALRM_PROC_NR; /* process to interrupt later */
|
||||
if (SELF == proc_nr) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||
exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */
|
||||
use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */
|
||||
|
||||
/* Get the timer structure and set the parameters for this alarm. */
|
||||
tp = &(proc_addr(proc_nr)->p_alarm_timer);
|
||||
tmr_arg(tp)->ta_int = proc_nr;
|
||||
switch (m_ptr->m_type) {
|
||||
case SYS_SYNCALRM: tp->tmr_func = cause_syncalrm; break;
|
||||
case SYS_SIGNALRM: tp->tmr_func = cause_signalrm; break;
|
||||
default: return(EINVAL); /* invalid alarm type */
|
||||
}
|
||||
|
||||
/* Return the ticks left on the previous alarm. */
|
||||
uptime = get_uptime();
|
||||
if ((tp->tmr_exp_time == TMR_NEVER) || (tp->tmr_exp_time < uptime) ) {
|
||||
m_ptr->ALRM_TIME_LEFT = 0;
|
||||
} else {
|
||||
m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime);
|
||||
}
|
||||
|
||||
/* Finally, (re)set the timer depending on 'exp_time'. */
|
||||
if (exp_time == 0) {
|
||||
reset_timer(tp);
|
||||
} else {
|
||||
tp->tmr_exp_time = (use_abs_time) ? exp_time : exp_time + get_uptime();
|
||||
set_timer(tp, tp->tmr_exp_time, tp->tmr_func);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* cause_signalrm *
|
||||
*===========================================================================*/
|
||||
PRIVATE void cause_signalrm(tp)
|
||||
timer_t *tp;
|
||||
{
|
||||
/* Routine called if a timer goes off for a process that requested an SIGALRM
|
||||
* signal using the alarm(2) system call. The timer argument 'ta_int' contains
|
||||
* the process number of the process to signal.
|
||||
*/
|
||||
cause_sig(tmr_arg(tp)->ta_int, SIGALRM);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* cause_syncalrm *
|
||||
*===========================================================================*/
|
||||
PRIVATE void cause_syncalrm(tp)
|
||||
timer_t *tp;
|
||||
{
|
||||
/* Routine called if a timer goes off and the process requested a synchronous
|
||||
* alarm. The process number is stored in timer argument 'ta_int'. Notify that
|
||||
* process given with a SYN_ALARM message.
|
||||
*/
|
||||
message m;
|
||||
m.NOTIFY_TYPE = SYN_ALARM;
|
||||
m.NOTIFY_ARG = get_uptime();
|
||||
m.NOTIFY_FLAGS = 0;
|
||||
lock_notify(tmr_arg(tp)->ta_int, &m);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VIRCOPY, SYS_PHYSCOPY, SYS_PHYSZERO
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_c1: CP_SRC_SPACE
|
||||
* m5_l1: CP_SRC_ADDR
|
||||
* m5_i1: CP_SRC_PROC_NR
|
||||
* m5_c2: CP_DST_SPACE
|
||||
* m5_l2: CP_DST_ADDR
|
||||
* m5_i2: CP_DST_PROC_NR
|
||||
* m5_l3: CP_NR_BYTES
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <minix/type.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* do_copy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_copy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or
|
||||
* physical addressing.
|
||||
*/
|
||||
struct vir_addr vir_addr[2]; /* virtual source and destination address */
|
||||
vir_bytes bytes; /* number of bytes to copy */
|
||||
int i;
|
||||
|
||||
/* Dismember the command message. */
|
||||
vir_addr[_SRC_].proc_nr = m_ptr->CP_SRC_PROC_NR;
|
||||
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_].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;
|
||||
|
||||
/* Now do some checks for both the source and destination virtual address.
|
||||
* This is done once for _SRC_, then once for _DST_.
|
||||
*/
|
||||
for (i=_SRC_; i<=_DST_; i++) {
|
||||
|
||||
/* 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) {
|
||||
kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_NUM);
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Check if physical addressing is used without SYS_PHYSCOPY. */
|
||||
if ((vir_addr[i].segment & PHYS_SEG) &&
|
||||
m_ptr->m_type != SYS_PHYSCOPY) return(EPERM);
|
||||
}
|
||||
|
||||
/* Check for overflow. This would happen for 64K segments and 16-bit
|
||||
* vir_bytes. Especially copying by the PM on do_fork() is affected.
|
||||
*/
|
||||
if (bytes != (vir_bytes) bytes) {
|
||||
kprintf("do_vircopy: overflow\n", NO_NUM);
|
||||
return(E2BIG);
|
||||
}
|
||||
|
||||
/* Now try to make the actual virtual copy. */
|
||||
return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );
|
||||
}
|
||||
|
||||
|
||||
/* Buffer to hold copy request vector from user. */
|
||||
PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE];
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vcopy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_vcopy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */
|
||||
int nr_req;
|
||||
int caller_pid;
|
||||
vir_bytes caller_vir;
|
||||
phys_bytes caller_phys;
|
||||
phys_bytes kernel_phys;
|
||||
phys_bytes bytes;
|
||||
int i,s;
|
||||
struct vir_cp_req *req;
|
||||
|
||||
/* Check if request vector size is ok. */
|
||||
nr_req = (unsigned) m_ptr->VCP_VEC_SIZE;
|
||||
if (nr_req > VCOPY_VEC_SIZE) return(EINVAL);
|
||||
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);
|
||||
if (0 == caller_phys) return(EFAULT);
|
||||
kernel_phys = vir2phys(vir_cp_req);
|
||||
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
|
||||
|
||||
/* Assume vector with requests is correct. Try to copy everything. */
|
||||
for (i=0; i<nr_req; i++) {
|
||||
|
||||
req = &vir_cp_req[i];
|
||||
|
||||
/* Check if physical addressing is used without SYS_PHYSVCOPY. */
|
||||
if (((req->src.segment | req->dst.segment) & PHYS_SEG) &&
|
||||
m_ptr->m_type != SYS_PHYSVCOPY)
|
||||
return(EPERM);
|
||||
if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK)
|
||||
return(s);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_physzero *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_physzero(m_ptr)
|
||||
register message *m_ptr;
|
||||
{
|
||||
/* Handle sys_physzero(). */
|
||||
phys_zero((phys_bytes) m_ptr->PZ_MEM_PTR, (phys_bytes) m_ptr->PZ_COUNT);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_UMAP
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_i1: CP_SRC_PROC_NR (process number)
|
||||
* m5_c1: CP_SRC_SPACE (segment where address is: T, D, or S)
|
||||
* m5_l1: CP_SRC_ADDR (virtual address)
|
||||
* m5_l2: CP_DST_ADDR (returns physical address)
|
||||
* m5_l3: CP_NR_BYTES (size of datastructure)
|
||||
*/
|
||||
|
||||
/*==========================================================================*
|
||||
* do_umap *
|
||||
*==========================================================================*/
|
||||
PUBLIC int do_umap(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Map virtual address to physical, for non-kernel processes. */
|
||||
int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE;
|
||||
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;
|
||||
phys_bytes phys_addr;
|
||||
|
||||
/* Verify process number. */
|
||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||
|
||||
/* See which mapping should be made. */
|
||||
switch(seg_type) {
|
||||
case LOCAL_SEG:
|
||||
phys_addr = umap_local(proc_addr(proc_nr), seg_index, offset, count);
|
||||
break;
|
||||
case REMOTE_SEG:
|
||||
phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count);
|
||||
break;
|
||||
case BIOS_SEG:
|
||||
phys_addr = umap_bios(proc_addr(proc_nr), offset, count);
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
m_ptr->CP_DST_ADDR = phys_addr;
|
||||
return (phys_addr == 0) ? EFAULT: OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_DEBUG
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include "../proc.h"
|
||||
#include "../glo.h"
|
||||
#include <limits.h>
|
||||
|
||||
#if ENABLE_LOCK_TIMING
|
||||
|
||||
static unsigned long starttimes[TIMING_CATEGORIES][2];
|
||||
|
||||
#define HIGHCOUNT 0
|
||||
#define LOWCOUNT 1
|
||||
|
||||
void timer_start(int cat, char *name)
|
||||
{
|
||||
static int init = 0;
|
||||
unsigned long h, l;
|
||||
int i;
|
||||
|
||||
if(cat < 0 || cat >= TIMING_CATEGORIES) return;
|
||||
|
||||
for(i = 0; i < sizeof(timingdata[0].names) && *name; i++)
|
||||
timingdata[cat].names[i] = *name++;
|
||||
timingdata[0].names[sizeof(timingdata[0].names)-1] = '\0';
|
||||
|
||||
if(starttimes[cat][HIGHCOUNT]) { return; }
|
||||
|
||||
if(!init) {
|
||||
int t, f;
|
||||
init = 1;
|
||||
for(t = 0; t < TIMING_CATEGORIES; t++) {
|
||||
timingdata[t].lock_timings_range[0] = 0;
|
||||
timingdata[t].resets = timingdata[t].misses =
|
||||
timingdata[t].measurements = 0;
|
||||
}
|
||||
}
|
||||
|
||||
read_tsc(&starttimes[cat][HIGHCOUNT], &starttimes[cat][LOWCOUNT]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void timer_end(int cat)
|
||||
{
|
||||
unsigned long h, l, d = 0, binsize;
|
||||
int bin;
|
||||
|
||||
read_tsc(&h, &l);
|
||||
if(cat < 0 || cat >= TIMING_CATEGORIES) return;
|
||||
if(!starttimes[cat][HIGHCOUNT]) {
|
||||
timingdata[cat].misses++;
|
||||
return;
|
||||
}
|
||||
if(starttimes[cat][HIGHCOUNT] == h) {
|
||||
d = (l - starttimes[cat][1]);
|
||||
} else if(starttimes[cat][HIGHCOUNT] == h-1 &&
|
||||
starttimes[cat][LOWCOUNT] > l) {
|
||||
d = ((ULONG_MAX - starttimes[cat][LOWCOUNT]) + l);
|
||||
} else {
|
||||
timingdata[cat].misses++;
|
||||
return;
|
||||
}
|
||||
starttimes[cat][HIGHCOUNT] = 0;
|
||||
if(!timingdata[cat].lock_timings_range[0] ||
|
||||
d < timingdata[cat].lock_timings_range[0] ||
|
||||
d > timingdata[cat].lock_timings_range[1]) {
|
||||
int t;
|
||||
if(!timingdata[cat].lock_timings_range[0] ||
|
||||
d < timingdata[cat].lock_timings_range[0])
|
||||
timingdata[cat].lock_timings_range[0] = d;
|
||||
if(!timingdata[cat].lock_timings_range[1] ||
|
||||
d > timingdata[cat].lock_timings_range[1])
|
||||
timingdata[cat].lock_timings_range[1] = d;
|
||||
for(t = 0; t < TIMING_POINTS; t++)
|
||||
timingdata[cat].lock_timings[t] = 0;
|
||||
timingdata[cat].binsize =
|
||||
(timingdata[cat].lock_timings_range[1] -
|
||||
timingdata[cat].lock_timings_range[0])/(TIMING_POINTS+1);
|
||||
if(timingdata[cat].binsize < 1)
|
||||
timingdata[cat].binsize = 1;
|
||||
timingdata[cat].resets++;
|
||||
}
|
||||
bin = (d-timingdata[cat].lock_timings_range[0]) /
|
||||
timingdata[cat].binsize;
|
||||
if(bin < 0 || bin >= TIMING_POINTS) {
|
||||
int t;
|
||||
/* this indicates a bug, but isn't really serious */
|
||||
for(t = 0; t < TIMING_POINTS; t++)
|
||||
timingdata[cat].lock_timings[t] = 0;
|
||||
timingdata[cat].misses++;
|
||||
} else {
|
||||
timingdata[cat].lock_timings[bin]++;
|
||||
timingdata[cat].measurements++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLE_K_DEBUGGING /* only include code if enabled */
|
||||
|
||||
#define PROCLIMIT 10000
|
||||
|
||||
PUBLIC void
|
||||
check_runqueues(char *when)
|
||||
{
|
||||
int q, l = 0;
|
||||
register struct proc *xp;
|
||||
|
||||
for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
|
||||
xp->p_found = 0;
|
||||
if(l++ > PROCLIMIT) { panic("check error", NO_NUM); }
|
||||
}
|
||||
|
||||
for (q=0; q < NR_SCHED_QUEUES; q++) {
|
||||
if(rdy_head[q] && !rdy_tail[q]) {
|
||||
kprintf("head but no tail: %s", (karg_t) when);
|
||||
panic("scheduling error", NO_NUM);
|
||||
}
|
||||
if(!rdy_head[q] && rdy_tail[q]) {
|
||||
kprintf("tail but no head: %s", (karg_t) when);
|
||||
panic("scheduling error", NO_NUM);
|
||||
}
|
||||
if(rdy_tail[q] && rdy_tail[q]->p_nextready != NIL_PROC) {
|
||||
kprintf("tail and tail->next not null; %s", (karg_t) when);
|
||||
panic("scheduling error", NO_NUM);
|
||||
}
|
||||
for(xp = rdy_head[q]; xp != NIL_PROC; xp = xp->p_nextready) {
|
||||
if (!xp->p_ready) {
|
||||
kprintf("scheduling error: unready on runq: %s\n", (karg_t) when);
|
||||
|
||||
panic("found unready process on run queue", NO_NUM);
|
||||
}
|
||||
if(xp->p_priority != q) {
|
||||
kprintf("scheduling error: wrong priority: %s\n", (karg_t) when);
|
||||
|
||||
panic("wrong priority", NO_NUM);
|
||||
}
|
||||
if(xp->p_found) {
|
||||
kprintf("scheduling error: double scheduling: %s\n", (karg_t) when);
|
||||
panic("proc more than once on scheduling queue", NO_NUM);
|
||||
}
|
||||
xp->p_found = 1;
|
||||
if(xp->p_nextready == NIL_PROC && rdy_tail[q] != xp) {
|
||||
kprintf("scheduling error: last element not tail: %s\n", (karg_t) when);
|
||||
panic("scheduling error", NO_NUM);
|
||||
}
|
||||
if(l++ > PROCLIMIT) panic("loop in schedule queue?", NO_NUM);
|
||||
}
|
||||
}
|
||||
|
||||
for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
|
||||
if(! isempty(xp) && xp->p_ready && ! xp->p_found) {
|
||||
kprintf("scheduling error: ready not on queue: %s\n", (karg_t) when);
|
||||
panic("ready proc not on scheduling queue", NO_NUM);
|
||||
if(l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================================================*
|
||||
* do_debug *
|
||||
*==========================================================================*/
|
||||
|
||||
#endif /* ENABLE_K_DEBUGGING */
|
||||
46
kernel/system/do_abort.c
Normal file
46
kernel/system/do_abort.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "../system.h"
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_ABORT
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: ABRT_HOW (how to abort, possibly fetch monitor params)
|
||||
* m1_i2: ABRT_MON_PROC (proc nr to get monitor params from)
|
||||
* m1_i3: ABRT_MON_LEN (length of monitor params)
|
||||
* m1_p1: ABRT_MON_ADDR (virtual address of params)
|
||||
*/
|
||||
#if USE_ABORT
|
||||
|
||||
/*===========================================================================*
|
||||
* do_abort *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_abort(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_abort. MINIX is unable to continue. This can originate in the
|
||||
* PM (normal abort or panic) or FS (panic), or TTY (user issued CTRL-ALT-DEL
|
||||
* or ESC after debugging dumps).
|
||||
*/
|
||||
int how = m_ptr->ABRT_HOW;
|
||||
|
||||
if (how == RBT_MONITOR) {
|
||||
/* The monitor is to run the specified instructions. */
|
||||
int proc_nr = m_ptr->ABRT_MON_PROC;
|
||||
int length = m_ptr->ABRT_MON_LEN + 1;
|
||||
vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR;
|
||||
phys_bytes src_phys = numap_local(proc_nr, src_vir, length);
|
||||
|
||||
/* Validate length and address of shutdown code before copying. */
|
||||
if (length > kinfo.params_size || src_phys == 0)
|
||||
phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
|
||||
else
|
||||
phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
|
||||
}
|
||||
prepare_shutdown(how);
|
||||
return(OK); /* pro-forma (really EDISASTER) */
|
||||
}
|
||||
|
||||
#endif /* USE_ABORT */
|
||||
|
||||
77
kernel/system/do_alarm.c
Normal file
77
kernel/system/do_alarm.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SETALARM
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i1: ALRM_PROC_NR (set alarm for this process)
|
||||
* m2_l1: ALRM_EXP_TIME (alarm's expiration time)
|
||||
* m2_i2: ALRM_ABS_TIME (expiration time is absolute?)
|
||||
* m2_l1: ALRM_SEC_LEFT (return seconds left of previous)
|
||||
*
|
||||
* Changes:
|
||||
* Aug 25, 2004 fully rewritten to clean up code (Jorrit N. Herder)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
#if USE_SETALARM
|
||||
|
||||
FORWARD _PROTOTYPE( void cause_alarm, (timer_t *tp) );
|
||||
|
||||
/*===========================================================================*
|
||||
* do_setalarm *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_setalarm(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* A process requests a synchronous alarm, or wants to cancel its alarm. */
|
||||
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 */
|
||||
clock_t uptime; /* placeholder for current uptime */
|
||||
|
||||
/* Extract shared parameters from the request message. */
|
||||
proc_nr = m_ptr->ALRM_PROC_NR; /* process to interrupt later */
|
||||
if (SELF == proc_nr) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||
exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */
|
||||
use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */
|
||||
|
||||
/* Get the timer structure and set the parameters for this alarm. */
|
||||
tp = &(proc_addr(proc_nr)->p_priv->s_alarm_timer);
|
||||
tmr_arg(tp)->ta_int = proc_nr;
|
||||
tp->tmr_func = cause_alarm;
|
||||
|
||||
/* Return the ticks left on the previous alarm. */
|
||||
uptime = get_uptime();
|
||||
if ((tp->tmr_exp_time == TMR_NEVER) || (tp->tmr_exp_time < uptime) ) {
|
||||
m_ptr->ALRM_TIME_LEFT = 0;
|
||||
} else {
|
||||
m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime);
|
||||
}
|
||||
|
||||
/* Finally, (re)set the timer depending on 'exp_time'. */
|
||||
if (exp_time == 0) {
|
||||
reset_timer(tp);
|
||||
} else {
|
||||
tp->tmr_exp_time = (use_abs_time) ? exp_time : exp_time + get_uptime();
|
||||
set_timer(tp, tp->tmr_exp_time, tp->tmr_func);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* cause_alarm *
|
||||
*===========================================================================*/
|
||||
PRIVATE void cause_alarm(tp)
|
||||
timer_t *tp;
|
||||
{
|
||||
/* Routine called if a timer goes off and the process requested a synchronous
|
||||
* alarm. The process number is stored in timer argument 'ta_int'. Notify that
|
||||
* process given with a SYN_ALARM message.
|
||||
*/
|
||||
lock_alert(CLOCK, tmr_arg(tp)->ta_int);
|
||||
}
|
||||
|
||||
#endif /* USE_SETALARM */
|
||||
71
kernel/system/do_copy.c
Normal file
71
kernel/system/do_copy.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VIRCOPY, SYS_PHYSCOPY
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_c1: CP_SRC_SPACE
|
||||
* m5_l1: CP_SRC_ADDR
|
||||
* m5_i1: CP_SRC_PROC_NR
|
||||
* m5_c2: CP_DST_SPACE
|
||||
* m5_l2: CP_DST_ADDR
|
||||
* m5_i2: CP_DST_PROC_NR
|
||||
* m5_l3: CP_NR_BYTES
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <minix/type.h>
|
||||
|
||||
#if (USE_VIRCOPY || USE_PHYSCOPY)
|
||||
|
||||
/*===========================================================================*
|
||||
* do_copy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_copy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or
|
||||
* physical addressing.
|
||||
*/
|
||||
struct vir_addr vir_addr[2]; /* virtual source and destination address */
|
||||
vir_bytes bytes; /* number of bytes to copy */
|
||||
int i;
|
||||
|
||||
/* Dismember the command message. */
|
||||
vir_addr[_SRC_].proc_nr = m_ptr->CP_SRC_PROC_NR;
|
||||
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_].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;
|
||||
|
||||
/* Now do some checks for both the source and destination virtual address.
|
||||
* This is done once for _SRC_, then once for _DST_.
|
||||
*/
|
||||
for (i=_SRC_; i<=_DST_; i++) {
|
||||
|
||||
/* 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) {
|
||||
kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_NUM);
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Check if physical addressing is used without SYS_PHYSCOPY. */
|
||||
if ((vir_addr[i].segment & PHYS_SEG) &&
|
||||
m_ptr->m_type != SYS_PHYSCOPY) return(EPERM);
|
||||
}
|
||||
|
||||
/* Check for overflow. This would happen for 64K segments and 16-bit
|
||||
* vir_bytes. Especially copying by the PM on do_fork() is affected.
|
||||
*/
|
||||
if (bytes != (vir_bytes) bytes) {
|
||||
kprintf("do_vircopy: overflow\n", NO_NUM);
|
||||
return(E2BIG);
|
||||
}
|
||||
|
||||
/* Now try to make the actual virtual copy. */
|
||||
return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );
|
||||
}
|
||||
#endif /* (USE_VIRCOPY || USE_PHYSCOPY) */
|
||||
|
||||
|
||||
44
kernel/system/do_devio.c
Normal file
44
kernel/system/do_devio.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_DEVIO
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i3: DIO_REQUEST (request input or output)
|
||||
* m2_i1: DIO_TYPE (flag indicating byte, word, or long)
|
||||
* m2_l1: DIO_PORT (port to read/ write)
|
||||
* m2_l2: DIO_VALUE (value to write/ return value read)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <minix/devio.h>
|
||||
|
||||
#if USE_DEVIO
|
||||
|
||||
/*===========================================================================*
|
||||
* do_devio *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_devio(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Perform actual device I/O for byte, word, and long values. */
|
||||
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break;
|
||||
case DIO_WORD: m_ptr->DIO_VALUE = inw(m_ptr->DIO_PORT); break;
|
||||
case DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
} else {
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
case DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
case DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_DEVIO */
|
||||
49
kernel/system/do_endksig.c
Normal file
49
kernel/system/do_endksig.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/* The system call that is implemented in this file:
|
||||
* SYS_SIGCTL # signal handling functionality
|
||||
*
|
||||
* The parameters and types for this system call are:
|
||||
* SIG_REQUEST # request to perform (long)
|
||||
* SIG_PROC # process to signal/ pending (int)
|
||||
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||
* SIG_MAP # bit map with pending signals (long)
|
||||
* SIG_NUMBER # signal number to send to process (int)
|
||||
*
|
||||
* Supported request types are in the parameter SIG_REQUEST:
|
||||
* S_GETSIG # get a pending kernel signal
|
||||
* S_ENDSIG # signal has been processed
|
||||
* S_SENDSIG # deliver a POSIX-style signal
|
||||
* S_SIGRETURN # return from a POSIX-style signal
|
||||
* S_KILL # send a signal to a process
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#include <sys/sigcontext.h>
|
||||
|
||||
#if USE_ENDKSIG
|
||||
|
||||
/*===========================================================================*
|
||||
* do_endksig *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_endksig(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Finish up after a kernel type signal, caused by a SYS_KILL message or a
|
||||
* call to cause_sig by a task. This is called by the PM after processing a
|
||||
* signal it got with SYS_GETKSIG.
|
||||
*/
|
||||
register struct proc *rp;
|
||||
|
||||
rp = proc_addr(m_ptr->SIG_PROC);
|
||||
if (isemptyp(rp)) return(EINVAL); /* process already dead? */
|
||||
|
||||
/* PM has finished one kernel signal. Perhaps process is ready now? */
|
||||
if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */
|
||||
if ((rp->p_rts_flags &= ~SIG_PENDING)==0) /* remove pending flag */
|
||||
lock_ready(rp); /* ready if no flags */
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_ENDKSIG */
|
||||
|
||||
63
kernel/system/do_exec.c
Normal file
63
kernel/system/do_exec.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_EXEC
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (process that did exec call)
|
||||
* m1_i3: PR_TRACING (flag to indicate tracing is on/ off)
|
||||
* 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 <signal.h>
|
||||
|
||||
#if USE_EXEC
|
||||
|
||||
/*===========================================================================*
|
||||
* do_exec *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_exec(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */
|
||||
|
||||
register struct proc *rp;
|
||||
reg_t sp; /* new sp */
|
||||
phys_bytes phys_name;
|
||||
char *np;
|
||||
|
||||
rp = proc_addr(m_ptr->PR_PROC_NR);
|
||||
if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP);
|
||||
sp = (reg_t) m_ptr->PR_STACK_PTR;
|
||||
rp->p_reg.sp = sp; /* set the stack pointer */
|
||||
#if (CHIP == M68000)
|
||||
rp->p_splow = sp; /* set the stack pointer low water */
|
||||
#ifdef FPP
|
||||
/* Initialize fpp for this process */
|
||||
fpp_new_state(rp);
|
||||
#endif
|
||||
#endif
|
||||
#if (CHIP == INTEL) /* wipe extra LDT entries */
|
||||
kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0,
|
||||
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
|
||||
#endif
|
||||
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_ready(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,
|
||||
(vir_bytes) P_NAME_LEN - 1);
|
||||
if (phys_name != 0) {
|
||||
phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1);
|
||||
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
|
||||
*np = 0; /* mark end */
|
||||
} else {
|
||||
kstrncpy(rp->p_name, "<unset>", P_NAME_LEN);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
#endif /* USE_EXEC */
|
||||
|
||||
|
||||
|
||||
42
kernel/system/do_exit.c
Normal file
42
kernel/system/do_exit.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_EXIT
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (slot number of exiting process)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
#if USE_EXIT
|
||||
|
||||
/*===========================================================================*
|
||||
* do_exit *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_exit(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_exit. A user process has exited or a system process requests
|
||||
* to exit. Only the PM can request other process slots to be cleared.
|
||||
* The routine to clean up a process table slot cancels outstanding timers,
|
||||
* possibly removes the process from the message queues, and resets certain
|
||||
* process table fields to the default values.
|
||||
*/
|
||||
int exit_proc_nr;
|
||||
|
||||
/* 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(exit_proc_nr); /* exit a user process */
|
||||
return(OK); /* report back to PM */
|
||||
}
|
||||
}
|
||||
|
||||
/* The PM or some other system process requested to be exited. */
|
||||
clear_proc(m_ptr->m_source);
|
||||
return(EDONTREPLY);
|
||||
}
|
||||
#endif /* USE_EXIT */
|
||||
|
||||
|
||||
62
kernel/system/do_fork.c
Normal file
62
kernel/system/do_fork.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_FORK
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (child's process table slot)
|
||||
* m1_i2: PR_PPROC_NR (parent, process that forked)
|
||||
* m1_i3: PR_PID (child pid received from PM)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#if (CHIP == INTEL)
|
||||
#include "../protect.h"
|
||||
#endif
|
||||
|
||||
#if USE_FORK
|
||||
|
||||
/*===========================================================================*
|
||||
* do_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. */
|
||||
|
||||
#if (CHIP == INTEL)
|
||||
reg_t old_ldt_sel;
|
||||
#endif
|
||||
register struct proc *rpc;
|
||||
struct proc *rpp;
|
||||
|
||||
rpp = proc_addr(m_ptr->PR_PPROC_NR);
|
||||
rpc = proc_addr(m_ptr->PR_PROC_NR);
|
||||
if (! isemptyp(rpc)) return(EINVAL);
|
||||
|
||||
/* Copy parent 'proc' struct to child. */
|
||||
#if (CHIP == INTEL)
|
||||
old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
|
||||
#endif
|
||||
|
||||
*rpc = *rpp; /* copy 'proc' struct */
|
||||
|
||||
#if (CHIP == INTEL)
|
||||
rpc->p_ldt_sel = old_ldt_sel;
|
||||
#endif
|
||||
rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */
|
||||
rpc->p_ntf_q = NULL; /* remove pending notifications */
|
||||
|
||||
/* Only one in group should have SIGNALED, child doesn't inherit tracing. */
|
||||
rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */
|
||||
rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP);
|
||||
sigemptyset(&rpc->p_pending);
|
||||
|
||||
rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
|
||||
rpc->p_user_time = 0; /* set all the accounting times to 0 */
|
||||
rpc->p_sys_time = 0;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_FORK */
|
||||
|
||||
@@ -1,61 +1,3 @@
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <unistd.h>
|
||||
#include <minix/config.h>
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_unused *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_unused(m)
|
||||
message *m; /* pointer to request message */
|
||||
{
|
||||
kprintf("SYS task got illegal request from %d.", m->m_source);
|
||||
return(EBADREQUEST); /* illegal message type */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_ABORT
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: ABRT_HOW (how to abort, possibly fetch monitor params)
|
||||
* m1_i2: ABRT_MON_PROC (proc nr to get monitor params from)
|
||||
* m1_i3: ABRT_MON_LEN (length of monitor params)
|
||||
* m1_p1: ABRT_MON_ADDR (virtual address of params)
|
||||
*/
|
||||
|
||||
/*===========================================================================*
|
||||
* do_abort *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_abort(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_abort. MINIX is unable to continue. This can originate in the
|
||||
* PM (normal abort or panic) or FS (panic), or TTY (a CTRL-ALT-DEL or ESC
|
||||
* after debugging dumps).
|
||||
*/
|
||||
int how = m_ptr->ABRT_HOW;
|
||||
|
||||
if (how == RBT_MONITOR) {
|
||||
/* The monitor is to run the specified instructions. */
|
||||
int proc_nr = m_ptr->ABRT_MON_PROC;
|
||||
int length = m_ptr->ABRT_MON_LEN + 1;
|
||||
vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR;
|
||||
phys_bytes src_phys = numap_local(proc_nr, src_vir, length);
|
||||
|
||||
/* Validate length and address of shutdown code before copying. */
|
||||
if (length > kinfo.params_size || src_phys == 0)
|
||||
phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
|
||||
else
|
||||
phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
|
||||
}
|
||||
prepare_shutdown(how);
|
||||
return(OK); /* pro-forma (really EDISASTER) */
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_GETINFO
|
||||
*
|
||||
@@ -71,6 +13,10 @@ message *m_ptr; /* pointer to request message */
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
#if USE_GETINFO
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getinfo *
|
||||
*===========================================================================*/
|
||||
@@ -96,7 +42,7 @@ register message *m_ptr; /* pointer to request message */
|
||||
break;
|
||||
}
|
||||
case GET_IMAGE: {
|
||||
length = sizeof(struct system_image) * IMAGE_SIZE;
|
||||
length = sizeof(struct system_image) * NR_BOOT_PROCS;
|
||||
src_phys = vir2phys(image);
|
||||
break;
|
||||
}
|
||||
@@ -123,6 +69,11 @@ register message *m_ptr; /* pointer to request message */
|
||||
src_phys = vir2phys(proc);
|
||||
break;
|
||||
}
|
||||
case GET_PRIVTAB: {
|
||||
length = sizeof(struct priv) * (NR_SYS_PROCS);
|
||||
src_phys = vir2phys(priv);
|
||||
break;
|
||||
}
|
||||
case GET_PROC: {
|
||||
nr = (m_ptr->I_KEY_LEN == SELF) ? m_ptr->m_source : m_ptr->I_KEY_LEN;
|
||||
if (! isokprocn(nr)) return(EINVAL); /* validate request */
|
||||
@@ -147,7 +98,7 @@ register message *m_ptr; /* pointer to request message */
|
||||
src_phys = vir2phys(&kmess);
|
||||
break;
|
||||
}
|
||||
#if ENABLE_LOCK_TIMING
|
||||
#if DEBUG_TIME_LOCKS
|
||||
case GET_LOCKTIMING: {
|
||||
length = sizeof(timingdata);
|
||||
src_phys = vir2phys(timingdata);
|
||||
@@ -167,4 +118,5 @@ register message *m_ptr; /* pointer to request message */
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_GETINFO */
|
||||
|
||||
55
kernel/system/do_getksig.c
Normal file
55
kernel/system/do_getksig.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/* The system call that is implemented in this file:
|
||||
* SYS_SIGCTL # signal handling functionality
|
||||
*
|
||||
* The parameters and types for this system call are:
|
||||
* SIG_REQUEST # request to perform (long)
|
||||
* SIG_PROC # process to signal/ pending (int)
|
||||
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||
* SIG_MAP # bit map with pending signals (long)
|
||||
* SIG_NUMBER # signal number to send to process (int)
|
||||
*
|
||||
* Supported request types are in the parameter SIG_REQUEST:
|
||||
* S_GETSIG # get a pending kernel signal
|
||||
* S_ENDSIG # signal has been processed
|
||||
* S_SENDSIG # deliver a POSIX-style signal
|
||||
* S_SIGRETURN # return from a POSIX-style signal
|
||||
* S_KILL # send a signal to a process
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#include <sys/sigcontext.h>
|
||||
|
||||
#if USE_GETKSIG
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getksig *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_getksig(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* PM is ready to accept signals and repeatedly does a system call to get
|
||||
* one. Find a process with pending signals. If no signals are available,
|
||||
* return NONE in the process number field.
|
||||
*/
|
||||
register struct proc *rp;
|
||||
|
||||
/* 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;
|
||||
m_ptr->SIG_MAP = rp->p_pending;
|
||||
sigemptyset(&rp->p_pending); /* ball is in PM's court */
|
||||
rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */
|
||||
return(OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* No process with pending signals was found. */
|
||||
m_ptr->SIG_PROC = NONE;
|
||||
return(OK);
|
||||
}
|
||||
#endif /* USE_GETKSIG */
|
||||
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
#if USE_IRQCTL
|
||||
|
||||
/*===========================================================================*
|
||||
* do_irqctl *
|
||||
*===========================================================================*/
|
||||
@@ -95,3 +96,5 @@ register message *m_ptr; /* pointer to request message */
|
||||
return(r);
|
||||
}
|
||||
|
||||
#endif /* USE_IRQCTL */
|
||||
|
||||
41
kernel/system/do_kill.c
Normal file
41
kernel/system/do_kill.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/* The system call that is implemented in this file:
|
||||
* SYS_SIGCTL # signal handling functionality
|
||||
*
|
||||
* The parameters and types for this system call are:
|
||||
* SIG_REQUEST # request to perform (long)
|
||||
* SIG_PROC # process to signal/ pending (int)
|
||||
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||
* SIG_MAP # bit map with pending signals (long)
|
||||
* SIG_NUMBER # signal number to send to process (int)
|
||||
*
|
||||
* Supported request types are in the parameter SIG_REQUEST:
|
||||
* S_GETSIG # get a pending kernel signal
|
||||
* S_ENDSIG # signal has been processed
|
||||
* S_SENDSIG # deliver a POSIX-style signal
|
||||
* S_SIGRETURN # return from a POSIX-style signal
|
||||
* S_KILL # send a signal to a process
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#include <sys/sigcontext.h>
|
||||
|
||||
#if USE_KILL
|
||||
|
||||
/*===========================================================================*
|
||||
* do_kill *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_kill(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_kill(). Cause a signal to be sent to a process via PM.
|
||||
* Note that this has nothing to do with the kill (2) system call, this
|
||||
* is how the FS (and possibly other servers) get access to cause_sig.
|
||||
*/
|
||||
cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_KILL */
|
||||
|
||||
27
kernel/system/do_memset.c
Normal file
27
kernel/system/do_memset.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_MEMSET
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_l1: CP_SRC_ADDR (virtual address)
|
||||
* m5_l2: CP_DST_ADDR (returns physical address)
|
||||
* m5_l3: CP_NR_BYTES (size of datastructure)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
#if USE_MEMSET
|
||||
|
||||
/*===========================================================================*
|
||||
* do_memset *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_memset(m_ptr)
|
||||
register message *m_ptr;
|
||||
{
|
||||
/* Handle sys_memset(). */
|
||||
phys_zero((phys_bytes) m_ptr->MEM_PTR, (phys_bytes) m_ptr->MEM_COUNT);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_MEMSET */
|
||||
|
||||
|
||||
53
kernel/system/do_newmap.c
Normal file
53
kernel/system/do_newmap.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_NEWMAP
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (install new map for this process)
|
||||
* m1_p1: PR_MEM_PTR (pointer to memory map)
|
||||
*/
|
||||
#include "../system.h"
|
||||
|
||||
#if USE_NEWMAP
|
||||
|
||||
/*===========================================================================*
|
||||
* do_newmap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_newmap(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_newmap(). Fetch the memory map from PM. */
|
||||
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys;
|
||||
int caller; /* whose space has the new map (usually PM) */
|
||||
int k; /* process whose map is to be loaded */
|
||||
int old_flags; /* value of flags before modification */
|
||||
struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
|
||||
|
||||
/* Extract message parameters and copy new memory map from PM. */
|
||||
caller = m_ptr->m_source;
|
||||
k = m_ptr->PR_PROC_NR;
|
||||
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
|
||||
if (!isokprocn(k)) return(EINVAL);
|
||||
rp = proc_addr(k); /* ptr to entry of user getting new map */
|
||||
|
||||
/* Copy the map from PM. */
|
||||
src_phys = umap_local(proc_addr(caller), 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));
|
||||
|
||||
#if (CHIP != M68000)
|
||||
alloc_segments(rp);
|
||||
#else
|
||||
pmmu_init_proc(rp);
|
||||
#endif
|
||||
old_flags = rp->p_rts_flags; /* save the previous value of the flags */
|
||||
rp->p_rts_flags &= ~NO_MAP;
|
||||
if (old_flags != 0 && rp->p_rts_flags == 0) lock_ready(rp);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
#endif /* USE_NEWMAP */
|
||||
|
||||
|
||||
50
kernel/system/do_schedctl.c
Normal file
50
kernel/system/do_schedctl.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SCHEDCTL
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR process number to change priority
|
||||
* m1_i2: PR_PRIORITY the new priority
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <minix/type.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#if USE_SCHEDCTL
|
||||
|
||||
/*===========================================================================*
|
||||
* do_schedctl *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_schedctl(message *m_ptr)
|
||||
{
|
||||
int proc_nr, pri, new_q ;
|
||||
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);
|
||||
pri = m_ptr->PR_PRIORITY;
|
||||
if (pri < PRIO_MIN || pri > PRIO_MAX) return(EINVAL);
|
||||
|
||||
/* The priority is currently between PRIO_MIN and PRIO_MAX. We have to
|
||||
* scale this between MIN_USER_Q and MAX_USER_Q.
|
||||
*/
|
||||
new_q = MAX_USER_Q + (pri-PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) /
|
||||
(PRIO_MAX-PRIO_MIN+1);
|
||||
if (new_q < MAX_USER_Q) new_q = MAX_USER_Q; /* shouldn't happen */
|
||||
if (new_q > MIN_USER_Q) new_q = MIN_USER_Q; /* shouldn't happen */
|
||||
|
||||
/* Make sure the process is not running while changing its priority; the
|
||||
* max_priority is the base priority. Put the process back in its new
|
||||
* queue if it is runnable.
|
||||
*/
|
||||
rp = proc_addr(proc_nr);
|
||||
lock_unready(rp);
|
||||
rp->p_max_priority = rp->p_priority = new_q;
|
||||
if (! rp->p_rts_flags) lock_ready(rp);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_SCHEDCTL */
|
||||
|
||||
61
kernel/system/do_sdevio.c
Normal file
61
kernel/system/do_sdevio.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SDEVIO
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i3: DIO_REQUEST (request input or output)
|
||||
* m2_i1: DIO_TYPE (flag indicating byte, word, or long)
|
||||
* m2_l1: DIO_PORT (port to read/ write)
|
||||
* m2_p1: DIO_VEC_ADDR (virtual address of buffer)
|
||||
* m2_l2: DIO_VEC_SIZE (number of elements)
|
||||
* m2_i2: DIO_VEC_PROC (process where buffer is)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <minix/devio.h>
|
||||
|
||||
#if USE_SDEVIO
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sdevio *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_sdevio(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
int proc_nr = m_ptr->DIO_VEC_PROC;
|
||||
int count = m_ptr->DIO_VEC_SIZE;
|
||||
long port = m_ptr->DIO_PORT;
|
||||
phys_bytes phys_buf;
|
||||
|
||||
/* Check if process number is OK. */
|
||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr))
|
||||
return(EINVAL);
|
||||
|
||||
/* Get and check physical address. */
|
||||
if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
|
||||
return(EFAULT);
|
||||
|
||||
/* Perform device I/O for bytes and words. Longs are not supported. */
|
||||
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: phys_insb(port, phys_buf, count); break;
|
||||
case DIO_WORD: phys_insw(port, phys_buf, count); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
} else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) {
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: phys_outsb(port, phys_buf, count); break;
|
||||
case DIO_WORD: phys_outsw(port, phys_buf, count); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return(EINVAL);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_SDEVIO */
|
||||
|
||||
|
||||
|
||||
84
kernel/system/do_segctl.c
Normal file
84
kernel/system/do_segctl.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SEGCTL
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l3: SEG_PHYS (physical base address)
|
||||
* m4_l4: SEG_SIZE (size of segment)
|
||||
* m4_l1: SEG_SELECT (return segment selector here)
|
||||
* m4_l2: SEG_OFFSET (return offset within segment here)
|
||||
* m4_l5: SEG_INDEX (return index into remote memory map here)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
#include "../system.h"
|
||||
#include "../protect.h"
|
||||
|
||||
#if USE_SEGCTL
|
||||
|
||||
/*===========================================================================*
|
||||
* do_segctl *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_segctl(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Return a segment selector and offset that can be used to reach a physical
|
||||
* address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
|
||||
*/
|
||||
u16_t selector;
|
||||
vir_bytes offset;
|
||||
int i, index;
|
||||
register struct proc *rp;
|
||||
phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS;
|
||||
vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE;
|
||||
int result;
|
||||
|
||||
/* First check if there is a slot available for this segment. */
|
||||
rp = proc_addr(m_ptr->m_source);
|
||||
index = -1;
|
||||
for (i=0; i < NR_REMOTE_SEGS; i++) {
|
||||
if (! rp->p_priv->s_farmem[i].in_use) {
|
||||
index = i;
|
||||
rp->p_priv->s_farmem[i].in_use = TRUE;
|
||||
rp->p_priv->s_farmem[i].mem_phys = phys;
|
||||
rp->p_priv->s_farmem[i].mem_len = size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0) return(ENOSPC);
|
||||
|
||||
|
||||
if (! machine.protected) {
|
||||
selector = phys / HCLICK_SIZE;
|
||||
offset = phys % HCLICK_SIZE;
|
||||
result = OK;
|
||||
} else {
|
||||
/* Check if the segment size can be recorded in bytes, that is, check
|
||||
* if descriptor's limit field can delimited the allowed memory region
|
||||
* precisely. This works up to 1MB. If the size is larger, 4K pages
|
||||
* instead of bytes are used.
|
||||
*/
|
||||
if (size < BYTE_GRAN_MAX) {
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size,
|
||||
USER_PRIVILEGE);
|
||||
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
||||
offset = 0;
|
||||
result = OK;
|
||||
} else {
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0,
|
||||
USER_PRIVILEGE);
|
||||
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
||||
offset = phys & 0xFFFF;
|
||||
result = OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request successfully done. Now return the result. */
|
||||
m_ptr->SEG_INDEX = index | REMOTE_SEG;
|
||||
m_ptr->SEG_SELECT = selector;
|
||||
m_ptr->SEG_OFFSET = offset;
|
||||
return(result);
|
||||
}
|
||||
|
||||
#endif /* USE_SEGCTL */
|
||||
|
||||
79
kernel/system/do_sigreturn.c
Normal file
79
kernel/system/do_sigreturn.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/* The system call that is implemented in this file:
|
||||
* SYS_SIGCTL # signal handling functionality
|
||||
*
|
||||
* The parameters and types for this system call are:
|
||||
* SIG_REQUEST # request to perform (long)
|
||||
* SIG_PROC # process to signal/ pending (int)
|
||||
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||
* SIG_MAP # bit map with pending signals (long)
|
||||
* SIG_NUMBER # signal number to send to process (int)
|
||||
*
|
||||
* Supported request types are in the parameter SIG_REQUEST:
|
||||
* S_GETSIG # get a pending kernel signal
|
||||
* S_ENDSIG # signal has been processed
|
||||
* S_SENDSIG # deliver a POSIX-style signal
|
||||
* S_SIGRETURN # return from a POSIX-style signal
|
||||
* S_KILL # send a signal to a process
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#include <sys/sigcontext.h>
|
||||
|
||||
#if USE_SIGRETURN
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sigreturn *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_sigreturn(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* POSIX style signals require sys_sigreturn to put things in order before
|
||||
* the signalled process can resume execution
|
||||
*/
|
||||
struct sigcontext sc;
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys;
|
||||
|
||||
rp = proc_addr(m_ptr->SIG_PROC);
|
||||
|
||||
/* Copy in the sigcontext structure. */
|
||||
src_phys = umap_local(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
|
||||
(vir_bytes) sizeof(struct sigcontext));
|
||||
if (src_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
|
||||
|
||||
/* Make sure that this is not just a jump buffer. */
|
||||
if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
|
||||
|
||||
/* Fix up only certain key registers if the compiler doesn't use
|
||||
* register variables within functions containing setjmp.
|
||||
*/
|
||||
if (sc.sc_flags & SC_NOREGLOCALS) {
|
||||
rp->p_reg.retreg = sc.sc_retreg;
|
||||
rp->p_reg.fp = sc.sc_fp;
|
||||
rp->p_reg.pc = sc.sc_pc;
|
||||
rp->p_reg.sp = sc.sc_sp;
|
||||
return(OK);
|
||||
}
|
||||
sc.sc_psw = rp->p_reg.psw;
|
||||
|
||||
#if (CHIP == INTEL)
|
||||
/* Don't panic kernel if user gave bad selectors. */
|
||||
sc.sc_cs = rp->p_reg.cs;
|
||||
sc.sc_ds = rp->p_reg.ds;
|
||||
sc.sc_es = rp->p_reg.es;
|
||||
#if _WORD_SIZE == 4
|
||||
sc.sc_fs = rp->p_reg.fs;
|
||||
sc.sc_gs = rp->p_reg.gs;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Restore the registers. */
|
||||
kmemcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
|
||||
return(OK);
|
||||
}
|
||||
#endif /* USE_SIGRETURN */
|
||||
|
||||
|
||||
89
kernel/system/do_sigsend.c
Normal file
89
kernel/system/do_sigsend.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/* The system call that is implemented in this file:
|
||||
* SYS_SIGCTL # signal handling functionality
|
||||
*
|
||||
* The parameters and types for this system call are:
|
||||
* SIG_REQUEST # request to perform (long)
|
||||
* SIG_PROC # process to signal/ pending (int)
|
||||
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||
* SIG_MAP # bit map with pending signals (long)
|
||||
* SIG_NUMBER # signal number to send to process (int)
|
||||
*
|
||||
* Supported request types are in the parameter SIG_REQUEST:
|
||||
* S_GETSIG # get a pending kernel signal
|
||||
* S_ENDSIG # signal has been processed
|
||||
* S_SENDSIG # deliver a POSIX-style signal
|
||||
* S_SIGRETURN # return from a POSIX-style signal
|
||||
* S_KILL # send a signal to a process
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#include <sys/sigcontext.h>
|
||||
|
||||
#if USE_SIGSEND
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sigsend *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_sigsend(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_sigsend, POSIX-style signal handling. */
|
||||
|
||||
struct sigmsg smsg;
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys, dst_phys;
|
||||
struct sigcontext sc, *scp;
|
||||
struct sigframe fr, *frp;
|
||||
|
||||
rp = proc_addr(m_ptr->SIG_PROC);
|
||||
|
||||
/* Get the sigmsg structure into our address space. */
|
||||
src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes)
|
||||
m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg));
|
||||
if (src_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg));
|
||||
|
||||
/* Compute the user stack pointer where sigcontext will be stored. */
|
||||
scp = (struct sigcontext *) smsg.sm_stkptr - 1;
|
||||
|
||||
/* Copy the registers to the sigcontext structure. */
|
||||
kmemcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
|
||||
|
||||
/* Finish the sigcontext initialization. */
|
||||
sc.sc_flags = SC_SIGCONTEXT;
|
||||
sc.sc_mask = smsg.sm_mask;
|
||||
|
||||
/* Copy the sigcontext structure to the user's stack. */
|
||||
dst_phys = umap_local(rp, D, (vir_bytes) scp,
|
||||
(vir_bytes) sizeof(struct sigcontext));
|
||||
if (dst_phys == 0) return(EFAULT);
|
||||
phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
|
||||
|
||||
/* Initialize the sigframe structure. */
|
||||
frp = (struct sigframe *) scp - 1;
|
||||
fr.sf_scpcopy = scp;
|
||||
fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
|
||||
fr.sf_fp = rp->p_reg.fp;
|
||||
rp->p_reg.fp = (reg_t) &frp->sf_fp;
|
||||
fr.sf_scp = scp;
|
||||
fr.sf_code = 0; /* XXX - should be used for type of FP exception */
|
||||
fr.sf_signo = smsg.sm_signo;
|
||||
fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
|
||||
|
||||
/* Copy the sigframe structure to the user's stack. */
|
||||
dst_phys = umap_local(rp, D, (vir_bytes) frp,
|
||||
(vir_bytes) sizeof(struct sigframe));
|
||||
if (dst_phys == 0) return(EFAULT);
|
||||
phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
|
||||
|
||||
/* Reset user registers to execute the signal handler. */
|
||||
rp->p_reg.sp = (reg_t) frp;
|
||||
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_SIGSEND */
|
||||
|
||||
72
kernel/system/do_svrctl.c
Normal file
72
kernel/system/do_svrctl.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SVRCTL
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i1: CTL_PROC_NR (process number of caller)
|
||||
* m2_i2: CTL_REQUEST (request type)
|
||||
* m2_i3: CTL_MM_PRIV (privilege)
|
||||
* m2_l1: CTL_SEND_MASK (new send mask to be installed)
|
||||
* m2_l2: CTL_PROC_TYPE (new process type)
|
||||
* m2_p1: CTL_ARG_PTR (argument pointer)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include "../ipc.h"
|
||||
#include <sys/svrctl.h>
|
||||
|
||||
#if USE_SVRCTL
|
||||
|
||||
/* NOTE: this call will radically change! */
|
||||
|
||||
/*===========================================================================*
|
||||
* do_svrctl *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_svrctl(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
register struct proc *rp;
|
||||
register struct priv *sp;
|
||||
int proc_nr, rights;
|
||||
int request;
|
||||
vir_bytes argp;
|
||||
|
||||
/* Extract message parameters. */
|
||||
proc_nr = m_ptr->CTL_PROC_NR;
|
||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||
|
||||
request = m_ptr->CTL_REQUEST;
|
||||
rights = m_ptr->CTL_MM_PRIV;
|
||||
argp = (vir_bytes) m_ptr->CTL_ARG_PTR;
|
||||
rp = proc_addr(proc_nr);
|
||||
|
||||
/* Check if the PM privileges are super user. */
|
||||
if (!rights || !isuserp(rp))
|
||||
return(EPERM);
|
||||
|
||||
/* See what is requested and handle the request. */
|
||||
switch (request) {
|
||||
case SYSSIGNON: {
|
||||
/* Make this process a server. The system processes should be able
|
||||
* to communicate with this new server, so update their send masks
|
||||
* as well.
|
||||
*/
|
||||
|
||||
/* Find a new system privileges structure for this process. */
|
||||
for (sp=BEG_PRIV_ADDR; sp< END_PRIV_ADDR; sp++)
|
||||
if (sp->s_proc_nr == NONE) break;
|
||||
if (sp->s_proc_nr != NONE) return(ENOSPC);
|
||||
|
||||
/* Now update the process' privileges as requested. */
|
||||
rp->p_priv = sp; /* assign to process */
|
||||
rp->p_priv->s_proc_nr = proc_nr(rp); /* set association */
|
||||
rp->p_priv->s_call_mask = SYSTEM_CALL_MASK;
|
||||
return(OK);
|
||||
}
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USE_SVRCTL */
|
||||
|
||||
40
kernel/system/do_times.c
Normal file
40
kernel/system/do_times.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_TIMES
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l1: T_PROC_NR (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"
|
||||
|
||||
#if USE_TIMES
|
||||
|
||||
/*===========================================================================*
|
||||
* do_times *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_times(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_times(). Retrieve the accounting information. */
|
||||
register struct proc *rp;
|
||||
int proc_nr;
|
||||
|
||||
/* Insert the times needed by the SYS_TIMES system 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);
|
||||
m_ptr->T_USER_TIME = rp->p_user_time;
|
||||
m_ptr->T_SYSTEM_TIME = rp->p_sys_time;
|
||||
}
|
||||
m_ptr->T_BOOT_TICKS = get_uptime();
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_TIMES */
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
* m2_l2: CTL_DATA data to be written or returned here
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
#if USE_TRACE
|
||||
|
||||
/*==========================================================================*
|
||||
* do_trace *
|
||||
@@ -138,3 +138,4 @@ register message *m_ptr;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_TRACE */
|
||||
52
kernel/system/do_umap.c
Normal file
52
kernel/system/do_umap.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_UMAP
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_i1: CP_SRC_PROC_NR (process number)
|
||||
* m5_c1: CP_SRC_SPACE (segment where address is: T, D, or S)
|
||||
* m5_l1: CP_SRC_ADDR (virtual address)
|
||||
* m5_l2: CP_DST_ADDR (returns physical address)
|
||||
* m5_l3: CP_NR_BYTES (size of datastructure)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
#if USE_UMAP
|
||||
|
||||
/*==========================================================================*
|
||||
* do_umap *
|
||||
*==========================================================================*/
|
||||
PUBLIC int do_umap(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Map virtual address to physical, for non-kernel processes. */
|
||||
int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE;
|
||||
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;
|
||||
phys_bytes phys_addr;
|
||||
|
||||
/* Verify process number. */
|
||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||
|
||||
/* See which mapping should be made. */
|
||||
switch(seg_type) {
|
||||
case LOCAL_SEG:
|
||||
phys_addr = umap_local(proc_addr(proc_nr), seg_index, offset, count);
|
||||
break;
|
||||
case REMOTE_SEG:
|
||||
phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count);
|
||||
break;
|
||||
case BIOS_SEG:
|
||||
phys_addr = umap_bios(proc_addr(proc_nr), offset, count);
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
m_ptr->CP_DST_ADDR = phys_addr;
|
||||
return (phys_addr == 0) ? EFAULT: OK;
|
||||
}
|
||||
|
||||
#endif /* USE_UMAP */
|
||||
15
kernel/system/do_unused.c
Normal file
15
kernel/system/do_unused.c
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_unused *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_unused(m)
|
||||
message *m; /* pointer to request message */
|
||||
{
|
||||
kprintf("SYSTEM got unused request %d", m->m_type);
|
||||
kprintf("from %d.\n", m->m_source);
|
||||
return(EBADREQUEST); /* illegal message type */
|
||||
}
|
||||
|
||||
|
||||
67
kernel/system/do_vcopy.c
Normal file
67
kernel/system/do_vcopy.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VIRVCOPY, SYS_PHYSVCOPY
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_c1: CP_SRC_SPACE
|
||||
* m5_l1: CP_SRC_ADDR
|
||||
* m5_i1: CP_SRC_PROC_NR
|
||||
* m5_c2: CP_DST_SPACE
|
||||
* m5_l2: CP_DST_ADDR
|
||||
* m5_i2: CP_DST_PROC_NR
|
||||
* m5_l3: CP_NR_BYTES
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <minix/type.h>
|
||||
|
||||
#if (USE_VIRVCOPY || USE_PHYSVCOPY)
|
||||
|
||||
/* Buffer to hold copy request vector from user. */
|
||||
PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE];
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vcopy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_vcopy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */
|
||||
int nr_req;
|
||||
int caller_pid;
|
||||
vir_bytes caller_vir;
|
||||
phys_bytes caller_phys;
|
||||
phys_bytes kernel_phys;
|
||||
phys_bytes bytes;
|
||||
int i,s;
|
||||
struct vir_cp_req *req;
|
||||
|
||||
/* Check if request vector size is ok. */
|
||||
nr_req = (unsigned) m_ptr->VCP_VEC_SIZE;
|
||||
if (nr_req > VCOPY_VEC_SIZE) return(EINVAL);
|
||||
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);
|
||||
if (0 == caller_phys) return(EFAULT);
|
||||
kernel_phys = vir2phys(vir_cp_req);
|
||||
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
|
||||
|
||||
/* Assume vector with requests is correct. Try to copy everything. */
|
||||
for (i=0; i<nr_req; i++) {
|
||||
|
||||
req = &vir_cp_req[i];
|
||||
|
||||
/* Check if physical addressing is used without SYS_PHYSVCOPY. */
|
||||
if (((req->src.segment | req->dst.segment) & PHYS_SEG) &&
|
||||
m_ptr->m_type != SYS_PHYSVCOPY)
|
||||
return(EPERM);
|
||||
if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK)
|
||||
return(s);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* (USE_VIRVCOPY || USE_PHYSVCOPY) */
|
||||
|
||||
@@ -1,100 +1,3 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_DEVIO
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i3: DIO_REQUEST (request input or output)
|
||||
* m2_i1: DIO_TYPE (flag indicating byte, word, or long)
|
||||
* m2_l1: DIO_PORT (port to read/ write)
|
||||
* m2_l2: DIO_VALUE (value to write/ return value read)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include "../debug.h"
|
||||
#include <minix/devio.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* do_devio *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_devio(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* perform actual device I/O for byte, word, and long values */
|
||||
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break;
|
||||
case DIO_WORD: m_ptr->DIO_VALUE = inw(m_ptr->DIO_PORT); break;
|
||||
case DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
} else {
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
case DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
case DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SDEVIO
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i3: DIO_REQUEST (request input or output)
|
||||
* m2_i1: DIO_TYPE (flag indicating byte, word, or long)
|
||||
* m2_l1: DIO_PORT (port to read/ write)
|
||||
* m2_p1: DIO_VEC_ADDR (virtual address of buffer)
|
||||
* m2_l2: DIO_VEC_SIZE (number of elements)
|
||||
* m2_i2: DIO_VEC_PROC (process where buffer is)
|
||||
*/
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sdevio *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_sdevio(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
int proc_nr = m_ptr->DIO_VEC_PROC;
|
||||
int count = m_ptr->DIO_VEC_SIZE;
|
||||
long port = m_ptr->DIO_PORT;
|
||||
phys_bytes phys_buf;
|
||||
|
||||
/* Check if process number is OK. */
|
||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr))
|
||||
return(EINVAL);
|
||||
|
||||
/* Get and check physical address. */
|
||||
if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
|
||||
return(EFAULT);
|
||||
|
||||
/* Perform device I/O for bytes and words. Longs are not supported. */
|
||||
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: phys_insb(port, phys_buf, count); break;
|
||||
case DIO_WORD: phys_insw(port, phys_buf, count); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
} else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) {
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: phys_outsb(port, phys_buf, count); break;
|
||||
case DIO_WORD: phys_outsw(port, phys_buf, count); break;
|
||||
default: return(EINVAL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return(EINVAL);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VDEVIO
|
||||
*
|
||||
@@ -105,6 +8,12 @@ register message *m_ptr; /* pointer to request message */
|
||||
* m2_i2: DIO_VEC_SIZE (number of ports to read or write)
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include <minix/devio.h>
|
||||
|
||||
#if USE_VDEVIO
|
||||
|
||||
|
||||
/* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
|
||||
PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE];
|
||||
|
||||
@@ -213,4 +122,5 @@ register message *m_ptr; /* pointer to request message */
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* USE_VDEVIO */
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SETPRIORITY
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: which
|
||||
* m1_i2: who
|
||||
* m1_i3: prio
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <minix/type.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* do_setpriority *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_setpriority(message *m_ptr)
|
||||
{
|
||||
int which_proc, pri, q, niceperq;
|
||||
struct proc *which_procp;
|
||||
|
||||
which_proc = m_ptr->m1_i1;
|
||||
pri = m_ptr->m1_i2;
|
||||
|
||||
/* pri is currently between PRIO_MIN and PRIO_MAX. We have to
|
||||
* scale this between MIN_USER_Q and MAX_USER_Q.
|
||||
*/
|
||||
|
||||
if(pri < PRIO_MIN || pri > PRIO_MAX)
|
||||
return EINVAL;
|
||||
|
||||
if(which_proc < 0 || which_proc >= NR_TASKS+NR_PROCS)
|
||||
return EINVAL;
|
||||
|
||||
which_procp = proc_addr(which_proc);
|
||||
|
||||
q = MAX_USER_Q + (pri - PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) / (PRIO_MAX-PRIO_MIN+1);
|
||||
|
||||
/* The below shouldn't happen. */
|
||||
if(q < MAX_USER_Q) q = MAX_USER_Q;
|
||||
if(q > MIN_USER_Q) q = MIN_USER_Q;
|
||||
|
||||
/* max_priority is the base priority. */
|
||||
which_procp->p_max_priority = q;
|
||||
lock_unready(which_procp);
|
||||
which_procp->p_priority = q;
|
||||
|
||||
/* Runnable? Put it (back) on its new run queue. */
|
||||
if(!which_procp->p_rts_flags)
|
||||
lock_ready(which_procp);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_FORK
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (child's process table slot)
|
||||
* m1_i2: PR_PPROC_NR (parent, process that forked)
|
||||
* m1_i3: PR_PID (child pid received from PM)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include "../sendmask.h"
|
||||
#include <signal.h>
|
||||
#if (CHIP == INTEL)
|
||||
#include "../protect.h"
|
||||
#endif
|
||||
#include "../debug.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_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. */
|
||||
|
||||
#if (CHIP == INTEL)
|
||||
reg_t old_ldt_sel;
|
||||
#endif
|
||||
register struct proc *rpc;
|
||||
struct proc *rpp;
|
||||
|
||||
rpp = proc_addr(m_ptr->PR_PPROC_NR);
|
||||
rpc = proc_addr(m_ptr->PR_PROC_NR);
|
||||
if (! isemptyp(rpc)) return(EINVAL);
|
||||
|
||||
/* Copy parent 'proc' struct to child. */
|
||||
#if (CHIP == INTEL)
|
||||
old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
|
||||
#endif
|
||||
|
||||
*rpc = *rpp; /* copy 'proc' struct */
|
||||
|
||||
#if (CHIP == INTEL)
|
||||
rpc->p_ldt_sel = old_ldt_sel;
|
||||
#endif
|
||||
rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */
|
||||
rpc->p_ntf_q = NULL; /* remove pending notifications */
|
||||
|
||||
/* Only one in group should have SIGNALED, child doesn't inherit tracing. */
|
||||
rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */
|
||||
rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP);
|
||||
sigemptyset(&rpc->p_pending);
|
||||
|
||||
rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
|
||||
rpc->p_user_time = 0; /* set all the accounting times to 0 */
|
||||
rpc->p_sys_time = 0;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_NEWMAP
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (install new map for this process)
|
||||
* m1_p1: PR_MEM_PTR (pointer to memory map)
|
||||
*/
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_newmap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_newmap(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_newmap(). Fetch the memory map from PM. */
|
||||
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys;
|
||||
int caller; /* whose space has the new map (usually PM) */
|
||||
int k; /* process whose map is to be loaded */
|
||||
int old_flags; /* value of flags before modification */
|
||||
struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
|
||||
|
||||
/* Extract message parameters and copy new memory map from PM. */
|
||||
caller = m_ptr->m_source;
|
||||
k = m_ptr->PR_PROC_NR;
|
||||
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
|
||||
if (!isokprocn(k)) return(EINVAL);
|
||||
rp = proc_addr(k); /* ptr to entry of user getting new map */
|
||||
|
||||
/* Copy the map from PM. */
|
||||
src_phys = umap_local(proc_addr(caller), 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));
|
||||
|
||||
#if (CHIP != M68000)
|
||||
alloc_segments(rp);
|
||||
#else
|
||||
pmmu_init_proc(rp);
|
||||
#endif
|
||||
old_flags = rp->p_rts_flags; /* save the previous value of the flags */
|
||||
rp->p_rts_flags &= ~NO_MAP;
|
||||
if (old_flags != 0 && rp->p_rts_flags == 0) lock_ready(rp);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_EXEC
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (process that did exec call)
|
||||
* m1_i3: PR_TRACING (flag to indicate tracing is on/ off)
|
||||
* 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)
|
||||
*/
|
||||
|
||||
/*===========================================================================*
|
||||
* do_exec *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_exec(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */
|
||||
|
||||
register struct proc *rp;
|
||||
reg_t sp; /* new sp */
|
||||
phys_bytes phys_name;
|
||||
char *np;
|
||||
|
||||
rp = proc_addr(m_ptr->PR_PROC_NR);
|
||||
if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP);
|
||||
sp = (reg_t) m_ptr->PR_STACK_PTR;
|
||||
rp->p_reg.sp = sp; /* set the stack pointer */
|
||||
#if (CHIP == M68000)
|
||||
rp->p_splow = sp; /* set the stack pointer low water */
|
||||
#ifdef FPP
|
||||
/* Initialize fpp for this process */
|
||||
fpp_new_state(rp);
|
||||
#endif
|
||||
#endif
|
||||
#if (CHIP == INTEL) /* wipe extra LDT entries */
|
||||
kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0,
|
||||
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
|
||||
#endif
|
||||
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_ready(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,
|
||||
(vir_bytes) P_NAME_LEN - 1);
|
||||
if (phys_name != 0) {
|
||||
phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1);
|
||||
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
|
||||
*np = 0; /* mark end */
|
||||
} else {
|
||||
kstrncpy(rp->p_name, "<unset>", P_NAME_LEN);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_XIT
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (slot number of exiting process)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_xit *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_xit(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_exit. A user process has exited or a system process requests
|
||||
* to exit. Only the PM can request other process slots to be cleared.
|
||||
* The routine to clean up a process table slot cancels outstanding timers,
|
||||
* possibly removes the process from the message queues, and resets certain
|
||||
* process table fields to the default values.
|
||||
*/
|
||||
int exit_proc_nr;
|
||||
|
||||
/* Determine what process exited. */
|
||||
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(exit_proc_nr); /* exit a user process */
|
||||
return(OK); /* report back to PM */
|
||||
}
|
||||
}
|
||||
|
||||
/* The PM or some other system process requested to be exited. */
|
||||
clear_proc(m_ptr->m_source);
|
||||
return(EDONTREPLY);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
/* The system call that is implemented in this file:
|
||||
* SYS_SIGCTL # signal handling functionality
|
||||
*
|
||||
* The parameters and types for this system call are:
|
||||
* SIG_REQUEST # request to perform (long)
|
||||
* SIG_PROC # process to signal/ pending (int)
|
||||
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||
* SIG_MAP # bit map with pending signals (long)
|
||||
* SIG_NUMBER # signal number to send to process (int)
|
||||
*
|
||||
* Supported request types are in the parameter SIG_REQUEST:
|
||||
* S_GETSIG # get a pending kernel signal
|
||||
* S_ENDSIG # signal has been processed
|
||||
* S_SENDSIG # deliver a POSIX-style signal
|
||||
* S_SIGRETURN # return from a POSIX-style signal
|
||||
* S_KILL # send a signal to a process
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#include <sys/sigcontext.h>
|
||||
|
||||
/* PM is ready to accept signals and repeatedly does a system call to get
|
||||
* one. Find a process with pending signals. If no signals are available,
|
||||
* return NONE in the process number field.
|
||||
*/
|
||||
PUBLIC int do_getsig(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
register struct proc *rp;
|
||||
|
||||
/* 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;
|
||||
m_ptr->SIG_MAP = rp->p_pending;
|
||||
sigemptyset(&rp->p_pending); /* ball is in PM's court */
|
||||
rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */
|
||||
return(OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* No process with pending signals was found. */
|
||||
m_ptr->SIG_PROC = NONE;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
PUBLIC int do_endsig(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Finish up after a kernel type signal, caused by a SYS_KILL message or a
|
||||
* call to cause_sig by a task. This is called by the PM after processing a
|
||||
* signal it got with SYS_GETSIG.
|
||||
*/
|
||||
register struct proc *rp;
|
||||
|
||||
rp = proc_addr(m_ptr->SIG_PROC);
|
||||
if (isemptyp(rp)) return(EINVAL); /* process already dead? */
|
||||
|
||||
/* PM has finished one kernel signal. Perhaps process is ready now? */
|
||||
if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */
|
||||
if ((rp->p_rts_flags &= ~SIG_PENDING)==0) /* remove pending flag */
|
||||
lock_ready(rp); /* ready if no flags */
|
||||
return(OK);
|
||||
}
|
||||
|
||||
PUBLIC int do_sigsend(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_sigsend, POSIX-style signal handling. */
|
||||
|
||||
struct sigmsg smsg;
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys, dst_phys;
|
||||
struct sigcontext sc, *scp;
|
||||
struct sigframe fr, *frp;
|
||||
|
||||
rp = proc_addr(m_ptr->SIG_PROC);
|
||||
|
||||
/* Get the sigmsg structure into our address space. */
|
||||
src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes)
|
||||
m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg));
|
||||
if (src_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg));
|
||||
|
||||
/* Compute the user stack pointer where sigcontext will be stored. */
|
||||
scp = (struct sigcontext *) smsg.sm_stkptr - 1;
|
||||
|
||||
/* Copy the registers to the sigcontext structure. */
|
||||
kmemcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
|
||||
|
||||
/* Finish the sigcontext initialization. */
|
||||
sc.sc_flags = SC_SIGCONTEXT;
|
||||
sc.sc_mask = smsg.sm_mask;
|
||||
|
||||
/* Copy the sigcontext structure to the user's stack. */
|
||||
dst_phys = umap_local(rp, D, (vir_bytes) scp,
|
||||
(vir_bytes) sizeof(struct sigcontext));
|
||||
if (dst_phys == 0) return(EFAULT);
|
||||
phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
|
||||
|
||||
/* Initialize the sigframe structure. */
|
||||
frp = (struct sigframe *) scp - 1;
|
||||
fr.sf_scpcopy = scp;
|
||||
fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
|
||||
fr.sf_fp = rp->p_reg.fp;
|
||||
rp->p_reg.fp = (reg_t) &frp->sf_fp;
|
||||
fr.sf_scp = scp;
|
||||
fr.sf_code = 0; /* XXX - should be used for type of FP exception */
|
||||
fr.sf_signo = smsg.sm_signo;
|
||||
fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
|
||||
|
||||
/* Copy the sigframe structure to the user's stack. */
|
||||
dst_phys = umap_local(rp, D, (vir_bytes) frp,
|
||||
(vir_bytes) sizeof(struct sigframe));
|
||||
if (dst_phys == 0) return(EFAULT);
|
||||
phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
|
||||
|
||||
/* Reset user registers to execute the signal handler. */
|
||||
rp->p_reg.sp = (reg_t) frp;
|
||||
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
PUBLIC int do_sigreturn(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* POSIX style signals require sys_sigreturn to put things in order before
|
||||
* the signalled process can resume execution
|
||||
*/
|
||||
struct sigcontext sc;
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys;
|
||||
|
||||
rp = proc_addr(m_ptr->SIG_PROC);
|
||||
|
||||
/* Copy in the sigcontext structure. */
|
||||
src_phys = umap_local(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
|
||||
(vir_bytes) sizeof(struct sigcontext));
|
||||
if (src_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
|
||||
|
||||
/* Make sure that this is not just a jmp_buf. */
|
||||
if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
|
||||
|
||||
/* Fix up only certain key registers if the compiler doesn't use
|
||||
* register variables within functions containing setjmp.
|
||||
*/
|
||||
if (sc.sc_flags & SC_NOREGLOCALS) {
|
||||
rp->p_reg.retreg = sc.sc_retreg;
|
||||
rp->p_reg.fp = sc.sc_fp;
|
||||
rp->p_reg.pc = sc.sc_pc;
|
||||
rp->p_reg.sp = sc.sc_sp;
|
||||
return(OK);
|
||||
}
|
||||
sc.sc_psw = rp->p_reg.psw;
|
||||
|
||||
#if (CHIP == INTEL)
|
||||
/* Don't panic kernel if user gave bad selectors. */
|
||||
sc.sc_cs = rp->p_reg.cs;
|
||||
sc.sc_ds = rp->p_reg.ds;
|
||||
sc.sc_es = rp->p_reg.es;
|
||||
#if _WORD_SIZE == 4
|
||||
sc.sc_fs = rp->p_reg.fs;
|
||||
sc.sc_gs = rp->p_reg.gs;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Restore the registers. */
|
||||
kmemcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sigctl *
|
||||
*===========================================================================*/
|
||||
|
||||
PUBLIC int do_kill(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_kill(). Cause a signal to be sent to a process via PM.
|
||||
* Note that this has nothing to do with the kill (2) system call, this
|
||||
* is how the FS (and possibly other servers) get access to cause_sig.
|
||||
*/
|
||||
cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
#include "../kernel.h"
|
||||
#include "../ipc.h"
|
||||
#include "../system.h"
|
||||
#include "../protect.h"
|
||||
#include <sys/svrctl.h>
|
||||
#include "../sendmask.h"
|
||||
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SVRCTL
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i1: CTL_PROC_NR (process number of caller)
|
||||
* m2_i2: CTL_REQUEST (request type)
|
||||
* m2_i3: CTL_MM_PRIV (privilege)
|
||||
* m2_l1: CTL_SEND_MASK (new send mask to be installed)
|
||||
* m2_l2: CTL_PROC_TYPE (new process type)
|
||||
* m2_p1: CTL_ARG_PTR (argument pointer)
|
||||
*/
|
||||
|
||||
/* NOTE: this call will radically change! */
|
||||
|
||||
/*===========================================================================*
|
||||
* do_svrctl *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_svrctl(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
register struct proc *rp;
|
||||
int proc_nr, priv;
|
||||
int request;
|
||||
vir_bytes argp;
|
||||
|
||||
/* Extract message parameters. */
|
||||
proc_nr = m_ptr->CTL_PROC_NR;
|
||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||
|
||||
request = m_ptr->CTL_REQUEST;
|
||||
priv = m_ptr->CTL_MM_PRIV;
|
||||
argp = (vir_bytes) m_ptr->CTL_ARG_PTR;
|
||||
rp = proc_addr(proc_nr);
|
||||
|
||||
/* Check if the PM privileges are super user. */
|
||||
if (!priv || !isuserp(rp))
|
||||
return(EPERM);
|
||||
|
||||
/* See what is requested and handle the request. */
|
||||
switch (request) {
|
||||
case SYSSIGNON: {
|
||||
/* Make this process a server. The system processes should be able
|
||||
* to communicate with this new server, so update their send masks
|
||||
* as well.
|
||||
*/
|
||||
/* fall through */
|
||||
}
|
||||
case SYSSENDMASK: {
|
||||
rp->p_call_mask = SYSTEM_CALL_MASK;
|
||||
rp->p_sendmask = ALLOW_ALL_MASK;
|
||||
send_mask_allow(proc_addr(USR8139)->p_sendmask, proc_nr);
|
||||
send_mask_allow(proc_addr(PM_PROC_NR)->p_sendmask, proc_nr);
|
||||
send_mask_allow(proc_addr(FS_PROC_NR)->p_sendmask, proc_nr);
|
||||
send_mask_allow(proc_addr(IS_PROC_NR)->p_sendmask, proc_nr);
|
||||
send_mask_allow(proc_addr(CLOCK)->p_sendmask, proc_nr);
|
||||
send_mask_allow(proc_addr(SYSTASK)->p_sendmask, proc_nr);
|
||||
send_mask_allow(proc_addr(FXP)->p_sendmask, proc_nr);
|
||||
return(OK);
|
||||
}
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SEGCTL
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l3: SEG_PHYS (physical base address)
|
||||
* m4_l4: SEG_SIZE (size of segment)
|
||||
* m4_l1: SEG_SELECT (return segment selector here)
|
||||
* m4_l2: SEG_OFFSET (return offset within segment here)
|
||||
* m4_l5: SEG_INDEX (return index into remote memory map here)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
/*===========================================================================*
|
||||
* do_segctl *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_segctl(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Return a segment selector and offset that can be used to reach a physical
|
||||
* address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
|
||||
*/
|
||||
u16_t selector;
|
||||
vir_bytes offset;
|
||||
int i, index;
|
||||
register struct proc *rp;
|
||||
phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS;
|
||||
vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE;
|
||||
int result;
|
||||
|
||||
/* First check if there is a slot available for this segment. */
|
||||
rp = proc_addr(m_ptr->m_source);
|
||||
index = -1;
|
||||
for (i=0; i < NR_REMOTE_SEGS; i++) {
|
||||
if (! rp->p_farmem[i].in_use) {
|
||||
index = i;
|
||||
rp->p_farmem[i].in_use = TRUE;
|
||||
rp->p_farmem[i].mem_phys = phys;
|
||||
rp->p_farmem[i].mem_len = size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0) return(ENOSPC);
|
||||
|
||||
|
||||
if (! machine.protected) {
|
||||
selector = phys / HCLICK_SIZE;
|
||||
offset = phys % HCLICK_SIZE;
|
||||
result = OK;
|
||||
} else {
|
||||
/* Check if the segment size can be recorded in bytes, that is, check
|
||||
* if descriptor's limit field can delimited the allowed memory region
|
||||
* precisely. This works up to 1MB. If the size is larger, 4K pages
|
||||
* instead of bytes are used.
|
||||
*/
|
||||
if (size < BYTE_GRAN_MAX) {
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size,
|
||||
USER_PRIVILEGE);
|
||||
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
||||
offset = 0;
|
||||
result = OK;
|
||||
} else {
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0,
|
||||
USER_PRIVILEGE);
|
||||
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
||||
offset = phys & 0xFFFF;
|
||||
result = OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request successfully done. Now return the result. */
|
||||
m_ptr->SEG_INDEX = index | REMOTE_SEG;
|
||||
m_ptr->SEG_SELECT = selector;
|
||||
m_ptr->SEG_OFFSET = offset;
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_IOPENABLE
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i2: PROC_NR (process to give I/O Protection Level bits)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
/*===========================================================================*
|
||||
* do_iopenable *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_iopenable(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
#if ENABLE_USERPRIV && ENABLE_USERIOPL
|
||||
enable_iop(proc_addr(m_ptr->PROC_NR));
|
||||
return(OK);
|
||||
#else
|
||||
return(EPERM);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user