- Kernel call handlers cleaned up. More strict checking of input parameters.

- Moved generic_handler() from system.c to system/do_irqctl.c.
- Set privileges of system processes somewhat stricter.
This commit is contained in:
Jorrit Herder 2005-07-29 15:26:23 +00:00
parent a93faca75f
commit 0946d128cd
25 changed files with 164 additions and 183 deletions

View file

@ -47,7 +47,7 @@ EXTERN reg_t mon_ss, mon_sp; /* boot monitor stack */
EXTERN int mon_return; /* true if we can return to monitor */
/* Variables that are initialized elsewhere are just extern here. */
extern struct system_image image[]; /* system image processes */
extern struct boot_image image[]; /* system image processes */
extern char *t_stack[]; /* task stack space */
extern struct segdesc_s gdt[]; /* global descriptor table */

View file

@ -30,6 +30,7 @@
*/
#define EMPTY_MASK (0)
#define FILLED_MASK (~0)
#define TASK_CALL_MASK (1 << RECEIVE)
#define USER_CALL_MASK ((1 << SENDREC) | (1 << ECHO))
/* Send masks determine to whom processes can send messages or notifications.

View file

@ -25,8 +25,6 @@
FORWARD _PROTOTYPE( void announce, (void));
FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
#define SHUTDOWN_TICKS 5 /* time allowed to do cleanup */
/*===========================================================================*
* main *
@ -34,7 +32,7 @@ FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
PUBLIC void main()
{
/* Start the ball rolling. */
struct system_image *ip; /* boot image pointer */
struct boot_image *ip; /* boot image pointer */
register struct proc *rp; /* process pointer */
register struct priv *sp; /* privilege structure pointer */
register int i, s;
@ -188,8 +186,8 @@ PUBLIC void prepare_shutdown(how)
int how;
{
/* This function prepares to shutdown MINIX. */
register struct proc *rp;
static timer_t shutdown_timer;
register struct proc *rp;
message m;
/* Show debugging dumps on panics. Make sure that the TTY task is still
@ -221,7 +219,7 @@ int how;
*/
kprintf("MINIX will now be shut down ...\n");
tmr_arg(&shutdown_timer)->ta_int = how;
set_timer(&shutdown_timer, get_uptime() + SHUTDOWN_TICKS, shutdown);
set_timer(&shutdown_timer, get_uptime() + HZ, shutdown);
}

View file

@ -51,7 +51,6 @@ _PROTOTYPE( phys_bytes umap_remote, (struct proc *rp, int seg,
vir_bytes vir_addr, vir_bytes bytes) );
_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
vir_bytes bytes) );
_PROTOTYPE( int generic_handler, (irq_hook_t *hook) );
#if (CHIP == INTEL)

View file

@ -20,15 +20,11 @@
* numap_local: umap_local D segment from proc nr instead of pointer
* virtual_copy: copy bytes from one virtual address to another
* get_randomness: accumulate randomness in a buffer
* generic_handler: interrupt handler for user-level device drivers
*
* Changes:
* Apr 25, 2005 made mapping of call vector explicit (Jorrit N. Herder)
* Oct 17, 2004 generic handler and IRQ policies (Jorrit N. Herder)
* Oct 10, 2004 dispatch system calls from call vector (Jorrit N. Herder)
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
* Sep 10, 2004 system call functions in library (Jorrit N. Herder)
* 2004 to 2005 various new syscalls (see syslib.h) (Jorrit N. Herder)
* 2004 to 2005 various new syscalls (see system.h) (Jorrit N. Herder)
*/
#include "kernel.h"
@ -184,6 +180,7 @@ int proc_type; /* system or user process flag */
if (sp->s_proc_nr != NONE) return(ENOSPC);
rc->p_priv = sp; /* assign new slot */
rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */
rc->p_priv->s_flags = SYS_PROC; /* mark as privileged */
} else {
rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */
rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */
@ -228,34 +225,6 @@ int source;
}
/*===========================================================================*
* generic_handler *
*===========================================================================*/
PUBLIC int generic_handler(hook)
irq_hook_t *hook;
{
/* This function handles hardware interrupt in a simple and generic way. All
* interrupts are transformed into messages to a driver. The IRQ line will be
* reenabled if the policy says so.
*/
/* As a side-effect, the interrupt handler gathers random information by
* timestamping the interrupt events. This is used for /dev/random.
*/
get_randomness(hook->irq);
/* Add a bit for this interrupt to the process' pending interrupts. When
* sending the notification message, this bit map will be magically set
* as an argument.
*/
priv(proc_addr(hook->proc_nr))->s_int_pending |= (1 << hook->notify_id);
/* Build notification message and return. */
lock_notify(HARDWARE, hook->proc_nr);
return(hook->policy & IRQ_REENABLE);
}
/*===========================================================================*
* send_sig *
*===========================================================================*/

