Split of architecture-dependent and -independent functions for i386,

mainly in the kernel and headers. This split based on work by
Ingmar Alting <iaalting@cs.vu.nl> done for his Minix PowerPC architecture
port.

 . kernel does not program the interrupt controller directly, do any
   other architecture-dependent operations, or contain assembly any more,
   but uses architecture-dependent functions in arch/$(ARCH)/.
 . architecture-dependent constants and types defined in arch/$(ARCH)/include.
 . <ibm/portio.h> moved to <minix/portio.h>, as they have become, for now,
   architecture-independent functions.
 . int86, sdevio, readbios, and iopenable are now i386-specific kernel calls
   and live in arch/i386/do_* now.
 . i386 arch now supports even less 86 code; e.g. mpx86.s and klib86.s have
   gone, and 'machine.protected' is gone (and always taken to be 1 in i386).
   If 86 support is to return, it should be a new architecture.
 . prototypes for the architecture-dependent functions defined in
   kernel/arch/$(ARCH)/*.c but used in kernel/ are in kernel/proto.h
 . /etc/make.conf included in makefiles and shell scripts that need to
   know the building architecture; it defines ARCH=<arch>, currently only
   i386.
 . some basic per-architecture build support outside of the kernel (lib)
 . in clock.c, only dequeue a process if it was ready
 . fixes for new include files

files deleted:
 . mpx/klib.s - only for choosing between mpx/klib86 and -386
 . klib86.s - only for 86

i386-specific files files moved (or arch-dependent stuff moved) to arch/i386/:
 . mpx386.s (entry point)
 . klib386.s
 . sconst.h
 . exception.c
 . protect.c
 . protect.h
 . i8269.c
This commit is contained in:
Ben Gras 2006-12-22 15:22:27 +00:00
parent f7984144d5
commit 6f77685609
100 changed files with 1528 additions and 1633 deletions

View file

@ -33,6 +33,7 @@
#undef EXTERN /* <minix/const.h> defined this */
#define EXTERN /* so we get proc & mproc */
#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../kernel/const.h"
#include "../../kernel/type.h"
#include "../../kernel/proc.h"

View file

@ -64,7 +64,7 @@
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <ibm/portio.h>
#include <minix/portio.h>
#include <ibm/cmos.h>
#include <sys/svrctl.h>

View file

@ -10,6 +10,7 @@
#undef EXTERN
#define EXTERN
#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../servers/pm/const.h"
#include "../../servers/pm/type.h"
#include "../../servers/pm/mproc.h"

View file

@ -19,6 +19,7 @@
#include <pm/type.h>
#include <pm/mproc.h>
#include <kernel/arch/i386/include/archtypes.h>
#include <kernel/const.h>
#include <kernel/type.h>
#include <kernel/proc.h>

View file

@ -11,6 +11,7 @@
#include <sys/ptrace.h>
#include "proto.h"
#include <kernel/arch/i386/include/archtypes.h>
#include <kernel/const.h>
#include <kernel/type.h>
#include <kernel/proc.h>

View file

@ -45,6 +45,7 @@
#include <setjmp.h>
#include "proto.h"
#include "../../kernel/arch/i386/include/archtypes.h"
#include <kernel/const.h>
#include <kernel/type.h>
#include <kernel/proc.h>

View file

@ -76,6 +76,7 @@
#include <stdio.h>
#include <ttyent.h>
#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../kernel/const.h"
#include "../../kernel/type.h"
#include "../../kernel/proc.h"

View file

@ -19,6 +19,7 @@
#include <string.h>
#include <stdlib.h>
#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../kernel/const.h"
#include "../../kernel/type.h"
#include "../../kernel/config.h"

View file

@ -30,6 +30,7 @@
#include <minix/type.h>
#include <minix/const.h>
#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../servers/pm/mproc.h"
#include "../../kernel/const.h"
#include "../../kernel/proc.h"

View file

@ -163,7 +163,7 @@ PRIVATE struct density {
u8_t steps; /* steps per cylinder (2 = double step) */
u8_t test; /* sector to try for density test */
u8_t rate; /* data rate (2=250, 1=300, 0=500 kbps) */
u8_t start; /* motor start (clock ticks) */
clock_t start; /* motor start (clock ticks) */
u8_t gap; /* gap size */
u8_t spec1; /* first specify byte (SRT/HUT) */
} fdensity[NT] = {

View file

@ -355,21 +355,7 @@ PRIVATE void m_init()
if (OK != (s=sys_getmachine(&machine))) {
panic("MEM","Couldn't get machine information.",s);
}
if (! machine.prot) {
m_geom[MEM_DEV].dv_size = cvul64(0x100000); /* 1M for 8086 systems */
} else {
#if _WORD_SIZE == 2
m_geom[MEM_DEV].dv_size = cvul64(0x1000000); /* 16M for 286 systems */
#else
m_geom[MEM_DEV].dv_size = cvul64(0xFFFFFFFF); /* 4G-1 for 386 systems */
#endif
}
#else /* !(CHIP == INTEL) */
#if (CHIP == M68000)
m_geom[MEM_DEV].dv_size = cvul64(MEM_BYTES);
#else /* !(CHIP == M68000) */
#error /* memory limit not set up */
#endif /* !(CHIP == M68000) */
m_geom[MEM_DEV].dv_size = cvul64(0xFFFFFFFF); /* 4G-1 for 386 systems */
#endif /* !(CHIP == INTEL) */
}

View file

@ -1,48 +0,0 @@
# Makefile for rescue driver
DRIVER = rescue
# directories
u = /usr
i = $u/include
s = $i/sys
m = $i/minix
b = $i/ibm
d = ..
# programs, flags, etc.
MAKE = exec make
CC = exec cc
CFLAGS = -I$i $(CPROFILE)
LDFLAGS = -i
LIBS = -lsys -lsysutil
OBJ = rescue.o
LIBDRIVER = $d/libdriver/driver.o
# build local binary
all build: $(DRIVER)
$(DRIVER): $(OBJ) $(LIBDRIVER)
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
install -S 8k $(DRIVER)
$(LIBDRIVER):
cd $d/libdriver && $(MAKE)
# install with other drivers
install: /sbin/$(DRIVER)
/sbin/$(DRIVER): $(DRIVER)
install -o root -cs $? $@
# clean up local files
clean:
rm -f $(DRIVER) *.o *.bak
depend:
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
# Include generated dependencies.
include .depend

View file

@ -1,249 +0,0 @@
/* This file contains the rescue device driver (/dev/rescue)
*
* Changes:
* Oct 21, 1992 created (Jorrit N. Herder)
*/
#include "../drivers.h"
#include "../libdriver/driver.h"
#include "../../kernel/const.h"
#include "../../kernel/config.h"
#include "../../kernel/type.h"
#define VERBOSE 0 /* enable/ disable messages */
#define NR_DEVS 1 /* number of rescue devices */
#define RESCUE_KBYTES 128 /* default size in kilobytes */
PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */
PRIVATE int m_seg[NR_DEVS]; /* segment index of each device */
PRIVATE int m_device; /* current device */
extern int errno; /* error number for PM calls */
FORWARD _PROTOTYPE( void m_init, (int argc, char **argv) );
FORWARD _PROTOTYPE( char *m_name, (void) );
FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, off_t position,
iovec_t *iov, unsigned nr_req, int safe));
FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
/* Entry points to this driver. */
PRIVATE struct driver m_dtab = {
m_name, /* current device's name */
m_do_open, /* open or mount */
do_nop, /* nothing on a close */
do_diocntl, /* standard I/O controls */
m_prepare, /* prepare for I/O on a given minor device */
m_transfer, /* do the I/O */
nop_cleanup, /* no need to clean up */
m_geometry, /* memory device "geometry" */
nop_signal, /* system signals */
nop_alarm,
nop_cancel,
nop_select,
NULL,
NULL
};
/*===========================================================================*
* main *
*===========================================================================*/
PUBLIC int main(int argc, char **argv)
{
/* Main program. Initialize the rescue driver and start the main loop. */
m_init(argc, argv);
driver_task(&m_dtab);
return(OK);
}
/*===========================================================================*
* m_name *
*===========================================================================*/
PRIVATE char *m_name()
{
/* Return a name for the current device. */
static char name[] = "rescue";
return name;
}
/*===========================================================================*
* m_prepare *
*===========================================================================*/
PRIVATE struct device *m_prepare(device)
int device;
{
/* Prepare for I/O on a device: check if the minor device number is ok. */
if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
m_device = device;
return(&m_geom[device]);
}
/*===========================================================================*
* m_transfer *
*===========================================================================*/
PRIVATE int m_transfer(proc_nr, opcode, position, iov, nr_req, safe)
int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER or DEV_SCATTER */
off_t position; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
int safe; /* safe copies? */
{
/* Read or write one the driver's minor devices. */
int seg;
unsigned count, left, chunk;
vir_bytes user_vir, vir_offset = 0;
struct device *dv;
unsigned long dv_size;
int s;
/* Get and check minor device number. */
if ((unsigned) m_device > NR_DEVS - 1) return(ENXIO);
dv = &m_geom[m_device];
dv_size = cv64ul(dv->dv_size);
while (nr_req > 0) {
/* How much to transfer and where to / from. */
count = iov->iov_size;
user_vir = iov->iov_addr;
/* Virtual copying. For rescue device. */
if (position >= dv_size) {
return(OK); /* check for EOF */
}
if (position + count > dv_size) count = dv_size - position;
seg = m_seg[m_device];
if (opcode == DEV_GATHER) { /* copy actual data */
int r;
if(safe) {
if((r=sys_safecopyto(proc_nr, user_vir, vir_offset,
position, count, seg)) != OK) {
printf("rescue: safecopy failed to user (proc %d, grant %d), error %d\n",
proc_nr, user_vir, r);
return EIO;
}
} else {
sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count);
}
} else {
if(safe) {
if(sys_safecopyfrom(proc_nr, user_vir, vir_offset,
position, count, seg) != OK) {
return EIO;
}
} else {
sys_vircopy(proc_nr,D,user_vir, SELF,seg,position, count);
}
}
/* Book the number of bytes transferred. */
if(safe) {
vir_offset += count;
} else {
iov->iov_addr += count;
}
if ((iov->iov_size -= count) == 0) {
iov++;
nr_req--;
vir_offset = 0;
}
position += count;
}
return(OK);
}
/*===========================================================================*
* m_do_open *
*===========================================================================*/
PRIVATE int m_do_open(dp, m_ptr)
struct driver *dp;
message *m_ptr;
{
/* Check device number on open. */
if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
return(OK);
}
/*===========================================================================*
* m_init *
*===========================================================================*/
PRIVATE void m_init(argc,argv)
int argc;
char **argv;
{
/* Initialize this task. All minor devices are initialized one by one. */
phys_bytes rescue_size;
phys_bytes rescue_base;
message m;
int i, s;
/* Initialize all rescue devices in a loop. */
for (i=0; i< NR_DEVS; i++) {
/* Determine size and base of rescue disks. See if rescue disk details
* exist in the data store. If no memory for the rescue disk was claimed
* yet, do it below.
*/
m.DS_KEY = (RESCUE_MAJOR << 8) + i;
if (OK == (s = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m))) {
rescue_size = m.DS_VAL_L1;
rescue_base = m.DS_VAL_L2;
}
else { /* no details known */
if (argc>i+1) rescue_size = atoi(argv[i+1]) * 1024;
else rescue_size = RESCUE_KBYTES * 1024;
if (allocmem(rescue_size, &rescue_base) < 0) {
report("RESCUE", "warning, allocmem failed", errno);
rescue_size = 0;
}
}
/* Now that we have the base and size of the rescue disk, set up all
* data structures if the rescue has a positive (nonzero) size.
*/
if (rescue_size > 0) {
/* Create a new remote segment to make virtual copies. */
if (OK != (s=sys_segctl(&m_seg[i], (u16_t *) &s,
(vir_bytes *) &s, rescue_base, rescue_size))) {
panic("RESCUE","Couldn't install remote segment.",s);
}
/* Set the device geometry for the outside world. */
m_geom[i].dv_base = cvul64(rescue_base);
m_geom[i].dv_size = cvul64(rescue_size);
/* Store the values in the data store for future retrieval. */
m.DS_KEY = (RESCUE_MAJOR << 8) + i;
m.DS_VAL_L1 = rescue_size;
m.DS_VAL_L2 = rescue_base;
if (OK != (s = _taskcall(DS_PROC_NR, DS_PUBLISH, &m))) {
panic("RESCUE","Couldn't store rescue disk details at DS.",s);
}
#if VERBOSE
printf("RESCUE disk %d (size %u/base %u) initialized\n",
i, rescue_size, rescue_base);
#endif
}
}
}
/*===========================================================================*
* m_geometry *
*===========================================================================*/
PRIVATE void m_geometry(entry)
struct partition *entry;
{
/* Memory devices don't have a geometry, but the outside world insists. */
entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
entry->heads = 64;
entry->sectors = 32;
}

View file

@ -62,7 +62,6 @@
#include <minix/type.h>
#include <minix/sysutil.h>
#include <timers.h>
#include <ibm/portio.h>
#include <net/hton.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>

View file

@ -1,6 +1,8 @@
# Makefile for terminal driver (TTY)
DRIVER = tty
include /etc/make.conf
# directories
u = /usr
i = $u/include
@ -12,7 +14,8 @@ d = ..
# programs, flags, etc.
MAKE = exec make
CC = exec cc
CFLAGS = -I$i
CPPFLAGS = -I$i -I../../kernel/arch/$(ARCH)/include
CFLAGS = $(CPPFLAGS)
LDFLAGS = -i
LIBS = -lsysutil -lsys -ltimers

View file

@ -14,6 +14,7 @@
#include <termios.h>
#include <signal.h>
#include <unistd.h>
#include <archtypes.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/keymap.h>

View file

@ -1,7 +1,7 @@
ETC=/etc/
USRETC=/usr/etc/
FILES1=fstab group hostname.file inet.conf motd.install mtab passwd profile protocols rc services termcap ttytab utmp rc.cd binary_sizes binary_sizes.big binary_sizes.xxl rc.rescue syslog.conf rc.daemons.dist rs.single
FILES1=fstab group hostname.file inet.conf motd.install mtab passwd profile protocols rc services termcap ttytab utmp rc.cd binary_sizes binary_sizes.big binary_sizes.xxl rc.rescue syslog.conf rc.daemons.dist rs.single make.conf
FILES2=shadow
FILES3=daily dhcptags.conf rc
@ -21,7 +21,7 @@ install::
p=`pwd` && cd /dev && sh $$p/../commands/scripts/MAKEDEV.sh null
p=`pwd` && cd /dev && sh $$p/../commands/scripts/MAKEDEV.sh std 2>/dev/null
@echo "Making user homedirs.."
for u in /usr/ast ~root; do (cd ast && tar cf - .[a-z]* ) | (cd $$u && tar xf - ); done
for u in /usr/ast ~root; do cp ast/.* $$u ; done
postinstall:
binsizes normal

View file

@ -128,7 +128,7 @@
#define FASTLOAD _FASTLOAD
/* Enable or disable system profiling. */
#define SPROFILE 0 /* statistical profiling */
#define SPROFILE 1 /* statistical profiling */
#define CPROFILE 0 /* call profiling */
#endif /* _CONFIG_H */

View file

@ -1,5 +1,5 @@
/*
ibm/portio.h
minix/portio.h
Created: Jan 15, 1992 by Philip Homburg
*/

View file

@ -69,6 +69,6 @@ error "_MINIX_MACHINE has incorrect value (0)"
#endif
/* Kernel debug checks */
#define DEBUG_LOCK_CHECK 0 /* Interrupt Lock/unlock sanity checking. */
#define DEBUG_LOCK_CHECK 1 /* Interrupt Lock/unlock sanity checking. */
#endif /* _MINIX_SYS_CONFIG_H */

View file

@ -136,7 +136,7 @@ struct machine {
int pc_at;
int ps_mca;
int processor;
int prot;
int padding; /* used to be protected */
int vdu_ega;
int vdu_vga;
};

View file

@ -1,51 +1,57 @@
# Makefile for kernel
include /etc/make.conf
# Directories
u = /usr
i = $u/include
l = $u/lib
s = system
a = arch/$(ARCH)
# Programs, flags, etc.
CC = exec cc
CPP = $l/cpp
LD = $(CC) -.o
CFLAGS = -I$i $(CPROFILE)
LDFLAGS = -i
CPPFLAGS=-I$i -I$a/include
CFLAGS=$(CPROFILE) $(CPPFLAGS)
LDFLAGS=-i
HEAD = mpx.o
OBJS = start.o protect.o klib.o table.o kprintf.o main.o proc.o \
i8259.o exception.o system.o clock.o utility.o debug.o profile.o
# first-stage, arch-dependent startup code
HEAD = head.o
FULLHEAD = $a/$(HEAD)
OBJS = start.o table.o main.o proc.o \
system.o clock.o utility.o debug.o profile.o interrupt.o
SYSTEM = system.a
ARCHLIB = $a/$(ARCH).a
LIBS = -ltimers -lsysutil
# What to make.
all: build
kernel build install: $(HEAD) $(OBJS)
cd system && $(MAKE) -$(MAKEFLAGS) $@
$(LD) $(CFLAGS) $(LDFLAGS) -o kernel \
$(HEAD) $(OBJS) \
$(SYSTEM) $(LIBS)
cd system && $(MAKE) $@
cd $a && $(MAKE) $@
$(LD) $(CFLAGS) $(LDFLAGS) -o kernel $(FULLHEAD) $(OBJS) \
$(SYSTEM) $(ARCHLIB) $(LIBS)
install -S 0 kernel
clean:
cd system && $(MAKE) -$(MAKEFLAGS) $@
cd $a && $(MAKE) -$(MAKEFLAGS) $@
rm -f *.a *.o *~ *.bak kernel
depend:
cd system && $(MAKE) -$(MAKEFLAGS) $@
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c *.s > .depend
cd $a && $(MAKE) $@
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
# How to build it
.s.o:
$(CC) $(CFLAGS) -c -o $@ $<
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
# Include generated dependencies.
klib.o: klib386.s klib88.s
mpx.o: mpx386.s mpx88.s
include .depend
$(HEAD):
cd $a && make HEAD=$(HEAD) $(HEAD)
# Include generated dependencies.
include .depend

81
kernel/arch/i386/Makefile Executable file
View file

