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:
parent
f7984144d5
commit
6f77685609
100 changed files with 1528 additions and 1633 deletions
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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] = {
|
||||
|
|
|
@ -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) */
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
ibm/portio.h
|
||||
minix/portio.h
|
||||
|
||||
Created: Jan 15, 1992 by Philip Homburg
|
||||
*/
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
81
kernel/arch/i386/Makefile
Executable 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
65
kernel/arch/i386/clock.c
Executable 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
/*===========================================================================*
|
|
@ -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 *
|
|
@ -7,7 +7,7 @@
|
|||
* m2_p1: RDB_BUF buffer address in requesting process
|
||||
*/
|
||||
|
||||
#include "../system.h"
|
||||
#include "../../system.h"
|
||||
#include <minix/type.h>
|
||||
|
||||
/*===========================================================================*
|
|
@ -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
|
||||
|
||||
/*===========================================================================*
|
|
@ -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
79
kernel/arch/i386/i8259.c
Executable 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;
|
||||
}
|
146
kernel/arch/i386/include/archconst.h
Normal file
146
kernel/arch/i386/include/archconst.h
Normal 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 */
|
62
kernel/arch/i386/include/archtypes.h
Normal file
62
kernel/arch/i386/include/archtypes.h
Normal 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 */
|
||||
|
|
@ -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
234
kernel/arch/i386/memory.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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. */
|
|
@ -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
72
kernel/arch/i386/proto.h
Normal 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
|
|
@ -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
102
kernel/arch/i386/system.c
Normal 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
|
129
kernel/clock.c
129
kernel/clock.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
193
kernel/i8259.c
193
kernel/i8259.c
|
@ -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
9
kernel/interface.h
Normal 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
141
kernel/interrupt.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -12,7 +12,6 @@
|
|||
* Jul 01, 2005 Created. (Jorrit N. Herder)
|
||||
*/
|
||||
#include <minix/com.h>
|
||||
#include "protect.h"
|
||||
#include "const.h"
|
||||
#include "type.h"
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
158
kernel/proto.h
158
kernel/proto.h
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
191
kernel/system.c
191
kernel/system.c
|
@ -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));
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -17,5 +17,6 @@ abort(void)
|
|||
{
|
||||
if (_clean) _clean(); /* flush all output files */
|
||||
raise(SIGABRT);
|
||||
/* NORETURN */
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -4,6 +4,7 @@ domainname.c
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <net/netlib.h>
|
||||
|
||||
int getdomainname(domain, size)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <lib.h>
|
||||
#define lstat _lstat
|
||||
#define stat _stat
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-O
|
||||
CFLAGS="-O -D_POSIX_SOURCE -D_MINIX"
|
||||
|
||||
LIBRARIES=libz
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <archtypes.h>
|
||||
#include "proto.h"
|
||||
#include "glo.h"
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
Loading…
Reference in a new issue