View file

@ -25,7 +25,7 @@ OBJECTS = \
$(SYSTEM)(do_trace.o) \
$(SYSTEM)(do_nice.o) \
$(SYSTEM)(do_times.o) \
$(SYSTEM)(do_alarm.o) \
$(SYSTEM)(do_setalarm.o) \
$(SYSTEM)(do_irqctl.o) \
$(SYSTEM)(do_devio.o) \
$(SYSTEM)(do_vdevio.o) \
@ -82,8 +82,8 @@ $(SYSTEM)(do_nice.o): do_nice.c
$(SYSTEM)(do_times.o): do_times.c
$(CC) do_times.c
$(SYSTEM)(do_alarm.o): do_alarm.c
$(CC) do_alarm.c
$(SYSTEM)(do_setalarm.o): do_setalarm.c
$(CC) do_setalarm.c
$(SYSTEM)(do_irqctl.o): do_irqctl.c
$(CC) do_irqctl.c

View file

@ -20,23 +20,25 @@ PUBLIC int do_abort(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Handle sys_abort. MINIX is unable to continue. This can originate in the
* PM (normal abort or panic) or FS (panic), or TTY (user issued CTRL-ALT-DEL
* or ESC after debugging dumps).
* PM (normal abort or panic) or FS (panic), or TTY (after CTRL-ALT-DEL).
*/
int how = m_ptr->ABRT_HOW;
int proc_nr;
int length;
phys_bytes src_phys;
/* See if the monitor is to run the specified instructions. */
if (how == RBT_MONITOR) {
int proc_nr = m_ptr->ABRT_MON_PROC;
int length = m_ptr->ABRT_MON_LEN + 1;
vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR;
phys_bytes src_phys = numap_local(proc_nr, src_vir, length);
/* Validate length and address of shutdown code before copying. */
if (length > kinfo.params_size || src_phys == 0)
phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
else
phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
proc_nr = m_ptr->ABRT_MON_PROC;
if (! isokprocn(proc_nr)) return(EINVAL);
length = m_ptr->ABRT_MON_LEN + 1;
if (length > kinfo.params_size) return(E2BIG);
src_phys = numap_local(proc_nr,(vir_bytes)m_ptr->ABRT_MON_ADDR,length);
if (! src_phys) return(EFAULT);
/* Parameters seem ok, copy them and prepare shutting down. */
phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
}
/* Now prepare to shutdown MINIX. */

View file

@ -23,8 +23,11 @@ message *m_ptr; /* pointer to request message */
*/
register struct proc *rp;
/* Get process pointer and verify that it had signals pending. If the
* process is already dead its flags will be reset.
*/
rp = proc_addr(m_ptr->SIG_PROC);
if (isemptyp(rp)) return(EINVAL); /* process already dead? */
if (! (rp->p_rts_flags & SIG_PENDING)) return(EINVAL);
/* PM has finished one kernel signal. Perhaps process is ready now? */
if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */

View file

@ -4,7 +4,6 @@
* The parameters for this system call are:
* m1_i1: PR_PROC_NR (child's process table slot)
* m1_i2: PR_PPROC_NR (parent, process that forked)
* m1_i3: PR_PID (child pid received from PM)
*/
#include "../system.h"
@ -33,6 +32,18 @@ register message *m_ptr; /* pointer to request message */
rpc = proc_addr(m_ptr->PR_PROC_NR);
if (isemptyp(rpp) || ! isemptyp(rpc)) return(EINVAL);
/* If this is a system process, make sure the child process gets its own
* privilege structure for accounting. This is the only part that can fail,
* so do this before allocating the process table slot.
*/
if (priv(rpc)->s_flags & SYS_PROC) {
if (OK != (i=get_priv(rpc, SYS_PROC))) return(i); /* get structure */
for (i=0; i< BITMAP_CHUNKS(NR_SYS_PROCS); i++) /* remove pending: */
priv(rpc)->s_notify_pending.chunk[i] = 0; /* - notifications */
priv(rpc)->s_int_pending = 0; /* - interrupts */
sigemptyset(&priv(rpc)->s_sig_pending); /* - signals */
}
/* Copy parent 'proc' struct to child. And reinitialize some fields. */
#if (CHIP == INTEL)
old_ldt_sel = rpc->p_ldt_sel; /* backup local descriptors */
@ -52,16 +63,6 @@ register message *m_ptr; /* pointer to request message */
rpc->p_user_time = 0; /* set all the accounting times to 0 */
rpc->p_sys_time = 0;
/* If this is a system process, make sure the child process gets its own
* privilege structure for accounting.
*/
if (priv(rpc)->s_flags & SYS_PROC) {
if (OK != (i=get_priv(rpc, SYS_PROC))) return(i); /* get structure */
for (i=0; i< BITMAP_CHUNKS(NR_SYS_PROCS); i++) /* remove pending: */
priv(rpc)->s_notify_pending.chunk[i] = 0; /* - notifications */
priv(rpc)->s_int_pending = 0; /* - interrupts */
sigemptyset(&priv(rpc)->s_sig_pending); /* - signals */
}
return(OK);
}

View file

@ -3,7 +3,6 @@
*
* 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_VAL_PTR2 (second, optional pointer)
@ -47,7 +46,7 @@ register message *m_ptr; /* pointer to request message */
break;
}
case GET_IMAGE: {
length = sizeof(struct system_image) * NR_BOOT_PROCS;
length = sizeof(struct boot_image) * NR_BOOT_PROCS;
src_phys = vir2phys(image);
break;
}