@ -0,0 +1,81 @@
# Makefile for kernel
include /etc/make.conf
ARCHAR=$(ARCH).a
# objects, excluding first-stage code, which is $(HEAD).
# the HEAD variable is passed as an argument to this Makefile
# by an upper level Makefile.
OBJS=$(ARCHAR)(exception.o) \
$(ARCHAR)(i8259.o) \
$(ARCHAR)(memory.o) \
$(ARCHAR)(protect.o) \
$(ARCHAR)(system.o) \
$(ARCHAR)(clock.o) \
$(ARCHAR)(klib386.o) \
$(ARCHAR)(do_readbios.o) \
$(ARCHAR)(do_int86.o) \
$(ARCHAR)(do_sdevio.o) \
$(ARCHAR)(do_iopenable.o)
CPPFLAGS=-Iinclude
CFLAGS=$(CPPFLAGS) -Wall
build: $(HEAD) $(ARCHAR)
$(ARCHAR): $(OBJS)
aal cr $@ *.o
depend:
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c *.s > .depend
clean:
rm -f *.a *.o *~
# How to build it
$(ARCHAR)(exception.o): exception.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(i8259.o): i8259.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(memory.o): memory.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(protect.o): protect.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(system.o): system.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(do_int86.o): do_int86.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(do_iopenable.o): do_iopenable.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(do_readbios.o): do_readbios.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(do_sdevio.o): do_sdevio.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(clock.o): clock.c
$(CC) $(CFLAGS) -c $<
$(ARCHAR)(klib386.o): klib386.s
$(CC) $(CFLAGS) -c $<
.s.o:
$(CC) $(CFLAGS) -c -o $@ $<
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
$(HEAD): mpx386.o
cp $< $@
# Include generated dependencies.
include .depend

65
kernel/arch/i386/clock.c Executable file
View file

@ -0,0 +1,65 @@
/* i386-specific clock functions. */
#include <ibm/ports.h>
#include <minix/portio.h>
#include "../../kernel.h"
#define CLOCK_ACK_BIT 0x80 /* PS/2 clock interrupt acknowledge bit */
/* Clock parameters. */
#define COUNTER_FREQ (2*TIMER_FREQ) /* counter frequency using square wave */
#define LATCH_COUNT 0x00 /* cc00xxxx, c = channel, x = any */
#define SQUARE_WAVE 0x36 /* ccaammmb, a = access, m = mode, b = BCD */
/* 11x11, 11 = LSB then MSB, x11 = sq wave */
#define TIMER_FREQ 1193182 /* clock frequency for timer in PC and AT */
#define TIMER_COUNT (TIMER_FREQ/HZ) /* initial value for counter*/
/*===========================================================================*
* arch_init_clock *
*===========================================================================*/
PUBLIC int arch_init_clock(void)
{
/* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz,
* and register the CLOCK task's interrupt handler to be run
* on every clock tick.
*/
outb(TIMER_MODE, SQUARE_WAVE); /* run continuously */
outb(TIMER0, (TIMER_COUNT & 0xff)); /* timer low byte */
outb(TIMER0, TIMER_COUNT >> 8); /* timer high byte */
return OK;
}
/*===========================================================================*
* clock_stop *
*===========================================================================*/
PUBLIC void clock_stop(void)
{
/* Reset the clock to the BIOS rate. (For rebooting.) */
outb(TIMER_MODE, 0x36);
outb(TIMER0, 0);
outb(TIMER0, 0);
}
/*===========================================================================*
* read_clock *
*===========================================================================*/
PUBLIC clock_t read_clock(void)
{
/* Read the counter of channel 0 of the 8253A timer. This counter
* counts down at a rate of TIMER_FREQ and restarts at
* TIMER_COUNT-1 when it reaches zero. A hardware interrupt
* (clock tick) occurs when the counter gets to zero and restarts
* its cycle.
*/
u32_t count;
outb(TIMER_MODE, LATCH_COUNT);
count = inb(TIMER0);
count |= (inb(TIMER0) << 8);
return count;
}

View file

