Various updates.

* Removed some variants of the SYS_GETINFO calls from the kernel;
  replaced them with new PM and utils libary functionality. Fixed
  bugs in utils library that used old get_kenv() variant.
* Implemented a buffer in the kernel to gather random data.
  Memory driver periodically checks this for /dev/random.
  A better random algorithm can now be implemented in the driver.
  Removed SYS_RANDOM; the SYS_GETINFO call is used instead.
* Remove SYS_KMALLOC from the kernel. Memory allocation can now
  be done at the process manager with new 'other' library functions.
This commit is contained in:
Jorrit Herder
2005-06-03 13:55:06 +00:00
parent 4904a5537a
commit f2a85e58d9
43 changed files with 245 additions and 222 deletions

View File

@@ -29,8 +29,8 @@
/* How many bytes should the circular buffer for kernel diagnostics. */
#define KMESS_BUF_SIZE 256
/* How many bytes for (port,value)-pairs vector to copy in. */
#define VDEVIO_BUF_SIZE 128
/* 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
@@ -41,6 +41,9 @@
/* 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 and macros for bit map manipulation. */
#define BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT)
#define BITMAP_CHUNKS(nr_bits) (((nr_bits)+BITCHUNK_BITS-1)/BITCHUNK_BITS)

View File

@@ -1,9 +1,6 @@
/* 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.
*
* Changes:
* Sep 28, 2004: skip_stop_sequence on exceptions in system processes
*/
#include "kernel.h"
@@ -78,7 +75,7 @@ unsigned vec_nr;
* notification ...
*/
if (istaskp(saved_proc)) { /* serious problem */
skip_stop_sequence = TRUE; /* directly shutdown */
kernel_exception = TRUE; /* directly shutdown */
panic("exception in a kernel task", NO_NUM);
} else {
clear_proc(saved_proc->p_nr);

View File

@@ -1,32 +1,30 @@
/* 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.
* defined as extern unless the _TABLE definition is seen. We rely on the
* compiler's default initialization (0) for several global variables.
*/
#ifdef _TABLE
#undef EXTERN
#define EXTERN
#endif
#include "const.h"
#include <minix/config.h>
/* MINIX' shutdown sequence uses watchdog timers to stop system services. The
* flag shutting_down must be initialized to FALSE. We rely on the compiler's
* default initialization (0) of global variables here.
*/
EXTERN char skip_stop_sequence; /* set to TRUE in case of an exception() */
EXTERN char shutting_down; /* TRUE if the system is shutting down */
/* Variables relating to shutting down MINIX. */
EXTERN char kernel_exception; /* TRUE after system exceptions */
EXTERN char shutting_down; /* TRUE if shutting down */
EXTERN struct proc *shutdown_process; /* process awaiting shutdown of */
EXTERN timer_t shutdown_timer; /* watchdog function called after timeout */
EXTERN timer_t shutdown_timer; /* timer for watchdog function */
/* Kernel information structures. This groups vital kernel information. */
EXTERN phys_bytes aout; /* address of a.out headers */
EXTERN struct kinfo kinfo; /* kernel information for users */
EXTERN struct machine machine; /* machine information for users */
EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
EXTERN phys_bytes aout; /* address of a.out headers */
EXTERN struct kinfo kinfo; /* kernel information for users */
EXTERN struct machine machine; /* machine information for users */
EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
EXTERN struct randomness krandom; /* gather kernel random information */
EXTERN struct memory mem[NR_MEMS]; /* base and size of chunks of memory */
/* Process scheduling info and kernel entry count. */
/* Process scheduling information and the kernel reentry count. */
EXTERN struct proc *proc_ptr; /* pointer to currently running process */
EXTERN struct proc *next_ptr; /* pointer to next process to run */
EXTERN char k_reenter; /* kernel reentry count (entry count less 1) */
@@ -43,21 +41,21 @@ EXTERN bitchunk_t notify_bitmap[BITMAP_CHUNKS(NR_NOTIFY_BUFS)];
EXTERN irq_hook_t irq_hooks[NR_IRQ_HOOKS]; /* hooks for general use */
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; /* bit map of all in-use irq's */
EXTERN int irq_use; /* map of all in-use irq's */
/* lock() timing data. */
/* 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; /* monitor stack */
EXTERN int mon_return; /* true if return to the monitor possible */
EXTERN reg_t mon_ss, mon_sp; /* boot monitor stack */
EXTERN int mon_return; /* true if we can return to monitor */
/* Variables that are initialized elsewhere are just extern here. */
extern struct system_image image[]; /* system image processes (table.c) */
extern char *t_stack[]; /* stack space for kernel tasks (table.c) */
extern struct segdesc_s gdt[]; /* protected mode global descriptor (protect.c) */
extern struct system_image image[]; /* system image processes */
extern char *t_stack[]; /* task stack space */
extern struct segdesc_s gdt[]; /* global descriptor table */
EXTERN _PROTOTYPE( void (*level0_func), (void) );
#endif /* (CHIP == INTEL) */

View File

@@ -248,7 +248,7 @@ int how; /* 0 = halt, 1 = reboot, 2 = panic!, ... */
*/
shutting_down = TRUE; /* flag for sys_exit() */
tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */
if (skip_stop_sequence) { /* set in exception() */
if (kernel_exception) { /* set in exception() */
kprintf("\nAn exception occured; skipping stop sequence.\n", NO_ARG);
shutdown(&shutdown_timer); /* TTY isn't scheduled */
} else {

View File

@@ -442,7 +442,6 @@ message *m_ptr; /* pointer to message buffer */
struct proc *caller_ptr;
lock(0, "notify");
kinfo.lock_notify ++;
caller_ptr = (k_reenter >= 0) ? proc_addr(HARDWARE) : proc_ptr;
result = mini_notify(caller_ptr, dst, m_ptr);
unlock(0);
@@ -654,7 +653,6 @@ message *m_ptr; /* pointer to message buffer */
/* Safe gateway to mini_send() for tasks. */
int result;
lock(2, "send");
kinfo.lock_send ++;
result = mini_send(proc_ptr, dst, m_ptr, NON_BLOCKING);
unlock(2);
return(result);

View File

@@ -62,6 +62,7 @@ _PROTOTYPE( void clear_proc, (int proc_nr) );
_PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr,
vir_bytes bytes) );
_PROTOTYPE( void sys_task, (void) );
_PROTOTYPE( void get_randomness, (void) );
_PROTOTYPE( int virtual_copy, (struct vir_addr *src, struct vir_addr *dst,
vir_bytes bytes) );
_PROTOTYPE( phys_bytes umap_local, (struct proc *rp, int seg,

View File

@@ -18,6 +18,7 @@
* umap_bios: map virtual address in BIOS_SEG to physical
* numap_local: umap_local D segment from proc nr instead of pointer
* virtual_copy: copy bytes from one virtual address to another
* get_randomness: accumulate randomness in a buffer
* generic_handler: interrupt handler for user-level device drivers
*
* Changes:
@@ -152,7 +153,6 @@ PRIVATE void initialize(void)
map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */
/* Server and driver control. */
map(SYS_KMALLOC, do_kmalloc); /* request chunk of free memory */
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 */
@@ -169,7 +169,6 @@ PRIVATE void initialize(void)
/* Miscellaneous. */
map(SYS_ABORT, do_abort); /* abort MINIX */
map(SYS_GETINFO, do_getinfo); /* request system information */
map(SYS_RANDOM, do_random); /* request kernel random data */
}
/*===========================================================================*
@@ -262,6 +261,20 @@ int proc_nr; /* slot of process to clean up */
}
/*===========================================================================*
* get_randomness *
*===========================================================================*/
PUBLIC void get_randomness()
{
/* Gather random information with help of the CPU's cycle counter. Only use
* the lowest bytes because the highest bytes won't differ that much.
*/
unsigned long tsc_high;
read_tsc(&tsc_high, &krandom.r_buf[krandom.r_next]);
if (krandom.r_size < RANDOM_ELEMENTS) krandom.r_size ++;
krandom.r_next = (krandom.r_next + 1 ) % RANDOM_ELEMENTS;
}
/*===========================================================================*
* generic_handler *
@@ -272,8 +285,15 @@ 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. */
get_randomness();
/* Build notification message and return. */
m.NOTIFY_TYPE = HARD_INT;
m.NOTIFY_ARG = hook->irq;
lock_notify(hook->proc_nr, &m);

View File

@@ -31,11 +31,9 @@ _PROTOTYPE( int do_umap, (message *m_ptr) );
_PROTOTYPE( int do_unused, (message *m_ptr) ); /* miscellaneous */
_PROTOTYPE( int do_abort, (message *m_ptr) );
_PROTOTYPE( int do_getinfo, (message *m_ptr) );
_PROTOTYPE( int do_random, (message *m_ptr) );
_PROTOTYPE( int do_exit, (message *m_ptr) ); /* system control */
_PROTOTYPE( int do_svrctl, (message *m_ptr) );
_PROTOTYPE( int do_kmalloc, (message *m_ptr) );
_PROTOTYPE( int do_iopenable, (message *m_ptr) );
_PROTOTYPE( int do_segctl, (message *m_ptr) );

View File

@@ -16,15 +16,6 @@ message *m; /* pointer to request message */
}
/*===========================================================================*
* do_random *
*===========================================================================*/
PUBLIC int do_random(m)
message *m; /* pointer to request message */
{
return(ENOSYS); /* no yet implemented */
}
/* The system call implemented in this file:
* m_type: SYS_ABORT
@@ -131,6 +122,7 @@ register message *m_ptr; /* pointer to request message */
length);
if (src_phys == 0 || dst_phys == 0) return(EFAULT);
phys_copy(src_phys, dst_phys, length);
/* fall through */
}
case GET_PROCTAB: {
length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
@@ -139,49 +131,22 @@ register message *m_ptr; /* pointer to request message */
}
case GET_PROC: {
nr = (m_ptr->I_KEY_LEN == SELF) ? m_ptr->m_source : m_ptr->I_KEY_LEN;
if (! isokprocn(nr)) return(EINVAL);
if (! isokprocn(nr)) return(EINVAL); /* validate request */
length = sizeof(struct proc);
src_phys = vir2phys(proc_addr(nr));
break;
}
case GET_MONPARAMS: {
src_phys = kinfo.params_base; /* already is a physical address! */
src_phys = kinfo.params_base; /* already is a physical */
length = kinfo.params_size;
break;
}
case GET_PROCNR: {
if (m_ptr->I_KEY_LEN == 0) { /* get own process nr */
/* GET_PROCNR functionality will be moved to the Process Manager! */
kprintf("GET_PROCNR (own) from %d\n", m_ptr->m_source);
src_phys = vir2phys(&proc_nr);
length = sizeof(int);
} else { /* lookup nr by name */
int proc_found = FALSE;
struct proc *pp;
struct vir_addr vsrc, vdst;
char key[8]; /* storage for process name to lookup */
/* GET_PROCNR functionality will be moved to the Process Manager! */
kprintf("GET_PROCNR (by name) from %d\n", m_ptr->m_source);
proc_nr = m_ptr->m_source; /* only caller can request copy */
if (m_ptr->I_KEY_LEN > sizeof(key)) return(EINVAL);
vsrc.proc_nr = proc_nr; vsrc.segment = D; vsrc.offset = (vir_bytes) m_ptr->I_KEY_PTR;
vdst.proc_nr = SYSTASK, vdst.segment = D; vdst.offset = (vir_bytes) key;
if (virtual_copy(&vsrc, &vdst, m_ptr->I_KEY_LEN) != OK) return(EFAULT);
#if DEAD_CODE
if (vir_copy(proc_nr, (vir_bytes) m_ptr->I_KEY_PTR, SYSTASK,
(vir_bytes) key, m_ptr->I_KEY_LEN) != OK) return(EFAULT);
#endif
for (pp=BEG_PROC_ADDR; pp<END_PROC_ADDR; pp++) {
if (kstrncmp(pp->p_name, key, m_ptr->I_KEY_LEN) == 0) {
src_phys = vir2phys(&(pp->p_nr));
length = sizeof(int);
proc_found = TRUE;
break;
}
}
if (! proc_found) return(ESRCH);
}
break;
case GET_RANDOMNESS: {
struct randomness copy = krandom; /* copy to keep counters */
krandom.r_next = krandom.r_size = 0; /* invalidate random data */
length = sizeof(struct randomness);
src_phys = vir2phys(&copy);
break;
}
case GET_KMESSAGES: {
length = sizeof(struct kmessages);

View File

@@ -219,38 +219,3 @@ register message *m_ptr; /* pointer to request message */
}
/* The system call implemented in this file:
* m_type: SYS_KMALLOC
*
* The parameters for this system call are:
* m4_l2: MEM_CHUNK_SIZE (request a buffer of this size)
* m4_l1: MEM_CHUNK_BASE (return physical address on success)
*
* Author:
* Jorrit N. Herder <jnherder@cs.vu.nl>
*/
/*===========================================================================*
* do_kmalloc *
*===========================================================================*/
PUBLIC int do_kmalloc(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Request a (DMA) buffer to be allocated in one of the memory chunks. */
phys_clicks tot_clicks;
struct memory *memp;
kprintf("SYS_KMALLOC called by %d\n", m_ptr->m_source);
tot_clicks = (m_ptr->MEM_CHUNK_SIZE + CLICK_SIZE-1) >> CLICK_SHIFT;
memp = &mem[NR_MEMS];
while ((--memp)->size < tot_clicks) {
if (memp == mem) {
return(ENOMEM);
}
}
memp->size -= tot_clicks;
m_ptr->MEM_CHUNK_BASE = (memp->base + memp->size) << CLICK_SHIFT;
return(OK);
}

View File

@@ -52,6 +52,11 @@ struct kmessages {
char km_buf[KMESS_BUF_SIZE]; /* buffer for messages */
};
struct randomness {
int r_next; /* next index to write */
int r_size; /* number of random elements */
unsigned long r_buf[RANDOM_ELEMENTS]; /* buffer for random info */
};
#if (CHIP == INTEL)
typedef unsigned reg_t; /* machine register */