View file

@ -5,7 +5,8 @@
* m5_c1: IRQ_REQUEST (control operation to perform)
* m5_c2: IRQ_VECTOR (irq line that must be controlled)
* m5_i1: IRQ_POLICY (irq policy allows reenabling interrupts)
* m5_l3: IRQ_HOOK_ID (index of irq hook assigned at kernel)
* m5_l3: IRQ_HOOK_ID (provides index to be returned on interrupt)
* ,, ,, (returns index of irq hook assigned at kernel)
*
* Author:
* Jorrit N. Herder <jnherder@cs.vu.nl>
@ -13,8 +14,11 @@
#include "../system.h"
#if USE_IRQCTL
FORWARD _PROTOTYPE(int generic_handler, (irq_hook_t *hook));
/*===========================================================================*
* do_irqctl *
*===========================================================================*/
@ -99,5 +103,33 @@ register message *m_ptr; /* pointer to request message */
return(r);
}
/*===========================================================================*
* generic_handler *
*===========================================================================*/
PRIVATE int generic_handler(hook)
irq_hook_t *hook;
{
/* This function handles hardware interrupt in a simple and generic way. All
* interrupts are transformed into messages to a driver. The IRQ line will be
* reenabled if the policy says so.
*/
/* As a side-effect, the interrupt handler gathers random information by
* timestamping the interrupt events. This is used for /dev/random.
*/
get_randomness(hook->irq);
/* Add a bit for this interrupt to the process' pending interrupts. When
* sending the notification message, this bit map will be magically set
* as an argument.
*/
priv(proc_addr(hook->proc_nr))->s_int_pending |= (1 << hook->notify_id);
/* Build notification message and return. */
lock_notify(HARDWARE, hook->proc_nr);
return(hook->policy & IRQ_REENABLE);
}
#endif /* USE_IRQCTL */

View file