@ -5,11 +5,14 @@
* m1_p1: INT86_REG86
*/
#include "../system.h"
#include "../../system.h"
#include <minix/type.h>
#include <minix/endpoint.h>
#include <minix/portio.h>
#include <ibm/int86.h>
#include "proto.h"
struct reg86u reg86;
/*===========================================================================*

View file

@ -8,8 +8,10 @@
* Jorrit N. Herder <jnherder@cs.vu.nl>
*/
#include "../system.h"
#include "../kernel.h"
#include "../../system.h"
#include "../../kernel.h"
#include "proto.h"
/*===========================================================================*
* do_iopenable *

View file

@ -7,7 +7,7 @@
* m2_p1: RDB_BUF buffer address in requesting process
*/
#include "../system.h"
#include "../../system.h"
#include <minix/type.h>
/*===========================================================================*

View file

@ -10,10 +10,12 @@
* m2_i2: DIO_VEC_PROC (process where buffer is)
*/
#include "../system.h"
#include "../../system.h"
#include <minix/devio.h>
#include <minix/endpoint.h>
#include "proto.h"
#if USE_SDEVIO
/*===========================================================================*

View file

@ -3,15 +3,14 @@
* a panic.
*/
#include "kernel.h"
#include "../../kernel.h"
#include <signal.h>
#include "proc.h"
#include "../../proc.h"
/*===========================================================================*
* exception *
*===========================================================================*/
PUBLIC void exception(vec_nr)
unsigned vec_nr;
PUBLIC void exception(unsigned vec_nr)
{
/* An exception or unexpected interrupt has occurred. */
@ -93,8 +92,7 @@ unsigned vec_nr;
/*===========================================================================*
* stacktrace *
*===========================================================================*/
PUBLIC void stacktrace(proc)
struct proc *proc;
PUBLIC void stacktrace(struct proc *proc)
{
reg_t bp, v_bp, v_pc, v_hbp;

79
kernel/arch/i386/i8259.c Executable file
View file

@ -0,0 +1,79 @@
/* This file contains routines for initializing the 8259 interrupt controller:
* put_irq_handler: register an interrupt handler
* rm_irq_handler: deregister an interrupt handler
* intr_handle: handle a hardware interrupt
* intr_init: initialize the interrupt controller(s)
*/
#include "../../kernel.h"
#include "../../proc.h"
#include "proto.h"
#include <minix/com.h>
#include <minix/portio.h>
#include <ibm/cpu.h>
#define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
#define ICW1_PC 0x13 /* edge triggered, no cascade, need ICW4 */
#define ICW1_PS 0x19 /* level triggered, cascade, need ICW4 */
#define ICW4_AT_SLAVE 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
#define ICW4_AT_MASTER 0x05 /* not SFNM, not buffered, normal EOI, 8086 */
#define ICW4_PC_SLAVE 0x09 /* not SFNM, buffered, normal EOI, 8086 */
#define ICW4_PC_MASTER 0x0D /* not SFNM, buffered, normal EOI, 8086 */
#define set_vec(nr, addr) ((void)0)
/*===========================================================================*
* intr_init *
*===========================================================================*/
PUBLIC int intr_init(mine)
int mine;
{
/* Initialize the 8259s, finishing with all interrupts disabled. This is
* only done in protected mode, in real mode we don't touch the 8259s, but
* use the BIOS locations instead. The flag "mine" is set if the 8259s are
* to be programmed for MINIX, or to be reset to what the BIOS expects.
*/
int i;
intr_disable();
/* 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
* has just one controller, because it must run in real mode.)
*/
outb( INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
outb( INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
/* ICW2 for master */
outb( INT_CTLMASK, (1 << CASCADE_IRQ));
/* ICW3 tells slaves */
outb( INT_CTLMASK, ICW4_AT_MASTER);
outb( INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
outb( INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
outb( INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
/* ICW2 for slave */
outb( INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */
outb( INT2_CTLMASK, ICW4_AT_SLAVE);
outb( INT2_CTLMASK, ~0); /* IRQ 8-15 mask */
/* Copy the BIOS vectors from the BIOS to the Minix location, so we
* can still make BIOS calls without reprogramming the i8259s.
*/
#if IRQ0_VECTOR != BIOS_IRQ0_VEC
phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L);
#endif
#if IRQ8_VECTOR != BIOS_IRQ8_VEC
phys_copy(BIOS_VECTOR(8) * 4L, VECTOR(8) * 4L, 8 * 4L);
#endif
return OK;
}
/*===========================================================================*
* intr_disabled *
*===========================================================================*/
PUBLIC int intr_disabled(void)
{
if(!(read_cpu_flags() & X86_FLAG_I))
return 1;
return 0;
}

View file

@ -0,0 +1,146 @@
#ifndef _I386_ACONST_H
#define _I386_ACONST_H 1
#include <ibm/interrupt.h>
#include <ibm/memory.h>
#define NR_REMOTE_SEGS 3 /* # remote memory regions (variable) */
/* Constants for protected mode. */
/* Table sizes. */
#define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS)
/* spec. and LDT's */
#define IDT_SIZE (IRQ8_VECTOR + 8) /* only up to the highest vector */
/* Fixed global descriptors. 1 to 7 are prescribed by the BIOS. */
#define GDT_INDEX 1 /* GDT descriptor */
#define IDT_INDEX 2 /* IDT descriptor */
#define DS_INDEX 3 /* kernel DS */
#define ES_INDEX 4 /* kernel ES (386: flag 4 Gb at startup) */
#define SS_INDEX 5 /* kernel SS (386: monitor SS at startup) */
#define CS_INDEX 6 /* kernel CS */
#define MON_CS_INDEX 7 /* temp for BIOS (386: monitor CS at startup) */
#define TSS_INDEX 8 /* kernel TSS */
#define DS_286_INDEX 9 /* scratch 16-bit source segment */
#define ES_286_INDEX 10 /* scratch 16-bit destination segment */
#define A_INDEX 11 /* 64K memory segment at A0000 */
#define B_INDEX 12 /* 64K memory segment at B0000 */
#define C_INDEX 13 /* 64K memory segment at C0000 */
#define D_INDEX 14 /* 64K memory segment at D0000 */
#define FIRST_LDT_INDEX 15 /* rest of descriptors are LDT's */
#define GDT_SELECTOR 0x08 /* (GDT_INDEX * DESC_SIZE) bad for asld */
#define IDT_SELECTOR 0x10 /* (IDT_INDEX * DESC_SIZE) */
#define DS_SELECTOR 0x18 /* (DS_INDEX * DESC_SIZE) */
#define ES_SELECTOR 0x20 /* (ES_INDEX * DESC_SIZE) */
#define FLAT_DS_SELECTOR 0x21 /* less privileged ES */
#define SS_SELECTOR 0x28 /* (SS_INDEX * DESC_SIZE) */
#define CS_SELECTOR 0x30 /* (CS_INDEX * DESC_SIZE) */
#define MON_CS_SELECTOR 0x38 /* (MON_CS_INDEX * DESC_SIZE) */
#define TSS_SELECTOR 0x40 /* (TSS_INDEX * DESC_SIZE) */
#define DS_286_SELECTOR 0x49 /* (DS_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */
#define ES_286_SELECTOR 0x51 /* (ES_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */
/* Privileges. */
#define INTR_PRIVILEGE 0 /* kernel and interrupt handlers */
#define TASK_PRIVILEGE 1 /* kernel tasks */
#define USER_PRIVILEGE 3 /* servers and user processes */
/* 286 hardware constants. */
/* Exception vector numbers. */
#define BOUNDS_VECTOR 5 /* bounds check failed */
#define INVAL_OP_VECTOR 6 /* invalid opcode */
#define COPROC_NOT_VECTOR 7 /* coprocessor not available */
#define DOUBLE_FAULT_VECTOR 8
#define COPROC_SEG_VECTOR 9 /* coprocessor segment overrun */
#define INVAL_TSS_VECTOR 10 /* invalid TSS */
#define SEG_NOT_VECTOR 11 /* segment not present */
#define STACK_FAULT_VECTOR 12 /* stack exception */
#define PROTECTION_VECTOR 13 /* general protection */
/* Selector bits. */
#define TI 0x04 /* table indicator */
#define RPL 0x03 /* requester privilege level */
/* Descriptor structure offsets. */
#define DESC_BASE 2 /* to base_low */
#define DESC_BASE_MIDDLE 4 /* to base_middle */
#define DESC_ACCESS 5 /* to access byte */
#define DESC_SIZE 8 /* sizeof (struct segdesc_s) */
/* Base and limit sizes and shifts. */
#define BASE_MIDDLE_SHIFT 16 /* shift for base --> base_middle */
/* Access-byte and type-byte bits. */
#define PRESENT 0x80 /* set for descriptor present */
#define DPL 0x60 /* descriptor privilege level mask */
#define DPL_SHIFT 5
#define SEGMENT 0x10 /* set for segment-type descriptors */
/* Access-byte bits. */
#define EXECUTABLE 0x08 /* set for executable segment */
#define CONFORMING 0x04 /* set for conforming segment if executable */
#define EXPAND_DOWN 0x04 /* set for expand-down segment if !executable*/
#define READABLE 0x02 /* set for readable segment if executable */
#define WRITEABLE 0x02 /* set for writeable segment if !executable */
#define TSS_BUSY 0x02 /* set if TSS descriptor is busy */
#define ACCESSED 0x01 /* set if segment accessed */
/* Special descriptor types. */
#define AVL_286_TSS 1 /* available 286 TSS */
#define LDT 2 /* local descriptor table */
#define BUSY_286_TSS 3 /* set transparently to the software */
#define CALL_286_GATE 4 /* not used */
#define TASK_GATE 5 /* only used by debugger */
#define INT_286_GATE 6 /* interrupt gate, used for all vectors */
#define TRAP_286_GATE 7 /* not used */
/* Extra 386 hardware constants. */
/* Exception vector numbers. */
#define PAGE_FAULT_VECTOR 14
#define COPROC_ERR_VECTOR 16 /* coprocessor error */
/* Descriptor structure offsets. */
#define DESC_GRANULARITY 6 /* to granularity byte */
#define DESC_BASE_HIGH 7 /* to base_high */
/* Type-byte bits. */
#define DESC_386_BIT 0x08 /* 386 types are obtained by ORing with this */
/* LDT's and TASK_GATE's don't need it */
/* Base and limit sizes and shifts. */
#define BASE_HIGH_SHIFT 24 /* shift for base --> base_high */
#define BYTE_GRAN_MAX 0xFFFFFL /* maximum size for byte granular segment */
#define GRANULARITY_SHIFT 16 /* shift for limit --> granularity */
#define OFFSET_HIGH_SHIFT 16 /* shift for (gate) offset --> offset_high */
#define PAGE_GRAN_SHIFT 12 /* extra shift for page granular limits */
/* Granularity byte. */
#define GRANULAR 0x80 /* set for 4K granularilty */
#define DEFAULT 0x40 /* set for 32-bit defaults (executable seg) */
#define BIG 0x40 /* set for "BIG" (expand-down seg) */
#define AVL 0x10 /* 0 for available */
#define LIMIT_HIGH 0x0F /* mask for high bits of limit */
/* Program stack words and masks. */
#define INIT_PSW 0x0200 /* initial psw */
#define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */
#define TRACEBIT 0x0100 /* OR this with psw in proc[] for tracing */
#define SETPSW(rp, new) /* permits only certain bits to be set */ \
((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
#define IF_MASK 0x00000200
#define IOPL_MASK 0x003000
/* 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
#define vir2phys(vir) (kinfo.data_base + (vir_bytes) (vir))
#endif /* _I386_ACONST_H */

View file

@ -0,0 +1,62 @@
#ifndef _I386_TYPES_H
#define _I386_TYPES_H
#include <minix/sys_config.h>
#include "archconst.h"
typedef unsigned reg_t; /* machine register */
typedef reg_t segdesc_t;
/* The stack frame layout is determined by the software, but for efficiency
* it is laid out so the assembly code to use it is as simple as possible.
* 80286 protected mode and all real modes use the same frame, built with
* 16-bit registers. Real mode lacks an automatic stack switch, so little
* is lost by using the 286 frame for it. The 386 frame differs only in
* having 32-bit registers and more segment registers. The same names are
* used for the larger registers to avoid differences in the code.
*/
struct stackframe_s { /* proc_ptr points here */
u16_t gs; /* last item pushed by save */
u16_t fs; /* ^ */
u16_t es; /* | */
u16_t ds; /* | */
reg_t di; /* di through cx are not accessed in C */
reg_t si; /* order is to match pusha/popa */
reg_t fp; /* bp */
reg_t st; /* hole for another copy of sp */
reg_t bx; /* | */
reg_t dx; /* | */
reg_t cx; /* | */
reg_t retreg; /* ax and above are all pushed by save */
reg_t retadr; /* return address for assembly code save() */
reg_t pc; /* ^ last item pushed by interrupt */
reg_t cs; /* | */
reg_t psw; /* | */
reg_t sp; /* | */
reg_t ss; /* these are pushed by CPU during interrupt */
};
struct segdesc_s { /* segment descriptor for protected mode */
u16_t limit_low;
u16_t base_low;
u8_t base_middle;
u8_t access; /* |P|DL|1|X|E|R|A| */
u8_t granularity; /* |G|X|0|A|LIMT| */
u8_t base_high;
};
#define LDT_SIZE (2 + NR_REMOTE_SEGS) /* CS, DS and remote segments */
/* Fixed local descriptors. */
#define CS_LDT_INDEX 0 /* process CS */
#define DS_LDT_INDEX 1 /* process DS=ES=FS=GS=SS */
#define EXTRA_LDT_INDEX 2 /* first of the extra LDT entries */
typedef struct segframe {
reg_t p_ldt_sel; /* selector in gdt with ldt base and limit */
struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote */
} segframe_t;
#endif /* #ifndef _I386_TYPES_H */

View file

@ -5,9 +5,10 @@
#include <minix/config.h>
#include <minix/const.h>
#include "const.h"
#include <ibm/interrupt.h>
#include <archconst.h>
#include "../../const.h"
#include "sconst.h"
#include "protect.h"
! This file contains a number of assembly code utility routines needed by the
! kernel. They are:
@ -23,8 +24,8 @@
.define _phys_insb ! likewise byte by byte
.define _phys_outsw ! transfer data from memory to (disk controller) port
.define _phys_outsb ! likewise byte by byte
.define _enable_irq ! enable an irq at the 8259 controller
.define _disable_irq ! disable an irq
.define _intr_unmask ! enable an irq at the 8259 controller
.define _intr_mask ! disable an irq
.define _phys_copy ! copy data from anywhere to anywhere in memory
.define _phys_memset ! write pattern anywhere in memory
.define _mem_rdw ! copy one word from [segment:offset]
@ -319,16 +320,16 @@ _phys_outsb:
!*==========================================================================*
!* enable_irq *
!* intr_unmask *
!*==========================================================================*/
! PUBLIC void enable_irq(irq_hook_t *hook)
! PUBLIC void intr_unmask(irq_hook_t *hook)
! Enable an interrupt request line by clearing an 8259 bit.
! Equivalent C code for hook->irq < 8:
! if ((irq_actids[hook->irq] &= ~hook->id) == 0)
! outb(INT_CTLMASK, inb(INT_CTLMASK) & ~(1 << irq));
.align 16
_enable_irq:
_intr_unmask:
push ebp
mov ebp, esp
pushf
@ -354,9 +355,9 @@ en_done:popf
!*==========================================================================*
!* disable_irq *
!* intr_mask *
!*==========================================================================*/
! PUBLIC int disable_irq(irq_hook_t *hook)
! PUBLIC int intr_mask(irq_hook_t *hook)
! Disable an interrupt request line by setting an 8259 bit.
! Equivalent C code for irq < 8:
! irq_actids[hook->irq] |= hook->id;
@ -364,7 +365,7 @@ en_done:popf
! Returns true iff the interrupt was not already disabled.
.align 16
_disable_irq:
_intr_mask:
push ebp
mov ebp, esp
pushf

234
kernel/arch/i386/memory.c Normal file
View file

@ -0,0 +1,234 @@
#include "../../kernel.h"
#include "../../proc.h"
#include <minix/type.h>
#include <string.h>
#include <sys/vm.h>
#include <minix/portio.h>
#include "proto.h"
/* VM functions and data. */
PRIVATE int vm_needs_init= 1;
PRIVATE u32_t vm_cr3;
FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value) );
FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr) );
FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value) );
FORWARD _PROTOTYPE( void set_cr3, (void) );
FORWARD _PROTOTYPE( void vm_enable_paging, (void) );
/* *** Internal VM Functions *** */
PUBLIC void vm_init(void)
{
int o;
phys_bytes p, pt_size;
phys_bytes vm_dir_base, vm_pt_base, phys_mem;
u32_t entry;
unsigned pages;
if (!vm_size)
panic("i386_vm_init: no space for page tables", NO_NUM);
/* Align page directory */
o= (vm_base % PAGE_SIZE);
if (o != 0)
o= PAGE_SIZE-o;
vm_dir_base= vm_base+o;
/* Page tables start after the page directory */
vm_pt_base= vm_dir_base+PAGE_SIZE;
pt_size= (vm_base+vm_size)-vm_pt_base;
pt_size -= (pt_size % PAGE_SIZE);
/* Compute the number of pages based on vm_mem_high */
pages= (vm_mem_high-1)/PAGE_SIZE + 1;
if (pages * I386_VM_PT_ENT_SIZE > pt_size)
panic("i386_vm_init: page table too small", NO_NUM);
for (p= 0; p*I386_VM_PT_ENT_SIZE < pt_size; p++)
{
phys_mem= p*PAGE_SIZE;
entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
I386_VM_PRESENT;
if (phys_mem >= vm_mem_high)
entry= 0;
phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
}
for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
{
phys_mem= vm_pt_base + p*PAGE_SIZE;
entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
I386_VM_PRESENT;
if (phys_mem >= vm_pt_base + pt_size)
entry= 0;
phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
}
vm_set_cr3(vm_dir_base);
level0(vm_enable_paging);
}
PRIVATE void phys_put32(addr, value)
phys_bytes addr;
u32_t value;
{
phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
}
PRIVATE u32_t phys_get32(addr)
phys_bytes addr;
{
u32_t value;
phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
return value;
}
PRIVATE void vm_set_cr3(value)
u32_t value;
{
vm_cr3= value;
level0(set_cr3);
}
PRIVATE void set_cr3()
{
write_cr3(vm_cr3);
}
PRIVATE void vm_enable_paging(void)
{
u32_t cr0;
cr0= read_cr0();
write_cr0(cr0 | I386_CR0_PG);
}
PUBLIC void vm_map_range(base, size, offset)
u32_t base;
u32_t size;
u32_t offset;
{
u32_t curr_pt, curr_pt_addr, entry;
int dir_ent, pt_ent;
if (base % PAGE_SIZE != 0)
panic("map_range: bad base", base);
if (size % PAGE_SIZE != 0)
panic("map_range: bad size", size);
if (offset % PAGE_SIZE != 0)
panic("map_range: bad offset", offset);
curr_pt= -1;
curr_pt_addr= 0;
while (size != 0)
{
dir_ent= (base >> I386_VM_DIR_ENT_SHIFT);
pt_ent= (base >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK;
if (dir_ent != curr_pt)
{
/* Get address of page table */
curr_pt= dir_ent;
curr_pt_addr= phys_get32(vm_cr3 +
dir_ent * I386_VM_PT_ENT_SIZE);
curr_pt_addr &= I386_VM_ADDR_MASK;
}
entry= offset | I386_VM_USER | I386_VM_WRITE |
I386_VM_PRESENT;
#if 0 /* Do we need this for memory mapped I/O? */
entry |= I386_VM_PCD | I386_VM_PWT;
#endif
phys_put32(curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE, entry);
offset += PAGE_SIZE;
base += PAGE_SIZE;
size -= PAGE_SIZE;
}
/* reload root of page table. */
vm_set_cr3(vm_cr3);
}
PUBLIC vir_bytes alloc_remote_segment(u32_t *selector,
segframe_t *segments, int index, phys_bytes phys, vir_bytes size,
int priv)
{
phys_bytes offset = 0;
/* 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(&segments->p_ldt[EXTRA_LDT_INDEX+index],
phys, size, priv);
*selector = ((EXTRA_LDT_INDEX+index)*0x08) | (1*0x04) | priv;
offset = 0;
} else {
init_dataseg(&segments->p_ldt[EXTRA_LDT_INDEX+index],
phys & ~0xFFFF, 0, priv);
*selector = ((EXTRA_LDT_INDEX+index)*0x08) | (1*0x04) | priv;
offset = phys & 0xFFFF;
}
return offset;
}
PUBLIC phys_bytes umap_remote(struct proc* rp, int seg,
vir_bytes vir_addr, vir_bytes bytes)
{
/* Calculate the physical memory address for a given virtual address. */
struct far_mem *fm;
if (bytes <= 0) return( (phys_bytes) 0);
if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
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);
return(fm->mem_phys + (phys_bytes) vir_addr);
}
/*===========================================================================*
* umap_local *
*===========================================================================*/
PUBLIC phys_bytes umap_local(rp, seg, vir_addr, bytes)
register struct proc *rp; /* pointer to proc table entry for process */
int seg; /* T, D, or S segment */
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 */
phys_bytes seg_base;
if (bytes <= 0) return( (phys_bytes) 0);
if (vir_addr + bytes <= vir_addr) return 0; /* overflow */
vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */
if (seg != T)
seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S);
if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir +
rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
if (vc >= rp->p_memmap[seg].mem_vir +
rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
seg_base = (phys_bytes) rp->p_memmap[seg].mem_phys;
seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */
pa = (phys_bytes) vir_addr;
pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
return(seg_base + pa);
}

View file

@ -56,8 +56,8 @@ begbss:
#include <minix/const.h>
#include <minix/com.h>
#include <ibm/interrupt.h>
#include "const.h"
#include "protect.h"
#include <archconst.h>
#include "../../const.h"
#include "sconst.h"
/* Selected 386 tss offsets. */

View file

@ -3,17 +3,14 @@
* for local descriptors in the process table.
*/
#include "kernel.h"
#include "proc.h"
#include "protect.h"
#include "../../kernel.h"
#include "../../proc.h"
#include <archconst.h>
#include "proto.h"
#if _WORD_SIZE == 4
#define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT)
#define TSS_TYPE (AVL_286_TSS | DESC_386_BIT)
#else
#define INT_GATE_TYPE INT_286_GATE
#define TSS_TYPE AVL_286_TSS
#endif
struct desctableptr_s {
char limit[sizeof(u16_t)];
@ -36,9 +33,7 @@ struct tss_s {
reg_t ss1;
reg_t sp2;
reg_t ss2;
#if _WORD_SIZE == 4
reg_t cr3;
#endif
reg_t ip;
reg_t flags;
reg_t ax;
@ -53,16 +48,12 @@ struct tss_s {
reg_t cs;
reg_t ss;
reg_t ds;
#if _WORD_SIZE == 4
reg_t fs;
reg_t gs;
#endif
reg_t ldt;
#if _WORD_SIZE == 4
u16_t trap;
u16_t iobase;
/* u8_t iomap[0]; */
#endif
};
PUBLIC struct segdesc_s gdt[GDT_SIZE]; /* used in klib.s and mpx.s */
@ -74,10 +65,79 @@ FORWARD _PROTOTYPE( void int_gate, (unsigned vec_nr, vir_bytes offset,
FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base,
vir_bytes size) );
/*===========================================================================*
* enable_iop *
*===========================================================================*/
PUBLIC void enable_iop(struct proc *pp)
{
/* Allow a user process to use I/O instructions. Change the I/O Permission
* Level bits in the psw. These specify least-privileged Current Permission
* Level allowed to execute I/O instructions. Users and servers have CPL 3.
* You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1.
*/
pp->p_reg.psw |= 0x3000;
}
/*===========================================================================*
* seg2phys *
*===========================================================================*/
PUBLIC phys_bytes seg2phys(U16_t seg)
{
/* Return the base address of a segment, with seg being a
* register, or a 286/386 segment selector.
*/
phys_bytes base;
struct segdesc_s *segdp;
segdp = &gdt[seg >> 3];
base = ((u32_t) segdp->base_low << 0)
| ((u32_t) segdp->base_middle << 16)
| ((u32_t) segdp->base_high << 24);
return base;
}
/*===========================================================================*
* phys2seg *
*===========================================================================*/
PUBLIC void phys2seg(u16_t *seg, vir_bytes *off, phys_bytes phys)
{
/* 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.
*/
*seg = FLAT_DS_SELECTOR;
*off = phys;
}
/*===========================================================================*
* init_dataseg *
*===========================================================================*/
PUBLIC void init_dataseg(register struct segdesc_s *segdp,
phys_bytes base, 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 */
}
/*===========================================================================*
* init_codeseg *
*===========================================================================*/
PUBLIC void init_codeseg(register struct segdesc_s *segdp, phys_bytes base,
vir_bytes size, int privilege)
{
/* Build descriptor for a code segment. */
sdesc(segdp, base, size);
segdp->access = (privilege << DPL_SHIFT)
| (PRESENT | SEGMENT | EXECUTABLE | READABLE);
/* CONFORMING = 0, ACCESSED = 0 */
}
/*===========================================================================*
* prot_init *
*===========================================================================*/
PUBLIC void prot_init()
PUBLIC void prot_init(void)
{
/* Set up tables for protected mode.
* All GDT slots are allocated at compile time.
@ -107,10 +167,8 @@ PUBLIC void prot_init()
{ segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE },
{ stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE },
{ general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE },
#if _WORD_SIZE == 4
{ page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE },
{ copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE },
#endif
{ hwint00, VECTOR( 0), INTR_PRIVILEGE },
{ hwint01, VECTOR( 1), INTR_PRIVILEGE },
{ hwint02, VECTOR( 2), INTR_PRIVILEGE },
@ -127,11 +185,7 @@ PUBLIC void prot_init()
{ hwint13, VECTOR(13), INTR_PRIVILEGE },
{ hwint14, VECTOR(14), INTR_PRIVILEGE },
{ hwint15, VECTOR(15), INTR_PRIVILEGE },
#if _WORD_SIZE == 2
{ p_s_call, SYS_VECTOR, USER_PRIVILEGE }, /* 286 system call */
#else
{ s_call, SYS386_VECTOR, USER_PRIVILEGE }, /* 386 system call */
#endif
{ level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE },
};
@ -161,10 +215,10 @@ PUBLIC void prot_init()
*/
for (rp = BEG_PROC_ADDR, ldt_index = FIRST_LDT_INDEX;
rp < END_PROC_ADDR; ++rp, ldt_index++) {
init_dataseg(&gdt[ldt_index], vir2phys(rp->p_ldt),
sizeof(rp->p_ldt), INTR_PRIVILEGE);
init_dataseg(&gdt[ldt_index], vir2phys(rp->p_seg.p_ldt),
sizeof(rp->p_seg.p_ldt), INTR_PRIVILEGE);
gdt[ldt_index].access = PRESENT | LDT;
rp->p_ldt_sel = ldt_index * DESC_SIZE;
rp->p_seg.p_ldt_sel = ldt_index * DESC_SIZE;
}
/* Build main TSS.
@ -185,42 +239,11 @@ PUBLIC void prot_init()
PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT));
}
#if _WORD_SIZE == 4
/* Complete building of main TSS. */
tss.iobase = sizeof tss; /* empty i/o permissions map */
#endif
}
/*===========================================================================*
* init_codeseg *
*===========================================================================*/
PUBLIC void init_codeseg(segdp, base, size, privilege)
register struct segdesc_s *segdp;
phys_bytes base;
vir_bytes size;
int privilege;
{
/* Build descriptor for a code segment. */
sdesc(segdp, base, size);
segdp->access = (privilege << DPL_SHIFT)
| (PRESENT | SEGMENT | EXECUTABLE | READABLE);
/* CONFORMING = 0, ACCESSED = 0 */
}
/*===========================================================================*
* init_dataseg *
*===========================================================================*/
PUBLIC void init_dataseg(segdp, base, size, privilege)
register struct segdesc_s *segdp;
phys_bytes base;
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 */
}
/*===========================================================================*
* sdesc *
@ -235,7 +258,6 @@ vir_bytes size;
segdp->base_middle = base >> BASE_MIDDLE_SHIFT;
segdp->base_high = base >> BASE_HIGH_SHIFT;
#if _WORD_SIZE == 4
--size; /* convert to a limit, 0 size means 4G */
if (size > BYTE_GRAN_MAX) {
segdp->limit_low = size >> PAGE_GRAN_SHIFT;
@ -246,60 +268,6 @@ vir_bytes size;
segdp->granularity = size >> GRANULARITY_SHIFT;
}
segdp->granularity |= DEFAULT; /* means BIG for data seg */
#else
segdp->limit_low = size - 1;
#endif
}
/*===========================================================================*
* seg2phys *
*===========================================================================*/
PUBLIC phys_bytes seg2phys(seg)
U16_t seg;
{
/* Return the base address of a segment, with seg being either a 8086 segment
* register, or a 286/386 segment selector.
*/
phys_bytes base;
struct segdesc_s *segdp;
if (! machine.prot) {
base = hclick_to_physb(seg);
} else {
segdp = &gdt[seg >> 3];
base = ((u32_t) segdp->base_low << 0)
| ((u32_t) segdp->base_middle << 16)
| ((u32_t) segdp->base_high << 24);
}
return base;
}
/*===========================================================================*
* phys2seg *
*===========================================================================*/
PUBLIC void phys2seg(seg, off, phys)
u16_t *seg;
vir_bytes *off;
phys_bytes phys;
{
/* 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.
*/
#if _WORD_SIZE == 2
if (! machine.prot) {
*seg = phys / HCLICK_SIZE;
*off = phys % HCLICK_SIZE;
} else {
unsigned bank = phys >> 16;
unsigned index = bank - 0xA + A_INDEX;
init_dataseg(&gdt[index], (phys_bytes) bank << 16, 0, TASK_PRIVILEGE);
*seg = (index * 0x08) | TASK_PRIVILEGE;
*off = phys & 0xFFFF;
}
#else
*seg = FLAT_DS_SELECTOR;
*off = phys;
#endif
}
/*===========================================================================*
@ -317,30 +285,13 @@ unsigned dpl_type;
idp->offset_low = offset;
idp->selector = CS_SELECTOR;
idp->p_dpl_type = dpl_type;
#if _WORD_SIZE == 4
idp->offset_high = offset >> OFFSET_HIGH_SHIFT;
#endif
}
/*===========================================================================*
* enable_iop *
*===========================================================================*/
PUBLIC void enable_iop(pp)
struct proc *pp;
{
/* Allow a user process to use I/O instructions. Change the I/O Permission
* Level bits in the psw. These specify least-privileged Current Permission
* Level allowed to execute I/O instructions. Users and servers have CPL 3.
* You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1.
*/
pp->p_reg.psw |= 0x3000;
}
/*===========================================================================*
* alloc_segments *
*===========================================================================*/
PUBLIC void alloc_segments(rp)
register struct proc *rp;
PUBLIC void alloc_segments(register struct proc *rp)
{
/* This is called at system initialization from main() and by do_newmap().
* The code has a separate function because of all hardware-dependencies.
@ -350,7 +301,6 @@ register struct proc *rp;
phys_bytes data_bytes;
int privilege;
if (machine.prot) {
data_bytes = (phys_bytes) (rp->p_memmap[S].mem_vir +
rp->p_memmap[S].mem_len) << CLICK_SHIFT;
if (rp->p_memmap[T].mem_len == 0)
@ -358,25 +308,17 @@ register struct proc *rp;
else
code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
privilege = (iskernelp(rp)) ? TASK_PRIVILEGE : USER_PRIVILEGE;
init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
init_codeseg(&rp->p_seg.p_ldt[CS_LDT_INDEX],
(phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT,
code_bytes, privilege);
init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
init_dataseg(&rp->p_seg.p_ldt[DS_LDT_INDEX],
(phys_bytes) rp->p_memmap[D].mem_phys << CLICK_SHIFT,
data_bytes, privilege);
rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
#if _WORD_SIZE == 4
rp->p_reg.gs =
rp->p_reg.fs =
#endif
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
} else {
rp->p_reg.cs = click_to_hclick(rp->p_memmap[T].mem_phys);
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = click_to_hclick(rp->p_memmap[D].mem_phys);
}
}

72
kernel/arch/i386/proto.h Normal file
View file

@ -0,0 +1,72 @@
#ifndef _I386_PROTO_H
#define _I386_PROTO_H
/* Hardware interrupt handlers. */
_PROTOTYPE( void hwint00, (void) );
_PROTOTYPE( void hwint01, (void) );
_PROTOTYPE( void hwint02, (void) );
_PROTOTYPE( void hwint03, (void) );
_PROTOTYPE( void hwint04, (void) );
_PROTOTYPE( void hwint05, (void) );
_PROTOTYPE( void hwint06, (void) );
_PROTOTYPE( void hwint07, (void) );
_PROTOTYPE( void hwint08, (void) );
_PROTOTYPE( void hwint09, (void) );
_PROTOTYPE( void hwint10, (void) );
_PROTOTYPE( void hwint11, (void) );
_PROTOTYPE( void hwint12, (void) );
_PROTOTYPE( void hwint13, (void) );
_PROTOTYPE( void hwint14, (void) );
_PROTOTYPE( void hwint15, (void) );
/* Exception handlers (real or protected mode), in numerical order. */
void _PROTOTYPE( int00, (void) ), _PROTOTYPE( divide_error, (void) );
void _PROTOTYPE( int01, (void) ), _PROTOTYPE( single_step_exception, (void) );
void _PROTOTYPE( int02, (void) ), _PROTOTYPE( nmi, (void) );
void _PROTOTYPE( int03, (void) ), _PROTOTYPE( breakpoint_exception, (void) );
void _PROTOTYPE( int04, (void) ), _PROTOTYPE( overflow, (void) );
void _PROTOTYPE( int05, (void) ), _PROTOTYPE( bounds_check, (void) );
void _PROTOTYPE( int06, (void) ), _PROTOTYPE( inval_opcode, (void) );
void _PROTOTYPE( int07, (void) ), _PROTOTYPE( copr_not_available, (void) );
void _PROTOTYPE( double_fault, (void) );
void _PROTOTYPE( copr_seg_overrun, (void) );
void _PROTOTYPE( inval_tss, (void) );
void _PROTOTYPE( segment_not_present, (void) );
void _PROTOTYPE( stack_exception, (void) );
void _PROTOTYPE( general_protection, (void) );
void _PROTOTYPE( page_fault, (void) );
void _PROTOTYPE( copr_error, (void) );
/* Software interrupt handlers, in numerical order. */
_PROTOTYPE( void trp, (void) );
_PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) );
_PROTOTYPE( void level0_call, (void) );
/* klib386.s */
_PROTOTYPE( void level0, (void (*func)(void)) );
_PROTOTYPE( void monitor, (void) );
_PROTOTYPE( void reset, (void) );
_PROTOTYPE( void int86, (void) );
_PROTOTYPE( unsigned long read_cr0, (void) );
_PROTOTYPE( void write_cr0, (unsigned long value) );
_PROTOTYPE( void write_cr3, (unsigned long value) );
_PROTOTYPE( unsigned long read_cpu_flags, (void) );
_PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) );
/* protect.c */
_PROTOTYPE( void prot_init, (void) );
_PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
vir_bytes size, int privilege) );
_PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
vir_bytes size, int privilege) );
_PROTOTYPE( void enable_iop, (struct proc *pp) );
/* functions defined in architecture-independent kernel source. */
#include "../../proto.h"
#endif

