From: Ben Gras Date: Fri, 22 Dec 2006 15:22:27 +0000 (+0000) Subject: Split of architecture-dependent and -independent functions for i386, X-Git-Tag: v3.1.3~128 X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=6f7768560995f355490bf0022aa42dee2dcca06d;p=minix.git Split of architecture-dependent and -independent functions for i386, mainly in the kernel and headers. This split based on work by Ingmar Alting 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. . moved to , 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=, 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 --- diff --git a/commands/ibm/postmort.c b/commands/ibm/postmort.c index 8c9555287..1060d7797 100755 --- a/commands/ibm/postmort.c +++ b/commands/ibm/postmort.c @@ -33,6 +33,7 @@ #undef EXTERN /* 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" diff --git a/commands/ibm/readclock.c b/commands/ibm/readclock.c index 047368bee..f4a51864e 100755 --- a/commands/ibm/readclock.c +++ b/commands/ibm/readclock.c @@ -64,7 +64,7 @@ #include #include #include -#include +#include #include #include diff --git a/commands/ibm/sdump.c b/commands/ibm/sdump.c index e6206da20..eb3ac6dfe 100755 --- a/commands/ibm/sdump.c +++ b/commands/ibm/sdump.c @@ -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" diff --git a/commands/mdb/core.c b/commands/mdb/core.c index 4eda5af8b..83fd86a2a 100644 --- a/commands/mdb/core.c +++ b/commands/mdb/core.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include diff --git a/commands/mdb/kernel.c b/commands/mdb/kernel.c index 119a8e29a..2afdf276b 100644 --- a/commands/mdb/kernel.c +++ b/commands/mdb/kernel.c @@ -11,6 +11,7 @@ #include #include "proto.h" +#include #include #include #include diff --git a/commands/mdb/mdb.c b/commands/mdb/mdb.c index e6f99c4f8..d3d6087ab 100644 --- a/commands/mdb/mdb.c +++ b/commands/mdb/mdb.c @@ -45,6 +45,7 @@ #include #include "proto.h" +#include "../../kernel/arch/i386/include/archtypes.h" #include #include #include diff --git a/commands/ps/ps.c b/commands/ps/ps.c index ce73d79d8..9f93439d2 100644 --- a/commands/ps/ps.c +++ b/commands/ps/ps.c @@ -76,6 +76,7 @@ #include #include +#include "../../kernel/arch/i386/include/archtypes.h" #include "../../kernel/const.h" #include "../../kernel/type.h" #include "../../kernel/proc.h" diff --git a/commands/simple/dumpcore.c b/commands/simple/dumpcore.c index 9b303d578..64d056cc1 100644 --- a/commands/simple/dumpcore.c +++ b/commands/simple/dumpcore.c @@ -19,6 +19,7 @@ #include #include +#include "../../kernel/arch/i386/include/archtypes.h" #include "../../kernel/const.h" #include "../../kernel/type.h" #include "../../kernel/config.h" diff --git a/commands/simple/top.c b/commands/simple/top.c index 70db7ca51..a5647ff8d 100644 --- a/commands/simple/top.c +++ b/commands/simple/top.c @@ -30,6 +30,7 @@ #include #include +#include "../../kernel/arch/i386/include/archtypes.h" #include "../../servers/pm/mproc.h" #include "../../kernel/const.h" #include "../../kernel/proc.h" diff --git a/drivers/floppy/floppy.c b/drivers/floppy/floppy.c index 1d9f59938..bc4cacd17 100644 --- a/drivers/floppy/floppy.c +++ b/drivers/floppy/floppy.c @@ -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] = { diff --git a/drivers/memory/memory.c b/drivers/memory/memory.c index d4b165942..1134a7d55 100644 --- a/drivers/memory/memory.c +++ b/drivers/memory/memory.c @@ -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) */ } diff --git a/drivers/rescue/Makefile b/drivers/rescue/Makefile deleted file mode 100644 index 66cf545ca..000000000 --- a/drivers/rescue/Makefile +++ /dev/null @@ -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 - diff --git a/drivers/rescue/rescue.c b/drivers/rescue/rescue.c deleted file mode 100644 index e597dec6d..000000000 --- a/drivers/rescue/rescue.c +++ /dev/null @@ -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; -} - diff --git a/drivers/rtl8139/rtl8139.c b/drivers/rtl8139/rtl8139.c index 3944036e8..f6c32d2fe 100755 --- a/drivers/rtl8139/rtl8139.c +++ b/drivers/rtl8139/rtl8139.c @@ -62,7 +62,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index 3661fa720..884bc2474 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -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 diff --git a/drivers/tty/keyboard.c b/drivers/tty/keyboard.c index 9b0357a23..ce402f656 100644 --- a/drivers/tty/keyboard.c +++ b/drivers/tty/keyboard.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/etc/Makefile b/etc/Makefile index a38f4e1c6..3baa22cd8 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -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 diff --git a/include/minix/config.h b/include/minix/config.h index 0d6df0429..bc79747e4 100755 --- a/include/minix/config.h +++ b/include/minix/config.h @@ -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 */ diff --git a/include/ibm/portio.h b/include/minix/portio.h similarity index 97% rename from include/ibm/portio.h rename to include/minix/portio.h index 07060bbda..9e7b412cb 100755 --- a/include/ibm/portio.h +++ b/include/minix/portio.h @@ -1,5 +1,5 @@ /* -ibm/portio.h +minix/portio.h Created: Jan 15, 1992 by Philip Homburg */ diff --git a/include/minix/sys_config.h b/include/minix/sys_config.h index 5df200d2e..97fea6fee 100755 --- a/include/minix/sys_config.h +++ b/include/minix/sys_config.h @@ -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 */ diff --git a/include/minix/type.h b/include/minix/type.h index 90c629bc4..65c9cbe48 100755 --- a/include/minix/type.h +++ b/include/minix/type.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; }; diff --git a/kernel/Makefile b/kernel/Makefile index 35de79fd8..6f59e3bcb 100755 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -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 + +# first-stage, arch-dependent startup code +HEAD = head.o +FULLHEAD = $a/$(HEAD) -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 +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 $@ $< +$(HEAD): + cd $a && make HEAD=$(HEAD) $(HEAD) + # Include generated dependencies. -klib.o: klib386.s klib88.s -mpx.o: mpx386.s mpx88.s include .depend - diff --git a/kernel/arch/i386/Makefile b/kernel/arch/i386/Makefile new file mode 100755 index 000000000..fe5f4e60c --- /dev/null +++ b/kernel/arch/i386/Makefile @@ -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 diff --git a/kernel/arch/i386/clock.c b/kernel/arch/i386/clock.c new file mode 100755 index 000000000..6c7f5060d --- /dev/null +++ b/kernel/arch/i386/clock.c @@ -0,0 +1,65 @@ + +/* i386-specific clock functions. */ + +#include +#include + +#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; +} + diff --git a/kernel/system/do_int86.c b/kernel/arch/i386/do_int86.c similarity index 94% rename from kernel/system/do_int86.c rename to kernel/arch/i386/do_int86.c index f669b7896..9809dc291 100644 --- a/kernel/system/do_int86.c +++ b/kernel/arch/i386/do_int86.c @@ -5,11 +5,14 @@ * m1_p1: INT86_REG86 */ -#include "../system.h" +#include "../../system.h" #include #include +#include #include +#include "proto.h" + struct reg86u reg86; /*===========================================================================* diff --git a/kernel/system/do_iopenable.c b/kernel/arch/i386/do_iopenable.c similarity index 91% rename from kernel/system/do_iopenable.c rename to kernel/arch/i386/do_iopenable.c index f37a46199..552b3a5f3 100644 --- a/kernel/system/do_iopenable.c +++ b/kernel/arch/i386/do_iopenable.c @@ -8,8 +8,10 @@ * Jorrit N. Herder */ -#include "../system.h" -#include "../kernel.h" +#include "../../system.h" +#include "../../kernel.h" + +#include "proto.h" /*===========================================================================* * do_iopenable * diff --git a/kernel/system/do_readbios.c b/kernel/arch/i386/do_readbios.c similarity index 97% rename from kernel/system/do_readbios.c rename to kernel/arch/i386/do_readbios.c index 94849fe6a..d09602f4c 100644 --- a/kernel/system/do_readbios.c +++ b/kernel/arch/i386/do_readbios.c @@ -7,7 +7,7 @@ * m2_p1: RDB_BUF buffer address in requesting process */ -#include "../system.h" +#include "../../system.h" #include /*===========================================================================* diff --git a/kernel/system/do_sdevio.c b/kernel/arch/i386/do_sdevio.c similarity index 98% rename from kernel/system/do_sdevio.c rename to kernel/arch/i386/do_sdevio.c index be39dd036..b76f4df49 100644 --- a/kernel/system/do_sdevio.c +++ b/kernel/arch/i386/do_sdevio.c @@ -10,10 +10,12 @@ * m2_i2: DIO_VEC_PROC (process where buffer is) */ -#include "../system.h" +#include "../../system.h" #include #include +#include "proto.h" + #if USE_SDEVIO /*===========================================================================* diff --git a/kernel/exception.c b/kernel/arch/i386/exception.c similarity index 96% rename from kernel/exception.c rename to kernel/arch/i386/exception.c index df6343ace..df98dd4e1 100755 --- a/kernel/exception.c +++ b/kernel/arch/i386/exception.c @@ -3,15 +3,14 @@ * a panic. */ -#include "kernel.h" +#include "../../kernel.h" #include -#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; diff --git a/kernel/arch/i386/i8259.c b/kernel/arch/i386/i8259.c new file mode 100755 index 000000000..642eeb58a --- /dev/null +++ b/kernel/arch/i386/i8259.c @@ -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 +#include +#include + +#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; +} diff --git a/kernel/arch/i386/include/archconst.h b/kernel/arch/i386/include/archconst.h new file mode 100644 index 000000000..2340a830f --- /dev/null +++ b/kernel/arch/i386/include/archconst.h @@ -0,0 +1,146 @@ + +#ifndef _I386_ACONST_H +#define _I386_ACONST_H 1 + +#include +#include + +#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 */ diff --git a/kernel/arch/i386/include/archtypes.h b/kernel/arch/i386/include/archtypes.h new file mode 100644 index 000000000..a506a18b3 --- /dev/null +++ b/kernel/arch/i386/include/archtypes.h @@ -0,0 +1,62 @@ + +#ifndef _I386_TYPES_H +#define _I386_TYPES_H + +#include +#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 */ + diff --git a/kernel/protect.h b/kernel/arch/i386/include/protect.h similarity index 100% rename from kernel/protect.h rename to kernel/arch/i386/include/protect.h diff --git a/kernel/klib386.s b/kernel/arch/i386/klib386.s similarity index 97% rename from kernel/klib386.s rename to kernel/arch/i386/klib386.s index d334bbccc..a8bbd1867 100755 --- a/kernel/klib386.s +++ b/kernel/arch/i386/klib386.s @@ -5,9 +5,10 @@ #include #include -#include "const.h" +#include +#include +#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 diff --git a/kernel/arch/i386/memory.c b/kernel/arch/i386/memory.c new file mode 100644 index 000000000..53a2aea38 --- /dev/null +++ b/kernel/arch/i386/memory.c @@ -0,0 +1,234 @@ + +#include "../../kernel.h" +#include "../../proc.h" + +#include +#include + +#include + +#include + +#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); +} + diff --git a/kernel/mpx386.s b/kernel/arch/i386/mpx386.s similarity index 99% rename from kernel/mpx386.s rename to kernel/arch/i386/mpx386.s index 0b5eee027..c6f94f14d 100755 --- a/kernel/mpx386.s +++ b/kernel/arch/i386/mpx386.s @@ -56,8 +56,8 @@ begbss: #include #include #include -#include "const.h" -#include "protect.h" +#include +#include "../../const.h" #include "sconst.h" /* Selected 386 tss offsets. */ diff --git a/kernel/protect.c b/kernel/arch/i386/protect.c similarity index 81% rename from kernel/protect.c rename to kernel/arch/i386/protect.c index a4c2e7693..d303ab59b 100755 --- a/kernel/protect.c +++ b/kernel/arch/i386/protect.c @@ -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 + +#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); - } } diff --git a/kernel/arch/i386/proto.h b/kernel/arch/i386/proto.h new file mode 100644 index 000000000..06eecd09f --- /dev/null +++ b/kernel/arch/i386/proto.h @@ -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 diff --git a/kernel/sconst.h b/kernel/arch/i386/sconst.h similarity index 83% rename from kernel/sconst.h rename to kernel/arch/i386/sconst.h index 41c6d136b..28e7b0517 100755 --- a/kernel/sconst.h +++ b/kernel/arch/i386/sconst.h @@ -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 diff --git a/kernel/arch/i386/system.c b/kernel/arch/i386/system.c new file mode 100644 index 000000000..72d28b8b7 --- /dev/null +++ b/kernel/arch/i386/system.c @@ -0,0 +1,102 @@ +/* system dependent functions for use inside the whole kernel. */ + +#include "../../kernel.h" + +#include +#include +#include +#include + +#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 diff --git a/kernel/clock.c b/kernel/clock.c index cfdc151f3..b748a3495 100755 --- a/kernel/clock.c +++ b/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 #include -/* 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 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) { - - /* 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); - } + while(TRUE) { + /* Go get a message. */ + result = 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); + } } } @@ -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; } + + diff --git a/kernel/config.h b/kernel/config.h index 9253fe94f..371dcae35 100644 --- a/kernel/config.h +++ b/kernel/config.h @@ -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. */ diff --git a/kernel/const.h b/kernel/const.h index 109dc2814..b8cd35263 100755 --- a/kernel/const.h +++ b/kernel/const.h @@ -2,20 +2,11 @@ #ifndef CONST_H #define CONST_H -#include /* interrupt numbers and hardware vectors */ -#include /* port addresses and magic numbers */ -#include /* BIOS addresses, sizes and magic numbers */ -#include /* BIOS addresses, sizes and magic numbers */ #include #include #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) - -/* 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) */ +#define lock(c, v) reallock(c, v) +#define unlock(c) realunlock(c) +#endif -#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 */ diff --git a/kernel/debug.h b/kernel/debug.h index 7169559a4..2cfb905d0 100644 --- a/kernel/debug.h +++ b/kernel/debug.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 */ diff --git a/kernel/glo.h b/kernel/glo.h index 7de20763a..891d54526 100755 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -12,6 +12,7 @@ #endif #include +#include #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 */ diff --git a/kernel/i8259.c b/kernel/i8259.c deleted file mode 100755 index 0e487656e..000000000 --- a/kernel/i8259.c +++ /dev/null @@ -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 - -#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 */ diff --git a/kernel/interface.h b/kernel/interface.h new file mode 100644 index 000000000..87f900cb4 --- /dev/null +++ b/kernel/interface.h @@ -0,0 +1,9 @@ +/* minix/kernel/interface.h - All interfaces the kernel needs. */ + +#ifndef _KERNEL_IF_H_ +#define _KERNEL_IF_H_ + +#include +#include + +#endif /* #ifndef _KERNEL_IF_H_ */ diff --git a/kernel/interrupt.c b/kernel/interrupt.c new file mode 100644 index 000000000..6d54fab22 --- /dev/null +++ b/kernel/interrupt.c @@ -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 +#include + +/* 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; +} + diff --git a/kernel/kernel.h b/kernel/kernel.h index 7df4de501..6ddc1f18f 100755 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -18,10 +18,6 @@ #include /* watchdog timer management */ #include /* return codes and error numbers */ -#if (CHIP == INTEL) -#include /* 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 */ diff --git a/kernel/klib.s b/kernel/klib.s deleted file mode 100755 index 27ee56f97..000000000 --- a/kernel/klib.s +++ /dev/null @@ -1,9 +0,0 @@ -# -! Chooses between the 8086 and 386 versions of the low level kernel code. - -#include -#if _WORD_SIZE == 2 -#include "klib88.s" -#else -#include "klib386.s" -#endif diff --git a/kernel/klib88.s b/kernel/klib88.s deleted file mode 100755 index e69de29bb..000000000 diff --git a/kernel/kprintf.c b/kernel/kprintf.c deleted file mode 100644 index 4f0feaef2..000000000 --- a/kernel/kprintf.c +++ /dev/null @@ -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 - -#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); -} diff --git a/kernel/main.c b/kernel/main.c index dd2100b80..d0223980b 100755 --- a/kernel/main.c +++ b/kernel/main.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 @@ -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); } diff --git a/kernel/mpx.s b/kernel/mpx.s deleted file mode 100755 index d6006c189..000000000 --- a/kernel/mpx.s +++ /dev/null @@ -1,9 +0,0 @@ -# -! Chooses between the 8086 and 386 versions of the Minix startup code. - -#include -#if _WORD_SIZE == 2 -#include "mpx88.s" -#else -#include "mpx386.s" -#endif diff --git a/kernel/mpx88.s b/kernel/mpx88.s deleted file mode 100755 index e69de29bb..000000000 diff --git a/kernel/priv.h b/kernel/priv.h index c02208b3c..913d27105 100755 --- a/kernel/priv.h +++ b/kernel/priv.h @@ -12,7 +12,6 @@ * Jul 01, 2005 Created. (Jorrit N. Herder) */ #include -#include "protect.h" #include "const.h" #include "type.h" diff --git a/kernel/proc.c b/kernel/proc.c index a07159f84..2e6a717c9 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -43,6 +43,7 @@ #include "kernel.h" #include "proc.h" #include +#include /* 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 } diff --git a/kernel/proc.h b/kernel/proc.h index bc1f7f547..9f0a264a4 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -10,22 +10,12 @@ * struct proc, be sure to change sconst.h to match. */ #include -#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 */ diff --git a/kernel/profile.c b/kernel/profile.c index ce4f50ac0..7e5d6aac8 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -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 +#include #include "kernel.h" #include "profile.h" #include "proc.h" @@ -29,70 +30,50 @@ #if SPROFILE #include -#include -/* 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 */ } diff --git a/kernel/profile.h b/kernel/profile.h index c8f54d87b..048e00c0d 100644 --- a/kernel/profile.h +++ b/kernel/profile.h @@ -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 */ diff --git a/kernel/proto.h b/kernel/proto.h index 084102402..b65a17144 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -4,6 +4,7 @@ #define PROTO_H #include +#include /* 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) ); - -/* 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) ); + 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) ); + +/* 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 */ diff --git a/kernel/start.c b/kernel/start.c index 1fbad7991..4b8fedf85 100755 --- a/kernel/start.c +++ b/kernel/start.c @@ -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 #include +#include + +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); } /*===========================================================================* diff --git a/kernel/system.c b/kernel/system.c index c0151ac4e..68d577d0b 100755 --- a/kernel/system.c +++ b/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 #include #include -#if (CHIP == INTEL) -#include -#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)); diff --git a/kernel/system/Makefile b/kernel/system/Makefile index 7916a24de..237a1e303 100644 --- a/kernel/system/Makefile +++ b/kernel/system/Makefile @@ -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 diff --git a/kernel/system/do_devio.c b/kernel/system/do_devio.c index 9c98bba00..810b5a9d0 100644 --- a/kernel/system/do_devio.c +++ b/kernel/system/do_devio.c @@ -10,6 +10,7 @@ #include "../system.h" #include #include +#include #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); } } diff --git a/kernel/system/do_exec.c b/kernel/system/do_exec.c index 554819856..909d63f3e 100644 --- a/kernel/system/do_exec.c +++ b/kernel/system/do_exec.c @@ -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, "", P_NAME_LEN); } + return(OK); } #endif /* USE_EXEC */ diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index 18437425e..b1daba701 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -8,9 +8,6 @@ #include "../system.h" #include -#if (CHIP == INTEL) -#include "../protect.h" -#endif #include @@ -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 diff --git a/kernel/system/do_getinfo.c b/kernel/system/do_getinfo.c index 0017fb4de..d365105a6 100644 --- a/kernel/system/do_getinfo.c +++ b/kernel/system/do_getinfo.c @@ -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); diff --git a/kernel/system/do_newmap.c b/kernel/system/do_newmap.c index fb24fa748..b595334a7 100644 --- a/kernel/system/do_newmap.c +++ b/kernel/system/do_newmap.c @@ -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); diff --git a/kernel/system/do_nice.c b/kernel/system/do_nice.c index bf5aad9e1..64a23ab78 100644 --- a/kernel/system/do_nice.c +++ b/kernel/system/do_nice.c @@ -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); diff --git a/kernel/system/do_safecopy.c b/kernel/system/do_safecopy.c index 41e3a7968..38bc2b19b 100644 --- a/kernel/system/do_safecopy.c +++ b/kernel/system/do_safecopy.c @@ -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. diff --git a/kernel/system/do_segctl.c b/kernel/system/do_segctl.c index 97e56937f..df723a837 100644 --- a/kernel/system/do_segctl.c +++ b/kernel/system/do_segctl.c @@ -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; diff --git a/kernel/system/do_sigreturn.c b/kernel/system/do_sigreturn.c index f887eb428..97a99c34a 100644 --- a/kernel/system/do_sigreturn.c +++ b/kernel/system/do_sigreturn.c @@ -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 */ diff --git a/kernel/system/do_sigsend.c b/kernel/system/do_sigsend.c index 85b62e7a3..b118edb34 100644 --- a/kernel/system/do_sigsend.c +++ b/kernel/system/do_sigsend.c @@ -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; diff --git a/kernel/system/do_sprofile.c b/kernel/system/do_sprofile.c index 9803338af..6c6198735 100644 --- a/kernel/system/do_sprofile.c +++ b/kernel/system/do_sprofile.c @@ -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)); diff --git a/kernel/system/do_trace.c b/kernel/system/do_trace.c index 8977ceaad..19299b3af 100644 --- a/kernel/system/do_trace.c +++ b/kernel/system/do_trace.c @@ -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. diff --git a/kernel/system/do_umap.c b/kernel/system/do_umap.c index 93331a7dd..933609523 100644 --- a/kernel/system/do_umap.c +++ b/kernel/system/do_umap.c @@ -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; diff --git a/kernel/system/do_vdevio.c b/kernel/system/do_vdevio.c index ff417718a..0d6e3c718 100644 --- a/kernel/system/do_vdevio.c +++ b/kernel/system/do_vdevio.c @@ -11,6 +11,7 @@ #include "../system.h" #include #include +#include #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 - 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 /*===========================================================================* * 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); -} - -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); + vm_map_range(base_clicks << CLICK_SHIFT, + size_clicks << CLICK_SHIFT, base_clicks << CLICK_SHIFT); } -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; - } -} diff --git a/kernel/table.c b/kernel/table.c index 9626fcdeb..f10ea97c3 100755 --- a/kernel/table.c +++ b/kernel/table.c @@ -32,7 +32,6 @@ #include "proc.h" #include "ipc.h" #include -#include /* Define stack sizes for the kernel tasks included in the system image. */ #define NO_STACK 0 diff --git a/kernel/type.h b/kernel/type.h index 7c5e53d57..4a8fb9c93 100755 --- a/kernel/type.h +++ b/kernel/type.h @@ -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 */ diff --git a/kernel/utility.c b/kernel/utility.c index 34263c65b..111fdea93 100755 --- a/kernel/utility.c +++ b/kernel/utility.c @@ -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 +#include /*===========================================================================* * 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); + } + } + } +} + diff --git a/lib/Makefile.in b/lib/Makefile.in index fdeb121a7..f35fbcec9 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -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" diff --git a/lib/ansi/abort.c b/lib/ansi/abort.c index 4ace48a6c..8013b69cf 100755 --- a/lib/ansi/abort.c +++ b/lib/ansi/abort.c @@ -17,5 +17,6 @@ abort(void) { if (_clean) _clean(); /* flush all output files */ raise(SIGABRT); + /* NORETURN */ } diff --git a/lib/generate.sh b/lib/generate.sh index 0d74f20f5..f520a32e7 100644 --- a/lib/generate.sh +++ b/lib/generate.sh @@ -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" diff --git a/lib/ip/domainname.c b/lib/ip/domainname.c index c82d81f24..cae29d778 100755 --- a/lib/ip/domainname.c +++ b/lib/ip/domainname.c @@ -4,6 +4,7 @@ domainname.c #include #include +#include #include int getdomainname(domain, size) diff --git a/lib/posix/_lstat.c b/lib/posix/_lstat.c index bb2108fe8..64e24f057 100644 --- a/lib/posix/_lstat.c +++ b/lib/posix/_lstat.c @@ -1,5 +1,6 @@ #include #define lstat _lstat +#define stat _stat #include #include diff --git a/lib/syslib/pci_set_acl.c b/lib/syslib/pci_set_acl.c index b9f2082ab..2ec17decd 100644 --- a/lib/syslib/pci_set_acl.c +++ b/lib/syslib/pci_set_acl.c @@ -4,6 +4,7 @@ pci_set_acl.c #include "pci.h" #include "syslib.h" +#include #include #include diff --git a/lib/zlib-1.2.3/Makefile.in b/lib/zlib-1.2.3/Makefile.in index 07d3f60bd..f6d469252 100644 --- a/lib/zlib-1.2.3/Makefile.in +++ b/lib/zlib-1.2.3/Makefile.in @@ -2,7 +2,7 @@ CC=cc -CFLAGS=-O +CFLAGS="-O -D_POSIX_SOURCE -D_MINIX" LIBRARIES=libz diff --git a/servers/is/Makefile b/servers/is/Makefile index 9c3c9cbf1..eb8b3a6ca 100644 --- a/servers/is/Makefile +++ b/servers/is/Makefile @@ -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 diff --git a/servers/is/dmp_kernel.c b/servers/is/dmp_kernel.c index 9b0ebc8a4..43c355d1a 100644 --- a/servers/is/dmp_kernel.c +++ b/servers/is/dmp_kernel.c @@ -4,6 +4,7 @@ #include #include #include +#include #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, diff --git a/servers/is/inc.h b/servers/is/inc.h index 88db7e9ec..6c17ee9a1 100644 --- a/servers/is/inc.h +++ b/servers/is/inc.h @@ -28,6 +28,7 @@ #include #include +#include #include "proto.h" #include "glo.h" diff --git a/servers/pm/Makefile b/servers/pm/Makefile index 17d52f216..addc090c0 100644 --- a/servers/pm/Makefile +++ b/servers/pm/Makefile @@ -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 \ diff --git a/servers/pm/alloc.c b/servers/pm/alloc.c index f81c2167e..6035b38ce 100644 --- a/servers/pm/alloc.c +++ b/servers/pm/alloc.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "mproc.h" #include "../../kernel/const.h" #include "../../kernel/config.h" diff --git a/servers/pm/main.c b/servers/pm/main.c index 58d66f34d..76e58ce5f 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "mproc.h" #include "param.h" diff --git a/servers/pm/misc.c b/servers/pm/misc.c index 7ce14d634..998d87113 100644 --- a/servers/pm/misc.c +++ b/servers/pm/misc.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include "mproc.h" #include "param.h" diff --git a/servers/pm/signal.c b/servers/pm/signal.c index 5dbeb18b8..63c3d9d18 100644 --- a/servers/pm/signal.c +++ b/servers/pm/signal.c @@ -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; diff --git a/servers/pm/utility.c b/servers/pm/utility.c index b38631329..0aaf59b86 100644 --- a/servers/pm/utility.c +++ b/servers/pm/utility.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "../../kernel/const.h" #include "../../kernel/config.h" #include "../../kernel/type.h" diff --git a/servers/rs/Makefile b/servers/rs/Makefile index 04bb1ace8..b5c8ca7d4 100644 --- a/servers/rs/Makefile +++ b/servers/rs/Makefile @@ -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 diff --git a/servers/rs/inc.h b/servers/rs/inc.h index 78407500c..fe56dc625 100644 --- a/servers/rs/inc.h +++ b/servers/rs/inc.h @@ -26,6 +26,7 @@ #include #include +#include #include /* For priv.h */ #include "../../kernel/priv.h"