@ -30,6 +30,7 @@ message *m_ptr; /* pointer to request message */
int sig_nr = m_ptr->SIG_NUMBER;
if (! isokprocn(proc_nr) || sig_nr > _NSIG) return(EINVAL);
if (iskerneln(proc_nr)) return(EPERM);
if (m_ptr->m_source == PM_PROC_NR) {
/* Directly send signal notification to a system process. */

View file

@ -2,9 +2,9 @@
* m_type: SYS_MEMSET
*
* The parameters for this system call are:
* m1_p1: MEM_PTR (virtual address)
* m1_i1: MEM_COUNT (returns physical address)
* m1_i2: MEM_PATTERN (size of datastructure)
* m2_p1: MEM_PTR (virtual address)
* m2_l1: MEM_COUNT (returns physical address)
* m2_l2: MEM_PATTERN (size of datastructure)
*/
#include "../system.h"

View file

@ -26,6 +26,7 @@ message *m_ptr; /* pointer to request message */
caller = m_ptr->m_source;
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
if (! isokprocn(m_ptr->PR_PROC_NR)) return(EINVAL);
if (iskerneln(m_ptr->PR_PROC_NR)) return(EPERM);
rp = proc_addr(m_ptr->PR_PROC_NR);
/* Copy the map from PM. */

View file

@ -23,6 +23,7 @@ PUBLIC int do_nice(message *m_ptr)
/* Extract the message parameters and do sanity checking. */
proc_nr = m_ptr->PR_PROC_NR;
if (! isokprocn(proc_nr)) return(EINVAL);
if (iskerneln(proc_nr)) return(EPERM);
pri = m_ptr->PR_PRIORITY;
if (pri < PRIO_MIN || pri > PRIO_MAX) return(EINVAL);

View file

@ -33,7 +33,7 @@ message *m_ptr; /* pointer to request message */
/* Make sure this process has its own privileges structure. */
if (! (priv(rp)->s_flags & SYS_PROC))
get_priv(rp, SYS_PROC);
if ((i=get_priv(rp, SYS_PROC)) != OK) return(i);
/* Now update the process' privileges as requested. */
rp->p_priv->s_call_mask = FILLED_MASK;

View file

@ -26,10 +26,13 @@ register message *m_ptr; /* pointer to request message */
long port = m_ptr->DIO_PORT;
phys_bytes phys_buf;
/* Check if process number is OK. */
/* Check if process number is OK. A process number is allowed here, because
* driver may directly provide a pointer to a buffer at the user-process
* that initiated the device I/O. Kernel processes, of course, are denied.
*/
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
if (! isokprocn(proc_nr))
return(EINVAL);
if (! isokprocn(proc_nr)) return(EINVAL);
if (iskerneln(proc_nr)) return(EPERM);
/* Get and check physical address. */
if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)

View file