View file

@ -3,13 +3,9 @@ W = _WORD_SIZE ! Machine word size.
! Offsets in struct proc. They MUST match proc.h.
P_STACKBASE = 0
#if _WORD_SIZE == 2
ESREG = P_STACKBASE
#else
GSREG = P_STACKBASE
FSREG = GSREG + 2 ! 386 introduces FS and GS segments
ESREG = FSREG + 2
#endif
DSREG = ESREG + 2
DIREG = DSREG + 2
SIREG = DIREG + W
@ -28,9 +24,4 @@ SSREG = SPREG + W
P_STACKTOP = SSREG + W
P_LDT_SEL = P_STACKTOP
P_LDT = P_LDT_SEL + W
#if _WORD_SIZE == 2
Msize = 12 ! size of a message in 16-bit words
#else
Msize = 9 ! size of a message in 32-bit words
#endif

102
kernel/arch/i386/system.c Normal file
View file

@ -0,0 +1,102 @@
/* system dependent functions for use inside the whole kernel. */
#include "../../kernel.h"
#include <unistd.h>
#include <ibm/cmos.h>
#include <ibm/bios.h>
#include <minix/portio.h>
#include "proto.h"
PUBLIC void arch_shutdown(int how)
{
/* Mask all interrupts, including the clock. */
outb( INT_CTLMASK, ~0);
if(how != RBT_RESET) {
/* return to boot monitor */
outb( INT_CTLMASK, 0);
outb( INT2_CTLMASK, 0);
/* Return to the boot monitor. Set
* the program if not already done.
*/
if (how != RBT_MONITOR)
phys_copy(vir2phys(""), kinfo.params_base, 1);
level0(monitor);
} else {
/* Reset the system by forcing a processor shutdown. First stop
* the BIOS memory test by setting a soft reset flag.
*/
u16_t magic = STOP_MEM_CHECK;
phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR,
SOFT_RESET_FLAG_SIZE);
level0(reset);
}
}
PUBLIC void system_init(void)
{
prot_init();
}
#define COM1_BASE 0x3F8
#define COM1_THR (COM1_BASE + 0)
#define LSR_THRE 0x20
#define COM1_LSR (COM1_BASE + 5)
PUBLIC void ser_putc(char c)
{
int i;
int lsr, thr;
lsr= COM1_LSR;
thr= COM1_THR;
for (i= 0; i<100000; i++)
{
if (inb( lsr) & LSR_THRE)
break;
}
outb( thr, c);
}
#if SPROFILE
PUBLIC int arch_init_profile_clock(u32_t freq)
{
int r;
/* Set CMOS timer frequency. */
outb(RTC_INDEX, RTC_REG_A);
outb(RTC_IO, RTC_A_DV_OK | freq);
/* Enable CMOS timer interrupts. */
outb(RTC_INDEX, RTC_REG_B);
r = inb(RTC_IO);
outb(RTC_INDEX, RTC_REG_B);
outb(RTC_IO, r | RTC_B_PIE);
/* Mandatory read of CMOS register to enable timer interrupts. */
outb(RTC_INDEX, RTC_REG_C);
inb(RTC_IO);
return CMOS_CLOCK_IRQ;
}
PUBLIC void arch_stop_profile_clock(void)
{
int r;
/* Disable CMOS timer interrupts. */
outb(RTC_INDEX, RTC_REG_B);
r = inb(RTC_IO);
outb(RTC_INDEX, RTC_REG_B);
outb(RTC_IO, r & !RTC_B_PIE);
}
PUBLIC void arch_ack_profile_clock(void)
{
/* Mandatory read of CMOS register to re-enable timer interrupts. */
outb(RTC_INDEX, RTC_REG_C);
inb(RTC_IO);
}
#endif

View file

@ -6,6 +6,7 @@
* CLOCK task thus is hidden from the outside world.
*
* Changes:
* Aug 18, 2006 removed direct hardware access etc, MinixPPC (Ingmar Alting)
* Oct 08, 2005 reordering and comment editing (A. S. Woodhull)
* Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder)
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
@ -34,22 +35,13 @@
#include <signal.h>
#include <minix/com.h>
/* Function prototype for PRIVATE functions. */
/* Function prototype for PRIVATE functions.
*/
FORWARD _PROTOTYPE( void init_clock, (void) );
FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) );
FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) );
FORWARD _PROTOTYPE( void load_update, (void));
/* Clock parameters. */
#define COUNTER_FREQ (2*TIMER_FREQ) /* counter frequency using square wave */
#define LATCH_COUNT 0x00 /* cc00xxxx, c = channel, x = any */
#define SQUARE_WAVE 0x36 /* ccaammmb, a = access, m = mode, b = BCD */
/* 11x11, 11 = LSB then MSB, x11 = sq wave */
#define TIMER_COUNT ((unsigned) (TIMER_FREQ/HZ)) /* initial value for counter*/
#define TIMER_FREQ 1193182L /* clock frequency for timer in PC and AT */
#define CLOCK_ACK_BIT 0x80 /* PS/2 clock interrupt acknowledge bit */
/* The CLOCK's timers queue. The functions in <timers.h> operate on this.
* Each system process possesses a single synchronous alarm timer. If other
* kernel parts want to use additional timers, they must declare their own
@ -57,11 +49,12 @@ FORWARD _PROTOTYPE( void load_update, (void));
* via (re)set_timer().
* When a timer expires its watchdog function is run by the CLOCK task.
*/
PRIVATE timer_t *clock_timers; /* queue of CLOCK timers */
PRIVATE clock_t next_timeout; /* realtime that next timer expires */
PRIVATE timer_t *clock_timers; /* queue of CLOCK timers */
PRIVATE clock_t next_timeout; /* realtime that next timer expires */
/* The time is incremented by the interrupt handler on each clock tick. */
PRIVATE clock_t realtime; /* real time clock */
/* The time is incremented by the interrupt handler on each clock tick.
*/
PRIVATE clock_t realtime = 0; /* real time clock */
PRIVATE irq_hook_t clock_hook; /* interrupt handler hook */
/*===========================================================================*
@ -71,25 +64,25 @@ PUBLIC void clock_task()
{
/* Main program of clock task. If the call is not HARD_INT it is an error.
*/
message m; /* message buffer for both input and output */
int result; /* result returned by the handler */
init_clock(); /* initialize clock task */
message m; /* message buffer for both input and output */
int result; /* result returned by the handler */
init_clock(); /* initialize clock task */
/* Main loop of the clock task. Get work, process it. Never reply. */
while (TRUE) {
while(TRUE) {
/* Go get a message. */
result = receive(ANY, &m);
/* Go get a message. */
receive(ANY, &m);
/* Handle the request. Only clock ticks are expected. */
switch (m.m_type) {
case HARD_INT:
result = do_clocktick(&m); /* handle clock tick */
break;
default: /* illegal request type */
kprintf("CLOCK: illegal request %d from %d.\n", m.m_type,m.m_source);
}
/* Handle the request. Only clock ticks are expected. */
switch (m.m_type) {
case HARD_INT:
result = do_clocktick(&m); /* handle clock tick */
break;
default: /* illegal request type */
kprintf("CLOCK: illegal request %d from %d.\n",
m.m_type, m.m_source);
}
}
}
@ -102,7 +95,7 @@ message *m_ptr; /* pointer to request message */
/* Despite its name, this routine is not called on every clock tick. It
* is called on those clock ticks when a lot of work needs to be done.
*/
/* A process used up a full quantum. The interrupt handler stored this
* process in 'prev_ptr'. First make sure that the process is not on the
* scheduling queues. Then announce the process ready again. Since it has
@ -110,15 +103,16 @@ message *m_ptr; /* pointer to request message */
* place in the queues. As a side-effect a new process will be scheduled.
*/
if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) {
lock_dequeue(prev_ptr); /* take it off the queues */
if(prev_ptr->p_rts_flags == 0) /* if it was runnable .. */
lock_dequeue(prev_ptr); /* take it off the queues */
lock_enqueue(prev_ptr); /* and reinsert it again */
}
/* Check if a clock timer expired and run its watchdog function. */
if (next_timeout <= realtime) {
tmrs_exptimers(&clock_timers, realtime, NULL);
next_timeout = clock_timers == NULL ?
TMR_NEVER : clock_timers->tmr_exp_time;
if (next_timeout <= realtime) {
tmrs_exptimers(&clock_timers, realtime, NULL);
next_timeout = (clock_timers == NULL) ?
TMR_NEVER : clock_timers->tmr_exp_time;
}
/* Inhibit sending a reply. */
@ -130,33 +124,25 @@ message *m_ptr; /* pointer to request message */
*===========================================================================*/
PRIVATE void init_clock()
{
/* First of all init the clock system.
*
* Here the (a) clock is set to produce a interrupt at
* every 1/60 second (ea. 60Hz).
*
* Running right away.
*/
arch_init_clock(); /* architecture-dependent initialization. */
/* Initialize the CLOCK's interrupt hook. */
clock_hook.proc_nr_e = CLOCK;
/* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz, and register
* the CLOCK task's interrupt handler to be run on every clock tick.
*/
outb(TIMER_MODE, SQUARE_WAVE); /* set timer to run continuously */
outb(TIMER0, TIMER_COUNT); /* load timer low byte */
outb(TIMER0, TIMER_COUNT >> 8); /* load timer high byte */
put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler);
enable_irq(&clock_hook); /* ready for clock interrupts */
/* Set a watchdog timer to periodically balance the scheduling queues. */
balance_queues(NULL); /* side-effect sets new timer */
}
/*===========================================================================*
* clock_stop *
*===========================================================================*/
PUBLIC void clock_stop()
{
/* Reset the clock to the BIOS rate. (For rebooting.) */
outb(TIMER_MODE, 0x36);
outb(TIMER0, 0);
outb(TIMER0, 0);
}
/*===========================================================================*
* clock_handler *
*===========================================================================*/
@ -189,9 +175,6 @@ irq_hook_t *hook;
*/
register unsigned ticks;
/* Acknowledge the PS/2 clock interrupt. */
if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
/* Get number of ticks and update realtime. */
ticks = lost_ticks + 1;
lost_ticks = 0;
@ -202,6 +185,7 @@ irq_hook_t *hook;
* process is running, charge the billable process for system time as well.
* Thus the unbillable process' user time is the billable user's system time.
*/
proc_ptr->p_user_time += ticks;
if (priv(proc_ptr)->s_flags & PREEMPTIBLE) {
proc_ptr->p_ticks_left -= ticks;
@ -213,7 +197,7 @@ irq_hook_t *hook;
/* Update load average. */
load_update();
/* Check if do_clocktick() must be called. Done for alarms and scheduling.
* Some processes, such as the kernel tasks, cannot be preempted.
*/
@ -227,9 +211,9 @@ irq_hook_t *hook;
/*===========================================================================*
* get_uptime *
*===========================================================================*/
PUBLIC clock_t get_uptime()
PUBLIC clock_t get_uptime(void)
{
/* Get and return the current clock uptime in ticks. */
/* Get and return the current clock uptime in ticks. */
return(realtime);
}
@ -263,25 +247,6 @@ struct timer *tp; /* pointer to timer structure */
TMR_NEVER : clock_timers->tmr_exp_time;
}
/*===========================================================================*
* read_clock *
*===========================================================================*/
PUBLIC unsigned long read_clock()
{
/* Read the counter of channel 0 of the 8253A timer. This counter counts
* down at a rate of TIMER_FREQ and restarts at TIMER_COUNT-1 when it
* reaches zero. A hardware interrupt (clock tick) occurs when the counter
* gets to zero and restarts its cycle.
*/
unsigned count;
outb(TIMER_MODE, LATCH_COUNT);
count = inb(TIMER0);
count |= (inb(TIMER0) << 8);
return count;
}
/*===========================================================================*
* load_update *
*===========================================================================*/
@ -314,3 +279,5 @@ PRIVATE void load_update(void)
kloadinfo.last_clock = realtime;
}

View file

@ -72,6 +72,8 @@
/* How many bytes for the kernel stack. Space allocated in mpx.s. */
#define K_STACK_BYTES 1024
#define K_PARAM_SIZE 512
/* This section allows to enable kernel debugging and timing functionality.
* For normal operation all options should be disabled.
*/

View file

