Initial revision
This commit is contained in:
58
kernel/system/Makefile
Normal file
58
kernel/system/Makefile
Normal file
@@ -0,0 +1,58 @@
|
||||
# Makefile for system library implementation
|
||||
|
||||
# Directories
|
||||
u = /usr
|
||||
i = $u/include
|
||||
s = $i/sys
|
||||
h = $i/minix
|
||||
m = $i/ibm
|
||||
l = $u/lib
|
||||
n = $i/net
|
||||
g = $n/gen
|
||||
x = .
|
||||
k = ..
|
||||
|
||||
# Programs, flags, etc.
|
||||
CC = exec cc
|
||||
CPP = $l/cpp
|
||||
LD = $(CC) -.o
|
||||
CFLAGS = -I$i
|
||||
LDFLAGS = -i
|
||||
|
||||
SYS = alarms.o copying.o debugging.o devio.o irqctl.o proctl.o \
|
||||
srvrctl.o misc.o sigctl.o tracing.o \
|
||||
do_copy.o do_vcopy.o
|
||||
|
||||
# What to make.
|
||||
all build: $(SYS)
|
||||
aal cr system.a $(SYS)
|
||||
|
||||
clean:
|
||||
rm -f *.a *.o *.bak
|
||||
|
||||
# Dependencies from src/kernel/kernel.h
|
||||
a = $h/config.h $h/const.h $h/type.h $h/ipc.h \
|
||||
$i/string.h $i/limits.h $i/errno.h $i/stddef.h \
|
||||
$s/types.h \
|
||||
$m/portio.h \
|
||||
$k/proc.h $k/const.h $k/type.h $k/proto.h $k/glo.h
|
||||
|
||||
# Dependencies from src/kernel/system.h
|
||||
b = $k/system.h $h/com.h $k/proc.h $k/assert.h
|
||||
|
||||
alarms.o: $a $b
|
||||
copying.o: $a $b
|
||||
debugging.o: $a $b
|
||||
devio.o: $a $b $h/devio.h
|
||||
irqctl.o: $a $b
|
||||
misc.o: $a $b $i/unistd.h
|
||||
proctl.o: $a $b $k/sendmask.h $k/protect.h $i/signal.h
|
||||
sigctl.o: $a $b $i/signal.h $s/sigcontext.h
|
||||
srvrctl.o: $a $b $s/svrctl.h $k/sendmask.h
|
||||
tracing.o: $a $b $s/ptrace.h
|
||||
|
||||
do_copy.o: $a $b
|
||||
do_vcopy.o: $a $b
|
||||
|
||||
|
||||
|
||||
130
kernel/system/alarms.c
Normal file
130
kernel/system/alarms.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: CLK_SIGNALRM, CLK_SYNCALRM, CLK_FLAGALRM
|
||||
*
|
||||
* 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)
|
||||
* m2_p1: ALRM_FLAG_PTR (virtual addr of alarm flag)
|
||||
*
|
||||
* Changes:
|
||||
* Aug 25, 2004 fully rewritten to unite all alarms (Jorrit N. Herder)
|
||||
* May 02, 2004 added new timeout flag alarm (Jorrit N. Herder)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
|
||||
FORWARD _PROTOTYPE( void cause_syncalrm, (timer_t *tp) );
|
||||
FORWARD _PROTOTYPE( void cause_flagalrm, (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 all of SYS_SIGNALRM, SYS_SYNCALRM, and SYS_FLAGALRM.
|
||||
*/
|
||||
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. */
|
||||
switch (m_ptr->m_type) {
|
||||
case SYS_SYNCALRM: /* notify with SYN_ALARM message */
|
||||
tp = &(proc_addr(proc_nr)->p_syncalrm);
|
||||
tmr_arg(tp)->ta_int = proc_nr;
|
||||
tp->tmr_func = cause_syncalrm;
|
||||
break;
|
||||
case SYS_SIGNALRM: /* send process a SIGALRM signal */
|
||||
tp = &(proc_addr(proc_nr)->p_signalrm);
|
||||
tmr_arg(tp)->ta_int = proc_nr;
|
||||
tp->tmr_func = cause_signalrm;
|
||||
break;
|
||||
case SYS_FLAGALRM: /* set caller's timeout flag to 1 */
|
||||
tp = &(proc_addr(proc_nr)->p_flagalrm);
|
||||
tmr_arg(tp)->ta_long =
|
||||
numap_local(proc_nr,(vir_bytes) m_ptr->ALRM_FLAG_PTR,sizeof(int));
|
||||
if (! tmr_arg(tp)->ta_long) return(EFAULT);
|
||||
tp->tmr_func = cause_flagalrm;
|
||||
break;
|
||||
default: /* invalid alarm type */
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* 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_flagalrm *
|
||||
*===========================================================================*/
|
||||
PRIVATE void cause_flagalrm(tp)
|
||||
timer_t *tp;
|
||||
{
|
||||
/* Routine called if a timer goes off for a process that requested a timeout
|
||||
* flag to be set when the alarm expires. The timer argument 'ta_long' gives
|
||||
* the physical address of the timeout flag. No validity check was done when
|
||||
* setting the alarm, so check for 0 here.
|
||||
*/
|
||||
int timeout = 1;
|
||||
phys_bytes timeout_flag = (phys_bytes) tmr_arg(tp)->ta_long;
|
||||
phys_copy(vir2phys(&timeout), tmr_arg(tp)->ta_long, sizeof(int));
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* 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.
|
||||
*/
|
||||
notify(tmr_arg(tp)->ta_int, SYN_ALARM);
|
||||
}
|
||||
|
||||
|
||||
133
kernel/system/copying.c
Normal file
133
kernel/system/copying.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VIRCOPY
|
||||
*
|
||||
* 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"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vircopy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_vircopy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_vircopy(). Copy data by using virtual 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)) {
|
||||
kprintf("do_vircopy: illegal proc nr\n",NO_ARG);
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Copying from or to special segments can only done by the owner. */
|
||||
if ((vir_addr[i].segment & SEGMENT_TYPE) != LOCAL_SEG &&
|
||||
vir_addr[i].proc_nr != m_ptr->m_source) {
|
||||
kprintf("do_vircopy: special seg permission denied\n", NO_ARG);
|
||||
return(EPERM);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for overflow. This would happen for 64K segments and 16-bit
|
||||
* vir_bytes. Especially copying by the MM on do_fork() is affected.
|
||||
*/
|
||||
if (bytes != (vir_bytes) bytes) {
|
||||
kprintf("do_vircopy: overflow\n", NO_ARG);
|
||||
return(E2BIG);
|
||||
}
|
||||
|
||||
/* Now try to make the actual virtual copy. */
|
||||
return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_PHYSCOPY
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_l1: CP_SRC_ADDR (physical source address)
|
||||
* m5_l2: CP_DST_ADDR (physical destination address)
|
||||
* m5_l3: CP_NR_BYTES (number of bytes to copy)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
/*===========================================================================*
|
||||
* do_physcopy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_physcopy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_physcopy(). Copy data by using physical addressing. */
|
||||
|
||||
phys_bytes src_phys, dst_phys, bytes;
|
||||
|
||||
/* Dismember the command message. */
|
||||
src_phys = (phys_bytes) m_ptr->CP_SRC_ADDR;
|
||||
dst_phys = (phys_bytes) m_ptr->CP_DST_ADDR;
|
||||
bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
|
||||
|
||||
/* Do some checks and copy the data. */
|
||||
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, dst_phys, bytes);
|
||||
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 */
|
||||
{
|
||||
/* Same as umap_local(), for non-kernel processes. */
|
||||
int proc_nr = (int) m_ptr->CP_SRC_PROC_NR;
|
||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||
|
||||
m_ptr->CP_DST_ADDR = umap_local(proc_addr(proc_nr),
|
||||
(int) m_ptr->CP_SRC_SPACE,
|
||||
(vir_bytes) m_ptr->CP_SRC_ADDR,
|
||||
(vir_bytes) m_ptr->CP_NR_BYTES);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
16
kernel/system/debugging.c
Normal file
16
kernel/system/debugging.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_DEBUG
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
#if ENABLE_K_DEBUGGING /* only include code if enabled */
|
||||
|
||||
/*==========================================================================*
|
||||
* do_debug *
|
||||
*==========================================================================*/
|
||||
|
||||
#endif /* ENABLE_K_DEBUGGING */
|
||||
215
kernel/system/devio.c
Normal file
215
kernel/system/devio.c
Normal file
@@ -0,0 +1,215 @@
|
||||
/* 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 <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
|
||||
*
|
||||
* 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_p1: DIO_VEC_ADDR (pointer to port/ value pairs)
|
||||
* m2_i2: DIO_VEC_SIZE (number of ports to read or write)
|
||||
*/
|
||||
|
||||
/* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
|
||||
PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE];
|
||||
|
||||
/* SYS_VDEVIO sends a pointer to a (port,value)-pairs vector at the caller.
|
||||
* Define the maximum number of (port,value)-pairs that can be handled in a
|
||||
* in a single SYS_VDEVIO system call based on the struct definitions.
|
||||
*/
|
||||
#define MAX_PVB_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvb_pair_t))
|
||||
#define MAX_PVW_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvw_pair_t))
|
||||
#define MAX_PVL_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvl_pair_t))
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vdevio *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_vdevio(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Perform a series of device I/O on behalf of a non-kernel process. The
|
||||
* I/O addresses and I/O values are fetched from and returned to some buffer
|
||||
* in user space. The actual I/O is wrapped by lock() and unlock() to prevent
|
||||
* that I/O batch from being interrrupted.
|
||||
* This is the counterpart of do_devio, which performs a single device I/O.
|
||||
*/
|
||||
pvb_pair_t *pvb_pairs; /* needed for byte values */
|
||||
pvw_pair_t *pvw_pairs; /* needed for word values */
|
||||
pvl_pair_t *pvl_pairs; /* needed for long values */
|
||||
int i;
|
||||
pid_t caller_pid; /* process id of caller */
|
||||
size_t bytes; /* # bytes to be copied */
|
||||
vir_bytes caller_vir; /* virtual address at caller */
|
||||
phys_bytes caller_phys; /* physical address at caller */
|
||||
phys_bytes kernel_phys; /* physical address in kernel */
|
||||
|
||||
|
||||
/* Check if nr of ports is ok and get size of (port,value) data. */
|
||||
if (m_ptr->DIO_VEC_SIZE <= 0) return(EINVAL);
|
||||
switch(m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE:
|
||||
if (m_ptr->DIO_VEC_SIZE > MAX_PVB_PAIRS) return(EINVAL);
|
||||
bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvb_pair_t));
|
||||
break;
|
||||
case DIO_WORD:
|
||||
if (m_ptr->DIO_VEC_SIZE > MAX_PVW_PAIRS) return(EINVAL);
|
||||
bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvw_pair_t));
|
||||
break;
|
||||
case DIO_LONG:
|
||||
if (m_ptr->DIO_VEC_SIZE > MAX_PVL_PAIRS) return(EINVAL);
|
||||
bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvl_pair_t));
|
||||
break;
|
||||
default: /* this once and for all checks for a correct type */
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Calculate physical addresses and copy (port,value)-pairs from user. */
|
||||
caller_pid = (pid_t) m_ptr->m_source;
|
||||
caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
|
||||
caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes);
|
||||
if (0 == caller_phys) return EFAULT;
|
||||
kernel_phys = vir2phys(vdevio_pv_buf);
|
||||
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
|
||||
|
||||
/* Perform actual device I/O for byte, word, and long values. Note that
|
||||
* the entire switch is wrapped in lock() and unlock() to prevent the I/O
|
||||
* batch from being interrupted. It may be cleaner to do this just around
|
||||
* the for loops, but this results in rather lenghty code.
|
||||
*/
|
||||
lock();
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: /* byte values */
|
||||
pvb_pairs = (pvb_pair_t *) vdevio_pv_buf;
|
||||
if (DIO_INPUT == m_ptr->DIO_REQUEST) {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
pvb_pairs[i].value = inb(pvb_pairs[i].port);
|
||||
} else {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
outb(pvb_pairs[i].port, pvb_pairs[i].value);
|
||||
}
|
||||
break;
|
||||
case DIO_WORD: /* word values */
|
||||
pvw_pairs = (pvw_pair_t *) vdevio_pv_buf;
|
||||
if (DIO_INPUT == m_ptr->DIO_REQUEST) {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
pvw_pairs[i].value = inw(pvw_pairs[i].port);
|
||||
} else {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
outw(pvw_pairs[i].port, pvw_pairs[i].value);
|
||||
}
|
||||
break;
|
||||
case DIO_LONG: /* fall through: long values */
|
||||
default: /* only DIO_LONG can arrive here, see above switch */
|
||||
pvl_pairs = (pvl_pair_t *) vdevio_pv_buf;
|
||||
if (DIO_INPUT == m_ptr->DIO_REQUEST) {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
pvl_pairs[i].value = inl(pvl_pairs[i].port);
|
||||
} else {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
outl(pvb_pairs[i].port, pvl_pairs[i].value);
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
|
||||
/* Almost done, copy back results for input requests. */
|
||||
if (DIO_INPUT == m_ptr->REQUEST)
|
||||
phys_copy(kernel_phys, caller_phys, (phys_bytes) bytes);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
69
kernel/system/do_copy.c
Normal file
69
kernel/system/do_copy.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_COPY
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_c1: CP_SRC_SPACE
|
||||
* m5_i1: CP_SRC_PROC_NR
|
||||
* m5_l1: CP_SRC_ADDR
|
||||
* m5_c2: CP_DST_SPACE
|
||||
* m5_i2: CP_DST_PROC_NR
|
||||
* m5_l2: CP_DST_ADDR
|
||||
* m5_l3: CP_NR_BYTES
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_copy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_copy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_copy(). Copy data by using virtual or physical addressing. */
|
||||
|
||||
int src_proc, dst_proc, src_space, dst_space;
|
||||
vir_bytes src_vir, dst_vir;
|
||||
phys_bytes src_phys, dst_phys, bytes;
|
||||
|
||||
/* Dismember the command message. */
|
||||
src_proc = m_ptr->CP_SRC_PROC_NR;
|
||||
dst_proc = m_ptr->CP_DST_PROC_NR;
|
||||
src_space = m_ptr->CP_SRC_SPACE;
|
||||
dst_space = m_ptr->CP_DST_SPACE;
|
||||
src_vir = (vir_bytes) m_ptr->CP_SRC_ADDR;
|
||||
dst_vir = (vir_bytes) m_ptr->CP_DST_ADDR;
|
||||
bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
|
||||
|
||||
/* Check if process number was given implicitly with SELF. */
|
||||
if (src_proc == SELF) src_proc = m_ptr->m_source;
|
||||
if (dst_proc == SELF) dst_proc = m_ptr->m_source;
|
||||
|
||||
/* Compute the source and destination addresses and do the copy. */
|
||||
if (src_proc == ABS) {
|
||||
src_phys = (phys_bytes) m_ptr->CP_SRC_ADDR;
|
||||
} else {
|
||||
if (bytes != (vir_bytes) bytes) {
|
||||
/* This would happen for 64K segments and 16-bit vir_bytes.
|
||||
* It would happen a lot for do_fork except MM uses ABS
|
||||
* copies for that case.
|
||||
*/
|
||||
panic("overflow in count in do_copy", NO_NUM);
|
||||
}
|
||||
src_phys = umap_local(proc_addr(src_proc), src_space, src_vir,
|
||||
(vir_bytes) bytes);
|
||||
}
|
||||
|
||||
if (dst_proc == ABS) {
|
||||
dst_phys = (phys_bytes) m_ptr->CP_DST_ADDR;
|
||||
} else {
|
||||
dst_phys = umap_local(proc_addr(dst_proc), dst_space, dst_vir,
|
||||
(vir_bytes) bytes);
|
||||
}
|
||||
|
||||
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, dst_phys, bytes);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
55
kernel/system/do_vcopy.c
Normal file
55
kernel/system/do_vcopy.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VCOPY
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: VCP_SRC_PROC (source process number)
|
||||
* m1_i2: VCP_DST_PROC (destination process number)
|
||||
* m1_i3: VCP_VEC_SIZE (vector size)
|
||||
* m1_p1: VCP_VEC_ADDR (pointer to vector)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vcopy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_vcopy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_vcopy(). Copy multiple blocks of memory */
|
||||
|
||||
int src_proc, dst_proc, vect_s, i;
|
||||
vir_bytes src_vir, dst_vir, vect_addr;
|
||||
phys_bytes src_phys, dst_phys, bytes;
|
||||
cpvec_t cpvec_table[CPVEC_NR];
|
||||
|
||||
/* Dismember the command message. */
|
||||
src_proc = m_ptr->VCP_SRC_PROC;
|
||||
dst_proc = m_ptr->VCP_DST_PROC;
|
||||
vect_s = m_ptr->VCP_VEC_SIZE;
|
||||
vect_addr = (vir_bytes)m_ptr->VCP_VEC_ADDR;
|
||||
|
||||
if (vect_s > CPVEC_NR) return EDOM;
|
||||
|
||||
src_phys= numap_local(m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
|
||||
if (!src_phys) return EFAULT;
|
||||
phys_copy(src_phys, vir2phys(cpvec_table),
|
||||
(phys_bytes) (vect_s * sizeof(cpvec_t)));
|
||||
|
||||
for (i = 0; i < vect_s; i++) {
|
||||
src_vir= cpvec_table[i].cpv_src;
|
||||
dst_vir= cpvec_table[i].cpv_dst;
|
||||
bytes= cpvec_table[i].cpv_size;
|
||||
src_phys = numap_local(src_proc,src_vir,(vir_bytes)bytes);
|
||||
dst_phys = numap_local(dst_proc,dst_vir,(vir_bytes)bytes);
|
||||
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, dst_phys, bytes);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
106
kernel/system/irqctl.c
Normal file
106
kernel/system/irqctl.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_IRQCTL
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_c1: IRQ_REQUEST (control operation to perform)
|
||||
* m5_c2: IRQ_VECTOR (irq line that must be controlled)
|
||||
* m5_i1: IRQ_POLICY (flags to control the IRQCTL request)
|
||||
* m5_i2: IRQ_PROC_NR (process number to notify)
|
||||
* m5_l1: IRQ_PORT (port to write to / read from)
|
||||
* m5_l2: IRQ_VIR_ADDR (virtual address at caller)
|
||||
* m5_l3: IRQ_MASK_VAL (value to be written or strobe mask)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_irqctl *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_irqctl(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Dismember the request message. */
|
||||
int irq = m_ptr->IRQ_VECTOR; /* which IRQ vector */
|
||||
int policy = m_ptr->IRQ_POLICY; /* policy field with flags */
|
||||
long port = m_ptr->IRQ_PORT; /* port to read or write */
|
||||
vir_bytes vir_addr = m_ptr->IRQ_VIR_ADDR; /* address at caller */
|
||||
phys_bytes phys_addr = 0; /* calculate physical address */
|
||||
long mask_val = m_ptr->IRQ_MASK_VAL; /* mask or value to be written */
|
||||
int proc_nr = m_ptr->IRQ_PROC_NR; /* process number to forward to */
|
||||
|
||||
/* Check if IRQ line is acceptable. */
|
||||
if ((unsigned) irq >= NR_IRQ_VECTORS) {
|
||||
kprintf("ST: irq line %d is not acceptable!\n", irq);
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* See what is requested and take needed actions. */
|
||||
switch(m_ptr->IRQ_REQUEST) {
|
||||
|
||||
/* Enable or disable IRQs. This is straightforward. */
|
||||
case IRQ_ENABLE: {
|
||||
enable_irq(&irqtab[irq].hook);
|
||||
break;
|
||||
}
|
||||
case IRQ_DISABLE: {
|
||||
disable_irq(&irqtab[irq].hook);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Control IRQ policies. Set a policy and needed details in the IRQ table.
|
||||
* This policy is used by a generic function to handle hardware interrupts.
|
||||
* The generic_handler() is contained in system.c.
|
||||
*/
|
||||
case IRQ_SETPOLICY: {
|
||||
|
||||
if (proc_nr == NONE) { /* remove irqtab entry */
|
||||
if (irqtab[irq].proc_nr != m_ptr->m_source) {
|
||||
return(EPERM); /* only owner may do so */
|
||||
}
|
||||
kprintf("ST: notify: cannot remove entry for IRQ %d\n",irq);
|
||||
return(ENOSYS); /* not yet supported */
|
||||
}
|
||||
else { /* install generic handler */
|
||||
if (irqtab[irq].proc_nr != NONE) { /* IRQ entry already taken */
|
||||
kprintf("ST: notify: slot for IRQ %d already taken\n", irq);
|
||||
return(EBUSY); /* cannot overwrite entry */
|
||||
}
|
||||
if (proc_nr == SELF) /* check for magic proc nr */
|
||||
proc_nr = m_ptr->m_source; /* set caller's proc nr */
|
||||
if (! isokprocn(proc_nr)) { /* check if proc nr is ok */
|
||||
kprintf("ST: notify: invalid proc_nr: %d\n", proc_nr);
|
||||
return(EINVAL);
|
||||
}
|
||||
if (policy & IRQ_READ_PORT) { /* get phys_addr at caller */
|
||||
switch(policy & (IRQ_BYTE|IRQ_WORD|IRQ_LONG)) {
|
||||
case IRQ_BYTE: phys_addr=numap_local(proc_nr,vir_addr,sizeof( u8_t));
|
||||
break;
|
||||
case IRQ_WORD: phys_addr=numap_local(proc_nr,vir_addr,sizeof(u16_t));
|
||||
break;
|
||||
case IRQ_LONG: phys_addr=numap_local(proc_nr,vir_addr,sizeof(u32_t));
|
||||
break;
|
||||
default: return(EINVAL); /* wrong type flags */
|
||||
}
|
||||
if (phys_addr==0) return(EFAULT); /* invalid address */
|
||||
}
|
||||
/* Arguments seem to be OK, register them in the IRQ table. */
|
||||
irqtab[irq].policy = policy; /* policy for interrupts */
|
||||
irqtab[irq].proc_nr = proc_nr; /* process number to notify */
|
||||
irqtab[irq].port = port; /* port to read or write */
|
||||
irqtab[irq].addr = phys_addr; /* address to store status */
|
||||
irqtab[irq].mask_val = mask_val; /* strobe mask or value */
|
||||
put_irq_handler(&irqtab[irq].hook, irq, generic_handler);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return(EINVAL); /* invalid IRQ_REQUEST */
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
234
kernel/system/misc.c
Normal file
234
kernel/system/misc.c
Normal file
@@ -0,0 +1,234 @@
|
||||
/* 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_l3: T_CHILD_UTIME
|
||||
* m4_l4: T_CHILD_STIME
|
||||
* m4_l5: T_BOOT_TICKS
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <unistd.h>
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* 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(); /* halt the volatile time counters in rp */
|
||||
m_ptr->T_USER_TIME = rp->user_time;
|
||||
m_ptr->T_SYSTEM_TIME = rp->sys_time;
|
||||
unlock();
|
||||
m_ptr->T_CHILD_UTIME = rp->child_utime;
|
||||
m_ptr->T_CHILD_STIME = rp->child_stime;
|
||||
}
|
||||
m_ptr->T_BOOT_TICKS = get_uptime();
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* 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
|
||||
* MM (normal abort or panic) or FS (panic), or TTY (a CTRL-ALT-DEL or ESC
|
||||
* after debugging dumps).
|
||||
*/
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys;
|
||||
vir_bytes len;
|
||||
int how = m_ptr->ABRT_HOW;
|
||||
|
||||
rp = proc_addr(m_ptr->m_source);
|
||||
|
||||
if (how == RBT_MONITOR) {
|
||||
/* The monitor is to run user specified instructions. */
|
||||
len = m_ptr->ABRT_MON_LEN + 1;
|
||||
assert(len <= mon_parmsize);
|
||||
src_phys = numap_local(m_ptr->ABRT_MON_PROC,
|
||||
(vir_bytes) m_ptr->ABRT_MON_ADDR, len);
|
||||
assert(src_phys != 0);
|
||||
phys_copy(src_phys, mon_params, (phys_bytes) len);
|
||||
}
|
||||
prepare_shutdown(how);
|
||||
return(OK); /* pro-forma (really EDISASTER) */
|
||||
}
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_GETINFO
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i3: I_REQUEST (what info to get)
|
||||
* m1_i4: I_PROC_NR (process to store value at)
|
||||
* m1_p1: I_VAL_PTR (where to put it)
|
||||
* m1_i1: I_VAL_LEN (maximum length expected, optional)
|
||||
* m1_p2: I_KEY_PTR (environment variable key)
|
||||
* m1_i2: I_KEY_LEN (lenght of environment variable key)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getinfo *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_getinfo(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Request system information to be copied to caller's address space. */
|
||||
size_t length;
|
||||
phys_bytes src_phys;
|
||||
phys_bytes dst_phys;
|
||||
int proc_nr, nr;
|
||||
|
||||
/* Set source address and length based on request type. */
|
||||
switch (m_ptr->I_REQUEST) {
|
||||
case GET_KENVIRON: {
|
||||
struct kenviron kenv;
|
||||
extern int end;
|
||||
|
||||
kenv.pc_at = pc_at; kenv.ps_mca = ps_mca;
|
||||
kenv.processor = processor; kenv.protected = protected_mode;
|
||||
kenv.ega = ega; kenv.vga = vga;
|
||||
|
||||
kenv.proc_addr = (vir_bytes) proc;
|
||||
kenv.params_base = mon_params;
|
||||
kenv.params_size = mon_parmsize;
|
||||
kenv.kmem_base = vir2phys(0);
|
||||
kenv.kmem_size = vir2phys(&end) - vir2phys(0) + 1;
|
||||
kenv.bootfs_base = proc_addr(MEMORY)->p_farmem[0].mem_phys;
|
||||
kenv.bootfs_size = proc_addr(MEMORY)->p_farmem[0].mem_len;
|
||||
length = sizeof(struct kenviron);
|
||||
src_phys = vir2phys(&kenv);
|
||||
break;
|
||||
}
|
||||
case GET_IMAGE: {
|
||||
length = sizeof(struct system_image) * IMAGE_SIZE;
|
||||
src_phys = vir2phys(image);
|
||||
break;
|
||||
}
|
||||
case GET_IRQTAB: {
|
||||
length = sizeof(struct irqtab) * NR_IRQ_VECTORS;
|
||||
src_phys = vir2phys(irqtab);
|
||||
break;
|
||||
}
|
||||
case GET_MEMCHUNKS: {
|
||||
length = sizeof(struct memory) * NR_MEMS;
|
||||
src_phys = vir2phys(mem);
|
||||
break;
|
||||
}
|
||||
case GET_SCHEDINFO: {
|
||||
/* This is slightly complicated because we need two data structures
|
||||
* at once, otherwise the scheduling information may be incorrect.
|
||||
* Copy the queue heads and fall through to copy the process table.
|
||||
*/
|
||||
length = sizeof(struct proc *) * NR_SCHED_QUEUES;
|
||||
src_phys = vir2phys(rdy_head);
|
||||
dst_phys = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->I_KEY_PTR,
|
||||
length);
|
||||
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, dst_phys, length);
|
||||
}
|
||||
case GET_PROCTAB: {
|
||||
length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
|
||||
src_phys = vir2phys(proc);
|
||||
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);
|
||||
length = sizeof(struct proc);
|
||||
src_phys = vir2phys(proc_addr(nr));
|
||||
break;
|
||||
}
|
||||
case GET_MONPARAMS: {
|
||||
src_phys = mon_params; /* already is a physical address! */
|
||||
length = mon_parmsize;
|
||||
break;
|
||||
}
|
||||
case GET_PROCNR: {
|
||||
length = sizeof(int);
|
||||
if (m_ptr->I_KEY_LEN == 0) { /* get own process nr */
|
||||
kprintf("GET_PROCNR (own) from %d\n", m_ptr->m_source);
|
||||
src_phys = vir2phys(&proc_nr);
|
||||
} else { /* lookup nr by name */
|
||||
int proc_found = FALSE;
|
||||
struct proc *pp;
|
||||
char key[8]; /* storage for process name to lookup */
|
||||
kprintf("GET_PROCNR (others) from %d\n", m_ptr->m_source);
|
||||
proc_nr = m_ptr->m_source; /* only caller can request copy */
|
||||
if (m_ptr->I_KEY_LEN > sizeof(key)) return(EINVAL);
|
||||
if (vir_copy(proc_nr, (vir_bytes) m_ptr->I_KEY_PTR, SYSTASK,
|
||||
(vir_bytes) key, m_ptr->I_KEY_LEN) != OK) return(EFAULT);
|
||||
for (pp=BEG_PROC_ADDR; pp<END_PROC_ADDR; pp++) {
|
||||
if (kstrncmp(pp->p_name, key, m_ptr->I_KEY_LEN) == 0) {
|
||||
src_phys = vir2phys(&(pp->p_nr));
|
||||
proc_found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! proc_found) return(ESRCH);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GET_KMESSAGES: {
|
||||
length = sizeof(struct kmessages);
|
||||
src_phys = vir2phys(&kmess);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Try to make the actual copy for the requested data. */
|
||||
if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG);
|
||||
proc_nr = m_ptr->m_source; /* only caller can request copy */
|
||||
dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR, length);
|
||||
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, dst_phys, length);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
45
kernel/system/old/do_abort.c
Normal file
45
kernel/system/old/do_abort.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <unistd.h>
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* 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
|
||||
* MM (normal abort or panic) or FS (panic), or TTY (a CTRL-ALT-DEL or ESC
|
||||
* after debugging dumps).
|
||||
*/
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys;
|
||||
vir_bytes len;
|
||||
int how = m_ptr->ABRT_HOW;
|
||||
|
||||
rp = proc_addr(m_ptr->m_source);
|
||||
|
||||
if (how == RBT_MONITOR) {
|
||||
/* The monitor is to run user specified instructions. */
|
||||
len = m_ptr->ABRT_MON_LEN + 1;
|
||||
assert(len <= mon_parmsize);
|
||||
src_phys = numap_local(m_ptr->ABRT_MON_PROC,
|
||||
(vir_bytes) m_ptr->ABRT_MON_ADDR, len);
|
||||
assert(src_phys != 0);
|
||||
phys_copy(src_phys, mon_params, (phys_bytes) len);
|
||||
}
|
||||
prepare_shutdown(how);
|
||||
return(OK); /* pro-forma (really EDISASTER) */
|
||||
}
|
||||
|
||||
34
kernel/system/old/do_endsig.c
Normal file
34
kernel/system/old/do_endsig.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_ENDSIG
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i1: SIG_PROC (process that was signaled)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* do_endsig *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_endsig(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a call
|
||||
* to cause_sig by a task
|
||||
*/
|
||||
|
||||
register struct proc *rp;
|
||||
|
||||
rp = proc_addr(m_ptr->SIG_PROC);
|
||||
if (isemptyp(rp)) return(EINVAL); /* process already dead? */
|
||||
assert(isuserp(rp));
|
||||
|
||||
/* MM has finished one KSIG. */
|
||||
if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
|
||||
&& (rp->p_flags &= ~SIG_PENDING) == 0)
|
||||
lock_ready(rp);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
65
kernel/system/old/do_exec.c
Normal file
65
kernel/system/old/do_exec.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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 "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#if (CHIP == INTEL)
|
||||
#include "../protect.h"
|
||||
#endif
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* 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;
|
||||
#define NLEN (sizeof(rp->p_name)-1)
|
||||
|
||||
rp = proc_addr(m_ptr->PR_PROC_NR);
|
||||
assert(isuserp(rp));
|
||||
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 */
|
||||
memset(&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_flags &= ~RECEIVING; /* MM does not reply to EXEC call */
|
||||
if (rp->p_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) NLEN);
|
||||
if (phys_name != 0) {
|
||||
phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN);
|
||||
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
|
||||
*np = 0;
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
45
kernel/system/old/do_exit.c
Normal file
45
kernel/system/old/do_exit.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_EXIT
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: EXIT_STATUS (exit status, 0 if normal exit)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_exit *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_exit(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_exit. A server or driver wants to exit. This may happen
|
||||
* on a panic, but also is done when MINIX is shutdown.
|
||||
*/
|
||||
register struct proc *rp;
|
||||
int proc_nr = m_ptr->m_source; /* can only exit own process */
|
||||
|
||||
if (m_ptr->EXIT_STATUS != 0) {
|
||||
kprintf("WARNING: system process %d exited with an error.\n", proc_nr );
|
||||
}
|
||||
|
||||
/* Now call the routine to clean up of the process table slot. This cancels
|
||||
* outstanding timers, possibly removes the process from the message queues,
|
||||
* and reset important process table fields.
|
||||
*/
|
||||
clear_proc(proc_nr);
|
||||
|
||||
/* If the shutdown sequence is active, see if it was awaiting the shutdown
|
||||
* of this system service. If so, directly continue the stop sequence.
|
||||
*/
|
||||
if (shutting_down && shutdown_process == proc_addr(proc_nr)) {
|
||||
stop_sequence(&shutdown_timer);
|
||||
}
|
||||
return(EDONTREPLY); /* no reply is sent */
|
||||
}
|
||||
|
||||
|
||||
64
kernel/system/old/do_fork.c
Normal file
64
kernel/system/old/do_fork.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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 MM)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#include "../sendmask.h"
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* 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);
|
||||
assert(isuserp(rpp));
|
||||
rpc = proc_addr(m_ptr->PR_PROC_NR);
|
||||
assert(isemptyp(rpc));
|
||||
|
||||
/* 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_flags |= NO_MAP; /* inhibit the process from running */
|
||||
|
||||
rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
|
||||
|
||||
/* Only 1 in group should have PENDING, child does not inherit trace status*/
|
||||
sigemptyset(&rpc->p_pending);
|
||||
rpc->p_pendcount = 0;
|
||||
rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
|
||||
|
||||
rpc->user_time = 0; /* set all the accounting times to 0 */
|
||||
rpc->sys_time = 0;
|
||||
rpc->child_utime = 0;
|
||||
rpc->child_stime = 0;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
148
kernel/system/old/do_getinfo.c
Normal file
148
kernel/system/old/do_getinfo.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_GETINFO
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i3: I_REQUEST (what info to get)
|
||||
* m1_i4: I_PROC_NR (process to store value at)
|
||||
* m1_p1: I_VAL_PTR (where to put it)
|
||||
* m1_i1: I_VAL_LEN (maximum length expected, optional)
|
||||
* m1_p2: I_KEY_PTR (environment variable key)
|
||||
* m1_i2: I_KEY_LEN (lenght of environment variable key)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getinfo *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_getinfo(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Request system information to be copied to caller's address space. */
|
||||
size_t length;
|
||||
phys_bytes src_phys;
|
||||
phys_bytes dst_phys;
|
||||
int proc_nr;
|
||||
|
||||
/* First get the process number and verify it. */
|
||||
proc_nr = (m_ptr->I_PROC_NR == SELF) ? m_ptr->m_source : m_ptr->I_PROC_NR;
|
||||
if (! isokprocn(proc_nr)) {
|
||||
printf("Invalid process number: %d from %d\n", proc_nr, m_ptr->m_source);
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Set source address and length based on request type. */
|
||||
switch (m_ptr->I_REQUEST) {
|
||||
case GET_KENVIRON: {
|
||||
struct kenviron kenv;
|
||||
extern int end;
|
||||
kenv.pc_at = pc_at; kenv.ps_mca = ps_mca;
|
||||
kenv.processor = processor; kenv.protected = protected_mode;
|
||||
kenv.ega = ega; kenv.vga = vga;
|
||||
kenv.proc_addr = (vir_bytes) proc;
|
||||
kenv.kmem_start = vir2phys(0);
|
||||
kenv.kmem_end = vir2phys(&end);
|
||||
length = sizeof(struct kenviron);
|
||||
src_phys = vir2phys(&kenv);
|
||||
break;
|
||||
}
|
||||
case GET_IMAGE: {
|
||||
length = sizeof(struct system_image) * IMAGE_SIZE;
|
||||
src_phys = vir2phys(image);
|
||||
break;
|
||||
}
|
||||
case GET_IRQTAB: {
|
||||
length = sizeof(struct irqtab) * NR_IRQ_VECTORS;
|
||||
src_phys = vir2phys(irqtab);
|
||||
break;
|
||||
}
|
||||
case GET_MEMCHUNKS: {
|
||||
length = sizeof(struct memory) * NR_MEMS;
|
||||
src_phys = vir2phys(mem);
|
||||
break;
|
||||
}
|
||||
case GET_SCHEDINFO: {
|
||||
/* This is slightly complicated because we need several variables
|
||||
* at once, otherwise the scheduling information may be incorrect.
|
||||
*/
|
||||
length = sizeof(struct proc *) * NR_SCHED_QUEUES;
|
||||
src_phys = vir2phys(rdy_head);
|
||||
dst_phys = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->I_KEY_PTR,
|
||||
length);
|
||||
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, dst_phys, length);
|
||||
/* Fall through to also get a copy of the process table. */
|
||||
}
|
||||
case GET_PROCTAB: {
|
||||
length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
|
||||
src_phys = vir2phys(proc);
|
||||
break;
|
||||
}
|
||||
case GET_PROC: {
|
||||
if (! isokprocn(m_ptr->I_KEY_LEN)) return(EINVAL);
|
||||
length = sizeof(struct proc);
|
||||
src_phys = vir2phys(proc_addr(m_ptr->I_KEY_LEN));
|
||||
break;
|
||||
}
|
||||
case GET_MONPARAMS: {
|
||||
src_phys = mon_params; /* already is a physical address! */
|
||||
length = mon_parmsize;
|
||||
break;
|
||||
}
|
||||
case GET_KENV: { /* get one string by name */
|
||||
char key[32]; /* boot variable key provided by caller */
|
||||
char *val; /* pointer to actual boot variable value */
|
||||
if (m_ptr->I_KEY_LEN > sizeof(key)) return(EINVAL);
|
||||
if (vir_copy(proc_nr, (vir_bytes) m_ptr->I_KEY_PTR,
|
||||
SYSTASK, (vir_bytes) key, m_ptr->I_KEY_LEN) != OK) return(EFAULT);
|
||||
if ((val=getkenv(key)) == NULL) return(ESRCH);
|
||||
length = strlen(val) + 1;
|
||||
src_phys = vir2phys(val);
|
||||
break;
|
||||
}
|
||||
case GET_PROCNR: {
|
||||
length = sizeof(int);
|
||||
if (m_ptr->I_KEY_LEN == 0) { /* get own process nr */
|
||||
src_phys = vir2phys(&proc_nr);
|
||||
} else { /* lookup nr by name */
|
||||
int proc_found = FALSE;
|
||||
struct proc *pp;
|
||||
char key[8]; /* storage for process name to lookup */
|
||||
if (m_ptr->I_KEY_LEN > sizeof(key)) return(EINVAL);
|
||||
if (vir_copy(proc_nr, (vir_bytes) m_ptr->I_KEY_PTR, SYSTASK,
|
||||
(vir_bytes) key, m_ptr->I_KEY_LEN) != OK) return(EFAULT);
|
||||
for (pp= BEG_PROC_ADDR; pp<END_PROC_ADDR; pp++) {
|
||||
if (strncmp(pp->p_name, key, m_ptr->I_KEY_LEN) == 0) {
|
||||
src_phys = vir2phys(&(pp->p_nr));
|
||||
proc_found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! proc_found) return(ESRCH);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GET_KMESSAGES: {
|
||||
length = sizeof(struct kmessages);
|
||||
src_phys = vir2phys(&kmess);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Try to make the actual copy for the requested data. */
|
||||
if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG);
|
||||
dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR, length);
|
||||
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, dst_phys, length);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
44
kernel/system/old/do_getmap.c
Normal file
44
kernel/system/old/do_getmap.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_GETMAP
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (process to get map of)
|
||||
* m1_p1: PR_MEM_PTR (copy the memory map here)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getmap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_getmap(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_getmap(). Report the memory map to MM. */
|
||||
|
||||
register struct proc *rp;
|
||||
phys_bytes dst_phys;
|
||||
int caller; /* where the map has to be stored */
|
||||
int k; /* process whose map is to be loaded */
|
||||
struct mem_map *map_ptr; /* virtual address of map inside caller (MM) */
|
||||
|
||||
/* Extract message parameters and copy new memory map to MM. */
|
||||
caller = m_ptr->m_source;
|
||||
k = m_ptr->PR_PROC_NR;
|
||||
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
|
||||
|
||||
assert(isokprocn(k)); /* unlikely: MM sends a bad proc nr. */
|
||||
|
||||
rp = proc_addr(k); /* ptr to entry of the map */
|
||||
|
||||
/* Copy the map to MM. */
|
||||
dst_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
|
||||
assert(dst_phys != 0);
|
||||
phys_copy(vir2phys(rp->p_map), dst_phys, sizeof(rp->p_map));
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
46
kernel/system/old/do_getsig.c
Normal file
46
kernel/system/old/do_getsig.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_GETSIG
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i1: SIG_PROC (return proc nr or NONE here)
|
||||
* m2_l1: SIG_MAP (return signal map here)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getsig *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_getsig(m_ptr)
|
||||
message *m_ptr; /* pointer to the request message */
|
||||
{
|
||||
/* MM is ready to accept signals and repeatedly does a system call to get one
|
||||
* Find a process with pending signals. If no more signals are available,
|
||||
* return NONE in the process number field.
|
||||
*/
|
||||
register struct proc *rp;
|
||||
|
||||
/* Only the MM is allowed to request pending signals. */
|
||||
if (m_ptr->m_source != MM_PROC_NR)
|
||||
return(EPERM);
|
||||
|
||||
/* Find the next process with pending signals. */
|
||||
for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++) {
|
||||
if (rp->p_flags & PENDING) {
|
||||
m_ptr->SIG_PROC = proc_number(rp);
|
||||
m_ptr->SIG_MAP = rp->p_pending;
|
||||
sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
|
||||
rp->p_flags &= ~PENDING; /* remains inhibited by SIG_PENDING */
|
||||
return(OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* No process with pending signals was found. */
|
||||
m_ptr->SIG_PROC = NONE;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
32
kernel/system/old/do_getsp.c
Normal file
32
kernel/system/old/do_getsp.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_GETSP
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: PR_PROC_NR (process to get stack pointer of)
|
||||
* m1_p1: PR_STACK_PTR (return stack pointer here)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getsp *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_getsp(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_getsp(). MM wants to know what sp is. */
|
||||
|
||||
register struct proc *rp;
|
||||
|
||||
rp = proc_addr(m_ptr->PR_PROC_NR);
|
||||
assert(isuserp(rp));
|
||||
m_ptr->PR_STACK_PTR = (char *) rp->p_reg.sp; /* return sp here (bad type) */
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
28
kernel/system/old/do_iopenable.c
Normal file
28
kernel/system/old/do_iopenable.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/* 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>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* 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
|
||||
}
|
||||
|
||||
|
||||
15
kernel/system/old/do_kill.c
Normal file
15
kernel/system/old/do_kill.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
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 MM.
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
36
kernel/system/old/do_kmalloc.c
Normal file
36
kernel/system/old/do_kmalloc.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_KMALLOC
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l2: MEM_CHUNK_SIZE (request a buffer of this size)
|
||||
* m4_l1: MEM_CHUNK_BASE (return physical address on success)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_kmalloc *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_kmalloc(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Request a (DMA) buffer to be allocated in one of the memory chunks. */
|
||||
phys_clicks tot_clicks;
|
||||
struct memory *memp;
|
||||
|
||||
tot_clicks = (m_ptr->MEM_CHUNK_SIZE + CLICK_SIZE-1) >> CLICK_SHIFT;
|
||||
memp = &mem[NR_MEMS];
|
||||
while ((--memp)->size < tot_clicks) {
|
||||
if (memp == mem) {
|
||||
return(ENOMEM);
|
||||
}
|
||||
}
|
||||
memp->size -= tot_clicks;
|
||||
m_ptr->MEM_CHUNK_BASE = (memp->base + memp->size) << CLICK_SHIFT;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
33
kernel/system/old/do_mem.c
Normal file
33
kernel/system/old/do_mem.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_MEM
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l1: MEM_CHUNK_BASE (memory base)
|
||||
* m4_l2: MEM_CHUNK_SIZE (memory size)
|
||||
* m4_l3: MEM_TOT_SIZE (total memory)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_mem *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_mem(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Return the base and size of the next chunk of memory. */
|
||||
|
||||
struct memory *memp;
|
||||
|
||||
for (memp = mem; memp < &mem[NR_MEMS]; ++memp) {
|
||||
m_ptr->MEM_CHUNK_BASE = memp->base;
|
||||
m_ptr->MEM_CHUNK_SIZE = memp->size;
|
||||
m_ptr->MEM_TOT_SIZE = tot_mem_size;
|
||||
memp->size = 0;
|
||||
if (m_ptr->MEM_CHUNK_SIZE != 0) break; /* found a chunk */
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
52
kernel/system/old/do_newmap.c
Normal file
52
kernel/system/old/do_newmap.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 "../kernel.h"
|
||||
#include "../system.h"
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* do_newmap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_newmap(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_newmap(). Fetch the memory map from MM. */
|
||||
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys;
|
||||
int caller; /* whose space has the new map (usually MM) */
|
||||
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 (MM) */
|
||||
|
||||
/* Extract message parameters and copy new memory map from MM. */
|
||||
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 MM. */
|
||||
src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
|
||||
assert(src_phys != 0);
|
||||
phys_copy(src_phys, vir2phys(rp->p_map), (phys_bytes) sizeof(rp->p_map));
|
||||
|
||||
#if (CHIP != M68000)
|
||||
alloc_segments(rp);
|
||||
#else
|
||||
pmmu_init_proc(rp);
|
||||
#endif
|
||||
old_flags = rp->p_flags; /* save the previous value of the flags */
|
||||
rp->p_flags &= ~NO_MAP;
|
||||
if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
86
kernel/system/old/do_phys2seg.c
Normal file
86
kernel/system/old/do_phys2seg.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_PHYS2SEG
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l1: SEG_SELECT (return segment selector here)
|
||||
* m4_l2: SEG_OFFSET (return offset within segment here)
|
||||
* m4_l3: SEG_PHYS (physical address to convert)
|
||||
* m4_l4: SEG_SIZE (size of segment)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include "../protect.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_phys2seg *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_phys2seg(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;
|
||||
register struct proc *rp;
|
||||
phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS;
|
||||
vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE;
|
||||
int result;
|
||||
|
||||
#if 0
|
||||
kprintf("FLAT DS SELECTOR used\n", NO_ARG);
|
||||
selector = FLAT_DS_SELECTOR;
|
||||
offset = phys;
|
||||
#else
|
||||
kprintf("Using Experimental LDT selector for video memory\n", NO_ARG);
|
||||
|
||||
if (!protected_mode) {
|
||||
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) {
|
||||
rp = proc_addr(m_ptr->m_source);
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX], phys, size,
|
||||
USER_PRIVILEGE);
|
||||
selector = (EXTRA_LDT_INDEX * 0x08) | (1 * 0x04) | USER_PRIVILEGE;
|
||||
offset = 0;
|
||||
result = OK;
|
||||
} else {
|
||||
#if ENABLE_USERPRIV && ENABLE_LOOSELDT
|
||||
rp = proc_addr(m_ptr->m_source);
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX], phys & ~0xFFFF, 0,
|
||||
USER_PRIVILEGE);
|
||||
selector = (EXTRA_LDT_INDEX * 0x08) | (1 * 0x04) | USER_PRIVILEGE;
|
||||
offset = phys & 0xFFFF;
|
||||
result = OK;
|
||||
#else
|
||||
result = E2BIG; /* allow settings only */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
kprintf("do_phys2seg: proc %d", m_ptr->m_source);
|
||||
kprintf(" phys %u", phys);
|
||||
kprintf(" size %u", size);
|
||||
kprintf(" sel %u", selector);
|
||||
kprintf(" off %u\n", offset);
|
||||
#endif
|
||||
m_ptr->SEG_SELECT = selector;
|
||||
m_ptr->SEG_OFFSET = offset;
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
37
kernel/system/old/do_physcopy.c
Normal file
37
kernel/system/old/do_physcopy.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_PHYSCOPY
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m5_l1: CP_SRC_ADDR (physical source address)
|
||||
* m5_l2: CP_DST_ADDR (physical destination address)
|
||||
* m5_l3: CP_NR_BYTES (number of bytes to copy)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_physcopy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_physcopy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_physcopy(). Copy data by using physical addressing. */
|
||||
|
||||
phys_bytes src_phys, dst_phys, bytes;
|
||||
|
||||
/* Dismember the command message. */
|
||||
src_phys = (phys_bytes) m_ptr->CP_SRC_ADDR;
|
||||
dst_phys = (phys_bytes) m_ptr->CP_DST_ADDR;
|
||||
bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
|
||||
|
||||
/* Do some checks and copy the data. */
|
||||
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
|
||||
phys_copy(src_phys, dst_phys, bytes);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
60
kernel/system/old/do_sdevio.c
Normal file
60
kernel/system/old/do_sdevio.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <minix/devio.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
72
kernel/system/old/do_sigreturn.c
Normal file
72
kernel/system/old/do_sigreturn.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_SIGRETURN
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i1: SIG_PROC (process number)
|
||||
* m2_i3: SIG_FLAGS (sig return flags) (unused)
|
||||
* m2_p1: SIG_CTXT_PTR (pointer to sigcontext structure)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <signal.h>
|
||||
#include <sys/sigcontext.h>
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sigreturn *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_sigreturn(m_ptr)
|
||||
register message *m_ptr;
|
||||
{
|
||||
/* 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);
|
||||
if (! isuserp(rp))
|
||||
printf("message source: %d; rp: %d\n", m_ptr->m_source, rp->p_nr);
|
||||
assert(isuserp(rp));
|
||||
|
||||
/* 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. */
|
||||
memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
67
kernel/system/old/do_svrctl.c
Normal file
67
kernel/system/old/do_svrctl.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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 "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <sys/svrctl.h>
|
||||
#include "../sendmask.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* 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 MM 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_type = P_SERVER;
|
||||
rp->p_sendmask = ALLOW_ALL_MASK;
|
||||
send_mask_allow(proc_addr(RTL8139)->p_sendmask, proc_nr);
|
||||
send_mask_allow(proc_addr(MM_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);
|
||||
return(OK);
|
||||
}
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
33
kernel/system/old/do_umap.c
Normal file
33
kernel/system/old/do_umap.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/* 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 "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
/*==========================================================================*
|
||||
* do_umap *
|
||||
*==========================================================================*/
|
||||
PUBLIC int do_umap(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Same as umap_local(), for non-kernel processes. */
|
||||
int proc_nr = (int) m_ptr->CP_SRC_PROC_NR;
|
||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||
|
||||
m_ptr->CP_DST_ADDR = umap_local(proc_addr(proc_nr),
|
||||
(int) m_ptr->CP_SRC_SPACE,
|
||||
(vir_bytes) m_ptr->CP_SRC_ADDR,
|
||||
(vir_bytes) m_ptr->CP_NR_BYTES);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
126
kernel/system/old/do_vdevio.c
Normal file
126
kernel/system/old/do_vdevio.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VDEVIO
|
||||
*
|
||||
* 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_p1: DIO_VEC_ADDR (pointer to port/ value pairs)
|
||||
* m2_i2: DIO_VEC_SIZE (number of ports to read or write)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <minix/devio.h>
|
||||
|
||||
/* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
|
||||
PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE];
|
||||
|
||||
/* SYS_VDEVIO sends a pointer to a (port,value)-pairs vector at the caller.
|
||||
* Define the maximum number of (port,value)-pairs that can be handled in a
|
||||
* in a single SYS_VDEVIO system call based on the struct definitions.
|
||||
*/
|
||||
#define MAX_PVB_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvb_pair_t))
|
||||
#define MAX_PVW_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvw_pair_t))
|
||||
#define MAX_PVL_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvl_pair_t))
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vdevio *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_vdevio(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Perform a series of device I/O on behalf of a non-kernel process. The
|
||||
* I/O addresses and I/O values are fetched from and returned to some buffer
|
||||
* in user space. The actual I/O is wrapped by lock() and unlock() to prevent
|
||||
* that I/O batch from being interrrupted.
|
||||
* This is the counterpart of do_devio, which performs a single device I/O.
|
||||
*/
|
||||
pvb_pair_t *pvb_pairs; /* needed for byte values */
|
||||
pvw_pair_t *pvw_pairs; /* needed for word values */
|
||||
pvl_pair_t *pvl_pairs; /* needed for long values */
|
||||
int i;
|
||||
pid_t caller_pid; /* process id of caller */
|
||||
size_t bytes; /* # bytes to be copied */
|
||||
vir_bytes caller_vir; /* virtual address at caller */
|
||||
phys_bytes caller_phys; /* physical address at caller */
|
||||
phys_bytes kernel_phys; /* physical address in kernel */
|
||||
|
||||
|
||||
/* Check if nr of ports is ok and get size of (port,value) data. */
|
||||
if (m_ptr->DIO_VEC_SIZE <= 0) return(EINVAL);
|
||||
switch(m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE:
|
||||
if (m_ptr->DIO_VEC_SIZE > MAX_PVB_PAIRS) return(EINVAL);
|
||||
bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvb_pair_t));
|
||||
break;
|
||||
case DIO_WORD:
|
||||
if (m_ptr->DIO_VEC_SIZE > MAX_PVW_PAIRS) return(EINVAL);
|
||||
bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvw_pair_t));
|
||||
break;
|
||||
case DIO_LONG:
|
||||
if (m_ptr->DIO_VEC_SIZE > MAX_PVL_PAIRS) return(EINVAL);
|
||||
bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvl_pair_t));
|
||||
break;
|
||||
default: /* this once and for all checks for a correct type */
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Calculate physical addresses and copy (port,value)-pairs from user. */
|
||||
caller_pid = (pid_t) m_ptr->m_source;
|
||||
caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
|
||||
caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes);
|
||||
if (0 == caller_phys) return EFAULT;
|
||||
kernel_phys = vir2phys(vdevio_pv_buf);
|
||||
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
|
||||
|
||||
/* Perform actual device I/O for byte, word, and long values. Note that
|
||||
* the entire switch is wrapped in lock() and unlock() to prevent the I/O
|
||||
* batch from being interrupted. It may be cleaner to do this just around
|
||||
* the for loops, but this results in rather lenghty code.
|
||||
*/
|
||||
lock();
|
||||
switch (m_ptr->DIO_TYPE) {
|
||||
case DIO_BYTE: /* byte values */
|
||||
pvb_pairs = (pvb_pair_t *) vdevio_pv_buf;
|
||||
if (DIO_INPUT == m_ptr->DIO_REQUEST) {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
pvb_pairs[i].value = inb(pvb_pairs[i].port);
|
||||
} else {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
outb(pvb_pairs[i].port, pvb_pairs[i].value);
|
||||
}
|
||||
break;
|
||||
case DIO_WORD: /* word values */
|
||||
pvw_pairs = (pvw_pair_t *) vdevio_pv_buf;
|
||||
if (DIO_INPUT == m_ptr->DIO_REQUEST) {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
pvw_pairs[i].value = inw(pvw_pairs[i].port);
|
||||
} else {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
outw(pvw_pairs[i].port, pvw_pairs[i].value);
|
||||
}
|
||||
break;
|
||||
case DIO_LONG: /* fall through: long values */
|
||||
default: /* only DIO_LONG can arrive here, see above switch */
|
||||
pvl_pairs = (pvl_pair_t *) vdevio_pv_buf;
|
||||
if (DIO_INPUT == m_ptr->DIO_REQUEST) {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
pvl_pairs[i].value = inl(pvl_pairs[i].port);
|
||||
} else {
|
||||
for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
|
||||
outl(pvb_pairs[i].port, pvl_pairs[i].value);
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
|
||||
/* Almost done, copy back results for input requests. */
|
||||
if (DIO_INPUT == m_ptr->REQUEST)
|
||||
phys_copy(kernel_phys, caller_phys, (phys_bytes) bytes);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
69
kernel/system/old/do_vircopy.c
Normal file
69
kernel/system/old/do_vircopy.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VIRCOPY
|
||||
*
|
||||
* 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"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vircopy *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_vircopy(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_vircopy(). Copy data by using virtual 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)) {
|
||||
kprintf("do_vircopy: illegal proc nr\n",NO_ARG);
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Copying from or to special segments can only done by the owner. */
|
||||
if ((vir_addr[i].segment & SEGMENT_TYPE) != LOCAL_SEG &&
|
||||
vir_addr[i].proc_nr != m_ptr->m_source) {
|
||||
kprintf("do_vircopy: special seg permission denied\n", NO_ARG);
|
||||
return(EPERM);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for overflow. This would happen for 64K segments and 16-bit
|
||||
* vir_bytes. Especially copying by the MM on do_fork() is affected.
|
||||
*/
|
||||
if (bytes != (vir_bytes) bytes) {
|
||||
kprintf("do_vircopy: overflow\n", NO_ARG);
|
||||
return(E2BIG);
|
||||
}
|
||||
|
||||
/* Now try to make the actual virtual copy. */
|
||||
return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );
|
||||
}
|
||||
|
||||
|
||||
38
kernel/system/old/do_xit.c
Normal file
38
kernel/system/old/do_xit.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*===========================================================================*
|
||||
* do_xit *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_xit(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_exit. A user process has exited (the MM sent the request).
|
||||
*/
|
||||
register struct proc *rp, *rc;
|
||||
struct proc *np, *xp;
|
||||
int exit_proc_nr;
|
||||
|
||||
/* Get a pointer to the process that exited. */
|
||||
exit_proc_nr = m_ptr->PR_PROC_NR;
|
||||
if (exit_proc_nr == SELF) exit_proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(exit_proc_nr)) return(EINVAL);
|
||||
rc = proc_addr(exit_proc_nr);
|
||||
|
||||
/* If this is a user process and the MM passed in a valid parent process,
|
||||
* accumulate the child times at the parent.
|
||||
*/
|
||||
if (isuserp(rc) && isokprocn(m_ptr->PR_PPROC_NR)) {
|
||||
rp = proc_addr(m_ptr->PR_PPROC_NR);
|
||||
lock();
|
||||
rp->child_utime += rc->user_time + rc->child_utime;
|
||||
rp->child_stime += rc->sys_time + rc->child_stime;
|
||||
unlock();
|
||||
}
|
||||
|
||||
/* Now call the routine to clean up of the process table slot. This cancels
|
||||
* outstanding timers, possibly removes the process from the message queues,
|
||||
* and resets important process table fields.
|
||||
*/
|
||||
clear_proc(exit_proc_nr);
|
||||
return(OK); /* tell MM that cleanup succeeded */
|
||||
}
|
||||
|
||||
|
||||
223
kernel/system/proctl.c
Normal file
223
kernel/system/proctl.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/* 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 MM)
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include "../sendmask.h"
|
||||
#include <signal.h>
|
||||
#if (CHIP == INTEL)
|
||||
#include "../protect.h"
|
||||
#endif
|
||||
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* 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);
|
||||
assert(isuserp(rpp));
|
||||
rpc = proc_addr(m_ptr->PR_PROC_NR);
|
||||
assert(isemptyp(rpc));
|
||||
|
||||
/* 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_flags |= NO_MAP; /* inhibit the process from running */
|
||||
|
||||
rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
|
||||
|
||||
/* Only 1 in group should have PENDING, child does not inherit trace status*/
|
||||
sigemptyset(&rpc->p_pending);
|
||||
rpc->p_pendcount = 0;
|
||||
rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
|
||||
|
||||
rpc->user_time = 0; /* set all the accounting times to 0 */
|
||||
rpc->sys_time = 0;
|
||||
rpc->child_utime = 0;
|
||||
rpc->child_stime = 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 MM. */
|
||||
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys;
|
||||
int caller; /* whose space has the new map (usually MM) */
|
||||
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 (MM) */
|
||||
|
||||
/* Extract message parameters and copy new memory map from MM. */
|
||||
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 MM. */
|
||||
src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr,
|
||||
sizeof(rp->p_memmap));
|
||||
assert(src_phys != 0);
|
||||
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_flags; /* save the previous value of the flags */
|
||||
rp->p_flags &= ~NO_MAP;
|
||||
if (old_flags != 0 && rp->p_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;
|
||||
#define NLEN (sizeof(rp->p_name)-1)
|
||||
|
||||
rp = proc_addr(m_ptr->PR_PROC_NR);
|
||||
assert(isuserp(rp));
|
||||
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_flags &= ~RECEIVING; /* MM does not reply to EXEC call */
|
||||
if (rp->p_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) NLEN);
|
||||
if (phys_name != 0) {
|
||||
phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN);
|
||||
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
|
||||
*np = 0;
|
||||
}
|
||||
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)
|
||||
* m1_i2: PR_PPROC_NR (slot number of parent process)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_xit *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_xit(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_exit. A user process has exited (the MM sent the request).
|
||||
*/
|
||||
register struct proc *rp, *rc;
|
||||
struct proc *np, *xp;
|
||||
int exit_proc_nr;
|
||||
|
||||
/* Get a pointer to the process that exited. */
|
||||
exit_proc_nr = m_ptr->PR_PROC_NR;
|
||||
if (exit_proc_nr == SELF) exit_proc_nr = m_ptr->m_source;
|
||||
if (! isokprocn(exit_proc_nr)) return(EINVAL);
|
||||
rc = proc_addr(exit_proc_nr);
|
||||
|
||||
/* If this is a user process and the MM passed in a valid parent process,
|
||||
* accumulate the child times at the parent.
|
||||
*/
|
||||
if (isuserp(rc) && isokprocn(m_ptr->PR_PPROC_NR)) {
|
||||
rp = proc_addr(m_ptr->PR_PPROC_NR);
|
||||
lock();
|
||||
rp->child_utime += rc->user_time + rc->child_utime;
|
||||
rp->child_stime += rc->sys_time + rc->child_stime;
|
||||
unlock();
|
||||
}
|
||||
|
||||
/* Now call the routine to clean up of the process table slot. This cancels
|
||||
* outstanding timers, possibly removes the process from the message queues,
|
||||
* and resets important process table fields.
|
||||
*/
|
||||
clear_proc(exit_proc_nr);
|
||||
return(OK); /* tell MM that cleanup succeeded */
|
||||
}
|
||||
|
||||
|
||||
227
kernel/system/sigctl.c
Normal file
227
kernel/system/sigctl.c
Normal file
@@ -0,0 +1,227 @@
|
||||
/* 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>
|
||||
INIT_ASSERT
|
||||
|
||||
/*===========================================================================*
|
||||
* do_sigctl *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_sigctl(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Only the MM and FS are allowed to use signal control operations. */
|
||||
if (m_ptr->m_source != MM_PROC_NR && m_ptr->m_source != FS_PROC_NR)
|
||||
return(EPERM);
|
||||
|
||||
/* Now see what request we got. The supported requests are S_GETSIG,
|
||||
* S_ENDSIG, S_SENDSIG, S_SIGRETURN, and S_KILL. Unsupported requests
|
||||
* result in an EINVAL error.
|
||||
*/
|
||||
switch(m_ptr->SIG_REQUEST) {
|
||||
|
||||
/* MM 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.
|
||||
*/
|
||||
case S_GETSIG: {
|
||||
|
||||
register struct proc *rp;
|
||||
|
||||
/* Find the next process with pending signals. */
|
||||
for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
|
||||
if (rp->p_flags & PENDING) {
|
||||
m_ptr->SIG_PROC = proc_number(rp);
|
||||
m_ptr->SIG_MAP = rp->p_pending;
|
||||
sigemptyset(&rp->p_pending); /* ball is in MM's court */
|
||||
rp->p_flags &= ~PENDING; /* blocked by SIG_PENDING */
|
||||
return(OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* No process with pending signals was found. */
|
||||
m_ptr->SIG_PROC = NONE;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a
|
||||
* call to cause_sig by a task
|
||||
*/
|
||||
case S_ENDSIG: {
|
||||
|
||||
register struct proc *rp;
|
||||
|
||||
rp = proc_addr(m_ptr->SIG_PROC);
|
||||
if (isemptyp(rp)) return(EINVAL); /* process already dead? */
|
||||
assert(isuserp(rp));
|
||||
|
||||
/* MM has finished one KSIG. Perhaps process is ready now? */
|
||||
if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
|
||||
&& (rp->p_flags &= ~SIG_PENDING) == 0)
|
||||
lock_ready(rp);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/* Handle sys_sendsig, POSIX-style signal handling.
|
||||
*/
|
||||
case S_SENDSIG: {
|
||||
|
||||
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);
|
||||
assert(isuserp(rp));
|
||||
|
||||
/* Get the sigmsg structure into our address space. */
|
||||
src_phys = umap_local(proc_addr(MM_PROC_NR), D, (vir_bytes)
|
||||
m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg));
|
||||
assert(src_phys != 0);
|
||||
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);
|
||||
}
|
||||
|
||||
/* POSIX style signals require sys_sigreturn to put things in order before
|
||||
* the signalled process can resume execution
|
||||
*/
|
||||
case S_SIGRETURN: {
|
||||
|
||||
struct sigcontext sc;
|
||||
register struct proc *rp;
|
||||
phys_bytes src_phys;
|
||||
|
||||
rp = proc_addr(m_ptr->SIG_PROC);
|
||||
if (! isuserp(rp)) {
|
||||
kprintf("S_SIGRETURN: message source: %d; ", m_ptr->m_source);
|
||||
kprintf("got non-user process rp: %d\n", rp->p_nr);
|
||||
}
|
||||
assert(isuserp(rp));
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Handle sys_kill(). Cause a signal to be sent to a process via MM.
|
||||
* 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.
|
||||
*/
|
||||
case S_KILL: {
|
||||
cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 MM.
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
241
kernel/system/srvrctl.c
Normal file
241
kernel/system/srvrctl.c
Normal file
@@ -0,0 +1,241 @@
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_EXIT
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m1_i1: EXIT_STATUS (exit status, 0 if normal exit)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include "../protect.h"
|
||||
#include <sys/svrctl.h>
|
||||
#include "../sendmask.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_exit *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_exit(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Handle sys_exit. A server or driver wants to exit. This may happen
|
||||
* on a panic, but also is done when MINIX is shutdown.
|
||||
*/
|
||||
register struct proc *rp;
|
||||
int proc_nr = m_ptr->m_source; /* can only exit own process */
|
||||
|
||||
if (m_ptr->EXIT_STATUS != 0) {
|
||||
kprintf("WARNING: system process %d exited with an error.\n", proc_nr );
|
||||
}
|
||||
|
||||
/* Now call the routine to clean up of the process table slot. This cancels
|
||||
* outstanding timers, possibly removes the process from the message queues,
|
||||
* and reset important process table fields.
|
||||
*/
|
||||
clear_proc(proc_nr);
|
||||
|
||||
/* If the shutdown sequence is active, see if it was awaiting the shutdown
|
||||
* of this system service. If so, directly continue the stop sequence.
|
||||
*/
|
||||
if (shutting_down && shutdown_process == proc_addr(proc_nr)) {
|
||||
stop_sequence(&shutdown_timer);
|
||||
}
|
||||
return(EDONTREPLY); /* no reply is sent */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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)
|
||||
*/
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* 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 MM 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_type = P_SERVER;
|
||||
rp->p_sendmask = ALLOW_ALL_MASK;
|
||||
send_mask_allow(proc_addr(RTL8139)->p_sendmask, proc_nr);
|
||||
send_mask_allow(proc_addr(MM_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);
|
||||
return(OK);
|
||||
}
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_MEMCTL
|
||||
*
|
||||
* 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_phys2seg *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_phys2seg(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;
|
||||
register struct proc *rp;
|
||||
phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS;
|
||||
vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE;
|
||||
int result;
|
||||
|
||||
kprintf("Using Experimental LDT selector for video memory\n", NO_ARG);
|
||||
|
||||
if (!protected_mode) {
|
||||
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) {
|
||||
rp = proc_addr(m_ptr->m_source);
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX], phys, size,
|
||||
USER_PRIVILEGE);
|
||||
selector = (EXTRA_LDT_INDEX * 0x08) | (1 * 0x04) | USER_PRIVILEGE;
|
||||
offset = 0;
|
||||
result = OK;
|
||||
} else {
|
||||
#if ENABLE_USERPRIV && ENABLE_LOOSELDT
|
||||
rp = proc_addr(m_ptr->m_source);
|
||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX], phys & ~0xFFFF, 0,
|
||||
USER_PRIVILEGE);
|
||||
selector = (EXTRA_LDT_INDEX * 0x08) | (1 * 0x04) | USER_PRIVILEGE;
|
||||
offset = phys & 0xFFFF;
|
||||
result = OK;
|
||||
#else
|
||||
result = E2BIG; /* allow settings only */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_KMALLOC
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l2: MEM_CHUNK_SIZE (request a buffer of this size)
|
||||
* m4_l1: MEM_CHUNK_BASE (return physical address on success)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
/*===========================================================================*
|
||||
* do_kmalloc *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_kmalloc(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
/* Request a (DMA) buffer to be allocated in one of the memory chunks. */
|
||||
phys_clicks tot_clicks;
|
||||
struct memory *memp;
|
||||
|
||||
tot_clicks = (m_ptr->MEM_CHUNK_SIZE + CLICK_SIZE-1) >> CLICK_SHIFT;
|
||||
memp = &mem[NR_MEMS];
|
||||
while ((--memp)->size < tot_clicks) {
|
||||
if (memp == mem) {
|
||||
return(ENOMEM);
|
||||
}
|
||||
}
|
||||
memp->size -= tot_clicks;
|
||||
m_ptr->MEM_CHUNK_BASE = (memp->base + memp->size) << CLICK_SHIFT;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
142
kernel/system/tracing.c
Normal file
142
kernel/system/tracing.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/* The system call implemented in this file:
|
||||
* m_type: SYS_TRACE
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i1: CTL_PROC_NR process that is traced
|
||||
* m2_i2: CTL_REQUEST trace request
|
||||
* m2_l1: CTL_ADDRESS address at traced process' space
|
||||
* m2_l2: CTL_DATA data to be written or returned here
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
#if ENABLE_K_TRACING /* only include code if tracing is enabled */
|
||||
|
||||
/*==========================================================================*
|
||||
* do_trace *
|
||||
*==========================================================================*/
|
||||
#define TR_VLSIZE ((vir_bytes) sizeof(long))
|
||||
|
||||
PUBLIC int do_trace(m_ptr)
|
||||
register message *m_ptr;
|
||||
{
|
||||
/* Handle the debugging commands supported by the ptrace system call
|
||||
* The commands are:
|
||||
* T_STOP stop the process
|
||||
* T_OK enable tracing by parent for this process
|
||||
* T_GETINS return value from instruction space
|
||||
* T_GETDATA return value from data space
|
||||
* T_GETUSER return value from user process table
|
||||
* T_SETINS set value from instruction space
|
||||
* T_SETDATA set value from data space
|
||||
* T_SETUSER set value in user process table
|
||||
* T_RESUME resume execution
|
||||
* T_EXIT exit
|
||||
* T_STEP set trace bit
|
||||
*
|
||||
* The T_OK and T_EXIT commands are handled completely by the memory manager,
|
||||
* all others come here.
|
||||
*/
|
||||
|
||||
register struct proc *rp;
|
||||
phys_bytes src, dst;
|
||||
vir_bytes tr_addr = (vir_bytes) m_ptr->CTL_ADDRESS;
|
||||
long tr_data = m_ptr->CTL_DATA;
|
||||
int tr_request = m_ptr->CTL_REQUEST;
|
||||
int tr_proc_nr = m_ptr->CTL_PROC_NR;
|
||||
int i;
|
||||
|
||||
rp = proc_addr(tr_proc_nr);
|
||||
if (isemptyp(rp)) return(EIO);
|
||||
switch (tr_request) {
|
||||
case T_STOP: /* stop process */
|
||||
if (rp->p_flags == 0) lock_unready(rp);
|
||||
rp->p_flags |= P_STOP;
|
||||
rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
|
||||
return(OK);
|
||||
|
||||
case T_GETINS: /* return value from instruction space */
|
||||
if (rp->p_memmap[T].mem_len != 0) {
|
||||
if ((src = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
|
||||
phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
|
||||
break;
|
||||
}
|
||||
/* Text space is actually data space - fall through. */
|
||||
|
||||
case T_GETDATA: /* return value from data space */
|
||||
if ((src = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
|
||||
phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
|
||||
break;
|
||||
|
||||
case T_GETUSER: /* return value from process table */
|
||||
if ((tr_addr & (sizeof(long) - 1)) != 0 ||
|
||||
tr_addr > sizeof(struct proc) - sizeof(long))
|
||||
return(EIO);
|
||||
tr_data = *(long *) ((char *) rp + (int) tr_addr);
|
||||
break;
|
||||
|
||||
case T_SETINS: /* set value in instruction space */
|
||||
if (rp->p_memmap[T].mem_len != 0) {
|
||||
if ((dst = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
|
||||
phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
|
||||
tr_data = 0;
|
||||
break;
|
||||
}
|
||||
/* Text space is actually data space - fall through. */
|
||||
|
||||
case T_SETDATA: /* set value in data space */
|
||||
if ((dst = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
|
||||
phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
|
||||
tr_data = 0;
|
||||
break;
|
||||
|
||||
case T_SETUSER: /* set value in process table */
|
||||
if ((tr_addr & (sizeof(reg_t) - 1)) != 0 ||
|
||||
tr_addr > sizeof(struct stackframe_s) - sizeof(reg_t))
|
||||
return(EIO);
|
||||
i = (int) tr_addr;
|
||||
#if (CHIP == INTEL)
|
||||
/* Altering segment registers might crash the kernel when it
|
||||
* tries to load them prior to restarting a process, so do
|
||||
* not allow it.
|
||||
*/
|
||||
if (i == (int) &((struct proc *) 0)->p_reg.cs ||
|
||||
i == (int) &((struct proc *) 0)->p_reg.ds ||
|
||||
i == (int) &((struct proc *) 0)->p_reg.es ||
|
||||
#if _WORD_SIZE == 4
|
||||
i == (int) &((struct proc *) 0)->p_reg.gs ||
|
||||
i == (int) &((struct proc *) 0)->p_reg.fs ||
|
||||
#endif
|
||||
i == (int) &((struct proc *) 0)->p_reg.ss)
|
||||
return(EIO);
|
||||
#endif
|
||||
if (i == (int) &((struct proc *) 0)->p_reg.psw)
|
||||
/* only selected bits are changeable */
|
||||
SETPSW(rp, tr_data);
|
||||
else
|
||||
*(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) tr_data;
|
||||
tr_data = 0;
|
||||
break;
|
||||
|
||||
case T_RESUME: /* resume execution */
|
||||
rp->p_flags &= ~P_STOP;
|
||||
if (rp->p_flags == 0) lock_ready(rp);
|
||||
tr_data = 0;
|
||||
break;
|
||||
|
||||
case T_STEP: /* set trace bit */
|
||||
rp->p_reg.psw |= TRACEBIT;
|
||||
rp->p_flags &= ~P_STOP;
|
||||
if (rp->p_flags == 0) lock_ready(rp);
|
||||
tr_data = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return(EIO);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#endif /* ENABLE_K_TRACING */
|
||||
Reference in New Issue
Block a user