@ -23,6 +23,7 @@ PUBLIC int do_setalarm(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* A process requests a synchronous alarm, or wants to cancel its alarm. */
register struct proc *rp; /* pointer to requesting process */
int proc_nr; /* which process wants the alarm */
long exp_time; /* expiration time for this alarm */
int use_abs_time; /* use absolute or relative time */
@ -30,12 +31,14 @@ message *m_ptr; /* pointer to request message */
clock_t uptime; /* placeholder for current uptime */
/* Extract shared parameters from the request message. */
proc_nr = m_ptr->m_source; /* process to interrupt later */
exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */
use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */
proc_nr = m_ptr->m_source; /* process to interrupt later */
rp = proc_addr(proc_nr);
if (! (priv(rp)->s_flags & SYS_PROC)) return(EPERM);
/* Get the timer structure and set the parameters for this alarm. */
tp = &(proc_addr(proc_nr)->p_priv->s_alarm_timer);
tp = &(priv(rp)->s_alarm_timer);
tmr_arg(tp)->ta_int = proc_nr;
tp->tmr_func = cause_alarm;

View file

@ -27,6 +27,8 @@ message *m_ptr; /* pointer to request message */
register struct proc *rp;
phys_bytes src_phys;
if (! isokprocn(m_ptr->SIG_PROC)) return(EINVAL);
if (iskerneln(m_ptr->SIG_PROC)) return(EPERM);
rp = proc_addr(m_ptr->SIG_PROC);
/* Copy in the sigcontext structure. */

View file

@ -29,6 +29,8 @@ message *m_ptr; /* pointer to request message */
struct sigcontext sc, *scp;
struct sigframe fr, *frp;
if (! isokprocn(m_ptr->SIG_PROC)) return(EINVAL);
if (iskerneln(m_ptr->SIG_PROC)) return(EPERM);
rp = proc_addr(m_ptr->SIG_PROC);
/* Get the sigmsg structure into our address space. */

View file

@ -47,6 +47,9 @@ register message *m_ptr;
int tr_proc_nr = m_ptr->CTL_PROC_NR;
int i;
if (! isokprocn(tr_proc_nr)) return(EINVAL);
if (iskerneln(tr_proc_nr)) return(EPERM);
rp = proc_addr(tr_proc_nr);
if (isemptyp(rp)) return(EIO);
switch (tr_request) {

View file

@ -2,13 +2,9 @@
* m_type: SYS_VIRVCOPY, SYS_PHYSVCOPY
*
* The parameters for this system call are:
* m5_c1: CP_SRC_SPACE
* m5_l1: CP_SRC_ADDR
* m5_i1: CP_SRC_PROC_NR
* m5_c2: CP_DST_SPACE
* m5_l2: CP_DST_ADDR
* m5_i2: CP_DST_PROC_NR
* m5_l3: CP_NR_BYTES
* m1_i3: VCP_VEC_SIZE size of copy request vector
* m1_p1: VCP_VEC_ADDR address of vector at caller
* m1_i2: VCP_NR_OK number of successfull copies
*/
#include "../system.h"
@ -52,16 +48,17 @@ register message *m_ptr; /* pointer to request message */
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
/* Assume vector with requests is correct. Try to copy everything. */
m_ptr->VCP_NR_OK = 0;
for (i=0; i<nr_req; i++) {
req = &vir_cp_req[i];
/* Check if physical addressing is used without SYS_PHYSVCOPY. */
if (((req->src.segment | req->dst.segment) & PHYS_SEG) &&
m_ptr->m_type != SYS_PHYSVCOPY)
return(EPERM);
m_ptr->m_type != SYS_PHYSVCOPY) return(EPERM);
if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK)
return(s);
m_ptr->VCP_NR_OK ++;
}
return(OK);
}

View file