@ -2,20 +2,11 @@
#ifndef CONST_H
#define CONST_H
#include <ibm/interrupt.h> /* interrupt numbers and hardware vectors */
#include <ibm/ports.h> /* port addresses and magic numbers */
#include <ibm/bios.h> /* BIOS addresses, sizes and magic numbers */
#include <ibm/cpu.h> /* BIOS addresses, sizes and magic numbers */
#include <minix/config.h>
#include <minix/bitmap.h>
#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))
/* Map a process number to a privilege structure id. */
#define s_nr_to_id(n) (NR_TASKS + (n) + 1)
@ -46,41 +37,27 @@
( MAP_CHUNK(map.chunk,bit) &= ~(1 << CHUNK_OFFSET(bit) )
#define NR_SYS_CHUNKS BITMAP_CHUNKS(NR_SYS_PROCS)
#if (CHIP == INTEL)
/* Program stack words and masks. */
#define INIT_PSW 0x0200 /* initial psw */
#define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */
#define TRACEBIT 0x0100 /* OR this with psw in proc[] for tracing */
#define SETPSW(rp, new) /* permits only certain bits to be set */ \
((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
#define IF_MASK 0x00000200
#define IOPL_MASK 0x003000
#if DEBUG_LOCK_CHECK
#define reallock(c, v) { if (!(read_cpu_flags() & X86_FLAG_I)) { kinfo.relocking++; } else { intr_disable(); } }
#define reallock(c, v) { if(intr_disabled()) { kinfo.relocking++; } else { intr_disable(); } }
#else
#define reallock(c, v) intr_disable()
#define reallock(c, v) intr_disable()
#endif
#define realunlock(c) intr_enable()
#define realunlock(c) intr_enable()
#if DEBUG_TIME_LOCKS
#define lock(c, v) do { reallock(c, v); locktimestart(c, v); } while(0)
#define unlock(c) do { locktimeend(c); realunlock(c); } while(0)
#else
/* 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) reallock(c, v)
#define unlock(c) realunlock(c)
#define lock(c, v) reallock(c, v)
#define unlock(c) realunlock(c)
#endif
/* 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
#endif /* (CHIP == INTEL) */
#if (CHIP == M68000)
/* M68000 specific constants go here. */
#endif /* (CHIP == M68000) */
/* args to intr_init() */
#define INTS_ORIG 0 /* restore interrupts */
#define INTS_MINIX 1 /* initialize interrupts for minix */
#endif /* CONST_H */

View file

@ -53,22 +53,4 @@ _PROTOTYPE( void timer_end, (int cat) );
#define locktimeend(c)
#endif /* DEBUG_TIME_LOCKS */
/* 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 { reallock(c, v); locktimestart(c, v); } while(0)
# undef unlock
# define unlock(c) do { locktimeend(c); realunlock(c); } while(0)
#endif
#endif /* DEBUG_H */

View file

@ -12,6 +12,7 @@
#endif
#include <minix/config.h>
#include <archtypes.h>
#include "config.h"
/* Variables relating to shutting down MINIX. */
@ -34,11 +35,9 @@ EXTERN struct proc *bill_ptr; /* process to bill for clock ticks */
EXTERN char k_reenter; /* kernel reentry count (entry count less 1) */
EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */
#if (CHIP == INTEL)
/* Interrupt related variables. */
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; /* map of all in-use irq's */
@ -61,10 +60,5 @@ extern char *t_stack[]; /* task stack space */
extern struct segdesc_s gdt[]; /* global descriptor table */
EXTERN _PROTOTYPE( void (*level0_func), (void) );
#endif /* (CHIP == INTEL) */
#if (CHIP == M68000)
/* M68000 specific variables go here. */
#endif
#endif /* GLO_H */

View file

@ -1,193 +0,0 @@
/* This file contains routines for initializing the 8259 interrupt controller:
* put_irq_handler: register an interrupt handler
* rm_irq_handler: deregister an interrupt handler
* intr_handle: handle a hardware interrupt
* intr_init: initialize the interrupt controller(s)
*/
#include "kernel.h"
#include "proc.h"
#include <minix/com.h>
#define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
#define ICW1_PC 0x13 /* edge triggered, no cascade, need ICW4 */
#define ICW1_PS 0x19 /* level triggered, cascade, need ICW4 */
#define ICW4_AT_SLAVE 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
#define ICW4_AT_MASTER 0x05 /* not SFNM, not buffered, normal EOI, 8086 */
#define ICW4_PC_SLAVE 0x09 /* not SFNM, buffered, normal EOI, 8086 */
#define ICW4_PC_MASTER 0x0D /* not SFNM, buffered, normal EOI, 8086 */
#if _WORD_SIZE == 2
typedef _PROTOTYPE( void (*vecaddr_t), (void) );
FORWARD _PROTOTYPE( void set_vec, (int vec_nr, vecaddr_t addr) );
PRIVATE vecaddr_t int_vec[] = {
int00, int01, int02, int03, int04, int05, int06, int07,
};
PRIVATE vecaddr_t irq_vec[] = {
hwint00, hwint01, hwint02, hwint03, hwint04, hwint05, hwint06, hwint07,
hwint08, hwint09, hwint10, hwint11, hwint12, hwint13, hwint14, hwint15,
};
#else
#define set_vec(nr, addr) ((void)0)
#endif
/*===========================================================================*
* intr_init *
*===========================================================================*/
PUBLIC void intr_init(mine)
int mine;
{
/* Initialize the 8259s, finishing with all interrupts disabled. This is
* only done in protected mode, in real mode we don't touch the 8259s, but
* use the BIOS locations instead. The flag "mine" is set if the 8259s are
* to be programmed for MINIX, or to be reset to what the BIOS expects.
*/
int i;
intr_disable();
if (machine.prot) {
/* 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
* has just one controller, because it must run in real mode.)
*/
outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
/* ICW2 for master */
outb(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
outb(INT_CTLMASK, ICW4_AT_MASTER);
outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
/* ICW2 for slave */
outb(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */
outb(INT2_CTLMASK, ICW4_AT_SLAVE);
outb(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */
/* Copy the BIOS vectors from the BIOS to the Minix location, so we
* can still make BIOS calls without reprogramming the i8259s.
*/
#if IRQ0_VECTOR != BIOS_IRQ0_VEC
phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L);
#endif
#if IRQ8_VECTOR != BIOS_IRQ8_VEC
phys_copy(BIOS_VECTOR(8) * 4L, VECTOR(8) * 4L, 8 * 4L);
#endif
} else {
/* Use the BIOS interrupt vectors in real mode. We only reprogram the
* exceptions here, the interrupt vectors are reprogrammed on demand.
* SYS_VECTOR is the Minix system call for message passing.
*/
for (i = 0; i < 8; i++) set_vec(i, int_vec[i]);
set_vec(SYS_VECTOR, s_call);
}
}
/*===========================================================================*
* put_irq_handler *
*===========================================================================*/
PUBLIC void put_irq_handler(hook, irq, handler)
irq_hook_t *hook;
int irq;
irq_handler_t handler;
{
/* Register an interrupt handler. */
int id;
irq_hook_t **line;
if (irq < 0 || irq >= NR_IRQ_VECTORS)
panic("invalid call to put_irq_handler", irq);
line = &irq_handlers[irq];
id = 1;
while (*line != NULL) {
if (hook == *line) return; /* extra initialization */
line = &(*line)->next;
id <<= 1;
}
if (id == 0) panic("Too many handlers for irq", irq);
hook->next = NULL;
hook->handler = handler;
hook->irq = irq;
hook->id = id;
*line = hook;
irq_use |= 1 << irq;
}
/*===========================================================================*
* rm_irq_handler *
*===========================================================================*/
PUBLIC void rm_irq_handler(hook)
irq_hook_t *hook;
{
/* Unregister an interrupt handler. */
int irq = hook->irq;
int id = hook->id;
irq_hook_t **line;
if (irq < 0 || irq >= NR_IRQ_VECTORS)
panic("invalid call to rm_irq_handler", irq);
line = &irq_handlers[irq];
while (*line != NULL) {
if ((*line)->id == id) {
(*line) = (*line)->next;
if (! irq_handlers[irq]) irq_use &= ~(1 << irq);
return;
}
line = &(*line)->next;
}
/* When the handler is not found, normally return here. */
}
/*===========================================================================*
* intr_handle *
*===========================================================================*/
PUBLIC void intr_handle(hook)
irq_hook_t *hook;
{
/* Call the interrupt handlers for an interrupt with the given hook list.
* The assembly part of the handler has already masked the IRQ, reenabled the
* controller(s) and enabled interrupts.
*/
/* Call list of handlers for an IRQ. */
while (hook != NULL) {
/* For each handler in the list, mark it active by setting its ID bit,
* call the function, and unmark it if the function returns true.
*/
irq_actids[hook->irq] |= hook->id;
if ((*hook->handler)(hook)) irq_actids[hook->irq] &= ~hook->id;
hook = hook->next;
}
/* The assembly code will now disable interrupts, unmask the IRQ if and only
* if all active ID bits are cleared, and restart a process.
*/
}
#if _WORD_SIZE == 2
/*===========================================================================*
* set_vec *
*===========================================================================*/
PRIVATE void set_vec(vec_nr, addr)
int vec_nr; /* which vector */
vecaddr_t addr; /* where to start */
{
/* Set up a real mode interrupt vector. */
u16_t vec[2];
/* Build the vector in the array 'vec'. */
vec[0] = (u16_t) addr;
vec[1] = (u16_t) physb_to_hclick(code_base);
/* Copy the vector into place. */
phys_copy(vir2phys(vec), vec_nr * 4L, 4L);
}
#endif /* _WORD_SIZE == 2 */

9
kernel/interface.h Normal file
View file

@ -0,0 +1,9 @@
/* minix/kernel/interface.h - All interfaces the kernel needs. */
#ifndef _KERNEL_IF_H_
#define _KERNEL_IF_H_
#include <minix/type.h>
#include <archtypes.h>
#endif /* #ifndef _KERNEL_IF_H_ */

141
kernel/interrupt.c Normal file
View file

@ -0,0 +1,141 @@
/*
* The Minix hardware interrupt system.
*
* This file contains routines for managing the interrupt
* controller.
*
* put_irq_handler: register an interrupt handler.
* rm_irq_handler: deregister an interrupt handler.
* intr_handle: handle a hardware interrupt.
* called by the system dependent part when an
* external interrupt occures.
* enable_irq: enable hook for IRQ.
* disable_irq: disable hook for IRQ.
*/
#include "kernel.h"
#include "proc.h"
#include <minix/com.h>
#include <archconst.h>
/* number of lists of IRQ hooks, one list per supported line. */
PUBLIC irq_hook_t* irq_handlers[NR_IRQ_VECTORS] = {0};
/*===========================================================================*
* put_irq_handler *
*===========================================================================*/
/* Register an interrupt handler. */
PUBLIC void put_irq_handler( irq_hook_t* hook, int irq, irq_handler_t handler)
{
int id;
irq_hook_t **line;
if( irq < 0 || irq >= NR_IRQ_VECTORS )
panic("invalid call to put_irq_handler", irq);
line = &irq_handlers[irq];
id = 1;
while ( *line != NULL ) {
if(hook == *line) return; /* extra initialization */
line = &(*line)->next;
id <<= 1; /* max 32 hooks for one line. */
}
if(id == 0)
panic("Too many handlers for irq", irq);
hook->next = NULL;
hook->handler = handler;
hook->irq = irq;
hook->id = id;
*line = hook;
irq_use |= 1 << irq; /* this does not work for irq >= 32 */
/* And as last enable the irq at the hardware.
*
* Internal this activates the line or source of the given interrupt.
*/
intr_unmask(hook);
}
/*===========================================================================*
* rm_irq_handler *
*===========================================================================*/
/* Unregister an interrupt handler. */
PUBLIC void rm_irq_handler( irq_hook_t* hook ) {
int irq = hook->irq;
int id = hook->id;
irq_hook_t **line;
if( irq < 0 || irq >= NR_IRQ_VECTORS )
panic("invalid call to rm_irq_handler", irq);
/* disable the irq. */
intr_mask(hook);
/* remove the hook. */
line = &irq_handlers[irq];
while( (*line) != NULL ) {
if((*line)->id == id) {
(*line) = (*line)->next;
if(!irq_handlers[irq])
irq_use &= ~(1 << irq);
return;
}
line = &(*line)->next;
}
/* When the handler is not found, normally return here. */
}
/*===========================================================================*
* intr_handle *
*===========================================================================*/
PUBLIC void intr_handle(irq_hook_t *hook)
{
/* Call the interrupt handlers for an interrupt with the given hook list.
* The assembly part of the handler has already masked the IRQ, reenabled the
* controller(s) and enabled interrupts.
*/
/* Call list of handlers for an IRQ. */
while( hook != NULL ) {
/* For each handler in the list, mark it active by setting its ID bit,
* call the function, and unmark it if the function returns true.
*/
irq_actids[hook->irq] |= hook->id;
/* Call the hooked function. */
if( (*hook->handler)(hook) )
irq_actids[hook->irq] &= ~hook->id;
/* Next hooked function. */
hook = hook->next;
}
/* The assembly code will now disable interrupts, unmask the IRQ if and only
* if all active ID bits are cleared, and restart a process.
*/
}
/* Enable/Disable a interrupt line. */
PUBLIC void enable_irq(hook)
irq_hook_t* hook;
{
if((irq_actids[hook->irq] &= ~hook->id) == 0) {
intr_unmask(hook);
return;
}
}
/* Return true if the interrupt was enabled before call. */
PUBLIC int disable_irq(hook)
irq_hook_t* hook;
{
if(irq_actids[hook->irq] & hook->id) /* already disabled */
return 0;
irq_actids[hook->irq] |= hook->id;
intr_mask(hook);
return TRUE;
}

View file

@ -18,10 +18,6 @@
#include <timers.h> /* watchdog timer management */
#include <errno.h> /* return codes and error numbers */
#if (CHIP == INTEL)
#include <ibm/portio.h> /* device I/O and toggle interrupts */
#endif
/* Important kernel header files. */
#include "config.h" /* configuration, MUST be first */
#include "const.h" /* constants, MUST be second */

View file

@ -1,9 +0,0 @@
#
! Chooses between the 8086 and 386 versions of the low level kernel code.
#include <minix/config.h>
#if _WORD_SIZE == 2
#include "klib88.s"
#else
#include "klib386.s"
#endif

View file

View file

@ -1,71 +0,0 @@
/*
* printf for the kernel
*
* Changes:
* Dec 10, 2004 kernel printing to circular buffer (Jorrit N. Herder)
*
* 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 output driver.
* Instead, the kernel accumulates characters in a buffer and notifies the
* output driver when a new message is ready.
*/
#include "kernel.h"
#include "proc.h"
#include <signal.h>
#define printf kprintf
#include "../lib/sysutil/kprintf.c"
#define END_OF_KMESS 0
FORWARD _PROTOTYPE( void ser_putc, (char c));
/*===========================================================================*
* kputc *
*===========================================================================*/
PUBLIC void kputc(c)
int c; /* character to append */
{
/* Accumulate a single character for a kernel message. Send a notification
* to the output driver if an END_OF_KMESS is encountered.
*/
if (c != END_OF_KMESS) {
if (do_serial_debug)
ser_putc(c);
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 {
int p, outprocs[] = OUTPUT_PROCS_ARRAY;
for(p = 0; outprocs[p] != NONE; p++) {
if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
send_sig(outprocs[p], SIGKMESS);
}
}
}
}
#define COM1_BASE 0x3F8
#define COM1_THR (COM1_BASE + 0)
#define LSR_THRE 0x20
#define COM1_LSR (COM1_BASE + 5)
PRIVATE void ser_putc(char c)
{
int i;
int lsr, thr;
return;
lsr= COM1_LSR;
thr= COM1_THR;
for (i= 0; i<100000; i++)
{
if (inb(lsr) & LSR_THRE)
break;
}
outb(thr, c);
}

View file

@ -7,10 +7,6 @@
* The entries into this file are:
* main: MINIX main program
* prepare_shutdown: prepare to take MINIX down
*
* Changes:
* Nov 24, 2004 simplified main() with system image (Jorrit N. Herder)
* Aug 20, 2004 new prepare_shutdown() and shutdown() (Jorrit N. Herder)
*/
#include "kernel.h"
#include <signal.h>
@ -24,7 +20,7 @@
/* Prototype declarations for PRIVATE functions. */
FORWARD _PROTOTYPE( void announce, (void));
FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
FORWARD _PROTOTYPE( void shutdown, (timer_t *));
/*===========================================================================*
* main *
@ -42,9 +38,6 @@ PUBLIC void main()
reg_t ktsb; /* kernel task stack base */
struct exec e_hdr; /* for a copy of an a.out header */
/* Initialize the interrupt controller. */
intr_init(1);
/* Clear the process table. Anounce each slot as empty and set up mappings
* for proc_addr() and proc_nr() macros. Do the same for the table with
* privilege structures for the system processes.
@ -168,19 +161,6 @@ PUBLIC void main()
alloc_segments(rp);
}
#if ENABLE_BOOTDEV
/* Expect an image of the boot device to be loaded into memory as well.
* The boot device is the last module that is loaded into memory, and,
* for example, can contain the root FS (useful for embedded systems).
*/
hdrindex ++;
phys_copy(aout + hdrindex * A_MINHDR,vir2phys(&e_hdr),(phys_bytes) A_MINHDR);
if (e_hdr.a_flags & A_IMG) {
kinfo.bootdev_base = e_hdr.a_syms;
kinfo.bootdev_size = e_hdr.a_data;
}
#endif
#if SPROFILE
sprofiling = 0; /* we're not profiling until instructed to */
#endif /* SPROFILE */
@ -205,11 +185,6 @@ PRIVATE void announce(void)
kprintf("\nMINIX %s.%s. "
"Copyright 2006, Vrije Universiteit, Amsterdam, The Netherlands\n",
OS_RELEASE, OS_VERSION);
#if (CHIP == INTEL)
/* Real mode, or 16/32-bit protected mode? */
kprintf("Executing in %s mode.\n\n",
machine.prot ? "32-bit protected" : "real");
#endif
}
/*===========================================================================*
@ -246,6 +221,7 @@ int how;
tmr_arg(&shutdown_timer)->ta_int = how;
set_timer(&shutdown_timer, get_uptime() + HZ, shutdown);
}
/*===========================================================================*
* shutdown *
*===========================================================================*/
@ -256,30 +232,8 @@ timer_t *tp;
* down MINIX. How to shutdown is in the argument: RBT_HALT (return to the
* monitor), RBT_MONITOR (execute given code), RBT_RESET (hard reset).
*/
int how = tmr_arg(tp)->ta_int;
u16_t magic;
/* Now mask all interrupts, including the clock, and stop the clock. */
outb(INT_CTLMASK, ~0);
intr_init(INTS_ORIG);
clock_stop();
if (mon_return && how != RBT_RESET) {
/* Reinitialize the interrupt controllers to the BIOS defaults. */
intr_init(0);
outb(INT_CTLMASK, 0);
outb(INT2_CTLMASK, 0);
/* Return to the boot monitor. Set the program if not already done. */
if (how != RBT_MONITOR) phys_copy(vir2phys(""), kinfo.params_base, 1);
level0(monitor);
}
/* Reset the system by jumping to the reset address (real mode), or by
* forcing a processor shutdown (protected mode). First stop the BIOS
* memory test by setting a soft reset flag.
*/
magic = STOP_MEM_CHECK;
phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR, SOFT_RESET_FLAG_SIZE);
level0(reset);
arch_shutdown(tmr_arg(tp)->ta_int);
}

View file

@ -1,9 +0,0 @@
#
! Chooses between the 8086 and 386 versions of the Minix startup code.
#include <minix/config.h>
#if _WORD_SIZE == 2
#include "mpx88.s"
#else
#include "mpx386.s"
#endif

View file

View file

@ -12,7 +12,6 @@
* Jul 01, 2005 Created. (Jorrit N. Herder)
*/
#include <minix/com.h>
#include "protect.h"
#include "const.h"
#include "type.h"

View file

@ -43,6 +43,7 @@
#include "kernel.h"
#include "proc.h"
#include <signal.h>
#include <minix/portio.h>
/* Scheduling and message passing functions. The functions are available to
* other parts of the kernel through lock_...(). The lock temporarily disables
@ -75,18 +76,10 @@ FORWARD _PROTOTYPE( void pick_proc, (void));
break; \
}
#if (CHIP == INTEL)
#define CopyMess(s,sp,sm,dp,dm) \
cp_mess(proc_addr(s)->p_endpoint, \
(sp)->p_memmap[D].mem_phys, \
(sp)->p_memmap[D].mem_phys, \
(vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm)
#endif /* (CHIP == INTEL) */
#if (CHIP == M68000)
/* M68000 does not have cp_mess() in assembly like INTEL. Declare prototype
* for cp_mess() here and define the function below. Also define CopyMess.
*/
#endif /* (CHIP == M68000) */
/*===========================================================================*
* sys_call *
@ -110,7 +103,7 @@ long bit_map; /* notification event set or flags */
int src_dst;
vir_clicks vlo, vhi; /* virtual clicks containing message to send */
#if 0
#if 1
if (caller_ptr->p_rts_flags & SLOT_FREE)
{
kprintf("called by the dead?!?\n");
@ -392,7 +385,7 @@ unsigned flags; /* system call flags */
xpp = &caller_ptr->p_caller_q;
while (*xpp != NIL_PROC) {
if (src_e == ANY || src_p == proc_nr(*xpp)) {
#if 0
#if 1
if ((*xpp)->p_rts_flags & SLOT_FREE)
{
kprintf("listening to the dead?!?\n");
@ -511,7 +504,7 @@ register struct proc *rp; /* this process is now runnable */
int front; /* add to front or back */
#if DEBUG_SCHED_CHECK
check_runqueues("enqueue");
check_runqueues("enqueue1");
if (rp->p_ready) kprintf("enqueue() already ready process\n");
#endif
@ -538,7 +531,7 @@ register struct proc *rp; /* this process is now runnable */
#if DEBUG_SCHED_CHECK
rp->p_ready = 1;
check_runqueues("enqueue");
check_runqueues("enqueue2");
#endif
}
@ -563,8 +556,9 @@ register struct proc *rp; /* this process is no longer runnable */
}
#if DEBUG_SCHED_CHECK
check_runqueues("dequeue");
if (! rp->p_ready) kprintf("dequeue() already unready process\n");
check_runqueues("dequeue1");
if (! rp->p_ready) kprintf("%s:%d: dequeue() already unready process\n",
f_str, f_line);
#endif
/* Now make sure that the process is not in its ready queue. Remove the
@ -587,7 +581,7 @@ register struct proc *rp; /* this process is no longer runnable */
#if DEBUG_SCHED_CHECK
rp->p_ready = 0;
check_runqueues("dequeue");
check_runqueues("dequeue2");
#endif
}

View file

@ -10,22 +10,12 @@
* struct proc, be sure to change sconst.h to match.
*/
#include <minix/com.h>
#include "protect.h"
#include "const.h"
#include "priv.h"
struct proc {
struct stackframe_s p_reg; /* process' registers saved in stack frame */
#if (CHIP == INTEL)
reg_t p_ldt_sel; /* selector in gdt with ldt base and limit */
struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote segments */
#endif
#if (CHIP == M68000)
/* M68000 specific registers and FPU details go here. */
#endif
struct segframe p_seg; /* segment descriptors */
proc_nr_t p_nr; /* number of this process (for fast access) */
struct priv *p_priv; /* system privileges structure */
short p_rts_flags; /* process is runnable only if zero */

View file

@ -3,7 +3,7 @@
* profiling.
*
* Statistical Profiling:
* The interrupt handler and control functions for the CMOS clock.
* The interrupt handler for profiling clock.
*
* Call Profiling:
* The table used for profiling data and a function to get its size.
@ -20,6 +20,7 @@
#if SPROFILE || CPROFILE
#include <minix/profile.h>
#include <minix/portio.h>
#include "kernel.h"
#include "profile.h"
#include "proc.h"
@ -29,70 +30,50 @@
#if SPROFILE
#include <string.h>
#include <ibm/cmos.h>
/* Function prototype for the CMOS clock handler. */
FORWARD _PROTOTYPE( int cmos_clock_handler, (irq_hook_t *hook) );
/* Function prototype for the profiling clock handler. */
FORWARD _PROTOTYPE( int profile_clock_handler, (irq_hook_t *hook) );
/* A hook for the CMOS clock interrupt handler. */
PRIVATE irq_hook_t cmos_clock_hook;
/* A hook for the profiling clock interrupt handler. */
PRIVATE irq_hook_t profile_clock_hook;
/*===========================================================================*
* init_cmos_clock *
* init_profile_clock *
*===========================================================================*/
PUBLIC void init_cmos_clock(unsigned freq)
PUBLIC void init_profile_clock(u32_t freq)
{
int r;
/* Register interrupt handler for statistical system profiling.
* This uses the CMOS timer.
*/
cmos_clock_hook.proc_nr_e = CLOCK;
put_irq_handler(&cmos_clock_hook, CMOS_CLOCK_IRQ, cmos_clock_handler);
enable_irq(&cmos_clock_hook);
int r, irq;
intr_disable();
/* Set CMOS timer frequency. */
outb(RTC_INDEX, RTC_REG_A);
outb(RTC_IO, RTC_A_DV_OK | freq);
/* Enable CMOS timer interrupts. */
outb(RTC_INDEX, RTC_REG_B);
r = inb(RTC_IO);
outb(RTC_INDEX, RTC_REG_B);
outb(RTC_IO, r | RTC_B_PIE);
/* Mandatory read of CMOS register to enable timer interrupts. */
outb(RTC_INDEX, RTC_REG_C);
inb(RTC_IO);
if((irq = arch_init_profile_clock(freq)) >= 0) {
/* Register interrupt handler for statistical system profiling. */
profile_clock_hook.proc_nr_e = CLOCK;
put_irq_handler(&profile_clock_hook, irq, profile_clock_handler);
enable_irq(&profile_clock_hook);
}
intr_enable();
}
/*===========================================================================*
* cmos_clock_stop *
* profile_clock_stop *
*===========================================================================*/
PUBLIC void stop_cmos_clock()
PUBLIC void stop_profile_clock()
{
int r;
intr_disable();
/* Disable CMOS timer interrupts. */
outb(RTC_INDEX, RTC_REG_B);
r = inb(RTC_IO);
outb(RTC_INDEX, RTC_REG_B);
outb(RTC_IO, r & !RTC_B_PIE);
arch_stop_profile_clock();
intr_enable();
/* Unregister interrupt handler. */
disable_irq(&cmos_clock_hook);
rm_irq_handler(&cmos_clock_hook);
disable_irq(&profile_clock_hook);
rm_irq_handler(&profile_clock_hook);
}
/*===========================================================================*
* cmos_clock_handler *
* profile_clock_handler *
*===========================================================================*/
PRIVATE int cmos_clock_handler(hook)
PRIVATE int profile_clock_handler(hook)
irq_hook_t *hook;
{
/* This executes on every tick of the CMOS timer. */
@ -136,9 +117,8 @@ irq_hook_t *hook;
sprof_info.total_samples++;
/* Mandatory read of CMOS register to re-enable timer interrupts. */
outb(RTC_INDEX, RTC_REG_C);
inb(RTC_IO);
/* Acknowledge interrupt if necessary. */
arch_ack_profile_clock();
return(1); /* reenable interrupts */
}

View file

@ -7,9 +7,6 @@
#if SPROFILE /* statistical profiling */
_PROTOTYPE( void init_cmos_clock, (unsigned freq) );
_PROTOTYPE( void stop_cmos_clock, (void) );
EXTERN int sprofiling; /* whether profiling is running */
EXTERN int sprof_mem_size; /* available user memory for data */
EXTERN struct sprof_info_s sprof_info; /* profiling info for user program */

View file

@ -4,6 +4,7 @@
#define PROTO_H
#include <minix/safecopies.h>
#include <archtypes.h>
/* Struct declarations. */
struct proc;
@ -11,15 +12,14 @@ struct timer;
/* clock.c */
_PROTOTYPE( void clock_task, (void) );
_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) );
/* main.c */
_PROTOTYPE( void main, (void) );
_PROTOTYPE( void prepare_shutdown, (int how) );
_PROTOTYPE( void idle_task, (void) );
/* utility.c */
_PROTOTYPE( int kprintf, (const char *fmt, ...) );
@ -55,115 +55,29 @@ _PROTOTYPE( int virtual_copy, (struct vir_addr *src, struct vir_addr *dst,
vir_bytes bytes) );
#define numap_local(proc_nr, vir_addr, bytes) \
umap_local(proc_addr(proc_nr), D, (vir_addr), (bytes))
_PROTOTYPE( phys_bytes umap_local, (struct proc *rp, int seg,
vir_bytes vir_addr, vir_bytes bytes) );
_PROTOTYPE( phys_bytes umap_remote, (struct proc *rp, int seg,
vir_bytes vir_addr, vir_bytes bytes) );
_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
vir_bytes bytes) );
_PROTOTYPE( phys_bytes umap_grant, (struct proc *, cp_grant_id_t,
vir_bytes));
_PROTOTYPE( phys_bytes umap_verify_grant, (struct proc *, endpoint_t,
cp_grant_id_t, vir_bytes, vir_bytes, int));
_PROTOTYPE( void clear_endpoint, (struct proc *rc) );
_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
vir_bytes bytes));
/* system/do_newmap.c */
_PROTOTYPE( int newmap, (struct proc *rp, struct mem_map *map_ptr) );
#if (CHIP == INTEL)
/* exception.c */
_PROTOTYPE( void exception, (unsigned vec_nr) );
_PROTOTYPE( void stacktrace, (struct proc *) );
/* i8259.c */
_PROTOTYPE( void intr_init, (int mine) );
_PROTOTYPE( void intr_handle, (irq_hook_t *hook) );
/* interrupt.c */
_PROTOTYPE( void intr_handle, (irq_hook_t *hook) );
_PROTOTYPE( void put_irq_handler, (irq_hook_t *hook, int irq,
irq_handler_t handler) );
_PROTOTYPE( void rm_irq_handler, (irq_hook_t *hook) );
irq_handler_t handler) );
_PROTOTYPE( void rm_irq_handler, (irq_hook_t *hook) );
_PROTOTYPE( void enable_irq, (irq_hook_t *hook) );
_PROTOTYPE( int disable_irq, (irq_hook_t *hook) );
/* klib*.s */
_PROTOTYPE( void int86, (void) );
_PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,vir_bytes src_offset,
phys_clicks dst_clicks, vir_bytes dst_offset) );
_PROTOTYPE( void enable_irq, (irq_hook_t *hook) );
_PROTOTYPE( int disable_irq, (irq_hook_t *hook) );
_PROTOTYPE( u16_t mem_rdw, (U16_t segm, vir_bytes offset) );
_PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
phys_bytes count) );
_PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern,
phys_bytes count) );
_PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void reset, (void) );
_PROTOTYPE( void level0, (void (*func)(void)) );
_PROTOTYPE( void monitor, (void) );
_PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low) );
_PROTOTYPE( unsigned long read_cr0, (void) );
_PROTOTYPE( void write_cr0, (unsigned long value) );
_PROTOTYPE( void write_cr3, (unsigned long value) );
_PROTOTYPE( unsigned long read_cpu_flags, (void) );
/* mpx*.s */
_PROTOTYPE( void idle_task, (void) );
_PROTOTYPE( void restart, (void) );
/* The following are never called from C (pure asm procs). */
/* Exception handlers (real or protected mode), in numerical order. */
void _PROTOTYPE( int00, (void) ), _PROTOTYPE( divide_error, (void) );
void _PROTOTYPE( int01, (void) ), _PROTOTYPE( single_step_exception, (void) );
void _PROTOTYPE( int02, (void) ), _PROTOTYPE( nmi, (void) );
void _PROTOTYPE( int03, (void) ), _PROTOTYPE( breakpoint_exception, (void) );
void _PROTOTYPE( int04, (void) ), _PROTOTYPE( overflow, (void) );
void _PROTOTYPE( int05, (void) ), _PROTOTYPE( bounds_check, (void) );
void _PROTOTYPE( int06, (void) ), _PROTOTYPE( inval_opcode, (void) );
void _PROTOTYPE( int07, (void) ), _PROTOTYPE( copr_not_available, (void) );
void _PROTOTYPE( double_fault, (void) );
void _PROTOTYPE( copr_seg_overrun, (void) );
void _PROTOTYPE( inval_tss, (void) );
void _PROTOTYPE( segment_not_present, (void) );
void _PROTOTYPE( stack_exception, (void) );
void _PROTOTYPE( general_protection, (void) );
void _PROTOTYPE( page_fault, (void) );
void _PROTOTYPE( copr_error, (void) );
/* Hardware interrupt handlers. */
_PROTOTYPE( void hwint00, (void) );
_PROTOTYPE( void hwint01, (void) );
_PROTOTYPE( void hwint02, (void) );
_PROTOTYPE( void hwint03, (void) );
_PROTOTYPE( void hwint04, (void) );
_PROTOTYPE( void hwint05, (void) );
_PROTOTYPE( void hwint06, (void) );
_PROTOTYPE( void hwint07, (void) );
_PROTOTYPE( void hwint08, (void) );
_PROTOTYPE( void hwint09, (void) );
_PROTOTYPE( void hwint10, (void) );
_PROTOTYPE( void hwint11, (void) );
_PROTOTYPE( void hwint12, (void) );
_PROTOTYPE( void hwint13, (void) );
_PROTOTYPE( void hwint14, (void) );
_PROTOTYPE( void hwint15, (void) );
/* Software interrupt handlers, in numerical order. */
_PROTOTYPE( void trp, (void) );
_PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) );
_PROTOTYPE( void level0_call, (void) );
/* protect.c */
_PROTOTYPE( void prot_init, (void) );
_PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
vir_bytes size, int privilege) );
_PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
vir_bytes size, int privilege) );
_PROTOTYPE( phys_bytes seg2phys, (U16_t seg) );
_PROTOTYPE( void phys2seg, (u16_t *seg, vir_bytes *off, phys_bytes phys));
_PROTOTYPE( void enable_iop, (struct proc *pp) );
_PROTOTYPE( void alloc_segments, (struct proc *rp) );
/* debug.c */
#if DEBUG_SCHED_CHECK
_PROTOTYPE( void check_runqueues, (char *when) );
#endif
/* system/do_vm.c */
_PROTOTYPE( void vm_map_default, (struct proc *pp) );
@ -172,10 +86,46 @@ _PROTOTYPE( void vm_map_default, (struct proc *pp) );
_PROTOTYPE( int verify_grant, (endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes,
int, vir_bytes, vir_bytes *, endpoint_t *));
#endif /* (CHIP == INTEL) */
#if SPROFILE
/* profile.c */
_PROTOTYPE( void init_profile_clock, (u32_t) );
_PROTOTYPE( void stop_profile_clock, (void) );
#endif
/* functions defined in architecture-dependent files. */
_PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
phys_bytes count) );
_PROTOTYPE( void alloc_segments, (struct proc *rp) );
_PROTOTYPE( void vm_init, (void) );
_PROTOTYPE( void vm_map_range, (u32_t base, u32_t size, u32_t offset) );
_PROTOTYPE( phys_bytes umap_local, (register struct proc *rp, int seg,
vir_bytes vir_addr, vir_bytes bytes));
_PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,
vir_bytes src_offset, phys_clicks dst_clicks, vir_bytes dst_offset));
_PROTOTYPE( phys_bytes umap_remote, (struct proc* rp, int seg,
vir_bytes vir_addr, vir_bytes bytes) );
_PROTOTYPE( phys_bytes seg2phys, (U16_t) );
_PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern,
phys_bytes count) );
_PROTOTYPE( vir_bytes alloc_remote_segment, (u32_t *, segframe_t *,
int, phys_bytes, vir_bytes, int));
_PROTOTYPE( int arch_init_clock, (void) );
_PROTOTYPE( clock_t read_clock, (void) );
_PROTOTYPE( void clock_stop, (void) );
_PROTOTYPE( int intr_init, (int) );
_PROTOTYPE( int intr_disabled, (void) );
_PROTOTYPE( int intr_unmask, (irq_hook_t* hook) );
_PROTOTYPE( int intr_mask, (irq_hook_t* hook) );
_PROTOTYPE( void idle_task, (void) );
_PROTOTYPE( void system_init, (void) );
_PROTOTYPE( void ser_putc, (char) );
_PROTOTYPE( void arch_shutdown, (int) );
_PROTOTYPE( void restart, (void) );
_PROTOTYPE( void idle_task, (void) );
_PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low) );
_PROTOTYPE( int arch_init_profile_clock, (u32_t freq) );
_PROTOTYPE( void arch_stop_profile_clock, (void) );
_PROTOTYPE( void arch_ack_profile_clock, (void) );
#if (CHIP == M68000)
/* M68000 specific prototypes go here. */
#endif /* (CHIP == M68000) */
#endif /* PROTO_H */

