From 42ab14815595104f3483532056f5ff1444ea0a0d Mon Sep 17 00:00:00 2001 From: Jorrit Herder Date: Thu, 14 Jul 2005 15:12:12 +0000 Subject: [PATCH] Reorganized system call library; uses separate file per call now. New configuration header file to include/ exclude functionality. Extracted privileged features from struct proc and create new struct priv. Renamed various system calls for readability. --- kernel/Makefile | 24 ++- kernel/clock.c | 64 +++---- kernel/const.h | 76 +++----- kernel/{system/debugging.c => debug.c} | 33 ++-- kernel/debug.h | 69 +++++++- kernel/exception.c | 5 +- kernel/glo.h | 12 +- kernel/i8259.c | 4 +- kernel/ipc.h | 8 +- kernel/kernel.h | 16 +- kernel/klibc.c | 39 +--- kernel/main.c | 37 ++-- kernel/proc.c | 225 +++++++++++++++++------- kernel/proc.h | 22 +-- kernel/protect.c | 1 - kernel/proto.h | 12 +- kernel/system.c | 116 +++++++----- kernel/system.h | 149 +++++++++++++--- kernel/system/Makefile | 117 +++++++++++- kernel/system/clock.c | 138 --------------- kernel/system/copying.c | 176 ------------------ kernel/system/do_abort.c | 46 +++++ kernel/system/do_alarm.c | 77 ++++++++ kernel/system/do_copy.c | 71 ++++++++ kernel/system/do_devio.c | 44 +++++ kernel/system/do_endksig.c | 49 ++++++ kernel/system/do_exec.c | 63 +++++++ kernel/system/do_exit.c | 42 +++++ kernel/system/do_fork.c | 62 +++++++ kernel/system/{misc.c => do_getinfo.c} | 72 ++------ kernel/system/do_getksig.c | 55 ++++++ kernel/system/{irqctl.c => do_irqctl.c} | 5 +- kernel/system/do_kill.c | 41 +++++ kernel/system/do_memset.c | 27 +++ kernel/system/do_newmap.c | 53 ++++++ kernel/system/do_schedctl.c | 50 ++++++ kernel/system/do_sdevio.c | 61 +++++++ kernel/system/do_segctl.c | 84 +++++++++ kernel/system/do_sigreturn.c | 79 +++++++++ kernel/system/do_sigsend.c | 89 ++++++++++ kernel/system/do_svrctl.c | 72 ++++++++ kernel/system/do_times.c | 40 +++++ kernel/system/{tracing.c => do_trace.c} | 3 +- kernel/system/do_umap.c | 52 ++++++ kernel/system/do_unused.c | 15 ++ kernel/system/do_vcopy.c | 67 +++++++ kernel/system/{devio.c => do_vdevio.c} | 104 +---------- kernel/system/priority.c | 56 ------ kernel/system/proctl.c | 209 ---------------------- kernel/system/sigctl.c | 192 -------------------- kernel/system/sysctl.c | 178 ------------------- kernel/table.c | 44 ++--- kernel/type.h | 15 +- 53 files changed, 1957 insertions(+), 1503 deletions(-) rename kernel/{system/debugging.c => debug.c} (87%) delete mode 100644 kernel/system/clock.c delete mode 100644 kernel/system/copying.c create mode 100644 kernel/system/do_abort.c create mode 100644 kernel/system/do_alarm.c create mode 100644 kernel/system/do_copy.c create mode 100644 kernel/system/do_devio.c create mode 100644 kernel/system/do_endksig.c create mode 100644 kernel/system/do_exec.c create mode 100644 kernel/system/do_exit.c create mode 100644 kernel/system/do_fork.c rename kernel/system/{misc.c => do_getinfo.c} (63%) create mode 100644 kernel/system/do_getksig.c rename kernel/system/{irqctl.c => do_irqctl.c} (98%) create mode 100644 kernel/system/do_kill.c create mode 100644 kernel/system/do_memset.c create mode 100644 kernel/system/do_newmap.c create mode 100644 kernel/system/do_schedctl.c create mode 100644 kernel/system/do_sdevio.c create mode 100644 kernel/system/do_segctl.c create mode 100644 kernel/system/do_sigreturn.c create mode 100644 kernel/system/do_sigsend.c create mode 100644 kernel/system/do_svrctl.c create mode 100644 kernel/system/do_times.c rename kernel/system/{tracing.c => do_trace.c} (99%) create mode 100644 kernel/system/do_umap.c create mode 100644 kernel/system/do_unused.c create mode 100644 kernel/system/do_vcopy.c rename kernel/system/{devio.c => do_vdevio.c} (62%) delete mode 100644 kernel/system/priority.c delete mode 100644 kernel/system/proctl.c delete mode 100644 kernel/system/sigctl.c delete mode 100644 kernel/system/sysctl.c diff --git a/kernel/Makefile b/kernel/Makefile index e973641f0..259e6a1b4 100755 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -15,27 +15,23 @@ LDFLAGS = -i HEAD = mpx.o OBJS = start.o protect.o klibc.o klib.o table.o main.o proc.o \ - i8259.o exception.o system.o clock.o misc.o -SYS_OBJS = $s/proctl.o $s/copying.o $s/devio.o $s/sysctl.o $s/misc.o \ - $s/sigctl.o $s/tracing.o $s/clock.o $s/irqctl.o $s/debugging.o \ - $s/priority.o -LIBS = -ltimers + i8259.o exception.o system.o clock.o utility.o debug.o +SYSTEM = system.a +LIBS = -ltimers # What to make. -kernel build: $(HEAD) $(OBJS) $(SYS_OBJS) - $(LD) $(CFLAGS) $(LDFLAGS) -o kernel $(HEAD) $(OBJS) $(SYS_OBJS) $(LIBS) - install -S 0 kernel - -$(SYS_OBJS): - cd system && $(MAKE) - -all install: +all: build +kernel build install: $(HEAD) $(OBJS) cd system && $(MAKE) -$(MAKEFLAGS) $@ + $(LD) $(CFLAGS) $(LDFLAGS) -o kernel \ + $(HEAD) $(OBJS) \ + $(SYSTEM) $(LIBS) + install -S 0 kernel clean: cd system && $(MAKE) -$(MAKEFLAGS) $@ - rm -f *.o *.bak kernel + rm -f *.a *.o *.bak kernel depend: cd system && $(MAKE) -$(MAKEFLAGS) $@ diff --git a/kernel/clock.c b/kernel/clock.c index 3cb3c697e..3cfb62394 100755 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -2,8 +2,8 @@ * Important events that are handled by the CLOCK include alarm timers and * (re)scheduling user processes. * The CLOCK offers a direct interface to kernel processes. System services - * can access its services through system calls, such as sys_syncalrm(). The - * CLOCK task thus is hidden for the outside. + * can access its services through system calls, such as sys_setalarm(). The + * CLOCK task thus is hidden for the outside world. * * Changes: * Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder) @@ -29,11 +29,10 @@ * The watchdog functions of expired timers are executed in do_clocktick(). * It is crucial that watchdog functions cannot block, or the CLOCK task may * be blocked. Do not send() a message when the receiver is not expecting it. - * The use of notify(), which always returns, is strictly preferred! + * Instead, notify(), which always returns, should be used. */ #include "kernel.h" -#include "debug.h" #include "proc.h" #include #include @@ -159,46 +158,31 @@ message *m_ptr; /* pointer to request message */ PRIVATE int clock_handler(hook) irq_hook_t *hook; { -/* This executes on every clock tick (i.e., every time the timer chip - * generates an interrupt). It does a little bit of work so the clock - * task does not have to be called on every tick. +/* This executes on each clock tick (i.e., every time the timer chip generates + * an interrupt). It does a little bit of work so the clock task does not have + * to be called on every tick. The clock task is called when: * - * Switch context to do_clocktick() if an alarm has gone off. - * Also switch there to reschedule if the reschedule will do something. - * This happens when - * (1) quantum has expired - * (2) current process received full quantum (as clock sampled it!) - * (3) something else is ready to run. + * (1) the scheduling quantum of the running process has expired, or + * (2) a timer has expired and the watchdog function should be run. * - * Many global global and static variables are accessed here. The safety - * of this must be justified. Most of them are not changed here: + * Many global global and static variables are accessed here. The safety of + * this must be justified. All scheduling and message passing code acquires a + * lock by temporarily disabling interrupts, so no conflicts with calls from + * the task level can occur. Furthermore, interrupts are not reentrant, the + * interrupt handler cannot be bothered by other interrupts. + * + * Variables that are updated in the clock's interrupt handler: + * lost_ticks: + * Clock ticks counted outside the clock task. This for example + * is used when the boot monitor processes a real mode interrupt. + * realtime: + * The current uptime is incremented with all outstanding ticks. * proc_ptr, bill_ptr: * These are used for accounting. It does not matter if proc.c * is changing them, provided they are always valid pointers, * since at worst the previous process would be billed. - * next_timeout, realtime, sched_ticks, bill_ptr, prev_ptr, - * These are tested to decide whether to call notify(). It - * does not matter if the test is sometimes (rarely) backwards - * due to a race, since this will only delay the high-level - * processing by one tick, or call the high level unnecessarily. - * The variables which are changed require more care: - * rp->p_user_time, rp->p_sys_time: - * These are protected by explicit locks in system.c. - * lost_ticks: - * Clock ticks counted outside the clock task. - * sched_ticks, prev_ptr: - * Updating these competes with similar code in do_clocktick(). - * No lock is necessary, because if bad things happen here - * (like sched_ticks going negative), the code in do_clocktick() - * will restore the variables to reasonable values, and an - * occasional missed or extra sched() is harmless. - * - * Are these complications worth the trouble? Well, they make the system 15% - * faster on a 5MHz 8088, and make task debugging much easier since there are - * no task switches on an inactive system. */ register unsigned ticks; - message m; /* Acknowledge the PS/2 clock interrupt. */ if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT); @@ -215,17 +199,16 @@ irq_hook_t *hook; */ proc_ptr->p_user_time += ticks; if (proc_ptr != bill_ptr) bill_ptr->p_sys_time += ticks; - if (proc_ptr->p_flags & PREEMPTIBLE) proc_ptr->p_sched_ticks -= ticks; + if (priv(proc_ptr)->s_flags & PREEMPTIBLE) proc_ptr->p_sched_ticks -= ticks; /* Check if do_clocktick() must be called. Done for alarms and scheduling. * Some processes, such as the kernel tasks, cannot be preempted. */ if ((next_timeout <= realtime) || (proc_ptr->p_sched_ticks <= 0)) { prev_ptr = proc_ptr; /* store running process */ - m.NOTIFY_TYPE = HARD_INT; - lock_notify(CLOCK, &m); /* send event notification */ + lock_alert(HARDWARE, CLOCK); /* send notification */ } - return(1); /* reenable clock interrupts */ + return(1); /* reenable interrupts */ } @@ -289,6 +272,7 @@ PRIVATE void init_clock() enable_irq(&clock_hook); /* ready for clock interrupts */ } + /*===========================================================================* * clock_stop * *===========================================================================*/ diff --git a/kernel/const.h b/kernel/const.h index 23463571a..e640a2058 100755 --- a/kernel/const.h +++ b/kernel/const.h @@ -1,22 +1,21 @@ -/* General constants used by the kernel. */ +/* General macros and constants used by the kernel. */ +#ifndef CONST_H +#define CONST_H #include /* interrupt numbers and hardware vectors */ #include /* port addresses and magic numbers */ #include /* BIOS addresses, sizes and magic numbers */ #include /* BIOS addresses, sizes and magic numbers */ #include +#include "config.h" /* To translate an address in kernel space to a physical address. This is * the same as umap_local(proc_ptr, D, vir, sizeof(*vir)), but less costly. */ #define vir2phys(vir) (kinfo.data_base + (vir_bytes) (vir)) -/* Constants used in virtual_copy(). Values must be 0 and 1, respectively! */ -#define _SRC_ 0 -#define _DST_ 1 - /* Translate a pointer to a field in a structure to a pointer to the structure - * itself. So it translates '&struct_ptr->field' back to 'struct_ptr'. + * itself. So it translates '&struct_ptr->field' back to 'struct_ptr'. */ #define structof(type, field, ptr) \ ((type *) (((char *) (ptr)) - offsetof(type, field))) @@ -24,30 +23,9 @@ /* How many bytes for the kernel stack. Space allocated in mpx.s. */ #define K_STACK_BYTES 1024 -/* How long should the process names be in the kernel? */ -#define P_NAME_LEN 8 - -/* Scheduling quantum. Number of ticks before preemption. */ -#define SCHED_MILLISEC 100 /* rate to call scheduler */ -#define SCHED_TICKS (SCHED_MILLISEC*HZ/1000) /* ticks per schedule */ - -/* How many bytes should the circular buffer for kernel diagnostics. */ -#define KMESS_BUF_SIZE 256 - -/* Maximum size in bytes for (port,value)-pairs vector to copy in. */ -#define VDEVIO_BUF_SIZE 64 - -/* How many elements in vector of virtual copy requests. */ -#define VCOPY_VEC_SIZE 16 - -/* How many IRQ hooks are there in total. */ -#define NR_IRQ_HOOKS 16 - -/* How many buffers for notification messages should there be? */ -#define NR_NOTIFY_BUFS 32 - -/* Buffer to gather randomness. How many entries before wrapping? */ -#define RANDOM_ELEMENTS 32 +/* Constants used in virtual_copy(). Values must be 0 and 1, respectively. */ +#define _SRC_ 0 +#define _DST_ 1 /* Constants and macros for bit map manipulation. */ #define BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT) @@ -58,6 +36,14 @@ #define SET_BIT(map,bit) ( MAP_CHUNK(map,bit) |= (1 << CHUNK_OFFSET(bit) ) #define UNSET_BIT(map,bit) ( MAP_CHUNK(map,bit) &= ~(1 << CHUNK_OFFSET(bit) ) +#define get_sys_bit(map,bit) \ + ( MAP_CHUNK(map.chunk,bit) & (1 << CHUNK_OFFSET(bit) ) +#define set_sys_bit(map,bit) \ + ( MAP_CHUNK(map.chunk,bit) |= (1 << CHUNK_OFFSET(bit) ) +#define unset_sys_bit(map,bit) \ + ( MAP_CHUNK(map.chunk,bit) &= ~(1 << CHUNK_OFFSET(bit) ) +#define NR_SYS_CHUNKS BITMAP_CHUNKS(NR_SYS_PROCS) + #if (CHIP == INTEL) @@ -70,29 +56,18 @@ #define IF_MASK 0x00000200 #define IOPL_MASK 0x003000 -#if ENABLE_LOCK_TIMING -#define locktimestart(c, v) timer_start(c, v) -#define locktimeend(c) timer_end(c) -#else -#define locktimestart(c, v) -#define locktimeend(c) -#endif - -#if ENABLE_K_LOCKCHECK -#define lockcheck if(!(read_cpu_flags() & X86_FLAG_I)) kinfo.relocking++; -#else -#define lockcheck -#endif - -/* Disable/Enable hardware interrupts. */ -#define lock(c, v) do { lockcheck; intr_disable(); locktimestart(c, v); } while(0) -#define unlock(c) do { locktimeend(c); intr_enable(); } while(0) +/* Disable/ enable hardware interrupts. The parameters of lock() and unlock() + * are used when debugging is enabled. See debug.h for more information. + */ +#define lock(c, v) intr_disable(); +#define unlock(c) intr_enable(); /* Sizes of memory tables. The boot monitor distinguishes three memory areas, * namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed * for DOS MINIX. */ -#define NR_MEMS 8 /* number of chunks of memory */ +#define NR_MEMS 8 + #endif /* (CHIP == INTEL) */ @@ -100,7 +75,4 @@ /* M68000 specific constants go here. */ #endif /* (CHIP == M68000) */ -#if ENABLE_INT_TIMING -#define INT_TIMING_BITS 12 -#define INT_TIMING_ELEMENTS (1L << 12) -#endif +#endif /* CONST_H */ diff --git a/kernel/system/debugging.c b/kernel/debug.c similarity index 87% rename from kernel/system/debugging.c rename to kernel/debug.c index 5c15f9162..05ad2716b 100644 --- a/kernel/system/debugging.c +++ b/kernel/debug.c @@ -1,17 +1,17 @@ -/* The system call implemented in this file: - * m_type: SYS_DEBUG - * - * The parameters for this system call are: +/* This file implements kernel debugging functionality that is not included + * in the standard kernel. Available functionality includes timing of lock + * functions and sanity checking of the scheduling queues. */ -#include "../kernel.h" -#include "../system.h" -#include "../proc.h" -#include "../glo.h" +#include "kernel.h" +#include "proc.h" +#include "debug.h" #include -#if ENABLE_LOCK_TIMING +#if DEBUG_TIME_LOCKS /* only include code if enabled */ +/* Data structures to store lock() timing data. */ +struct lock_timingdata timingdata[TIMING_CATEGORIES]; static unsigned long starttimes[TIMING_CATEGORIES][2]; #define HIGHCOUNT 0 @@ -42,8 +42,6 @@ void timer_start(int cat, char *name) } read_tsc(&starttimes[cat][HIGHCOUNT], &starttimes[cat][LOWCOUNT]); - - return; } void timer_end(int cat) @@ -102,9 +100,10 @@ void timer_end(int cat) return; } -#endif +#endif /* DEBUG_TIME_LOCKS */ -#if ENABLE_K_DEBUGGING /* only include code if enabled */ + +#if DEBUG_SCHED_CHECK /* only include code if enabled */ #define PROCLIMIT 10000 @@ -157,7 +156,7 @@ check_runqueues(char *when) } for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) { - if(! isempty(xp) && xp->p_ready && ! xp->p_found) { + if(! isemptyp(xp) && xp->p_ready && ! xp->p_found) { kprintf("scheduling error: ready not on queue: %s\n", (karg_t) when); panic("ready proc not on scheduling queue", NO_NUM); if(l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); } @@ -165,8 +164,4 @@ check_runqueues(char *when) } } -/*==========================================================================* - * do_debug * - *==========================================================================*/ - -#endif /* ENABLE_K_DEBUGGING */ +#endif /* DEBUG_SCHED_CHECK */ diff --git a/kernel/debug.h b/kernel/debug.h index 259c29484..5b80995ef 100644 --- a/kernel/debug.h +++ b/kernel/debug.h @@ -1,15 +1,74 @@ #ifndef DEBUG_H #define DEBUG_H -#include +/* This header file defines all debugging constants and macros, and declares + * some variables. Certain debugging features redefine standard constants + * and macros. Therefore, this header file should be included after the + * other kernel headers. + */ -#if ENABLE_LOCK_TIMING +#include "config.h" + +/* It's interesting to measure the time spent withing locked regions, because + * this is the time that the system is deaf to interrupts. + */ +#if DEBUG_TIME_LOCKS + +#define TIMING_POINTS 20 /* timing resolution */ +#define TIMING_CATEGORIES 20 +#define TIMING_NAME 10 + +/* Definition of the data structure to store lock() timing data. */ +struct lock_timingdata { + char names[TIMING_NAME]; + unsigned long lock_timings[TIMING_POINTS]; + unsigned long lock_timings_range[2]; + unsigned long binsize, resets, misses, measurements; +}; + +/* The data is declared here, but allocated in debug.c. */ +extern struct lock_timingdata timingdata[TIMING_CATEGORIES]; + +/* Prototypes for the timing functionality. */ _PROTOTYPE( void timer_start, (int cat, char *name) ); _PROTOTYPE( void timer_end, (int cat) ); -#endif -#if ENABLE_K_DEBUGGING /* debugging */ +#define locktimestart(c, v) timer_start(c, v) +#define locktimeend(c) timer_end(c) +#else +#define locktimestart(c, v) +#define locktimeend(c) +#endif /* DEBUG_TIME_LOCKS */ + + +/* The locking checks counts relocking situation, which are dangerous because + * the inner lock may unlock the outer one. + */ +#if DEBUG_LOCK_CHECK +#define lockcheck if (!(read_cpu_flags() & X86_FLAG_I)) kinfo.relocking++; +#else +#define lockcheck +#endif /* DEBUG_LOCK_CHECK */ + + +/* This check makes sure that the scheduling queues are in a consistent state. + * The check is run when the queues are updated with ready() and unready(). + */ +#if DEBUG_SCHED_CHECK _PROTOTYPE( void check_runqueues, (char *when) ); +#endif /* DEBUG_SCHED_CHECK */ + + +/* The timing and checking of kernel locking requires a redefine of the lock() + * and unlock() macros. That's done here. This redefine requires that this + * header is included after the other kernel headers. + */ +#if (DEBUG_TIME_LOCKS || DEBUG_LOCK_CHECK) +# undef lock +# define lock(c, v) do { lockcheck; intr_disable(); locktimestart(c, v); } while(0) +# undef unlock +# define unlock(c) do { locktimeend(c); intr_enable(); } while(0) #endif -#endif /* DEBUG_H */ + +#endif /* DEBUG_H */ diff --git a/kernel/exception.c b/kernel/exception.c index d6af1298e..6e19ed645 100755 --- a/kernel/exception.c +++ b/kernel/exception.c @@ -1,12 +1,11 @@ /* This file contains a simple exception handler. Exceptions in user - * processes are converted to signals. Exceptions in the kernel, MM and - * FS cause a panic. + * processes are converted to signals. Exceptions in a kernel task cause + * a panic. */ #include "kernel.h" #include #include "proc.h" -#include "debug.h" /*==========================================================================* * exception * diff --git a/kernel/glo.h b/kernel/glo.h index 492e20e2c..a8711d0f5 100755 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -1,7 +1,10 @@ +#ifndef GLO_H +#define GLO_H + /* Global variables used in the kernel. This file contains the declarations; * storage space for the variables is allocated in table.c, because EXTERN is * defined as extern unless the _TABLE definition is seen. We rely on the - * compiler's default initialization (0) for several global variables. + * compiler's default initialization (0) for several global variables. */ #ifdef _TABLE #undef EXTERN @@ -9,6 +12,7 @@ #endif #include +#include "config.h" /* Variables relating to shutting down MINIX. */ EXTERN char kernel_exception; /* TRUE after system exceptions */ @@ -42,11 +46,6 @@ EXTERN irq_hook_t *irq_handlers[NR_IRQ_VECTORS];/* list of IRQ handlers */ EXTERN int irq_actids[NR_IRQ_VECTORS]; /* IRQ ID bits active */ EXTERN int irq_use; /* map of all in-use irq's */ -/* Data structure to store lock() timing data. */ -#if ENABLE_LOCK_TIMING -EXTERN struct lock_timedata timingdata[TIMING_CATEGORIES]; -#endif - /* Miscellaneous. */ EXTERN reg_t mon_ss, mon_sp; /* boot monitor stack */ EXTERN int mon_return; /* true if we can return to monitor */ @@ -63,3 +62,4 @@ EXTERN _PROTOTYPE( void (*level0_func), (void) ); /* M68000 specific variables go here. */ #endif +#endif /* GLO_H */ diff --git a/kernel/i8259.c b/kernel/i8259.c index 64f5041b0..04f96f74d 100755 --- a/kernel/i8259.c +++ b/kernel/i8259.c @@ -7,7 +7,6 @@ #include "kernel.h" #include "proc.h" -#include "debug.h" #include #define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */ @@ -49,7 +48,8 @@ int mine; */ int i; - lock(6, "intr_init"); + intr_disable(); + if (machine.protected) { /* The AT and newer PS/2 have two interrupt controllers, one master, * one slaved at IRQ 2. (We don't have to deal with the PC that diff --git a/kernel/ipc.h b/kernel/ipc.h index e9bab8d6d..cb9d8f7b3 100644 --- a/kernel/ipc.h +++ b/kernel/ipc.h @@ -1,3 +1,6 @@ +#ifndef IPC_H +#define IPC_H + /* Masks and flags for system calls. */ #define SYSCALL_FUNC 0x0F /* mask for system call function */ #define SYSCALL_FLAGS 0xF0 /* mask for system call flags */ @@ -11,10 +14,13 @@ #define RECEIVE 2 /* function code for receiving messages */ #define SENDREC 3 /* function code for SEND + RECEIVE */ #define NOTIFY 4 /* function code for notifications */ +#define ALERT 5 /* function code for alerting */ /* Call masks indicating which system calls a process can make. */ #define EMPTY_CALL_MASK (0) -#define USER_CALL_MASK (1 << SENDREC) +#define _USER_CALL_MASK ((1 << SENDREC) | (1 << ALERT)) #define SYSTEM_CALL_MASK (~0) +#define USER_CALL_MASK (~0) +#endif /* IPC_H */ diff --git a/kernel/kernel.h b/kernel/kernel.h index 780ff8e26..37838801b 100755 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -1,3 +1,6 @@ +#ifndef KERNEL_H +#define KERNEL_H + /* This is the master header for the kernel. It includes some other files * and defines the principal constants. */ @@ -19,8 +22,13 @@ #include /* device I/O and toggle interrupts */ #endif -#include "const.h" /* kernel constants */ -#include "type.h" /* kernel type definitions */ -#include "proto.h" /* kernel function prototypes */ -#include "glo.h" /* kernel global variables */ +/* Important kernel header files. */ +#include "config.h" /* configuration, MUST be first */ +#include "const.h" /* constants, MUST be second */ +#include "type.h" /* type definitions, MUST be third */ +#include "proto.h" /* function prototypes */ +#include "glo.h" /* global variables */ +#include "ipc.h" /* IPC constants */ +#include "debug.h" /* debugging, MUST be last kernel header */ +#endif /* KERNEL_H */ diff --git a/kernel/klibc.c b/kernel/klibc.c index e960b8534..1c3cbd2d7 100644 --- a/kernel/klibc.c +++ b/kernel/klibc.c @@ -9,14 +9,13 @@ * kmemset: set n bytes to c starting at pointer p * kprintf: printf for the kernel (see working below) * kstrcmp: lexicographical comparison of two strings - * kstrlen: get number of non-null characters in string * kstrncpy: copy string and pad or copy up to n chars * * This file contains the routines that take care of kernel messages, i.e., * diagnostic output within the kernel. Kernel messages are not directly * displayed on the console, because this must be done by the PRINT driver. * Instead, the kernel accumulates characters in a buffer and notifies the - * PRINT driver when a new message is ready. + * output driver when a new message is ready. */ #include "kernel.h" @@ -154,63 +153,31 @@ int c; /* character to append */ /* Accumulate a single character for a kernel message. Send a notification * the to PRINTF_PROC driver if an END_OF_KMESS is encountered. */ - message m; if (c != END_OF_KMESS) { kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */ if (kmess.km_size < KMESS_BUF_SIZE) kmess.km_size += 1; kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE; } else { - m.NOTIFY_TYPE = NEW_KMESS; - lock_notify(PRINTF_PROC, &m); + lock_alert(SYSTEM, PRINTF_PROC); } } -/*=========================================================================* - * kstrlen * - *=========================================================================*/ -PUBLIC size_t kstrlen(const char *org) -{ - register const char *s = org; - while (*s++) - /* EMPTY */ ; - return --s - org; -} - /*=========================================================================* * kstrcmp * *=========================================================================*/ int kstrcmp(register const char *s1, register const char *s2) { - while (*s1 == *s2++) { + while (*s1 == *s2++) if (*s1++ == '\0') return 0; - } if (*s1 == '\0') return -1; if (*--s2 == '\0') return 1; return (unsigned char) *s1 - (unsigned char) *s2; } -/*=========================================================================* - * kstrncmp * - *=========================================================================*/ -PUBLIC int kstrncmp(register const char *s1, register const char *s2, register size_t n) -{ - while (n > 0 && *s1 == *s2++) { - if (*s1++ == '\0') return 0; - n--; - } - if (n > 0) { - if (*s1 == '\0') return -1; - if (*--s2 == '\0') return 1; - return (unsigned char) *s1 - (unsigned char) *s2; - } - return 0; -} - - /*=========================================================================* * kstrncpy * *=========================================================================*/ diff --git a/kernel/main.c b/kernel/main.c index 50641470c..13c3602f6 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -19,7 +19,6 @@ #include #include #include "proc.h" -#include "sendmask.h" /* Prototype declarations for PRIVATE functions. */ FORWARD _PROTOTYPE( void announce, (void)); @@ -33,7 +32,8 @@ PUBLIC void main() { /* Start the ball rolling. */ register struct proc *rp; - register int i; + register struct priv *sp; + register int i,s; int hdrindex; /* index to array of a.out headers */ phys_clicks text_base; vir_clicks text_clicks; @@ -46,13 +46,19 @@ PUBLIC void main() intr_init(1); /* Clear the process table. Anounce each slot as empty and set up mappings - * for proc_addr() and proc_nr() macros. + * for proc_addr() and proc_nr() macros. Do the same for the table with + * system properties structures. */ for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) { rp->p_rts_flags = SLOT_FREE; /* initialize free slot */ rp->p_nr = i; /* proc number from ptr */ (pproc_addr + NR_TASKS)[i] = rp; /* proc ptr from number */ } + for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) { + sp->s_proc_nr = NONE; /* initialize as free */ + sp->s_id = i; /* priv structure index */ + ppriv_addr[i] = sp; /* priv ptr from number */ + } /* Set up proc table entries for tasks and servers. The stacks of the * kernel tasks are initialized to an array in data space. The stacks @@ -65,23 +71,23 @@ PUBLIC void main() /* Task stacks. */ ktsb = (reg_t) t_stack; - for (i=0; i < IMAGE_SIZE; ++i) { - ip = &image[i]; /* t's task attributes */ - rp = proc_addr(ip->proc_nr); /* t's process slot */ + for (i=0; i < NR_BOOT_PROCS; ++i) { + ip = &image[i]; /* process' attributes */ + (void) init_proc(ip->proc_nr, NONE); /* initialize new process */ + rp = proc_addr(ip->proc_nr); /* get process pointer */ kstrncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set name */ rp->p_name[P_NAME_LEN-1] = '\0'; /* just for safety */ - rp->p_flags = ip->flags; /* process flags */ rp->p_max_priority = ip->priority; /* max scheduling priority */ rp->p_priority = ip->priority; /* current priority */ rp->p_quantum_size = ip->quantum; /* quantum size in ticks */ rp->p_sched_ticks = ip->quantum; /* current credit */ rp->p_full_quantums = QUANTUMS(ip->priority); /* quantums left */ - rp->p_call_mask = ip->call_mask; /* allowed system calls */ - rp->p_sendmask = ip->sendmask; /* sendmask protection */ + rp->p_priv->s_flags = ip->flags; /* process flags */ + rp->p_priv->s_call_mask = ip->call_mask;/* allowed system calls */ if (i-NR_TASKS < 0) { /* part of the kernel? */ if (ip->stksize > 0) { /* HARDWARE stack size is 0 */ - rp->p_stguard = (reg_t *) ktsb; - *rp->p_stguard = STACK_GUARD; + rp->p_priv->s_stack_guard = (reg_t *) ktsb; + *rp->p_priv->s_stack_guard = STACK_GUARD; } ktsb += ip->stksize; /* point to high end of stack */ rp->p_reg.sp = ktsb; /* this task's initial stack ptr */ @@ -126,9 +132,6 @@ PUBLIC void main() } /* Set ready. The HARDWARE task is never ready. */ -#if ENABLE_K_DEBUGGING - rp->p_ready = 0; -#endif if (rp->p_nr != HARDWARE) lock_ready(rp); rp->p_rts_flags = 0; @@ -198,12 +201,6 @@ int how; /* reason to shut down */ return; /* await sys_abort() from TTY */ } - /* The TTY expects two HARD_STOP notifications. One to switch to the - * primary console for stop sequence output, and one to actually exit. - */ - m.NOTIFY_TYPE = HARD_STOP; - lock_notify(TTY, &m); - /* Allow processes to be scheduled to clean up, unless a CPU exception * occurred. This is done by setting a timer. The timer argument passes * the shutdown status. diff --git a/kernel/proc.c b/kernel/proc.c index 24399048f..4f3c53418 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -38,14 +38,10 @@ * nonempty lists. As shown above, this is not required with pointer pointers. */ -#include "kernel.h" -#include #include +#include +#include "kernel.h" #include "proc.h" -#include "const.h" -#include "debug.h" -#include "ipc.h" -#include "sendmask.h" /* Scheduling and message passing functions. The functions are available to @@ -56,6 +52,7 @@ FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst, message *m_ptr, unsigned flags) ); FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, int src, message *m_ptr, unsigned flags) ); +FORWARD _PROTOTYPE( int mini_alert, (struct proc *caller_ptr, int dst) ); FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst, message *m_ptr ) ); @@ -64,12 +61,22 @@ FORWARD _PROTOTYPE( void unready, (struct proc *rp) ); FORWARD _PROTOTYPE( void sched, (struct proc *rp) ); FORWARD _PROTOTYPE( void pick_proc, (void) ); -#define BuildMess(m,n) \ + +#define BuildOldMess(m,n) \ (m).NOTIFY_SOURCE = (n)->n_source, \ (m).NOTIFY_TYPE = (n)->n_type, \ (m).NOTIFY_FLAGS = (n)->n_flags, \ (m).NOTIFY_ARG = (n)->n_arg; +#define BuildMess(m_ptr, src, dst_ptr) \ + (m_ptr)->m_source = (src); \ + (m_ptr)->m_type = NOTIFY_FROM(src); \ + (m_ptr)->NOTIFY_TIMESTAMP = get_uptime(); \ + if ((src) == HARDWARE) { \ + (m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_int_pending; \ + priv(dst_ptr)->s_int_pending = 0; \ + } + #if (CHIP == INTEL) #define CopyMess(s,sp,sm,dp,dm) \ cp_mess(s, (sp)->p_memmap[D].mem_phys, (vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm) @@ -107,7 +114,7 @@ message *m_ptr; /* pointer to message in the caller's space */ * kernel may only be SENDREC, because tasks always reply and may not block * if the caller doesn't do receive(). */ - if (! (caller_ptr->p_call_mask & (1 << function)) || + if (! (priv(caller_ptr)->s_call_mask & (1 << function)) || (iskerneln(src_dst) && function != SENDREC)) return(ECALLDENIED); @@ -115,6 +122,7 @@ message *m_ptr; /* pointer to message in the caller's space */ if (! (isokprocn(src_dst) || src_dst == ANY || function == ECHO)) return(EBADSRCDST); +#if DEAD_CODE /* temporarily disabled for testing ALERT */ /* Check validity of message pointer. */ vb = (vir_bytes) m_ptr; vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */ @@ -132,6 +140,7 @@ message *m_ptr; /* pointer to message in the caller's space */ if (vhi < vlo || vhi - caller_ptr->p_memmap[D].mem_vir >= caller_ptr->p_memmap[D].mem_len) return(EFAULT); +#endif #endif /* Now check if the call is known and try to perform the request. The only @@ -169,6 +178,9 @@ message *m_ptr; /* pointer to message in the caller's space */ case RECEIVE: result = mini_receive(caller_ptr, src_dst, m_ptr, flags); break; + case ALERT: + result = mini_alert(caller_ptr, src_dst); + break; case NOTIFY: result = mini_notify(caller_ptr, src_dst, m_ptr); break; @@ -182,14 +194,16 @@ message *m_ptr; /* pointer to message in the caller's space */ } /* If the caller made a successfull, blocking system call it's priority may - * be raised. The priority have been lowered if a process consumed to many - * full quantums in a row to prevent damage from infinite loops + * be raised. The priority may have been lowered if a process consumed too + * many full quantums in a row to prevent damage from infinite loops */ +#if DEAD_CODE /* temporarily disabled for testing ALERT */ if ((caller_ptr->p_priority > caller_ptr->p_max_priority) && ! (flags & NON_BLOCKING) && (result == OK)) { caller_ptr->p_priority = caller_ptr->p_max_priority; caller_ptr->p_full_quantums = QUANTUMS(caller_ptr->p_priority); } +#endif /* Now, return the result of the system call to the caller. */ return(result); @@ -264,6 +278,9 @@ unsigned flags; /* system call flags */ register struct notification **ntf_q_pp; message m; int bit_nr; + sys_map_t *map; + bitchunk_t *chunk; + int i, src_id, src_proc_nr; /* Check to see if a message from desired source is already available. * The caller's SENDING flag may be set if SENDREC couldn't send. If it is @@ -271,6 +288,48 @@ unsigned flags; /* system call flags */ */ if (!(caller_ptr->p_rts_flags & SENDING)) { + /* Check if there are pending notifications, except for SENDREC. */ + if (! (flags & FRESH_ANSWER)) { + + map = &priv(caller_ptr)->s_notify_pending; + for (chunk=&map->chunk[0]; chunk<&map->chunk[NR_SYS_CHUNKS]; chunk++) { + + /* Find a pending notification from the requested source. */ + if (! *chunk) continue; /* no bits in chunk */ + for (i=0; ! (*chunk & (1<chunk[0]) * BITCHUNK_BITS + i; + if (src_id >= NR_SYS_PROCS) break; /* out of range */ + src_proc_nr = id_to_nr(src_id); /* get source proc */ + if (src!=ANY && src!=src_proc_nr) continue; /* source not ok */ + *chunk &= ~(1 << i); /* no longer pending */ + + /* Found a suitable source, deliver the notification message. */ + BuildMess(&m, src_proc_nr, caller_ptr); /* assemble message */ + CopyMess(src_proc_nr, proc_addr(HARDWARE), &m, caller_ptr, m_ptr); + return(OK); /* report success */ + } + + ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */ + while (*ntf_q_pp != NULL) { + if (src == ANY || src == (*ntf_q_pp)->n_source) { + /* Found notification. Assemble and copy message. */ + BuildOldMess(m, *ntf_q_pp); + if (m.m_source == HARDWARE) { + m.NOTIFY_ARG = caller_ptr->p_priv->s_int_pending; + caller_ptr->p_priv->s_int_pending = 0; + } + CopyMess((*ntf_q_pp)->n_source, proc_addr(HARDWARE), &m, + caller_ptr, m_ptr); + /* Remove notification from queue and bit map. */ + bit_nr = (int) (*ntf_q_pp - ¬ify_buffer[0]); + *ntf_q_pp = (*ntf_q_pp)->n_next;/* remove from queue */ + free_bit(bit_nr, notify_bitmap, NR_NOTIFY_BUFS); + return(OK); /* report success */ + } + ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */ + } + } + /* Check caller queue. Use pointer pointers to keep code simple. */ xpp = &caller_ptr->p_caller_q; while (*xpp != NIL_PROC) { @@ -284,25 +343,6 @@ unsigned flags; /* system call flags */ xpp = &(*xpp)->p_q_link; /* proceed to next */ } - /* Check if there are pending notifications, except for SENDREC. */ - if (! (flags & FRESH_ANSWER)) { - - ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */ - while (*ntf_q_pp != NULL) { - if (src == ANY || src == (*ntf_q_pp)->n_source) { - /* Found notification. Assemble and copy message. */ - BuildMess(m, *ntf_q_pp); - CopyMess((*ntf_q_pp)->n_source, proc_addr(HARDWARE), &m, - caller_ptr, m_ptr); - /* Remove notification from queue and bit map. */ - bit_nr = (int) (*ntf_q_pp - ¬ify_buffer[0]); - *ntf_q_pp = (*ntf_q_pp)->n_next;/* remove from queue */ - free_bit(bit_nr, notify_bitmap, NR_NOTIFY_BUFS); - return(OK); /* report success */ - } - ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */ - } - } } /* No suitable message is available or the caller couldn't send in SENDREC. @@ -320,6 +360,45 @@ unsigned flags; /* system call flags */ } +/*===========================================================================* + * mini_alert * + *===========================================================================*/ +PRIVATE int mini_alert(caller_ptr, dst) +register struct proc *caller_ptr; /* sender of the notification */ +int dst; /* which process to notify */ +{ + register struct proc *dst_ptr = proc_addr(dst); + int src_id; /* source id for late delivery */ + message m; /* the notification message */ + + /* Check to see if target is blocked waiting for this message. A process + * can be both sending and receiving during a SENDREC system call. + */ + if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING && + (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) { + + /* Destination is indeed waiting for a message. Assemble a notification + * message and deliver it. Copy from pseudo-source HARDWARE, since the + * message is in the kernel's address space. + */ + BuildMess(&m, proc_nr(caller_ptr), dst_ptr); + CopyMess(proc_nr(caller_ptr), proc_addr(HARDWARE), &m, + dst_ptr, dst_ptr->p_messbuf); + dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */ + if (dst_ptr->p_rts_flags == 0) ready(dst_ptr); + return(OK); + } + + /* Destination is not ready to receive the notification. Add it to the + * bit map with pending notifications. Note the indirectness: the system id + * instead of the process number is used in the pending bit map. + */ + src_id = priv(caller_ptr)->s_id; + set_sys_bit(priv(dst_ptr)->s_notify_pending, src_id); + return(OK); +} + + /*===========================================================================* * mini_notify * *===========================================================================*/ @@ -337,15 +416,22 @@ message *m_ptr; /* pointer to message buffer */ /* Check to see if target is blocked waiting for this message. A process * can be both sending and receiving during a SENDREC system call. */ - if ( (dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING && - (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) { + if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING && + (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) { - /* Destination is indeed waiting for this message. */ - CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr, - dst_ptr, dst_ptr->p_messbuf); - dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */ - if (dst_ptr->p_rts_flags == 0) ready(dst_ptr); - return(OK); + /* Destination is indeed waiting for this message. Check if the source + * is HARDWARE; this is a special case that gets the map of pending + * interrupts as an argument. Then deliver the notification message. + */ + if (proc_nr(caller_ptr) == HARDWARE) { + m_ptr->NOTIFY_ARG = priv(dst_ptr)->s_int_pending; + priv(dst_ptr)->s_int_pending = 0; + } + + CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr, dst_ptr, dst_ptr->p_messbuf); + dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */ + if (dst_ptr->p_rts_flags == 0) ready(dst_ptr); + return(OK); } /* Destination is not ready. Add the notification to the pending queue. @@ -389,26 +475,27 @@ message *m_ptr; /* pointer to message buffer */ /*==========================================================================* * lock_notify * *==========================================================================*/ -PUBLIC int lock_notify(dst, m_ptr) -int dst; /* to whom is message being sent? */ -message *m_ptr; /* pointer to message buffer */ +PUBLIC int lock_alert(src, dst) +int src; /* sender of the notification */ +int dst; /* who is to be notified */ { -/* Safe gateway to mini_notify() for tasks and interrupt handlers. MINIX +/* Safe gateway to mini_notify() for tasks and interrupt handlers. The sender + * is explicitely given to prevent confusion where the call comes from. MINIX * kernel is not reentrant, which means to interrupts are disabled after * the first kernel entry (hardware interrupt, trap, or exception). Locking - * work is done by temporarily disabling interrupts. + * is done by temporarily disabling interrupts. */ int result; /* Exception or interrupt occurred, thus already locked. */ if (k_reenter >= 0) { - result = mini_notify(proc_addr(HARDWARE), dst, m_ptr); + result = mini_alert(proc_addr(src), dst); } /* Call from task level, locking is required. */ else { - lock(0, "notify"); - result = mini_notify(proc_ptr, dst, m_ptr); + lock(0, "alert"); + result = mini_alert(proc_addr(src), dst); unlock(0); } return(result); @@ -424,11 +511,9 @@ register struct proc *rp; /* this process is now runnable */ /* Add 'rp' to one of the queues of runnable processes. */ register int q = rp->p_priority; /* scheduling queue to use */ -#if ENABLE_K_DEBUGGING - if(rp->p_ready) { - kprintf("ready() already ready process\n", NO_NUM); - } - rp->p_ready = 1; +#if DEBUG_SCHED_CHECK + check_runqueues("ready"); + if(rp->p_ready) kprintf("ready() already ready process\n", NO_NUM); #endif /* Processes, in principle, are added to the end of the queue. However, @@ -439,7 +524,7 @@ register struct proc *rp; /* this process is now runnable */ rdy_head[q] = rdy_tail[q] = rp; /* create a new queue */ rp->p_nextready = NIL_PROC; /* mark new end */ } - else if (rp->p_flags & SCHED_Q_HEAD) { /* add to head of queue */ + else if (priv(rp)->s_flags & RDY_Q_HEAD) { /* add to head of queue */ rp->p_nextready = rdy_head[q]; /* chain head of queue */ rdy_head[q] = rp; /* set new queue head */ } @@ -449,6 +534,11 @@ register struct proc *rp; /* this process is now runnable */ rp->p_nextready = NIL_PROC; /* mark new end */ } pick_proc(); /* select next to run */ + +#if DEBUG_SCHED_CHECK + rp->p_ready = 1; + check_runqueues("ready"); +#endif } /*===========================================================================* @@ -463,19 +553,17 @@ register struct proc *rp; /* this process is no longer runnable */ register struct proc **xpp; /* iterate over queue */ register struct proc *prev_xp; -#if ENABLE_K_DEBUGGING - if(!rp->p_ready) { - kprintf("unready() already unready process\n", NO_NUM); - } - rp->p_ready = 0; -#endif - /* Side-effect for kernel: check if the task's stack still is ok? */ if (iskernelp(rp)) { - if (*rp->p_stguard != STACK_GUARD) + if (*priv(rp)->s_stack_guard != STACK_GUARD) panic("stack overrun by task", proc_nr(rp)); } +#if DEBUG_SCHED_CHECK + check_runqueues("unready"); + if (! rp->p_ready) kprintf("unready() already unready process\n", NO_NUM); +#endif + /* Now make sure that the process is not in its ready queue. Remove the * process if it is found. A process can be made unready even if it is not * running by being sent a signal that kills it. @@ -493,6 +581,11 @@ register struct proc *rp; /* this process is no longer runnable */ } prev_xp = *xpp; /* save previous in chain */ } + +#if DEBUG_SCHED_CHECK + rp->p_ready = 0; + check_runqueues("unready"); +#endif } /*===========================================================================* @@ -504,16 +597,19 @@ struct proc *sched_ptr; /* quantum eating process */ int q; /* Check if this process is preemptible, otherwise leave it as is. */ - if (! (sched_ptr->p_flags & PREEMPTIBLE)) { + if (! (priv(sched_ptr)->s_flags & PREEMPTIBLE)) { +#if DEAD_CODE kprintf("Warning, sched for nonpreemptible proc %d\n", sched_ptr->p_nr); +#endif return; } +#if DEAD_CODE if (sched_ptr->p_nr == IS_PROC_NR) { kprintf("Scheduling IS: pri: %d, ", sched_ptr->p_priority); kprintf("qua %d", sched_ptr->p_full_quantums); } - +#endif /* Process exceeded the maximum number of full quantums it is allowed * to use in a row. Lower the process' priority, but make sure we don't * end up in the IDLE queue. This helps to limit the damage caused by @@ -525,8 +621,10 @@ struct proc *sched_ptr; /* quantum eating process */ unready(sched_ptr); /* remove from queues */ sched_ptr->p_priority ++; /* lower priority */ ready(sched_ptr); /* add to new queue */ +#if DEAD_CODE kprintf("Warning, proc %d got lower priority: ", sched_ptr->p_nr); kprintf("%d\n", sched_ptr->p_priority); +#endif } sched_ptr->p_full_quantums = QUANTUMS(sched_ptr->p_priority); } @@ -548,12 +646,13 @@ kprintf("%d\n", sched_ptr->p_priority); sched_ptr->p_sched_ticks = sched_ptr->p_quantum_size; pick_proc(); +#if DEAD_CODE if (sched_ptr->p_nr == IS_PROC_NR) { kprintf("Next proc: %d, ", next_ptr->p_nr); kprintf("pri: %d, ", next_ptr->p_priority); kprintf("qua: %d\n", next_ptr->p_full_quantums); - } +#endif } @@ -576,7 +675,7 @@ PRIVATE void pick_proc() for (q=0; q < NR_SCHED_QUEUES; q++) { if ( (rp = rdy_head[q]) != NIL_PROC) { next_ptr = rp; /* run process 'rp' next */ - if (rp->p_flags & BILLABLE) + if (priv(rp)->s_flags & BILLABLE) bill_ptr = rp; /* bill for system time */ return; } diff --git a/kernel/proc.h b/kernel/proc.h index eb7d8e74c..dc5c7f096 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -12,6 +12,7 @@ #include #include "protect.h" #include "const.h" +#include "priv.h" struct proc { struct stackframe_s p_reg; /* process' registers saved in stack frame */ @@ -25,9 +26,8 @@ struct proc { /* M68000 specific registers and FPU details go here. */ #endif - reg_t *p_stguard; /* stack guard word */ proc_nr_t p_nr; /* number of this process (for fast access) */ - char p_flags; /* PREEMTIBLE, BILLABLE, etc. */ + struct priv *p_priv; /* system privileges structure */ char p_rts_flags; /* SENDING, RECEIVING, etc. */ char p_priority; /* current scheduling priority */ @@ -36,11 +36,7 @@ struct proc { char p_sched_ticks; /* number of scheduling ticks left */ char p_full_quantums; /* number of full quantums left */ - char p_call_mask; /* bit map with allowed system call traps */ - send_mask_t p_sendmask; /* mask indicating to whom proc may send */ - - struct mem_map p_memmap[NR_LOCAL_SEGS]; /* local memory map (T, D, S) */ - struct far_mem p_farmem[NR_REMOTE_SEGS]; /* remote memory map */ + struct mem_map p_memmap[NR_LOCAL_SEGS]; /* memory map (T, D, S) */ clock_t p_user_time; /* user time in ticks */ clock_t p_sys_time; /* sys time in ticks */ @@ -53,19 +49,15 @@ struct proc { proc_nr_t p_getfrom; /* from whom does process want to receive? */ proc_nr_t p_sendto; /* to whom does process want to send? */ - timer_t p_alarm_timer; /* timer shared by different alarm types */ sigset_t p_pending; /* bit map for pending kernel signals */ char p_name[P_NAME_LEN]; /* name of the process, including \0 */ -#if ENABLE_K_DEBUGGING +#if DEBUG_SCHED_CHECK int p_ready, p_found; #endif }; -/* Guard word for task stacks. */ -#define STACK_GUARD ((reg_t) (sizeof(reg_t) == 2 ? 0xBEEF : 0xDEADBEEF)) - /* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */ #define SLOT_FREE 0x01 /* process slot is free */ #define NO_MAP 0x02 /* keeps unmapped forked child from running */ @@ -74,11 +66,7 @@ struct proc { #define SIGNALED 0x10 /* set when new kernel signal arrives */ #define SIG_PENDING 0x20 /* unready while signal being processed */ #define P_STOP 0x40 /* set when process is being traced */ - -/* Bits for the other process flags. */ -#define PREEMPTIBLE 0x01 /* kernel tasks are not preemptible */ -#define SCHED_Q_HEAD 0x02 /* add to queue head instead of tail */ -#define BILLABLE 0x04 /* system services are not billable */ +#define NO_PRIV 0x80 /* privilege structure not yet initialized */ /* Scheduling priorities for p_priority. Values must start at zero (highest * priority) and increment. Priorities of the processes in the boot image can diff --git a/kernel/protect.c b/kernel/protect.c index 4b8acead1..a7f7ca15b 100755 --- a/kernel/protect.c +++ b/kernel/protect.c @@ -215,7 +215,6 @@ vir_bytes size; int privilege; { /* Build descriptor for a data segment. */ - sdesc(segdp, base, size); segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE); /* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */ diff --git a/kernel/proto.h b/kernel/proto.h index b26a21a0e..ef25c46c0 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -13,16 +13,13 @@ _PROTOTYPE( void clock_stop, (void) ); _PROTOTYPE( clock_t get_uptime, (void) ); _PROTOTYPE( unsigned long read_clock, (void) ); _PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f) ); -_PROTOTYPE( void reset_timer, (struct timer *tp) ); +_PROTOTYPE( void reset_timer, (struct timer *tp) ); /* klibc.c */ _PROTOTYPE( int katoi, (register const char *s)); _PROTOTYPE( void *kmemcpy, (void *s1, const void *s2, register size_t n)); _PROTOTYPE( void *kmemset, (void *s, register int c, register size_t n)); _PROTOTYPE( int kstrcmp, (register const char *s1, register const char *s2)); -_PROTOTYPE( size_t kstrlen, (const char *s)); -_PROTOTYPE( int kstrncmp, - (register const char *s1, register const char *s2, register size_t n)); _PROTOTYPE( char *kstrncpy, (char *s1, register const char *s2, register const ssize_t n)); #define karg(arg) (karg_t) (arg) @@ -33,14 +30,16 @@ _PROTOTYPE( void main, (void) ); _PROTOTYPE( void prepare_shutdown, (int how) ); _PROTOTYPE( void stop_sequence, (struct timer *tp) ); -/* misc.c */ +/* utility.c */ _PROTOTYPE( void panic, (_CONST char *s, int n) ); +_PROTOTYPE( void safe_lock, (int c, char *v) ); +_PROTOTYPE( void safe_unlock, (void) ); _PROTOTYPE( int alloc_bit, (bitchunk_t *map, bit_t nr_bits) ); _PROTOTYPE( void free_bit, (bit_t nr, bitchunk_t *map, bit_t nr_bits) ); /* proc.c */ _PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) ); -_PROTOTYPE( int lock_notify, (int dst, message *m_ptr) ); +_PROTOTYPE( int lock_alert, (int src, int dst) ); _PROTOTYPE( int lock_send, (int dst, message *m_ptr) ); _PROTOTYPE( void lock_ready, (struct proc *rp) ); _PROTOTYPE( void lock_sched, (struct proc *rp) ); @@ -52,6 +51,7 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds, /* system.c */ _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) ); +_PROTOTYPE( int init_proc, (int proc_nr, int proto_nr) ); _PROTOTYPE( void clear_proc, (int proc_nr) ); _PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr, vir_bytes bytes) ); diff --git a/kernel/system.c b/kernel/system.c index d5db29770..6b56917d5 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -22,6 +22,7 @@ * generic_handler: interrupt handler for user-level device drivers * * Changes: + * Apr 25, 2005 new init_proc() function (Jorrit N. Herder) * Apr 25, 2005 made mapping of call vector explicit (Jorrit N. Herder) * Oct 29, 2004 new clear_proc() function (Jorrit N. Herder) * Oct 17, 2004 generic handler and IRQ policies (Jorrit N. Herder) @@ -38,8 +39,6 @@ #include #include #include -#include -#include "sendmask.h" #if (CHIP == INTEL) #include #include "protect.h" @@ -55,7 +54,7 @@ PUBLIC int (*call_vec[NR_SYS_CALLS])(message *m_ptr); #define map(call_nr, handler) \ {extern int dummy[NR_SYS_CALLS > (unsigned) (call_nr) ? 1 : -1];} \ - call_vec[(call_nr)] = (handler) + call_vec[(call_nr)] = (handler) FORWARD _PROTOTYPE( void initialize, (void)); @@ -78,11 +77,9 @@ PUBLIC void sys_task() /* Handle the request. */ if ((unsigned) m.m_type < NR_SYS_CALLS) { - result = (*call_vec[m.m_type])(&m); /* do system call */ - } else if(m.NOTIFY_TYPE == KSIG_PENDING) { - message pmm; - pmm.NOTIFY_TYPE = KSIG_PENDING; - lock_notify(PM_PROC_NR, &pmm); + result = (*call_vec[m.m_type])(&m); /* handle the kernel call */ + } else if (m.m_type == NEW_KSIG) { + lock_alert(SYSTEM, PM_PROC_NR); /* tell PM about signal */ continue; } else { kprintf("Warning, illegal SYSTASK request from %d.\n", m.m_source); @@ -94,7 +91,7 @@ PUBLIC void sys_task() * is known to be blocked waiting for a message. */ if (result != EDONTREPLY) { - m.m_type = result; /* report status of call */ + m.m_type = result; /* report status of call */ if (OK != lock_send(m.m_source, &m)) { kprintf("Warning, SYSTASK couldn't reply to request from %d\n", m.m_source); @@ -109,7 +106,7 @@ PUBLIC void sys_task() *===========================================================================*/ PRIVATE void initialize(void) { - register struct proc *rp; + register struct priv *sp; int i; /* Initialize IRQ handler hooks. Mark all hooks available. */ @@ -118,8 +115,8 @@ PRIVATE void initialize(void) } /* Initialize all alarm timers for all processes. */ - for (rp=BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) { - tmr_inittimer(&(rp->p_alarm_timer)); + for (sp=BEG_PRIV_ADDR; sp < END_PRIV_ADDR; sp++) { + tmr_inittimer(&(sp->s_alarm_timer)); } /* Initialize the call vector to a safe default handler. Some system calls @@ -132,23 +129,22 @@ PRIVATE void initialize(void) } /* Process management. */ - map(SYS_FORK, do_fork); /* informs kernel that a process has forked */ - map(SYS_XIT, do_xit); /* informs kernel that a process has exited */ - map(SYS_NEWMAP, do_newmap); /* allows PM to set up a process memory map */ - map(SYS_EXEC, do_exec); /* sets program counter and stack pointer after EXEC */ - map(SYS_TRACE, do_trace); /* request a trace operation */ + map(SYS_FORK, do_fork); /* a process forked a new process */ + map(SYS_NEWMAP, do_newmap); /* set up a process memory map */ + map(SYS_EXEC, do_exec); /* update process after execute */ + map(SYS_EXIT, do_exit); /* clean up after process exit */ + map(SYS_TRACE, do_trace); /* request a trace operation */ /* Signal handling. */ map(SYS_KILL, do_kill); /* cause a process to be signaled */ - map(SYS_GETSIG, do_getsig); /* PM checks for pending signals */ - map(SYS_ENDSIG, do_endsig); /* PM finished processing signal */ + map(SYS_GETKSIG, do_getksig); /* PM checks for pending signals */ + map(SYS_ENDKSIG, do_endksig); /* PM finished processing signal */ map(SYS_SIGSEND, do_sigsend); /* start POSIX-style signal */ map(SYS_SIGRETURN, do_sigreturn); /* return from POSIX-style signal */ /* Clock functionality. */ map(SYS_TIMES, do_times); /* get uptime and process times */ - map(SYS_SIGNALRM, do_signalrm); /* causes an alarm signal */ - map(SYS_SYNCALRM, do_syncalrm); /* send a notification message */ + map(SYS_SETALARM, do_setalarm); /* schedule a synchronous alarm */ /* Device I/O. */ map(SYS_IRQCTL, do_irqctl); /* interrupt control operations */ @@ -156,25 +152,60 @@ PRIVATE void initialize(void) map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */ map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */ - /* Server and driver control. */ + /* System control. */ + map(SYS_SETPRIORITY, do_schedctl); /* set scheduling priority */ map(SYS_SEGCTL, do_segctl); /* add segment and get selector */ - map(SYS_IOPENABLE, do_iopenable); /* enable CPU I/O protection bits */ map(SYS_SVRCTL, do_svrctl); /* kernel control functions */ /* Copying. */ map(SYS_UMAP, do_umap); /* map virtual to physical address */ map(SYS_VIRCOPY, do_vircopy); /* use pure virtual addressing */ map(SYS_PHYSCOPY, do_physcopy); /* use physical addressing */ - map(SYS_PHYSZERO, do_physzero); /* zero physical memory region */ map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */ map(SYS_PHYSVCOPY, do_physvcopy); /* vector with copy requests */ - map(SYS_SETPRIORITY, do_setpriority); /* set scheduling priority */ + map(SYS_MEMSET, do_memset); /* write char to memory area */ /* Miscellaneous. */ map(SYS_ABORT, do_abort); /* abort MINIX */ map(SYS_GETINFO, do_getinfo); /* request system information */ } + +/*===========================================================================* + * init_proc * + *===========================================================================*/ +PUBLIC int init_proc(proc_nr, proto_nr) +int proc_nr; /* slot of process to initialize */ +int proto_nr; /* prototype process to copy from */ +{ + register struct proc *rc, *rp; + register struct priv *sp; + int i; + + /* Get a pointer to the process to initialize. */ + rc = proc_addr(proc_nr); + + /* If there is a prototype process to initialize from, use it. Otherwise, + * assume the caller will take care of initialization, but make sure that + * the new process gets a pointer to a system properties structure. + */ + if (isokprocn(proto_nr)) { + kprintf("INIT proc from prototype %d\n", proto_nr); + + } else { + for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) { + if (sp->s_proc_nr == NONE) { /* found free slot */ + sp->s_proc_nr = proc_nr; /* set association */ + rc->p_priv = sp; /* assign to process */ + return(OK); + } + } + kprintf("No free PRIV structure!\n", NO_NUM); + return(ENOSPC); /* out of resources */ + } +} + + /*===========================================================================* * clear_proc * *===========================================================================*/ @@ -189,7 +220,7 @@ int proc_nr; /* slot of process to clean up */ rc = proc_addr(proc_nr); /* Turn off any alarm timers at the clock. */ - reset_timer(&rc->p_alarm_timer); + reset_timer(&rc->p_priv->s_alarm_timer); /* Make sure the exiting process is no longer scheduled. */ if (rc->p_rts_flags == 0) lock_unready(rc); @@ -232,7 +263,6 @@ int proc_nr; /* slot of process to clean up */ kstrncpy(rc->p_name, "", P_NAME_LEN); /* unset name */ sigemptyset(&rc->p_pending); /* remove pending signals */ rc->p_rts_flags = SLOT_FREE; /* announce slot empty */ - rc->p_sendmask = DENY_ALL_MASK; /* set most restrictive mask */ #if (CHIP == M68000) pmmu_delete(rc); /* we're done, remove tables */ @@ -260,7 +290,7 @@ PUBLIC void get_randomness() * On machines without RDTSC, we use the get_uptime() - read_clock() * has a higher resolution, but would involve I/O calls. */ - if(machine.processor > 486) + if (machine.processor > 486) read_tsc(&tsc_high, &krandom.r_buf[krandom.r_next]); else krandom.r_buf[krandom.r_next] = get_uptime(); @@ -278,18 +308,21 @@ 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. - * In addition, the interrupt handler gathers random information in a buffer - * by timestamping the interrupts. */ - message m; - /* Gather random information. */ + /* As a side-effect, the interrupt handler gathers random information by + * timestamping the interrupt events. This is used for /dev/random. + */ get_randomness(); + /* 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->irq); + /* Build notification message and return. */ - m.NOTIFY_TYPE = HARD_INT; - m.NOTIFY_ARG = hook->irq; - lock_notify(hook->proc_nr, &m); + lock_alert(HARDWARE, hook->proc_nr); return(hook->policy & IRQ_REENABLE); } @@ -302,9 +335,9 @@ int proc_nr; /* process to be signalled */ int sig_nr; /* signal to be sent, 1 to _NSIG */ { /* A system process wants to send a signal to a process. Examples are: - * TTY wanting to cause SIGINT upon getting a DEL - * CLOCK wanting to cause SIGALRM when timer expires - * FS wanting to cause SIGPIPE for a broken pipe + * - HARDWARE wanting to cause a SIGSEGV after a CPU exception + * - TTY wanting to cause SIGINT upon getting a DEL + * - FS wanting to cause SIGPIPE for a broken pipe * Signals are handled by sending a message to PM. This function handles the * signals and makes sure the PM gets them by sending a notification. The * process being signaled is blocked while PM has not finished all signals @@ -313,7 +346,6 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */ * PM can block waiting for FS to do a core dump. */ register struct proc *rp; - message m; /* Check if the signal is already pending. Process it otherwise. */ rp = proc_addr(proc_nr); @@ -322,8 +354,7 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */ if (! (rp->p_rts_flags & SIGNALED)) { /* other pending */ if (rp->p_rts_flags == 0) lock_unready(rp); /* make not ready */ rp->p_rts_flags |= SIGNALED | SIG_PENDING; /* update flags */ - m.NOTIFY_TYPE = KSIG_PENDING; - lock_notify(SYSTASK, &m); + lock_alert(HARDWARE, SYSTEM); } } } @@ -370,7 +401,6 @@ vir_bytes vir_addr; /* virtual address in bytes within the seg */ vir_bytes bytes; /* # of bytes to be copied */ { /* Calculate the physical memory address for a given virtual address. */ - vir_clicks vc; /* the virtual address in clicks */ phys_bytes pa; /* intermediate variables as phys_bytes */ #if (CHIP == INTEL) @@ -451,7 +481,7 @@ vir_bytes bytes; /* # of bytes to be copied */ if (bytes <= 0) return( (phys_bytes) 0); if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0); - fm = &rp->p_farmem[seg]; + fm = &rp->p_priv->s_farmem[seg]; if (! fm->in_use) return( (phys_bytes) 0); if (vir_addr + bytes > fm->mem_len) return( (phys_bytes) 0); diff --git a/kernel/system.h b/kernel/system.h index 3faeed6b1..c787f5683 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -1,60 +1,151 @@ -/* Function prototypes for the system library. The implementation is contained - * in src/kernel/system/. The system library allows to access system services - * by doing a system call. System calls are transformed into request messages - * to the SYS task that is responsible for handling the call. By convention, a - * sys_call() is transformed into a message with type SYS_CALL that is handled - * in a function named do_call(). +/* Function prototypes for the system library. The prototypes in this file + * are undefined to do_unused if the kernel call is not enabled in config.h. + * The implementation is contained in src/kernel/system/. + * + * The system library allows to access system services by doing a system call. + * System calls are transformed into request messages to the SYS task that is + * responsible for handling the call. By convention, sys_call() is transformed + * into a message with type SYS_CALL that is handled in a function do_call(). */ #ifndef SYSTEM_H #define SYSTEM_H /* Common includes for the system library. */ -#include -#include +#include "kernel.h" #include "proc.h" -_PROTOTYPE( int do_exec, (message *m_ptr) ); /* process control */ -_PROTOTYPE( int do_fork, (message *m_ptr) ); -_PROTOTYPE( int do_newmap, (message *m_ptr) ); -_PROTOTYPE( int do_xit, (message *m_ptr) ); +/* Default handler for unused kernel calls. */ +_PROTOTYPE( int do_unused, (message *m_ptr) ); -_PROTOTYPE( int do_copy, (message *m_ptr) ); /* copying */ +_PROTOTYPE( int do_exec, (message *m_ptr) ); +#if ! USE_EXEC +#define do_exec do_unused +#endif + +_PROTOTYPE( int do_fork, (message *m_ptr) ); +#if ! USE_FORK +#define do_fork do_unused +#endif + +_PROTOTYPE( int do_newmap, (message *m_ptr) ); +#if ! USE_NEWMAP +#define do_newmap do_unused +#endif + +_PROTOTYPE( int do_exit, (message *m_ptr) ); +#if ! USE_EXIT +#define do_exit do_unused +#endif + +_PROTOTYPE( int do_trace, (message *m_ptr) ); +#if ! USE_TRACE +#define do_trace do_unused +#endif + +_PROTOTYPE( int do_schedctl, (message *m_ptr) ); +#if ! USE_SCHEDCTL +#define do_schedctl do_unused +#endif + +_PROTOTYPE( int do_copy, (message *m_ptr) ); #define do_vircopy do_copy #define do_physcopy do_copy +#if ! (USE_VIRCOPY || USE_PHYSCOPY) +#define do_copy do_unused +#endif + _PROTOTYPE( int do_vcopy, (message *m_ptr) ); #define do_virvcopy do_vcopy #define do_physvcopy do_vcopy +#if ! (USE_VIRVCOPY || USE_PHYSVCOPY) +#define do_vcopy do_unused +#endif + _PROTOTYPE( int do_umap, (message *m_ptr) ); -_PROTOTYPE( int do_physzero, (message *m_ptr) ); +#if ! USE_UMAP +#define do_umap do_unused +#endif + +_PROTOTYPE( int do_memset, (message *m_ptr) ); +#if ! USE_MEMSET +#define do_memset do_unused +#endif -_PROTOTYPE( int do_unused, (message *m_ptr) ); /* miscellaneous */ _PROTOTYPE( int do_abort, (message *m_ptr) ); +#if ! USE_ABORT +#define do_abort do_unused +#endif + _PROTOTYPE( int do_getinfo, (message *m_ptr) ); +#if ! USE_GETINFO +#define do_getinfo do_unused +#endif + +_PROTOTYPE( int do_svrctl, (message *m_ptr) ); +#if ! USE_SVRCTL +#define do_svrctl do_unused +#endif -_PROTOTYPE( int do_svrctl, (message *m_ptr) ); /* system control */ -_PROTOTYPE( int do_iopenable, (message *m_ptr) ); _PROTOTYPE( int do_segctl, (message *m_ptr) ); +#if ! USE_SEGCTL +#define do_segctl do_unused +#endif + +_PROTOTYPE( int do_irqctl, (message *m_ptr) ); +#if ! USE_IRQCTL +#define do_irqctl do_unused +#endif -_PROTOTYPE( int do_irqctl, (message *m_ptr) ); /* device I/O */ _PROTOTYPE( int do_devio, (message *m_ptr) ); +#if ! USE_DEVIO +#define do_devio do_unused +#endif + _PROTOTYPE( int do_vdevio, (message *m_ptr) ); +#if ! USE_VDEVIO +#define do_vdevio do_unused +#endif + _PROTOTYPE( int do_sdevio, (message *m_ptr) ); +#if ! USE_SDEVIO +#define do_sdevio do_unused +#endif + +_PROTOTYPE( int do_kill, (message *m_ptr) ); +#if ! USE_KILL +#define do_kill do_unused +#endif + +_PROTOTYPE( int do_getksig, (message *m_ptr) ); +#if ! USE_GETKSIG +#define do_getksig do_unused +#endif + +_PROTOTYPE( int do_endksig, (message *m_ptr) ); +#if ! USE_ENDKSIG +#define do_endksig do_unused +#endif -_PROTOTYPE( int do_kill, (message *m_ptr) ); /* signal handling */ -_PROTOTYPE( int do_getsig, (message *m_ptr) ); -_PROTOTYPE( int do_endsig, (message *m_ptr) ); _PROTOTYPE( int do_sigsend, (message *m_ptr) ); +#if ! USE_SIGSEND +#define do_sigsend do_unused +#endif + _PROTOTYPE( int do_sigreturn, (message *m_ptr) ); -_PROTOTYPE( int do_setpriority, (message *m_ptr) ); +#if ! USE_SIGRETURN +#define do_sigreturn do_unused +#endif + +_PROTOTYPE( int do_times, (message *m_ptr) ); +#if ! USE_TIMES +#define do_times do_unused +#endif -_PROTOTYPE( int do_times, (message *m_ptr) ); /* clock functions */ _PROTOTYPE( int do_setalarm, (message *m_ptr) ); -#define do_flagalrm do_setalarm -#define do_signalrm do_setalarm -#define do_syncalrm do_setalarm - -_PROTOTYPE( int do_trace, (message *m_ptr) ); /* process tracing */ - +#if ! USE_SETALARM +#define do_setalarm do_unused +#endif #endif /* SYSTEM_H */ + diff --git a/kernel/system/Makefile b/kernel/system/Makefile index 498fe26aa..d81ad887a 100644 --- a/kernel/system/Makefile +++ b/kernel/system/Makefile @@ -5,20 +5,50 @@ u = /usr i = $u/include # Programs, flags, etc. -CC = exec cc +CC = exec cc $(CFLAGS) -c CPP = $l/cpp LD = $(CC) -.o CFLAGS = -I$i LDFLAGS = -i -SYS = clock.o copying.o debugging.o devio.o irqctl.o proctl.o \ - sysctl.o misc.o sigctl.o tracing.o priority.o +SYSTEM = ../system.a # What to make. -all build: $(SYS) +all build install: $(SYSTEM) + +OBJECTS = \ + $(SYSTEM)(do_unused.o) \ + $(SYSTEM)(do_fork.o) \ + $(SYSTEM)(do_exec.o) \ + $(SYSTEM)(do_newmap.o) \ + $(SYSTEM)(do_exit.o) \ + $(SYSTEM)(do_trace.o) \ + $(SYSTEM)(do_schedctl.o) \ + $(SYSTEM)(do_times.o) \ + $(SYSTEM)(do_alarm.o) \ + $(SYSTEM)(do_irqctl.o) \ + $(SYSTEM)(do_devio.o) \ + $(SYSTEM)(do_vdevio.o) \ + $(SYSTEM)(do_sdevio.o) \ + $(SYSTEM)(do_copy.o) \ + $(SYSTEM)(do_vcopy.o) \ + $(SYSTEM)(do_umap.o) \ + $(SYSTEM)(do_memset.o) \ + $(SYSTEM)(do_svrctl.o) \ + $(SYSTEM)(do_segctl.o) \ + $(SYSTEM)(do_getksig.o) \ + $(SYSTEM)(do_endksig.o) \ + $(SYSTEM)(do_kill.o) \ + $(SYSTEM)(do_sigsend.o) \ + $(SYSTEM)(do_sigreturn.o) \ + $(SYSTEM)(do_abort.o) \ + $(SYSTEM)(do_getinfo.o) \ + +$(SYSTEM): $(OBJECTS) + aal cr $@ *.o clean: - rm -f *.a *.o *.bak + rm -f $(SYSTEM) *.o *.bak depend: /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend @@ -27,4 +57,81 @@ depend: include .depend +$(SYSTEM)(do_unused.o): do_unused.c + $(CC) do_unused.c + +$(SYSTEM)(do_fork.o): do_fork.c + $(CC) do_fork.c + +$(SYSTEM)(do_exec.o): do_exec.c + $(CC) do_exec.c + +$(SYSTEM)(do_newmap.o): do_newmap.c + $(CC) do_newmap.c + +$(SYSTEM)(do_exit.o): do_exit.c + $(CC) do_exit.c + +$(SYSTEM)(do_trace.o): do_trace.c + $(CC) do_trace.c + +$(SYSTEM)(do_schedctl.o): do_schedctl.c + $(CC) do_schedctl.c + +$(SYSTEM)(do_times.o): do_times.c + $(CC) do_times.c + +$(SYSTEM)(do_alarm.o): do_alarm.c + $(CC) do_alarm.c + +$(SYSTEM)(do_irqctl.o): do_irqctl.c + $(CC) do_irqctl.c + +$(SYSTEM)(do_devio.o): do_devio.c + $(CC) do_devio.c + +$(SYSTEM)(do_sdevio.o): do_sdevio.c + $(CC) do_sdevio.c + +$(SYSTEM)(do_vdevio.o): do_vdevio.c + $(CC) do_vdevio.c + +$(SYSTEM)(do_copy.o): do_copy.c + $(CC) do_copy.c + +$(SYSTEM)(do_vcopy.o): do_vcopy.c + $(CC) do_vcopy.c + +$(SYSTEM)(do_umap.o): do_umap.c + $(CC) do_umap.c + +$(SYSTEM)(do_memset.o): do_memset.c + $(CC) do_memset.c + +$(SYSTEM)(do_getksig.o): do_getksig.c + $(CC) do_getksig.c + +$(SYSTEM)(do_endksig.o): do_endksig.c + $(CC) do_endksig.c + +$(SYSTEM)(do_kill.o): do_kill.c + $(CC) do_kill.c + +$(SYSTEM)(do_sigsend.o): do_sigsend.c + $(CC) do_sigsend.c + +$(SYSTEM)(do_sigreturn.o): do_sigreturn.c + $(CC) do_sigreturn.c + +$(SYSTEM)(do_getinfo.o): do_getinfo.c + $(CC) do_getinfo.c + +$(SYSTEM)(do_abort.o): do_abort.c + $(CC) do_abort.c + +$(SYSTEM)(do_svrctl.o): do_svrctl.c + $(CC) do_svrctl.c + +$(SYSTEM)(do_segctl.o): do_segctl.c + $(CC) do_segctl.c diff --git a/kernel/system/clock.c b/kernel/system/clock.c deleted file mode 100644 index 9a5223227..000000000 --- a/kernel/system/clock.c +++ /dev/null @@ -1,138 +0,0 @@ -/* The system call implemented in this file: - * m_type: SYS_TIMES - * - * The parameters for this system call are: - * m4_l1: T_PROC_NR (get info for this process) - * m4_l1: T_USER_TIME (return values ...) - * m4_l2: T_SYSTEM_TIME - * m4_l5: T_BOOT_TICKS - */ - -#include "../kernel.h" -#include "../system.h" -#include "../debug.h" -#include - -/*===========================================================================* - * do_times * - *===========================================================================*/ -PUBLIC int do_times(m_ptr) -register message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_times(). Retrieve the accounting information. */ - - register struct proc *rp; - int proc_nr; - - /* Insert the times needed by the SYS_TIMES system call in the message. */ - proc_nr = (m_ptr->T_PROC_NR == SELF) ? m_ptr->m_source : m_ptr->T_PROC_NR; - if (isokprocn(proc_nr)) { - rp = proc_addr(m_ptr->T_PROC_NR); - lock(11, "do_times"); /* halt the volatile time counters in rp */ - m_ptr->T_USER_TIME = rp->p_user_time; - m_ptr->T_SYSTEM_TIME = rp->p_sys_time; - unlock(11); - } - m_ptr->T_BOOT_TICKS = get_uptime(); - return(OK); -} - - -/* The system call implemented in this file: - * m_type: SYS_SIGNALRM, SYS_SYNCALRM - * - * The parameters for this system call are: - * m2_i1: ALRM_PROC_NR (set alarm for this process) - * m2_l1: ALRM_EXP_TIME (alarm's expiration time) - * m2_i2: ALRM_ABS_TIME (expiration time is absolute?) - * m2_l1: ALRM_SEC_LEFT (return seconds left of previous) - * - * Changes: - * Aug 25, 2004 fully rewritten to clean up code (Jorrit N. Herder) - */ - -FORWARD _PROTOTYPE( void cause_syncalrm, (timer_t *tp) ); -FORWARD _PROTOTYPE( void cause_signalrm, (timer_t *tp) ); - -/*===========================================================================* - * do_setalarm * - *===========================================================================*/ -PUBLIC int do_setalarm(m_ptr) -message *m_ptr; /* pointer to request message */ -{ -/* A process requests an alarm, or wants to cancel its alarm. This function - * is shared used for both the SYS_SIGNALRM and SYS_SYNCALRM. - */ - int proc_nr; /* which process wants the alarm */ - long exp_time; /* expiration time for this alarm */ - int use_abs_time; /* use absolute or relative time */ - timer_t *tp; /* the process' timer structure */ - clock_t uptime; /* placeholder for current uptime */ - - /* Extract shared parameters from the request message. */ - proc_nr = m_ptr->ALRM_PROC_NR; /* process to interrupt later */ - if (SELF == proc_nr) proc_nr = m_ptr->m_source; - if (! isokprocn(proc_nr)) return(EINVAL); - exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */ - use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */ - - /* Get the timer structure and set the parameters for this alarm. */ - tp = &(proc_addr(proc_nr)->p_alarm_timer); - tmr_arg(tp)->ta_int = proc_nr; - switch (m_ptr->m_type) { - case SYS_SYNCALRM: tp->tmr_func = cause_syncalrm; break; - case SYS_SIGNALRM: tp->tmr_func = cause_signalrm; break; - default: return(EINVAL); /* invalid alarm type */ - } - - /* Return the ticks left on the previous alarm. */ - uptime = get_uptime(); - if ((tp->tmr_exp_time == TMR_NEVER) || (tp->tmr_exp_time < uptime) ) { - m_ptr->ALRM_TIME_LEFT = 0; - } else { - m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime); - } - - /* Finally, (re)set the timer depending on 'exp_time'. */ - if (exp_time == 0) { - reset_timer(tp); - } else { - tp->tmr_exp_time = (use_abs_time) ? exp_time : exp_time + get_uptime(); - set_timer(tp, tp->tmr_exp_time, tp->tmr_func); - } - return(OK); -} - - -/*===========================================================================* - * cause_signalrm * - *===========================================================================*/ -PRIVATE void cause_signalrm(tp) -timer_t *tp; -{ -/* Routine called if a timer goes off for a process that requested an SIGALRM - * signal using the alarm(2) system call. The timer argument 'ta_int' contains - * the process number of the process to signal. - */ - cause_sig(tmr_arg(tp)->ta_int, SIGALRM); -} - - -/*===========================================================================* - * cause_syncalrm * - *===========================================================================*/ -PRIVATE void cause_syncalrm(tp) -timer_t *tp; -{ -/* Routine called if a timer goes off and the process requested a synchronous - * alarm. The process number is stored in timer argument 'ta_int'. Notify that - * process given with a SYN_ALARM message. - */ - message m; - m.NOTIFY_TYPE = SYN_ALARM; - m.NOTIFY_ARG = get_uptime(); - m.NOTIFY_FLAGS = 0; - lock_notify(tmr_arg(tp)->ta_int, &m); -} - - diff --git a/kernel/system/copying.c b/kernel/system/copying.c deleted file mode 100644 index 1f34ccb79..000000000 --- a/kernel/system/copying.c +++ /dev/null @@ -1,176 +0,0 @@ -/* The system call implemented in this file: - * m_type: SYS_VIRCOPY, SYS_PHYSCOPY, SYS_PHYSZERO - * - * The parameters for this system call are: - * m5_c1: CP_SRC_SPACE - * m5_l1: CP_SRC_ADDR - * m5_i1: CP_SRC_PROC_NR - * m5_c2: CP_DST_SPACE - * m5_l2: CP_DST_ADDR - * m5_i2: CP_DST_PROC_NR - * m5_l3: CP_NR_BYTES - */ - -#include "../kernel.h" -#include "../system.h" -#include - -/*===========================================================================* - * do_copy * - *===========================================================================*/ -PUBLIC int do_copy(m_ptr) -register message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or - * physical addressing. - */ - struct vir_addr vir_addr[2]; /* virtual source and destination address */ - vir_bytes bytes; /* number of bytes to copy */ - int i; - - /* Dismember the command message. */ - vir_addr[_SRC_].proc_nr = m_ptr->CP_SRC_PROC_NR; - vir_addr[_SRC_].segment = m_ptr->CP_SRC_SPACE; - vir_addr[_SRC_].offset = (vir_bytes) m_ptr->CP_SRC_ADDR; - vir_addr[_DST_].proc_nr = m_ptr->CP_DST_PROC_NR; - vir_addr[_DST_].segment = m_ptr->CP_DST_SPACE; - vir_addr[_DST_].offset = (vir_bytes) m_ptr->CP_DST_ADDR; - bytes = (phys_bytes) m_ptr->CP_NR_BYTES; - - /* Now do some checks for both the source and destination virtual address. - * This is done once for _SRC_, then once for _DST_. - */ - for (i=_SRC_; i<=_DST_; i++) { - - /* Check if process number was given implictly with SELF and is valid. */ - if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source; - if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) { - kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_NUM); - return(EINVAL); - } - - /* Check if physical addressing is used without SYS_PHYSCOPY. */ - if ((vir_addr[i].segment & PHYS_SEG) && - m_ptr->m_type != SYS_PHYSCOPY) return(EPERM); - } - - /* Check for overflow. This would happen for 64K segments and 16-bit - * vir_bytes. Especially copying by the PM on do_fork() is affected. - */ - if (bytes != (vir_bytes) bytes) { - kprintf("do_vircopy: overflow\n", NO_NUM); - return(E2BIG); - } - - /* Now try to make the actual virtual copy. */ - return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) ); -} - - -/* Buffer to hold copy request vector from user. */ -PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE]; - -/*===========================================================================* - * do_vcopy * - *===========================================================================*/ -PUBLIC int do_vcopy(m_ptr) -register message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */ - int nr_req; - int caller_pid; - vir_bytes caller_vir; - phys_bytes caller_phys; - phys_bytes kernel_phys; - phys_bytes bytes; - int i,s; - struct vir_cp_req *req; - - /* Check if request vector size is ok. */ - nr_req = (unsigned) m_ptr->VCP_VEC_SIZE; - if (nr_req > VCOPY_VEC_SIZE) return(EINVAL); - bytes = nr_req * sizeof(struct vir_cp_req); - - /* Calculate physical addresses and copy (port,value)-pairs from user. */ - caller_pid = (int) m_ptr->m_source; - caller_vir = (vir_bytes) m_ptr->VCP_VEC_ADDR; - caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes); - if (0 == caller_phys) return(EFAULT); - kernel_phys = vir2phys(vir_cp_req); - phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes); - - /* Assume vector with requests is correct. Try to copy everything. */ - for (i=0; isrc.segment | req->dst.segment) & PHYS_SEG) && - m_ptr->m_type != SYS_PHYSVCOPY) - return(EPERM); - if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK) - return(s); - } - return(OK); -} - -/*===========================================================================* - * do_physzero * - *===========================================================================*/ -PUBLIC int do_physzero(m_ptr) -register message *m_ptr; -{ -/* Handle sys_physzero(). */ - phys_zero((phys_bytes) m_ptr->PZ_MEM_PTR, (phys_bytes) m_ptr->PZ_COUNT); - return(OK); -} - - -/* The system call implemented in this file: - * m_type: SYS_UMAP - * - * The parameters for this system call are: - * m5_i1: CP_SRC_PROC_NR (process number) - * m5_c1: CP_SRC_SPACE (segment where address is: T, D, or S) - * m5_l1: CP_SRC_ADDR (virtual address) - * m5_l2: CP_DST_ADDR (returns physical address) - * m5_l3: CP_NR_BYTES (size of datastructure) - */ - -/*==========================================================================* - * do_umap * - *==========================================================================*/ -PUBLIC int do_umap(m_ptr) -register message *m_ptr; /* pointer to request message */ -{ -/* Map virtual address to physical, for non-kernel processes. */ - int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE; - int seg_index = m_ptr->CP_SRC_SPACE & SEGMENT_INDEX; - vir_bytes offset = m_ptr->CP_SRC_ADDR; - int count = m_ptr->CP_NR_BYTES; - int proc_nr = (int) m_ptr->CP_SRC_PROC_NR; - phys_bytes phys_addr; - - /* Verify process number. */ - if (proc_nr == SELF) proc_nr = m_ptr->m_source; - if (! isokprocn(proc_nr)) return(EINVAL); - - /* See which mapping should be made. */ - switch(seg_type) { - case LOCAL_SEG: - phys_addr = umap_local(proc_addr(proc_nr), seg_index, offset, count); - break; - case REMOTE_SEG: - phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count); - break; - case BIOS_SEG: - phys_addr = umap_bios(proc_addr(proc_nr), offset, count); - break; - default: - return(EINVAL); - } - m_ptr->CP_DST_ADDR = phys_addr; - return (phys_addr == 0) ? EFAULT: OK; -} - - diff --git a/kernel/system/do_abort.c b/kernel/system/do_abort.c new file mode 100644 index 000000000..3a68bc8d7 --- /dev/null +++ b/kernel/system/do_abort.c @@ -0,0 +1,46 @@ +#include "../system.h" +#include + + +/* The system call implemented in this file: + * m_type: SYS_ABORT + * + * The parameters for this system call are: + * m1_i1: ABRT_HOW (how to abort, possibly fetch monitor params) + * m1_i2: ABRT_MON_PROC (proc nr to get monitor params from) + * m1_i3: ABRT_MON_LEN (length of monitor params) + * m1_p1: ABRT_MON_ADDR (virtual address of params) + */ +#if USE_ABORT + +/*===========================================================================* + * do_abort * + *===========================================================================*/ +PUBLIC int do_abort(m_ptr) +message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_abort. MINIX is unable to continue. This can originate in the + * PM (normal abort or panic) or FS (panic), or TTY (user issued CTRL-ALT-DEL + * or ESC after debugging dumps). + */ + int how = m_ptr->ABRT_HOW; + + if (how == RBT_MONITOR) { + /* The monitor is to run the specified instructions. */ + int proc_nr = m_ptr->ABRT_MON_PROC; + int length = m_ptr->ABRT_MON_LEN + 1; + vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR; + phys_bytes src_phys = numap_local(proc_nr, src_vir, length); + + /* Validate length and address of shutdown code before copying. */ + if (length > kinfo.params_size || src_phys == 0) + phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11); + else + phys_copy(src_phys, kinfo.params_base, (phys_bytes) length); + } + prepare_shutdown(how); + return(OK); /* pro-forma (really EDISASTER) */ +} + +#endif /* USE_ABORT */ + diff --git a/kernel/system/do_alarm.c b/kernel/system/do_alarm.c new file mode 100644 index 000000000..a1d6c4ef8 --- /dev/null +++ b/kernel/system/do_alarm.c @@ -0,0 +1,77 @@ +/* The system call implemented in this file: + * m_type: SYS_SETALARM + * + * The parameters for this system call are: + * m2_i1: ALRM_PROC_NR (set alarm for this process) + * m2_l1: ALRM_EXP_TIME (alarm's expiration time) + * m2_i2: ALRM_ABS_TIME (expiration time is absolute?) + * m2_l1: ALRM_SEC_LEFT (return seconds left of previous) + * + * Changes: + * Aug 25, 2004 fully rewritten to clean up code (Jorrit N. Herder) + */ + +#include "../system.h" + +#if USE_SETALARM + +FORWARD _PROTOTYPE( void cause_alarm, (timer_t *tp) ); + +/*===========================================================================* + * do_setalarm * + *===========================================================================*/ +PUBLIC int do_setalarm(m_ptr) +message *m_ptr; /* pointer to request message */ +{ +/* A process requests a synchronous alarm, or wants to cancel its alarm. */ + int proc_nr; /* which process wants the alarm */ + long exp_time; /* expiration time for this alarm */ + int use_abs_time; /* use absolute or relative time */ + timer_t *tp; /* the process' timer structure */ + clock_t uptime; /* placeholder for current uptime */ + + /* Extract shared parameters from the request message. */ + proc_nr = m_ptr->ALRM_PROC_NR; /* process to interrupt later */ + if (SELF == proc_nr) proc_nr = m_ptr->m_source; + if (! isokprocn(proc_nr)) return(EINVAL); + exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */ + use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */ + + /* Get the timer structure and set the parameters for this alarm. */ + tp = &(proc_addr(proc_nr)->p_priv->s_alarm_timer); + tmr_arg(tp)->ta_int = proc_nr; + tp->tmr_func = cause_alarm; + + /* Return the ticks left on the previous alarm. */ + uptime = get_uptime(); + if ((tp->tmr_exp_time == TMR_NEVER) || (tp->tmr_exp_time < uptime) ) { + m_ptr->ALRM_TIME_LEFT = 0; + } else { + m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime); + } + + /* Finally, (re)set the timer depending on 'exp_time'. */ + if (exp_time == 0) { + reset_timer(tp); + } else { + tp->tmr_exp_time = (use_abs_time) ? exp_time : exp_time + get_uptime(); + set_timer(tp, tp->tmr_exp_time, tp->tmr_func); + } + return(OK); +} + + +/*===========================================================================* + * cause_alarm * + *===========================================================================*/ +PRIVATE void cause_alarm(tp) +timer_t *tp; +{ +/* Routine called if a timer goes off and the process requested a synchronous + * alarm. The process number is stored in timer argument 'ta_int'. Notify that + * process given with a SYN_ALARM message. + */ + lock_alert(CLOCK, tmr_arg(tp)->ta_int); +} + +#endif /* USE_SETALARM */ diff --git a/kernel/system/do_copy.c b/kernel/system/do_copy.c new file mode 100644 index 000000000..d6975012c --- /dev/null +++ b/kernel/system/do_copy.c @@ -0,0 +1,71 @@ +/* The system call implemented in this file: + * m_type: SYS_VIRCOPY, SYS_PHYSCOPY + * + * The parameters for this system call are: + * m5_c1: CP_SRC_SPACE + * m5_l1: CP_SRC_ADDR + * m5_i1: CP_SRC_PROC_NR + * m5_c2: CP_DST_SPACE + * m5_l2: CP_DST_ADDR + * m5_i2: CP_DST_PROC_NR + * m5_l3: CP_NR_BYTES + */ + +#include "../system.h" +#include + +#if (USE_VIRCOPY || USE_PHYSCOPY) + +/*===========================================================================* + * do_copy * + *===========================================================================*/ +PUBLIC int do_copy(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or + * physical addressing. + */ + struct vir_addr vir_addr[2]; /* virtual source and destination address */ + vir_bytes bytes; /* number of bytes to copy */ + int i; + + /* Dismember the command message. */ + vir_addr[_SRC_].proc_nr = m_ptr->CP_SRC_PROC_NR; + vir_addr[_SRC_].segment = m_ptr->CP_SRC_SPACE; + vir_addr[_SRC_].offset = (vir_bytes) m_ptr->CP_SRC_ADDR; + vir_addr[_DST_].proc_nr = m_ptr->CP_DST_PROC_NR; + vir_addr[_DST_].segment = m_ptr->CP_DST_SPACE; + vir_addr[_DST_].offset = (vir_bytes) m_ptr->CP_DST_ADDR; + bytes = (phys_bytes) m_ptr->CP_NR_BYTES; + + /* Now do some checks for both the source and destination virtual address. + * This is done once for _SRC_, then once for _DST_. + */ + for (i=_SRC_; i<=_DST_; i++) { + + /* Check if process number was given implictly with SELF and is valid. */ + if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source; + if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) { + kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_NUM); + return(EINVAL); + } + + /* Check if physical addressing is used without SYS_PHYSCOPY. */ + if ((vir_addr[i].segment & PHYS_SEG) && + m_ptr->m_type != SYS_PHYSCOPY) return(EPERM); + } + + /* Check for overflow. This would happen for 64K segments and 16-bit + * vir_bytes. Especially copying by the PM on do_fork() is affected. + */ + if (bytes != (vir_bytes) bytes) { + kprintf("do_vircopy: overflow\n", NO_NUM); + return(E2BIG); + } + + /* Now try to make the actual virtual copy. */ + return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) ); +} +#endif /* (USE_VIRCOPY || USE_PHYSCOPY) */ + + diff --git a/kernel/system/do_devio.c b/kernel/system/do_devio.c new file mode 100644 index 000000000..26bf87a7f --- /dev/null +++ b/kernel/system/do_devio.c @@ -0,0 +1,44 @@ +/* The system call implemented in this file: + * m_type: SYS_DEVIO + * + * The parameters for this system call are: + * m2_i3: DIO_REQUEST (request input or output) + * m2_i1: DIO_TYPE (flag indicating byte, word, or long) + * m2_l1: DIO_PORT (port to read/ write) + * m2_l2: DIO_VALUE (value to write/ return value read) + * + * Author: + * Jorrit N. Herder + */ + +#include "../system.h" +#include + +#if USE_DEVIO + +/*===========================================================================* + * do_devio * + *===========================================================================*/ +PUBLIC int do_devio(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ + /* Perform actual device I/O for byte, word, and long values. */ + if (m_ptr->DIO_REQUEST == DIO_INPUT) { + switch (m_ptr->DIO_TYPE) { + case DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break; + case DIO_WORD: m_ptr->DIO_VALUE = inw(m_ptr->DIO_PORT); break; + case DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break; + default: return(EINVAL); + } + } else { + switch (m_ptr->DIO_TYPE) { + case DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break; + case DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break; + case DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break; + default: return(EINVAL); + } + } + return(OK); +} + +#endif /* USE_DEVIO */ diff --git a/kernel/system/do_endksig.c b/kernel/system/do_endksig.c new file mode 100644 index 000000000..e2babbfad --- /dev/null +++ b/kernel/system/do_endksig.c @@ -0,0 +1,49 @@ +/* The system call that is implemented in this file: + * SYS_SIGCTL # signal handling functionality + * + * The parameters and types for this system call are: + * SIG_REQUEST # request to perform (long) + * SIG_PROC # process to signal/ pending (int) + * SIG_CTXT_PTR # pointer to sigcontext structure (pointer) + * SIG_FLAGS # flags for S_SIGRETURN call (int) + * SIG_MAP # bit map with pending signals (long) + * SIG_NUMBER # signal number to send to process (int) + * + * Supported request types are in the parameter SIG_REQUEST: + * S_GETSIG # get a pending kernel signal + * S_ENDSIG # signal has been processed + * S_SENDSIG # deliver a POSIX-style signal + * S_SIGRETURN # return from a POSIX-style signal + * S_KILL # send a signal to a process + */ + +#include "../system.h" +#include +#include + +#if USE_ENDKSIG + +/*===========================================================================* + * do_endksig * + *===========================================================================*/ +PUBLIC int do_endksig(m_ptr) +message *m_ptr; /* pointer to request message */ +{ +/* Finish up after a kernel type signal, caused by a SYS_KILL message or a + * call to cause_sig by a task. This is called by the PM after processing a + * signal it got with SYS_GETKSIG. + */ + register struct proc *rp; + + rp = proc_addr(m_ptr->SIG_PROC); + if (isemptyp(rp)) return(EINVAL); /* process already dead? */ + + /* PM has finished one kernel signal. Perhaps process is ready now? */ + if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */ + if ((rp->p_rts_flags &= ~SIG_PENDING)==0) /* remove pending flag */ + lock_ready(rp); /* ready if no flags */ + return(OK); +} + +#endif /* USE_ENDKSIG */ + diff --git a/kernel/system/do_exec.c b/kernel/system/do_exec.c new file mode 100644 index 000000000..d5e0635ce --- /dev/null +++ b/kernel/system/do_exec.c @@ -0,0 +1,63 @@ +/* The system call implemented in this file: + * m_type: SYS_EXEC + * + * The parameters for this system call are: + * m1_i1: PR_PROC_NR (process that did exec call) + * m1_i3: PR_TRACING (flag to indicate tracing is on/ off) + * m1_p1: PR_STACK_PTR (new stack pointer) + * m1_p2: PR_NAME_PTR (pointer to program name) + * m1_p3: PR_IP_PTR (new instruction pointer) + */ +#include "../system.h" +#include + +#if USE_EXEC + +/*===========================================================================* + * do_exec * + *===========================================================================*/ +PUBLIC int do_exec(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */ + + register struct proc *rp; + reg_t sp; /* new sp */ + phys_bytes phys_name; + char *np; + + rp = proc_addr(m_ptr->PR_PROC_NR); + if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP); + sp = (reg_t) m_ptr->PR_STACK_PTR; + rp->p_reg.sp = sp; /* set the stack pointer */ +#if (CHIP == M68000) + rp->p_splow = sp; /* set the stack pointer low water */ +#ifdef FPP + /* Initialize fpp for this process */ + fpp_new_state(rp); +#endif +#endif +#if (CHIP == INTEL) /* wipe extra LDT entries */ + kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0, + (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0])); +#endif + rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */ + rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */ + if (rp->p_rts_flags == 0) lock_ready(rp); + + /* Save command name for debugging, ps(1) output, etc. */ + phys_name = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->PR_NAME_PTR, + (vir_bytes) P_NAME_LEN - 1); + if (phys_name != 0) { + phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1); + for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {} + *np = 0; /* mark end */ + } else { + kstrncpy(rp->p_name, "", P_NAME_LEN); + } + return(OK); +} +#endif /* USE_EXEC */ + + + diff --git a/kernel/system/do_exit.c b/kernel/system/do_exit.c new file mode 100644 index 000000000..c690b0914 --- /dev/null +++ b/kernel/system/do_exit.c @@ -0,0 +1,42 @@ +/* The system call implemented in this file: + * m_type: SYS_EXIT + * + * The parameters for this system call are: + * m1_i1: PR_PROC_NR (slot number of exiting process) + */ + +#include "../system.h" + +#if USE_EXIT + +/*===========================================================================* + * do_exit * + *===========================================================================*/ +PUBLIC int do_exit(m_ptr) +message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_exit. A user process has exited or a system process requests + * to exit. Only the PM can request other process slots to be cleared. + * The routine to clean up a process table slot cancels outstanding timers, + * possibly removes the process from the message queues, and resets certain + * process table fields to the default values. + */ + int exit_proc_nr; + + /* Determine what process exited. User processes are handled here. */ + if (PM_PROC_NR == m_ptr->m_source) { + exit_proc_nr = m_ptr->PR_PROC_NR; /* get exiting process */ + if (exit_proc_nr != SELF) { /* PM tries to exit self */ + if (! isokprocn(exit_proc_nr)) return(EINVAL); + clear_proc(exit_proc_nr); /* exit a user process */ + return(OK); /* report back to PM */ + } + } + + /* The PM or some other system process requested to be exited. */ + clear_proc(m_ptr->m_source); + return(EDONTREPLY); +} +#endif /* USE_EXIT */ + + diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c new file mode 100644 index 000000000..8afdcd4eb --- /dev/null +++ b/kernel/system/do_fork.c @@ -0,0 +1,62 @@ +/* The system call implemented in this file: + * m_type: SYS_FORK + * + * The parameters for this system call are: + * m1_i1: PR_PROC_NR (child's process table slot) + * m1_i2: PR_PPROC_NR (parent, process that forked) + * m1_i3: PR_PID (child pid received from PM) + */ + +#include "../system.h" +#include +#if (CHIP == INTEL) +#include "../protect.h" +#endif + +#if USE_FORK + +/*===========================================================================* + * do_fork * + *===========================================================================*/ +PUBLIC int do_fork(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_fork(). PR_PPROC_NR has forked. The child is PR_PROC_NR. */ + +#if (CHIP == INTEL) + reg_t old_ldt_sel; +#endif + register struct proc *rpc; + struct proc *rpp; + + rpp = proc_addr(m_ptr->PR_PPROC_NR); + rpc = proc_addr(m_ptr->PR_PROC_NR); + if (! isemptyp(rpc)) return(EINVAL); + + /* Copy parent 'proc' struct to child. */ +#if (CHIP == INTEL) + old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */ +#endif + + *rpc = *rpp; /* copy 'proc' struct */ + +#if (CHIP == INTEL) + rpc->p_ldt_sel = old_ldt_sel; +#endif + rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */ + rpc->p_ntf_q = NULL; /* remove pending notifications */ + + /* Only one in group should have SIGNALED, child doesn't inherit tracing. */ + rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */ + rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP); + sigemptyset(&rpc->p_pending); + + rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */ + rpc->p_user_time = 0; /* set all the accounting times to 0 */ + rpc->p_sys_time = 0; + + return(OK); +} + +#endif /* USE_FORK */ + diff --git a/kernel/system/misc.c b/kernel/system/do_getinfo.c similarity index 63% rename from kernel/system/misc.c rename to kernel/system/do_getinfo.c index 8eea9c6b2..6dfc9191f 100644 --- a/kernel/system/misc.c +++ b/kernel/system/do_getinfo.c @@ -1,61 +1,3 @@ -#include "../kernel.h" -#include "../system.h" -#include -#include - - -/*===========================================================================* - * do_unused * - *===========================================================================*/ -PUBLIC int do_unused(m) -message *m; /* pointer to request message */ -{ - kprintf("SYS task got illegal request from %d.", m->m_source); - return(EBADREQUEST); /* illegal message type */ -} - - - -/* The system call implemented in this file: - * m_type: SYS_ABORT - * - * The parameters for this system call are: - * m1_i1: ABRT_HOW (how to abort, possibly fetch monitor params) - * m1_i2: ABRT_MON_PROC (proc nr to get monitor params from) - * m1_i3: ABRT_MON_LEN (length of monitor params) - * m1_p1: ABRT_MON_ADDR (virtual address of params) - */ - -/*===========================================================================* - * do_abort * - *===========================================================================*/ -PUBLIC int do_abort(m_ptr) -message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_abort. MINIX is unable to continue. This can originate in the - * PM (normal abort or panic) or FS (panic), or TTY (a CTRL-ALT-DEL or ESC - * after debugging dumps). - */ - int how = m_ptr->ABRT_HOW; - - if (how == RBT_MONITOR) { - /* The monitor is to run the specified instructions. */ - int proc_nr = m_ptr->ABRT_MON_PROC; - int length = m_ptr->ABRT_MON_LEN + 1; - vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR; - phys_bytes src_phys = numap_local(proc_nr, src_vir, length); - - /* Validate length and address of shutdown code before copying. */ - if (length > kinfo.params_size || src_phys == 0) - phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11); - else - phys_copy(src_phys, kinfo.params_base, (phys_bytes) length); - } - prepare_shutdown(how); - return(OK); /* pro-forma (really EDISASTER) */ -} - - /* The system call implemented in this file: * m_type: SYS_GETINFO * @@ -71,6 +13,10 @@ message *m_ptr; /* pointer to request message */ * Jorrit N. Herder */ +#include "../system.h" + +#if USE_GETINFO + /*===========================================================================* * do_getinfo * *===========================================================================*/ @@ -96,7 +42,7 @@ register message *m_ptr; /* pointer to request message */ break; } case GET_IMAGE: { - length = sizeof(struct system_image) * IMAGE_SIZE; + length = sizeof(struct system_image) * NR_BOOT_PROCS; src_phys = vir2phys(image); break; } @@ -123,6 +69,11 @@ register message *m_ptr; /* pointer to request message */ src_phys = vir2phys(proc); break; } + case GET_PRIVTAB: { + length = sizeof(struct priv) * (NR_SYS_PROCS); + src_phys = vir2phys(priv); + break; + } case GET_PROC: { nr = (m_ptr->I_KEY_LEN == SELF) ? m_ptr->m_source : m_ptr->I_KEY_LEN; if (! isokprocn(nr)) return(EINVAL); /* validate request */ @@ -147,7 +98,7 @@ register message *m_ptr; /* pointer to request message */ src_phys = vir2phys(&kmess); break; } -#if ENABLE_LOCK_TIMING +#if DEBUG_TIME_LOCKS case GET_LOCKTIMING: { length = sizeof(timingdata); src_phys = vir2phys(timingdata); @@ -167,4 +118,5 @@ register message *m_ptr; /* pointer to request message */ return(OK); } +#endif /* USE_GETINFO */ diff --git a/kernel/system/do_getksig.c b/kernel/system/do_getksig.c new file mode 100644 index 000000000..51e5bfcfb --- /dev/null +++ b/kernel/system/do_getksig.c @@ -0,0 +1,55 @@ +/* The system call that is implemented in this file: + * SYS_SIGCTL # signal handling functionality + * + * The parameters and types for this system call are: + * SIG_REQUEST # request to perform (long) + * SIG_PROC # process to signal/ pending (int) + * SIG_CTXT_PTR # pointer to sigcontext structure (pointer) + * SIG_FLAGS # flags for S_SIGRETURN call (int) + * SIG_MAP # bit map with pending signals (long) + * SIG_NUMBER # signal number to send to process (int) + * + * Supported request types are in the parameter SIG_REQUEST: + * S_GETSIG # get a pending kernel signal + * S_ENDSIG # signal has been processed + * S_SENDSIG # deliver a POSIX-style signal + * S_SIGRETURN # return from a POSIX-style signal + * S_KILL # send a signal to a process + */ + +#include "../system.h" +#include +#include + +#if USE_GETKSIG + +/*===========================================================================* + * do_getksig * + *===========================================================================*/ +PUBLIC int do_getksig(m_ptr) +message *m_ptr; /* pointer to request message */ +{ +/* PM is ready to accept signals and repeatedly does a system call to get + * one. Find a process with pending signals. If no signals are available, + * return NONE in the process number field. + */ + register struct proc *rp; + + /* Find the next process with pending signals. */ + for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) { + if (rp->p_rts_flags & SIGNALED) { + m_ptr->SIG_PROC = rp->p_nr; + m_ptr->SIG_MAP = rp->p_pending; + sigemptyset(&rp->p_pending); /* ball is in PM's court */ + rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */ + return(OK); + } + } + + /* No process with pending signals was found. */ + m_ptr->SIG_PROC = NONE; + return(OK); +} +#endif /* USE_GETKSIG */ + + diff --git a/kernel/system/irqctl.c b/kernel/system/do_irqctl.c similarity index 98% rename from kernel/system/irqctl.c rename to kernel/system/do_irqctl.c index 8cb0a1a71..618c07f83 100644 --- a/kernel/system/irqctl.c +++ b/kernel/system/do_irqctl.c @@ -11,9 +11,10 @@ * Jorrit N. Herder */ -#include "../kernel.h" #include "../system.h" +#if USE_IRQCTL + /*===========================================================================* * do_irqctl * *===========================================================================*/ @@ -95,3 +96,5 @@ register message *m_ptr; /* pointer to request message */ return(r); } +#endif /* USE_IRQCTL */ + diff --git a/kernel/system/do_kill.c b/kernel/system/do_kill.c new file mode 100644 index 000000000..0b33cc90f --- /dev/null +++ b/kernel/system/do_kill.c @@ -0,0 +1,41 @@ +/* The system call that is implemented in this file: + * SYS_SIGCTL # signal handling functionality + * + * The parameters and types for this system call are: + * SIG_REQUEST # request to perform (long) + * SIG_PROC # process to signal/ pending (int) + * SIG_CTXT_PTR # pointer to sigcontext structure (pointer) + * SIG_FLAGS # flags for S_SIGRETURN call (int) + * SIG_MAP # bit map with pending signals (long) + * SIG_NUMBER # signal number to send to process (int) + * + * Supported request types are in the parameter SIG_REQUEST: + * S_GETSIG # get a pending kernel signal + * S_ENDSIG # signal has been processed + * S_SENDSIG # deliver a POSIX-style signal + * S_SIGRETURN # return from a POSIX-style signal + * S_KILL # send a signal to a process + */ + +#include "../system.h" +#include +#include + +#if USE_KILL + +/*===========================================================================* + * do_kill * + *===========================================================================*/ +PUBLIC int do_kill(m_ptr) +message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_kill(). Cause a signal to be sent to a process via PM. + * Note that this has nothing to do with the kill (2) system call, this + * is how the FS (and possibly other servers) get access to cause_sig. + */ + cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER); + return(OK); +} + +#endif /* USE_KILL */ + diff --git a/kernel/system/do_memset.c b/kernel/system/do_memset.c new file mode 100644 index 000000000..68efcf9e8 --- /dev/null +++ b/kernel/system/do_memset.c @@ -0,0 +1,27 @@ +/* The system call implemented in this file: + * m_type: SYS_MEMSET + * + * The parameters for this system call are: + * m5_l1: CP_SRC_ADDR (virtual address) + * m5_l2: CP_DST_ADDR (returns physical address) + * m5_l3: CP_NR_BYTES (size of datastructure) + */ + +#include "../system.h" + +#if USE_MEMSET + +/*===========================================================================* + * do_memset * + *===========================================================================*/ +PUBLIC int do_memset(m_ptr) +register message *m_ptr; +{ +/* Handle sys_memset(). */ + phys_zero((phys_bytes) m_ptr->MEM_PTR, (phys_bytes) m_ptr->MEM_COUNT); + return(OK); +} + +#endif /* USE_MEMSET */ + + diff --git a/kernel/system/do_newmap.c b/kernel/system/do_newmap.c new file mode 100644 index 000000000..60d712bfb --- /dev/null +++ b/kernel/system/do_newmap.c @@ -0,0 +1,53 @@ +/* The system call implemented in this file: + * m_type: SYS_NEWMAP + * + * The parameters for this system call are: + * m1_i1: PR_PROC_NR (install new map for this process) + * m1_p1: PR_MEM_PTR (pointer to memory map) + */ +#include "../system.h" + +#if USE_NEWMAP + +/*===========================================================================* + * do_newmap * + *===========================================================================*/ +PUBLIC int do_newmap(m_ptr) +message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_newmap(). Fetch the memory map from PM. */ + + register struct proc *rp; + phys_bytes src_phys; + int caller; /* whose space has the new map (usually PM) */ + int k; /* process whose map is to be loaded */ + int old_flags; /* value of flags before modification */ + struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ + + /* Extract message parameters and copy new memory map from PM. */ + caller = m_ptr->m_source; + k = m_ptr->PR_PROC_NR; + map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR; + if (!isokprocn(k)) return(EINVAL); + rp = proc_addr(k); /* ptr to entry of user getting new map */ + + /* Copy the map from PM. */ + src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr, + sizeof(rp->p_memmap)); + if (src_phys == 0) return(EFAULT); + phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap)); + +#if (CHIP != M68000) + alloc_segments(rp); +#else + pmmu_init_proc(rp); +#endif + old_flags = rp->p_rts_flags; /* save the previous value of the flags */ + rp->p_rts_flags &= ~NO_MAP; + if (old_flags != 0 && rp->p_rts_flags == 0) lock_ready(rp); + + return(OK); +} +#endif /* USE_NEWMAP */ + + diff --git a/kernel/system/do_schedctl.c b/kernel/system/do_schedctl.c new file mode 100644 index 000000000..08a0a5fa8 --- /dev/null +++ b/kernel/system/do_schedctl.c @@ -0,0 +1,50 @@ +/* The system call implemented in this file: + * m_type: SYS_SCHEDCTL + * + * The parameters for this system call are: + * m1_i1: PR_PROC_NR process number to change priority + * m1_i2: PR_PRIORITY the new priority + */ + +#include "../system.h" +#include +#include + +#if USE_SCHEDCTL + +/*===========================================================================* + * do_schedctl * + *===========================================================================*/ +PUBLIC int do_schedctl(message *m_ptr) +{ + int proc_nr, pri, new_q ; + register struct proc *rp; + + /* Extract the message parameters and do sanity checking. */ + proc_nr = m_ptr->PR_PROC_NR; + if (! isokprocn(proc_nr)) return(EINVAL); + pri = m_ptr->PR_PRIORITY; + if (pri < PRIO_MIN || pri > PRIO_MAX) return(EINVAL); + + /* The priority is currently between PRIO_MIN and PRIO_MAX. We have to + * scale this between MIN_USER_Q and MAX_USER_Q. + */ + new_q = MAX_USER_Q + (pri-PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) / + (PRIO_MAX-PRIO_MIN+1); + if (new_q < MAX_USER_Q) new_q = MAX_USER_Q; /* shouldn't happen */ + if (new_q > MIN_USER_Q) new_q = MIN_USER_Q; /* shouldn't happen */ + + /* Make sure the process is not running while changing its priority; the + * max_priority is the base priority. Put the process back in its new + * queue if it is runnable. + */ + rp = proc_addr(proc_nr); + lock_unready(rp); + rp->p_max_priority = rp->p_priority = new_q; + if (! rp->p_rts_flags) lock_ready(rp); + + return(OK); +} + +#endif /* USE_SCHEDCTL */ + diff --git a/kernel/system/do_sdevio.c b/kernel/system/do_sdevio.c new file mode 100644 index 000000000..cc723bcf6 --- /dev/null +++ b/kernel/system/do_sdevio.c @@ -0,0 +1,61 @@ +/* The system call implemented in this file: + * m_type: SYS_SDEVIO + * + * The parameters for this system call are: + * m2_i3: DIO_REQUEST (request input or output) + * m2_i1: DIO_TYPE (flag indicating byte, word, or long) + * m2_l1: DIO_PORT (port to read/ write) + * m2_p1: DIO_VEC_ADDR (virtual address of buffer) + * m2_l2: DIO_VEC_SIZE (number of elements) + * m2_i2: DIO_VEC_PROC (process where buffer is) + */ + +#include "../system.h" +#include + +#if USE_SDEVIO + +/*===========================================================================* + * do_sdevio * + *===========================================================================*/ +PUBLIC int do_sdevio(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ + int proc_nr = m_ptr->DIO_VEC_PROC; + int count = m_ptr->DIO_VEC_SIZE; + long port = m_ptr->DIO_PORT; + phys_bytes phys_buf; + + /* Check if process number is OK. */ + if (proc_nr == SELF) proc_nr = m_ptr->m_source; + if (! isokprocn(proc_nr)) + return(EINVAL); + + /* Get and check physical address. */ + if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0) + return(EFAULT); + + /* Perform device I/O for bytes and words. Longs are not supported. */ + if (m_ptr->DIO_REQUEST == DIO_INPUT) { + switch (m_ptr->DIO_TYPE) { + case DIO_BYTE: phys_insb(port, phys_buf, count); break; + case DIO_WORD: phys_insw(port, phys_buf, count); break; + default: return(EINVAL); + } + } else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) { + switch (m_ptr->DIO_TYPE) { + case DIO_BYTE: phys_outsb(port, phys_buf, count); break; + case DIO_WORD: phys_outsw(port, phys_buf, count); break; + default: return(EINVAL); + } + } + else { + return(EINVAL); + } + return(OK); +} + +#endif /* USE_SDEVIO */ + + + diff --git a/kernel/system/do_segctl.c b/kernel/system/do_segctl.c new file mode 100644 index 000000000..0b39813e4 --- /dev/null +++ b/kernel/system/do_segctl.c @@ -0,0 +1,84 @@ +/* The system call implemented in this file: + * m_type: SYS_SEGCTL + * + * The parameters for this system call are: + * m4_l3: SEG_PHYS (physical base address) + * m4_l4: SEG_SIZE (size of segment) + * m4_l1: SEG_SELECT (return segment selector here) + * m4_l2: SEG_OFFSET (return offset within segment here) + * m4_l5: SEG_INDEX (return index into remote memory map here) + * + * Author: + * Jorrit N. Herder + */ +#include "../system.h" +#include "../protect.h" + +#if USE_SEGCTL + +/*===========================================================================* + * do_segctl * + *===========================================================================*/ +PUBLIC int do_segctl(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ +/* Return a segment selector and offset that can be used to reach a physical + * address, for use by a driver doing memory I/O in the A0000 - DFFFF range. + */ + u16_t selector; + vir_bytes offset; + int i, index; + register struct proc *rp; + phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS; + vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE; + int result; + + /* First check if there is a slot available for this segment. */ + rp = proc_addr(m_ptr->m_source); + index = -1; + for (i=0; i < NR_REMOTE_SEGS; i++) { + if (! rp->p_priv->s_farmem[i].in_use) { + index = i; + rp->p_priv->s_farmem[i].in_use = TRUE; + rp->p_priv->s_farmem[i].mem_phys = phys; + rp->p_priv->s_farmem[i].mem_len = size; + break; + } + } + if (index < 0) return(ENOSPC); + + + if (! machine.protected) { + selector = phys / HCLICK_SIZE; + offset = phys % HCLICK_SIZE; + result = OK; + } else { + /* Check if the segment size can be recorded in bytes, that is, check + * if descriptor's limit field can delimited the allowed memory region + * precisely. This works up to 1MB. If the size is larger, 4K pages + * instead of bytes are used. + */ + if (size < BYTE_GRAN_MAX) { + init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size, + USER_PRIVILEGE); + selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE; + offset = 0; + result = OK; + } else { + init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0, + USER_PRIVILEGE); + selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE; + offset = phys & 0xFFFF; + result = OK; + } + } + + /* Request successfully done. Now return the result. */ + m_ptr->SEG_INDEX = index | REMOTE_SEG; + m_ptr->SEG_SELECT = selector; + m_ptr->SEG_OFFSET = offset; + return(result); +} + +#endif /* USE_SEGCTL */ + diff --git a/kernel/system/do_sigreturn.c b/kernel/system/do_sigreturn.c new file mode 100644 index 000000000..d7abab433 --- /dev/null +++ b/kernel/system/do_sigreturn.c @@ -0,0 +1,79 @@ +/* The system call that is implemented in this file: + * SYS_SIGCTL # signal handling functionality + * + * The parameters and types for this system call are: + * SIG_REQUEST # request to perform (long) + * SIG_PROC # process to signal/ pending (int) + * SIG_CTXT_PTR # pointer to sigcontext structure (pointer) + * SIG_FLAGS # flags for S_SIGRETURN call (int) + * SIG_MAP # bit map with pending signals (long) + * SIG_NUMBER # signal number to send to process (int) + * + * Supported request types are in the parameter SIG_REQUEST: + * S_GETSIG # get a pending kernel signal + * S_ENDSIG # signal has been processed + * S_SENDSIG # deliver a POSIX-style signal + * S_SIGRETURN # return from a POSIX-style signal + * S_KILL # send a signal to a process + */ + +#include "../system.h" +#include +#include + +#if USE_SIGRETURN + +/*===========================================================================* + * do_sigreturn * + *===========================================================================*/ +PUBLIC int do_sigreturn(m_ptr) +message *m_ptr; /* pointer to request message */ +{ +/* POSIX style signals require sys_sigreturn to put things in order before + * the signalled process can resume execution + */ + struct sigcontext sc; + register struct proc *rp; + phys_bytes src_phys; + + rp = proc_addr(m_ptr->SIG_PROC); + + /* Copy in the sigcontext structure. */ + src_phys = umap_local(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR, + (vir_bytes) sizeof(struct sigcontext)); + if (src_phys == 0) return(EFAULT); + phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext)); + + /* Make sure that this is not just a jump buffer. */ + if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL); + + /* Fix up only certain key registers if the compiler doesn't use + * register variables within functions containing setjmp. + */ + if (sc.sc_flags & SC_NOREGLOCALS) { + rp->p_reg.retreg = sc.sc_retreg; + rp->p_reg.fp = sc.sc_fp; + rp->p_reg.pc = sc.sc_pc; + rp->p_reg.sp = sc.sc_sp; + return(OK); + } + sc.sc_psw = rp->p_reg.psw; + +#if (CHIP == INTEL) + /* Don't panic kernel if user gave bad selectors. */ + sc.sc_cs = rp->p_reg.cs; + sc.sc_ds = rp->p_reg.ds; + sc.sc_es = rp->p_reg.es; +#if _WORD_SIZE == 4 + sc.sc_fs = rp->p_reg.fs; + sc.sc_gs = rp->p_reg.gs; +#endif +#endif + + /* Restore the registers. */ + kmemcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs)); + return(OK); +} +#endif /* USE_SIGRETURN */ + + diff --git a/kernel/system/do_sigsend.c b/kernel/system/do_sigsend.c new file mode 100644 index 000000000..88c35469c --- /dev/null +++ b/kernel/system/do_sigsend.c @@ -0,0 +1,89 @@ +/* The system call that is implemented in this file: + * SYS_SIGCTL # signal handling functionality + * + * The parameters and types for this system call are: + * SIG_REQUEST # request to perform (long) + * SIG_PROC # process to signal/ pending (int) + * SIG_CTXT_PTR # pointer to sigcontext structure (pointer) + * SIG_FLAGS # flags for S_SIGRETURN call (int) + * SIG_MAP # bit map with pending signals (long) + * SIG_NUMBER # signal number to send to process (int) + * + * Supported request types are in the parameter SIG_REQUEST: + * S_GETSIG # get a pending kernel signal + * S_ENDSIG # signal has been processed + * S_SENDSIG # deliver a POSIX-style signal + * S_SIGRETURN # return from a POSIX-style signal + * S_KILL # send a signal to a process + */ + +#include "../system.h" +#include +#include + +#if USE_SIGSEND + +/*===========================================================================* + * do_sigsend * + *===========================================================================*/ +PUBLIC int do_sigsend(m_ptr) +message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_sigsend, POSIX-style signal handling. */ + + struct sigmsg smsg; + register struct proc *rp; + phys_bytes src_phys, dst_phys; + struct sigcontext sc, *scp; + struct sigframe fr, *frp; + + rp = proc_addr(m_ptr->SIG_PROC); + + /* Get the sigmsg structure into our address space. */ + src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes) + m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg)); + if (src_phys == 0) return(EFAULT); + phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg)); + + /* Compute the user stack pointer where sigcontext will be stored. */ + scp = (struct sigcontext *) smsg.sm_stkptr - 1; + + /* Copy the registers to the sigcontext structure. */ + kmemcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs)); + + /* Finish the sigcontext initialization. */ + sc.sc_flags = SC_SIGCONTEXT; + sc.sc_mask = smsg.sm_mask; + + /* Copy the sigcontext structure to the user's stack. */ + dst_phys = umap_local(rp, D, (vir_bytes) scp, + (vir_bytes) sizeof(struct sigcontext)); + if (dst_phys == 0) return(EFAULT); + phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext)); + + /* Initialize the sigframe structure. */ + frp = (struct sigframe *) scp - 1; + fr.sf_scpcopy = scp; + fr.sf_retadr2= (void (*)()) rp->p_reg.pc; + fr.sf_fp = rp->p_reg.fp; + rp->p_reg.fp = (reg_t) &frp->sf_fp; + fr.sf_scp = scp; + fr.sf_code = 0; /* XXX - should be used for type of FP exception */ + fr.sf_signo = smsg.sm_signo; + fr.sf_retadr = (void (*)()) smsg.sm_sigreturn; + + /* Copy the sigframe structure to the user's stack. */ + dst_phys = umap_local(rp, D, (vir_bytes) frp, + (vir_bytes) sizeof(struct sigframe)); + if (dst_phys == 0) return(EFAULT); + phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe)); + + /* Reset user registers to execute the signal handler. */ + rp->p_reg.sp = (reg_t) frp; + rp->p_reg.pc = (reg_t) smsg.sm_sighandler; + + return(OK); +} + +#endif /* USE_SIGSEND */ + diff --git a/kernel/system/do_svrctl.c b/kernel/system/do_svrctl.c new file mode 100644 index 000000000..15801920d --- /dev/null +++ b/kernel/system/do_svrctl.c @@ -0,0 +1,72 @@ +/* The system call implemented in this file: + * m_type: SYS_SVRCTL + * + * The parameters for this system call are: + * m2_i1: CTL_PROC_NR (process number of caller) + * m2_i2: CTL_REQUEST (request type) + * m2_i3: CTL_MM_PRIV (privilege) + * m2_l1: CTL_SEND_MASK (new send mask to be installed) + * m2_l2: CTL_PROC_TYPE (new process type) + * m2_p1: CTL_ARG_PTR (argument pointer) + */ + +#include "../system.h" +#include "../ipc.h" +#include + +#if USE_SVRCTL + +/* NOTE: this call will radically change! */ + +/*===========================================================================* + * do_svrctl * + *===========================================================================*/ +PUBLIC int do_svrctl(m_ptr) +message *m_ptr; /* pointer to request message */ +{ + register struct proc *rp; + register struct priv *sp; + int proc_nr, rights; + int request; + vir_bytes argp; + + /* Extract message parameters. */ + proc_nr = m_ptr->CTL_PROC_NR; + if (proc_nr == SELF) proc_nr = m_ptr->m_source; + if (! isokprocn(proc_nr)) return(EINVAL); + + request = m_ptr->CTL_REQUEST; + rights = m_ptr->CTL_MM_PRIV; + argp = (vir_bytes) m_ptr->CTL_ARG_PTR; + rp = proc_addr(proc_nr); + + /* Check if the PM privileges are super user. */ + if (!rights || !isuserp(rp)) + return(EPERM); + + /* See what is requested and handle the request. */ + switch (request) { + case SYSSIGNON: { + /* Make this process a server. The system processes should be able + * to communicate with this new server, so update their send masks + * as well. + */ + + /* Find a new system privileges structure for this process. */ + for (sp=BEG_PRIV_ADDR; sp< END_PRIV_ADDR; sp++) + if (sp->s_proc_nr == NONE) break; + if (sp->s_proc_nr != NONE) return(ENOSPC); + + /* Now update the process' privileges as requested. */ + rp->p_priv = sp; /* assign to process */ + rp->p_priv->s_proc_nr = proc_nr(rp); /* set association */ + rp->p_priv->s_call_mask = SYSTEM_CALL_MASK; + return(OK); + } + default: + return(EINVAL); + } +} + +#endif /* USE_SVRCTL */ + diff --git a/kernel/system/do_times.c b/kernel/system/do_times.c new file mode 100644 index 000000000..bbd925bcc --- /dev/null +++ b/kernel/system/do_times.c @@ -0,0 +1,40 @@ +/* The system call implemented in this file: + * m_type: SYS_TIMES + * + * The parameters for this system call are: + * m4_l1: T_PROC_NR (get info for this process) + * m4_l1: T_USER_TIME (return values ...) + * m4_l2: T_SYSTEM_TIME + * m4_l5: T_BOOT_TICKS + */ + +#include "../system.h" + +#if USE_TIMES + +/*===========================================================================* + * do_times * + *===========================================================================*/ +PUBLIC int do_times(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_times(). Retrieve the accounting information. */ + register struct proc *rp; + int proc_nr; + + /* Insert the times needed by the SYS_TIMES system call in the message. + * The clock's interrupt handler may run to update the user or system time + * while in this code, but that cannot do any harm. + */ + proc_nr = (m_ptr->T_PROC_NR == SELF) ? m_ptr->m_source : m_ptr->T_PROC_NR; + if (isokprocn(proc_nr)) { + rp = proc_addr(m_ptr->T_PROC_NR); + m_ptr->T_USER_TIME = rp->p_user_time; + m_ptr->T_SYSTEM_TIME = rp->p_sys_time; + } + m_ptr->T_BOOT_TICKS = get_uptime(); + return(OK); +} + +#endif /* USE_TIMES */ + diff --git a/kernel/system/tracing.c b/kernel/system/do_trace.c similarity index 99% rename from kernel/system/tracing.c rename to kernel/system/do_trace.c index 02d9f3bf7..bcf07bef7 100644 --- a/kernel/system/tracing.c +++ b/kernel/system/do_trace.c @@ -8,10 +8,10 @@ * m2_l2: CTL_DATA data to be written or returned here */ -#include "../kernel.h" #include "../system.h" #include +#if USE_TRACE /*==========================================================================* * do_trace * @@ -138,3 +138,4 @@ register message *m_ptr; return(OK); } +#endif /* USE_TRACE */ diff --git a/kernel/system/do_umap.c b/kernel/system/do_umap.c new file mode 100644 index 000000000..79956e19f --- /dev/null +++ b/kernel/system/do_umap.c @@ -0,0 +1,52 @@ +/* The system call implemented in this file: + * m_type: SYS_UMAP + * + * The parameters for this system call are: + * m5_i1: CP_SRC_PROC_NR (process number) + * m5_c1: CP_SRC_SPACE (segment where address is: T, D, or S) + * m5_l1: CP_SRC_ADDR (virtual address) + * m5_l2: CP_DST_ADDR (returns physical address) + * m5_l3: CP_NR_BYTES (size of datastructure) + */ + +#include "../system.h" + +#if USE_UMAP + +/*==========================================================================* + * do_umap * + *==========================================================================*/ +PUBLIC int do_umap(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ +/* Map virtual address to physical, for non-kernel processes. */ + int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE; + int seg_index = m_ptr->CP_SRC_SPACE & SEGMENT_INDEX; + vir_bytes offset = m_ptr->CP_SRC_ADDR; + int count = m_ptr->CP_NR_BYTES; + int proc_nr = (int) m_ptr->CP_SRC_PROC_NR; + phys_bytes phys_addr; + + /* Verify process number. */ + if (proc_nr == SELF) proc_nr = m_ptr->m_source; + if (! isokprocn(proc_nr)) return(EINVAL); + + /* See which mapping should be made. */ + switch(seg_type) { + case LOCAL_SEG: + phys_addr = umap_local(proc_addr(proc_nr), seg_index, offset, count); + break; + case REMOTE_SEG: + phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count); + break; + case BIOS_SEG: + phys_addr = umap_bios(proc_addr(proc_nr), offset, count); + break; + default: + return(EINVAL); + } + m_ptr->CP_DST_ADDR = phys_addr; + return (phys_addr == 0) ? EFAULT: OK; +} + +#endif /* USE_UMAP */ diff --git a/kernel/system/do_unused.c b/kernel/system/do_unused.c new file mode 100644 index 000000000..c0278ade7 --- /dev/null +++ b/kernel/system/do_unused.c @@ -0,0 +1,15 @@ + +#include "../system.h" + +/*===========================================================================* + * do_unused * + *===========================================================================*/ +PUBLIC int do_unused(m) +message *m; /* pointer to request message */ +{ + kprintf("SYSTEM got unused request %d", m->m_type); + kprintf("from %d.\n", m->m_source); + return(EBADREQUEST); /* illegal message type */ +} + + diff --git a/kernel/system/do_vcopy.c b/kernel/system/do_vcopy.c new file mode 100644 index 000000000..42cef8620 --- /dev/null +++ b/kernel/system/do_vcopy.c @@ -0,0 +1,67 @@ +/* The system call implemented in this file: + * m_type: SYS_VIRVCOPY, SYS_PHYSVCOPY + * + * The parameters for this system call are: + * m5_c1: CP_SRC_SPACE + * m5_l1: CP_SRC_ADDR + * m5_i1: CP_SRC_PROC_NR + * m5_c2: CP_DST_SPACE + * m5_l2: CP_DST_ADDR + * m5_i2: CP_DST_PROC_NR + * m5_l3: CP_NR_BYTES + */ + +#include "../system.h" +#include + +#if (USE_VIRVCOPY || USE_PHYSVCOPY) + +/* Buffer to hold copy request vector from user. */ +PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE]; + +/*===========================================================================* + * do_vcopy * + *===========================================================================*/ +PUBLIC int do_vcopy(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ +/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */ + int nr_req; + int caller_pid; + vir_bytes caller_vir; + phys_bytes caller_phys; + phys_bytes kernel_phys; + phys_bytes bytes; + int i,s; + struct vir_cp_req *req; + + /* Check if request vector size is ok. */ + nr_req = (unsigned) m_ptr->VCP_VEC_SIZE; + if (nr_req > VCOPY_VEC_SIZE) return(EINVAL); + bytes = nr_req * sizeof(struct vir_cp_req); + + /* Calculate physical addresses and copy (port,value)-pairs from user. */ + caller_pid = (int) m_ptr->m_source; + caller_vir = (vir_bytes) m_ptr->VCP_VEC_ADDR; + caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes); + if (0 == caller_phys) return(EFAULT); + kernel_phys = vir2phys(vir_cp_req); + phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes); + + /* Assume vector with requests is correct. Try to copy everything. */ + for (i=0; isrc.segment | req->dst.segment) & PHYS_SEG) && + m_ptr->m_type != SYS_PHYSVCOPY) + return(EPERM); + if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK) + return(s); + } + return(OK); +} + +#endif /* (USE_VIRVCOPY || USE_PHYSVCOPY) */ + diff --git a/kernel/system/devio.c b/kernel/system/do_vdevio.c similarity index 62% rename from kernel/system/devio.c rename to kernel/system/do_vdevio.c index 499148695..5b94870d1 100644 --- a/kernel/system/devio.c +++ b/kernel/system/do_vdevio.c @@ -1,100 +1,3 @@ -/* The system call implemented in this file: - * m_type: SYS_DEVIO - * - * The parameters for this system call are: - * m2_i3: DIO_REQUEST (request input or output) - * m2_i1: DIO_TYPE (flag indicating byte, word, or long) - * m2_l1: DIO_PORT (port to read/ write) - * m2_l2: DIO_VALUE (value to write/ return value read) - * - * Author: - * Jorrit N. Herder - */ - -#include "../kernel.h" -#include "../system.h" -#include "../debug.h" -#include - -/*===========================================================================* - * do_devio * - *===========================================================================*/ -PUBLIC int do_devio(m_ptr) -register message *m_ptr; /* pointer to request message */ -{ - /* perform actual device I/O for byte, word, and long values */ - if (m_ptr->DIO_REQUEST == DIO_INPUT) { - switch (m_ptr->DIO_TYPE) { - case DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break; - case DIO_WORD: m_ptr->DIO_VALUE = inw(m_ptr->DIO_PORT); break; - case DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break; - default: return(EINVAL); - } - } else { - switch (m_ptr->DIO_TYPE) { - case DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break; - case DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break; - case DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break; - default: return(EINVAL); - } - } - return(OK); -} - - -/* The system call implemented in this file: - * m_type: SYS_SDEVIO - * - * The parameters for this system call are: - * m2_i3: DIO_REQUEST (request input or output) - * m2_i1: DIO_TYPE (flag indicating byte, word, or long) - * m2_l1: DIO_PORT (port to read/ write) - * m2_p1: DIO_VEC_ADDR (virtual address of buffer) - * m2_l2: DIO_VEC_SIZE (number of elements) - * m2_i2: DIO_VEC_PROC (process where buffer is) - */ - -/*===========================================================================* - * do_sdevio * - *===========================================================================*/ -PUBLIC int do_sdevio(m_ptr) -register message *m_ptr; /* pointer to request message */ -{ - int proc_nr = m_ptr->DIO_VEC_PROC; - int count = m_ptr->DIO_VEC_SIZE; - long port = m_ptr->DIO_PORT; - phys_bytes phys_buf; - - /* Check if process number is OK. */ - if (proc_nr == SELF) proc_nr = m_ptr->m_source; - if (! isokprocn(proc_nr)) - return(EINVAL); - - /* Get and check physical address. */ - if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0) - return(EFAULT); - - /* Perform device I/O for bytes and words. Longs are not supported. */ - if (m_ptr->DIO_REQUEST == DIO_INPUT) { - switch (m_ptr->DIO_TYPE) { - case DIO_BYTE: phys_insb(port, phys_buf, count); break; - case DIO_WORD: phys_insw(port, phys_buf, count); break; - default: return(EINVAL); - } - } else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) { - switch (m_ptr->DIO_TYPE) { - case DIO_BYTE: phys_outsb(port, phys_buf, count); break; - case DIO_WORD: phys_outsw(port, phys_buf, count); break; - default: return(EINVAL); - } - } - else { - return(EINVAL); - } - return(OK); -} - - /* The system call implemented in this file: * m_type: SYS_VDEVIO * @@ -105,6 +8,12 @@ register message *m_ptr; /* pointer to request message */ * m2_i2: DIO_VEC_SIZE (number of ports to read or write) */ +#include "../system.h" +#include + +#if USE_VDEVIO + + /* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */ PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE]; @@ -213,4 +122,5 @@ register message *m_ptr; /* pointer to request message */ return(OK); } +#endif /* USE_VDEVIO */ diff --git a/kernel/system/priority.c b/kernel/system/priority.c deleted file mode 100644 index 33db5d5eb..000000000 --- a/kernel/system/priority.c +++ /dev/null @@ -1,56 +0,0 @@ -/* The system call implemented in this file: - * m_type: SYS_SETPRIORITY - * - * The parameters for this system call are: - * m1_i1: which - * m1_i2: who - * m1_i3: prio - */ - -#include "../kernel.h" -#include "../system.h" -#include -#include - -/*===========================================================================* - * do_setpriority * - *===========================================================================*/ -PUBLIC int do_setpriority(message *m_ptr) -{ - int which_proc, pri, q, niceperq; - struct proc *which_procp; - - which_proc = m_ptr->m1_i1; - pri = m_ptr->m1_i2; - - /* pri is currently between PRIO_MIN and PRIO_MAX. We have to - * scale this between MIN_USER_Q and MAX_USER_Q. - */ - - if(pri < PRIO_MIN || pri > PRIO_MAX) - return EINVAL; - - if(which_proc < 0 || which_proc >= NR_TASKS+NR_PROCS) - return EINVAL; - - which_procp = proc_addr(which_proc); - - q = MAX_USER_Q + (pri - PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) / (PRIO_MAX-PRIO_MIN+1); - - /* The below shouldn't happen. */ - if(q < MAX_USER_Q) q = MAX_USER_Q; - if(q > MIN_USER_Q) q = MIN_USER_Q; - - /* max_priority is the base priority. */ - which_procp->p_max_priority = q; - lock_unready(which_procp); - which_procp->p_priority = q; - - /* Runnable? Put it (back) on its new run queue. */ - if(!which_procp->p_rts_flags) - lock_ready(which_procp); - - return OK; -} - - diff --git a/kernel/system/proctl.c b/kernel/system/proctl.c deleted file mode 100644 index a10f35c3e..000000000 --- a/kernel/system/proctl.c +++ /dev/null @@ -1,209 +0,0 @@ -/* The system call implemented in this file: - * m_type: SYS_FORK - * - * The parameters for this system call are: - * m1_i1: PR_PROC_NR (child's process table slot) - * m1_i2: PR_PPROC_NR (parent, process that forked) - * m1_i3: PR_PID (child pid received from PM) - */ - -#include "../kernel.h" -#include "../system.h" -#include "../sendmask.h" -#include -#if (CHIP == INTEL) -#include "../protect.h" -#endif -#include "../debug.h" - - -/*===========================================================================* - * do_fork * - *===========================================================================*/ -PUBLIC int do_fork(m_ptr) -register message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_fork(). PR_PPROC_NR has forked. The child is PR_PROC_NR. */ - -#if (CHIP == INTEL) - reg_t old_ldt_sel; -#endif - register struct proc *rpc; - struct proc *rpp; - - rpp = proc_addr(m_ptr->PR_PPROC_NR); - rpc = proc_addr(m_ptr->PR_PROC_NR); - if (! isemptyp(rpc)) return(EINVAL); - - /* Copy parent 'proc' struct to child. */ -#if (CHIP == INTEL) - old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */ -#endif - - *rpc = *rpp; /* copy 'proc' struct */ - -#if (CHIP == INTEL) - rpc->p_ldt_sel = old_ldt_sel; -#endif - rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */ - rpc->p_ntf_q = NULL; /* remove pending notifications */ - - /* Only one in group should have SIGNALED, child doesn't inherit tracing. */ - rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */ - rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP); - sigemptyset(&rpc->p_pending); - - rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */ - rpc->p_user_time = 0; /* set all the accounting times to 0 */ - rpc->p_sys_time = 0; - - return(OK); -} - - -/* The system call implemented in this file: - * m_type: SYS_NEWMAP - * - * The parameters for this system call are: - * m1_i1: PR_PROC_NR (install new map for this process) - * m1_p1: PR_MEM_PTR (pointer to memory map) - */ - - -/*===========================================================================* - * do_newmap * - *===========================================================================*/ -PUBLIC int do_newmap(m_ptr) -message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_newmap(). Fetch the memory map from PM. */ - - register struct proc *rp; - phys_bytes src_phys; - int caller; /* whose space has the new map (usually PM) */ - int k; /* process whose map is to be loaded */ - int old_flags; /* value of flags before modification */ - struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ - - /* Extract message parameters and copy new memory map from PM. */ - caller = m_ptr->m_source; - k = m_ptr->PR_PROC_NR; - map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR; - if (!isokprocn(k)) return(EINVAL); - rp = proc_addr(k); /* ptr to entry of user getting new map */ - - /* Copy the map from PM. */ - src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr, - sizeof(rp->p_memmap)); - if (src_phys == 0) return(EFAULT); - phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap)); - -#if (CHIP != M68000) - alloc_segments(rp); -#else - pmmu_init_proc(rp); -#endif - old_flags = rp->p_rts_flags; /* save the previous value of the flags */ - rp->p_rts_flags &= ~NO_MAP; - if (old_flags != 0 && rp->p_rts_flags == 0) lock_ready(rp); - - return(OK); -} - - -/* The system call implemented in this file: - * m_type: SYS_EXEC - * - * The parameters for this system call are: - * m1_i1: PR_PROC_NR (process that did exec call) - * m1_i3: PR_TRACING (flag to indicate tracing is on/ off) - * m1_p1: PR_STACK_PTR (new stack pointer) - * m1_p2: PR_NAME_PTR (pointer to program name) - * m1_p3: PR_IP_PTR (new instruction pointer) - */ - -/*===========================================================================* - * do_exec * - *===========================================================================*/ -PUBLIC int do_exec(m_ptr) -register message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */ - - register struct proc *rp; - reg_t sp; /* new sp */ - phys_bytes phys_name; - char *np; - - rp = proc_addr(m_ptr->PR_PROC_NR); - if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP); - sp = (reg_t) m_ptr->PR_STACK_PTR; - rp->p_reg.sp = sp; /* set the stack pointer */ -#if (CHIP == M68000) - rp->p_splow = sp; /* set the stack pointer low water */ -#ifdef FPP - /* Initialize fpp for this process */ - fpp_new_state(rp); -#endif -#endif -#if (CHIP == INTEL) /* wipe extra LDT entries */ - kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0, - (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0])); -#endif - rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */ - rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */ - if (rp->p_rts_flags == 0) lock_ready(rp); - - /* Save command name for debugging, ps(1) output, etc. */ - phys_name = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->PR_NAME_PTR, - (vir_bytes) P_NAME_LEN - 1); - if (phys_name != 0) { - phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1); - for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {} - *np = 0; /* mark end */ - } else { - kstrncpy(rp->p_name, "", P_NAME_LEN); - } - return(OK); -} - - -/* The system call implemented in this file: - * m_type: SYS_XIT - * - * The parameters for this system call are: - * m1_i1: PR_PROC_NR (slot number of exiting process) - */ - - - -/*===========================================================================* - * do_xit * - *===========================================================================*/ -PUBLIC int do_xit(m_ptr) -message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_exit. A user process has exited or a system process requests - * to exit. Only the PM can request other process slots to be cleared. - * The routine to clean up a process table slot cancels outstanding timers, - * possibly removes the process from the message queues, and resets certain - * process table fields to the default values. - */ - int exit_proc_nr; - - /* Determine what process exited. */ - if (PM_PROC_NR == m_ptr->m_source) { - exit_proc_nr = m_ptr->PR_PROC_NR; /* get exiting process */ - if (exit_proc_nr != SELF) { /* PM tries to exit self */ - if (! isokprocn(exit_proc_nr)) return(EINVAL); - clear_proc(exit_proc_nr); /* exit a user process */ - return(OK); /* report back to PM */ - } - } - - /* The PM or some other system process requested to be exited. */ - clear_proc(m_ptr->m_source); - return(EDONTREPLY); -} - - diff --git a/kernel/system/sigctl.c b/kernel/system/sigctl.c deleted file mode 100644 index fc5c5cde6..000000000 --- a/kernel/system/sigctl.c +++ /dev/null @@ -1,192 +0,0 @@ -/* The system call that is implemented in this file: - * SYS_SIGCTL # signal handling functionality - * - * The parameters and types for this system call are: - * SIG_REQUEST # request to perform (long) - * SIG_PROC # process to signal/ pending (int) - * SIG_CTXT_PTR # pointer to sigcontext structure (pointer) - * SIG_FLAGS # flags for S_SIGRETURN call (int) - * SIG_MAP # bit map with pending signals (long) - * SIG_NUMBER # signal number to send to process (int) - * - * Supported request types are in the parameter SIG_REQUEST: - * S_GETSIG # get a pending kernel signal - * S_ENDSIG # signal has been processed - * S_SENDSIG # deliver a POSIX-style signal - * S_SIGRETURN # return from a POSIX-style signal - * S_KILL # send a signal to a process - */ - -#include "../kernel.h" -#include "../system.h" -#include -#include - -/* PM is ready to accept signals and repeatedly does a system call to get - * one. Find a process with pending signals. If no signals are available, - * return NONE in the process number field. - */ -PUBLIC int do_getsig(m_ptr) -message *m_ptr; /* pointer to request message */ -{ - register struct proc *rp; - - /* Find the next process with pending signals. */ - for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) { - if (rp->p_rts_flags & SIGNALED) { - m_ptr->SIG_PROC = rp->p_nr; - m_ptr->SIG_MAP = rp->p_pending; - sigemptyset(&rp->p_pending); /* ball is in PM's court */ - rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */ - return(OK); - } - } - - /* No process with pending signals was found. */ - m_ptr->SIG_PROC = NONE; - return(OK); -} - -PUBLIC int do_endsig(m_ptr) -message *m_ptr; /* pointer to request message */ -{ -/* Finish up after a kernel type signal, caused by a SYS_KILL message or a - * call to cause_sig by a task. This is called by the PM after processing a - * signal it got with SYS_GETSIG. - */ - register struct proc *rp; - - rp = proc_addr(m_ptr->SIG_PROC); - if (isemptyp(rp)) return(EINVAL); /* process already dead? */ - - /* PM has finished one kernel signal. Perhaps process is ready now? */ - if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */ - if ((rp->p_rts_flags &= ~SIG_PENDING)==0) /* remove pending flag */ - lock_ready(rp); /* ready if no flags */ - return(OK); -} - -PUBLIC int do_sigsend(m_ptr) -message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_sigsend, POSIX-style signal handling. */ - - struct sigmsg smsg; - register struct proc *rp; - phys_bytes src_phys, dst_phys; - struct sigcontext sc, *scp; - struct sigframe fr, *frp; - - rp = proc_addr(m_ptr->SIG_PROC); - - /* Get the sigmsg structure into our address space. */ - src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes) - m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg)); - if (src_phys == 0) return(EFAULT); - phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg)); - - /* Compute the user stack pointer where sigcontext will be stored. */ - scp = (struct sigcontext *) smsg.sm_stkptr - 1; - - /* Copy the registers to the sigcontext structure. */ - kmemcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs)); - - /* Finish the sigcontext initialization. */ - sc.sc_flags = SC_SIGCONTEXT; - sc.sc_mask = smsg.sm_mask; - - /* Copy the sigcontext structure to the user's stack. */ - dst_phys = umap_local(rp, D, (vir_bytes) scp, - (vir_bytes) sizeof(struct sigcontext)); - if (dst_phys == 0) return(EFAULT); - phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext)); - - /* Initialize the sigframe structure. */ - frp = (struct sigframe *) scp - 1; - fr.sf_scpcopy = scp; - fr.sf_retadr2= (void (*)()) rp->p_reg.pc; - fr.sf_fp = rp->p_reg.fp; - rp->p_reg.fp = (reg_t) &frp->sf_fp; - fr.sf_scp = scp; - fr.sf_code = 0; /* XXX - should be used for type of FP exception */ - fr.sf_signo = smsg.sm_signo; - fr.sf_retadr = (void (*)()) smsg.sm_sigreturn; - - /* Copy the sigframe structure to the user's stack. */ - dst_phys = umap_local(rp, D, (vir_bytes) frp, - (vir_bytes) sizeof(struct sigframe)); - if (dst_phys == 0) return(EFAULT); - phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe)); - - /* Reset user registers to execute the signal handler. */ - rp->p_reg.sp = (reg_t) frp; - rp->p_reg.pc = (reg_t) smsg.sm_sighandler; - - return(OK); -} - -PUBLIC int do_sigreturn(m_ptr) -message *m_ptr; /* pointer to request message */ -{ -/* POSIX style signals require sys_sigreturn to put things in order before - * the signalled process can resume execution - */ - struct sigcontext sc; - register struct proc *rp; - phys_bytes src_phys; - - rp = proc_addr(m_ptr->SIG_PROC); - - /* Copy in the sigcontext structure. */ - src_phys = umap_local(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR, - (vir_bytes) sizeof(struct sigcontext)); - if (src_phys == 0) return(EFAULT); - phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext)); - - /* Make sure that this is not just a jmp_buf. */ - if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL); - - /* Fix up only certain key registers if the compiler doesn't use - * register variables within functions containing setjmp. - */ - if (sc.sc_flags & SC_NOREGLOCALS) { - rp->p_reg.retreg = sc.sc_retreg; - rp->p_reg.fp = sc.sc_fp; - rp->p_reg.pc = sc.sc_pc; - rp->p_reg.sp = sc.sc_sp; - return(OK); - } - sc.sc_psw = rp->p_reg.psw; - -#if (CHIP == INTEL) - /* Don't panic kernel if user gave bad selectors. */ - sc.sc_cs = rp->p_reg.cs; - sc.sc_ds = rp->p_reg.ds; - sc.sc_es = rp->p_reg.es; -#if _WORD_SIZE == 4 - sc.sc_fs = rp->p_reg.fs; - sc.sc_gs = rp->p_reg.gs; -#endif -#endif - - /* Restore the registers. */ - kmemcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs)); - return(OK); -} - -/*===========================================================================* - * do_sigctl * - *===========================================================================*/ - -PUBLIC int do_kill(m_ptr) -message *m_ptr; /* pointer to request message */ -{ -/* Handle sys_kill(). Cause a signal to be sent to a process via PM. - * Note that this has nothing to do with the kill (2) system call, this - * is how the FS (and possibly other servers) get access to cause_sig. - */ - cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER); - return(OK); -} - - diff --git a/kernel/system/sysctl.c b/kernel/system/sysctl.c deleted file mode 100644 index 4dd97c283..000000000 --- a/kernel/system/sysctl.c +++ /dev/null @@ -1,178 +0,0 @@ -#include "../kernel.h" -#include "../ipc.h" -#include "../system.h" -#include "../protect.h" -#include -#include "../sendmask.h" - - - -/* The system call implemented in this file: - * m_type: SYS_SVRCTL - * - * The parameters for this system call are: - * m2_i1: CTL_PROC_NR (process number of caller) - * m2_i2: CTL_REQUEST (request type) - * m2_i3: CTL_MM_PRIV (privilege) - * m2_l1: CTL_SEND_MASK (new send mask to be installed) - * m2_l2: CTL_PROC_TYPE (new process type) - * m2_p1: CTL_ARG_PTR (argument pointer) - */ - -/* NOTE: this call will radically change! */ - -/*===========================================================================* - * do_svrctl * - *===========================================================================*/ -PUBLIC int do_svrctl(m_ptr) -message *m_ptr; /* pointer to request message */ -{ - register struct proc *rp; - int proc_nr, priv; - int request; - vir_bytes argp; - - /* Extract message parameters. */ - proc_nr = m_ptr->CTL_PROC_NR; - if (proc_nr == SELF) proc_nr = m_ptr->m_source; - if (! isokprocn(proc_nr)) return(EINVAL); - - request = m_ptr->CTL_REQUEST; - priv = m_ptr->CTL_MM_PRIV; - argp = (vir_bytes) m_ptr->CTL_ARG_PTR; - rp = proc_addr(proc_nr); - - /* Check if the PM privileges are super user. */ - if (!priv || !isuserp(rp)) - return(EPERM); - - /* See what is requested and handle the request. */ - switch (request) { - case SYSSIGNON: { - /* Make this process a server. The system processes should be able - * to communicate with this new server, so update their send masks - * as well. - */ - /* fall through */ - } - case SYSSENDMASK: { - rp->p_call_mask = SYSTEM_CALL_MASK; - rp->p_sendmask = ALLOW_ALL_MASK; - send_mask_allow(proc_addr(USR8139)->p_sendmask, proc_nr); - send_mask_allow(proc_addr(PM_PROC_NR)->p_sendmask, proc_nr); - send_mask_allow(proc_addr(FS_PROC_NR)->p_sendmask, proc_nr); - send_mask_allow(proc_addr(IS_PROC_NR)->p_sendmask, proc_nr); - send_mask_allow(proc_addr(CLOCK)->p_sendmask, proc_nr); - send_mask_allow(proc_addr(SYSTASK)->p_sendmask, proc_nr); - send_mask_allow(proc_addr(FXP)->p_sendmask, proc_nr); - return(OK); - } - default: - return(EINVAL); - } -} - -/* The system call implemented in this file: - * m_type: SYS_SEGCTL - * - * The parameters for this system call are: - * m4_l3: SEG_PHYS (physical base address) - * m4_l4: SEG_SIZE (size of segment) - * m4_l1: SEG_SELECT (return segment selector here) - * m4_l2: SEG_OFFSET (return offset within segment here) - * m4_l5: SEG_INDEX (return index into remote memory map here) - * - * Author: - * Jorrit N. Herder - */ - -/*===========================================================================* - * do_segctl * - *===========================================================================*/ -PUBLIC int do_segctl(m_ptr) -register message *m_ptr; /* pointer to request message */ -{ -/* Return a segment selector and offset that can be used to reach a physical - * address, for use by a driver doing memory I/O in the A0000 - DFFFF range. - */ - u16_t selector; - vir_bytes offset; - int i, index; - register struct proc *rp; - phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS; - vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE; - int result; - - /* First check if there is a slot available for this segment. */ - rp = proc_addr(m_ptr->m_source); - index = -1; - for (i=0; i < NR_REMOTE_SEGS; i++) { - if (! rp->p_farmem[i].in_use) { - index = i; - rp->p_farmem[i].in_use = TRUE; - rp->p_farmem[i].mem_phys = phys; - rp->p_farmem[i].mem_len = size; - break; - } - } - if (index < 0) return(ENOSPC); - - - if (! machine.protected) { - selector = phys / HCLICK_SIZE; - offset = phys % HCLICK_SIZE; - result = OK; - } else { - /* Check if the segment size can be recorded in bytes, that is, check - * if descriptor's limit field can delimited the allowed memory region - * precisely. This works up to 1MB. If the size is larger, 4K pages - * instead of bytes are used. - */ - if (size < BYTE_GRAN_MAX) { - init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size, - USER_PRIVILEGE); - selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE; - offset = 0; - result = OK; - } else { - init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0, - USER_PRIVILEGE); - selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE; - offset = phys & 0xFFFF; - result = OK; - } - } - - /* Request successfully done. Now return the result. */ - m_ptr->SEG_INDEX = index | REMOTE_SEG; - m_ptr->SEG_SELECT = selector; - m_ptr->SEG_OFFSET = offset; - return(result); -} - - -/* The system call implemented in this file: - * m_type: SYS_IOPENABLE - * - * The parameters for this system call are: - * m2_i2: PROC_NR (process to give I/O Protection Level bits) - * - * Author: - * Jorrit N. Herder - */ - -/*===========================================================================* - * 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 -} - - diff --git a/kernel/table.c b/kernel/table.c index ca2401052..cbd5ed6b4 100755 --- a/kernel/table.c +++ b/kernel/table.c @@ -32,7 +32,6 @@ #include "kernel.h" #include "proc.h" #include "ipc.h" -#include "sendmask.h" #include #include @@ -61,43 +60,46 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)]; * routine and stack size is also provided. */ #define IDLE_F (PREEMPTIBLE | BILLABLE) -#define USER_F (PREEMPTIBLE | SCHED_Q_HEAD) -#define SYS_F (PREEMPTIBLE) +#define USER_F (PREEMPTIBLE | RDY_Q_HEAD) +#define SYS_F (PREEMPTIBLE | SYS_PROC) +#define TCB_F (SYS_PROC) /* trusted computing base */ #define IDLE_T 32 /* ticks */ #define USER_T 8 /* ticks */ #define SYS_T 16 /* ticks */ PUBLIC struct system_image image[] = { - { IDLE, idle_task, IDLE_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_CALL_MASK, DENY_ALL_MASK, "IDLE" }, - { CLOCK, clock_task, 0, SYS_T, TASK_Q, CLOCK_S, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "CLOCK" }, - { SYSTASK, sys_task, 0, SYS_T, TASK_Q, SYSTEM_S, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "SYS" }, - { HARDWARE, 0, 0, SYS_T, TASK_Q, HARDWARE_S, EMPTY_CALL_MASK, ALLOW_ALL_MASK,"HARDW." }, - { PM_PROC_NR, 0, 0, SYS_T, 3, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "PM" }, - { FS_PROC_NR, 0, 0, SYS_T, 3, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "FS" }, - { IS_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "IS" }, - { TTY, 0, SYS_F, SYS_T, 1, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "TTY" }, - { MEMORY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "MEMORY" }, + { IDLE, idle_task, IDLE_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_CALL_MASK, 0, "IDLE" }, + { CLOCK, clock_task, TCB_F, SYS_T, TASK_Q, CLOCK_S, SYSTEM_CALL_MASK, 0, "CLOCK" }, + { SYSTEM, sys_task, TCB_F, SYS_T, TASK_Q, SYSTEM_S, SYSTEM_CALL_MASK, 0, "SYS" }, + { HARDWARE, 0, 0, SYS_T, TASK_Q, HARDWARE_S, EMPTY_CALL_MASK, 0,"KERNEL" }, + { PM_PROC_NR, 0, TCB_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "PM" }, + { FS_PROC_NR, 0, TCB_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "FS" }, + { IS_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "IS" }, + { TTY, 0, SYS_F, SYS_T, 1, 0, SYSTEM_CALL_MASK, 0, "TTY" }, + { MEMORY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "MEMORY" }, #if ENABLE_AT_WINI - { AT_WINI, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "AT_WINI" }, + { AT_WINI, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "AT_WINI" }, #endif #if ENABLE_FLOPPY - { FLOPPY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "FLOPPY" }, + { FLOPPY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "FLOPPY" }, #endif #if ENABLE_PRINTER - { PRINTER, 0, SYS_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "PRINTER" }, + { PRINTER, 0, SYS_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "PRINTER" }, #endif #if ENABLE_RTL8139 - { USR8139, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "RTL8139" }, + { USR8139, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "RTL8139" }, #endif #if ENABLE_FXP - { FXP, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "FXP" }, + { FXP, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "FXP" }, #endif #if ENABLE_DPETH - { DPETH, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "DPETH" }, + { DPETH, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "DPETH" }, #endif - { LOG_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "LOG" }, - { INIT_PROC_NR, 0, USER_F, USER_T, USER_Q, 0, USER_CALL_MASK, USER_PROC_SENDMASK, "INIT" }, +#if ENABLE_LOG + { LOG_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "LOG" }, +#endif + { INIT_PROC_NR, 0, USER_F, USER_T, USER_Q, 0, USER_CALL_MASK, 0, "INIT" }, }; /* Verify the size of the system image table at compile time. If the number @@ -105,5 +107,5 @@ PUBLIC struct system_image image[] = { * a compile time error. Note that no space is allocated because 'dummy' is * declared extern. */ -extern int dummy[(IMAGE_SIZE==sizeof(image)/sizeof(struct system_image))?1:-1]; +extern int dummy[(NR_BOOT_PROCS==sizeof(image)/sizeof(struct system_image))?1:-1]; diff --git a/kernel/type.h b/kernel/type.h index d2460c422..ffeb3cf95 100755 --- a/kernel/type.h +++ b/kernel/type.h @@ -8,13 +8,12 @@ typedef _PROTOTYPE( void task_t, (void) ); */ typedef long karg_t; /* use largest type here */ -/* Process related types. - * A process number defines the index into the process table. With a signed - * short we can support up to 256 user processes and more kernel tasks than - * one can ever create. - */ -typedef short proc_nr_t; /* process table entry number */ -typedef unsigned long send_mask_t; /* bit mask for sender */ +/* Process table and system property related types. */ +typedef int proc_nr_t; /* process table entry number */ +typedef short sys_id_t; /* system process index */ +typedef struct { /* bitmap for system indexes */ + bitchunk_t chunk[BITMAP_CHUNKS(NR_SYS_PROCS)]; +} sys_map_t; struct system_image { proc_nr_t proc_nr; /* process number to use */ @@ -24,7 +23,7 @@ struct system_image { int priority; /* scheduling priority */ int stksize; /* stack size for tasks */ char call_mask; /* allowed system calls */ - send_mask_t sendmask; /* send mask protection */ + long send_mask; /* send mask protection */ char proc_name[P_NAME_LEN]; /* name in process table */ };