@ -14,16 +14,11 @@
#if USE_VDEVIO
/* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE];
PRIVATE char vdevio_buf[VDEVIO_BUF_SIZE];
PRIVATE pvb_pair_t *pvb = (pvb_pair_t *) vdevio_buf;
PRIVATE pvw_pair_t *pvw = (pvw_pair_t *) vdevio_buf;
PRIVATE pvl_pair_t *pvl = (pvl_pair_t *) vdevio_buf;
/* 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 *
@ -37,88 +32,57 @@ register message *m_ptr; /* pointer to request message */
* 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;
int caller_proc; /* process number 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_proc = m_ptr->m_source;
caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes);
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(13, "do_vdevio");
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(13);
int vec_size; /* size of vector */
int io_in; /* true if input */
size_t bytes; /* # bytes to be copied */
int caller_proc; /* process number of caller */
vir_bytes caller_vir; /* virtual address at caller */
phys_bytes caller_phys; /* physical address at caller */
int i;
/* 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);
/* Get the request, size of the request vector, and check the values. */
if (m_ptr->DIO_REQUEST == DIO_INPUT) io_in = TRUE;
else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) io_in = FALSE;
else return(EINVAL);
if ((vec_size = m_ptr->DIO_VEC_SIZE) <= 0) return(EINVAL);
switch (m_ptr->DIO_TYPE) {
case DIO_BYTE: bytes = vec_size * sizeof(pvb_pair_t); break;
case DIO_WORD: bytes = vec_size * sizeof(pvw_pair_t); break;
case DIO_LONG: bytes = vec_size * sizeof(pvl_pair_t); break;
default: return(EINVAL); /* check type once and for all */
}
if (bytes > sizeof(vdevio_buf)) return(E2BIG);
/* Calculate physical addresses and copy (port,value)-pairs from user. */
caller_proc = m_ptr->m_source;
caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes);
if (0 == caller_phys) return(EFAULT);
phys_copy(caller_phys, vir2phys(vdevio_buf), (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.
*/
lock(13, "do_vdevio");
switch (m_ptr->DIO_TYPE) {
case DIO_BYTE: /* byte values */
if (io_in) for (i=0; i<vec_size; i++) pvb[i].value = inb(pvb[i].port);
else for (i=0; i<vec_size; i++) outb(pvb[i].port, pvb[i].value);
break;
case DIO_WORD: /* word values */
if (io_in) for (i=0; i<vec_size; i++) pvw[i].value = inw(pvw[i].port);
else for (i=0; i<vec_size; i++) outw(pvw[i].port, pvw[i].value);
break;
default: /* long values */
if (io_in) for (i=0; i<vec_size; i++) pvl[i].value = inl(pvl[i].port);
else for (i=0; i<vec_size; i++) outl(pvb[i].port, pvl[i].value);
}
unlock(13);
/* Almost done, copy back results for input requests. */
if (io_in) phys_copy(vir2phys(vdevio_buf), caller_phys, (phys_bytes) bytes);
return(OK);
}
#endif /* USE_VDEVIO */

View file

@ -19,7 +19,7 @@
* or PRIVATE. The reason for this is that extern variables cannot have a
* default initialization. If such variables are shared, they must also be
* declared in one of the *.h files without the initialization. Examples
* include 'system_image' (this file) and 'idt' and 'gdt' (protect.c).
* include 'boot_image' (this file) and 'idt' and 'gdt' (protect.c).
*
* Changes:
* Nov 10, 2004 removed controller->driver mappings (Jorrit N. Herder)
@ -68,10 +68,10 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
#define USER_T 8 /* ticks */
#define SYS_T 16 /* ticks */
PUBLIC struct system_image image[] = {
PUBLIC struct boot_image image[] = {
{ IDLE, idle_task, IDLE_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_MASK, EMPTY_MASK, "IDLE" },
{ CLOCK, clock_task, TASK_F, SYS_T, TASK_Q, CLOCK_S, FILLED_MASK, SYSTEM_SEND_MASK, "CLOCK" },
{ SYSTEM, sys_task, TASK_F, SYS_T, TASK_Q, SYSTEM_S, FILLED_MASK, SYSTEM_SEND_MASK, "SYSTEM" },
{ CLOCK, clock_task, TASK_F, SYS_T, TASK_Q, CLOCK_S, TASK_CALL_MASK, SYSTEM_SEND_MASK, "CLOCK" },
{ SYSTEM, sys_task, TASK_F, SYS_T, TASK_Q, SYSTEM_S, TASK_CALL_MASK, SYSTEM_SEND_MASK, "SYSTEM" },
{ HARDWARE, 0, TASK_F, SYS_T, TASK_Q, HARDWARE_S, EMPTY_MASK, SYSTEM_SEND_MASK, "KERNEL" },
{ PM_PROC_NR, 0, SYS_F, SYS_T, 3, 0, FILLED_MASK, SERVER_SEND_MASK, "PM" },
{ FS_PROC_NR, 0, SYS_F, SYS_T, 4, 0, FILLED_MASK, SERVER_SEND_MASK, "FS" },
@ -111,5 +111,5 @@ PUBLIC struct system_image image[] = {
* a compile time error. Note that no space is allocated because 'dummy' is
* declared extern.
*/
extern int dummy[(NR_BOOT_PROCS==sizeof(image)/sizeof(struct system_image))?1:-1];
extern int dummy[(NR_BOOT_PROCS==sizeof(image)/sizeof(struct boot_image))?1:-1];

View file

@ -10,7 +10,7 @@ typedef struct { /* bitmap for system indexes */
bitchunk_t chunk[BITMAP_CHUNKS(NR_SYS_PROCS)];
} sys_map_t;
struct system_image {
struct boot_image {
proc_nr_t proc_nr; /* process number to use */
task_t *initial_pc; /* start function for tasks */
int flags; /* process flags */