View file

@ -1,18 +1,13 @@
/* This file contains the C startup code for Minix on Intel processors.
* It cooperates with mpx.s to set up a good environment for main().
*
* This code runs in real mode for a 16 bit kernel and may have to switch
* to protected mode for a 286.
* For a 32 bit kernel this already runs in protected mode, but the selectors
* are still those given by the BIOS with interrupts disabled, so the
* descriptors need to be reloaded and interrupt descriptors made.
*/
/* First C file used by the kernel. */
#include "kernel.h"
#include "protect.h"
#include "proc.h"
#include <stdlib.h>
#include <string.h>
#include <archconst.h>
PRIVATE char params[K_PARAM_SIZE];
FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key));
/*===========================================================================*
@ -31,28 +26,20 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
extern int etext, end;
int h;
/* Decide if mode is protected; 386 or higher implies protected mode.
* This must be done first, because it is needed for, e.g., seg2phys().
* For 286 machines we cannot decide on protected mode, yet. This is
* done below.
*/
#if _WORD_SIZE != 2
machine.prot = 1;
#endif
/* Record where the kernel and the monitor are. */
kinfo.code_base = seg2phys(cs);
kinfo.code_size = (phys_bytes) &etext; /* size of code segment */
kinfo.data_base = seg2phys(ds);
kinfo.data_size = (phys_bytes) &end; /* size of data segment */
/* Initialize protected mode descriptors. */
prot_init();
/* Architecture-dependent initialization. */
system_init();
/* Copy the boot parameters to the local buffer. */
kinfo.params_base = seg2phys(mds) + parmoff;
kinfo.params_size = MIN(parmsize,sizeof(params)-2);
phys_copy(kinfo.params_base, vir2phys(params), kinfo.params_size);
phys_copy(kinfo.params_base,
vir2phys(params), kinfo.params_size);
/* Record miscellaneous information for user-space servers. */
kinfo.nr_procs = NR_PROCS;
@ -70,14 +57,8 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
for(h = 0; h < _LOAD_HISTORY; h++)
kloadinfo.proc_load_history[h] = 0;
/* Processor? 86, 186, 286, 386, ...
* Decide if mode is protected for older machines.
*/
/* Processor? Decide if mode is protected for older machines. */
machine.processor=atoi(get_value(params, "processor"));
#if _WORD_SIZE == 2
machine.prot = machine.processor >= 286;
#endif
if (! machine.prot) mon_return = 0;
/* XT, AT or MCA bus? */
value = get_value(params, "bus");
@ -95,6 +76,8 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
/* Return to assembler code to switch to protected mode (if 286),
* reload selectors and call main().
*/
intr_init(INTS_MINIX);
}
/*===========================================================================*

View file

@ -14,10 +14,7 @@
* get_priv: assign privilege structure to user or system process
* send_sig: send a signal directly to a system process
* cause_sig: take action to cause a signal to occur via PM
* umap_local: map virtual address in LOCAL_SEG to physical
* umap_remote: map virtual address in REMOTE_SEG to physical
* umap_bios: map virtual address in BIOS_SEG to physical
* umap_grant: map grant number in a process to physical
* virtual_copy: copy bytes from one virtual address to another
* get_randomness: accumulate randomness in a buffer
* clear_endpoint: remove a process' ability to send and receive messages
@ -39,10 +36,6 @@
#include <sys/sigcontext.h>
#include <minix/endpoint.h>
#include <minix/safecopies.h>
#if (CHIP == INTEL)
#include <ibm/memory.h>
#include "protect.h"
#endif
/* Declaration of the call vector that defines the mapping of system calls
* to handler functions. The vector is initialized in sys_init() with map(),
@ -160,9 +153,7 @@ PRIVATE void initialize(void)
/* Device I/O. */
map(SYS_IRQCTL, do_irqctl); /* interrupt control operations */
map(SYS_DEVIO, do_devio); /* inb, inw, inl, outb, outw, outl */
map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */
map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */
map(SYS_INT86, do_int86); /* real-mode BIOS calls */
/* Memory management. */
map(SYS_NEWMAP, do_newmap); /* set up a process memory map */
@ -180,7 +171,6 @@ PRIVATE void initialize(void)
map(SYS_SAFECOPYFROM, do_safecopy); /* copy with pre-granted permission */
map(SYS_SAFECOPYTO, do_safecopy); /* copy with pre-granted permission */
map(SYS_VSAFECOPY, do_vsafecopy); /* vectored safecopy */
map(SYS_READBIOS, do_readbios); /* read from BIOS locations */
/* Clock functionality. */
map(SYS_TIMES, do_times); /* get uptime and process times */
@ -189,12 +179,19 @@ PRIVATE void initialize(void)
/* System control. */
map(SYS_ABORT, do_abort); /* abort MINIX */
map(SYS_GETINFO, do_getinfo); /* request system information */
map(SYS_IOPENABLE, do_iopenable); /* Enable I/O */
/* Profiling. */
map(SYS_SPROF, do_sprofile); /* start/stop statistical profiling */
map(SYS_CPROF, do_cprofile); /* get/reset call profiling data */
map(SYS_PROFBUF, do_profbuf); /* announce locations to kernel */
/* i386-specific. */
#if _MINIX_CHIP == _CHIP_INTEL
map(SYS_INT86, do_int86); /* real-mode BIOS calls */
map(SYS_READBIOS, do_readbios); /* read from BIOS locations */
map(SYS_IOPENABLE, do_iopenable); /* Enable I/O */
map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */
#endif
}
/*===========================================================================*
@ -230,26 +227,16 @@ int proc_type; /* system or user process flag */
PUBLIC void get_randomness(source)
int source;
{
/* On machines with the RDTSC (cycle counter read instruction - pentium
* and up), use that for high-resolution raw entropy gathering. Otherwise,
* use the realtime clock (tick resolution).
*
* Unfortunately this test is run-time - we don't want to bother with
* compiling different kernels for different machines.
*
* On machines without RDTSC, we use read_clock().
/* Use architecture-dependent high-resolution clock for
* raw entropy gathering.
*/
int r_next;
unsigned long tsc_high, tsc_low;
source %= RANDOM_SOURCES;
r_next= krandom.bin[source].r_next;
if (machine.processor > 486) {
read_tsc(&tsc_high, &tsc_low);
krandom.bin[source].r_buf[r_next] = tsc_low;
} else {
krandom.bin[source].r_buf[r_next] = read_clock();
}
read_tsc(&tsc_high, &tsc_low);
krandom.bin[source].r_buf[r_next] = tsc_low;
if (krandom.bin[source].r_size < RANDOM_ELEMENTS) {
krandom.bin[source].r_size ++;
}
@ -313,6 +300,8 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */
}
}
#if _MINIX_CHIP == _CHIP_INTEL
/*===========================================================================*
* umap_bios *
*===========================================================================*/
@ -322,7 +311,7 @@ vir_bytes vir_addr; /* virtual address in BIOS segment */
vir_bytes bytes; /* # of bytes to be copied */
{
/* Calculate the physical memory address at the BIOS. Note: currently, BIOS
* address zero (the first BIOS interrupt vector) is not considered, as an
* address zero (the first BIOS interrupt vector) is not considered as an
* error here, but since the physical address will be zero as well, the
* calling function will think an error occurred. This is not a problem,
* since no one uses the first BIOS interrupt vector.
@ -334,126 +323,11 @@ vir_bytes bytes; /* # of bytes to be copied */
else if (vir_addr >= BASE_MEM_TOP && vir_addr + bytes <= UPPER_MEM_END)
return (phys_bytes) vir_addr;
#if DEAD_CODE /* brutal fix, if the above is too restrictive */
if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END)
return (phys_bytes) vir_addr;
#endif
kprintf("Warning, error in umap_bios, virtual address 0x%x\n", vir_addr);
return 0;
}
/*===========================================================================*
* umap_local *
*===========================================================================*/
PUBLIC phys_bytes umap_local(rp, seg, vir_addr, bytes)
register struct proc *rp; /* pointer to proc table entry for process */
int seg; /* T, D, or S segment */
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)
phys_bytes seg_base;
#endif
/* If 'seg' is D it could really be S and vice versa. T really means T.
* If the virtual address falls in the gap, it causes a problem. On the
* 8088 it is probably a legal stack reference, since "stackfaults" are
* not detected by the hardware. On 8088s, the gap is called S and
* accepted, but on other machines it is called D and rejected.
* The Atari ST behaves like the 8088 in this respect.
*/
if (bytes <= 0) return( (phys_bytes) 0);
if (vir_addr + bytes <= vir_addr) return 0; /* overflow */
vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */
#if (CHIP == INTEL) || (CHIP == M68000)
if (seg != T)
seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S);
#else
if (seg != T)
seg = (vc < rp->p_memmap[S].mem_vir ? D : S);
#endif
if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir +
rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
if (vc >= rp->p_memmap[seg].mem_vir +
rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
#if (CHIP == INTEL)
seg_base = (phys_bytes) rp->p_memmap[seg].mem_phys;
seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */
#endif
pa = (phys_bytes) vir_addr;
#if (CHIP != M68000)
pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
return(seg_base + pa);
#endif
#if (CHIP == M68000)
pa -= (phys_bytes)rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
pa += (phys_bytes)rp->p_memmap[seg].mem_phys << CLICK_SHIFT;
return(pa);
#endif
}
/*===========================================================================*
* umap_grant *
*===========================================================================*/
PUBLIC phys_bytes umap_grant(rp, grant, bytes)
struct proc *rp; /* pointer to proc table entry for process */
cp_grant_id_t grant; /* grant no. */
vir_bytes bytes; /* size */
{
int proc_nr;
vir_bytes offset;
endpoint_t granter;
/* See if the grant in that process is sensible, and
* find out the virtual address and (optionally) new
* process for that address.
*
* Then convert that process to a slot number.
*/
if(verify_grant(rp->p_endpoint, ANY, grant, bytes, 0, 0,
&offset, &granter) != OK) {
return 0;
}
if(!isokendpt(granter, &proc_nr)) {
return 0;
}
/* Do the mapping from virtual to physical. */
return umap_local(proc_addr(proc_nr), D, offset, bytes);
}
/*===========================================================================*
* umap_remote *
*===========================================================================*/
PUBLIC phys_bytes umap_remote(rp, seg, vir_addr, bytes)
register struct proc *rp; /* pointer to proc table entry for process */
int seg; /* index of remote segment */
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. */
struct far_mem *fm;
if (bytes <= 0) return( (phys_bytes) 0);
if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
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);
return(fm->mem_phys + (phys_bytes) vir_addr);
}
/*===========================================================================*
* umap_verify_grant *
*===========================================================================*/
@ -485,6 +359,37 @@ int access; /* does grantee want to CPF_READ or _WRITE? */
return umap_local(proc_addr(proc_nr), D, v_offset, bytes);
}
/*===========================================================================*
* umap_grant *
*===========================================================================*/
PUBLIC phys_bytes umap_grant(rp, grant, bytes)
struct proc *rp; /* pointer to proc table entry for process */
cp_grant_id_t grant; /* grant no. */
vir_bytes bytes; /* size */
{
int proc_nr;
vir_bytes offset;
endpoint_t granter;
/* See if the grant in that process is sensible, and
* find out the virtual address and (optionally) new
* process for that address.
*
* Then convert that process to a slot number.
*/
if(verify_grant(rp->p_endpoint, ANY, grant, bytes, 0, 0,
&offset, &granter) != OK) {
return 0;
}
if(!isokendpt(granter, &proc_nr)) {
return 0;
}
/* Do the mapping from virtual to physical. */
return umap_local(proc_addr(proc_nr), D, offset, bytes);
}
/*===========================================================================*
* virtual_copy *
*===========================================================================*/
@ -529,10 +434,12 @@ vir_bytes bytes; /* # of bytes to copy */
seg_index = vir_addr[i]->segment & SEGMENT_INDEX;
phys_addr[i] = umap_remote(p, seg_index, vir_addr[i]->offset, bytes);
break;
#if _MINIX_CHIP == _CHIP_INTEL
case BIOS_SEG:
if(!p) return EDEADSRCDST;
phys_addr[i] = umap_bios(p, vir_addr[i]->offset, bytes );
break;
#endif
case PHYS_SEG:
phys_addr[i] = vir_addr[i]->offset;
break;
@ -562,8 +469,6 @@ register struct proc *rc; /* slot of process to clean up */
{
register struct proc *rp; /* iterate over process table */
register struct proc **xpp; /* iterate over caller queue */
int i;
int sys_id;
if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc));

View file

@ -1,15 +1,18 @@
# Makefile for system library implementation
include /etc/make.conf
# Directories
u = /usr
i = $u/include
a = ../arch
# Programs, flags, etc.
CC = exec cc $(CFLAGS) -c
CCNOPROF = exec cc $(CFLAGSNOPROF) -c # no call profiling for these
CPP = $l/cpp
LD = $(CC) -.o
CFLAGS = -I$i $(CPROFILE)
CFLAGS = -I$i $(CPROFILE) -I$a/$(ARCH)/include
CFLAGSNOPROF = -I$i
LDFLAGS = -i
@ -31,8 +34,6 @@ OBJECTS = \
$(SYSTEM)(do_irqctl.o) \
$(SYSTEM)(do_devio.o) \
$(SYSTEM)(do_vdevio.o) \
$(SYSTEM)(do_int86.o) \
$(SYSTEM)(do_sdevio.o) \
$(SYSTEM)(do_copy.o) \
$(SYSTEM)(do_vcopy.o) \
$(SYSTEM)(do_umap.o) \
@ -44,19 +45,17 @@ OBJECTS = \
$(SYSTEM)(do_getksig.o) \
$(SYSTEM)(do_endksig.o) \
$(SYSTEM)(do_kill.o) \
$(SYSTEM)(do_readbios.o) \
$(SYSTEM)(do_sigsend.o) \
$(SYSTEM)(do_sigreturn.o) \
$(SYSTEM)(do_abort.o) \
$(SYSTEM)(do_getinfo.o) \
$(SYSTEM)(do_iopenable.o) \
$(SYSTEM)(do_vm.o) \
$(SYSTEM)(do_vm_setbuf.o) \
$(SYSTEM)(do_sprofile.o) \
$(SYSTEM)(do_cprofile.o) \
$(SYSTEM)(do_profbuf.o)
$(SYSTEM): $(OBJECTS)
build $(SYSTEM): $(OBJECTS)
aal cr $@ *.o
clean:
@ -102,15 +101,9 @@ $(SYSTEM)(do_irqctl.o): 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_int86.o): do_int86.c
$(CC) do_int86.c
$(SYSTEM)(do_copy.o): do_copy.c
$(CC) do_copy.c
@ -144,9 +137,6 @@ $(SYSTEM)(do_getinfo.o): do_getinfo.c
$(SYSTEM)(do_abort.o): do_abort.c
$(CC) do_abort.c
$(SYSTEM)(do_readbios.o): do_readbios.c
$(CC) do_readbios.c
$(SYSTEM)(do_setgrant.o): do_setgrant.c
$(CC) do_setgrant.c
@ -159,9 +149,6 @@ $(SYSTEM)(do_safecopy.o): do_safecopy.c
$(SYSTEM)(do_segctl.o): do_segctl.c
$(CC) do_segctl.c
$(SYSTEM)(do_iopenable.o): do_iopenable.c
$(CC) do_iopenable.c
$(SYSTEM)(do_vm.o): do_vm.o
do_vm.o: do_vm.c
$(CC) do_vm.c

View file

@ -10,6 +10,7 @@
#include "../system.h"
#include <minix/devio.h>
#include <minix/endpoint.h>
#include <minix/portio.h>
#if USE_DEVIO
@ -66,16 +67,17 @@ doit:
/* Process a single I/O request for byte, word, and long values. */
if (io_dir == _DIO_INPUT) {
switch (io_type) {
/* maybe "it" should not be called ports */
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;
case _DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break;
default: return(EINVAL);
}
} else {
switch (io_type) {
case _DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
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;
case _DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
default: return(EINVAL);
}
}

View file

@ -33,23 +33,18 @@ register message *m_ptr; /* pointer to request message */
rp = proc_addr(proc);
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 */
phys_memset(vir2phys(&rp->p_ldt[EXTRA_LDT_INDEX]), 0,
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
#if (_MINIX_CHIP == _CHIP_INTEL)
/* wipe extra LDT entries */
phys_memset(vir2phys(&rp->p_seg.p_ldt[EXTRA_LDT_INDEX]), 0,
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_seg.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_enqueue(rp);
/* Save command name for debugging, ps(1) output, etc. */
phys_name = numap_local(who_p, (vir_bytes) m_ptr->PR_NAME_PTR,
(vir_bytes) P_NAME_LEN - 1);
(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++) {}
@ -57,6 +52,7 @@ register message *m_ptr; /* pointer to request message */
} else {
strncpy(rp->p_name, "<unset>", P_NAME_LEN);
}
return(OK);
}
#endif /* USE_EXEC */

View file

@ -8,9 +8,6 @@
#include "../system.h"
#include <signal.h>
#if (CHIP == INTEL)
#include "../protect.h"
#endif
#include <minix/endpoint.h>
@ -23,7 +20,7 @@ PUBLIC int do_fork(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_fork(). PR_ENDPT has forked. The child is PR_SLOT. */
#if (CHIP == INTEL)
#if (_MINIX_CHIP == _CHIP_INTEL)
reg_t old_ldt_sel;
#endif
register struct proc *rpc; /* child process pointer */
@ -42,10 +39,10 @@ register message *m_ptr; /* pointer to request message */
/* Copy parent 'proc' struct to child. And reinitialize some fields. */
gen = _ENDPOINT_G(rpc->p_endpoint);
#if (CHIP == INTEL)
old_ldt_sel = rpc->p_ldt_sel; /* backup local descriptors */
#if (_MINIX_CHIP == _CHIP_INTEL)
old_ldt_sel = rpc->p_seg.p_ldt_sel; /* backup local descriptors */
*rpc = *rpp; /* copy 'proc' struct */
rpc->p_ldt_sel = old_ldt_sel; /* restore descriptors */
rpc->p_seg.p_ldt_sel = old_ldt_sel; /* restore descriptors */
#else
*rpc = *rpp; /* copy 'proc' struct */
#endif

View file

@ -11,9 +11,14 @@
#include "../system.h"
#if !( POWERPC )
static unsigned long bios_buf[1024]; /* 4K, what about alignment */
static vir_bytes bios_buf_vir, bios_buf_len;
#endif /* #if !( POWERPC ) */
#if USE_GETINFO
/*===========================================================================*
@ -119,6 +124,8 @@ register message *m_ptr; /* pointer to request message */
break;
}
#endif
#if !( POWERPC )
case GET_BIOSBUFFER:
bios_buf_vir = (vir_bytes)bios_buf;
bios_buf_len = sizeof(bios_buf);
@ -135,7 +142,8 @@ register message *m_ptr; /* pointer to request message */
length = sizeof(bios_buf_vir);
src_phys = vir2phys(&bios_buf_vir);
break;
#endif /* #if !( POWERPC ) */
case GET_IRQACTIDS: {
length = sizeof(irq_actids);
src_phys = vir2phys(irq_actids);

View file

@ -48,13 +48,10 @@ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
src_phys = umap_local(proc_addr(who_p), 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));
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 */
if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);

View file

@ -30,7 +30,7 @@ PUBLIC int do_nice(message *m_ptr)
if (pri == PRIO_STOP) {
/* Take process off the scheduling queues. */
lock_dequeue(rp);
if(rp->p_rts_flags == 0) lock_dequeue(rp);
rp->p_rts_flags |= NO_PRIORITY;
return(OK);
}
@ -48,7 +48,7 @@ PUBLIC int do_nice(message *m_ptr)
/* Make sure the process is not running while changing its priority.
* Put the process back in its new queue if it is runnable.
*/
lock_dequeue(rp);
if(rp->p_rts_flags == 0) lock_dequeue(rp);
rp->p_rts_flags &= ~NO_PRIORITY;
rp->p_max_priority = rp->p_priority = new_q;
if (! rp->p_rts_flags) lock_enqueue(rp);

View file

@ -247,7 +247,6 @@ int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE
PUBLIC int do_safecopy(m_ptr)
register message *m_ptr; /* pointer to request message */
{
static endpoint_t new_granter;
static int access, src_seg, dst_seg;
/* Set src and dst parameters.

View file

@ -9,7 +9,6 @@
* m4_l5: SEG_INDEX (return index into remote memory map here)
*/
#include "../system.h"
#include "../protect.h"
#if USE_SEGCTL
@ -22,7 +21,7 @@ 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;
u32_t selector;
vir_bytes offset;
int i, index;
register struct proc *rp;
@ -44,30 +43,9 @@ register message *m_ptr; /* pointer to request message */
}
if (index < 0) return(ENOSPC);
if (! machine.prot) {
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;
}
}
offset = alloc_remote_segment(&selector, &rp->p_seg,
i, phys, size, USER_PRIVILEGE);
result = OK;
/* Request successfully done. Now return the result. */
m_ptr->SEG_INDEX = index | REMOTE_SEG;

View file

@ -40,7 +40,7 @@ message *m_ptr; /* pointer to request message */
sc.sc_psw = rp->p_reg.psw;
#if (CHIP == INTEL)
#if (_MINIX_CHIP == _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;
@ -52,7 +52,11 @@ message *m_ptr; /* pointer to request message */
#endif
/* Restore the registers. */
#if _MINIX_CHIP == _CHIP_POWERPC
memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct stackframe_s));
#else
memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct sigregs));
#endif
return(OK);
}
#endif /* USE_SIGRETURN */

View file

@ -45,6 +45,11 @@ message *m_ptr; /* pointer to request message */
/* Copy the registers to the sigcontext structure. */
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
#ifdef POWERPC
memcpy(&sc.sc_regs, (char *) &rp->p_reg, struct(stackframe_s));
#else
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
#endif
/* Finish the sigcontext initialization. */
sc.sc_flags = 0; /* unused at this time */
@ -73,6 +78,16 @@ message *m_ptr; /* pointer to request message */
if (dst_phys == 0) return(EFAULT);
phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
#if ( _MINIX_CHIP == _CHIP_POWERPC ) /* stuff that can't be done in the assembler code. */
/* When the signal handlers C code is called it will write this value
* into the signal frame (over the sf_retadr value).
*/
rp->p_reg.lr = smsg.sm_sigreturn;
/* The first (and only) parameter for the user signal handler function.
*/
rp->p_reg.retreg = smsg.sm_signo; /* note the retreg == first argument */
#endif
/* Reset user registers to execute the signal handler. */
rp->p_reg.sp = (reg_t) frp;
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;

View file

@ -59,7 +59,7 @@ register message *m_ptr; /* pointer to request message */
sprof_mem_size = m_ptr->PROF_MEM_SIZE;
init_cmos_clock(m_ptr->PROF_FREQ);
init_profile_clock(m_ptr->PROF_FREQ);
sprofiling = 1;
@ -78,7 +78,7 @@ register message *m_ptr; /* pointer to request message */
sprofiling = 0;
stop_cmos_clock();
stop_profile_clock();
phys_copy(vir2phys((vir_bytes) &sprof_info),
sprof_info_addr, (phys_bytes) sizeof(sprof_info));

View file

@ -102,7 +102,7 @@ register message *m_ptr;
tr_addr > sizeof(struct stackframe_s) - sizeof(reg_t))
return(EIO);
i = (int) tr_addr;
#if (CHIP == INTEL)
#if (_MINIX_CHIP == _CHIP_INTEL)
/* Altering segment registers might crash the kernel when it
* tries to load them prior to restarting a process, so do
* not allow it.

View file

@ -43,9 +43,11 @@ register message *m_ptr; /* pointer to request message */
case REMOTE_SEG:
phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count);
break;
#if _MINIX_CHIP == _CHIP_INTEL
case BIOS_SEG:
phys_addr = umap_bios(proc_addr(proc_nr), offset, count);
break;
#endif
case GRANT_SEG:
phys_addr = umap_grant(proc_addr(proc_nr), offset, count);
break;

View file

@ -11,6 +11,7 @@
#include "../system.h"
#include <minix/devio.h>
#include <minix/endpoint.h>
#include <minix/portio.h>
#if USE_VDEVIO
@ -112,16 +113,22 @@ register message *m_ptr; /* pointer to request message */
lock(13, "do_vdevio");
switch (io_type) {
case _DIO_BYTE: /* byte values */
if (io_in) for (i=0; i<vec_size; i++) pvb[i].value = inb(pvb[i].port);
else for (i=0; i<vec_size; i++) outb(pvb[i].port, pvb[i].value);
if (io_in) for (i=0; i<vec_size; i++)
pvb[i].value = inb( pvb[i].port);
else for (i=0; i<vec_size; i++)
outb( pvb[i].port, pvb[i].value);
break;
case _DIO_WORD: /* word values */
if (io_in) for (i=0; i<vec_size; i++) pvw[i].value = inw(pvw[i].port);
else for (i=0; i<vec_size; i++) outw(pvw[i].port, pvw[i].value);
if (io_in) for (i=0; i<vec_size; i++)
pvw[i].value = inw( pvw[i].port);
else for (i=0; i<vec_size; i++)
outw( pvw[i].port, pvw[i].value);
break;
default: /* long values */
if (io_in) for (i=0; i<vec_size; i++) pvl[i].value = inl(pvl[i].port);
else for (i=0; i<vec_size; i++) outl(pvb[i].port, pvl[i].value);
if (io_in) for (i=0; i<vec_size; i++)
pvl[i].value = inl(pvl[i].port);
else for (i=0; i<vec_size; i++)
outl( pvb[i].port, pvl[i].value);
}
unlock(13);

View file

@ -6,23 +6,13 @@
* m4_l2: Map (TRUE) or unmap (FALSE) (VM_MAP_MAPUNMAP)
* m4_l3: Base address (VM_MAP_BASE)
* m4_l4: Size (VM_MAP_SIZE)
* m4_l5: Memory address (VM_MAP_ADDR)
* m4_l5: address (VM_MAP_ADDR)
*/
#include "../system.h"
#include <sys/vm.h>
PRIVATE int vm_needs_init= 1;
PRIVATE u32_t vm_cr3;
FORWARD _PROTOTYPE( void vm_init, (void) );
FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value) );
FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr) );
FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value) );
FORWARD _PROTOTYPE( void set_cr3, (void) );
FORWARD _PROTOTYPE( void vm_enable_paging, (void) );
FORWARD _PROTOTYPE( void map_range, (u32_t base, u32_t size,
u32_t offset) );
#include <sys/vm.h>
/*===========================================================================*
* do_vm_map *
@ -35,11 +25,10 @@ message *m_ptr; /* pointer to request message */
struct proc *pp;
/* do_serial_debug= 1; */
if (vm_needs_init)
{
vm_needs_init= 0;
vm_init();
vm_needs_init= 0;
vm_init();
}
if (m_ptr->VM_MAP_ENDPT == SELF) {
@ -63,17 +52,17 @@ message *m_ptr; /* pointer to request message */
{
pp->p_misc_flags |= MF_VM;
map_range(p_phys, size, offset);
vm_map_range(p_phys, size, offset);
}
else
{
map_range(p_phys, size, p_phys);
vm_map_range(p_phys, size, p_phys);
}
vm_set_cr3(vm_cr3);
return OK;
}
/*===========================================================================*
* vm_map_default *
*===========================================================================*/
@ -88,137 +77,7 @@ struct proc *pp;
base_clicks= pp->p_memmap[D].mem_phys;
size_clicks= pp->p_memmap[S].mem_phys+pp->p_memmap[S].mem_len -
base_clicks;
map_range(base_clicks << CLICK_SHIFT, size_clicks << CLICK_SHIFT,
base_clicks << CLICK_SHIFT);
vm_set_cr3(vm_cr3);
vm_map_range(base_clicks << CLICK_SHIFT,
size_clicks << CLICK_SHIFT, base_clicks << CLICK_SHIFT);
}
PRIVATE void vm_init(void)
{
int o;
phys_bytes p, pt_size;
phys_bytes vm_dir_base, vm_pt_base, phys_mem;
u32_t entry;
unsigned pages;
if (!vm_size)
panic("vm_init: no space for page tables", NO_NUM);
/* Align page directory */
o= (vm_base % PAGE_SIZE);
if (o != 0)
o= PAGE_SIZE-o;
vm_dir_base= vm_base+o;
/* Page tables start after the page directory */
vm_pt_base= vm_dir_base+PAGE_SIZE;
pt_size= (vm_base+vm_size)-vm_pt_base;
pt_size -= (pt_size % PAGE_SIZE);
/* Compute the number of pages based on vm_mem_high */
pages= (vm_mem_high-1)/PAGE_SIZE + 1;
if (pages * I386_VM_PT_ENT_SIZE > pt_size)
panic("vm_init: page table too small", NO_NUM);
for (p= 0; p*I386_VM_PT_ENT_SIZE < pt_size; p++)
{
phys_mem= p*PAGE_SIZE;
entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
I386_VM_PRESENT;
if (phys_mem >= vm_mem_high)
entry= 0;
phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
}
for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
{
phys_mem= vm_pt_base + p*PAGE_SIZE;
entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
I386_VM_PRESENT;
if (phys_mem >= vm_pt_base + pt_size)
entry= 0;
phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
}
vm_set_cr3(vm_dir_base);
level0(vm_enable_paging);
}
PRIVATE void phys_put32(addr, value)
phys_bytes addr;
u32_t value;
{
phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
}
PRIVATE u32_t phys_get32(addr)
phys_bytes addr;
{
u32_t value;
phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
return value;
}
PRIVATE void vm_set_cr3(value)
u32_t value;
{
vm_cr3= value;
level0(set_cr3);
}
PRIVATE void set_cr3()
{
write_cr3(vm_cr3);
}
PRIVATE void vm_enable_paging(void)
{
u32_t cr0;
cr0= read_cr0();
write_cr0(cr0 | I386_CR0_PG);
}
PRIVATE void map_range(base, size, offset)
u32_t base;
u32_t size;
u32_t offset;
{
u32_t curr_pt, curr_pt_addr, entry;
int dir_ent, pt_ent;
if (base % PAGE_SIZE != 0)
panic("map_range: bad base", base);
if (size % PAGE_SIZE != 0)
panic("map_range: bad size", size);
if (offset % PAGE_SIZE != 0)
panic("map_range: bad offset", offset);
curr_pt= -1;
curr_pt_addr= 0;
while (size != 0)
{
dir_ent= (base >> I386_VM_DIR_ENT_SHIFT);
pt_ent= (base >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK;
if (dir_ent != curr_pt)
{
/* Get address of page table */
curr_pt= dir_ent;
curr_pt_addr= phys_get32(vm_cr3 +
dir_ent * I386_VM_PT_ENT_SIZE);
curr_pt_addr &= I386_VM_ADDR_MASK;
}
entry= offset | I386_VM_USER | I386_VM_WRITE |
I386_VM_PRESENT;
#if 0 /* Do we need this for memory mapped I/O? */
entry |= I386_VM_PCD | I386_VM_PWT;
#endif
phys_put32(curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE, entry);
offset += PAGE_SIZE;
base += PAGE_SIZE;
size -= PAGE_SIZE;
}
}

View file

@ -32,7 +32,6 @@
#include "proc.h"
#include "ipc.h"
#include <minix/com.h>
#include <ibm/int86.h>
/* Define stack sizes for the kernel tasks included in the system image. */
#define NO_STACK 0

View file

@ -47,49 +47,6 @@ struct randomness {
} bin[RANDOM_SOURCES];
};
#if (CHIP == INTEL)
typedef unsigned reg_t; /* machine register */
/* The stack frame layout is determined by the software, but for efficiency
* it is laid out so the assembly code to use it is as simple as possible.
* 80286 protected mode and all real modes use the same frame, built with
* 16-bit registers. Real mode lacks an automatic stack switch, so little
* is lost by using the 286 frame for it. The 386 frame differs only in
* having 32-bit registers and more segment registers. The same names are
* used for the larger registers to avoid differences in the code.
*/
struct stackframe_s { /* proc_ptr points here */
#if _WORD_SIZE == 4
u16_t gs; /* last item pushed by save */
u16_t fs; /* ^ */
#endif
u16_t es; /* | */
u16_t ds; /* | */
reg_t di; /* di through cx are not accessed in C */
reg_t si; /* order is to match pusha/popa */
reg_t fp; /* bp */
reg_t st; /* hole for another copy of sp */
reg_t bx; /* | */
reg_t dx; /* | */
reg_t cx; /* | */
reg_t retreg; /* ax and above are all pushed by save */
reg_t retadr; /* return address for assembly code save() */
reg_t pc; /* ^ last item pushed by interrupt */
reg_t cs; /* | */
reg_t psw; /* | */
reg_t sp; /* | */
reg_t ss; /* these are pushed by CPU during interrupt */
};
struct segdesc_s { /* segment descriptor for protected mode */
u16_t limit_low;
u16_t base_low;
u8_t base_middle;
u8_t access; /* |P|DL|1|X|E|R|A| */
u8_t granularity; /* |G|X|0|A|LIMT| */
u8_t base_high;
};
typedef unsigned long irq_policy_t;
typedef unsigned long irq_id_t;
@ -105,10 +62,4 @@ typedef struct irq_hook {
typedef int (*irq_handler_t)(struct irq_hook *);
#endif /* (CHIP == INTEL) */
#if (CHIP == M68000)
/* M68000 specific types go here. */
#endif /* (CHIP == M68000) */
#endif /* TYPE_H */

View file

@ -1,9 +1,14 @@
/* This file contains a collection of miscellaneous procedures:
* panic: abort MINIX due to a fatal error
* kprintf: (from lib/sysutil/kprintf.c)
* kputc: buffered putc used by kernel kprintf
*/
#include "kernel.h"
#include "proc.h"
#include <unistd.h>
#include <signal.h>
/*===========================================================================*
* panic *
@ -25,3 +30,37 @@ int nr;
/* Abort MINIX. */
prepare_shutdown(RBT_PANIC);
}
/* Include system printf() implementation named kprintf() */
#define printf kprintf
#include "../lib/sysutil/kprintf.c"
#define END_OF_KMESS 0
/*===========================================================================*
* kputc *
*===========================================================================*/
PUBLIC void kputc(c)
int c; /* character to append */
{
/* Accumulate a single character for a kernel message. Send a notification
* to the output driver if an END_OF_KMESS is encountered.
*/
if (c != END_OF_KMESS) {
if (do_serial_debug)
ser_putc(c);
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 {
int p, outprocs[] = OUTPUT_PROCS_ARRAY;
for(p = 0; outprocs[p] != NONE; p++) {
if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
send_sig(outprocs[p], SIGKMESS);
}
}
}
}

View file

@ -4,6 +4,8 @@
#OBJDIR=.
. /etc/make.conf
SUBDIRS="ansi \
curses \
dummy \
@ -20,7 +22,7 @@ SUBDIRS="ansi \
util \
sysutil \
timers \
i386 \
$ARCH \
zlib-1.2.3 \
ack
gnu"

View file

@ -17,5 +17,6 @@ abort(void)
{
if (_clean) _clean(); /* flush all output files */
raise(SIGABRT);
/* NORETURN */
}

View file

@ -1,6 +1,10 @@
#!/bin/sh
# called with parameters: 1:dir 2:ackbase 3:gnubase
set -e
. /etc/make.conf
exec >Makefile
exec 3>Makedepend-ack
exec 4>Makedepend-gnu
@ -243,7 +247,8 @@ if [ $OBJDIR = "." ]; then
echo "install: install-ack"
echo
echo "install-ack: all-ack"
echo " cp $ACKBASE/*.[ao] /usr/lib/i386"
# $ARCH is from /etc/make.conf
echo " cp $ACKBASE/*.[ao] /usr/lib/$ARCH"
echo
echo "install-gnu: all-gnu"
echo " cp $GNUBASE/*.[ao] /usr/gnu/lib"

View file

@ -4,6 +4,7 @@ domainname.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <net/netlib.h>
int getdomainname(domain, size)

View file

@ -1,5 +1,6 @@
#include <lib.h>
#define lstat _lstat
#define stat _stat
#include <sys/stat.h>
#include <string.h>

View file

@ -4,6 +4,7 @@ pci_set_acl.c
#include "pci.h"
#include "syslib.h"
#include <unistd.h>
#include <minix/rs.h>
#include <minix/sysutil.h>

View file

@ -2,7 +2,7 @@
CC=cc
CFLAGS=-O
CFLAGS="-O -D_POSIX_SOURCE -D_MINIX"
LIBRARIES=libz

View file

@ -1,6 +1,8 @@
# Makefile for Information Server (IS)
SERVER = is
include /etc/make.conf
# directories
u = /usr
i = $u/include
@ -13,7 +15,8 @@ f = $u/src/servers/fs
# programs, flags, etc.
CC = exec cc
CFLAGS = -I$i $(CPROFILE)
CPPFLAGS=-I../../kernel/arch/$(ARCH)/include -I$i
CFLAGS = $(CPROFILE) $(CPPFLAGS)
LDFLAGS = -i
LIBS = -lsysutil -lsys

View file

@ -4,6 +4,7 @@
#include <timers.h>
#include <ibm/interrupt.h>
#include <minix/endpoint.h>
#include <minix/sys_config.h>
#include "../../kernel/const.h"
#include "../../kernel/config.h"
#include "../../kernel/debug.h"
@ -292,7 +293,6 @@ PUBLIC void kenv_dmp()
printf("- pc_at: %3d\n", machine.pc_at);
printf("- ps_mca: %3d\n", machine.ps_mca);
printf("- processor: %3d\n", machine.processor);
printf("- protected: %3d\n", machine.prot);
printf("- vdu_ega: %3d\n", machine.vdu_ega);
printf("- vdu_vga: %3d\n\n", machine.vdu_vga);
printf("Kernel info structure:\n");
@ -482,7 +482,7 @@ PUBLIC void proctab_dmp()
return;
}
printf("\n-nr-----gen---endpoint-name--- -prior-quant- -user---sys----size-rts flags-\n");
printf("\n-nr-----gen---endpoint-name--- -prior-quant- -user----sys----size-rts flags\n");
for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
if (isemptyp(rp)) continue;
@ -495,7 +495,7 @@ PUBLIC void proctab_dmp()
else if (proc_nr(rp) < 0) printf("[%2d] ", proc_nr(rp));
else printf(" %2d ", proc_nr(rp));
printf(" %5d %10d ", _ENDPOINT_G(rp->p_endpoint), rp->p_endpoint);
printf("%-8.8s %02u/%02u %02d/%02u %6lu%6lu %6uK %s",
printf("%-8.8s %02u/%02u %02d/%02u %6lu %6lu %5uK %s",
rp->p_name,
rp->p_priority, rp->p_max_priority,
rp->p_ticks_left, rp->p_quantum_size,

View file

@ -28,6 +28,7 @@
#include <unistd.h>
#include <signal.h>
#include <archtypes.h>
#include "proto.h"
#include "glo.h"

View file

@ -1,6 +1,8 @@
# Makefile for Process Manager (PM)
SERVER = pm
include /etc/make.conf
# directories
u = /usr
i = $u/include
@ -10,7 +12,8 @@ k = $u/src/kernel
# programs, flags, etc.
CC = exec cc
CFLAGS = -I$i $(CPROFILE)
CPPFLAGS=-I../../kernel/arch/$(ARCH)/include -I$i
CFLAGS = $(CPROFILE) $(CPPFLAGS)
LDFLAGS = -i
OBJ = main.o forkexit.o break.o exec.o time.o timers.o \

View file

@ -24,6 +24,7 @@
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <archconst.h>
#include "mproc.h"
#include "../../kernel/const.h"
#include "../../kernel/config.h"

View file

@ -21,6 +21,8 @@
#include <sys/resource.h>
#include <sys/utsname.h>
#include <string.h>
#include <archconst.h>
#include <archtypes.h>
#include "mproc.h"
#include "param.h"

View file

@ -24,6 +24,8 @@
#include <minix/sysinfo.h>
#include <minix/type.h>
#include <string.h>
#include <archconst.h>
#include <archtypes.h>
#include <lib.h>
#include "mproc.h"
#include "param.h"

View file

@ -693,6 +693,8 @@ register struct mproc *rmp; /* whose core is to be dumped */
struct mproc *p_mp;
clock_t t[5];
printf("dumpcore for %d / %s\n", rmp->mp_pid, rmp->mp_name);
/* Do not create core files for set uid execution */
if (rmp->mp_realuid != rmp->mp_effuid) return OK;

View file

@ -24,6 +24,8 @@
#include <minix/config.h>
#include <timers.h>
#include <string.h>
#include <archconst.h>
#include <archtypes.h>
#include "../../kernel/const.h"
#include "../../kernel/config.h"
#include "../../kernel/type.h"

View file

@ -2,6 +2,8 @@
SERVER = rs
UTIL = service
include /etc/make.conf
# directories
u = /usr
i = $u/include
@ -11,7 +13,8 @@ b = $i/ibm
# programs, flags, etc.
CC = exec cc
CFLAGS = -I$i $(CPROFILE)
CPPFLAGS = -I../../kernel/arch/$(ARCH)/include
CFLAGS = -I$i $(CPROFILE) $(CPPFLAGS)
LDFLAGS = -i
UTIL_LIBS = -lsysutil -lsys
LIBS = -lsysutil -lsys

View file

@ -26,6 +26,7 @@
#include <minix/keymap.h>
#include <minix/bitmap.h>
#include <archtypes.h>
#include <timers.h> /* For priv.h */
#include "../../kernel/priv.h"