]> Zhao Yanbai Git Server - minix.git/commitdiff
Basic VM and other minor improvements.
authorBen Gras <ben@minix3.org>
Wed, 19 Nov 2008 12:26:10 +0000 (12:26 +0000)
committerBen Gras <ben@minix3.org>
Wed, 19 Nov 2008 12:26:10 +0000 (12:26 +0000)
Not complete, probably not fully debugged or optimized.

273 files changed:
Makefile
boot/boot.c
boot/bootimage.c
boot/rawfs.c
commands/Makefile
commands/ash/Makefile
commands/ibm/Makefile
commands/profile/sprofalyze.pl
commands/ps/ps.c
commands/simple/Makefile
commands/simple/last.c
commands/simple/mkfs.c
commands/simple/top.c
commands/syslogd/Makefile
drivers/amddev/Makefile
drivers/amddev/amddev.c
drivers/at_wini/Makefile
drivers/at_wini/at_wini.c
drivers/audio/es1370/Makefile
drivers/audio/es1371/Makefile
drivers/audio/framework/audio_fw.c
drivers/audio/sb16/Makefile
drivers/bios_wini/Makefile
drivers/bios_wini/bios_wini.c
drivers/dp8390/Makefile
drivers/dp8390/dp8390.c
drivers/dpeth/Makefile
drivers/floppy/Makefile
drivers/floppy/floppy.c
drivers/fxp/Makefile
drivers/fxp/fxp.c
drivers/lance/Makefile
drivers/lance/lance.c
drivers/libdriver/Makefile
drivers/libdriver/driver.c
drivers/libdriver/driver.h
drivers/libdriver_asyn/Makefile
drivers/libdriver_asyn/driver.c
drivers/libdriver_asyn/driver.h
drivers/log/Makefile
drivers/log/diag.c
drivers/log/log.c
drivers/memory/Makefile
drivers/memory/memory.c
drivers/memory/ramdisk/rc
drivers/orinoco/Makefile
drivers/orinoco/hermes.c
drivers/orinoco/orinoco.c
drivers/pci/Makefile
drivers/pci/main.c
drivers/pci/pci.c
drivers/printer/Makefile
drivers/random/Makefile
drivers/readclock/Makefile
drivers/rtl8139/Makefile
drivers/sb16/Makefile
drivers/ti1225/Makefile
drivers/ti1225/ti1225.c
drivers/tty/Makefile
drivers/tty/console.c
drivers/tty/keyboard.c
drivers/tty/keymaps/Makefile
drivers/tty/pty.c
drivers/tty/rs232.c
drivers/tty/tty.c
drivers/tty/tty.h
etc/drivers.conf
etc/make.conf
etc/rc
include/minix/com.h
include/minix/config.h
include/minix/const.h
include/minix/devio.h
include/minix/ipc.h
include/minix/sys_config.h
include/minix/syslib.h
include/minix/sysutil.h
include/minix/tty.h [new file with mode: 0644]
include/minix/type.h
include/minix/vm.h [new file with mode: 0755]
include/sys/ioc_tty.h
include/sys/mman.h [new file with mode: 0755]
include/sys/video.h [new file with mode: 0644]
include/sys/vm.h
include/sys/vm_i386.h [new file with mode: 0644]
include/time.h
include/tools.h
kernel/Makefile
kernel/arch/i386/Makefile
kernel/arch/i386/arch_do_vmctl.c [new file with mode: 0644]
kernel/arch/i386/do_int86.c
kernel/arch/i386/do_readbios.c
kernel/arch/i386/do_sdevio.c
kernel/arch/i386/exception.c
kernel/arch/i386/include/archconst.h
kernel/arch/i386/include/archtypes.h
kernel/arch/i386/klib386.s
kernel/arch/i386/memory.c
kernel/arch/i386/mpx386.s
kernel/arch/i386/protect.c
kernel/arch/i386/proto.h
kernel/arch/i386/sconst.h
kernel/arch/i386/system.c
kernel/arch/i386/vm.h [new file with mode: 0644]
kernel/clock.c
kernel/config.h
kernel/const.h
kernel/debug.c
kernel/debug.h
kernel/glo.h
kernel/interrupt.c
kernel/ipc.h
kernel/main.c
kernel/proc.c
kernel/proc.h
kernel/profile.c
kernel/profile.h
kernel/proto.h
kernel/start.c
kernel/system.c
kernel/system.h
kernel/system/Makefile
kernel/system/do_abort.c
kernel/system/do_copy.c
kernel/system/do_cprofile.c
kernel/system/do_devio.c
kernel/system/do_exec.c
kernel/system/do_exit.c
kernel/system/do_fork.c
kernel/system/do_getinfo.c
kernel/system/do_irqctl.c
kernel/system/do_mapdma.c
kernel/system/do_newmap.c
kernel/system/do_privctl.c
kernel/system/do_profbuf.c
kernel/system/do_safecopy.c
kernel/system/do_sigreturn.c
kernel/system/do_sigsend.c
kernel/system/do_sprofile.c
kernel/system/do_trace.c
kernel/system/do_umap.c
kernel/system/do_unused.c
kernel/system/do_vcopy.c
kernel/system/do_vdevio.c
kernel/system/do_vm.c [deleted file]
kernel/system/do_vmctl.c [new file with mode: 0644]
kernel/table.c
kernel/type.h
kernel/utility.c
kernel/vm.h [new file with mode: 0644]
lib/other/Makefile.in
lib/other/_getnprocnr.c
lib/other/_vm_dmacalls.c [new file with mode: 0644]
lib/posix/Makefile.in
lib/posix/_mmap.c [new file with mode: 0755]
lib/posix/getloadavg.c
lib/stdtime/Makefile.in
lib/syscall/Makefile.in
lib/syscall/mmap.s [new file with mode: 0755]
lib/syscall/vm_dmacalls.s [new file with mode: 0644]
lib/syslib/Makefile.in
lib/syslib/alloc_util.c [new file with mode: 0644]
lib/syslib/ds.c
lib/syslib/panic.c
lib/syslib/safecopies.c
lib/syslib/sys_fork.c
lib/syslib/sys_getinfo.c
lib/syslib/sys_vm_map.c [deleted file]
lib/syslib/sys_vmctl.c [new file with mode: 0755]
lib/syslib/vm_allocmem.c [new file with mode: 0644]
lib/syslib/vm_brk.c [new file with mode: 0644]
lib/syslib/vm_exec_newmem.c [new file with mode: 0644]
lib/syslib/vm_exit.c [new file with mode: 0644]
lib/syslib/vm_fork.c [new file with mode: 0644]
lib/syslib/vm_map_phys.c [new file with mode: 0644]
lib/syslib/vm_push_sig.c [new file with mode: 0644]
lib/syslib/vm_umap.c [new file with mode: 0644]
lib/sysutil/Makefile.in
lib/sysutil/kputc.c
lib/sysutil/micro_delay.c
lib/sysutil/stacktrace.c [new file with mode: 0644]
lib/sysutil/sys_hz.c [new file with mode: 0644]
servers/Makefile
servers/ds/Makefile
servers/inet/Makefile
servers/inet/generic/eth.c
servers/inet/mnx_eth.c
servers/init/Makefile
servers/is/Makefile
servers/is/dmp.c
servers/is/dmp_kernel.c
servers/is/dmp_pm.c
servers/is/main.c
servers/mfs/Makefile
servers/mfs/buf.h
servers/mfs/cache.c
servers/mfs/const.h
servers/mfs/device.c
servers/mfs/glo.h
servers/mfs/main.c
servers/mfs/mount.c
servers/mfs/proto.h
servers/mfs/read.c
servers/mfs/super.c
servers/mfs/super.h
servers/mfs/type.h
servers/mfs/utility.c
servers/mfs/write.c
servers/pm/Makefile
servers/pm/alloc.c [deleted file]
servers/pm/asynsend.c [deleted file]
servers/pm/break.c
servers/pm/const.h
servers/pm/exec.c
servers/pm/forkexit.c
servers/pm/kputc.c
servers/pm/main.c
servers/pm/misc.c
servers/pm/mproc.h
servers/pm/profile.c
servers/pm/proto.h
servers/pm/signal.c
servers/pm/trace.c
servers/pm/utility.c
servers/rs/Makefile
servers/rs/exec.c
servers/rs/manager.c
servers/rs/service.c
servers/vfs/Makefile
servers/vfs/buf.h [deleted file]
servers/vfs/device.c
servers/vfs/exec.c
servers/vfs/link.c
servers/vfs/main.c
servers/vfs/misc.c
servers/vfs/mmap.c [new file with mode: 0644]
servers/vfs/mount.c
servers/vfs/open.c
servers/vfs/pipe.c
servers/vfs/proto.h
servers/vfs/utility.c
servers/vm/Makefile [new file with mode: 0644]
servers/vm/alloc.c [new file with mode: 0644]
servers/vm/asynsend.c [new file with mode: 0644]
servers/vm/break.c [new file with mode: 0644]
servers/vm/exec.c [new file with mode: 0644]
servers/vm/exit.c [new file with mode: 0644]
servers/vm/fork.c [new file with mode: 0644]
servers/vm/glo.h [new file with mode: 0644]
servers/vm/i386/Makefile [new file with mode: 0644]
servers/vm/i386/arch_pagefaults.c [new file with mode: 0644]
servers/vm/i386/arch_vmproc.h [new file with mode: 0644]
servers/vm/i386/memory.h [new file with mode: 0644]
servers/vm/i386/pagefaults.h [new file with mode: 0644]
servers/vm/i386/pagetable.c [new file with mode: 0644]
servers/vm/i386/pagetable.h [new file with mode: 0644]
servers/vm/i386/util.s [new file with mode: 0644]
servers/vm/i386/vm.c [new file with mode: 0644]
servers/vm/main.c [new file with mode: 0644]
servers/vm/mmap.c [new file with mode: 0644]
servers/vm/pagefaults.c [new file with mode: 0644]
servers/vm/proto.h [new file with mode: 0644]
servers/vm/region.c [new file with mode: 0644]
servers/vm/region.h [new file with mode: 0644]
servers/vm/sanitycheck.h [new file with mode: 0644]
servers/vm/signal.c [new file with mode: 0644]
servers/vm/slaballoc.c [new file with mode: 0644]
servers/vm/util.h [new file with mode: 0644]
servers/vm/utility.c [new file with mode: 0644]
servers/vm/vfs.c [new file with mode: 0644]
servers/vm/vm.h [new file with mode: 0644]
servers/vm/vmproc.h [new file with mode: 0644]
tools/Makefile

index f31a1df4a1d1ce9b627633b927d4e75dd589dbbf..0c2ea71508093936ca6c6c9d0b6ec235e2932eb7 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,7 @@ usage:
 # 'make install' target.
 # 
 # etcfiles has to be done first.
-world: includes depend libraries cmds install postinstall
+world: includes depend cmds install postinstall
 
 includes:
        cd include && $(MAKE) install gcc
index eae2ae75c85b18dffff8ab21d3caafc33b49a07c..ddd04fca5142b65df1dcc11d90fce495ade4ca2e 100755 (executable)
@@ -18,6 +18,7 @@ char version[]=               "2.20";
 #include <string.h>
 #include <errno.h>
 #include <ibm/partition.h>
+#include <ibm/bios.h>
 #include <minix/config.h>
 #include <minix/type.h>
 #include <minix/com.h>
@@ -28,6 +29,7 @@ char version[]=               "2.20";
 #if BIOS
 #include <kernel/const.h>
 #include <kernel/type.h>
+#include <sys/video.h>
 #endif
 #if UNIX
 #include <stdio.h>
@@ -46,6 +48,10 @@ char version[]=              "2.20";
 #define arraylimit(a)          ((a) + arraysize(a))
 #define between(a, c, z)       ((unsigned) ((c) - (a)) <= ((z) - (a)))
 
+u16_t vid_port;                /* Video i/o port. */
+u32_t vid_mem_base;    /* Video memory base address. */
+u32_t vid_mem_size;    /* Video memory size. */
+
 int fsok= -1;          /* File system state.  Initially unknown. */
 
 static int block_size;
@@ -590,6 +596,19 @@ void initialize(void)
                bootdev.name[5] += bootdev.secondary;
        }
 
+       /* Find out about the video hardware. */
+        raw_copy(mon2abs(&vid_port), VDU_CRT_BASE_ADDR, sizeof(vid_port));
+       if(vid_port == C_6845) {
+               vid_mem_base = COLOR_BASE;
+               vid_mem_size = COLOR_SIZE;
+       } else {
+               vid_mem_base = MONO_BASE;
+               vid_mem_size = MONO_SIZE;
+       }
+
+       if(get_video() >= 3)
+               vid_mem_size = EGA_SIZE;
+
 #else /* DOS */
        /* Take the monitor out of the memory map if we have memory to spare,
         * note that only half our PSP is needed at the new place, the first
@@ -1959,3 +1978,4 @@ void main(int argc, char **argv)
 /*
  * $PchId: boot.c,v 1.14 2002/02/27 19:46:14 philip Exp $
  */
+
index fcedfd7201d4e49e20095f0c72491a4a45d31d89..66354c173423a6742fa8ac7647995b448f2afd3a 100755 (executable)
@@ -18,6 +18,8 @@
 #include <minix/const.h>
 #include <minix/type.h>
 #include <minix/syslib.h>
+#include <minix/tty.h>
+#include <sys/video.h>
 #include <kernel/const.h>
 #include <kernel/type.h>
 #include <ibm/partition.h>
 
 static int block_size = 0;
 
+extern u16_t vid_port;         /* Video i/o port. */
+extern u32_t vid_mem_base;     /* Video memory base address. */
+extern u32_t vid_mem_size;     /* Video memory size. */
+
 #define click_shift    clck_shft       /* 7 char clash with click_size. */
 
 /* Some kernels have extra features: */
@@ -376,6 +382,42 @@ int get_segment(u32_t *vsec, long *size, u32_t *addr, u32_t limit)
        return 1;
 }
 
+static void restore_screen(void)
+{
+       struct boot_tty_info boot_tty_info;
+       u32_t info_location;
+#define LINES 25
+#define CHARS 80
+       static u16_t consolescreen[LINES][CHARS];
+
+       /* Try and find out what the main console was displaying
+        * by looking into video memory.
+        */
+
+       info_location = vid_mem_base+vid_mem_size-sizeof(boot_tty_info);
+        raw_copy(mon2abs(&boot_tty_info), info_location,
+                sizeof(boot_tty_info));
+
+        if(boot_tty_info.magic == TTYMAGIC) {
+                if(boot_tty_info.flags & (BTIF_CONSORIGIN|BTIF_CONSCURSOR) ==
+                       (BTIF_CONSORIGIN|BTIF_CONSCURSOR)) {
+                       int line;
+                       raw_copy(mon2abs(consolescreen), 
+                               vid_mem_base + boot_tty_info.consorigin,
+                               sizeof(consolescreen));
+                       clear_screen();
+                       for(line = 0; line < LINES; line++) {
+                               int ch;
+                               for(ch = 0; ch < CHARS; ch++) {
+                                       u16_t newch = consolescreen[line][ch] & BYTE;
+                                       if(newch < ' ') newch = ' ';
+                                       putch(newch);
+                               }
+                       }
+               }
+        }
+}
+
 void exec_image(char *image)
 /* Get a Minix image into core, patch it up and execute. */
 {
@@ -607,8 +649,13 @@ void exec_image(char *image)
 
        /* Read leftover character, if any. */
        scan_keyboard();
+
+       /* Restore screen contents. */
+       restore_screen();
 }
 
+
+
 ino_t latest_version(char *version, struct stat *stp)
 /* Recursively read the current directory, selecting the newest image on
  * the way up.  (One can't use r_stat while reading a directory.)
index 06ec2f50f550af45e5822adc1078226f5936d466..27b25c9849eb364b6dfd7724c6df4fa44be86541 100755 (executable)
@@ -61,7 +61,7 @@ static char dirbuf[_MAX_BLOCK_SIZE];  /* Scratch/Directory block. */
 static block_t a_indir, a_dindir;      /* Addresses of the indirects. */
 static off_t dirpos;                   /* Reading pos in a dir. */
 
-#define fsbuf(b)       (* (struct buf *) (b))
+#define fsbuf(b)       (* (union fsdata_u *) (b))
 
 #define        zone_shift      (super.s_log_zone_size) /* zone to block ratio */
 
@@ -110,6 +110,7 @@ void r_stat(Ino_t inum, struct stat *stp)
        block_t block;
        block_t ino_block;
        ino_t ino_offset;
+       union fsdata_u *blockbuf;
 
        /* Calculate start of i-list */
        block = START_BLOCK + super.s_imap_blocks + super.s_zmap_blocks;
@@ -120,13 +121,14 @@ void r_stat(Ino_t inum, struct stat *stp)
        block += ino_block;
 
        /* Fetch the block */
-       readblock(block, scratch, block_size);
+       blockbuf = (union fsdata_u *) scratch;
+       readblock(block, blockbuf, block_size);
 
        if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
                d2_inode *dip;
                int i;
 
-               dip= &fsbuf(scratch).b_v2_ino[ino_offset];
+               dip= &blockbuf->b__v2_ino[ino_offset];
 
                curfil.i_mode= dip->d2_mode;
                curfil.i_nlinks= dip->d2_nlinks;
@@ -142,7 +144,7 @@ void r_stat(Ino_t inum, struct stat *stp)
                d1_inode *dip;
                int i;
 
-               dip= &fsbuf(scratch).b_v1_ino[ino_offset];
+               dip= &blockbuf->b__v1_ino[ino_offset];
 
                curfil.i_mode= dip->d1_mode;
                curfil.i_nlinks= dip->d1_nlinks;
@@ -263,8 +265,8 @@ off_t r_vir2abs(off_t virblk)
 
                i = zone / (zone_t) nr_indirects;
                ind_zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
-                               ? fsbuf(dindir).b_v2_ind[i]
-                               : fsbuf(dindir).b_v1_ind[i];
+                               ? fsbuf(dindir).b__v2_ind[i]
+                               : fsbuf(dindir).b__v1_ind[i];
                zone %= (zone_t) nr_indirects;
        }
        if (ind_zone == 0) return 0;
@@ -276,8 +278,8 @@ off_t r_vir2abs(off_t virblk)
                a_indir= z;
        }
        zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
-               ? fsbuf(indir).b_v2_ind[(int) zone]
-               : fsbuf(indir).b_v1_ind[(int) zone];
+               ? fsbuf(indir).b__v2_ind[(int) zone]
+               : fsbuf(indir).b__v1_ind[(int) zone];
 
        /* Calculate absolute datablock number */
        z = ((block_t) zone << zone_shift) + zone_index;
index 3f51f484caf86bd4a06754b06c82e77c8d75faa4..930c9b18cfb9f9cb0a2be4a2487086cea0242e41 100755 (executable)
@@ -4,7 +4,7 @@ MAKE    = exec make -$(MAKEFLAGS)
 BZIP2=bzip2-1.0.3
 FLEX=flex-2.5.4
 
-SMALLPROGRAMS=`arch` aal advent ash autil awk byacc cawf cron de dhcpd dis88 elle elvis ftp101 ftpd200 ibm indent m4 make mdb mined patch pax profile ps reboot rlogind scripts sh simple syslogd talk talkd telnet telnetd urlget yap zoneinfo
+SMALLPROGRAMS=`arch` aal advent ash autil awk byacc cawf cron de dhcpd dis88 elle elvis ftp101 ftpd200 ibm indent m4 make mined patch pax profile ps reboot rlogind scripts sh simple syslogd talk talkd telnet telnetd urlget yap
 
 usage:
        @echo "Usage: make all          # Compile all commands" >&2
index 108bba28a54e67e1b263b5fe7cc1093c6768c444..3acb338fe515bd81d50fbe5f6212c9363940fa5d 100755 (executable)
@@ -55,16 +55,16 @@ sh: $(OBJS)
 install:       /usr/bin/ash /usr/bin/sh /bin/sh /bin/bigsh
 
 /usr/bin/ash:  sh
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/sh:   /usr/bin/ash
-       install -l $? $@
+       install -l $< $@
 
 /bin/sh:       /usr/bin/ash
-       install -lcs $? $@
+       install -lcs $< $@
 
 /bin/bigsh:    /usr/bin/ash
-       install -S 6600k -lcs $? $@
+       install -S 6600k -lcs $< $@
 
 clean:
        rm -f $(CLEANFILES) sh core
@@ -75,7 +75,7 @@ token.def: mktokens
        sh mktokens
 
 arith.c:       arith.y
-       $(YACC) -d $?
+       $(YACC) -d $<
        mv y.tab.c $@
        mv y.tab.h arith_y.h
 
index 95337f1a6d8805e528e538a95aff46163c18d35d..26f9b10a98f66ff56f30c48ff5935c5700de2d21 100755 (executable)
@@ -22,8 +22,7 @@ ALL   = \
        postmort \
        recwave \
        repartition \
-       screendump \
-       sdump \
+       screendump
 
 all:   $(ALL)
 
@@ -109,7 +108,6 @@ install:    \
        /usr/bin/recwave \
        /usr/bin/repartition \
        /usr/bin/screendump \
-       /usr/bin/sdump \
        /bin/loadkeys \
 
 /usr/bin/atnormalize:  atnormalize
index 3c2d7c08b0f9fc13ecee23b43b83e4b36ebf2956..36caff90419db8d49a6213e70254aef045be1be3 100755 (executable)
@@ -30,11 +30,11 @@ servers/inet/inet
 servers/is/is
 servers/pm/pm
 servers/rs/rs
+servers/vm/vm
 servers/rs/service
 
 drivers/at_wini/at_wini
 drivers/bios_wini/bios_wini
-drivers/cmos/cmos
 drivers/dp8390/dp8390
 drivers/dpeth/dpeth
 drivers/floppy/floppy
index f6f5fe31db174693e71584dd2f2c166e744e776e..fa82bdd335977cbdc902bd0a542eff785c72eb5e 100644 (file)
@@ -84,6 +84,7 @@
 #include "../../servers/pm/mproc.h"
 #include "../../servers/vfs/fproc.h"
 #include "../../servers/vfs/const.h"
+#include "../../servers/mfs/const.h"
 
 
 /*----- ps's local stuff below this line ------*/
@@ -109,7 +110,9 @@ size_t n_ttyinfo;           /* Number of tty info slots */
 
 /* Number of tasks and processes and addresses of the main process tables. */
 int nr_tasks, nr_procs;                
+#if 0
 vir_bytes proc_addr, mproc_addr, fproc_addr;   
+#endif
 extern int errno;
 
 /* Process tables of the kernel, MM, and FS. */
@@ -315,10 +318,14 @@ char *argv[];
   if ((memfd = open(MEM_PATH, O_RDONLY)) == -1) err(MEM_PATH);
   if (gettynames() == -1) err("Can't get tty names");
 
+#if 0
   getsysinfo(PM_PROC_NR, SI_PROC_ADDR, &mproc_addr);
   getsysinfo(FS_PROC_NR, SI_PROC_ADDR, &fproc_addr);
+#endif
   getsysinfo(PM_PROC_NR, SI_KINFO, &kinfo);
+#if 0
   proc_addr = kinfo.proc_addr;
+#endif
   nr_tasks = kinfo.nr_tasks;   
   nr_procs = kinfo.nr_procs;
 
@@ -329,6 +336,7 @@ char *argv[];
   if (ps_proc == NULL || ps_mproc == NULL || ps_fproc == NULL)
        err("Out of memory");
 
+#if 0
   /* Get kernel process table */
   if (addrread(kmemfd, (phys_clicks) 0,
                proc_addr, (char *) ps_proc,
@@ -347,6 +355,17 @@ char *argv[];
                nr_procs * sizeof(ps_fproc[0]))
                        != nr_procs * sizeof(ps_fproc[0]))
        err("Can't get fs proc table from /dev/mem");
+#else
+       if(getsysinfo(PM_PROC_NR, SI_KPROC_TAB, ps_proc) < 0) {
+               fprintf(stderr, "getsysinfo() for SI_KPROC_TAB failed.\n");
+               exit(1);
+       }
+
+       if(getsysinfo(PM_PROC_NR, SI_PROC_TAB, ps_mproc) < 0) {
+               fprintf(stderr, "getsysinfo() for SI_PROC_TAB failed.\n");
+               exit(1);
+       }
+#endif
 
   /* We need to know where INIT hangs out. */
   for (i = FS_PROC_NR; i < nr_procs; i++) {
@@ -479,8 +498,13 @@ int endpoints;
   bufp->ps_flags = ps_proc[p_ki].p_rts_flags;
 
   if (p_nr >= low_user) {
+#if 0
        bufp->ps_dev = ps_fproc[p_nr].fp_tty;
        bufp->ps_ftask = ps_fproc[p_nr].fp_task;
+#else
+       bufp->ps_dev = 0;
+       bufp->ps_ftask = 0;
+#endif
   } else {
        bufp->ps_dev = 0;
        bufp->ps_ftask = 0;
@@ -511,9 +535,11 @@ int endpoints;
                bufp->ps_state = T_STATE;       /* stopped (traced) */
        else if (ps_proc[p_ki].p_rts_flags == 0)
                bufp->ps_state = R_STATE;       /* in run-queue */
+#if 0
        else if (ps_mproc[p_nr].mp_flags & (WAITING | PAUSED | SIGSUSPENDED) ||
                 ps_fproc[p_nr].fp_suspended == SUSPENDED)
                bufp->ps_state = S_STATE;       /* sleeping */
+#endif
        else
                bufp->ps_state = W_STATE;       /* a short wait */
   } else {                     /* tasks are simple */
index 31b0ac2de66489da320c296fdd28b602b645b805..8aa7fc4a681012dc052985ab1940ab476de736dd 100755 (executable)
@@ -16,7 +16,7 @@ CC    = exec cc
 # all: $(ALL)                  default rule, make all binaries
 #
 # cat: cat.c                   'cat' is made from 'cat.c'
-#      $(CCLD) -o $@ $?        compile 'cat.c' ($?) to 'cat' ($@)
+#      $(CCLD) -o $@ $<        compile 'cat.c' ($<) to 'cat' ($@)
 #      install -S 4kw $@       stack size is 8k (8086) or 16k (others)
 #
 # install:     \               rule to install all binaries
@@ -24,11 +24,11 @@ CC  = exec cc
 #      /bin/cat \              important binaries are also in /bin
 #
 # /usr/bin/cat:        cat
-#      install -cs -o bin $? $@        copy 'cat' to '/usr/bin/cat' (-c),
+#      install -cs -o bin $< $@        copy 'cat' to '/usr/bin/cat' (-c),
 #                                      strip symbol table (-s)
 #
 # /bin/cat:    /usr/bin/cat
-#      install -lcs $? $@      install '/bin/cat' by linking (if possible)
+#      install -lcs $< $@      install '/bin/cat' by linking (if possible)
 #                              or copying (otherwise)
 #
 # Some of the binaries are installed under more than one name.  The extra
@@ -108,7 +108,6 @@ ALL = \
        isoread \
        join \
        kill \
-       last \
        leave \
        life \
        loadramdisk \
@@ -224,175 +223,175 @@ arp:    arp.c
        $(CCLD) -o $@ arp.c
 
 at:    at.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 backup:        backup.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 badblocks:     badblocks.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 banner:        banner.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 basename:      basename.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 cal:   cal.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 calendar:      calendar.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 cat:   cat.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 cdiff: cdiff.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 28kw $@
 
 cdprobe: cdprobe.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 28kw $@
 
 cgrep: cgrep.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 5kw $@
 
 chmem: chmem.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 chmod: chmod.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 16kw $@
 
 chown: chown.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 16kw $@
 
 chroot:        chroot.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 ci:    ci.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 cksum: cksum.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 cleantmp:      cleantmp.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 cmp:   cmp.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 co:    co.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 comm:  comm.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 compress:      compress.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 450k $@
 
 cp:    cp.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 32kw $@
 
 crc:   crc.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 cut:   cut.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 dd:    dd.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 20kw $@
 
 decomp16:      decomp16.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 dev2name:      dev2name.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 devsize:       devsize.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 df:    df.c
-       $(CCLD) -I$(SYS) -o $@ $?
+       $(CCLD) -I$(SYS) -o $@ $<
        @install -S 4kw $@
 
 dhrystone:     dhrystone.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 diff:  diff.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 512kw $@
 
 dirname:       dirname.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 du:    du.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 256kw $@
 
 dumpcore:      dumpcore.c
-       $(CCLD) -D_SYSTEM=1 -o $@ $? -lsysutil -lsys 
+       $(CCLD) -D_SYSTEM=1 -o $@ $< -lsys
        @install -S 32k $@
 
 ed:    ed.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 32kw $@
 
 eject: eject.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 env:   env.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 50k $@
 
 expand:        expand.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 factor:        factor.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 fgrep: fgrep.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 10kw $@
 
 file:  file.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 25kw $@
 
 find:  find.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 25kw $@
 
 finger:        finger.c
@@ -404,19 +403,19 @@ fix:      fix.c
        @install -S 32kw $@
 
 fold:  fold.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 fortune:       fortune.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 fsck:  fsck.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8192k $@
 
 fsck1: fsck1.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 32kw $@
 
 getty: getty.c /usr/include/minix/config.h
@@ -424,15 +423,15 @@ getty:    getty.c /usr/include/minix/config.h
        @install -S 4kw $@
 
 gomoku:        gomoku.c
-       $(CCLD) -o $@ $? -lcurses
+       $(CCLD) -o $@ $< -lcurses
        @install -S 8kw $@
 
 grep:  grep.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 32kw $@
 
 head:  head.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 host:  host.c
@@ -444,7 +443,7 @@ hostaddr:   hostaddr.c
        @install -S 8kw $@
 
 id:    id.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 ifconfig:      ifconfig.c
@@ -452,7 +451,7 @@ ifconfig:   ifconfig.c
        @install -S 4kw $@
 
 ifdef: ifdef.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 in.fingerd:    in.fingerd.c
@@ -464,182 +463,182 @@ in.rshd:        in.rshd.c
        @install -S 8kw $@
 
 installx:      install.c       # Note: avoided confict with 'install' rule.
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
 
 intr:  intr.c
        $(CCLD) -o $@ intr.c
        @install -S 4kw $@
 
 irdpd: irdpd.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 isoread:       isoread.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 join:  join.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 kill:  kill.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 last:  last.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 5kw $@
 
 leave: leave.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 life:  life.c
-       $(CCLD) -o $@ $? -lcurses
+       $(CCLD) -o $@ $< -lcurses
        @install -S 15kw $@
 
 loadramdisk:   loadramdisk.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        install -S 4kw $@
 
 login: login.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        install -S 4kw $@
 
 look:  look.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 lp:    lp.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 lpd:   lpd.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 ls:    ls.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 20kw $@
 
 mail:  mail.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 man:   man.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 10kw $@
 
 mesg:  mesg.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 mkdir: mkdir.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 mkfifo:        mkfifo.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 mkfs:  mkfs.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 25kw $@
 
 mknod: mknod.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 mkproto:       mkproto.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 20kw $@
 
 mkswap:        mkswap.c
-       $(CCLD) -I$(SYS) -o $@ $?
+       $(CCLD) -I$(SYS) -o $@ $<
        @install -S 4kw $@
 
 modem: modem.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 mount: mount.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 12kw $@
 
 mt:    mt.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 newroot:       newroot.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 32kw $@
 
 nm:    nm.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 32kw $@
 
 nice:  nice.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 nonamed:       nonamed.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 od:    od.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 passwd:        passwd.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 paste: paste.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 ping:  ping.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 pr:    pr.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 16kw $@
 
 pr_routes:     pr_routes.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 progressbar:   progressbar.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 prep:  prep.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 printf:        printf.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 printenv:      printenv.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 printroot:     printroot.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 proto: proto.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 15kw $@
 
 pwd:   pwd.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 pwdauth:       pwdauth.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 ramdisk:       ramdisk.c
@@ -667,27 +666,27 @@ rev:      rev.c
        @install -S 8kw $@
 
 readall:       readall.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 readfs:        readfs.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 25kw $@
 
 remsync:       remsync.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 256k $@
 
 rget:  rget.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 rlogin:        rlogin.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 rmdir: rmdir.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 15kw $@
 
 rsh:   rsh.c
@@ -695,79 +694,79 @@ rsh:      rsh.c
        @install -S 8kw $@
 
 sed:   sed.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 shar:  shar.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 size:  size.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 sleep: sleep.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 slip:  slip.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 20k $@
 
 sort:  sort.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 30kw $@
 
 split: split.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 stat:  stat.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 strings:       strings.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 strip: strip.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 8kw $@
 
 stty:  stty.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 su:    su.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 sum:   sum.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 swapfs:        swapfs.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 sync:  sync.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 synctree:      synctree.c
-       $(CCLD) -o $@ -wo $?
+       $(CCLD) -o $@ -wo $<
        install -S 256kw $@
 
 sysenv:        sysenv.c
-       $(CCLD) -o $@ -wo $?
+       $(CCLD) -o $@ -wo $<
        @install -S 4kw $@
 
 tail:  tail.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 16kw $@
 
 tar:   tar.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 256kw $@
 
 tcpd:  tcpd.c
@@ -783,62 +782,62 @@ tcpstat:  tcpstat.c
        @install -S 8kw $@
 
 tee:   tee.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 term:  term.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 termcap:       termcap.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 tget:  tget.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 time:  time.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 touch: touch.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 top:   top.c
-       $(CCLD) -o $@ $? -lcurses
+       $(CCLD) -o $@ $< -lcurses
 
 tr:    tr.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 tsort: tsort.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 treecmp:       treecmp.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 truncate:      truncate.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 ttt:   ttt.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 tty:   tty.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 udpstat:       udpstat.c
-       $(CCLD) -o $@ -I$(SERVERS) $?
+       $(CCLD) -o $@ -I$(SERVERS) $<
        @install -S 32k $@
 
 umount:        umount.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 uname: uname.c /usr/include/minix/config.h
@@ -846,57 +845,57 @@ uname:    uname.c /usr/include/minix/config.h
        @install -S 4kw $@
 
 unexpand:      unexpand.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 uniq:  uniq.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 update:        update.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 2kw $@
 
 uud:   uud.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 uue:   uue.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 vol:   vol.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 80k $@      # note: '-S' is upper limit to 'vol -m'
 
 wc:    wc.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 which: which.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 who:   who.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 whoami:        whoami.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 write: write.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
 
 writeisofs:    writeisofs.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
 
 xargs: xargs.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 16kw $@
 
 yes:   yes.c
-       $(CCLD) -o $@ $?
+       $(CCLD) -o $@ $<
        @install -S 4kw $@
 
 install:       \
@@ -989,8 +988,6 @@ install:    \
                /usr/bin/isoinfo \
        /usr/bin/join \
        /usr/bin/kill \
-       /usr/bin/last \
-               /usr/bin/uptime \
        /usr/bin/leave \
        /usr/bin/life \
        /usr/bin/loadramdisk \
@@ -1116,611 +1113,611 @@ install:      \
        #
 
 /usr/bin/add_route:    add_route
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/del_route:    /usr/bin/add_route
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/arp:  arp
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/at:   at
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/backup:       backup
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/restore:      /usr/bin/backup
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/badblocks:    badblocks
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/banner:       banner
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/basename:     basename
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cal:  cal
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/calendar:     calendar
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cat:  cat
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cdiff:        cdiff
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cdprobe: cdprobe
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cgrep:        cgrep
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/chmem:        chmem
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/chmod:        chmod
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/chown:        chown
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /bin/chroot:   chroot
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/chgrp:        /usr/bin/chown
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/ci:   ci
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cksum:        cksum
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cleantmp:     cleantmp
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cmp:  cmp
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/co:   co
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/comm: comm
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/compress:     compress
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/uncompress /usr/bin/zcat:     /usr/bin/compress
-       install -l $? $@
+       install -l $< $@
 
 /bin/cp:       cp
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cp:   cp
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/clone /usr/bin/cpdir \
 /usr/bin/ln /usr/bin/mv /usr/bin/rm:   /usr/bin/cp
-       install -l $? $@
+       install -l $< $@
 
 /bin/ln /bin/mv /bin/rm:       /bin/cp
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/crc:  crc
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/cut:  cut
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/dd:   dd
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /bin/dev2name: dev2name
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/devsize:      devsize
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/decomp16:     decomp16
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/df:   df
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/dhrystone:    dhrystone
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/diff: diff
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/dirname:      dirname
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/du:   du
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/dumpcore:     dumpcore
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/ed:   ed
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/eject:        eject
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/env:  env
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/expand:       expand
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/factor:       factor
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/fgrep:        fgrep
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/file: file
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/find: find
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/finger:       finger
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/fix:  fix
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/fold: fold
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/fortune:      fortune
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/fsck: fsck
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/fsck1:        fsck1
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /bin/getty:    getty
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/getty:        getty
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/gomoku:       gomoku
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/grep: grep
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/egrep:        /usr/bin/grep
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/head: head
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/host: host
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/hostaddr:     hostaddr
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/id:   id
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/ifconfig:     ifconfig
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/ifdef:        ifdef
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/in.fingerd:   in.fingerd
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/in.rshd:      in.rshd
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /bin/install:  installx
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/install:      installx
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/intr: intr
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/irdpd:        irdpd
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/isoread:      isoread
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/isodir /usr/bin/isoinfo:      /usr/bin/isoread
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/join: join
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/kill: kill
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/last: last
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/uptime:       /usr/bin/last
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/leave:        leave
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/life: life
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/loadramdisk:  loadramdisk
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/login:        login
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/look: look
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/lp:   lp
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/lpd:  lpd
-       install -cs -o daemon -m 4755 $? $@
+       install -cs -o daemon -m 4755 $< $@
 
 /usr/bin/ls:   ls
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /bin/ls:       ls
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/mail: mail
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/man:  man
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/mesg: mesg
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/mkdir:        mkdir
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/mkfifo:       mkfifo
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/mkfs: mkfs
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/mknod:        mknod
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/mkproto:      mkproto
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/mkswap:       mkswap
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/modem:        modem
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/mount:        mount
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/mt:   mt
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/newroot:      newroot
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/nm:   nm
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/nice: nice
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/nonamed:      nonamed
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/od:   od
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/passwd:       passwd
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/chfn /usr/bin/chsh:   /usr/bin/passwd
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/paste:        paste
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/ping: ping
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/pr:   pr
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/pr_routes:    pr_routes
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/progressbar:  progressbar
-       install -cs -o root -m 755 $? $@
+       install -cs -o root -m 755 $< $@
 
 /usr/bin/prep: prep
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/printf:       printf
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/printenv:     printenv
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/printroot:    printroot
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/proto:        proto
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/pwd:  pwd
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/lib/pwdauth:      pwdauth
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/ramdisk:      ramdisk
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/rarpd:        rarpd
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/rcp:  rcp
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/rawspeed:     rawspeed
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/rdate:        rdate
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/readall:      readall
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/readlink:     /usr/bin/stat
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/readfs:       readfs
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/remsync:      remsync
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/rev:  rev
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/rget: rget
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/rput: /usr/bin/rget
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/rlogin:       rlogin
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/rmdir:        rmdir
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/rsh:  rsh
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/sed:  sed
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /bin/sed:      sed
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/shar: shar
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/size: size
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/sleep:        sleep
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/slip: slip
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/sort: sort
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/split:        split
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/stat: stat
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/fstat:        /usr/bin/stat
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/strings:      strings
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/strip:        strip
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/stty: stty
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/su:   su
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/sum:  sum
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/swapfs:       swapfs
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/sync: sync
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/synctree:     synctree
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /bin/sysenv:   sysenv
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/sysenv:       sysenv
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tail: tail
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tar:  tar
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tcpd: tcpd
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tcpdp:        tcpdp
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tcpstat:      tcpstat
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tee:  tee
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/term: term
-       install -cs -o bin -g uucp -m 2755 $? $@
+       install -cs -o bin -g uucp -m 2755 $< $@
 
 /usr/bin/termcap:      termcap
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tget: tget
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/time: time
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/top:  top
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/touch:        touch
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tr:   tr
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/treecmp:      treecmp
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/truncate:     truncate
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tsort:        tsort
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/ttt:  ttt
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/tty:  tty
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/udpstat:      udpstat
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/umount:       umount
-       install -cs -o root -m 4755 $? $@
+       install -cs -o root -m 4755 $< $@
 
 /usr/bin/uname:        uname
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/arch: /usr/bin/uname
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/unexpand:     unexpand
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/uniq: uniq
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/update:       update
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/uud:  uud
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/uudecode:     /usr/bin/uud
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/uue:  uue
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/uuencode:     /usr/bin/uue
-       install -l $? $@
+       install -l $< $@
 
 /usr/bin/vol:  vol
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/wc:   wc
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/which:        which
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/who:  who
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/whoami:       whoami
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/write:        write
-       install -cs -o bin -g tty -m 2755 $? $@
+       install -cs -o bin -g tty -m 2755 $< $@
 
 /usr/bin/writeisofs:   writeisofs
-       install -cs -S 2M -o bin $? $@
+       install -cs -S 2M -o bin $< $@
 
 /usr/bin/xargs:        xargs
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /usr/bin/yes:  yes
-       install -cs -o bin $? $@
+       install -cs -o bin $< $@
 
 /bin/cat:      /usr/bin/cat
-       install -lcs $? $@
+       install -lcs $< $@
 
 /bin/fsck:     /usr/bin/fsck
-       install -lcs $? $@
+       install -lcs $< $@
 
 /bin/intr:     /usr/bin/intr
-       install -lcs $? $@
+       install -lcs $< $@
 
 /bin/mount:    /usr/bin/mount
-       install -lcs $? $@
+       install -lcs $< $@
 
 /bin/printroot:        /usr/bin/printroot
-       install -lcs $? $@
+       install -lcs $< $@
 
 /bin/pwd:      /usr/bin/pwd
-       install -lcs $? $@
+       install -lcs $< $@
 
 /bin/sync:     /usr/bin/sync
-       install -lcs $? $@
+       install -lcs $< $@
 
 /bin/umount:   /usr/bin/umount
-       install -lcs $? $@
+       install -lcs $< $@
 
 clean:
        rm -rf $(ALL) a.out core
index 74124b0527c8493016e151cc7e95d1fb80d87608..80b085bf983a253ceb45f4a592bce681a591be11 100755 (executable)
@@ -479,3 +479,4 @@ char *argv[];
   printf("\nwtmp begins %.16s \n", ctime(&wtmp_buffer[0].ut_time));
   return(0);
 }
+
index faddeb51d68e59bd5f14367a94cd003aa757c70c..ef29539ca68f914a58eaf2ba5683da902982a3f2 100755 (executable)
 #define BIN                  2
 #define BINGRP               2
 #define BIT_MAP_SHIFT       13
-#define N_BLOCKS         MAX_BLOCK_NR
-#define N_BLOCKS16       (128L * 1024)
 #define INODE_MAX       ((unsigned) 65535)
 
-/* You can make a really large file system on a 16-bit system, but the array
- * of bits that get_block()/putblock() needs gets a bit big, so we can only
- * prefill MAX_INIT blocks.  (16-bit fsck can't check a file system larger
- * than N_BLOCKS16 anyway.)
- */
-#define MAX_INIT        (sizeof(char *) == 2 ? N_BLOCKS16 : N_BLOCKS)
-
 
 #ifdef DOS
 maybedefine O_RDONLY 4         /* O_RDONLY | BINARY_BIT */
@@ -90,12 +81,12 @@ char *progname;
 
 long current_time, bin_time;
 char *zero, *lastp;
-char umap[MAX_INIT / 8];       /* bit map tells if block read yet */
+char *umap_array;      /* bit map tells if block read yet */
+int umap_array_elements = 0;
 block_t zone_map;              /* where is zone map? (depends on # inodes) */
 int inodes_per_block;
 int fs_version;
 unsigned int block_size;
-block_t max_nrblocks;
 
 FILE *proto;
 
@@ -167,14 +158,12 @@ char *argv[];
   i = 0;
   fs_version = 3;
   inodes_per_block = 0;
-  max_nrblocks = N_BLOCKS;
   block_size = 0;
   while ((ch = getopt(argc, argv, "12b:di:lotB:")) != EOF)
        switch (ch) {
            case '1':
                fs_version = 1;
                inodes_per_block = V1_INODES_PER_BLOCK;
-               max_nrblocks = 0xFFFF;
                break;
            case '2':
                fs_version = 2;
@@ -262,12 +251,6 @@ char *argv[];
        /* Read the line with the block and inode counts. */
        getline(line, token);
        blocks = atol(token[0]);
-       if (blocks > max_nrblocks) pexit("Block count too large");
-       if (sizeof(char *) == 2 && blocks > N_BLOCKS16) {
-               fprintf(stderr,
-               "%s: warning: FS is larger than the %dM that fsck can check!\n",
-                       progname, (int) (N_BLOCKS16 / (1024L * 1024)));
-       }
        inodes = atoi(token[1]);
 
        /* Process mode line for root directory. */
@@ -305,7 +288,6 @@ char *argv[];
 
        }
        if (blocks < 5) pexit("Block count too small");
-       if (blocks > max_nrblocks) pexit("Block count too large");
        if (i < 1) pexit("Inode count too small");
        if (i > INODE_MAX && fs_version < 3) pexit("Inode count too large");
        inodes = (ino_t) i;
@@ -320,6 +302,17 @@ char *argv[];
   nrblocks = blocks;
   nrinodes = inodes;
 
+{
+  size_t bytes;
+  bytes = 1 + blocks/8;
+  if(!(umap_array = malloc(bytes))) {
+       fprintf(stderr, "mkfs: can't allocate block bitmap (%d bytes).\n",
+               bytes);
+       exit(1);
+  }
+  umap_array_elements = bytes;
+}
+
   /* Open special. */
   special(argv[--optind]);
 
@@ -336,7 +329,7 @@ char *argv[];
        }
        testb[0] = 0x3245;
        testb[1] = 0x11FF;
-       testb[block_size-1] = 0x1F2F;
+       testb[block_size/2-1] = 0x1F2F;
        if ((w=write(fd, (char *) testb, block_size)) != block_size) {
                if(w < 0) perror("write");
                printf("%d/%d\n", w, block_size);
@@ -350,7 +343,7 @@ char *argv[];
        testb[1] = 0;
        nread = read(fd, (char *) testb, block_size);
        if (nread != block_size || testb[0] != 0x3245 || testb[1] != 0x11FF ||
-               testb[block_size-1] != 0x1F2F) {
+               testb[block_size/2-1] != 0x1F2F) {
                if(nread < 0) perror("read");
 printf("nread = %d\n", nread);
 printf("testb = 0x%x 0x%x 0x%x\n", testb[0], testb[1], testb[block_size-1]);
@@ -370,24 +363,6 @@ printf("testb = 0x%x 0x%x 0x%x\n", testb[0], testb[1], testb[block_size-1]);
 
   cache_init();
 
-#if (MACHINE == ATARI)
-  if (isdev) {
-       char block0[BLOCK_SIZE];
-       get_block((block_t) 0, block0);
-       /* Need to read twice; first time gets an empty block */
-       get_block((block_t) 0, block0);
-       /* Zero parts of the boot block so the disk won't be
-        * recognized as a tos disk any more. */
-       block0[0] = block0[1] = 0;      /* branch code to boot code    */
-       strncpy(&block0[2], "MINIX ", (size_t) 6);
-       block0[16] = 0;         /* number of FATS              */
-       block0[17] = block0[18] = 0;    /* number of dir entries       */
-       block0[22] = block0[23] = 0;    /* sectors/FAT                 */
-       bzero(&block0[30], 480);/* boot code                   */
-       put_block((block_t) 0, block0);
-  } else
-#endif
-
        put_block((block_t) 0, zero);   /* Write a null boot block. */
 
   zone_shift = 0;              /* for future use */
@@ -1229,12 +1204,14 @@ block_t n;
 
   int w, s, mask, r;
 
-  if (sizeof(char *) == 2 && n >= MAX_INIT) pexit("can't initialize past 128M");
   w = n / 8;
+  if(w >= umap_array_elements) {
+       pexit("umap array too small - this can't happen");
+  }
   s = n % 8;
   mask = 1 << s;
-  r = (umap[w] & mask ? 1 : 0);
-  umap[w] |= mask;
+  r = (umap_array[w] & mask ? 1 : 0);
+  umap_array[w] |= mask;
   return(r);
 }
 
index a5647ff8d33cdd848c4ff7789883ec733e494a41..4679f4f7ffe30d58f6d7e56bf2e9724fecacf625 100644 (file)
@@ -40,6 +40,7 @@
 
 char *Tclr_all;
 
+#if 0
 int print_memory(struct pm_mem_info *pmi)
 {
         int h;
@@ -58,6 +59,7 @@ int print_memory(struct pm_mem_info *pmi)
 
        return 1;
 }
+#endif
 
 int print_load(double *loads, int nloads)
 {
@@ -209,10 +211,13 @@ void showtop(int r)
        int nloads, i, p, lines = 0;
        static struct proc prev_proc[PROCS], proc[PROCS];
        struct winsize winsize;
-        static struct pm_mem_info pmi;
+        /*
+       static struct pm_mem_info pmi;
+       */
        static int prev_uptime, uptime;
        static struct mproc mproc[NR_PROCS];
        struct tms tms;
+       int mem = 0;
 
        uptime = times(&tms);
 
@@ -222,10 +227,13 @@ void showtop(int r)
                exit(1);
        }
 
+#if 0
         if(getsysinfo(PM_PROC_NR, SI_MEM_ALLOC, &pmi) < 0) {
                fprintf(stderr, "getsysinfo() for SI_MEM_ALLOC failed.\n");
+               mem = 0;
                exit(1);;
-       }
+       } else mem = 1;
+#endif
 
        if(getsysinfo(PM_PROC_NR, SI_KPROC_TAB, proc) < 0) {
                fprintf(stderr, "getsysinfo() for SI_KPROC_TAB failed.\n");
@@ -247,7 +255,9 @@ void showtop(int r)
 
        lines += print_load(loads, NLOADS);
        lines += print_proc_summary(proc);
-       lines += print_memory(&pmi);
+#if 0
+       if(mem) { lines += print_memory(&pmi); }
+#endif
 
        if(winsize.ws_row > 0) r = winsize.ws_row;
 
@@ -347,3 +357,4 @@ int main(int argc, char *argv[])
        return 0;
 }
 
+int sys_hz() { return 50; }
index 66094bb24ccbc5489618c0b87974b955c7c2e283..c34a13d556bc66716e86cca244b145179b655804 100644 (file)
@@ -22,7 +22,7 @@ all: $(TARGETS)
 
 syslogd:       syslogd.o
        $(CC) $? $(LDFLAGS)
-       @install -S 8kw $@
+       @install $@
 
 syslog_test: syslog_test.o syslog.o
        $(CC) syslog_test.o syslog.o $(LDFLAGS)
index 85abf1d5a4612c87e29131d453c8c7c568197cde..c231b2b554ce57125af2a40f065e49de0e865916 100644 (file)
@@ -5,8 +5,7 @@ DRIVER = amddev
 CC =   exec cc
 CFLAGS = $(CPROFILE)
 LDFLAGS = -i 
-#LIBS = -lsysutil -lsys -ltimers
-LIBS = -lsysutil -lsys 
+LIBS = -lsys 
 
 OBJ = amddev.o
 
index fe011a9c62f7d1227ef208697147caea425d7d51..1491af5532b37422c65fa5145d6de0fc4f4ebd6e 100644 (file)
@@ -15,7 +15,7 @@ Driver for the AMD Device Exclusion Vector (DEV)
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <sys/vm.h>
+#include <sys/vm_i386.h>
 #include <minix/com.h>
 #include <minix/const.h>
 #include <minix/ipc.h>
@@ -213,17 +213,13 @@ static void write_reg(int function, int index, u32_t value)
 
 static void init_domain(int index)
 {
-       int r;
        size_t o, size, memsize;
        phys_bytes busaddr;
 
        size= 0x100000 / 8;
-       table= malloc(size + PAGE_SIZE);
+       table= alloc_contig(size, AC_ALIGN4K, &busaddr);
        if (table == NULL)
                panic("AMDDEV","malloc failed", NO_NUM);
-       o= (unsigned)table & (PAGE_SIZE-1);
-       if (o)
-               table += PAGE_SIZE-o;
        if (index == 0)
        {
                memset(table, 0, size);
@@ -237,9 +233,6 @@ static void init_domain(int index)
                memset(table, 0x00, size);
        }
 
-       r= sys_umap(SELF, D, (vir_bytes)table, size, &busaddr);
-       if (r != OK)
-               panic("AMDDEV","sys_umap failed", r);
 printf("init_domain: busaddr = %p\n", busaddr);
 
        write_reg(DEVF_BASE_HI, index, 0);
@@ -265,6 +258,7 @@ static void init_map(int index)
        printf("after write: DEVF_MAP: 0x%x\n", read_reg(DEVF_MAP, index));
 }
 
+#if 0
 static int do_add(message *m)
 {
        int r;
@@ -282,19 +276,19 @@ static int do_add(message *m)
                size, start, proc);
 #endif
 
-       if (start % PAGE_SIZE)
+       if (start % I386_PAGE_SIZE)
        {
                printf("amddev`do_add: bad start 0x%x from proc %d\n",
                        start, proc);
                return EINVAL;
        }
-       if (size % PAGE_SIZE)
+       if (size % I386_PAGE_SIZE)
        {
                printf("amddev`do_add: bad size 0x%x from proc %d\n",
                        size, proc);
                return EINVAL;
        }
-       r= sys_umap(proc, D, (vir_bytes)start, size, &busaddr);
+       r= sys_umap(proc, VM_D, (vir_bytes)start, size, &busaddr);
        if (r != OK)
        {
                printf("amddev`do_add: umap failed for 0x%x@0x%x, proc %d\n",
@@ -304,6 +298,7 @@ static int do_add(message *m)
        add_range(busaddr, size);
 
 }
+#endif
 
 static int do_add_phys(message *m)
 {
@@ -319,12 +314,12 @@ static int do_add_phys(message *m)
                size, start);
 #endif
 
-       if (start % PAGE_SIZE)
+       if (start % I386_PAGE_SIZE)
        {
                printf("amddev`do_add_phys: bad start 0x%x\n", start);
                return EINVAL;
        }
-       if (size % PAGE_SIZE)
+       if (size % I386_PAGE_SIZE)
        {
                printf("amddev`do_add_phys: bad size 0x%x\n", size);
                return EINVAL;
@@ -355,12 +350,12 @@ static int do_del_phys(message *m)
                size, start);
 #endif
 
-       if (start % PAGE_SIZE)
+       if (start % I386_PAGE_SIZE)
        {
                printf("amddev`do_del_phys: bad start 0x%x\n", start);
                return EINVAL;
        }
-       if (size % PAGE_SIZE)
+       if (size % I386_PAGE_SIZE)
        {
                printf("amddev`do_del_phys: bad size 0x%x\n", size);
                return EINVAL;
@@ -391,13 +386,13 @@ static int do_add4pci(message *m)
 "amddev`do_add4pci: got request for 0x%x@0x%x from %d for pci dev %u.%u.%u\n",
                size, start, proc, pci_bus, pci_dev, pci_func);
 
-       if (start % PAGE_SIZE)
+       if (start % I386_PAGE_SIZE)
        {
                printf("amddev`do_add4pci: bad start 0x%x from proc %d\n",
                        start, proc);
                return EINVAL;
        }
-       if (size % PAGE_SIZE)
+       if (size % I386_PAGE_SIZE)
        {
                printf("amddev`do_add4pci: bad size 0x%x from proc %d\n",
                        size, proc);
@@ -406,7 +401,7 @@ static int do_add4pci(message *m)
 
        printf("amddev`do_add4pci: should check with PCI\n");
 
-       r= sys_umap(proc, D, (vir_bytes)start, size, &busaddr);
+       r= sys_umap(proc, VM_D, (vir_bytes)start, size, &busaddr);
        if (r != OK)
        {
                printf(
@@ -415,7 +410,7 @@ static int do_add4pci(message *m)
                return r;
        }
 
-       r= adddma(proc, busaddr, size);
+       r= adddma(proc, start, size);
        if (r != 0)
        {
                r= -errno;
@@ -439,9 +434,9 @@ static void add_range(u32_t busaddr, u32_t size)
        printf("add_range: mapping 0x%x@0x%x\n", size, busaddr);
 #endif
 
-       for (o= 0; o<size; o += PAGE_SIZE)
+       for (o= 0; o<size; o += I386_PAGE_SIZE)
        {
-               bit= (busaddr+o)/PAGE_SIZE;
+               bit= (busaddr+o)/I386_PAGE_SIZE;
                table[bit/8] &= ~(1 << (bit % 8));
        }
 }
@@ -454,9 +449,9 @@ static void del_range(u32_t busaddr, u32_t size)
        printf("del_range: mapping 0x%x@0x%x\n", size, busaddr);
 #endif
 
-       for (o= 0; o<size; o += PAGE_SIZE)
+       for (o= 0; o<size; o += I386_PAGE_SIZE)
        {
-               bit= (busaddr+o)/PAGE_SIZE;
+               bit= (busaddr+o)/I386_PAGE_SIZE;
                table[bit/8] |= (1 << (bit % 8));
        }
 }
index cc8d07e0891257807df46d68e88ee4288c615e41..70f93f9ef9ad6c665554292c9c8157aa73f427ff 100644 (file)
@@ -15,7 +15,7 @@ MAKE = exec make
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i -L../libdriver
-LIBS = -lsysutil -lsys -ltimers -ldriver
+LIBS = -ldriver -lsys -ltimers 
 
 OBJ = at_wini.o 
 
index 7c3f9ced13fbb322c8fac7612042a1b32c40c7c6..d69e661f82ee1a42b4ca7c2f222f37615b182ac8 100644 (file)
 
 #include <minix/sysutil.h>
 #include <minix/keymap.h>
+#include <minix/type.h>
 #include <sys/ioc_disk.h>
 #include <ibm/pci.h>
+#include <sys/mman.h>
 
 #define ATAPI_DEBUG        0   /* To debug ATAPI code. */
 
@@ -294,7 +296,6 @@ PRIVATE struct wini {               /* main drive struct, one entry per drive */
 PRIVATE int w_device = -1;
 PRIVATE int w_controller = -1;
 PRIVATE int w_major = -1;
-PRIVATE char w_id_string[40];
 
 PRIVATE int win_tasknr;                        /* my task number */
 PRIVATE int w_command;                 /* current command in execution */
@@ -309,7 +310,7 @@ PRIVATE struct device *w_dv;                /* device's base and size */
 #define ATA_DMA_SECTORS        64
 #define ATA_DMA_BUF_SIZE       (ATA_DMA_SECTORS*SECTOR_SIZE)
 
-PRIVATE char dma_buf[ATA_DMA_BUF_SIZE];
+PRIVATE char *dma_buf;
 PRIVATE phys_bytes dma_buf_phys;
 
 #define N_PRDTE        1024    /* Should be enough for large requests */
@@ -320,7 +321,10 @@ PRIVATE struct prdte
        u16_t prdte_count;
        u8_t prdte_reserved;
        u8_t prdte_flags;
-} prdt[N_PRDTE];
+};
+
+#define PRDT_BYTES (sizeof(struct prdte) * N_PRDTE)
+PRIVATE struct prdte *prdt;
 PRIVATE phys_bytes prdt_phys;
 
 #define PRDTE_FL_EOT   0x80    /* End of table */
@@ -428,6 +432,8 @@ PUBLIC int main(int argc, char *argv[])
 /* Install signal handlers. Ask PM to transform signal into message. */
   struct sigaction sa;
 
+  init_buffer();
+
   sa.sa_handler = SIG_MESS;
   sigemptyset(&sa.sa_mask);
   sa.sa_flags = 0;
@@ -475,16 +481,34 @@ PRIVATE void init_params()
        w_identify_wakeup_ticks = WAKEUP_TICKS;
   }
 
-  if (disable_dma)
-       printf("DMA for ATA devices is disabled.\n");
-
-  s= sys_umap(SELF, D, (vir_bytes)dma_buf, sizeof(dma_buf), &dma_buf_phys);
-  if (s != 0)
-       panic("at_wini", "can't map dma buffer", s);
-
-  s= sys_umap(SELF, D, (vir_bytes)prdt, sizeof(prdt), &prdt_phys);
-  if (s != 0)
-       panic("at_wini", "can't map prd table", s);
+  if (disable_dma) {
+       printf("at_wini%d: DMA for ATA devices is disabled.\n", w_instance);
+  } else {
+       /* Ask for anonymous memory for DMA, that is physically contiguous. */
+       dma_buf = mmap(0, ATA_DMA_BUF_SIZE, PROT_READ|PROT_WRITE,
+               MAP_PREALLOC | MAP_CONTIG | MAP_ANON, -1, 0);
+       prdt = mmap(0, PRDT_BYTES,
+               PROT_READ|PROT_WRITE, MAP_CONTIG | MAP_ANON, -1, 0);
+       if(dma_buf == MAP_FAILED || prdt == MAP_FAILED) {
+               disable_dma = 1;
+               printf("at_wini%d: no dma\n", w_instance);
+       } else {
+               s= sys_umap(SELF, VM_D, (vir_bytes)dma_buf,
+                       ATA_DMA_BUF_SIZE, &dma_buf_phys);
+               if (s != 0)
+                       panic("at_wini", "can't map dma buffer", s);
+
+               s= sys_umap(SELF, VM_D, (vir_bytes)prdt,
+                       PRDT_BYTES, &prdt_phys);
+               if (s != 0)
+                       panic("at_wini", "can't map prd table", s);
+#if 0
+               printf("at_wini%d: physical dma_buf: 0x%lx, "
+                       "prdt tab: 0x%lx\n",
+                       w_instance, dma_buf_phys, prdt_phys);
+#endif
+       }
+  }
 
   if (w_instance == 0) {
          /* Get the number of drives from the BIOS data area */
@@ -524,7 +548,7 @@ PRIVATE void init_params()
                        0 /* no DMA */, NO_IRQ, 0, 0, drive);
                w_next_drive++;
        }
-  }
+  } 
 
   /* Look for controllers on the pci bus. Skip none the first instance,
    * skip one and then 2 for every instance, for every next instance.
@@ -779,15 +803,6 @@ message *m_ptr;
                wn->state |= IGNORING;
                return(ENXIO);
          }
-
-#if VERBOSE
-         printf("%s: AT driver detected ", w_name());
-         if (wn->state & (SMART|ATAPI)) {
-               printf("%.40s\n", w_id_string);
-         } else {
-               printf("%ux%ux%u\n", wn->pcylinders, wn->pheads, wn->psectors);
-         }
-#endif
   }
 
 #if ENABLE_ATAPI
@@ -898,9 +913,6 @@ PRIVATE int w_identify()
        /* This is an ATA device. */
        wn->state |= SMART;
 
-       /* Why are the strings byte swapped??? */
-       for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];
-
        /* Preferred CHS translation mode. */
        wn->pcylinders = id_word(1);
        wn->pheads = id_word(3);
@@ -958,7 +970,8 @@ PRIVATE int w_identify()
                else if (id_dma && dma_base)
                {
                        w= id_word(ID_MULTIWORD_DMA);
-                       if (w & (ID_MWDMA_2_SUP|ID_MWDMA_1_SUP|ID_MWDMA_0_SUP))
+                       if (w_pci_debug &&
+                       (w & (ID_MWDMA_2_SUP|ID_MWDMA_1_SUP|ID_MWDMA_0_SUP)))
                        {
                                printf(
                                "%s: multiword DMA modes supported:%s%s%s\n",
@@ -967,7 +980,8 @@ PRIVATE int w_identify()
                                        (w & ID_MWDMA_1_SUP) ? " 1" : "",
                                        (w & ID_MWDMA_2_SUP) ? " 2" : "");
                        }
-                       if (w & (ID_MWDMA_0_SEL|ID_MWDMA_1_SEL|ID_MWDMA_2_SEL))
+                       if (w_pci_debug &&
+                       (w & (ID_MWDMA_0_SEL|ID_MWDMA_1_SEL|ID_MWDMA_2_SEL)))
                        {
                                printf(
                                "%s: multiword DMA mode selected:%s%s%s\n",
@@ -976,7 +990,7 @@ PRIVATE int w_identify()
                                        (w & ID_MWDMA_1_SEL) ? " 1" : "",
                                        (w & ID_MWDMA_2_SEL) ? " 2" : "");
                        }
-                       if (ultra_dma) 
+                       if (w_pci_debug && ultra_dma) 
                        {
                                w= id_word(ID_ULTRA_DMA);
                                if (w & (ID_UDMA_0_SUP|ID_UDMA_1_SUP|
@@ -1048,9 +1062,6 @@ PRIVATE int w_identify()
        if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, 512)) != OK)
                panic(w_name(),"Call to sys_insw() failed", s);
 
-       /* Why are the strings byte swapped??? */
-       for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1];
-
        size = 0;       /* Size set later. */
 #endif
   } else {
@@ -1114,14 +1125,17 @@ PRIVATE int w_io_test(void)
        int r, save_dev;
        int save_timeout, save_errors, save_wakeup;
        iovec_t iov;
+       static char *buf;
+
 #ifdef CD_SECTOR_SIZE
-       static char buf[CD_SECTOR_SIZE];
+#define BUFSIZE CD_SECTOR_SIZE
 #else
-       static char buf[SECTOR_SIZE];
+#define BUFSIZE SECTOR_SIZE
 #endif
+       STATICINIT(buf, BUFSIZE);
 
        iov.iov_addr = (vir_bytes) buf;
-       iov.iov_size = sizeof(buf);
+       iov.iov_size = BUFSIZE;
        save_dev = w_device;
 
        /* Reduce timeout values for this test transaction. */
@@ -1321,8 +1335,8 @@ int safe;                 /* iov contains addresses (0) or grants? */
                nbytes = diff64(dv_size, position);
        block = div64u(add64(w_dv->dv_base, position), SECTOR_SIZE);
 
-       do_dma= wn->dma;
        do_write= (opcode == DEV_SCATTER_S);
+       do_dma= wn->dma;
        
        if (nbytes >= wn->max_count) {
                /* The drive can't do more then max_count at once. */
@@ -1475,14 +1489,17 @@ int safe;                       /* iov contains addresses (0) or grants? */
                        s=sys_safe_insw(wn->base_cmd + REG_DATA, proc_nr, 
                                (void *) (iov->iov_addr), addr_offset,
                                        SECTOR_SIZE);
+                  if(s != OK) {
+                       panic(w_name(),"Call to sys_safe_insw() failed", s);
+                  }
                   } else {
                        s=sys_insw(wn->base_cmd + REG_DATA, proc_nr, 
                                (void *) (iov->iov_addr + addr_offset),
                                        SECTOR_SIZE);
-                  }
                   if(s != OK) {
                        panic(w_name(),"Call to sys_insw() failed", s);
                   }
+                  }
                } else {
                   if(safe) {
                        s=sys_safe_outsw(wn->base_cmd + REG_DATA, proc_nr,
@@ -1662,14 +1679,14 @@ int safe;
        offset= 0;      /* Offset in current iov */
 
 #if 0
-       printf("setup_dma: proc_nr %d\n", proc_nr);
+       printf("at_wini: setup_dma: proc_nr %d\n", proc_nr);
 #endif
 
        while (size > 0)
        {
 #if 0
                printf(
-               "setup_dma: iov[%d]: addr 0x%x, size %d offset %d, size %d\n",
+               "at_wini: setup_dma: iov[%d]: addr 0x%x, size %d offset %d, size %d\n",
                        i, iov[i].iov_addr, iov[i].iov_size, offset, size);
 #endif
                        
@@ -1679,13 +1696,15 @@ int safe;
                if (n == 0 || (n & 1))
                        panic("at_wini", "bad size in iov", iov[i].iov_size);
                if(safe) {
-                r= sys_umap(proc_nr, GRANT_SEG, iov[i].iov_addr, n,&user_phys);
+                r= sys_umap(proc_nr, VM_GRANT, iov[i].iov_addr, n,&user_phys);
+               if (r != 0)
+                       panic("at_wini", "can't map user buffer (VM_GRANT)", r);
                 user_phys += offset;
                } else {
-                r= sys_umap(proc_nr, D, iov[i].iov_addr+offset, n, &user_phys);
-               }
+                r= sys_umap(proc_nr, VM_D, iov[i].iov_addr+offset, n, &user_phys);
                if (r != 0)
-                       panic("at_wini", "can't map user buffer", r);
+                       panic("at_wini", "can't map user buffer (VM_D)", r);
+               }
                if (user_phys & 1)
                {
                        /* Buffer is not aligned */
@@ -2709,7 +2728,7 @@ PRIVATE int at_in(int line, u32_t port, u32_t *value,
                return OK;
        printf("at_wini%d: line %d: %s failed: %d; port %x\n", 
                w_instance, line, typename, s, value, port);
-        panic(w_name(), "sys_out failed", NO_NUM);
+        panic(w_name(), "sys_in failed", NO_NUM);
 }
 
 #undef panic
index 579c917323582aea667ba496f20918464156e5b7..d10121df6460ec69dee1ba57e1169f924a590221 100644 (file)
@@ -12,7 +12,7 @@ gen_drv_dir = ../../gen_drivers/cyclic_dma
 CC =   exec cc
 CFLAGS = -I$i
 LDFLAGS = -i
-LIBS = -lsys -lsysutil 
+LIBS = -lsys
 
 # build local binary
 all:   es1370
index 309ad04684ccce97e41c08b4f5ff5c0aef7a60a5..ae7d5faf155f4d67138c05afd761dd919079142e 100755 (executable)
@@ -11,7 +11,7 @@ b = $i/ibm
 CC             = exec cc
 CFLAGS         = -I$i
 LDFLAGS = -i
-LIBS   = -lsys -lsysutil 
+LIBS   = -lsys 
 
 PROGRAM_NAME   = es1371
 INSTALL_BIN            = /usr/sbin/$(PROGRAM_NAME)
index de259079841c4021c6b95be888222a7f0dcaa691..38d8e6cdbc41d9537494701d9fc454a97ab92370 100755 (executable)
@@ -45,6 +45,7 @@
 #include "audio_fw.h"
 #include <sys/vm.h>
 #include <minix/ds.h>
+#include <sys/vm_i386.h>
 
 
 FORWARD _PROTOTYPE( int msg_open, (int minor_dev_nr) );
@@ -85,7 +86,6 @@ PUBLIC void main(void)
 
        /* Here is the main loop of the dma driver.  It waits for a message, 
           carries it out, and sends a reply. */
-       printf("%s up and running\n", drv.DriverName);
 
        while(1) {
                receive(ANY, &mess);
@@ -886,19 +886,16 @@ PRIVATE int init_buffers(sub_dev_t *sub_dev_ptr)
        size_t size, off;
        unsigned left;
        u32_t i;
+       phys_bytes ph;
 
        /* allocate dma buffer space */
        size= sub_dev_ptr->DmaSize + 64 * 1024;
-       base= malloc(size + PAGE_SIZE);
+       off = base= alloc_contig(size, AC_ALIGN4K, &ph);
        if (!base) {
                error("%s: failed to allocate dma buffer for channel %d\n", 
                                drv.DriverName,i);
                return EIO;
        }
-       /* Align base */
-       off= ((size_t)base % PAGE_SIZE);
-       if (off)
-               base += PAGE_SIZE-off;
        sub_dev_ptr->DmaBuf= base;
 
        tell_dev((vir_bytes)base, size, 0, 0, 0);
index cdb52e42f806d94170df4379ff618f3b79ee1720..2b2591f333aa9030353b6c47c50bcf598693222a 100755 (executable)
@@ -12,7 +12,7 @@ d = ..
 CC =   exec cc
 CFLAGS = -I$i
 LDFLAGS = -i
-LIBS = -lsys -lsysutil
+LIBS = -lsys 
 
 
 # build local binary
index daf107dcad9cfc28ac7fca5104b441485f10656b..5b6888b8a6fac44e60ce213cca8fcdbf70f3830d 100644 (file)
@@ -14,7 +14,7 @@ MAKE = exec make
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i -L../libdriver 
-LIBS = -lsysutil -lsys -ltimers -ldriver 
+LIBS = -ldriver    -lsys  -lsys -ltimers 
 
 OBJ = bios_wini.o 
 
index 87d6fd2fd4ba885abcc70b7c88c8714e3291d24b..98dcecf58002a131e54aa1b8843e298ab4caf958 100644 (file)
@@ -166,7 +166,7 @@ vir_bytes from_vir;
 endpoint_t to_proc;
 int to_seg;
 vir_bytes to_vir;
-vir_bytes grant_offset;
+size_t grant_offset;
 size_t size;
 {
        phys_bytes addr;
index 87d2ae91c53366665f0abc08f8d911393d116b82..08a02c1b17fb0186e88d7b362dcd2ba4b0afd3a6 100644 (file)
@@ -13,7 +13,7 @@ d = ..
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i 
-LIBS = -lsysutil -lsys -ltimers
+LIBS = -lsys -ltimers
 
 OBJ = 3c503.o dp8390.o ne2000.o rtl8029.o wdeth.o
 
index 4f62de524696a024739063f6721e5a82dbaa9d09..479e421e9fd85791fd347594676d95bb5bb139c9 100644 (file)
@@ -59,6 +59,7 @@
 #include <net/hton.h>
 #include <net/gen/ether.h>
 #include <net/gen/eth_io.h>
+#include <sys/vm_i386.h>
 #include <sys/vm.h>
 #include "assert.h"
 
@@ -2540,18 +2541,22 @@ dpeth_t *dep;
                return;
        }
 
-       size = dep->de_ramsize + PAGE_SIZE;     /* Add PAGE_SIZE for
+       size = dep->de_ramsize + I386_PAGE_SIZE;        /* Add I386_PAGE_SIZE for
                                                 * alignment
                                                 */
        buf= malloc(size);
        if (buf == NULL)
                panic(__FILE__, "map_hw_buffer: cannot malloc size", size);
-       o= PAGE_SIZE - ((vir_bytes)buf % PAGE_SIZE);
+       o= I386_PAGE_SIZE - ((vir_bytes)buf % I386_PAGE_SIZE);
        abuf= buf + o;
        printf("buf at 0x%x, abuf at 0x%x\n", buf, abuf);
 
+#if 0
        r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)abuf,
                        dep->de_ramsize, (phys_bytes)dep->de_linmem);
+#else
+       r = ENOSYS;
+#endif
        if (r != OK)
                panic(__FILE__, "map_hw_buffer: sys_vm_map failed", r);
        dep->de_locmem = abuf;
index 726c527cb9b57af6e624007c7bf3badfb2dfdd95..81f9db26a44c111904c2b0bf2f8de1634b37c5e1 100644 (file)
@@ -15,7 +15,7 @@ LDFLAGS       = -i -o $@
 
 SRCS   = 3c501.c 3c509.c 3c503.c ne.c wd.c 8390.c devio.c netbuff.c dp.c
 OBJS   = 3c501.o 3c509.o 3c503.o ne.o wd.o 8390.o devio.o netbuff.o dp.o
-LIBS   = -lsysutil -lsys # -ltimers
+LIBS   = -lsys
 
 ##  Build rules
 all build:     $(DRIVER)
index 397de8c191a3a84253889556d395585dbc1681a6..478dde0ded7e5121c808142dcffdfec40d13fe1b 100644 (file)
@@ -14,7 +14,7 @@ MAKE = exec make
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i -L../libdriver
-LIBS = -lsysutil -ldriver  -lsys -ltimers
+LIBS = -ldriver -lsys  -ltimers
 
 OBJ = floppy.o 
 
index f21c4de7ba66eb3b876011561e590a1b3ce5d27d..b1ed29c26f3ac80a0c7a14208734ccf8cadc15fb 100644 (file)
@@ -294,6 +294,8 @@ PUBLIC void main()
   struct floppy *fp;
   int s;
 
+  init_buffer();
+
   f_next_timeout = TMR_NEVER;
   tmr_inittimer(&f_tmr_timeout);
 
index ee795c3224f913a2df8a1ed625a9a9851300aa20..3850d3502ebe21c5785b866b7ebd38b1494a9d92 100644 (file)
@@ -13,7 +13,7 @@ d = ..
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i 
-LIBS = -lsysutil -lsys -ltimers
+LIBS = -lsys  -ltimers
 
 OBJ = fxp.o mii.o
 
@@ -21,7 +21,7 @@ OBJ = fxp.o mii.o
 all build:     $(DRIVER)
 $(DRIVER):     $(OBJ) 
        $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
-       install -S 96k $(DRIVER)
+       install -S 128k $(DRIVER)
 
 # install with other drivers
 install:       /usr/sbin/$(DRIVER)
index fb76cd515235659b854655972da004ff52c37921..1a146f1398ffea284ac0be98c9bc7bf00c99a45b 100644 (file)
@@ -211,7 +211,8 @@ fxp_t;
 #define FT_82558A      0x2
 #define FT_82559       0x4
 
-static fxp_t fxp_table[FXP_PORT_NR];
+static fxp_t *fxp_table;
+phys_bytes fxp_table_phys;
 
 static u16_t eth_ign_proto;
 static tmra_ut fxp_watchdog;
@@ -281,6 +282,7 @@ int main(int argc, char *argv[])
        u32_t tasknr;
        fxp_t *fp;
        long v;
+       vir_bytes ft = sizeof(*fxp_table)*FXP_PORT_NR;
 
        if (argc < 1)
                panic("FXP", "A head which at this time has no name", NO_NUM);
@@ -292,6 +294,11 @@ int main(int argc, char *argv[])
 #endif
        eth_ign_proto= htons((u16_t) v);
 
+       if(!(fxp_table = alloc_contig(ft, 0, &fxp_table_phys)))
+               panic("FXP","couldn't allocate table", r);
+
+       memset(fxp_table, 0, ft);
+
        if((r=micro_delay_calibrate()) != OK)
                panic("FXP","rmicro_delay_calibrate failed", r);
 
@@ -795,7 +802,7 @@ fxp_t *fp;
        fxp_do_conf(fp);
 
        /* Set pointer to statistical counters */
-       r= sys_umap(SELF, D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
+       r= sys_umap(SELF, VM_D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
                &bus_addr);
        if (r != OK)
                panic("FXP","sys_umap failed", r);
@@ -835,6 +842,7 @@ fxp_t *fp;
        int i, r;
        struct rfd *rfdp;
        struct tx *txp;
+       phys_bytes ph;
 
        fp->fxp_rx_nbuf= N_RX_BUF;
        rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);
@@ -844,33 +852,33 @@ fxp_t *fp;
        tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);
        fp->fxp_tx_bufsize= tx_totbufsize;
 
-#define BUFALIGN       4096
        tot_bufsize= sizeof(*tmpbufp) + tx_totbufsize + rx_totbufsize;
        if (tot_bufsize % 4096)
                tot_bufsize += 4096 - (tot_bufsize % 4096);
-       alloc_bufsize= tot_bufsize+BUFALIGN;
-       alloc_buf= malloc(alloc_bufsize);
+       alloc_bufsize= tot_bufsize;
+       alloc_buf= alloc_contig(alloc_bufsize, AC_ALIGN4K, &ph);
        if (alloc_buf == NULL)
        {
-               panic(__FILE__, "fxp_init_buf: unable to malloc size",
+               panic(__FILE__, "fxp_init_buf: unable to alloc_contig size",
                        alloc_bufsize);
        }
 
        buf= (phys_bytes)alloc_buf;
-       buf += BUFALIGN - (buf % BUFALIGN);
 
        tell_dev((vir_bytes)buf, tot_bufsize, 0, 0, 0);
 
        tmpbufp= (union tmpbuf *)buf;
 
        fp->fxp_rx_buf= (struct rfd *)&tmpbufp[1];
-       r= sys_umap(SELF, D, (vir_bytes)fp->fxp_rx_buf, rx_totbufsize,
+       r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_rx_buf, rx_totbufsize,
                &fp->fxp_rx_busaddr);
        if (r != OK)
                panic("FXP","sys_umap failed", r);
 
+#if 0
        printf("fxp_init_buf: got phys 0x%x for vir 0x%x\n",
                fp->fxp_rx_busaddr, fp->fxp_rx_buf);
+#endif
 
        for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)
        {
@@ -878,7 +886,7 @@ fxp_t *fp;
                rfdp->rfd_command= 0;
                if (i != fp->fxp_rx_nbuf-1)
                {
-                       r= sys_umap(SELF, D, (vir_bytes)&rfdp[1],
+                       r= sys_umap(SELF, VM_D, (vir_bytes)&rfdp[1],
                                sizeof(rfdp[1]), &rfdp->rfd_linkaddr);
                        if (r != OK)
                                panic("FXP","sys_umap failed", r);
@@ -896,7 +904,7 @@ fxp_t *fp;
        fp->fxp_rx_head= 0;
 
        fp->fxp_tx_buf= (struct tx *)((char *)fp->fxp_rx_buf+rx_totbufsize);
-       r= sys_umap(SELF, D, (vir_bytes)fp->fxp_tx_buf,
+       r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_tx_buf,
                (phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);
        if (r != OK)
                panic("FXP","sys_umap failed", r);
@@ -907,7 +915,7 @@ fxp_t *fp;
                txp->tx_command= TXC_EL | CBL_NOP;      /* Just in case */
                if (i != fp->fxp_tx_nbuf-1)
                {
-                       r= sys_umap(SELF, D, (vir_bytes)&txp[1],
+                       r= sys_umap(SELF, VM_D, (vir_bytes)&txp[1],
                                (phys_bytes)sizeof(txp[1]),
                                &txp->tx_linkaddr);
                        if (r != OK)
@@ -938,7 +946,7 @@ fxp_t *fp;
 
        /* Reset device */
        fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
-       tickdelay(MICROS_TO_TICKS(CSR_PORT_RESET_DELAY));
+       tickdelay(micros_to_ticks(CSR_PORT_RESET_DELAY));
 
        /* Disable interrupts */
        fxp_outb(port, SCB_INT_MASK, SIM_M);
@@ -995,7 +1003,7 @@ fxp_t *fp;
        tmpbufp->ias.ias_linkaddr= 0;
        memcpy(tmpbufp->ias.ias_ethaddr, fp->fxp_address.ea_addr,
                sizeof(tmpbufp->ias.ias_ethaddr));
-       r= sys_umap(SELF, D, (vir_bytes)&tmpbufp->ias,
+       r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->ias,
                (phys_bytes)sizeof(tmpbufp->ias), &bus_addr);
        if (r != OK)
                panic("FXP","sys_umap failed", r);
@@ -1007,7 +1015,7 @@ fxp_t *fp;
                /* Wait for CU command to complete */
                if (tmpbufp->ias.ias_status & CBL_F_C)
                        break;
-       } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
+       } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
 
        if (!(tmpbufp->ias.ias_status & CBL_F_C))
                panic("FXP","fxp_confaddr: CU command failed to complete", NO_NUM);
@@ -1731,7 +1739,7 @@ fxp_t *fp;
        memcpy(tmpbufp->cc.cc_bytes, fp->fxp_conf_bytes,
                sizeof(tmpbufp->cc.cc_bytes));
 
-       r= sys_umap(SELF, D, (vir_bytes)&tmpbufp->cc,
+       r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->cc,
                (phys_bytes)sizeof(tmpbufp->cc), &bus_addr);
        if (r != OK)
                panic("FXP","sys_umap failed", r);
@@ -1743,7 +1751,7 @@ fxp_t *fp;
                /* Wait for CU command to complete */
                if (tmpbufp->cc.cc_status & CBL_F_C)
                        break;
-       } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
+       } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
 
        if (!(tmpbufp->cc.cc_status & CBL_F_C))
                panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM);
@@ -1786,7 +1794,7 @@ int check_idle;
                scb_cmd= fxp_inb(port, SCB_CMD);
                if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)
                        break;
-       } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
+       } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
 
        if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)
                panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM);
@@ -1823,7 +1831,7 @@ int check_idle;
                scb_cmd= fxp_inb(port, SCB_CMD);
                if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)
                        break;
-       } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
+       } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
 
        if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)
                panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM);
@@ -1899,7 +1907,7 @@ message *mp;
                /* Wait for CU command to complete */
                if (*p != 0)
                        break;
-       } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
+       } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
 
        if (*p == 0)
                panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
@@ -1983,7 +1991,7 @@ message *mp;
                /* Wait for CU command to complete */
                if (*p != 0)
                        break;
-       } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
+       } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
 
        if (*p == 0)
                panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
@@ -2798,7 +2806,7 @@ int reg;
                v= fxp_inl(port, CSR_MDI_CTL);
                if (v & CM_READY)
                        break;
-       } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
+       } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
 
        if (!(v & CM_READY))
                panic("FXP","mii_read: MDI not ready after command", NO_NUM);
@@ -2932,9 +2940,11 @@ int pci_func;
        r= ds_retrieve_u32("amddev", &u32);
        if (r != OK)
        {
+#if 0
                printf(
                "fxp`tell_dev: ds_retrieve_u32 failed for 'amddev': %d\n",
                        r);
+#endif
                return;
        }
 
index 78ab487c163a16b457d6e9f5e6e07b975e3c4d97..6995bb47dc8d29fefb2933bbe60604ed34391784 100644 (file)
@@ -13,7 +13,7 @@ d = ..
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i 
-LIBS = -lsysutil  -lsys
+LIBS =  -lsys 
 #-lutils -ltimers
 
 OBJ = lance.o
@@ -22,7 +22,7 @@ OBJ = lance.o
 all build:     $(DRIVER)
 $(DRIVER):     $(OBJ) 
        $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
-       install -S 16k $(DRIVER)
+       install -S 128k $(DRIVER)
 
 # install with other drivers
 install:       /usr/sbin/$(DRIVER)
index 1f37969e6c226546fd7ea3b19a1274e017296884..72401f0b10e0862685794b701ac9743b18d846ee 100644 (file)
@@ -193,7 +193,7 @@ unsigned long vir2phys( unsigned long x )
        int r;
        unsigned long value;
        
-       if ( (r=sys_umap( SELF, D, x, 4, &value )) != OK )
+       if ( (r=sys_umap( SELF, VM_D, x, 4, &value )) != OK )
                panic( "lance", "sys_umap failed", r );
        
        return value;
@@ -202,7 +202,7 @@ unsigned long vir2phys( unsigned long x )
 /* DMA limitations */
 #define DMA_ADDR_MASK  0xFFFFFF        /* mask to verify DMA address is 24-bit */
 
-#define CORRECT_DMA_MEM() ( (virt_to_bus(lance + sizeof(lance)) & ~DMA_ADDR_MASK) == 0 )
+#define CORRECT_DMA_MEM() ( (virt_to_bus(lance_buf + sizeof(struct lance_interface)) & ~DMA_ADDR_MASK) == 0 )
 
 #define ETH_FRAME_LEN           1518
 
@@ -297,7 +297,8 @@ struct lance_interface
 
 /* =============== global variables =============== */
 static struct lance_interface  *lp;
-static char lance[sizeof(struct lance_interface)+8];
+#define LANCE_BUF_SIZE (sizeof(struct lance_interface))
+static char *lance_buf = NULL;
 static int rx_slot_nr = 0;          /* Rx-slot number */
 static int tx_slot_nr = 0;          /* Tx-slot number */
 static int cur_tx_slot_nr = 0;      /* Tx-slot number */
@@ -1682,8 +1683,11 @@ ether_card_t *ec;
   unsigned short ioaddr = ec->ec_port;
 
   /* ============= setup init_block(cf. lance_probe1) ================ */
-  /* make sure data structure is 8-byte aligned */
-  l = ((Address)lance + 7) & ~7;
+  /* make sure data structure is 8-byte aligned and below 16MB (for DMA) */
+  assert(!lance_buf);
+  if(!(lance_buf = alloc_contig(LANCE_BUF_SIZE, AC_ALIGN4K|AC_LOWER16M, &l))) {
+       panic( "lance", "alloc_contig failed", LANCE_BUF_SIZE);
+  }
   lp = (struct lance_interface *)l;
   lp->init_block.mode = 0x3;      /* disable Rx and Tx */
   lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;
index 534ac1a69f7f29163641e083da3971a459f8126a..c88984a155ce815af3ab1a3190114b848689b9cc 100644 (file)
@@ -11,7 +11,7 @@ m = $i/minix
 CC = exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i
-LIBS = -lsysutil -lsys
+LIBS = -lsys
 LIB = libdriver.a
 
 OBJECTS = driver.o drvlib.o mq.o
index fe960f22f81255188e5c2e2423a0f6f711e8f8f9..733ffa391504aaf5c6911c98b90a9e4698e51eb4 100644 (file)
 #include <minix/mq.h>
 #include "driver.h"
 
-#if (CHIP == INTEL)
-
-#if USE_EXTRA_DMA_BUF && DMA_BUF_SIZE < 2048
-/* A bit extra scratch for the Adaptec driver. */
-#define BUF_EXTRA      (2048 - DMA_BUF_SIZE)
-#else
-#define BUF_EXTRA      0
-#endif
-
 /* Claim space for variables. */
-PRIVATE u8_t buffer[(unsigned) 2 * DMA_BUF_SIZE + BUF_EXTRA];
+#if 0
+PRIVATE u8_t buffer[(unsigned) 2 * DMA_BUF_SIZE];
+#endif
 u8_t *tmp_buf;                 /* the DMA buffer eventually */
 phys_bytes tmp_phys;           /* phys address of DMA buffer */
 
-#else /* CHIP != INTEL */
-
-/* Claim space for variables. */
-u8_t tmp_buf[DMA_BUF_SIZE];    /* the DMA buffer */
-phys_bytes tmp_phys;           /* phys address of DMA buffer */
-
-#endif /* CHIP != INTEL */
-
-FORWARD _PROTOTYPE( void init_buffer, (void) );
 FORWARD _PROTOTYPE( int do_rdwt, (struct driver *dr, message *mp, int safe) );
 FORWARD _PROTOTYPE( int do_vrdwt, (struct driver *dr, message *mp, int safe) );
 
@@ -86,9 +70,6 @@ struct driver *dp;    /* Device dependent entry points. */
   /* Init MQ library. */
   mq_init();
 
-  /* Get a DMA buffer. */
-  init_buffer();
-
   /* Here is the main loop of the disk task.  It waits for a message, carries
    * it out, and sends a reply.
    */
@@ -176,25 +157,17 @@ struct driver *dp;        /* Device dependent entry points. */
 /*===========================================================================*
  *                             init_buffer                                  *
  *===========================================================================*/
-PRIVATE void init_buffer()
+PUBLIC void init_buffer(void)
 {
 /* Select a buffer that can safely be used for DMA transfers.  It may also
  * be used to read partition tables and such.  Its absolute address is
  * 'tmp_phys', the normal address is 'tmp_buf'.
  */
 
-#if (CHIP == INTEL)
   unsigned left;
 
-  tmp_buf = buffer;
-  sys_umap(SELF, D, (vir_bytes)buffer, (phys_bytes)sizeof(buffer), &tmp_phys);
-
-  if ((left = dma_bytes_left(tmp_phys)) < DMA_BUF_SIZE) {
-       /* First half of buffer crosses a 64K boundary, can't DMA into that */
-       tmp_buf += left;
-       tmp_phys += left;
-  }
-#endif /* CHIP == INTEL */
+  if(!(tmp_buf = alloc_contig(2*DMA_BUF_SIZE, AC_ALIGN4K, &tmp_phys)))
+       panic(__FILE__, "can't allocate tmp_buf", DMA_BUF_SIZE);
 }
 
 /*===========================================================================*
@@ -216,8 +189,8 @@ int safe;                   /* use safecopies? */
 
   /* Check the user buffer (not relevant for safe copies). */
   if(!safe) {
-         sys_umap(mp->IO_ENDPT, D, (vir_bytes) mp->ADDRESS, mp->COUNT, &phys_addr);
-         if (phys_addr == 0) return(EFAULT);
+         printf("libdriver_asyn: do_rdwt: no support for non-safe command.\n");
+         return EINVAL;
   }
 
   /* Prepare for I/O. */
index 8c019e92ea33b4283e92dfe752d04efc1da247a9..03dd9324bdc267e76c21d3dcd00fa2f2e9ee3fc3 100644 (file)
@@ -45,14 +45,6 @@ struct driver {
   _PROTOTYPE( int (*dr_hw_int), (struct driver *dp, message *m_ptr) );
 };
 
-#if (CHIP == INTEL)
-
-/* Number of bytes you can DMA before hitting a 64K boundary: */
-#define dma_bytes_left(phys)    \
-   ((unsigned) (sizeof(int) == 2 ? 0 : 0x10000) - (unsigned) ((phys) & 0xFFFF))
-
-#endif /* CHIP == INTEL */
-
 /* Base and size of a partition in bytes. */
 struct device {
   u64_t dv_base;
@@ -75,6 +67,7 @@ _PROTOTYPE( int nop_select, (struct driver *dp, message *m_ptr) );
 _PROTOTYPE( int do_diocntl, (struct driver *dp, message *m_ptr, int safe) );
 _PROTOTYPE( int nop_ioctl, (struct driver *dp, message *m_ptr, int safe) );
 _PROTOTYPE( int mq_queue, (message *m_ptr) );
+_PROTOTYPE( void init_buffer, (void) );
 
 /* Parameters for the disk drive. */
 #define SECTOR_SIZE      512   /* physical sector size in bytes */
index 534ac1a69f7f29163641e083da3971a459f8126a..c88984a155ce815af3ab1a3190114b848689b9cc 100644 (file)
@@ -11,7 +11,7 @@ m = $i/minix
 CC = exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i
-LIBS = -lsysutil -lsys
+LIBS = -lsys
 LIB = libdriver.a
 
 OBJECTS = driver.o drvlib.o mq.o
index f97173e89c945d79029291c86d710fa3efcc0384..21c137b49dd4a7edf50aa2ced487748a8a60bec5 100644 (file)
 #include <minix/mq.h>
 #include "driver.h"
 
-#if (CHIP == INTEL)
-
-#if USE_EXTRA_DMA_BUF && DMA_BUF_SIZE < 2048
-/* A bit extra scratch for the Adaptec driver. */
-#define BUF_EXTRA      (2048 - DMA_BUF_SIZE)
-#else
-#define BUF_EXTRA      0
-#endif
-
 /* Claim space for variables. */
-PRIVATE u8_t buffer[(unsigned) 2 * DMA_BUF_SIZE + BUF_EXTRA];
-u8_t *tmp_buf;                 /* the DMA buffer eventually */
+u8_t *tmp_buf = NULL;          /* the DMA buffer eventually */
 phys_bytes tmp_phys;           /* phys address of DMA buffer */
 
-#else /* CHIP != INTEL */
-
-/* Claim space for variables. */
-u8_t tmp_buf[DMA_BUF_SIZE];    /* the DMA buffer */
-phys_bytes tmp_phys;           /* phys address of DMA buffer */
-
-#endif /* CHIP != INTEL */
-
 FORWARD _PROTOTYPE( void init_buffer, (void) );
 FORWARD _PROTOTYPE( int do_rdwt, (struct driver *dr, message *mp, int safe) );
 FORWARD _PROTOTYPE( int do_vrdwt, (struct driver *dr, message *mp, int safe) );
@@ -88,9 +70,6 @@ struct driver *dp;    /* Device dependent entry points. */
   /* Init MQ library. */
   mq_init();
 
-  /* Get a DMA buffer. */
-  init_buffer();
-
   /* Here is the main loop of the disk task.  It waits for a message, carries
    * it out, and sends a reply.
    */
@@ -112,6 +91,7 @@ struct driver *dp;   /* Device dependent entry points. */
        device_caller = mess.m_source;
        proc_nr = mess.IO_ENDPT;
 
+#if 0
        if (mess.m_type != SYN_ALARM && mess.m_type != DEV_PING &&
                mess.m_type != 4105 /* notify from TTY */ &&
                mess.m_type != DEV_SELECT &&
@@ -119,9 +99,10 @@ struct driver *dp;  /* Device dependent entry points. */
                mess.m_type != DIAGNOSTICS_S &&
                mess.m_type != CANCEL)
        {
-               printf("libdriver_asyn`driver_task: message %d\n",
-                       mess.m_type);
+               printf("libdriver_asyn`driver_task: msg %d / 0x%x from %d\n",
+                       mess.m_type, mess.m_type, mess.m_source);
        }
+#endif
 
        if (mess.m_type == DEV_SELECT)
        {
@@ -129,9 +110,11 @@ struct driver *dp; /* Device dependent entry points. */
                if (first)
                {
                        first= 0;
+#if 0
                        printf(
        "libdriver_asyn`driver_task: first DEV_SELECT: minor 0x%x, ops 0x%x\n",
                                mess.DEVICE, mess.IO_ENDPT);
+#endif
                }
        }
 
@@ -223,15 +206,19 @@ struct driver *dp;        /* Device dependent entry points. */
                }
                else if (mess.m_type == DIAGNOSTICS_S)
                {
+#if 0
                        if (device_caller == FS_PROC_NR)
                                printf("driver_task: sending DIAG_REPL to FS\n");
+#endif
                        reply_mess.m_type = DIAG_REPL;
                        reply_mess.REP_STATUS = r;      
                }
                else
                {
+#if 0
                        printf("driver_task: TASK_REPLY to req %d\n",
                                mess.m_type);
+#endif
                        reply_mess.m_type = TASK_REPLY;
                        reply_mess.REP_ENDPT = proc_nr;
                        /* Status is # of bytes transferred or error code. */
@@ -258,18 +245,11 @@ PRIVATE void init_buffer()
  * 'tmp_phys', the normal address is 'tmp_buf'.
  */
 
-#if (CHIP == INTEL)
   unsigned left;
 
-  tmp_buf = buffer;
-  sys_umap(SELF, D, (vir_bytes)buffer, (phys_bytes)sizeof(buffer), &tmp_phys);
-
-  if ((left = dma_bytes_left(tmp_phys)) < DMA_BUF_SIZE) {
-       /* First half of buffer crosses a 64K boundary, can't DMA into that */
-       tmp_buf += left;
-       tmp_phys += left;
+  if(!(tmp_buf = alloc_contig(2*DMA_BUF_SIZE, 0, &tmp_phys))) {
+       panic(__FILE__, "can't allocate tmp_buf", NO_NUM);
   }
-#endif /* CHIP == INTEL */
 }
 
 /*===========================================================================*
@@ -557,6 +537,8 @@ PUBLIC int mq_queue(message *m)
        return OK;
 }
 
+#if 0
+
 #define ASYN_NR        100
 PRIVATE asynmsg_t msgtable[ASYN_NR];
 PRIVATE int first_slot= 0, next_slot= 0;
@@ -644,3 +626,4 @@ message *mp;
        return senda(msgtable+first_slot, next_slot-first_slot);
 }
 
+#endif
index 8c019e92ea33b4283e92dfe752d04efc1da247a9..0737f1748139348a0549d06df2fdd4c8cb95c62d 100644 (file)
@@ -45,14 +45,6 @@ struct driver {
   _PROTOTYPE( int (*dr_hw_int), (struct driver *dp, message *m_ptr) );
 };
 
-#if (CHIP == INTEL)
-
-/* Number of bytes you can DMA before hitting a 64K boundary: */
-#define dma_bytes_left(phys)    \
-   ((unsigned) (sizeof(int) == 2 ? 0 : 0x10000) - (unsigned) ((phys) & 0xFFFF))
-
-#endif /* CHIP == INTEL */
-
 /* Base and size of a partition in bytes. */
 struct device {
   u64_t dv_base;
index b7f482182d7682890d0b5636e4147500ededf8d3..221d1baa1de3cf8c80e571e60be3bffd448cf739 100644 (file)
@@ -13,7 +13,7 @@ MAKE = exec make
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i -L../libdriver_asyn
-LIBS = -lsysutil -ldriver  -lsys
+LIBS = -ldriver  -lsys 
 LIB_DEP = ../libdriver_asyn/libdriver.a
 
 OBJ = log.o diag.o kputc.o
@@ -22,11 +22,11 @@ OBJ = log.o diag.o kputc.o
 all build:     $(DRIVER)
 $(DRIVER):     $(OBJ) $(LIB_DEP)
        $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
-       install -S 16kb $(DRIVER)
+       install -S 32kb $(DRIVER)
 
 # install with other drivers
 install:       $(DRIVER)
-       install -o root -cs $? /sbin/$(DRIVER) 
+       install -o root -cs $< /sbin/$(DRIVER) 
 
 # clean up local files
 clean:
index eb8da9e0001e64c2e406fa8c6bd8c99e5b14c0f2..0dacbd323ee98ce16f234d653549347baa219720 100644 (file)
 #include <fcntl.h>
 #include <minix/type.h>
 #include <minix/safecopies.h>
+#include <minix/sys_config.h>
 
 #include "log.h"
-#include "../../kernel/const.h"
-#include "../../kernel/config.h"
-#include "../../kernel/type.h"
 
 /*==========================================================================*
  *                             do_new_kmess                                *
@@ -24,8 +22,8 @@ PUBLIC int do_new_kmess(m)
 message *m;                                    /* notification message */
 {
 /* Notification for a new kernel message. */
-  struct kmessages kmess;              /* entire kmess structure */
-  char print_buf[KMESS_BUF_SIZE];      /* copy new message here */
+  static struct kmessages kmess;               /* entire kmess structure */
+  static char print_buf[_KMESS_BUF_SIZE];      /* copy new message here */
   int bytes;
   int i, r;
   int *prev_nextp;
@@ -79,12 +77,12 @@ message *m;                                 /* notification message */
    * Check for size being positive, the buffer might as well be emptied!
    */
   if (kmess.km_size > 0) {
-      bytes = ((kmess.km_next + KMESS_BUF_SIZE) - (*prev_nextp)) %
-       KMESS_BUF_SIZE;
+      bytes = ((kmess.km_next + _KMESS_BUF_SIZE) - (*prev_nextp)) %
+       _KMESS_BUF_SIZE;
       r= *prev_nextp;                          /* start at previous old */ 
       i=0;
       while (bytes > 0) {                      
-          print_buf[i] = kmess.km_buf[(r%KMESS_BUF_SIZE)];
+          print_buf[i] = kmess.km_buf[(r%_KMESS_BUF_SIZE)];
           bytes --;
           r ++;
           i ++;
@@ -136,5 +134,7 @@ PUBLIC int do_diagnostics(message *m, int safe)
   }
   log_append(diagbuf, i);
 
+  if(m->m_type == ASYN_DIAGNOSTICS) return EDONTREPLY;
+
   return OK;
 }
index 27c58cd16d5ce2548b31df6b9fda70f616f7886e..e22789093651acb4aee35ca271c0e7b18b8523d5 100644 (file)
@@ -9,8 +9,6 @@
 #include "log.h"
 #include <sys/time.h>
 #include <sys/select.h>
-#include "../../kernel/const.h"
-#include "../../kernel/type.h"
 
 #define LOG_DEBUG              0       /* enable/ disable debugging */
 
@@ -403,10 +401,10 @@ int safe;
                r = do_diagnostics(m_ptr, 0);
                break;
        }
-       case DIAGNOSTICS_S: {
+       case ASYN_DIAGNOSTICS:
+       case DIAGNOSTICS_S:
                r = do_diagnostics(m_ptr, 1);
                break;
-       }
        case DEV_STATUS: {
                printf("log_other: unexpected DEV_STATUS request\n");
                r = EDONTREPLY;
index 5b77a1c0dc7ee8c126de53750872dbd64bb7816f..c3c251237a1180428f743a27ed50112be2dbadb0 100644 (file)
@@ -14,7 +14,7 @@ MAKE = exec make
 CC =   exec cc
 CFLAGS = -I$i
 LDFLAGS = -i -L../libdriver
-LIBS =  -lsysutil -ldriver -lsys
+LIBS =  -ldriver -lsys  
 
 # imgrd_s.s is the ACK assembler version of the ramdisk. For more portability,
 # use the C version imgrd.c. However, the C compiler takes too much memory
index d5b9af79658e01d95471c03d0e9c947e91443767..520bb93158abb79c0cd82c1cc4da2f9743d3f60d 100644 (file)
@@ -27,6 +27,7 @@
 #define MY_DS_NAME_SIZE "dev:memory:ramdisk_size"
 
 #include <sys/vm.h>
+#include <sys/vm_i386.h>
 
 #include "assert.h"
 
@@ -71,7 +72,7 @@ PRIVATE struct driver m_dtab = {
 /* One page of temporary mapping area - enough to be able to page-align
  * one page.
  */
-static char pagedata_buf[2*PAGE_SIZE];
+static char pagedata_buf[2*I386_PAGE_SIZE];
 vir_bytes pagedata_aligned;
 
 /* Buffer for the /dev/zero null byte feed. */
@@ -171,8 +172,10 @@ int safe;                  /* safe copies */
            break;
 
        /* Virtual copying. For RAM disk, kernel memory and boot device. */
-       case RAM_DEV:
        case KMEM_DEV:
+               return EIO;
+               break;
+       case RAM_DEV:
        case BOOT_DEV:
            if (position >= dv_size) return(OK);        /* check for EOF */
            if (position + count > dv_size) count = dv_size - position;
@@ -207,15 +210,19 @@ int safe;                 /* safe copies */
                count = dv_size - position;
            mem_phys = cv64ul(dv->dv_base) + position;
 
-           page_off = mem_phys % PAGE_SIZE;
+           page_off = mem_phys % I386_PAGE_SIZE;
            pagestart = mem_phys - page_off; 
 
            /* All memory to the map call has to be page-aligned.
             * Don't have to map same page over and over.
             */
            if(!any_mapped || pagestart_mapped != pagestart) {
+#if 0
              if((r=sys_vm_map(SELF, 1, pagedata_aligned,
-               PAGE_SIZE, pagestart)) != OK) {
+               I386_PAGE_SIZE, pagestart)) != OK) {
+#else
+               if(1) {
+#endif
                printf("memory: sys_vm_map failed: %d\n", r);
                return r;
             }
@@ -224,7 +231,7 @@ int safe;                   /* safe copies */
           }
 
            /* how much to be done within this page. */
-           subcount = PAGE_SIZE-page_off;
+           subcount = I386_PAGE_SIZE-page_off;
            if(subcount > count)
                subcount = count;
 
@@ -324,12 +331,14 @@ PRIVATE void m_init()
   }
 
   /* Install remote segment for /dev/kmem memory. */
+#if 0
   m_geom[KMEM_DEV].dv_base = cvul64(kinfo.kmem_base);
   m_geom[KMEM_DEV].dv_size = cvul64(kinfo.kmem_size);
   if (OK != (s=sys_segctl(&m_seg[KMEM_DEV], (u16_t *) &s, (vir_bytes *) &s, 
                kinfo.kmem_base, kinfo.kmem_size))) {
       panic("MEM","Couldn't install remote segment.",s);
   }
+#endif
 
   /* Install remote segment for /dev/boot memory, if enabled. */
   m_geom[BOOT_DEV].dv_base = cvul64(kinfo.bootdev_base);
@@ -365,8 +374,8 @@ PRIVATE void m_init()
   }
 
   /* Page-align page pointer. */
-  pagedata_aligned = (u32_t) pagedata_buf + PAGE_SIZE;
-  pagedata_aligned -= pagedata_aligned % PAGE_SIZE;
+  pagedata_aligned = (u32_t) pagedata_buf + I386_PAGE_SIZE;
+  pagedata_aligned -= pagedata_aligned % I386_PAGE_SIZE;
 
   /* Set up memory range for /dev/mem. */
   m_geom[MEM_DEV].dv_size = cvul64(0xffffffff);
@@ -404,15 +413,11 @@ int safe;
        if (m_ptr->DEVICE != RAM_DEV) return(EINVAL);
         if ((dv = m_prepare(m_ptr->DEVICE)) == NIL_DEV) return(ENXIO);
 
-#if 0
-       ramdev_size= m_ptr->POSITION;
-#else
        /* Get request structure */
           s= sys_safecopyfrom(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->IO_GRANT,
                0, (vir_bytes)&ramdev_size, sizeof(ramdev_size), D);
        if (s != OK)
                return s;
-#endif
 
 #if DEBUG
        printf("allocating ramdisk of size 0x%x\n", ramdev_size);
@@ -447,27 +452,6 @@ int safe;
        first_time= 0;
        break;
     }
-    case MIOCMAP:
-    case MIOCUNMAP: {
-       int r, do_map;
-       struct mapreq mapreq;
-
-       if ((*dp->dr_prepare)(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
-       if (m_device != MEM_DEV)
-               return ENOTTY;
-
-       do_map= (m_ptr->REQUEST == MIOCMAP);    /* else unmap */
-
-       /* Get request structure */
-          r= sys_safecopyfrom(m_ptr->IO_ENDPT, (vir_bytes)m_ptr->IO_GRANT,
-               0, (vir_bytes)&mapreq, sizeof(mapreq), D);
-
-       if (r != OK)
-               return r;
-       r= sys_vm_map(m_ptr->IO_ENDPT, do_map,
-               (phys_bytes)mapreq.base, mapreq.size, mapreq.offset);
-       return r;
-    }
 
     default:
        return(do_diocntl(&m_dtab, m_ptr, safe));
index e4e78163460fb7839b22ba0fccf8a01ac60013ad..3aae388f8640a32001ec547ff37b6992e58f02ec 100644 (file)
@@ -9,7 +9,6 @@ then
 else
        /bin/service -c up /bin/at_wini -dev /dev/c0d0 -config /etc/drivers.conf -label at_wini_0
        /bin/service -c up /bin/at_wini -dev /dev/c1d0 -config /etc/drivers.conf -label at_wini_1 -args ata_instance=1
-       #/bin/service -c up /bin/at_wini -dev /dev/c0d0 -script /etc/rs.single -config /etc/drivers.conf
 fi
 
 rootdev=`sysenv rootdev` || echo 'No rootdev?'
index 256fed94490942929f1486632b7b301ec26556bf..9a1d8900b02f5048aaaed06fe71d299e5c667d22 100755 (executable)
@@ -13,7 +13,7 @@ d = ..
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i
-LIBS = -lsysutil -lsys -ltimers
+LIBS = -lsys -ltimers
 
 OBJ = orinoco.o hermes.o
  
index 640edf01a366ea47aa1527531e59935582f67a0f..095553be600dd579393148e85f51b33289de2324 100755 (executable)
@@ -44,8 +44,6 @@
 #include "string.h"
 int this_proc;
 
-#define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)       
-
 /*****************************************************************************
  *            milli_delay                                                    *
  *                                                                           *
index c26056d4138be2c3d98d37fac64fd25cff368c8d..2ec3aa71cfb2edd6ba6bb6eb230472977cf80392 100755 (executable)
@@ -93,7 +93,7 @@ static tmra_ut or_watchdog;
 #include       <net/hton.h>
 #include       <net/gen/ether.h>
 #include       <net/gen/eth_io.h>
-#include       <sys/vm.h>
+#include       <sys/vm_i386.h>
 #include       <sys/types.h>
 #include       <fcntl.h>
 #include       <unistd.h>
@@ -738,24 +738,29 @@ static void map_hw_buffer(t_or *orp) {
        char *buf, *abuf;       
        hermes_t *hw = &(orp->hw);      
 
-       /* This way, the buffer will be at least PAGE_SIZE big: see 
+       /* This way, the buffer will be at least I386_PAGE_SIZE big: see 
         * calculation with the offset */
-       size = 2 * PAGE_SIZE;   
+       size = 2 * I386_PAGE_SIZE;      
 
        buf = (char *)malloc(size);
        if(buf == NULL) 
                panic(__FILE__, "map_hw_buffer: cannot malloc size:", size);
 
-       /* Let the mapped memory by PAGE_SIZE aligned */
-       o = PAGE_SIZE - ((vir_bytes)buf % PAGE_SIZE);
+       /* Let the mapped memory by I386_PAGE_SIZE aligned */
+       o = I386_PAGE_SIZE - ((vir_bytes)buf % I386_PAGE_SIZE);
        abuf = buf + o;
 
+#if 0
        r = sys_vm_map(SELF, 1, (vir_bytes)abuf, 
-                       1 * PAGE_SIZE, (phys_bytes)orp->or_base_port);
+                       1 * I386_PAGE_SIZE, (phys_bytes)orp->or_base_port);
+#else
+       r = ENOSYS;
+#endif
 
        if(r!=OK) 
                panic(__FILE__, "map_hw_buffer: sys_vm_map failed:", r);
 
+
        hw->locmem = abuf;
 }
 
index a19a1f8f11948f9b910be312cfc53f6a3426d42f..60d1fd6f8111e8311e718711ea668940d1007b4c 100644 (file)
@@ -13,7 +13,7 @@ d = ..
 CC =   cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i 
-LIBS = -lsysutil  -lsys -ltimers
+LIBS =  -lsys -ltimers 
 
 OBJ = main.o pci.o pci_table.o
 
index 213fe921c71838644b3acbbdf55c7caa0d9fd393..fba9440fe4a019d71bbf37ee9fa2672663ebc766 100644 (file)
@@ -388,8 +388,10 @@ message *mp;
        }
 
        acl[i].inuse= 0;
+#if 0
        printf("do_acl: deleting ACL for %d ('%s') at entry %d\n",
                acl[i].acl.rsp_endpoint, acl[i].acl.rsp_label, i);
+#endif
 
        /* Also release all devices held by this process */
        pci_release(proc_nr);
index 0876c33cc70221ef14c4f40b2a6f0eab5313df18..c319fcda0ac45da058f5d69b257674c13ba6ffa3 100644 (file)
@@ -10,7 +10,7 @@ Created:      Jan 2000 by Philip Homburg <philip@cs.vu.nl>
 #include "../drivers.h"
 #include <assert.h>
 #include <ibm/pci.h>
-#include <sys/vm.h>
+#include <sys/vm_i386.h>
 #include <minix/com.h>
 #include <minix/rs.h>
 #include <minix/syslib.h>
@@ -118,7 +118,9 @@ FORWARD _PROTOTYPE( int do_piix, (int devind)                               );
 FORWARD _PROTOTYPE( int do_amd_isabr, (int devind)                     );
 FORWARD _PROTOTYPE( int do_sis_isabr, (int devind)                     );
 FORWARD _PROTOTYPE( int do_via_isabr, (int devind)                     );
+#if 0
 FORWARD _PROTOTYPE( void report_vga, (int devind)                      );
+#endif
 FORWARD _PROTOTYPE( char *pci_vid_name, (U16_t vid)                    );
 FORWARD _PROTOTYPE( char *pci_baseclass_name, (U8_t baseclass)         );
 FORWARD _PROTOTYPE( char *pci_subclass_name, (U8_t baseclass,
@@ -872,8 +874,10 @@ printf("probe_bus(%d)\n", busind);
                                print_capabilities(devind);
 
                        t3= ((baseclass << 16) | (subclass << 8) | infclass);
+#if 0
                        if (t3 == PCI_T3_VGA || t3 == PCI_T3_VGA_OLD)
                                report_vga(devind);
+#endif
 
                        if (nr_pcidev >= NR_PCIDEV)
                          panic("PCI","too many PCI devices", nr_pcidev);
@@ -1406,8 +1410,8 @@ PRIVATE void complete_bars()
                        if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
                                continue;
                        size= pcidev[i].pd_bar[j].pb_size;
-                       if (size < PAGE_SIZE)
-                               size= PAGE_SIZE;
+                       if (size < I386_PAGE_SIZE)
+                               size= I386_PAGE_SIZE;
                        base= memgap_high-size;
                        base &= ~(u32_t)(size-1);
                        if (base < memgap_low)
@@ -2010,6 +2014,7 @@ int devind;
 }
 
 
+#if 0
 /*===========================================================================*
  *                             report_vga                                   *
  *===========================================================================*/
@@ -2042,6 +2047,7 @@ int devind;
                        amount);
        }
 }
+#endif
 
 
 /*===========================================================================*
index 243bd0dec95d023c1884318ab7033ee5ad35cf66..7e3228fb4975acf3323f58f8a703fc5519020721 100644 (file)
@@ -13,7 +13,7 @@ d = ..
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i
-LIBS = -lsysutil  -lsys
+LIBS =  -lsys   -lsys
 
 OBJ = printer.o
 
index ec447e5f9c9c981cf2a1479a410f689b6bb4d5e2..9e376cad5299eccd54b2e1e188535a8d6f94d988 100644 (file)
@@ -14,7 +14,7 @@ MAKE = exec make
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i -L../libdriver_asyn
-LIBS = -lsysutil -ldriver -lsys 
+LIBS =  -ldriver -lsys 
 LIB_DEPS=../libdriver_asyn/libdriver.a
 
 OBJ = main.o random.o sha2.o aes/rijndael_api.o aes/rijndael_alg.o
index 2d9a2ebe19b1c813c452161740f522a9bfcc2c81..66a32f850e34f0d24151e9de8a51922b3b957675 100644 (file)
@@ -6,7 +6,7 @@ MAKE = exec make
 CC =   exec cc
 CFLAGS=-D_MINIX=1 -D_POSIX_SOURCE=1 -D_SYSTEM=1
 LDFLAGS = -i
-LIBS = -lsysutil -lsys
+LIBS =  -lsys
 
 OBJ = readclock.o 
 
index eef744678de078cca4ecfc50b2371f781280a3dd..0e6d2bb112a6b85a592f3bee2ed83b0abd488d6a 100644 (file)
@@ -14,7 +14,7 @@ MAKE = exec make
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i
-LIBS = -lsysutil -lsys -ltimers
+LIBS = -lsys   -ltimers 
 
 OBJ = rtl8139.o 
 
index 4105a446f67c111ecdbc50adada73d387c43bdeb..3f159633a5da4892a16441ab3b3effa9b4fa128b 100644 (file)
@@ -12,7 +12,7 @@ d = ..
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i
-LIBS = -lsysutil -lsys
+LIBS = -lsys
 
 
 # build local binary
index dd2512a42542031f1857b6cd0a28e0e8ca18c3c8..b197db5dd1cfae90c2485281997767538fc4712e 100644 (file)
@@ -13,7 +13,7 @@ d = ..
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i 
-LIBS = -lsysutil  -lsys -ltimers
+LIBS = -lsys -ltimers
 
 OBJ = ti1225.o
 
index f35c3d9ec6e11f9801771d273b0814b6dd118ef8..eeed9b237079111fda1289da877c980864a3c7a7 100644 (file)
@@ -7,6 +7,7 @@ Created:        Dec 2005 by Philip Homburg
 #include "../drivers.h"
 #include <ibm/pci.h>
 #include <sys/vm.h>
+#include <sys/vm_i386.h>
 
 #include "ti1225.h"
 #include "i82365.h"
@@ -29,7 +30,7 @@ PRIVATE struct port
        char *base_ptr;
        volatile struct csr *csr_ptr;
 
-       char buffer[2*PAGE_SIZE];
+       char buffer[2*I386_PAGE_SIZE];
 } ports[NR_PORTS];
 
 #define PF_PRESENT     1
@@ -257,8 +258,8 @@ u32_t base;
        vir_bytes buf_base;
 
        buf_base= (vir_bytes)pp->buffer;
-       if (buf_base % PAGE_SIZE)
-               buf_base += PAGE_SIZE-(buf_base % PAGE_SIZE);
+       if (buf_base % I386_PAGE_SIZE)
+               buf_base += I386_PAGE_SIZE-(buf_base % I386_PAGE_SIZE);
        pp->base_ptr= (char *)buf_base;
        if (debug)
        {
@@ -269,8 +270,12 @@ u32_t base;
        /* Clear low order bits in base */
        base &= ~(u32_t)0xF;
 
+#if 0
        r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)pp->base_ptr,
-               PAGE_SIZE, (phys_bytes)base);
+               I386_PAGE_SIZE, (phys_bytes)base);
+#else
+       r = ENOSYS;
+#endif
        if (r != OK)
                panic("ti1225", "map_regs: sys_vm_map failed", r);
 }
@@ -422,7 +427,7 @@ struct port *pp;
                csr_present= pp->csr_ptr->csr_present;
                if (csr_present & CP_PWRCYCLE)
                        break;
-       } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
+       } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
 
        if (!(csr_present & CP_PWRCYCLE))
        {
index 4f891d06514afdac4ae9177c46cd974aea8113ab..710ea9f57eae8376aaf865fc0e7b2c301a2e11b9 100644 (file)
@@ -14,10 +14,10 @@ d = ..
 # programs, flags, etc.
 MAKE = exec make
 CC =   exec cc
-CPPFLAGS = -I$i -I../../kernel/arch/$(ARCH)/include
+CPPFLAGS = -I$i 
 CFLAGS = $(CPPFLAGS)
 LDFLAGS = -i
-LIBS = -lsysutil -lsys -ltimers
+LIBS =  -lsys -ltimers
 
 OBJ = tty.o console.o vidcopy.o keyboard.o pty.o rs232.o 
 
@@ -25,7 +25,7 @@ OBJ = tty.o console.o vidcopy.o keyboard.o pty.o rs232.o
 all build:     $(DRIVER)
 $(DRIVER):     $(OBJ) 
        $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
-       install -S 8k $(DRIVER)
+       install -S 16k $(DRIVER)
 
 # install with other drivers
 install:       
index c7a2421f583c9dd3b1961f5d5e7d33700567ccc5..f7abd263d5557297d68aaf097a922b22641b4276 100644 (file)
 #include <termios.h>
 #include <sys/ioctl.h>
 #include <sys/vm.h>
+#include <sys/video.h>
+#include <minix/tty.h>
 #include <minix/callnr.h>
 #include <minix/com.h>
+#include <minix/sys_config.h>
 #include "tty.h"
 
-#include "../../kernel/const.h"
-#include "../../kernel/config.h"
-#include "../../kernel/type.h"
-
 /* Set this to 1 if you want console output duplicated on the first
  * serial line.
   */
 #define DUP_CONS_TO_SER        0
 
-/* Definitions used by the console driver. */
-#define MONO_BASE    0xB0000L  /* base of mono video memory */
-#define COLOR_BASE   0xB8000L  /* base of color video memory */
-#define MONO_SIZE     0x1000   /* 4K mono video memory */
-#define COLOR_SIZE    0x4000   /* 16K color video memory */
-#define EGA_SIZE      0x8000   /* EGA & VGA have at least 32K */
-#define BLANK_COLOR   0x0700   /* determines cursor color on blank screen */
-#define SCROLL_UP          0   /* scroll forward */
-#define SCROLL_DOWN        1   /* scroll backward */
-#define BLANK_MEM ((u16_t *) 0)        /* tells mem_vid_copy() to blank the screen */
-#define CONS_RAM_WORDS    80   /* video ram buffer size */
-#define MAX_ESC_PARMS      4   /* number of escape sequence params allowed */
-
-/* Constants relating to the controller chips. */
-#define M_6845         0x3B4   /* port for 6845 mono */
-#define C_6845         0x3D4   /* port for 6845 color */
-#define INDEX              0   /* 6845's index register */
-#define DATA               1   /* 6845's data register */
-#define STATUS             6   /* 6845's status register */
-#define VID_ORG           12   /* 6845's origin register */
-#define CURSOR            14   /* 6845's cursor register */
-
 /* The clock task should provide an interface for this */
 #define TIMER_FREQ  1193182L    /* clock frequency for timer in PC and AT */
 
-/* Beeper. */
-#define BEEP_FREQ     0x0533   /* value to put into timer to set beep freq */
-#define B_TIME            3    /* length of CTRL-G beep is ticks */
-
-/* definitions used for font management */
-#define GA_SEQUENCER_INDEX     0x3C4
-#define GA_SEQUENCER_DATA      0x3C5
-#define GA_GRAPHICS_INDEX      0x3CE
-#define GA_GRAPHICS_DATA       0x3CF
-#define GA_VIDEO_ADDRESS       0xA0000L
-#define GA_FONT_SIZE           8192
-
 /* Global variables used by the console driver and assembly support. */
 PUBLIC int vid_index;          /* index of video segment in remote mem map */
 PUBLIC u16_t vid_seg;
 PUBLIC vir_bytes vid_off;      /* video ram is found at vid_seg:vid_off */
-PUBLIC unsigned vid_size;      /* 0x2000 for color or 0x0800 for mono */
+PUBLIC phys_bytes vid_size;    /* 0x2000 for color or 0x0800 for mono */
+PUBLIC phys_bytes vid_base;
 PUBLIC unsigned vid_mask;      /* 0x1FFF for color or 0x07FF for mono */
 PUBLIC unsigned blank_color = BLANK_COLOR; /* display code for blank */
 
@@ -87,6 +53,7 @@ PRIVATE unsigned font_lines;  /* font lines per character */
 PRIVATE unsigned scr_width;    /* # characters on a line */
 PRIVATE unsigned scr_lines;    /* # lines on the screen */
 PRIVATE unsigned scr_size;     /* # characters on the screen */
+PUBLIC unsigned info_location; /* location in video memory of struct */
 
 PRIVATE int disabled_vc = -1;  /* Virtual console that was active when 
                                 * disable_console was called.
@@ -95,6 +62,9 @@ PRIVATE int disabled_sm;      /* Scroll mode to be restored when re-enabling
                                 * console
                                 */
 
+/* boot_tty_info we use to communicate with the boot code. */
+struct boot_tty_info boot_tty_info;
+
 /* Per console data. */
 typedef struct console {
   tty_t *c_tty;                        /* associated TTY struct */
@@ -113,11 +83,34 @@ typedef struct console {
   int *c_esc_parmp;            /* pointer to current escape parameter */
   int c_esc_parmv[MAX_ESC_PARMS];      /* list of escape parameters */
   u16_t c_ramqueue[CONS_RAM_WORDS];    /* buffer for video RAM */
+  int c_line;                  /* line no */
 } console_t;
 
+#define UPDATEBOOTINFO(ccons, infofield, value)        {               \
+       if(ccons->c_line == 0) {                                \
+               boot_tty_info.infofield = value;                \
+               mem_vid_copy((u16_t *) &boot_tty_info,          \
+                       info_location/2, sizeof(boot_tty_info)/2);      \
+       }                                                       \
+}
+
+#define UPDATE_CURSOR(ccons, cursor) {                         \
+       ccons->c_cur = cursor;                                  \
+       UPDATEBOOTINFO(ccons, conscursor, ccons->c_cur);        \
+       if(curcons && ccons == curcons)                         \
+               set_6845(CURSOR, ccons->c_cur);                 \
+}
+
+#define UPDATE_ORIGIN(ccons, origin) {                         \
+       ccons->c_org = origin;                                  \
+       UPDATEBOOTINFO(ccons, consorigin, ccons->c_org);        \
+       if (curcons && ccons == curcons)                        \
+               set_6845(VID_ORG, ccons->c_org);                \
+}
+
 PRIVATE int nr_cons= 1;                /* actual number of consoles */
 PRIVATE console_t cons_table[NR_CONS];
-PRIVATE console_t *curcons;    /* currently visible */
+PRIVATE console_t *curcons = NULL;     /* currently visible */
 
 /* Color if using a color controller. */
 #define color  (vid_port == C_6845)
@@ -142,14 +135,20 @@ FORWARD _PROTOTYPE( void flush, (console_t *cons)                 );
 FORWARD _PROTOTYPE( void parse_escape, (console_t *cons, int c)                );
 FORWARD _PROTOTYPE( void scroll_screen, (console_t *cons, int dir)     );
 FORWARD _PROTOTYPE( void set_6845, (int reg, unsigned val)             );
-FORWARD _PROTOTYPE( void get_6845, (int reg, unsigned *val)            );
 FORWARD _PROTOTYPE( void stop_beep, (timer_t *tmrp)                    );
 FORWARD _PROTOTYPE( void cons_org0, (void)                             );
 FORWARD _PROTOTYPE( void disable_console, (void)                       );
 FORWARD _PROTOTYPE( void reenable_console, (void)                      );
 FORWARD _PROTOTYPE( int ga_program, (struct sequence *seq)             );
 FORWARD _PROTOTYPE( int cons_ioctl, (tty_t *tp, int)                   );
+
+#if DUP_CONS_TO_SER
 FORWARD _PROTOTYPE( void ser_putc, (char c)                            );
+#endif
+
+#if 0
+FORWARD _PROTOTYPE( void get_6845, (int reg, unsigned *val)            );
+#endif
 
 /*===========================================================================*
  *                             cons_write                                   *
@@ -174,7 +173,7 @@ int try;
   /* Check quickly for nothing to do, so this can be called often without
    * unmodular tests elsewhere.
    */
-  if ((count = tp->tty_outleft) == 0 || tp->tty_inhibited) return;
+  if ((count = tp->tty_outleft) == 0 || tp->tty_inhibited) return 0;
 
   /* Copy the user bytes to buf[] for decent addressing. Loop over the
    * copies, since the user buffer may be much larger than buf[].
@@ -228,6 +227,8 @@ int try;
                                                        tp->tty_outcum);
        tp->tty_outcum = 0;
   }
+
+  return 0;
 }
 
 /*===========================================================================*
@@ -365,9 +366,9 @@ int dir;                    /* SCROLL_UP or SCROLL_DOWN */
        } else
        if (!wrap && cons->c_org + scr_size + scr_width >= cons->c_limit) {
                vid_vid_copy(cons->c_org + scr_width, cons->c_start, chars);
-               cons->c_org = cons->c_start;
+               UPDATE_ORIGIN(cons, cons->c_start);
        } else {
-               cons->c_org = (cons->c_org + scr_width) & vid_mask;
+               UPDATE_ORIGIN(cons, (cons->c_org + scr_width) & vid_mask);
        }
        new_line = (cons->c_org + chars) & vid_mask;
   } else {
@@ -378,9 +379,9 @@ int dir;                    /* SCROLL_UP or SCROLL_DOWN */
        if (!wrap && cons->c_org < cons->c_start + scr_width) {
                new_org = cons->c_limit - scr_size;
                vid_vid_copy(cons->c_org, new_org + scr_width, chars);
-               cons->c_org = new_org;
+               UPDATE_ORIGIN(cons, new_org);
        } else {
-               cons->c_org = (cons->c_org - scr_width) & vid_mask;
+               UPDATE_ORIGIN(cons, (cons->c_org - scr_width) & vid_mask);
        }
        new_line = cons->c_org;
   }
@@ -388,8 +389,6 @@ int dir;                    /* SCROLL_UP or SCROLL_DOWN */
   blank_color = cons->c_blank;
   mem_vid_copy(BLANK_MEM, new_line, scr_width);
 
-  /* Set the new video origin. */
-  if (cons == curcons) set_6845(VID_ORG, cons->c_org);
   flush(cons);
 }
 
@@ -421,10 +420,8 @@ register console_t *cons;  /* pointer to console struct */
   if (cons->c_row < 0) cons->c_row = 0;
   if (cons->c_row >= scr_lines) cons->c_row = scr_lines - 1;
   cur = cons->c_org + cons->c_row * scr_width + cons->c_column;
-  if (cur != cons->c_cur) {
-       if (cons == curcons) set_6845(CURSOR, cur);
-       cons->c_cur = cur;
-  }
+  if (cur != cons->c_cur)
+       UPDATE_CURSOR(cons, cur);
 }
 
 /*===========================================================================*
@@ -747,6 +744,7 @@ unsigned val;                       /* 16-bit value to set it to */
   sys_voutb(char_out, 4);                      /* do actual output */
 }
 
+#if 0
 /*===========================================================================*
  *                             get_6845                                     *
  *===========================================================================*/
@@ -765,6 +763,7 @@ unsigned *val;                      /* 16-bit value to set it to */
   v2 = v;
   *val = (v1 << 8) | v2;
 }
+#endif
 
 /*===========================================================================*
  *                             beep                                         *
@@ -810,8 +809,7 @@ PRIVATE void beep()
  *===========================================================================*/
 PUBLIC void do_video(message *m)
 {
-       int i, n, r, ops, watch, safe = 0;
-       unsigned char c;
+       int r, safe = 0;
 
        /* Execute the requested device driver function. */
        r= EINVAL;      /* just in case */
@@ -827,8 +825,10 @@ PUBLIC void do_video(message *m)
                break;
            case DEV_IOCTL_S:
                safe=1;
-               if (m->TTY_REQUEST == MIOCMAP || m->TTY_REQUEST == MIOCUNMAP)
-               {
+               switch(m->TTY_REQUEST) {
+                 case MIOCMAP:
+                 case MIOCUNMAP: {
+#if 0
                        int r, do_map;
                        struct mapreq mapreq;
 
@@ -859,8 +859,50 @@ PUBLIC void do_video(message *m)
                        r= sys_vm_map(safe ? m->POSITION : m->IO_ENDPT,
                          do_map, (phys_bytes)mapreq.base, mapreq.size,
                          mapreq.offset);
+#else
+                       r = ENOSYS;
+                       printf("tty: %ld used old MIOCMAP interface\n",
+                               safe ? m->POSITION : m->IO_ENDPT);
+#endif
+                       tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT, r);
+                       return;
+                  }
+                 case TIOCMAPMEM:
+                 case TIOCUNMAPMEM: {
+                       int r, do_map;
+                       struct mapreqvm mapreqvm;
+                       void *result;
+
+                       do_map= (m->REQUEST == TIOCMAPMEM);     /* else unmap */
+
+                       /* Get request structure */
+                       if(safe) {
+                          r = sys_safecopyfrom(m->IO_ENDPT,
+                               (vir_bytes)m->ADDRESS, 0, (vir_bytes) &mapreqvm,
+                               sizeof(mapreqvm), D);
+                       } else {
+                         r= sys_vircopy(m->IO_ENDPT, D,
+                               (vir_bytes)m->ADDRESS,
+                               SELF, D, (vir_bytes)&mapreqvm,sizeof(mapreqvm));
+                       }
+                       if (r != OK)
+                       {
+                               tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT,
+                                       r);
+                               return;
+                       }
+
+                       /* In safe ioctl mode, the POSITION field contains
+                        * the endpt number of the original requestor.
+                        * IO_ENDPT is always FS.
+                        */
+
+                       if(do_map) {
+                       } else {
+                       }
                        tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT, r);
                        return;
+                  }
                }
                r= ENOTTY;
                break;
@@ -940,19 +982,19 @@ tty_t *tp;
 {
 /* Initialize the screen driver. */
   console_t *cons;
-  phys_bytes vid_base;
   u16_t bios_columns, bios_crtbase, bios_fontlines;
   u8_t bios_rows;
   int line;
   int s;
   static int vdu_initialized = 0;
-  unsigned page_size;
+  static unsigned page_size;
 
   /* Associate console and TTY. */
   line = tp - &tty_table[0];
   if (line >= nr_cons) return;
   cons = &cons_table[line];
   cons->c_tty = tp;
+  cons->c_line = line;
   tp->tty_priv = cons;
 
   /* Fill in TTY function hooks. */
@@ -987,6 +1029,7 @@ tty_t *tp;
        }
        if (machine.vdu_ega) vid_size = EGA_SIZE;
        wrap = ! machine.vdu_ega;
+       info_location = vid_size - sizeof(struct boot_tty_info);
 
        s = sys_segctl(&vid_index, &vid_seg, &vid_off, vid_base, vid_size);
 
@@ -997,7 +1040,8 @@ tty_t *tp;
        scr_size = scr_lines * scr_width;
 
        /* There can be as many consoles as video memory allows. */
-       nr_cons = vid_size / scr_size;
+       nr_cons = (vid_size - sizeof(struct boot_tty_info)/2) / scr_size;
+
        if (nr_cons > NR_CONS) nr_cons = NR_CONS;
        if (nr_cons > 1) wrap = 0;
        page_size = vid_size / nr_cons;
@@ -1013,13 +1057,18 @@ tty_t *tp;
        blank_color = BLANK_COLOR;
        mem_vid_copy(BLANK_MEM, cons->c_start, scr_size);
   } else {
-       int i, n;
        /* Set the cursor of the console vty at the bottom. c_cur
         * is updated automatically later.
         */
        scroll_screen(cons, SCROLL_UP);
        cons->c_row = scr_lines - 1;
        cons->c_column = 0;
+
+       memset(&boot_tty_info, 0, sizeof(boot_tty_info));
+       UPDATE_CURSOR(cons, cons->c_cur);
+       UPDATE_ORIGIN(cons, cons->c_org);
+       boot_tty_info.flags = BTIF_CONSCURSOR | BTIF_CONSORIGIN;
+       boot_tty_info.magic = TTYMAGIC;
   }
   select_console(0);
   cons_ioctl(tp, 0);
@@ -1045,9 +1094,9 @@ int c;
        cons_putk(c);
   if (c != 0) {
       kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
-      if (kmess.km_size < KMESS_BUF_SIZE)
+      if (kmess.km_size < _KMESS_BUF_SIZE)
           kmess.km_size += 1;          
-      kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
+      kmess.km_next = (kmess.km_next + 1) % _KMESS_BUF_SIZE;
   } else {
       notify(LOG_PROC_NR);
   }
@@ -1060,9 +1109,8 @@ PUBLIC void do_new_kmess(m)
 message *m;
 {
 /* Notification for a new kernel message. */
-  struct kmessages kmess;                      /* kmessages structure */
+  static struct kmessages kmess;               /* kmessages structure */
   static int prev_next = 0;                    /* previous next seen */
-  int size, next;
   int bytes;
   int r;
 
@@ -1081,15 +1129,15 @@ message *m;
 
   /* Print only the new part. Determine how many new bytes there are with 
    * help of the current and previous 'next' index. Note that the kernel
-   * buffer is circular. This works fine if less then KMESS_BUF_SIZE bytes
-   * is new data; else we miss % KMESS_BUF_SIZE here.  
+   * buffer is circular. This works fine if less then _KMESS_BUF_SIZE bytes
+   * is new data; else we miss % _KMESS_BUF_SIZE here.  
    * Check for size being positive, the buffer might as well be emptied!
    */
   if (kmess.km_size > 0) {
-      bytes = ((kmess.km_next + KMESS_BUF_SIZE) - prev_next) % KMESS_BUF_SIZE;
+      bytes = ((kmess.km_next + _KMESS_BUF_SIZE) - prev_next) % _KMESS_BUF_SIZE;
       r=prev_next;                             /* start at previous old */ 
       while (bytes > 0) {                      
-          cons_putk( kmess.km_buf[(r%KMESS_BUF_SIZE)] );
+          cons_putk( kmess.km_buf[(r%_KMESS_BUF_SIZE)] );
           bytes --;
           r ++;
       }
@@ -1121,6 +1169,8 @@ int safe;
        int r;
        if(safe) {
           r = sys_safecopyfrom(proc_nr, src, offset, (vir_bytes) &c, 1, D);
+          if(r != OK)
+                  printf("<tty: proc %d, grant %ld>", proc_nr, src);
        } else {
           r = sys_vircopy(proc_nr, D, src+offset, SELF, D, (vir_bytes) &c, 1);
        }
@@ -1132,9 +1182,12 @@ int safe;
        cons_putk(c);
   }
   cons_putk(0);                        /* always terminate, even with EFAULT */
-  m_ptr->m_type = DIAG_REPL;
-  m_ptr->REP_STATUS = result;
-  send(m_ptr->m_source, m_ptr);
+
+  if(m_ptr->m_type != ASYN_DIAGNOSTICS) {
+         m_ptr->m_type = DIAG_REPL;
+         m_ptr->REP_STATUS = result;
+         send(m_ptr->m_source, m_ptr);
+  }
 }
 
 /*===========================================================================*
@@ -1237,7 +1290,7 @@ PRIVATE void cons_org0()
                if (n > cons->c_org - cons->c_start)
                        n = cons->c_org - cons->c_start;
                vid_vid_copy(cons->c_org, cons->c_org - n, scr_size);
-               cons->c_org -= n;
+               UPDATE_ORIGIN(cons, cons->c_org - n);
        }
        flush(cons);
   }
@@ -1283,10 +1336,12 @@ PUBLIC void select_console(int cons_line)
 /* Set the current console to console number 'cons_line'. */
 
   if (cons_line < 0 || cons_line >= nr_cons) return;
+
   ccurrent = cons_line;
   curcons = &cons_table[cons_line];
-  set_6845(VID_ORG, curcons->c_org);
-  set_6845(CURSOR, curcons->c_cur);
+
+  UPDATE_CURSOR(curcons, curcons->c_cur);
+  UPDATE_ORIGIN(curcons, curcons->c_org);
 }
 
 /*===========================================================================*
@@ -1358,8 +1413,11 @@ int try;
   tp->tty_winsize.ws_col= scr_width;
   tp->tty_winsize.ws_xpixel= scr_width * 8;
   tp->tty_winsize.ws_ypixel= scr_lines * font_lines;
+
+  return 0;
 }
 
+#if DUP_CONS_TO_SER
 #define COM1_BASE      0x3F8
 #define COM1_THR       (COM1_BASE + 0)
 #define                LSR_THRE        0x20
@@ -1381,3 +1439,4 @@ PRIVATE void ser_putc(char c)
        }
        sys_outb(thr, c);
 }
+#endif
index 3325cd9515fc55c9c73ded4d3355ce95fcb47ca0..5ff44c89bd5cf858beec819ae8317e145d64afb4 100644 (file)
 #include <termios.h>
 #include <signal.h>
 #include <unistd.h>
-#include <archtypes.h>
 #include <minix/callnr.h>
 #include <minix/com.h>
 #include <minix/keymap.h>
 #include "tty.h"
 #include "keymaps/us-std.src"
-#include "../../kernel/const.h"
-#include "../../kernel/config.h"
-#include "../../kernel/type.h"
-#include "../../kernel/proc.h"
 
 int irq_hook_id = -1;
 int aux_irq_hook_id = -1;
@@ -132,10 +127,9 @@ PRIVATE struct kbd_outack
 
 PRIVATE int kbd_watchdog_set= 0;
 PRIVATE int kbd_alive= 1;
+PRIVATE int sticky_alt_mode = 0;
 PRIVATE timer_t tmr_kbd_wd;
 
-int sticky_alt_mode = 0;
-
 FORWARD _PROTOTYPE( void handle_req, (struct kbd *kbdp, message *m)    );
 FORWARD _PROTOTYPE( int handle_status, (struct kbd *kbdp, message *m)  );
 FORWARD _PROTOTYPE( void kbc_cmd0, (int cmd)                           );
@@ -153,6 +147,13 @@ FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try)                 );
 FORWARD _PROTOTYPE( unsigned map_key, (int scode)                      );
 FORWARD _PROTOTYPE( void kbd_watchdog, (timer_t *tmrp)                 );
 
+int micro_delay(u32_t usecs)
+{
+       /* TTY can't use the library micro_delay() as that calls PM. */
+       tickdelay(micros_to_ticks(usecs));
+       return OK;
+}
+
 /*===========================================================================*
  *                             do_kbd                                       *
  *===========================================================================*/
@@ -500,7 +501,6 @@ message *m_ptr;
   int o, isaux;
   unsigned char scode;
   struct kbd *kbdp;
-  static timer_t timer;                /* timer must be static! */
 
   /* Fetch the character from the keyboard hardware and acknowledge it. */
   if (!scan_keyboard(&scode, &isaux))
@@ -637,7 +637,7 @@ PRIVATE void kbd_send()
        }
        if (sb & (KB_OUT_FULL|KB_IN_FULL))
        {
-               printf("not sending 1: sb = 0x%x\n", sb);
+               printf("not sending 1: sb = 0x%lx\n", sb);
                return;
        }
        micro_delay(KBC_IN_DELAY);
@@ -646,7 +646,7 @@ PRIVATE void kbd_send()
        }
        if (sb & (KB_OUT_FULL|KB_IN_FULL))
        {
-               printf("not sending 2: sb = 0x%x\n", sb);
+               printf("not sending 2: sb = 0x%lx\n", sb);
                return;
        }
 
@@ -864,10 +864,10 @@ PRIVATE int kbc_read()
        while (micro_elapsed(&ms) < 1000000);
 #endif
        panic("TTY", "kbc_read failed to complete", NO_NUM);
+       return EINVAL;
 }
 
 
-
 /*===========================================================================*
  *                             kb_wait                                      *
  *===========================================================================*/
@@ -876,7 +876,7 @@ PRIVATE int kb_wait()
 /* Wait until the controller is ready; return zero if this times out. */
 
   int retries;
-  unsigned long status, temp;
+  unsigned long status;
   int s, isaux;
   unsigned char byte;
 
@@ -940,6 +940,12 @@ PUBLIC void kb_init_once(void)
 {
   int i;
   u8_t ccb;
+  char env[100];
+
+  if(env_get_param("sticky_alt", env, sizeof(env)-1) == OK
+   && atoi(env) == 1) {
+        sticky_alt_mode = 1; 
+  }
 
   set_leds();                  /* turn off numlock led */
   scan_keyboard(NULL, NULL);   /* discard leftover keystroke */
@@ -1020,7 +1026,7 @@ message *m_ptr;                   /* pointer to the request message */
  * notifications if it is pressed. At most one binding per key can exist.
  */
   int i; 
-  int result;
+  int result = EINVAL;
 
   switch (m_ptr->FKEY_REQUEST) {       /* see what we must do */
   case FKEY_MAP:                       /* request for new mapping */
@@ -1104,8 +1110,6 @@ message *m_ptr;                   /* pointer to the request message */
           }
       }
       break;
-  default:
-          result =  EINVAL;            /* key cannot be observed */
   }
 
   /* Almost done, return result to caller. */
@@ -1128,7 +1132,6 @@ int scode;                        /* scan code for a function key */
   message m;
   int key;
   int proc_nr;
-  int i,s;
 
   /* Ignore key releases. If this is a key press, get full key code. */
   if (scode & KEY_RELEASE) return(FALSE);      /* key release */
@@ -1166,31 +1169,17 @@ int scode;                      /* scan code for a function key */
  *===========================================================================*/
 PRIVATE void show_key_mappings()
 {
-    int i,s;
-    struct proc proc;
-
+    int i;
     printf("\n");
     printf("System information.   Known function key mappings to request debug dumps:\n");
     printf("-------------------------------------------------------------------------\n");
     for (i=0; i<12; i++) {
 
       printf(" %sF%d: ", i+1<10? " ":"", i+1);
-      if (fkey_obs[i].proc_nr != NONE) {
-          if ((s=sys_getproc(&proc, fkey_obs[i].proc_nr))!=OK)
-              printf("sys_getproc: %d\n", s);
-          printf("%-14.14s", proc.p_name);
-      } else {
-          printf("%-14.14s", "<none>");
-      }
+      printf("%-14.14s", "<none>");
 
       printf("    %sShift-F%d: ", i+1<10? " ":"", i+1);
-      if (sfkey_obs[i].proc_nr != NONE) {
-          if ((s=sys_getproc(&proc, sfkey_obs[i].proc_nr))!=OK)
-              printf("sys_getproc: %d\n", s);
-          printf("%-14.14s", proc.p_name);
-      } else {
-          printf("%-14.14s", "<none>");
-      }
+      printf("%-14.14s", "<none>");
       printf("\n");
     }
     printf("\n");
@@ -1260,12 +1249,6 @@ int *isauxp;
 #endif
 }
 
-int micro_delay(u32_t usecs)
-{
-       tickdelay(MICROS_TO_TICKS(usecs));
-       return OK;
-}
-
 /*===========================================================================*
  *                             kbd_watchdog                                 *
  *===========================================================================*/
index 24943e99fec6d0adf7ccabbdd7083ff7b84c8862..952a806d599a1bb8c4a829bfca2b405b5808f10b 100644 (file)
@@ -4,8 +4,8 @@ LK =    /usr/lib/keymaps
 
 .SUFFIXES:     .src .map
 
-.src.map:
-       $(CC) -DKEYSRC=\"$<\" $(CPROFILE) genmap.c -lsysutil -lsys
+.src.map: 
+       $(CC) -DKEYSRC=\"$<\" genmap.c
        ./a.out > $@
        @rm -f a.out
 
index b90fe6e8043add760f8e260d3c76da6487713e57..ca408d691f73d48d2bb398efdda0dbd6aac130b7 100644 (file)
@@ -89,7 +89,6 @@ message *m_ptr;
 /* Perform an open/close/read/write call on a /dev/ptypX device. */
   pty_t *pp = tp->tty_priv;
   int r;
-  phys_bytes p;
   int safe = 0;
 
   switch (m_ptr->m_type) {
@@ -108,15 +107,6 @@ message *m_ptr;
                r = EINVAL;
                break;
        }
-#if DEAD_CODE
-       if (numap_local(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS,
-                                                       m_ptr->COUNT) == 0) {
-#else
-       if ((r = sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
-               m_ptr->COUNT, &p)) != OK) {
-#endif
-               break;
-       }
        pp->rdsendreply = TRUE;
        pp->rdcaller = m_ptr->m_source;
        pp->rdproc = m_ptr->IO_ENDPT;
@@ -130,12 +120,6 @@ message *m_ptr;
                return;                 /* already done */
        }
 
-#if DEAD_CODE
-       if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
-               r = EAGAIN;                             /* don't suspend */
-               pp->rdleft = pp->rdcum = 0;
-       } else
-#endif
        {
                r = SUSPEND;                            /* do suspend */
                pp->rdsendreply = FALSE;
@@ -157,16 +141,6 @@ message *m_ptr;
                r = EINVAL;
                break;
        }
-#if DEAD_CODE
-       if (numap_local(m_ptr->IO_ENDPT, (vir_bytes) m_ptr->ADDRESS,
-                                                       m_ptr->COUNT) == 0) {
-               r = EFAULT;
-#else
-       if ((r = sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
-               m_ptr->COUNT, &p)) != OK) {
-#endif
-               break;
-       }
        pp->wrsendreply = TRUE;
        pp->wrcaller = m_ptr->m_source;
        pp->wrproc = m_ptr->IO_ENDPT;
@@ -179,12 +153,6 @@ message *m_ptr;
                return;                 /* already done */
        }
 
-#if DEAD_CODE
-       if (m_ptr->TTY_FLAGS & O_NONBLOCK) {            /* don't suspend */
-               r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
-               pp->wrleft = pp->wrcum = 0;
-       } else
-#endif
        {
                pp->wrsendreply = FALSE;                        /* do suspend */
                r = SUSPEND;
@@ -244,7 +212,7 @@ int try;
  */
   pty_t *pp = tp->tty_priv;
   int count, ocount, s;
-  phys_bytes user_phys;
+
 
   /* PTY closed down? */
   if (pp->state & PTY_CLOSED) {
@@ -259,7 +227,7 @@ int try;
                        tp->tty_outleft = tp->tty_outcum = 0;
                }
        }
-       return;
+       return 0;
   }
 
   /* While there is something to do. */
@@ -473,6 +441,8 @@ int try;
                        notify(pp->wrcaller);
        }
   }
+
+  return 0;
 }
 
 /*===========================================================================*
@@ -485,7 +455,7 @@ int try;
 /* The tty side has closed, so shut down the pty side. */
   pty_t *pp = tp->tty_priv;
 
-  if (!(pp->state & PTY_ACTIVE)) return;
+  if (!(pp->state & PTY_ACTIVE)) return 0;
 
   if (pp->rdleft > 0) {
        assert(!pp->rdsendreply);
@@ -498,6 +468,8 @@ int try;
   }
 
   if (pp->state & PTY_CLOSED) pp->state = 0; else pp->state |= TTY_CLOSED;
+
+  return 0;
 }
 
 /*===========================================================================*
@@ -515,6 +487,8 @@ int try;
        pp->wrleft= 0;
        notify(pp->wrcaller);
   }
+
+  return 0;
 }
 
 /*===========================================================================*
@@ -529,6 +503,8 @@ int try;
 
   pp->ocount = 0;
   pp->otail = pp->ohead;
+
+  return 0;
 }
 
 /*===========================================================================*
index a0afd5450582333848d8f0785ad578c707684c64..8bc70599fe9c81910b883df5ecce2e9b3bd1123b 100644 (file)
 
 #if NR_RS_LINES > 0
 
-#if (MACHINE != IBM_PC) && (MACHINE != ATARI)
-#error                         /* rs232.c only supports PC and Atari ST */
-#endif
-
-#if (MACHINE == ATARI)
-#include "staddr.h"
-#include "stsound.h"
-#include "stmfp.h"
-#if (NR_RS_LINES > 1)
-#error                         /* Only one physical RS232 line available */
-#endif
-#endif
-
-#if (MACHINE == IBM_PC)                /* PC/AT 8250/16450 chip combination */
-
 /* 8250 constants. */
 #define UART_FREQ         115200L      /* timer frequency */
 
 #define MS_RLSD              0x80       /* Received Line Signal Detect */
 #define MS_DRLSD             0x08       /* RLSD Delta */
 
-#else /* MACHINE == ATARI */           /* Atari ST 68901 USART */
-
-/* Most of the USART constants are already defined in stmfp.h . The local
- * definitions made here are for keeping C code changes smaller.   --kub
- */
-
-#define UART_FREQ          19200L      /* timer frequency */
-
-/* Line status bits. */
-#define LS_OVERRUN_ERR       R_OE
-#define LS_PARITY_ERR        R_PE
-#define LS_FRAMING_ERR       R_FE
-#define LS_BREAK_INTERRUPT   R_BREAK
-
-/* Modem status bits. */
-#define MS_CTS               IO_SCTS   /* 0x04 */
-
-#endif /* MACHINE == ATARI */
-
-#define DATA_BITS_SHIFT         8      /* amount data bits shifted in mode */
-#define DEF_BAUD             1200      /* default baud rate */
+#define DATA_BITS_SHIFT         8      /* amount data bits shifted in mode */
+#define DEF_BAUD             1200      /* default baud rate */
 
-#define RS_IBUFSIZE          1024      /* RS232 input buffer size */
-#define RS_OBUFSIZE          1024      /* RS232 output buffer size */
+#define RS_IBUFSIZE          1024      /* RS232 input buffer size */
+#define RS_OBUFSIZE          1024      /* RS232 output buffer size */
 
 /* Input buffer watermarks.
  * The external device is asked to stop sending when the buffer
  * exactly reaches high water, or when TTY requests it.  Sending restarts
  * when the input buffer empties below the low watermark.
  */
-#define RS_ILOWWATER   (1 * RS_IBUFSIZE / 4)
-#define RS_IHIGHWATER  (3 * RS_IBUFSIZE / 4)
+#define RS_ILOWWATER   (1 * RS_IBUFSIZE / 4)
+#define RS_IHIGHWATER  (3 * RS_IBUFSIZE / 4)
 
 /* Output buffer low watermark.
  * TTY is notified when the output buffer empties below the low watermark, so
  * it may continue filling the buffer if doing a large write.
  */
-#define RS_OLOWWATER   (1 * RS_OBUFSIZE / 4)
-
-#if (MACHINE == IBM_PC)
+#define RS_OLOWWATER   (1 * RS_OBUFSIZE / 4)
 
 /* Macros to handle flow control.
  * Interrupts must be off when they are used.
 #define devhup(rs)     \
        ((my_inb(rs->modem_status_port) & (MS_RLSD|MS_DRLSD)) == MS_DRLSD)
 
-#else /* MACHINE == ATARI */
-
-/* Macros to handle flow control.
- * Time is critical - already the function call for lock()/restore() is
- * annoying.
- * istart() tells external device we are ready by raising RTS.
- * istop() tells external device we are not ready by dropping RTS.
- * DTR is kept high all the time (it probably should be raised by open and
- * dropped by close of the device). NOTE: The modem lines are active low.
- */
-#define set_porta(msk,val) { register int s = lock();          \
-                            SOUND->sd_selr = YM_IOA;           \
-                            SOUND->sd_wdat =                   \
-                               SOUND->sd_rdat & (msk) | (val); \
-                            restore(s);        }
-#define istart(rs)         { set_porta( ~(PA_SRTS|PA_SDTR),0 ); \
-                            (rs)->idevready = TRUE;    }
-#define istop(rs)          { set_porta( ~PA_SDTR, PA_SRTS );   \
-                            (rs)->idevready = FALSE;   }
-
-/* Macro to tell if device is ready.  The rs->cts field is set to MS_CTS if
- * CLOCAL is in effect for a line without a CTS wire.
- */
-#define devready(rs)         ((~MFP->mf_gpip | rs->cts) & MS_CTS)
-
-/* Transmitter ready test */
-#define txready(rs)          (MFP->mf_tsr & (T_EMPTY | T_UE))
-
-#endif /* MACHINE == ATARI */
-
 /* Types. */
 typedef unsigned char bool_t;  /* boolean */
 
@@ -234,11 +168,6 @@ typedef struct rs232 {
 
 PUBLIC rs232_t rs_lines[NR_RS_LINES];
 
-/* Table and macro to translate an RS232 line number to its rs_lines entry. */
-PRIVATE rs232_t *p_rs_addr[NR_RS_LINES];
-
-#define rs_addr(line)  (p_rs_addr[line])
-
 #if (MACHINE == IBM_PC)
 /* 8250 base addresses. */
 PRIVATE port_t addr_8250[] = {
@@ -472,7 +401,6 @@ rs232_t *rs;                        /* which line */
   }
   if (divisor == 0) return;    /* B0? */
 
-#if (MACHINE == IBM_PC)
   /* Compute line control flag bits. */
   line_controls = 0;
   if (tp->tty_termios.c_cflag & PARENB) {
@@ -502,27 +430,6 @@ rs232_t *rs;                       /* which line */
        rs->ostate &= ~ORAW;
 
   unlock();
-
-#else /* MACHINE == ATARI */
-
-  line_controls = U_Q16;
-  if (tp->tty_termios.c_cflag & PARENB) {
-       line_controls |= U_PAR;
-       if (!(tp->tty_termios.c_cflag & PARODD)) line_controls |= U_EVEN;
-  }
-  line_controls |= (divisor >= (UART_FREQ / 110)) ? U_ST2 : U_ST1;
-
-  switch (tp->tty_termios.c_cflag & CSIZE) {   /* XXX - are U_Dn like CSn? */
-       case CS5:       line_controls |= U_D5; break;
-       case CS5:       line_controls |= U_D6; break;
-       case CS5:       line_controls |= U_D7; break;
-       case CS5:       line_controls |= U_D8; break;
-  }
-  lock();
-  MFP->mf_ucr = line_controls;
-  MFP->mf_tddr = divisor;
-  unlock();
-#endif /* MACHINE == ATARI */
 }
 
 /*===========================================================================*
@@ -536,11 +443,8 @@ tty_t *tp;                 /* which TTY */
 
   register rs232_t *rs;
   int line;
-#if (MACHINE == IBM_PC)
   port_t this_8250;
   int irq;
-  long v;
-#endif
 
   /* Associate RS232 and TTY structures. */
   line = tp - &tty_table[NR_CONS];
@@ -550,7 +454,6 @@ tty_t *tp;                  /* which TTY */
   /* Set up input queue. */
   rs->ihead = rs->itail = rs->ibuf;
 
-#if (MACHINE == IBM_PC)
   /* Precalculate port numbers for speed. Magic numbers in the code (once). */
   this_8250 = addr_8250[line];
   rs->xmit_port = this_8250 + 0;
@@ -563,7 +466,6 @@ tty_t *tp;                  /* which TTY */
   rs->modem_ctl_port = this_8250 + 4;
   rs->line_status_port = this_8250 + 5;
   rs->modem_status_port = this_8250 + 6;
-#endif
 
   /* Set up the hardware to a base state, in particular
    *   o turn off DTR (MC_DTR) to try to stop the external device.
@@ -580,22 +482,17 @@ tty_t *tp;                        /* which TTY */
    */
   istop(rs);                   /* sets modem_ctl_port */
   rs_config(rs);
-#if (MACHINE == IBM_PC)
   sys_outb(rs->int_enab_port, 0);
-#endif
 
   /* Clear any harmful leftover interrupts.  An output interrupt is harmless
    * and will occur when interrupts are enabled anyway.  Set up the output
    * queue using the status from clearing the modem status interrupt.
    */
-#if (MACHINE == IBM_PC)
   sys_inb(rs->line_status_port, &dummy);
   sys_inb(rs->recv_port, &dummy);
-#endif
   rs->ostate = devready(rs) | ORAW | OSWREADY; /* reads modem_ctl_port */
   rs->ohead = rs->otail = rs->obuf;
 
-#if (MACHINE == IBM_PC)
   /* Enable interrupts for both interrupt controller and device. */
   irq = (line & 1) == 0 ? RS232_IRQ : SECONDARY_IRQ;
 
@@ -613,20 +510,6 @@ tty_t *tp;                 /* which TTY */
 
   sys_outb(rs->int_enab_port, IE_LINE_STATUS_CHANGE | IE_MODEM_STATUS_CHANGE
                                | IE_RECEIVER_READY | IE_TRANSMITTER_READY);
-#else /* MACHINE == ATARI */
-  /* Initialize the 68901 chip, then enable interrupts. */
-  MFP->mf_scr = 0x00;
-  MFP->mf_tcdcr |= T_Q004;
-  MFP->mf_rsr = R_ENA;
-  MFP->mf_tsr = T_ENA;
-  MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
-                (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
-  MFP->mf_ddr = (MFP->mf_ddr & ~ (IO_SCTS|IO_SDCD));
-  MFP->mf_iera |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
-  MFP->mf_imra |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
-  MFP->mf_ierb |= (IB_SCTS|IB_SDCD);
-  MFP->mf_imrb |= (IB_SCTS|IB_SDCD);
-#endif /* MACHINE == ATARI */
 
   /* Fill in TTY function hooks. */
   tp->tty_devread = rs_read;
@@ -721,7 +604,7 @@ int try;
        if (ostate & ODEVHUP) {
                sigchar(tp, SIGHUP);
                tp->tty_termios.c_ospeed = B0;  /* Disable further I/O. */
-               return;
+               return 0;
        }
   }
 
@@ -744,6 +627,8 @@ int try;
        unlock();
        if ((rs->itail += count) == bufend(rs->ibuf)) rs->itail = rs->ibuf;
   }
+
+  return 0;
 }
 
 /*===========================================================================*
@@ -787,7 +672,6 @@ int dummy;
 {
 /* The line is closed; optionally hang up. */
   rs232_t *rs = tp->tty_priv;
-  int r;
 
   if (tp->tty_termios.c_cflag & HUPCL) {
        sys_outb(rs->modem_ctl_port, MC_OUT2 | MC_RTS);
@@ -797,7 +681,6 @@ int dummy;
 
 /* Low level (interrupt) routines. */
 
-#if (MACHINE == IBM_PC)
 /*===========================================================================*
  *                             rs232_handler                                *
  *===========================================================================*/
@@ -831,50 +714,6 @@ struct rs232 *rs;
        return;
   }
 }
-#endif /* MACHINE == IBM_PC */
-
-#if (MACHINE == ATARI)
-/*===========================================================================*
- *                             siaint                                       *
- *===========================================================================*/
-PRIVATE void siaint(type)
-int    type;          /* interrupt type */
-{
-/* siaint is the rs232 interrupt procedure for Atari ST's. For ST there are
- * as much as 5 interrupt lines used for rs232. The trap type byte left on the
- * stack by the assembler interrupt handler identifies the interrupt cause.
- */
-
-  register unsigned char  code;
-  register rs232_t *rs = &rs_lines[0];
-  int s = lock();
-
-  switch (type & 0x00FF)
-  {
-       case 0x00:             /* receive buffer full */
-               in_int(rs);
-               break;
-       case 0x01:             /* receive error */
-               line_int(rs);
-               break;
-       case 0x02:             /* transmit buffer empty */
-               out_int(rs);
-               break;
-       case 0x03:             /* transmit error */
-               code = MFP->mf_tsr;
-               if (code & ~(T_ENA | T_UE | T_EMPTY))
-               {
-                   printf("sia: transmit error: status=%x\r\n", code);
-                   /* MFP->mf_udr = lastchar; */ /* retry */
-               }
-               break;
-       case 0x04:              /* modem lines change */
-               modem_int(rs);
-               break;
-  }
-  restore(s);
-}
-#endif /* MACHINE == ATARI */
 
 /*===========================================================================*
  *                             in_int                                       *
@@ -895,11 +734,7 @@ register rs232_t *rs;              /* line with input interrupt */
   return;
 #endif
 
-#if (MACHINE == IBM_PC)
   sys_inb(rs->recv_port, &c);
-#else /* MACHINE == ATARI */
-  c = MFP->mf_udr;
-#endif
 
   if (!(rs->ostate & ORAW)) {
        if (c == rs->oxoff) {
@@ -937,14 +772,8 @@ register rs232_t *rs;              /* line with line status interrupt */
 /* Check for and record errors. */
 
  unsigned long s;
-#if (MACHINE == IBM_PC)
   sys_inb(rs->line_status_port, &s);
   rs->lstatus = s;
-#else /* MACHINE == ATARI */
-  rs->lstatus = MFP->mf_rsr;
-  MFP->mf_rsr &= R_ENA;
-  rs->pad = MFP->mf_udr;       /* discard char in case of LS_OVERRUN_ERR */
-#endif /* MACHINE == ATARI */
   if (rs->lstatus & LS_FRAMING_ERR) ++rs->framing_errors;
   if (rs->lstatus & LS_OVERRUN_ERR) ++rs->overrun_errors;
   if (rs->lstatus & LS_PARITY_ERR) ++rs->parity_errors;
@@ -961,12 +790,6 @@ register rs232_t *rs;              /* line with modem interrupt */
  * If the device just became ready, restart output.
  */
 
-#if (MACHINE == ATARI)
-  /* Set active edge interrupt so that next change causes a new interrupt */
-  MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
-                (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
-#endif
-
   if (devhup(rs)) {
        rs->ostate |= ODEVHUP;
        rs->tty->tty_events = 1;
@@ -994,11 +817,7 @@ register rs232_t *rs;              /* line with output interrupt */
 
   if (rs->ostate >= (ODEVREADY | OQUEUED | OSWREADY)) {
        /* Bit test allows ORAW and requires the others. */
-#if (MACHINE == IBM_PC)
        sys_outb(rs->xmit_port, *rs->otail);
-#else /* MACHINE == ATARI */
-       MFP->mf_udr = *rs->otail;
-#endif
        if (++rs->otail == bufend(rs->obuf)) rs->otail = rs->obuf;
        if (--rs->ocount == 0) {
                rs->ostate ^= (ODONE | OQUEUED);  /* ODONE on, OQUEUED off */
index 56b41247739bebb265f996f2d67f526f70b0d7ea..15dac4ee15aa5450b7823a26f64adc52a603b60b 100644 (file)
@@ -61,9 +61,9 @@
 #include <sys/ioc_tty.h>
 #include <signal.h>
 #include <minix/callnr.h>
-#if (CHIP == INTEL)
+#include <minix/sys_config.h>
+#include <minix/tty.h>
 #include <minix/keymap.h>
-#endif
 #include "tty.h"
 
 #include <sys/time.h>
@@ -92,6 +92,7 @@ unsigned long rs_irq_set = 0;
 #if NR_RS_LINES == 0
 #define rs_init(tp)    ((void) 0)
 #endif
+
 #if NR_PTYS == 0
 #define pty_init(tp)   ((void) 0)
 #define do_pty(tp, mp) ((void) 0)
@@ -138,17 +139,21 @@ PUBLIC timer_t *tty_timers;               /* queue of TTY timers */
 PUBLIC clock_t tty_next_timeout;       /* time that the next alarm is due */
 PUBLIC struct machine machine;         /* kernel environment variables */
 
+extern PUBLIC unsigned info_location;
+extern PUBLIC phys_bytes vid_size;     /* 0x2000 for color or 0x0800 for mono */
+extern PUBLIC phys_bytes vid_base;
+
+
 /*===========================================================================*
  *                             tty_task                                     *
  *===========================================================================*/
-PUBLIC void main(void)
+PUBLIC int main(void)
 {
 /* Main routine of the terminal task. */
 
   message tty_mess;            /* buffer for all incoming messages */
   unsigned line;
   int r, s;
-  register struct proc *rp;
   register tty_t *tp;
 
   /* Get kernel environment (protected_mode, pc_at and ega are needed). */ 
@@ -162,9 +167,8 @@ PUBLIC void main(void)
   /* Final one-time keyboard initialization. */
   kb_init_once();
 
-  printf("\n");
-
   while (TRUE) {
+       int adflag = 0;
 
        /* Check for and handle any events on any of the ttys. */
        for (tp = FIRST_TTY; tp < END_TTY; tp++) {
@@ -212,14 +216,16 @@ PUBLIC void main(void)
                continue;
        }
        case DIAGNOSTICS:               /* a server wants to print some */
+#if 0
                if (tty_mess.m_source != LOG_PROC_NR)
                {
-                       printf("WARNING: old DIAGNOSTICS from %d\n",
-                               tty_mess.m_source);
+                       printf("[%d ", tty_mess.m_source);
                }
+#endif
                do_diagnostics(&tty_mess, 0);
                continue;
        case DIAGNOSTICS_S: 
+       case ASYN_DIAGNOSTICS: 
                do_diagnostics(&tty_mess, 1);
                continue;
        case GET_KMESS:
@@ -299,6 +305,8 @@ PUBLIC void main(void)
                                                tty_mess.IO_ENDPT, EINVAL);
        }
   }
+
+  return 0;
 }
 
 /*===========================================================================*
@@ -397,7 +405,7 @@ register message *m_ptr;    /* pointer to message sent to the task */
 int safe;                      /* use safecopies? */
 {
 /* A process wants to read from a terminal. */
-  int r, status;
+  int r;
 
   /* Check if there is already a process hanging in a read, check if the
    * parameters are correct, do I/O.
@@ -775,9 +783,6 @@ message *m_ptr;                     /* pointer to message sent to task */
   if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc &&
        (!tp->tty_out_safe || tp->tty_out_vir_g==(vir_bytes)m_ptr->IO_GRANT)) {
        /* Process was writing when killed.  Clean up output. */
-#if DEAD_CODE
-       (*tp->tty_ocancel)(tp, 0); 
-#endif
        r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
        tp->tty_outleft = tp->tty_outcum = tp->tty_outrevived = 0;
   } 
@@ -849,9 +854,6 @@ tty_t *tp;                  /* TTY to check for events. */
  * messages (in proc.c).  This is handled by explicitly checking each line
  * for fresh input and completed output on each interrupt.
  */
-  char *buf;
-  unsigned count;
-  int status;
 
   do {
        tp->tty_events = 0;
@@ -989,7 +991,6 @@ int count;                  /* number of input characters */
 
   int ch, sig, ct;
   int timeset = FALSE;
-  static unsigned char csize_mask[] = { 0x1F, 0x3F, 0x7F, 0xFF };
 
   for (ct = 0; ct < count; ct++) {
        /* Take one character. */
@@ -1373,7 +1374,7 @@ tty_t *tp;
  * sure that an attribute change doesn't affect the processing of current
  * output.  Once output finishes the ioctl is executed as in do_ioctl().
  */
-  int result;
+  int result = EINVAL;
 
   if (tp->tty_outleft > 0) return;             /* output not finished */
 
@@ -1535,8 +1536,6 @@ PRIVATE void tty_init()
 
   register tty_t *tp;
   int s;
-  struct sigaction sa;
-  char env[100];
 
   /* Initialize the terminal lines. */
   for (tp = FIRST_TTY,s=0; tp < END_TTY; tp++,s++) {
@@ -1566,25 +1565,6 @@ PRIVATE void tty_init()
                tp->tty_minor = s - (NR_CONS+NR_RS_LINES) + TTYPX_MINOR;
        }
   }
-
-  if(env_get_param("sticky_alt", env, sizeof(env)-1) == OK
-   && atoi(env) == 1) {
-       sticky_alt_mode = 1;
-  }
-
-
-#if DEAD_CODE
-  /* Install signal handlers. Ask PM to transform signal into message. */
-  sa.sa_handler = SIG_MESS;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_flags = 0;
-  if (sigaction(SIGTERM,&sa,NULL)<0) panic("TTY","sigaction failed", errno);
-  if (sigaction(SIGKMESS,&sa,NULL)<0) panic("TTY","sigaction failed", errno);
-  if (sigaction(SIGKSTOP,&sa,NULL)<0) panic("TTY","sigaction failed", errno);
-#endif
-#if DEBUG
-       printf("end of tty_init\n");
-#endif
 }
 
 /*===========================================================================*
@@ -1670,6 +1650,7 @@ tty_t *tp;
 int try;
 {
   /* Some functions need not be implemented at the device level. */
+  return 0;
 }
 
 /*===========================================================================*
index 2f3f24c9d93ad8207504a4e2240b561dd7849063..22c059d2c6719c9589e3090e52cef572087e63cc 100644 (file)
@@ -1,8 +1,6 @@
 /*     tty.h - Terminals       */
 
 #include <timers.h>
-#include "../../kernel/const.h"
-#include "../../kernel/type.h"
 
 #undef lock
 #undef unlock
@@ -115,8 +113,6 @@ extern unsigned long rs_irq_set;
 
 extern int panicing;   /* From panic.c in sysutil */
 
-extern int sticky_alt_mode;    /* right-alt sticky to switch codepages */
-
 /* Values for the fields. */
 #define NOT_ESCAPED        0   /* previous character is not LNEXT (^V) */
 #define ESCAPED            1   /* previous character was LNEXT (^V) */
index d16b93309cfac3fa09a75a82eb31a1f8c8b0be82..61707fc3fdedb5868839d14baf96a0a20c2cf942 100644 (file)
@@ -163,6 +163,7 @@ driver is
                GETINFO         # 26
                SETGRANT        # 34
        ;
+       uid 0;
 };
 
 driver pci
@@ -217,7 +218,9 @@ driver mfs
                TIMES           # 25
                SAFECOPYFROM    # 31
                SAFECOPYTO      # 32
+               GETINFO
                SETGRANT        # 34
+                UMAP            # 14
                ;
        uid     0;
 };
index da18f0fbe68607d7713e9ef8c8da6a802d343bcc..890f9eb07fd32da8c78fc4acd25033cdba13017a 100644 (file)
@@ -1 +1,3 @@
+# which architecture to compile for
 ARCH=i386
+
diff --git a/etc/rc b/etc/rc
index 2578ad5a2c47b593ed5bdb92c42d4e93360536d4..763c680fe58b1173e19e0a3a62245689d76b72db 100755 (executable)
--- a/etc/rc
+++ b/etc/rc
@@ -42,7 +42,6 @@ esac
 
 case $action in
 start)
-    echo ""
     echo -n "Multiuser startup in progress ...:"
 
     # National keyboard?
index 6317ba6fff6f4c1bbea8247e74b50b446acb72a0..108b0a195351eec6b4d042414999c994abaa8adf 100755 (executable)
 /* User-space processes, that is, device drivers, servers, and INIT. */
 #define PM_PROC_NR       0     /* process manager */
 #define FS_PROC_NR       1     /* file system */
-#define RS_PROC_NR       2     /* reincarnation server */
+#define VFS_PROC_NR      FS_PROC_NR /* FS has been renamed to VFS. */
+#define RS_PROC_NR       2     /* memory driver (RAM disk, null, etc.) */
 #define MEM_PROC_NR      3     /* memory driver (RAM disk, null, etc.) */
 #define LOG_PROC_NR      4     /* log device driver */
 #define TTY_PROC_NR      5     /* terminal (TTY) driver */
 #define DS_PROC_NR       6     /* data store server */
 #define MFS_PROC_NR       7     /* minix root filesystem */
-#define INIT_PROC_NR     8     /* init -- goes multiuser */
+#define VM_PROC_NR        8     /* memory server */
+#define INIT_PROC_NR     9     /* init -- goes multiuser */
 
 /* Number of processes contained in the system image. */
 #define NR_BOOT_PROCS  (NR_TASKS + INIT_PROC_NR + 1)
 #define DEV_SCATTER_S          (DEV_RQ_BASE + 22) /* (safecopy) write from a vector */
 #define DEV_GATHER_S           (DEV_RQ_BASE + 23) /* (safecopy) read into a vector */
 #define DEV_IOCTL_S            (DEV_RQ_BASE + 24) /* (safecopy) I/O control code */
+#define DEV_MMAP_S             (DEV_RQ_BASE + 25) /* (safecopy) mmap interface */
 
 #define DEV_REPLY       (DEV_RS_BASE + 0) /* general task reply */
 #define DEV_CLONED      (DEV_RS_BASE + 1) /* return cloned minor */
 #  define SYS_ABORT      (KERNEL_CALL + 27)    /* sys_abort() */
 #  define SYS_IOPENABLE  (KERNEL_CALL + 28)    /* sys_enable_iop() */
 #  define SYS_VM_SETBUF  (KERNEL_CALL + 29)    /* sys_vm_setbuf() */
-#  define SYS_VM_MAP    (KERNEL_CALL + 30)     /* sys_vm_map() */
 #  define SYS_SAFECOPYFROM (KERNEL_CALL + 31)  /* sys_safecopyfrom() */
 #  define SYS_SAFECOPYTO   (KERNEL_CALL + 32)  /* sys_safecopyto() */
 #  define SYS_VSAFECOPY  (KERNEL_CALL + 33)    /* sys_vsafecopy() */
 #  define SYS_STIME    (KERNEL_CALL + 39)      /* sys_stime() */
 
 #  define SYS_MAPDMA   (KERNEL_CALL + 42)      /* sys_mapdma() */
+#  define SYS_VMCTL    (KERNEL_CALL + 43)      /* sys_vmctl() */
 
-#define NR_SYS_CALLS   43      /* number of system calls */ 
+#define NR_SYS_CALLS   44      /* number of system calls */ 
 
 /* Pseudo call for use in kernel/table.c. */
 #define SYS_ALL_CALLS (NR_SYS_CALLS)
 #   define GET_LOADINFO   15   /* get load average information */
 #   define GET_IRQACTIDS  16   /* get the IRQ masks */
 #   define GET_PRIVID    17    /* get ID of privilege structure */
+#   define GET_HZ        18    /* get HZ value */
+#   define GET_WHOAMI    19    /* get own name and endpoint */
 #define I_ENDPT      m7_i4     /* calling process */
 #define I_VAL_PTR      m7_p1   /* virtual address at caller */ 
 #define I_VAL_LEN      m7_i1   /* max length of value */
 #define I_VAL_PTR2     m7_p2   /* second virtual address */ 
 #define I_VAL_LEN2_E   m7_i2   /* second length, or proc nr */
 
+/* GET_WHOAMI fields. */
+#define GIWHO_EP       m3_i1
+#define GIWHO_NAME     m3_ca1
+
 /* Field names for SYS_TIMES. */
 #define T_ENDPT                m4_l1   /* process to request time info for */
 #define T_USER_TIME    m4_l1   /* user time consumed by process */
 #define PR_MEM_PTR     m1_p1   /* tells where memory map is for sys_newmap
                                 * and sys_fork
                                 */
+#define PR_FORK_FLAGS  m1_i3
 
 /* Field names for SYS_INT86 */
 #define INT86_REG86    m1_p1   /* pointer to registers */
 
+/* Flags for PR_FORK_FLAGS. */
+#define PFF_VMINHIBIT  0x01    /* Don't schedule until release by VM. */
+
 /* Field names for SYS_SAFECOPY* */
 #define SCP_FROM_TO    m2_i1   /* from/to whom? */
 #define SCP_INFO       m2_i2   /* byte: DDDDSSSS Dest and Src seg */
 #define RDB_ADDR       m2_l1
 #define RDB_BUF                m2_p1
 
+/* Field names for SYS_VMCTL. */
+#define SVMCTL_WHO     m1_i1
+#define SVMCTL_PARAM   m1_i2   /* All SYS_VMCTL requests. */
+#define SVMCTL_VALUE   m1_i3
+#define SVMCTL_PF_WHO          m1_i1   /* GET_PAGEFAULT reply: process ep */
+#define SVMCTL_PF_I386_CR2     m1_i2   /* GET_PAGEFAULT reply: CR2 */
+#define SVMCTL_PF_I386_ERR     m1_i3   /* GET_PAGEFAULT reply: error code */
+#define SVMCTL_MRG_ADDR                m1_p1   /* MEMREQ_GET reply: address */
+#define SVMCTL_MRG_LEN         m1_i1   /* MEMREQ_GET reply: length */
+#define SVMCTL_MRG_WRITE       m1_i2   /* MEMREQ_GET reply: writeflag */
+#define SVMCTL_MRG_EP          m1_i3   /* MEMREQ_GET reply: process */
+
+/* Values for SVMCTL_PARAM. */
+#define VMCTL_I386_SETCR3      10
+#define VMCTL_GET_PAGEFAULT    11
+#define VMCTL_CLEAR_PAGEFAULT  12
+#define VMCTL_I386_GETCR3      13
+#define VMCTL_MEMREQ_GET       14
+#define VMCTL_MEMREQ_REPLY     15
+
 /*===========================================================================*
  *                Messages for the Reincarnation Server                     *
  *===========================================================================*/
 #  define GETKM_PTR          m1_p1
 #define GET_KMESS_S    (DIAG_BASE+4)   /* get kmess from TTY */
 #  define GETKM_GRANT        m1_i1
+#define ASYN_DIAGNOSTICS (DIAG_BASE+5)         /* grant-based, replyless DIAGNOSTICS */
 
 #define DIAG_REPL      (DIAG_BASE+0x80+0)      /* reply to DIAGNOSTICS(_S) */
 
                                         * FS to update its uid and gid 
                                         * fields.
                                         */
+#define EXC_NM_RF_FULLVM       4       
 
 /* Parameters for the EXEC_RESTART call */
 #define EXC_RS_PROC    m1_i1           /* process that needs to be restarted */
                                         * implementations. See <minix/vfsif.h>
                                         */
 
+/* Requests sent by VM to VFS, done on behalf of a user process. */
+#define VM_VFS_BASE    0xB00           
+#define VM_VFS_OPEN    (VM_VFS_BASE+0) /* open() on behalf of user process. */
+#      define VMVO_NAME_GRANT          m2_i1   /* 0-terminated */
+#      define VMVO_NAME_LENGTH         m2_i2   /* name length including 0 */
+#      define VMVO_FLAGS               m2_i3
+#      define VMVO_MODE                m2_l1
+#      define VMVO_ENDPOINT            m2_l2
+#define VM_VFS_MMAP    (VM_VFS_BASE+1) /* mmap() */
+#define VM_VFS_CLOSE   (VM_VFS_BASE+2) /* close() */
+#      define VMVC_FD                  m1_i1
+#      define VMVC_ENDPOINT            m1_i2
+
+/*===========================================================================*
+ *                Messages for VM server                                    *
+ *===========================================================================*/
+#define VM_RQ_BASE             0xC00
+
+/* Calls from PM */
+#define VM_EXIT                        (VM_RQ_BASE+0)
+#      define VME_ENDPOINT             m1_i1
+#define VM_FORK                        (VM_RQ_BASE+1)
+#      define VMF_ENDPOINT             m1_i1
+#      define VMF_SLOTNO               m1_i2
+#      define VMF_CHILD_ENDPOINT       m1_i3   /* result */
+#define VM_BRK                 (VM_RQ_BASE+2)
+#      define VMB_ENDPOINT             m1_i1
+#      define VMB_ADDR                 m1_p1
+#      define VMB_RETADDR              m1_p2   /* result */
+#define VM_EXEC_NEWMEM         (VM_RQ_BASE+3)
+#      define VMEN_ENDPOINT            m1_i1
+#      define VMEN_ARGSPTR             m1_p1
+#      define VMEN_ARGSSIZE            m1_i2
+#      define VMEN_FLAGS               m1_i3   /* result */
+#      define VMEN_STACK_TOP           m1_p2   /* result */
+#define VM_PUSH_SIG            (VM_RQ_BASE+4)
+#      define VMPS_ENDPOINT            m1_i1
+#      define VMPS_OLD_SP              m1_p1   /* result */
+#define VM_WILLEXIT            (VM_RQ_BASE+5)
+#      define VMWE_ENDPOINT            m1_i1
+
+/* General calls. */
+#define VM_MMAP                        (VM_RQ_BASE+10)
+#      define VMM_ADDR                 m5_l1
+#      define VMM_LEN                  m5_l2
+#      define VMM_PROT                 m5_c1
+#      define VMM_FLAGS                m5_c2
+#      define VMM_FD                   m5_i1
+#      define VMM_OFFSET               m5_i2
+#      define VMM_RETADDR              m5_l1   /* result */
+#define VM_UMAP                        (VM_RQ_BASE+11)
+#      define VMU_SEG                  m1_i1
+#      define VMU_OFFSET               m1_p1
+#      define VMU_LENGTH               m1_p2
+#      define VMU_RETADDR              m1_p3
+
+/* to VM: inform VM about a region of memory that is used for
+ * bus-master DMA
+ */
+#define VM_ADDDMA      (VM_RQ_BASE+12)
+#      define VMAD_REQ                 m2_i2
+#      define VMAD_EP                  m2_i1
+#      define VMAD_START               m2_l1
+#      define VMAD_SIZE                m2_l2
+
+/* to VM: inform VM that a region of memory that is no longer
+ * used for bus-master DMA
+ */
+#define VM_DELDMA       (VM_RQ_BASE+13)
+#      define VMDD_REQ                 m2_i2
+#      define VMDD_EP                  m2_i1
+#      define VMDD_START               m2_l1
+#      define VMDD_SIZE                m2_l2
+
+/* to VM: ask VM for a region of memory that should not
+ * be used for bus-master DMA any longer
+ */
+#define VM_GETDMA       (VM_RQ_BASE+14)
+#      define VMGD_REQ                 m2_i2
+#      define VMGD_PROCP               m2_i1
+#      define VMGD_BASEP               m2_l1
+#      define VMGD_SIZEP               m2_l2
+
+#define VM_MAP_PHYS            (VM_RQ_BASE+15)
+#      define VMMP_EP                  m1_i1
+#      define VMMP_PHADDR              m1_p2
+#      define VMMP_LEN                 m1_i2
+#      define VMMP_VADDR_REPLY         m1_p3
+
+#define VM_UNMAP_PHYS          (VM_RQ_BASE+16)
+#      define VMUP_EP                  m1_i1
+#      define VMUP_VADDR               m1_p1
+
+#define VM_UNMAP               (VM_RQ_BASE+17)
+#      define VMUM_ADDR                m1_p1
+#      define VMUM_LEN                 m1_i1
+
+#define VM_ALLOCMEM            (VM_RQ_BASE+18)
+#      define VMAM_CLICKS              m1_p1
+#      define VMAM_MEMBASE             m1_i1
+
+/* Calls from VFS. */
+#      define VMV_ENDPOINT             m1_i1   /* for all VM_VFS_REPLY_* */
+#define VM_VFS_REPLY_OPEN      (VM_RQ_BASE+30)
+#      define VMVRO_FD                 m1_i2
+#define VM_VFS_REPLY_MMAP      (VM_RQ_BASE+31)
+#define VM_VFS_REPLY_CLOSE     (VM_RQ_BASE+32)
+
+/* Total. */
+#define VM_NCALLS                              33
+
 #endif /* _MINIX_COM_H */ 
index b0686f3c80869d7ee80da20556dd50ceee1d5f2a..8bac14ba4d968535de8a9488097cc3413d4e1504 100755 (executable)
 #define NR_PROCS         _NR_PROCS 
 #define NR_SYS_PROCS      _NR_SYS_PROCS
 
-#if _MINIX_SMALL
-
-#define NR_BUFS        100
-#define NR_BUF_HASH 128
-
-#else
-
-/* The buffer cache should be made as large as you can afford. */
-#if (MACHINE == IBM_PC && _WORD_SIZE == 2)
-#define NR_BUFS           40   /* # blocks in the buffer cache */
-#define NR_BUF_HASH       64   /* size of buf hash table; MUST BE POWER OF 2*/
-#endif
-
-#if (MACHINE == IBM_PC && _WORD_SIZE == 4)
-#define NR_BUFS         1200   /* # blocks in the buffer cache */
-#define NR_BUF_HASH     2048   /* size of buf hash table; MUST BE POWER OF 2*/
-#endif
-
-#if (MACHINE == SUN_4_60)
-#define NR_BUFS                 512    /* # blocks in the buffer cache (<=1536) */
-#define NR_BUF_HASH     512    /* size of buf hash table; MUST BE POWER OF 2*/
-#endif
-
-#endif /* _MINIX_SMALL */
-
 /* Number of controller tasks (/dev/cN device classes). */
 #define NR_CTRLRS          2
 
-/* Enable or disable the second level file system cache on the RAM disk. */
-#define ENABLE_CACHE2      0
-
-/* Enable or disable swapping processes to disk. */
-#define ENABLE_SWAP       0
-
-/* Include or exclude an image of /dev/boot in the boot image. 
- * Please update the makefile in /usr/src/tools/ as well.
- */
-#define ENABLE_BOOTDEV    0    /* load image of /dev/boot at boot time */
-
 /* DMA_SECTORS may be increased to speed up DMA based drivers. */
 #define DMA_SECTORS        1   /* DMA buffer size (must be >= 1) */
 
index 57d35deb34ba41a6958e15f37123c426ebb81987..a26716b15dd940dec4c48b23eff37fc9eaf554ea 100755 (executable)
@@ -11,7 +11,7 @@
 #define TRUE               1   /* used for turning integers into Booleans */
 #define FALSE              0   /* used for turning integers into Booleans */
 
-#define HZ               60    /* clock freq (software settable on IBM-PC) */
+#define HZ            600      /* clock freq (software settable on IBM-PC) */
 
 #define SUPER_USER (uid_t) 0   /* uid_t of superuser */
 
@@ -19,7 +19,7 @@
 #define CPVEC_NR          16   /* max # of entries in a SYS_VCOPY request */
 #define CPVVEC_NR         64   /* max # of entries in a SYS_VCOPY request */
 #define SCPVEC_NR        64    /* max # of entries in a SYS_VSAFECOPY* request */
-#define NR_IOREQS      MIN(NR_BUFS, 64)
+#define NR_IOREQS        64
                                /* maximum number of entries in an iorequest */
 
 /* Message passing constants. */
 
 #define GRANT_SEG     0x0800   /* flag indicating grant for umap */
 
+#define LOCAL_VM_SEG  0x1000   /* same as LOCAL_SEG, but with vm lookup */
+#define VM_D           (LOCAL_VM_SEG | D)
+#define VM_T           (LOCAL_VM_SEG | T)
+#define MEM_GRANT      3
+#define VM_GRANT       (LOCAL_VM_SEG | MEM_GRANT)
+
 /* Labels used to disable code sections for different reasons. */
 #define DEAD_CODE         0    /* unused code in normal configuration */
 #define FUTURE_CODE       0    /* new code to be activated + tested later */
 #define CLICK_SHIFT      12    /* log2 of CLICK_SIZE */
 #endif
 
+/* Sizes of memory tables. The boot monitor distinguishes three memory areas,
+ * namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed
+ * for DOS MINIX.
+*/
+#define NR_MEMS            8 
+
+
 /* Click to byte conversions (and vice versa). */
 #define HCLICK_SHIFT       4   /* log2 of HCLICK_SIZE */
 #define HCLICK_SIZE       16   /* hardware segment conversion magic */
 #define I_NOT_ALLOC     0000000        /* this inode is free */
 
 /* Some limits. */
-#define MAX_BLOCK_NR  ((block_t) 077777777)    /* largest block number */
-#define HIGHEST_ZONE   ((zone_t) 077777777)    /* largest zone number */
 #define MAX_INODE_NR ((ino_t) 037777777777)    /* largest inode number */
 #define MAX_FILE_POS ((off_t) 0x7FFFFFFF)      /* largest legal file offset */
 
index e123f85219bc63f6b528db328626c8abf9e5b485..8ce9b8aa97c4d40a627c2d7ee1f34473328341e3 100644 (file)
@@ -29,8 +29,8 @@ typedef struct { u16_t port; u32_t value; } pvl_pair_t;
        (pv).port = _p;                                         \
        (pv).value = _v;                                        \
        if((pv).port != _p || (pv).value != _v) {               \
-               printf("%s:%d: actual port: %x != %x || "       \
-                       "actual value: %x != %x\n",             \
+               printf("%s:%d: actual port: 0x%x != 0x%lx || "  \
+                       "actual value: 0x%x != 0x%lx\n",        \
                        __FILE__, __LINE__, (pv).port, _p, (pv).value, _v); \
                panic(__FILE__, "pv_set(" #pv ", " #p ", " #v ")", NO_NUM); \
        }                                                       \
index 1eef6fb1e7e284442e423b8ce1db298524c1c750..8f661892744541665c20c261e91d0a199343e526 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _IPC_H
 #define _IPC_H
 
+#include <minix/type.h>
+
 /*==========================================================================* 
  * Types relating to messages.                                                     *
  *==========================================================================*/ 
index 97fea6fee0a7d4d047a02d4e6489a5315ce629b0..c0fd599c02a952ea8536552a5b422e74553e4471 100755 (executable)
@@ -20,7 +20,6 @@
 
 #define _NR_PROCS      100
 #define _NR_SYS_PROCS  32
-#define _NR_HOLES (2*_NR_PROCS+4)  /* No. of memory holes maintained by PM */
 
 /* Set the CHIP type based on the machine selected. The symbol CHIP is actually
  * indicative of more than just the CPU.  For example, machines for which
@@ -71,4 +70,6 @@ error "_MINIX_MACHINE has incorrect value (0)"
 /* Kernel debug checks */
 #define DEBUG_LOCK_CHECK 1     /* Interrupt Lock/unlock sanity checking. */
 
+#define _KMESS_BUF_SIZE  30000
+
 #endif /* _MINIX_SYS_CONFIG_H */
index 77a1e4e8f03fcd31a936ee253240a4606297c94b..bdc2fcbbd2b838b46b0ce3bd1f838fc1ef2a0cc6 100755 (executable)
@@ -34,7 +34,8 @@ _PROTOTYPE( int sys_abort, (int how, ...));
 _PROTOTYPE( int sys_enable_iop, (endpoint_t proc));
 _PROTOTYPE( int sys_exec, (endpoint_t proc, char *ptr,  
                                char *aout, vir_bytes initpc));
-_PROTOTYPE( int sys_fork, (int parent, int child, int *, struct mem_map *ptr));
+_PROTOTYPE( int sys_fork, (endpoint_t parent, endpoint_t child, int *,
+       struct mem_map *ptr, u32_t vm));
 _PROTOTYPE( int sys_newmap, (endpoint_t proc, struct mem_map *ptr));
 _PROTOTYPE( int sys_exit, (endpoint_t proc));
 _PROTOTYPE( int sys_trace, (int req, endpoint_t proc, long addr, long *data_p));
@@ -48,6 +49,13 @@ _PROTOTYPE( int sys_vm_setbuf, (phys_bytes base, phys_bytes size,
                                                        phys_bytes high));
 _PROTOTYPE( int sys_vm_map, (endpoint_t proc_nr, int do_map,
        phys_bytes base, phys_bytes size, phys_bytes offset));
+_PROTOTYPE( int sys_vmctl, (endpoint_t who, int param, u32_t value));
+_PROTOTYPE( int sys_vmctl_get_pagefault_i386, (endpoint_t *who, u32_t *cr2, u32_t *err));
+_PROTOTYPE( int sys_vmctl_get_cr3_i386, (endpoint_t who, u32_t *cr3)  );
+_PROTOTYPE( int sys_vmctl_get_memreq, (endpoint_t *who, vir_bytes *mem,
+        vir_bytes *len, int *wrflag) );
+
+
 
 _PROTOTYPE( int sys_readbios, (phys_bytes address, void *buf, size_t size));
 _PROTOTYPE( int sys_stime, (time_t boottime));
@@ -71,6 +79,9 @@ _PROTOTYPE( int sys_stime, (time_t boottime));
   sys_sdevio(DIO_SAFE_OUTPUT_WORD, port, ept, (void*)grant, count, offset)
 _PROTOTYPE( int sys_sdevio, (int req, long port, endpoint_t proc_nr,
        void *buffer, int count, vir_bytes offset));
+_PROTOTYPE(void *alloc_contig, (size_t len, int flags, phys_bytes *phys));
+#define AC_ALIGN4K     0x01
+#define AC_LOWER16M    0x02
 
 /* Clock functionality: get system times or (un)schedule an alarm call. */
 _PROTOTYPE( int sys_times, (endpoint_t proc_nr, clock_t *user_time,
@@ -128,6 +139,8 @@ _PROTOTYPE(int sys_physvcopy, (phys_cp_req *vec_ptr,int vec_size,int *nr_ok));
 
 _PROTOTYPE(int sys_umap, (endpoint_t proc_nr, int seg, vir_bytes vir_addr,
         vir_bytes bytes, phys_bytes *phys_addr));
+_PROTOTYPE(int sys_umap_data_fb, (endpoint_t proc_nr, vir_bytes vir_addr,
+        vir_bytes bytes, phys_bytes *phys_addr));
 _PROTOTYPE(int sys_segctl, (int *index, u16_t *seg, vir_bytes *off,
        phys_bytes phys, vir_bytes size));
 
@@ -151,6 +164,7 @@ _PROTOTYPE(int sys_segctl, (int *index, u16_t *seg, vir_bytes *off,
 #define sys_getprivid(nr)      sys_getinfo(GET_PRIVID, 0, 0,0, nr)
 _PROTOTYPE(int sys_getinfo, (int request, void *val_ptr, int val_len,
                                 void *val_ptr2, int val_len2)          );
+_PROTOTYPE(int sys_whoami, (endpoint_t *ep, char *name, int namelen));
 
 /* Signal control. */
 _PROTOTYPE(int sys_kill, (endpoint_t proc, int sig) );
index 8702ea8c2d76925061c3bcf7443008bebf5b0dd7..2af9bbc053f9d65538d149f0ac3f0786c4d1e441 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _MINIX_SYSUTIL_H
 #define _MINIX_SYSUTIL_H 1
 
+#include <minix/ipc.h>
+
 /* Extra system library definitions to support device drivers and servers.
  *
  * Created:
@@ -48,9 +50,15 @@ _PROTOTYPE( int getuptime, (clock_t *ticks));
 _PROTOTYPE( int getuptime2, (clock_t *ticks, time_t *boottime));
 _PROTOTYPE( int tickdelay, (clock_t ticks));
 _PROTOTYPE( int micro_delay_calibrate, (void));
+_PROTOTYPE( u32_t sys_hz, (void));
+_PROTOTYPE( void util_stacktrace, (void));
+_PROTOTYPE( void util_nstrcat, (char *str, unsigned long n) );
+_PROTOTYPE( void util_stacktrace_strcat, (char *));
 _PROTOTYPE( int micro_delay, (u32_t micros));
+_PROTOTYPE( u32_t micros_to_ticks, (u32_t micros));
+_PROTOTYPE( int asynsend, (endpoint_t ep, message *msg));
 
-#define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)
+#define ASSERT(c) if(!(c)) { panic(__FILE__, "assert " #c " failed at line", __LINE__); }
 
 #endif /* _MINIX_SYSUTIL_H */
 
diff --git a/include/minix/tty.h b/include/minix/tty.h
new file mode 100644 (file)
index 0000000..fcf8d2f
--- /dev/null
@@ -0,0 +1,28 @@
+
+#ifndef _MINIX_TTY_H
+#define _MINIX_TTY_H
+
+#include <sys/types.h>
+
+#define TTYMAGIC       0xb105
+
+/* A struct that the tty driver can use to pass values to the boot monitor.
+ * Currently only the value of the origin of the first vty (console), so the
+ * boot monitor can properly display it when panicing (tty isn't scheduled
+ * to switch to the first vty). It's written at the end of video memory
+ * (video memory base + video memory size - sizeof(struct boot_tty_info).
+ */
+
+struct boot_tty_info {
+       u16_t   reserved[30];   /* reserved, set to 0 */
+       u16_t   consorigin;     /* origin in video memory of console */
+       u16_t   conscursor;     /* position of cursor of console */
+       u16_t   flags;          /* flags indicating which fields are valid */
+       u16_t   magic;          /* magic number indicating struct is valid */
+};
+
+#define BTIF_CONSORIGIN        0x01    /* consorigin is set */
+#define BTIF_CONSCURSOR        0x02    /* conscursor is set */
+
+#endif
+
index 08582c25320bc1a87836c330af8de5c9bc44ae0e..8be6b33a6aa368d23b0ec27edc3307192d1eb9a9 100755 (executable)
@@ -16,7 +16,7 @@ typedef unsigned int phys_clicks;     /* physical addr/length in clicks */
 typedef int endpoint_t;                        /* process identifier */
 
 #if (_MINIX_CHIP == _CHIP_INTEL)
-typedef unsigned int vir_bytes;        /* virtual addresses and lengths in bytes */
+typedef long unsigned int vir_bytes;   /* virtual addresses/lengths in bytes */
 #endif
 
 #if (_MINIX_CHIP == _CHIP_M68000)
@@ -48,19 +48,6 @@ struct vir_addr {
   vir_bytes offset;
 };
 
-/* Memory allocation by PM. */
-struct hole {
-  struct hole *h_next;          /* pointer to next entry on the list */
-  phys_clicks h_base;           /* where does the hole begin? */
-  phys_clicks h_len;            /* how big is the hole? */
-};
-
-/* Memory info from PM. */
-struct pm_mem_info {
-       struct hole pmi_holes[_NR_HOLES];/* memory (un)allocations */
-       u32_t pmi_hi_watermark;          /* highest ever-used click + 1 */
-};
-
 #define phys_cp_req vir_cp_req 
 struct vir_cp_req {
   struct vir_addr src;
@@ -98,14 +85,14 @@ struct kinfo {
   phys_bytes data_base;                /* base of kernel data */
   phys_bytes data_size;
   vir_bytes proc_addr;         /* virtual address of process table */
-  phys_bytes kmem_base;                /* kernel memory layout (/dev/kmem) */
-  phys_bytes kmem_size;
+  phys_bytes _kmem_base;       /* kernel memory layout (/dev/kmem) */
+  phys_bytes _kmem_size;
   phys_bytes bootdev_base;     /* boot device from boot image (/dev/boot) */
   phys_bytes bootdev_size;
   phys_bytes ramdev_base;      /* boot device from boot image (/dev/boot) */
   phys_bytes ramdev_size;
-  phys_bytes params_base;      /* parameters passed by boot monitor */
-  phys_bytes params_size;
+  phys_bytes _params_base;     /* parameters passed by boot monitor */
+  phys_bytes _params_size;
   int nr_procs;                        /* number of user processes */
   int nr_tasks;                        /* number of kernel tasks */
   char release[6];             /* kernel release number */
@@ -176,4 +163,21 @@ struct memory {
        phys_bytes      size;
 };
 
+#define STATICINIT(v, n) \
+       if(!(v)) {      \
+               phys_bytes myph; \
+               if(!((v) = alloc_contig(sizeof(*(v)) * (n), 0, &myph))) { \
+                       panic(__FILE__, "allocating " #v " failed", n); \
+               }       \
+       }
+
+/* The kernel outputs diagnostic messages in a circular buffer. */
+struct kmessages {
+  int km_next;                          /* next index to write */
+  int km_size;                          /* current size in buffer */
+  char km_buf[_KMESS_BUF_SIZE];          /* buffer for messages */
+};
+
+
 #endif /* _TYPE_H */
+
diff --git a/include/minix/vm.h b/include/minix/vm.h
new file mode 100755 (executable)
index 0000000..475f499
--- /dev/null
@@ -0,0 +1,29 @@
+/* Prototypes and definitions for VM interface. */
+
+#ifndef _MINIX_VM_H
+#define _MINIX_VM_H
+
+#include <sys/types.h>
+#include <minix/endpoint.h>
+
+_PROTOTYPE( int vm_exit, (endpoint_t ep));
+_PROTOTYPE( int vm_fork, (endpoint_t ep, int slotno, int *child_ep));
+_PROTOTYPE( int vm_brk, (endpoint_t ep, char *newaddr));
+_PROTOTYPE( int vm_exec_newmem, (endpoint_t ep, struct exec_newmem *args,
+       int args_bytes, char **ret_stack_top, int *ret_flags));
+_PROTOTYPE( int vm_push_sig, (endpoint_t ep, vir_bytes *old_sp));
+_PROTOTYPE( int vm_willexit, (endpoint_t ep));
+_PROTOTYPE( int vm_adddma, (endpoint_t req_e, endpoint_t proc_e, 
+                                phys_bytes start, phys_bytes size)      );
+_PROTOTYPE( int vm_deldma, (endpoint_t req_e, endpoint_t proc_e, 
+                                phys_bytes start, phys_bytes size)      );
+_PROTOTYPE( int vm_getdma, (endpoint_t req_e, endpoint_t *procp,
+                               phys_bytes *basep, phys_bytes *sizep)   );
+_PROTOTYPE( void *vm_map_phys, (endpoint_t who, size_t len, void *physaddr));
+_PROTOTYPE( int vm_unmap_phys, (endpoint_t who, void *vaddr, size_t len));
+
+_PROTOTYPE( int vm_allocmem, (phys_clicks memclicks, phys_clicks *retmembase));
+
+
+#endif /* _MINIX_VM_H */
+
index 948a41e09f9eda0b5f620128c9bedb400933651b..c37972443fd343323779373635b81ffdb0656a54 100755 (executable)
@@ -36,4 +36,8 @@
 #define KIOCSLEDS       _IOW('k', 2, struct kio_leds)
 #define KIOCSMAP       _IOW('k', 3, keymap_t)
 
+/* /dev/video ioctls. */
+#define TIOCMAPMEM     _IORW('v', 1, struct mapreqvm)
+#define TIOCUNMAPMEM   _IORW('v', 2, struct mapreqvm)
+
 #endif /* _S_I_TTY_H */
diff --git a/include/sys/mman.h b/include/sys/mman.h
new file mode 100755 (executable)
index 0000000..1c3ef37
--- /dev/null
@@ -0,0 +1,29 @@
+
+#ifndef _MMAN_H
+#define _MMAN_H
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+/* prot argument for mmap() */
+#define PROT_NONE       0x00    /* no permissions */
+#define PROT_READ       0x01    /* pages can be read */
+#define PROT_WRITE      0x02    /* pages can be written */
+#define PROT_EXEC       0x04    /* pages can be executed */
+
+/* flags argument for mmap()  */
+#define MAP_SHARED      0x0001          /* share changes */
+#define MAP_PRIVATE     0x0002          /* changes are private */
+#define MAP_ANON       0x0004          /* anonymous memory */
+#define MAP_PREALLOC   0x0008          /* not on-demand */
+#define MAP_CONTIG     0x0010          /* contiguous in physical memory */
+#define MAP_LOWER16M   0x0020          /* physically below 16MB */
+
+/* mmap() error return */
+#define MAP_FAILED      ((void *)-1)
+
+_PROTOTYPE( void *mmap, (void *, size_t, int, int, int, off_t));
+_PROTOTYPE( int munmap, (void *, size_t));
+
+#endif /* _MMAN_H */
diff --git a/include/sys/video.h b/include/sys/video.h
new file mode 100644 (file)
index 0000000..f6f425e
--- /dev/null
@@ -0,0 +1,39 @@
+
+#ifndef _SYS_VIDEO_H
+#define _SYS_VIDEO_H 1
+
+/* Definitions used by the console driver. */
+#define MONO_BASE    0xB0000L   /* base of mono video memory */
+#define COLOR_BASE   0xB8000L   /* base of color video memory */
+#define MONO_SIZE     0x1000    /* 4K mono video memory */
+#define COLOR_SIZE    0x4000    /* 16K color video memory */
+#define EGA_SIZE      0x8000    /* EGA & VGA have at least 32K */
+#define BLANK_COLOR   0x0700    /* determines cursor color on blank screen */
+#define SCROLL_UP          0    /* scroll forward */
+#define SCROLL_DOWN        1    /* scroll backward */
+#define BLANK_MEM ((u16_t *) 0) /* tells mem_vid_copy() to blank the screen */
+#define CONS_RAM_WORDS    80    /* video ram buffer size */
+#define MAX_ESC_PARMS      4    /* number of escape sequence params allowed */
+
+/* Constants relating to the controller chips. */
+#define M_6845         0x3B4    /* port for 6845 mono */
+#define C_6845         0x3D4    /* port for 6845 color */
+#define INDEX              0    /* 6845's index register */
+#define DATA               1    /* 6845's data register */
+#define STATUS             6    /* 6845's status register */
+#define VID_ORG           12    /* 6845's origin register */
+#define CURSOR            14    /* 6845's cursor register */
+
+/* Beeper. */
+#define BEEP_FREQ     0x0533    /* value to put into timer to set beep freq */
+#define B_TIME             3    /* length of CTRL-G beep is ticks */
+
+/* definitions used for font management */
+#define GA_SEQUENCER_INDEX      0x3C4
+#define GA_SEQUENCER_DATA       0x3C5
+#define GA_GRAPHICS_INDEX       0x3CE
+#define GA_GRAPHICS_DATA        0x3CF
+#define GA_VIDEO_ADDRESS        0xA0000L
+#define GA_FONT_SIZE            8192
+
+#endif
index a5d95374b84d5f45e712a577ad944575d3adb0ac..b0155aa441f196235550a5748017597566c9efe6 100644 (file)
@@ -2,8 +2,6 @@
 sys/vm.h
 */
 
-#define PAGE_SIZE      4096
-
 /* MIOCMAP */
 struct mapreq
 {
@@ -13,18 +11,14 @@ struct mapreq
        int readonly;
 };
 
-/* i386 paging constants */
-#define I386_VM_PRESENT        0x001   /* Page is present */
-#define I386_VM_WRITE  0x002   /* Read/write access allowed */
-#define I386_VM_USER   0x004   /* User access allowed */
-#define I386_VM_PWT    0x008   /* Write through */
-#define I386_VM_PCD    0x010   /* Cache disable */
-#define I386_VM_ADDR_MASK 0xFFFFF000 /* physical address */
-
-#define I386_VM_PT_ENT_SIZE    4       /* Size of a page table entry */
-#define I386_VM_DIR_ENTRIES    1024    /* Number of entries in a page dir */
-#define I386_VM_DIR_ENT_SHIFT  22      /* Shift to get entry in page dir. */
-#define I386_VM_PT_ENT_SHIFT   12      /* Shift to get entry in page table */
-#define I386_VM_PT_ENT_MASK    0x3FF   /* Mask to get entry in page table */
 
-#define I386_CR0_PG            0x80000000      /* Enable paging */             
+/* MIOCMAPVM */
+struct mapreqvm
+{
+       int     flags;          /* reserved, must be 0 */
+       off_t   phys_offset;
+       size_t  size;
+       int     readonly;
+       char    reserved[40];   /* reserved, must be 0 */
+       void    *vaddr_ret;     /* result vaddr */
+};
diff --git a/include/sys/vm_i386.h b/include/sys/vm_i386.h
new file mode 100644 (file)
index 0000000..dcea95b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+sys/vm_i386.h
+*/
+
+#define I386_PAGE_SIZE 4096
+
+/* i386 paging constants */
+#define I386_VM_PRESENT        0x001   /* Page is present */
+#define I386_VM_WRITE  0x002   /* Read/write access allowed */
+#define I386_VM_USER   0x004   /* User access allowed */
+#define I386_VM_PWT    0x008   /* Write through */
+#define I386_VM_PCD    0x010   /* Cache disable */
+#define I386_VM_ACC    0x020   /* Accessed */
+#define I386_VM_ADDR_MASK 0xFFFFF000 /* physical address */
+
+/* Page directory specific flags. */
+#define I386_VM_BIGPAGE        0x080   /* 4MB page */
+
+/* Page table specific flags. */
+#define I386_VM_DIRTY  0x040   /* Dirty */
+#define I386_VM_PTAVAIL1 0x080 /* Available for use. */
+#define I386_VM_PTAVAIL2 0x100 /* Available for use. */
+
+#define I386_VM_PT_ENT_SIZE    4       /* Size of a page table entry */
+#define I386_VM_DIR_ENTRIES    1024    /* Number of entries in a page dir */
+#define I386_VM_DIR_ENT_SHIFT  22      /* Shift to get entry in page dir. */
+#define I386_VM_PT_ENT_SHIFT   12      /* Shift to get entry in page table */
+#define I386_VM_PT_ENT_MASK    0x3FF   /* Mask to get entry in page table */
+#define I386_VM_PT_ENTRIES     1024    /* Number of entries in a page table */
+#define I386_VM_PFA_SHIFT      22      /* Page frame address shift */
+
+#define I386_CR0_PG            0x80000000      /* Enable paging */             
+
+/* i386 paging 'functions' */
+#define I386_VM_PTE(v) (((v) >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK)
+#define I386_VM_PDE(v) ( (v) >> I386_VM_DIR_ENT_SHIFT)
+#define I386_VM_PFA(e) ( (e) & I386_VM_ADDR_MASK)
+#define I386_VM_PAGE(v)        ( (v) >> I386_VM_PFA_SHIFT)
+
+/* i386 pagefault error code bits */
+#define I386_VM_PFE_P  0x01    /* Pagefault caused by non-present page.
+                                * (otherwise protection violation.)
+                                */
+#define I386_VM_PFE_W  0x02    /* Caused by write (otherwise read) */
+#define I386_VM_PFE_U  0x04    /* CPU in user mode (otherwise supervisor) */
index 8cb0f3a8cf97b7a1992bf4bc896ecfe94e4508a4..6915480e2eef03660ec2f2f307764eb2edd41734 100755 (executable)
@@ -9,7 +9,7 @@
 #ifndef _TIME_H
 #define _TIME_H
 
-#define CLOCKS_PER_SEC    60   /* MINIX always uses 60 Hz, even in Europe */
+#define CLOCKS_PER_SEC    60
 
 #ifdef _POSIX_SOURCE
 #define CLK_TCK CLOCKS_PER_SEC /* obsolescent mame for CLOCKS_PER_SEC */
index e1a81060d4ad7c9e017e957b9127b268828bd0de..b59e00ecbc0d2da00df2019591f8050258f02942 100755 (executable)
@@ -1,3 +1,6 @@
+#ifndef _INCLUDE_TOOLS_H
+#define _INCLUDE_TOOLS_H 1
+
 /* Constants describing the disk */
 #define SECTOR_SIZE    512
 #define SECTOR_SHIFT   9
@@ -121,3 +124,4 @@ _PROTOTYPE( void relocate, (void));
 _PROTOTYPE( int writesectors, (int _off, int _seg, off_t _adr, int _ct));
 #endif
 
+#endif
index f1e839735be0a8134f6db85d613e275252171f42..407731a77535b4c06bf9226dc08d4cd59f5c7f3b 100755 (executable)
@@ -18,21 +18,20 @@ CFLAGS=$(CPROFILE) $(CPPFLAGS) $(EXTRA_OPTS)
 LDFLAGS=-i 
 
 # first-stage, arch-dependent startup code
-HEAD = head.o
-FULLHEAD = $a/$(HEAD)
+HEAD = $a/mpx386.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
+LIBS = -ltimers -lsys
 
 # What to make.
 all: build 
-kernel build install: $(HEAD) $(OBJS) 
+kernel build install: $(OBJS) 
        cd system && $(MAKE) $@
        cd $a && $(MAKE) $@
-       $(LD) $(CFLAGS) $(LDFLAGS) -o kernel $(FULLHEAD) $(OBJS) \
+       $(LD) $(CFLAGS) $(LDFLAGS) -o kernel $(HEAD) $(OBJS) \
                $(SYSTEM) $(ARCHLIB) $(LIBS)
        install -S 0 kernel
 
@@ -50,8 +49,5 @@ depend:
 .c.o:
        $(CC) $(CFLAGS) -c -o $@ $<
 
-$(HEAD): 
-       cd $a && make HEAD=$(HEAD) $(HEAD)
-
 # Include generated dependencies.
 include .depend
index c7a5dc6a77ac82f3ed9563ad2069415a1ac07700..20d9181e479e851374e66538f7bc219b1ca60d98 100755 (executable)
@@ -8,17 +8,19 @@ ARCHAR=$(ARCH).a
 # 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)
+OBJS=  arch_do_vmctl.o \
+       clock.o \
+       do_int86.o \
+       do_iopenable.o \
+       do_readbios.o \
+       do_sdevio.o \
+       exception.o \
+       i8259.o \
+       klib386.o \
+       memory.o \
+       mpx386.o \
+       protect.o \
+       system.o
 
 CPPFLAGS=-Iinclude
 CFLAGS=$(CPPFLAGS) -Wall
@@ -56,6 +58,9 @@ $(ARCHAR)(do_int86.o): do_int86.c
 $(ARCHAR)(do_iopenable.o): do_iopenable.c
        $(CC) $(CFLAGS) -c $<
 
+$(ARCHAR)(arch_do_vmctl.o): arch_do_vmctl.c
+       $(CC) $(CFLAGS) -c $<
+
 $(ARCHAR)(do_readbios.o): do_readbios.c
        $(CC) $(CFLAGS) -c $<
 
diff --git a/kernel/arch/i386/arch_do_vmctl.c b/kernel/arch/i386/arch_do_vmctl.c
new file mode 100644 (file)
index 0000000..b82ce52
--- /dev/null
@@ -0,0 +1,56 @@
+/* The kernel call implemented in this file:
+ *   m_type:   SYS_VMCTL
+ *
+ * The parameters for this kernel call are:
+ *     SVMCTL_WHO      which process
+ *     SVMCTL_PARAM    set this setting (VMCTL_*)
+ *     SVMCTL_VALUE    to this value
+ */
+
+#include "../../system.h"
+#include <minix/type.h>
+
+extern u32_t kernel_cr3;
+
+/*===========================================================================*
+ *                             arch_do_vmctl                                *
+ *===========================================================================*/
+PUBLIC int arch_do_vmctl(m_ptr, p)
+register message *m_ptr;       /* pointer to request message */
+struct proc *p;
+{
+  switch(m_ptr->SVMCTL_PARAM) {
+       case VMCTL_I386_GETCR3:
+               /* Get process CR3. */
+               m_ptr->SVMCTL_VALUE = p->p_seg.p_cr3;
+               return OK;
+       case VMCTL_I386_SETCR3:
+               /* Set process CR3. */
+               if(m_ptr->SVMCTL_VALUE) {
+                       p->p_seg.p_cr3 = m_ptr->SVMCTL_VALUE;
+                       p->p_misc_flags |= MF_FULLVM;
+               } else {
+                       p->p_seg.p_cr3 = kernel_cr3;
+                       p->p_misc_flags &= ~MF_FULLVM;
+               }
+               RTS_LOCK_UNSET(p, VMINHIBIT);
+               return OK;
+        case VMCTL_GET_PAGEFAULT:
+       {
+               struct proc *rp;
+               if(!(rp=pagefaults))
+                       return ESRCH;
+               pagefaults = rp->p_nextpagefault;
+               if(!RTS_ISSET(rp, PAGEFAULT))
+                       minix_panic("non-PAGEFAULT process on pagefault chain",
+                               rp->p_endpoint);
+                m_ptr->SVMCTL_PF_WHO = rp->p_endpoint;
+                m_ptr->SVMCTL_PF_I386_CR2 = rp->p_pagefault.pf_virtual;
+               m_ptr->SVMCTL_PF_I386_ERR = rp->p_pagefault.pf_flags;
+               return OK;
+       }
+  }
+
+  kprintf("arch_do_vmctl: strange param %d\n", m_ptr->SVMCTL_PARAM);
+  return EINVAL;
+}
index 9809dc29170a268cddd6f08fbeebb41d7826a689..9ff1db87628f51663b69bb77d3d1504946b4d719 100644 (file)
@@ -21,28 +21,23 @@ struct reg86u reg86;
 PUBLIC int do_int86(m_ptr)
 register message *m_ptr;       /* pointer to request message */
 {
-  vir_bytes caller_vir;
-  phys_bytes caller_phys, kernel_phys;
-
-  caller_vir = (vir_bytes) m_ptr->INT86_REG86;
-  caller_phys = umap_local(proc_addr(who_p), D, caller_vir, sizeof(reg86));
-  if (0 == caller_phys) return(EFAULT);
-  kernel_phys = vir2phys(&reg86);
-  phys_copy(caller_phys, kernel_phys, (phys_bytes) sizeof(reg86));
+  data_copy(who_e, (vir_bytes) m_ptr->INT86_REG86,
+       SYSTEM, (vir_bytes) &reg86, sizeof(reg86));
 
   level0(int86);
 
   /* Copy results back to the caller */
-  phys_copy(kernel_phys, caller_phys, (phys_bytes) sizeof(reg86));
+  data_copy(SYSTEM, (vir_bytes) &reg86,
+       who_e, (vir_bytes) m_ptr->INT86_REG86, sizeof(reg86));
 
   /* The BIOS call eats interrupts. Call get_randomness to generate some
    * entropy. Normally, get_randomness is called from an interrupt handler.
    * Figuring out the exact source is too complicated. CLOCK_IRQ is normally
    * not very random.
    */
-  lock(0, "do_int86");
+  lock;
   get_randomness(CLOCK_IRQ);
-  unlock(0);
+  unlock;
 
   return(OK);
 }
index d09602f4c2b4f4c9a30da980dcdc4cce03675881..d5a5a068cb9f5bfaf150c6ea32522dc6f885f5e5 100644 (file)
 PUBLIC int do_readbios(m_ptr)
 register message *m_ptr;       /* pointer to request message */
 {
-  int proc_nr;
-  struct proc *p;
-  phys_bytes address, phys_buf, phys_bios;
-  vir_bytes buf;
-  size_t size;
+  struct vir_addr src, dst;     
+        
+  src.segment = BIOS_SEG;
+  dst.segment = D;
+  src.offset = m_ptr->RDB_ADDR;
+  dst.offset = (vir_bytes) m_ptr->RDB_BUF;
+  src.proc_nr_e = NONE;
+  dst.proc_nr_e = m_ptr->m_source;      
 
-  address = m_ptr->RDB_ADDR;
-  buf = (vir_bytes)m_ptr->RDB_BUF;
-  size = m_ptr->RDB_SIZE;
-
-  okendpt(m_ptr->m_source, &proc_nr);
-  p = proc_addr(proc_nr);
-  phys_buf = umap_local(p, D, buf, size);
-  if (phys_buf == 0)
-       return EFAULT;
-  phys_bios = umap_bios(p, address, size);
-  if (phys_bios == 0)
-       return EPERM;
-  phys_copy(phys_bios, phys_buf, size);
-  return 0;
+  return virtual_copy_vmcheck(&src, &dst, m_ptr->RDB_SIZE);
 }
index c0ea693d772d4d0910a07b72d65369d778f6a127..5028d9e650a3df3192506ec026a9c94af927e465 100644 (file)
@@ -77,7 +77,7 @@ register message *m_ptr;      /* pointer to request message */
        return EPERM;
      }
      /* Get and check physical address. */
-     if ((phys_buf = numap_local(proc_nr,
+     if ((phys_buf = umap_virtual(proc_addr(proc_nr), D,
         (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
          return(EFAULT);
   }
index a979fe87742d2ae2bdce91b37a39f9245af7f7dd..7fa7cc686cc25018aa40e6263fd1496e86894161 100755 (executable)
@@ -6,8 +6,66 @@
 #include "../../kernel.h"
 #include "proto.h"
 #include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <minix/sysutil.h>
 #include "../../proc.h"
 
+extern int vm_copy_in_progress;
+extern struct proc *vm_copy_from, *vm_copy_to;
+extern u32_t vm_copy_from_v, vm_copy_to_v;
+extern u32_t vm_copy_from_p, vm_copy_to_p, vm_copy_cr3;
+
+u32_t pagefault_cr2, pagefault_count = 0;
+
+void pagefault(struct proc *pr, int trap_errno)
+{
+       int s;
+       vir_bytes ph;
+       u32_t pte;
+
+       if(pagefault_count != 1)
+               minix_panic("recursive pagefault", pagefault_count);
+
+       /* Don't schedule this process until pagefault is handled. */
+       if(RTS_ISSET(pr, PAGEFAULT))
+               minix_panic("PAGEFAULT set", pr->p_endpoint);
+       RTS_LOCK_SET(pr, PAGEFAULT);
+
+       if(pr->p_endpoint <= INIT_PROC_NR) {
+               /* Page fault we can't / don't want to
+                * handle.
+                */
+               kprintf("pagefault for process %d ('%s'), pc = 0x%x\n",
+                       pr->p_endpoint, pr->p_name, pr->p_reg.pc);
+               proc_stacktrace(pr);
+               minix_panic("page fault in system process", pr->p_endpoint);
+
+               return;
+       }
+
+       /* Save pagefault details, suspend process,
+        * add process to pagefault chain,
+        * and tell VM there is a pagefault to be
+        * handled.
+        */
+       pr->p_pagefault.pf_virtual = pagefault_cr2;
+       pr->p_pagefault.pf_flags = trap_errno;
+       pr->p_nextpagefault = pagefaults;
+       pagefaults = pr;
+       lock_notify(HARDWARE, VM_PROC_NR);
+
+       pagefault_count = 0;
+
+#if 0
+       kprintf("pagefault for process %d ('%s'), pc = 0x%x\n",
+                       pr->p_endpoint, pr->p_name, pr->p_reg.pc);
+       proc_stacktrace(pr);
+#endif
+
+       return;
+}
+
 /*===========================================================================*
  *                             exception                                    *
  *===========================================================================*/
@@ -62,8 +120,13 @@ u32_t old_eflags;
    * k_reenter larger than zero.
    */
   if (k_reenter == 0 && ! iskernelp(saved_proc)) {
-#if 0
        {
+               switch(vec_nr) {
+                       case PAGE_FAULT_VECTOR:
+                               pagefault(saved_proc, trap_errno);
+                               return;
+               }
+
                kprintf(
 "exception for process %d, endpoint %d ('%s'), pc = 0x%x:0x%x, sp = 0x%x:0x%x\n",
                        proc_nr(saved_proc), saved_proc->p_endpoint,
@@ -75,12 +138,11 @@ u32_t old_eflags;
                        vec_nr, (unsigned long)trap_errno,
                        (unsigned long)old_eip, old_cs,
                        (unsigned long)old_eflags);
-#if DEBUG_STACKTRACE
-               stacktrace(saved_proc);
-#endif
+               proc_stacktrace(saved_proc);
        }
-#endif
 
+       kprintf("kernel: cause_sig %d for %d\n",
+               ep->signum, saved_proc->p_endpoint);
        cause_sig(proc_nr(saved_proc), ep->signum);
        return;
   }
@@ -92,43 +154,45 @@ u32_t old_eflags;
        kprintf("\n%s\n", ep->msg);
   kprintf("k_reenter = %d ", k_reenter);
   kprintf("process %d (%s), ", proc_nr(saved_proc), saved_proc->p_name);
-  kprintf("pc = %u:0x%x", (unsigned) saved_proc->p_reg.cs,
-  (unsigned) saved_proc->p_reg.pc);
+  kprintf("pc = %u:0x%x\n", (unsigned) saved_proc->p_reg.cs,
+         (unsigned) saved_proc->p_reg.pc);
   kprintf(
   "vec_nr= %d, trap_errno= 0x%lx, eip= 0x%lx, cs= 0x%x, eflags= 0x%lx\n",
        vec_nr, (unsigned long)trap_errno,
        (unsigned long)old_eip, old_cs, (unsigned long)old_eflags);
+  proc_stacktrace(saved_proc);
 
-  panic("exception in a kernel task", NO_NUM);
+  minix_panic("exception in a kernel task", saved_proc->p_endpoint);
 }
 
-#if DEBUG_STACKTRACE
 /*===========================================================================*
  *                             stacktrace                                   *
  *===========================================================================*/
-PUBLIC void stacktrace(struct proc *proc)
+PUBLIC void proc_stacktrace(struct proc *proc)
 {
        reg_t bp, v_bp, v_pc, v_hbp;
 
        v_bp = proc->p_reg.fp;
 
-       kprintf("stacktrace: ");
+       kprintf("ep %d pc 0x%lx stack ", proc->p_endpoint, proc->p_reg.pc);
+
        while(v_bp) {
-               phys_bytes p;
-               if(!(p = umap_local(proc, D, v_bp, sizeof(v_bp)))) {
-                       kprintf("(bad bp %lx)", v_bp);
+               if(data_copy(proc->p_endpoint, v_bp,
+                       SYSTEM, (vir_bytes) &v_hbp, sizeof(v_hbp)) != OK) {
+                       kprintf("(v_bp 0x%lx ?)", v_bp);
+                       break;
+               }
+               if(data_copy(proc->p_endpoint, v_bp + sizeof(v_pc),
+                       SYSTEM, (vir_bytes) &v_pc, sizeof(v_pc)) != OK) {
+                       kprintf("(v_pc 0x%lx ?)", v_pc);
                        break;
                }
-               phys_copy(p+sizeof(v_pc), vir2phys(&v_pc), sizeof(v_pc));
-               phys_copy(p, vir2phys(&v_hbp), sizeof(v_hbp));
                kprintf("0x%lx ", (unsigned long) v_pc);
                if(v_hbp != 0 && v_hbp <= v_bp) {
-                       kprintf("(bad hbp %lx)", v_hbp);
+                       kprintf("(hbp %lx ?)", v_hbp);
                        break;
                }
                v_bp = v_hbp;
        }
        kprintf("\n");
 }
-#endif
-
index 2340a830f898dd652850831c6be6aabaa0e5a60d..d1d78d5f293068c5daf622e073ecf92549935c8c 100644 (file)
 #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 */
index a506a18b3c5b8936d8e1132f8c640d8d5ce2477d..ac17eeb7f2125bffa2e3201e9d004dcfcdb1af4b 100644 (file)
@@ -55,8 +55,18 @@ struct segdesc_s {           /* segment descriptor for protected mode */
 
 typedef struct segframe {
        reg_t p_ldt_sel;    /* selector in gdt with ldt base and limit */
+       reg_t   p_cr3;          /* page table root */
        struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote */
 } segframe_t;
 
+/* Page fault event. Stored in process table. Only valid if PAGEFAULT
+ * set in p_rts_flags.
+ */
+struct pagefault
+{
+       u32_t   pf_virtual;     /* Address causing fault (CR2). */
+       u32_t   pf_flags;       /* Pagefault flags on stack. */
+};
+
 #endif /* #ifndef _I386_TYPES_H */
 
index d978c6f52ab982221c3ca1d065d3ea2cfe2e5ce5..e91bba094108f5dddf4052ea7413d5dfa442ae49 100755 (executable)
@@ -8,6 +8,7 @@
 #include <ibm/interrupt.h>
 #include <archconst.h>
 #include "../../const.h"
+#include "vm.h"
 #include "sconst.h"
 
 ! This file contains a number of assembly code utility routines needed by the
@@ -15,7 +16,7 @@
 
 .define        _monitor        ! exit Minix and return to the monitor
 .define        _int86          ! let the monitor make an 8086 interrupt call
-.define        _cp_mess        ! copies messages from source to destination
+!.define       _cp_mess        ! copies messages from source to destination
 .define        _exit           ! dummy for library routines
 .define        __exit          ! dummy for library routines
 .define        ___exit         ! dummy for library routines
 .define        _level0         ! call a function at level 0
 .define        _read_cpu_flags ! read the cpu flags
 .define        _read_cr0       ! read cr0
+.define        _write_cr3      ! write cr3
+.define _last_cr3
 .define        _write_cr0      ! write a value in cr0
-.define        _write_cr3      ! write a value in cr3 (root of the page table)
+
+.define        _kernel_cr3     
 
 ! The routines only guarantee to preserve the registers the C compiler
 ! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
@@ -162,42 +166,42 @@ csinit:   mov     eax, DS_SELECTOR
 ! Note that the message size, "Msize" is in DWORDS (not bytes) and must be set
 ! correctly.  Changing the definition of message in the type file and not
 ! changing it here will lead to total disaster.
-
-CM_ARGS        =       4 + 4 + 4 + 4 + 4       ! 4 + 4 + 4 + 4 + 4
-!              es  ds edi esi eip      proc scl sof dcl dof
-
-       .align  16
-_cp_mess:
-       cld
-       push    esi
-       push    edi
-       push    ds
-       push    es
-
-       mov     eax, FLAT_DS_SELECTOR
-       mov     ds, ax
-       mov     es, ax
-
-       mov     esi, CM_ARGS+4(esp)             ! src clicks
-       shl     esi, CLICK_SHIFT
-       add     esi, CM_ARGS+4+4(esp)           ! src offset
-       mov     edi, CM_ARGS+4+4+4(esp)         ! dst clicks
-       shl     edi, CLICK_SHIFT
-       add     edi, CM_ARGS+4+4+4+4(esp)       ! dst offset
-
-       mov     eax, CM_ARGS(esp)       ! process number of sender
-       stos                            ! copy number of sender to dest message
-       add     esi, 4                  ! do not copy first word
-       mov     ecx, Msize - 1          ! remember, first word does not count
-       rep
-       movs                            ! copy the message
-
-       pop     es
-       pop     ds
-       pop     edi
-       pop     esi
-       ret                             ! that is all folks!
-
+!
+!CM_ARGS       =       4 + 4 + 4 + 4 + 4       ! 4 + 4 + 4 + 4 + 4
+!!             es  ds edi esi eip      proc scl sof dcl dof
+!
+!      .align  16
+!_cp_mess:
+!      cld
+!      push    esi
+!      push    edi
+!      push    ds
+!      push    es
+!
+!      mov     eax, FLAT_DS_SELECTOR
+!      mov     ds, ax
+!      mov     es, ax
+!
+!      mov     esi, CM_ARGS+4(esp)             ! src clicks
+!      shl     esi, CLICK_SHIFT
+!      add     esi, CM_ARGS+4+4(esp)           ! src offset
+!      mov     edi, CM_ARGS+4+4+4(esp)         ! dst clicks
+!      shl     edi, CLICK_SHIFT
+!      add     edi, CM_ARGS+4+4+4+4(esp)       ! dst offset
+!
+!      mov     eax, CM_ARGS(esp)       ! process number of sender
+!      stos                            ! copy number of sender to dest message
+!      add     esi, 4                  ! do not copy first word
+!      mov     ecx, Msize - 1          ! remember, first word does not count
+!      rep
+!      movs                            ! copy the message
+!
+!      pop     es
+!      pop     ds
+!      pop     edi
+!      pop     esi
+!      ret                             ! that is all folks!
+!
 
 !*===========================================================================*
 !*                             exit                                         *
@@ -229,6 +233,9 @@ _phys_insw:
        cld
        push    edi
        push    es
+
+       LOADKERNELCR3
+
        mov     ecx, FLAT_DS_SELECTOR
        mov     es, cx
        mov     edx, 8(ebp)             ! port to read from
@@ -254,6 +261,9 @@ _phys_insb:
        cld
        push    edi
        push    es
+
+       LOADKERNELCR3
+
        mov     ecx, FLAT_DS_SELECTOR
        mov     es, cx
        mov     edx, 8(ebp)             ! port to read from
@@ -280,6 +290,9 @@ _phys_outsw:
        cld
        push    esi
        push    ds
+
+       LOADKERNELCR3
+
        mov     ecx, FLAT_DS_SELECTOR
        mov     ds, cx
        mov     edx, 8(ebp)             ! port to write to
@@ -306,6 +319,9 @@ _phys_outsb:
        cld
        push    esi
        push    ds
+
+       LOADKERNELCR3
+
        mov     ecx, FLAT_DS_SELECTOR
        mov     ds, cx
        mov     edx, 8(ebp)             ! port to write to
@@ -412,6 +428,8 @@ _phys_copy:
        push    edi
        push    es
 
+       LOADKERNELCR3
+
        mov     eax, FLAT_DS_SELECTOR
        mov     es, ax
 
@@ -456,6 +474,9 @@ _phys_memset:
        push    esi
        push    ebx
        push    ds
+
+       LOADKERNELCR3
+
        mov     esi, 8(ebp)
        mov     eax, 16(ebp)
        mov     ebx, FLAT_DS_SELECTOR
@@ -485,6 +506,7 @@ fill_done:
        pop     esi
        pop     ebp
        ret
+       
 
 !*===========================================================================*
 !*                             mem_rdw                                      *
@@ -585,14 +607,13 @@ _write_cr0:
        ret
 
 !*===========================================================================*
-!*                           write_cr3                                      *
+!*                             write_cr3                               *
 !*===========================================================================*
 ! PUBLIC void write_cr3(unsigned long value);
 _write_cr3:
-       push    ebp
-       mov     ebp, esp
-       mov     eax, 8(ebp)
-       mov     cr3, eax
-       pop     ebp
+       push    ebp
+       mov     ebp, esp
+       LOADCR3WITHEAX(0x22, 8(ebp))
+       pop     ebp
        ret
 
index 53a2aea38dbebb94402d66103d61829ad9ba9880..e020088681584c7b5d062243a718cbc67feb1dda 100644 (file)
@@ -1,20 +1,26 @@
 
 #include "../../kernel.h"
 #include "../../proc.h"
+#include "../../vm.h"
 
 #include <minix/type.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
 #include <string.h>
 
-#include <sys/vm.h>
+#include <sys/vm_i386.h>
 
 #include <minix/portio.h>
 
 #include "proto.h"
+#include "../../proto.h"
+#include "../../debug.h"
 
 /* VM functions and data. */
-
-PRIVATE int vm_needs_init= 1;
 PRIVATE u32_t vm_cr3;
+PUBLIC u32_t kernel_cr3;
+extern u32_t cswitch;
+u32_t last_cr3 = 0;
 
 FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value)    );
 FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr)                        );
@@ -22,6 +28,13 @@ FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value)                   );
 FORWARD _PROTOTYPE( void set_cr3, (void)                               );
 FORWARD _PROTOTYPE( void vm_enable_paging, (void)                      );
 
+#if DEBUG_VMASSERT
+#define vmassert(t) { \
+       if(!(t)) { minix_panic("vm: assert " #t " failed\n", __LINE__); } }
+#else
+#define vmassert(t) { }
+#endif
+
 /* *** Internal VM Functions *** */
 
 PUBLIC void vm_init(void)
@@ -31,31 +44,35 @@ PUBLIC void vm_init(void)
        phys_bytes vm_dir_base, vm_pt_base, phys_mem;
        u32_t entry;
        unsigned pages;
+       struct proc* rp;
 
        if (!vm_size)
-               panic("i386_vm_init: no space for page tables", NO_NUM);
+               minix_panic("i386_vm_init: no space for page tables", NO_NUM);
+
+       if(vm_running)
+               return;
 
        /* Align page directory */
-       o= (vm_base % PAGE_SIZE);
+       o= (vm_base % I386_PAGE_SIZE);
        if (o != 0)
-               o= PAGE_SIZE-o;
+               o= I386_PAGE_SIZE-o;
        vm_dir_base= vm_base+o;
 
        /* Page tables start after the page directory */
-       vm_pt_base= vm_dir_base+PAGE_SIZE;
+       vm_pt_base= vm_dir_base+I386_PAGE_SIZE;
 
        pt_size= (vm_base+vm_size)-vm_pt_base;
-       pt_size -= (pt_size % PAGE_SIZE);
+       pt_size -= (pt_size % I386_PAGE_SIZE);
 
        /* Compute the number of pages based on vm_mem_high */
-       pages= (vm_mem_high-1)/PAGE_SIZE + 1;
+       pages= (vm_mem_high-1)/I386_PAGE_SIZE + 1;
 
        if (pages * I386_VM_PT_ENT_SIZE > pt_size)
-               panic("i386_vm_init: page table too small", NO_NUM);
+               minix_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;
+               phys_mem= p*I386_PAGE_SIZE;
                entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
                        I386_VM_PRESENT;
                if (phys_mem >= vm_mem_high)
@@ -65,15 +82,33 @@ PUBLIC void vm_init(void)
 
        for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
        {
-               phys_mem= vm_pt_base + p*PAGE_SIZE;
+               phys_mem= vm_pt_base + p*I386_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);
        }
+
+       /* Set this cr3 in all currently running processes for
+        * future context switches.
+        */
+       for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
+               u32_t mycr3;
+               if(isemptyp(rp)) continue;
+               rp->p_seg.p_cr3 = vm_dir_base;
+       }
+
+       kernel_cr3 = vm_dir_base;
+
+       /* Set this cr3 now (not active until paging enabled). */
        vm_set_cr3(vm_dir_base);
+
+       /* Actually enable paging (activating cr3 load above). */
        level0(vm_enable_paging);
+
+       /* Don't do this init in the future. */
+       vm_running = 1;
 }
 
 PRIVATE void phys_put32(addr, value)
@@ -113,50 +148,6 @@ PRIVATE void vm_enable_paging(void)
        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)
@@ -188,6 +179,10 @@ PUBLIC phys_bytes umap_remote(struct proc* rp, int seg,
 /* Calculate the physical memory address for a given virtual address. */
   struct far_mem *fm;
 
+#if 0
+  if(rp->p_misc_flags & MF_FULLVM) return 0;
+#endif
+
   if (bytes <= 0) return( (phys_bytes) 0);
   if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
 
@@ -212,6 +207,9 @@ vir_bytes bytes;                /* # of bytes to be copied */
   phys_bytes pa;                /* intermediate variables as phys_bytes */
   phys_bytes seg_base;
 
+  if(seg != T && seg != D && seg != S)
+       minix_panic("umap_local: wrong seg", seg);
+
   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 */
@@ -232,3 +230,569 @@ vir_bytes bytes;                /* # of bytes to be copied */
   return(seg_base + pa);
 }
 
+/*===========================================================================*
+ *                              umap_virtual                                 *
+ *===========================================================================*/
+PUBLIC phys_bytes umap_virtual(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 */
+{
+       vir_bytes linear;
+       u32_t phys = 0;
+
+       if(seg == MEM_GRANT) {
+               phys = umap_grant(rp, vir_addr, bytes);
+       } else {
+               if(!(linear = umap_local(rp, seg, vir_addr, bytes))) {
+                       kprintf("SYSTEM:umap_virtual: umap_local failed\n");
+                       phys = 0;
+               } else {
+                       if(vm_lookup(rp, linear, &phys, NULL) != OK) {
+                               kprintf("SYSTEM:umap_virtual: vm_lookup of %s: seg 0x%lx: 0x%lx failed\n", rp->p_name, seg, vir_addr);
+                               phys = 0;
+                       }
+                       if(phys == 0)
+                               minix_panic("vm_lookup returned phys", phys);
+               }
+       }
+
+       if(phys == 0) {
+               kprintf("SYSTEM:umap_virtual: lookup failed\n");
+               return 0;
+       }
+
+       /* Now make sure addresses are contiguous in physical memory
+        * so that the umap makes sense.
+        */
+       if(bytes > 0 && !vm_contiguous(rp, linear, bytes)) {
+               kprintf("umap_virtual: %s: %d at 0x%lx (vir 0x%lx) not contiguous\n",
+                       rp->p_name, bytes, linear, vir_addr);
+               return 0;
+       }
+
+       /* phys must be larger than 0 (or the caller will think the call
+        * failed), and address must not cross a page boundary.
+        */
+       vmassert(phys);
+
+       return phys;
+}
+
+/*===========================================================================*
+ *                              vm_lookup                                    *
+ *===========================================================================*/
+PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical, u32_t *ptent)
+{
+       u32_t *root, *pt;
+       int pde, pte;
+       u32_t pde_v, pte_v;
+
+       vmassert(proc);
+       vmassert(physical);
+       vmassert(!(proc->p_rts_flags & SLOT_FREE));
+
+       /* Retrieve page directory entry. */
+       root = (u32_t *) proc->p_seg.p_cr3;
+       vmassert(!((u32_t) root % I386_PAGE_SIZE));
+       pde = I386_VM_PDE(virtual);
+       vmassert(pde >= 0 && pde < I386_VM_DIR_ENTRIES);
+       pde_v = phys_get32((u32_t) (root + pde));
+       if(!(pde_v & I386_VM_PRESENT)) {
+#if 0
+               kprintf("vm_lookup: %d:%s:0x%lx: cr3 0x%lx: pde %d not present\n",
+                       proc->p_endpoint, proc->p_name, virtual, root, pde);
+               kprintf("kernel stack: ");
+               util_stacktrace();
+#endif
+               return EFAULT;
+       }
+
+       /* Retrieve page table entry. */
+       pt = (u32_t *) I386_VM_PFA(pde_v);
+       vmassert(!((u32_t) pt % I386_PAGE_SIZE));
+       pte = I386_VM_PTE(virtual);
+       vmassert(pte >= 0 && pte < I386_VM_PT_ENTRIES);
+       pte_v = phys_get32((u32_t) (pt + pte));
+       if(!(pte_v & I386_VM_PRESENT)) {
+#if 0
+               kprintf("vm_lookup: %d:%s:0x%lx: cr3 %lx: pde %d: pte %d not present\n",
+                       proc->p_endpoint, proc->p_name, virtual, root, pde, pte);
+               kprintf("kernel stack: ");
+               util_stacktrace();
+#endif
+               return EFAULT;
+       }
+
+       if(ptent) *ptent = pte_v;
+
+       /* Actual address now known; retrieve it and add page offset. */
+       *physical = I386_VM_PFA(pte_v);
+       *physical += virtual % I386_PAGE_SIZE;
+
+       return OK;
+}
+
+/* From virtual address v in process p,
+ * lookup physical address and assign it to d.
+ * If p is NULL, assume it's already a physical address.
+ */
+#define LOOKUP(d, p, v, flagsp) {      \
+       int r;                          \
+       if(!(p)) { (d) = (v); }         \
+       else {                          \
+               if((r=vm_lookup((p), (v), &(d), flagsp)) != OK) { \
+                       kprintf("vm_copy: lookup failed of 0x%lx in %d (%s)\n"\
+                               "kernel stacktrace: ", (v), (p)->p_endpoint, \
+                                       (p)->p_name);           \
+                       util_stacktrace();                      \
+                       return r;                               \
+               } } }
+
+/*===========================================================================*
+ *                              vm_copy                                      *
+ *===========================================================================*/
+int vm_copy(vir_bytes src, struct proc *srcproc,
+        vir_bytes dst, struct proc *dstproc, phys_bytes bytes)
+{
+#define WRAPS(v) (ULONG_MAX - (v) <= bytes)
+
+       if(WRAPS(src) || WRAPS(dst))
+               minix_panic("vm_copy: linear address wraps", NO_NUM);
+
+       while(bytes > 0) {
+               u32_t n, flags;
+               phys_bytes p_src, p_dst;
+#define PAGEREMAIN(v) (I386_PAGE_SIZE - ((v) % I386_PAGE_SIZE))
+
+               /* We can copy this number of bytes without
+                * crossing a page boundary, but don't copy more
+                * than asked.
+                */
+               n = MIN(PAGEREMAIN(src), PAGEREMAIN(dst));
+               n = MIN(n, bytes);
+               vmassert(n > 0);
+               vmassert(n <= I386_PAGE_SIZE);
+
+               /* Convert both virtual addresses to physical and do
+                * copy.
+                */
+               LOOKUP(p_src, srcproc, src, NULL);
+               LOOKUP(p_dst, dstproc, dst, &flags);
+               if(!(flags & I386_VM_WRITE)) {
+                       kprintf("vm_copy: copying to nonwritable page\n");
+                       kprintf("kernel stack: ");
+                       util_stacktrace();
+                       return EFAULT;
+               }
+               phys_copy(p_src, p_dst, n);
+
+               /* Book number of bytes copied. */
+               vmassert(bytes >= n);
+               bytes -= n;
+               src += n;
+               dst += n;
+       }
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                              vm_contiguous                                *
+ *===========================================================================*/
+PUBLIC int vm_contiguous(struct proc *targetproc, u32_t vir_buf, size_t bytes)
+{
+       int first = 1, r, boundaries = 0;
+       u32_t prev_phys, po;
+       u32_t prev_vir;
+
+       vmassert(targetproc);
+       vmassert(bytes > 0);
+       vmassert(vm_running);
+
+       /* Start and end at page boundary to make logic simpler. */
+       po = vir_buf % I386_PAGE_SIZE;
+       if(po > 0) {
+               bytes += po;
+               vir_buf -= po;
+       }
+       po = (vir_buf + bytes) % I386_PAGE_SIZE;
+       if(po > 0)
+               bytes += I386_PAGE_SIZE - po;
+
+       /* Keep going as long as we cross a page boundary. */
+       while(bytes > 0) {
+               u32_t phys;
+
+               if((r=vm_lookup(targetproc, vir_buf, &phys, NULL)) != OK) {
+                       kprintf("vm_contiguous: vm_lookup failed, %d\n", r);
+                       kprintf("kernel stack: ");
+                       util_stacktrace();
+                       return 0;
+               }
+
+               if(!first) {
+                       if(prev_phys+I386_PAGE_SIZE != phys) {
+                               kprintf("vm_contiguous: no (0x%lx, 0x%lx)\n",
+                                       prev_phys, phys);
+                               kprintf("kernel stack: ");
+                               util_stacktrace();
+                               return 0;
+                       }
+               }
+
+               first = 0;
+
+               prev_phys = phys;
+               prev_vir = vir_buf;
+               vir_buf += I386_PAGE_SIZE;
+               bytes -= I386_PAGE_SIZE;
+               boundaries++;
+       }
+
+       if(verbose_vm)
+               kprintf("vm_contiguous: yes (%d boundaries tested)\n",
+                       boundaries);
+
+       return 1;
+}
+
+int vm_checkrange_verbose = 0;
+
+/*===========================================================================*
+ *                              vm_checkrange                                *
+ *===========================================================================*/
+PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
+       vir_bytes vir, vir_bytes bytes, int wrfl, int checkonly)
+{
+       u32_t flags, po, v;
+       int r;
+
+       vmassert(vm_running);
+
+       /* If caller has had a reply to this request, return it. */
+       if(RTS_ISSET(caller, VMREQUEST)) {
+               if(caller->p_vmrequest.who == target->p_endpoint) {
+                       if(caller->p_vmrequest.vmresult == VMSUSPEND)
+                               minix_panic("check sees VMSUSPEND?", NO_NUM);
+                       RTS_LOCK_UNSET(caller, VMREQUEST);
+#if 0
+                       kprintf("SYSTEM: vm_checkrange: returning vmresult %d\n",
+                               caller->p_vmrequest.vmresult);
+#endif
+                       return caller->p_vmrequest.vmresult;
+               } else {
+#if 0
+                       kprintf("SYSTEM: vm_checkrange: caller has a request for %d, "
+                               "but our target is %d\n",
+                               caller->p_vmrequest.who, target->p_endpoint);
+#endif
+               }
+       }
+
+       po = vir % I386_PAGE_SIZE;
+       if(po > 0) {
+               vir -= po;
+               bytes += po;
+       }
+
+       vmassert(target);
+       vmassert(bytes > 0);
+
+       for(v = vir; v < vir + bytes;  v+= I386_PAGE_SIZE) {
+               u32_t phys;
+
+               /* If page exists and it's writable if desired, we're OK
+                * for this page.
+                */
+               if(vm_lookup(target, v, &phys, &flags) == OK &&
+                       !(wrfl && !(flags & I386_VM_WRITE))) {
+                       if(vm_checkrange_verbose) {
+#if 0
+                               kprintf("SYSTEM: checkrange:%s:%d: 0x%lx: write 0x%lx, flags 0x%lx, phys 0x%lx, OK\n",
+                               target->p_name, target->p_endpoint, v, wrfl, flags, phys);
+#endif
+                       }
+                       continue;
+               }
+
+               if(vm_checkrange_verbose) {
+                       kprintf("SYSTEM: checkrange:%s:%d: 0x%lx: write 0x%lx, flags 0x%lx, phys 0x%lx, NOT OK\n",
+                       target->p_name, target->p_endpoint, v, wrfl, flags, phys);
+               }
+
+               if(checkonly)
+                       return VMSUSPEND;
+
+               /* This range is not OK for this process. Set parameters
+                * of the request and notify VM about the pending request.
+                */
+               if(RTS_ISSET(caller, VMREQUEST))
+                       minix_panic("VMREQUEST already set", caller->p_endpoint);
+               RTS_LOCK_SET(caller, VMREQUEST);
+
+               /* Set parameters in caller. */
+               caller->p_vmrequest.writeflag = wrfl;
+               caller->p_vmrequest.start = vir;
+               caller->p_vmrequest.length = bytes;
+               caller->p_vmrequest.who = target->p_endpoint;
+
+               /* Set caller in target. */
+               target->p_vmrequest.requestor = caller;
+
+               /* Connect caller on vmrequest wait queue. */
+               caller->p_vmrequest.nextrequestor = vmrequest;
+               vmrequest = caller;
+               soft_notify(VM_PROC_NR);
+
+#if 0
+               kprintf("SYSTEM: vm_checkrange: range bad for "
+                       "target %s:0x%lx-0x%lx, caller %s\n",
+                               target->p_name, vir, vir+bytes, caller->p_name);
+
+               kprintf("vm_checkrange kernel trace: ");
+               util_stacktrace();
+               kprintf("target trace: ");
+               proc_stacktrace(target);
+#endif
+
+               if(target->p_endpoint == VM_PROC_NR) {
+                       kprintf("caller trace: ");
+                       proc_stacktrace(caller);
+                       kprintf("target trace: ");
+                       proc_stacktrace(target);
+                       minix_panic("VM ranges should be OK", NO_NUM);
+               }
+
+               return VMSUSPEND;
+       }
+
+       return OK;
+}
+
+char *flagstr(u32_t e, int dir)
+{
+       static char str[80];
+       strcpy(str, "");
+#define FLAG(v) do { if(e & (v)) { strcat(str, #v " "); } } while(0)
+       FLAG(I386_VM_PRESENT);
+       FLAG(I386_VM_WRITE);
+       FLAG(I386_VM_USER);
+       FLAG(I386_VM_PWT);
+       FLAG(I386_VM_PCD);
+       if(dir)
+               FLAG(I386_VM_BIGPAGE);  /* Page directory entry only */
+       else
+               FLAG(I386_VM_DIRTY);    /* Page table entry only */
+
+       return str;
+}
+
+void vm_pt_print(u32_t *pagetable, u32_t v)
+{
+       int pte, l = 0;
+       int col = 0;
+
+       vmassert(!((u32_t) pagetable % I386_PAGE_SIZE));
+
+       for(pte = 0; pte < I386_VM_PT_ENTRIES; pte++) {
+               u32_t pte_v, pfa;
+               pte_v = phys_get32((u32_t) (pagetable + pte));
+               if(!(pte_v & I386_VM_PRESENT))
+                       continue;
+               pfa = I386_VM_PFA(pte_v);
+               kprintf("%4d:%08lx:%08lx ",
+                       pte, v + I386_PAGE_SIZE*pte, pfa);
+               col++;
+               if(col == 3) { kprintf("\n"); col = 0; }
+       }
+       if(col > 0) kprintf("\n");
+
+       return;
+}
+
+/*===========================================================================*
+ *                              vm_print                                     *
+ *===========================================================================*/
+void vm_print(u32_t *root)
+{
+       int pde;
+
+       vmassert(!((u32_t) root % I386_PAGE_SIZE));
+
+       for(pde = 0; pde < I386_VM_DIR_ENTRIES; pde++) {
+               u32_t pde_v;
+               u32_t *pte_a;
+               pde_v = phys_get32((u32_t) (root + pde));
+               if(!(pde_v & I386_VM_PRESENT))
+                       continue;
+               pte_a = (u32_t *) I386_VM_PFA(pde_v);
+               kprintf("%4d: pt %08lx %s\n",
+                       pde, pte_a, flagstr(pde_v, 1));
+               vm_pt_print(pte_a, pde * I386_VM_PT_ENTRIES * I386_PAGE_SIZE);
+       }
+
+
+       return;
+}
+
+/*===========================================================================*
+ *                             virtual_copy_f                               *
+ *===========================================================================*/
+PUBLIC int virtual_copy_f(src_addr, dst_addr, bytes, vmcheck)
+struct vir_addr *src_addr;     /* source virtual address */
+struct vir_addr *dst_addr;     /* destination virtual address */
+vir_bytes bytes;               /* # of bytes to copy  */
+int vmcheck;                   /* if nonzero, can return VMSUSPEND */
+{
+/* Copy bytes from virtual address src_addr to virtual address dst_addr. 
+ * Virtual addresses can be in ABS, LOCAL_SEG, REMOTE_SEG, or BIOS_SEG.
+ */
+  struct vir_addr *vir_addr[2];        /* virtual source and destination address */
+  phys_bytes phys_addr[2];     /* absolute source and destination */ 
+  int seg_index;
+  int i, r;
+  struct proc *procs[2];
+
+  /* Check copy count. */
+  if (bytes <= 0) return(EDOM);
+
+  /* Do some more checks and map virtual addresses to physical addresses. */
+  vir_addr[_SRC_] = src_addr;
+  vir_addr[_DST_] = dst_addr;
+
+  for (i=_SRC_; i<=_DST_; i++) {
+       int proc_nr, type;
+       struct proc *p;
+
+       type = vir_addr[i]->segment & SEGMENT_TYPE;
+       if((type != PHYS_SEG && type != BIOS_SEG) &&
+          isokendpt(vir_addr[i]->proc_nr_e, &proc_nr))
+               p = proc_addr(proc_nr);
+       else 
+               p = NULL;
+
+       procs[i] = p;
+
+      /* Get physical address. */
+      switch(type) {
+      case LOCAL_SEG:
+      case LOCAL_VM_SEG:
+         if(!p) return EDEADSRCDST;
+          seg_index = vir_addr[i]->segment & SEGMENT_INDEX;
+         if(type == LOCAL_SEG)
+                 phys_addr[i] = umap_local(p, seg_index, vir_addr[i]->offset,
+                       bytes);
+         else
+               phys_addr[i] = umap_virtual(p, seg_index, vir_addr[i]->offset,
+                       bytes);
+         if(phys_addr[i] == 0) {
+               kprintf("virtual_copy: map 0x%x failed for %s seg %d, "
+                       "offset %lx, len %d, i %d\n",
+                       type, p->p_name, seg_index, vir_addr[i]->offset,
+                       bytes, i);
+         }
+          break;
+      case REMOTE_SEG:
+         if(!p) return EDEADSRCDST;
+          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:
+          phys_addr[i] = umap_bios(vir_addr[i]->offset, bytes );
+          break;
+#endif
+      case PHYS_SEG:
+          phys_addr[i] = vir_addr[i]->offset;
+          break;
+      case GRANT_SEG:
+         phys_addr[i] = umap_grant(p, vir_addr[i]->offset, bytes);
+         break;
+      default:
+         kprintf("virtual_copy: strange type 0x%x\n", type);
+          return(EINVAL);
+      }
+
+      /* Check if mapping succeeded. */
+      if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG)  {
+      kprintf("virtual_copy EFAULT\n");
+          return(EFAULT);
+      }
+  }
+
+  if(vmcheck && procs[_SRC_])
+       CHECKRANGE_OR_SUSPEND(procs[_SRC_], phys_addr[_SRC_], bytes, 0);
+  if(vmcheck && procs[_DST_])
+       CHECKRANGE_OR_SUSPEND(procs[_DST_], phys_addr[_DST_], bytes, 1);
+
+  /* Now copy bytes between physical addresseses. */
+  if(!vm_running || (procs[_SRC_] == NULL && procs[_DST_] == NULL)) {
+       /* Without vm, address ranges actually are physical. */
+       phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes);
+       r = OK;
+  } else {
+       /* With vm, addresses need further interpretation. */
+       r = vm_copy(phys_addr[_SRC_], procs[_SRC_], 
+               phys_addr[_DST_], procs[_DST_], (phys_bytes) bytes);
+       if(r != OK) {
+               kprintf("vm_copy: %lx to %lx failed\n",
+                       phys_addr[_SRC_],phys_addr[_DST_]);
+       }
+  }
+
+  return(r);
+}
+
+/*===========================================================================*
+ *                             data_copy                                    *
+ *===========================================================================*/
+PUBLIC int data_copy(
+       endpoint_t from_proc, vir_bytes from_addr,
+       endpoint_t to_proc, vir_bytes to_addr,
+       size_t bytes)
+{
+  struct vir_addr src, dst;
+
+  src.segment = dst.segment = D;
+  src.offset = from_addr;
+  dst.offset = to_addr;
+  src.proc_nr_e = from_proc;
+  dst.proc_nr_e = to_proc;
+
+  return virtual_copy(&src, &dst, bytes);
+}
+
+/*===========================================================================*
+ *                             arch_pre_exec                                *
+ *===========================================================================*/
+PUBLIC int arch_pre_exec(struct proc *pr, u32_t ip, u32_t sp)
+{
+/* wipe extra LDT entries, set program counter, and stack pointer. */
+       memset(pr->p_seg.p_ldt + EXTRA_LDT_INDEX, 0,
+               sizeof(pr->p_seg.p_ldt[0]) * (LDT_SIZE - EXTRA_LDT_INDEX));
+       pr->p_reg.pc = ip;
+       pr->p_reg.sp = sp;
+}
+
+/*===========================================================================*
+ *                             arch_umap                                    *
+ *===========================================================================*/
+PUBLIC int arch_umap(struct proc *pr, vir_bytes offset, vir_bytes count,
+       int seg, phys_bytes *addr)
+{
+       switch(seg) {
+               case BIOS_SEG:
+                       *addr = umap_bios(offset, count);
+                       return OK;
+       }
+
+       /* This must be EINVAL; the umap fallback function in
+        * lib/syslib/alloc_util.c depends on it to detect an
+        * older kernel (as opposed to mapping error).
+        */
+       return EINVAL;
+}
+
+
index c6f94f14d0daf8d5d68cc06b1001dd90b460d321..15a5cd62fead99c9d477253a9bc22be39ef2bc19 100755 (executable)
@@ -1,4 +1,4 @@
-# 
+#
 ! This file, mpx386.s, is included by mpx.s when Minix is compiled for 
 ! 32-bit Intel CPUs. The alternative mpx88.s is compiled for 16-bit CPUs.
 
@@ -58,6 +58,7 @@ begbss:
 #include <ibm/interrupt.h>
 #include <archconst.h>
 #include "../../const.h"
+#include "vm.h"
 #include "sconst.h"
 
 /* Selected 386 tss offsets. */
@@ -71,6 +72,13 @@ begbss:
 
 .define        _restart
 .define        save
+.define        _kernel_cr3
+.define        _pagefault_cr2
+.define _pagefault_count
+
+.define errexception
+.define exception1
+.define exception
 
 .define        _divide_error
 .define        _single_step_exception
@@ -88,6 +96,9 @@ begbss:
 .define        _general_protection
 .define        _page_fault
 .define        _copr_error
+.define        _params_size
+.define _params_offset
+.define _mon_ds
 
 .define        _hwint00        ! handlers for hardware interrupts
 .define        _hwint01
@@ -173,6 +184,11 @@ copygdt:
        mov     ss, ax
        mov     esp, k_stktop   ! set sp to point to the top of kernel stack
 
+! Save boot parameters into these global variables for i386 code
+       mov     (_params_size), edx
+       mov     (_params_offset), ebx
+       mov     (_mon_ds), SS_SELECTOR
+
 ! Call C startup code to set up a proper environment to run main().
        push    edx
        push    ebx
@@ -216,6 +232,7 @@ csinit:
 #define hwint_master(irq)      \
        call    save                    /* save interrupted process state */;\
        push    (_irq_handlers+4*irq)   /* irq_handlers[irq]              */;\
+       LOADCR3WITHEAX(irq, (_kernel_cr3))      /* switch to kernel page table    */;\
        call    _intr_handle            /* intr_handle(irq_handlers[irq]) */;\
        pop     ecx                                                         ;\
        cmp     (_irq_actids+4*irq), 0  /* interrupt still active?        */;\
@@ -267,6 +284,7 @@ _hwint07:           ! Interrupt routine for irq 7 (printer)
 #define hwint_slave(irq)       \
        call    save                    /* save interrupted process state */;\
        push    (_irq_handlers+4*irq)   /* irq_handlers[irq]              */;\
+       LOADCR3WITHEAX(irq, (_kernel_cr3))      /* switch to kernel page table    */;\
        call    _intr_handle            /* intr_handle(irq_handlers[irq]) */;\
        pop     ecx                                                         ;\
        cmp     (_irq_actids+4*irq), 0  /* interrupt still active?        */;\
@@ -358,6 +376,7 @@ _p_s_call:
     o16        push    es
     o16        push    fs
     o16        push    gs
+
        mov     si, ss          ! ss is kernel data segment
        mov     ds, si          ! load rest of kernel segments
        mov     es, si          ! kernel does not use fs, gs
@@ -371,6 +390,9 @@ _p_s_call:
        push    ebx             ! pointer to user message
        push    eax             ! source / destination
        push    ecx             ! call number (ipc primitive to use)
+
+!      LOADCR3WITHEAX(0x20, (_kernel_cr3))
+
        call    _sys_call       ! sys_call(call_nr, src_dst, m_ptr, bit_map)
                                ! caller is now explicitly in proc_ptr
        mov     AXREG(esi), eax ! sys_call MUST PRESERVE si
@@ -391,6 +413,7 @@ _restart:
        mov     (_next_ptr), 0
 0:     mov     esp, (_proc_ptr)        ! will assume P_STACKBASE == 0
        lldt    P_LDT_SEL(esp)          ! enable process' segment descriptors 
+       LOADCR3WITHEAX(0x21, P_CR3(esp))        ! switch to process page table
        lea     eax, P_STACKTOP(esp)    ! arrange for next interrupt
        mov     (_tss+TSS3_S_SP0), eax  ! to save state in process table
 restart1:
@@ -464,6 +487,11 @@ _general_protection:
 
 _page_fault:
        push    PAGE_FAULT_VECTOR
+       push    eax
+       mov     eax, cr2
+sseg   mov     (_pagefault_cr2), eax
+sseg   inc     (_pagefault_count)
+       pop     eax
        jmp     errexception
 
 _copr_error:
@@ -492,12 +520,16 @@ errexception:
  sseg  pop     (trap_errno)
 exception1:                            ! Common for all exceptions.
        push    eax                     ! eax is scratch register
+
        mov     eax, 0+4(esp)           ! old eip
  sseg  mov     (old_eip), eax
        movzx   eax, 4+4(esp)           ! old cs
  sseg  mov     (old_cs), eax
        mov     eax, 8+4(esp)           ! old eflags
  sseg  mov     (old_eflags), eax
+
+       LOADCR3WITHEAX(0x24, (_kernel_cr3))
+
        pop     eax
        call    save
        push    (old_eflags)
@@ -517,6 +549,15 @@ _level0_call:
        call    save
        jmp     (_level0_func)
 
+!*===========================================================================*
+!*                             load_kernel_cr3                              *
+!*===========================================================================*
+.align 16
+_load_kernel_cr3:
+       mov     eax, (_kernel_cr3)
+       mov     cr3, eax
+       ret
+
 !*===========================================================================*
 !*                             data                                         *
 !*===========================================================================*
@@ -533,3 +574,4 @@ k_stktop:                   ! top of kernel stack
        .comm   old_eip, 4
        .comm   old_cs, 4
        .comm   old_eflags, 4
+
index d303ab59b486d63550a17b34213c69612c6c2e62..a360113eb5d3c98b63c3c5c907e8cf43a3a8aef5 100755 (executable)
@@ -307,7 +307,10 @@ PUBLIC void alloc_segments(register struct proc *rp)
           code_bytes = data_bytes;     /* common I&D, poor protect */
       else
           code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
-      privilege = (iskernelp(rp)) ? TASK_PRIVILEGE : USER_PRIVILEGE;
+      if( (iskernelp(rp)))
+       privilege = TASK_PRIVILEGE;
+      else
+       privilege = USER_PRIVILEGE;
       init_codeseg(&rp->p_seg.p_ldt[CS_LDT_INDEX],
           (phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT,
           code_bytes, privilege);
index 0530bf35a47f605665fbb6baec881bca7228f0b8..de8de011ebb8f880bbca93fefef93d18067ff304 100644 (file)
@@ -44,10 +44,16 @@ _PROTOTYPE( void trp, (void) );
 _PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) ); 
 _PROTOTYPE( void level0_call, (void) );
 
+/* memory.c */
+_PROTOTYPE( void vir_insb, (u16_t port, struct proc *proc, u32_t vir, size_t count));
+_PROTOTYPE( void vir_outsb, (u16_t port, struct proc *proc, u32_t vir, size_t count));
+_PROTOTYPE( void vir_insw, (u16_t port, struct proc *proc, u32_t vir, size_t count));
+_PROTOTYPE( void vir_outsw, (u16_t port, struct proc *proc, u32_t vir, size_t count));
+
+
 /* exception.c */
 _PROTOTYPE( void exception, (unsigned vec_nr, u32_t trap_errno,
        u32_t old_eip, U16_t old_cs, u32_t old_eflags)                  );
-_PROTOTYPE( void stacktrace, (struct proc *proc)                       );
 
 /* klib386.s */
 _PROTOTYPE( void level0, (void (*func)(void))                           );
@@ -62,6 +68,7 @@ _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 i386_invlpg, (U32_t addr) );
 
 /* protect.c */
 _PROTOTYPE( void prot_init, (void)                                             );
index 28e7b05177f5efb82cac02caff7b5b85619892d2..34254f03a55c0b4a1c19916db29f892515d38314 100755 (executable)
@@ -23,5 +23,6 @@ SPREG         =       PSWREG + W
 SSREG          =       SPREG + W
 P_STACKTOP     =       SSREG + W
 P_LDT_SEL      =       P_STACKTOP
-P_LDT          =       P_LDT_SEL + W
+P_CR3          =       P_LDT_SEL + W
+P_LDT          =       P_CR3 + W
 Msize          =       9               ! size of a message in 32-bit words
index 6b7e100ca356d61bb719da3f2e6fe8d4e17bdf3a..aa0aef6488a88fda17192ce134b42e378effa9ef 100644 (file)
@@ -3,10 +3,14 @@
 #include "../../kernel.h"
 
 #include <unistd.h>
+#include <ctype.h>
+#include <string.h>
 #include <ibm/cmos.h>
 #include <ibm/bios.h>
 #include <minix/portio.h>
 #include <minix/u64.h>
+#include <minix/sysutil.h>
+#include <a.out.h>
 
 #include "proto.h"
 #include "../../proc.h"
@@ -31,7 +35,39 @@ PUBLIC void arch_shutdown(int how)
                 * the program if not already done.
                 */
                if (how != RBT_MONITOR)
-                       phys_copy(vir2phys(""), kinfo.params_base, 1);
+                       arch_set_params("", 1);
+               if(minix_panicing) {
+                       int source, dest;
+                       static char mybuffer[sizeof(params_buffer)];
+                       char *lead = "echo \\n*** kernel messages:\\n";
+                       int leadlen = strlen(lead);
+                       strcpy(mybuffer, lead);
+
+#define DECSOURCE source = (source - 1 + _KMESS_BUF_SIZE) % _KMESS_BUF_SIZE
+
+                       dest = sizeof(mybuffer)-1;
+                       mybuffer[dest--] = '\0';
+
+                       source = kmess.km_next;
+                       DECSOURCE; 
+
+                       while(dest >= leadlen) {
+                               char c = kmess.km_buf[source];
+                               if(c == '\n') {
+                                       mybuffer[dest--] = 'n';
+                                       mybuffer[dest] = '\\';
+                               } else if(isprint(c) &&
+                                       c != '\'' && c != '"' &&
+                                       c != '\\' && c != ';') {
+                                       mybuffer[dest] = c;
+                               } else  mybuffer[dest] = '|';
+
+                               DECSOURCE;
+                               dest--;
+                       }
+
+                       arch_set_params(mybuffer, strlen(mybuffer)+1);
+               }
                level0(monitor);
        } else {
                /* Reset the system by forcing a processor shutdown. First stop
@@ -44,6 +80,17 @@ PUBLIC void arch_shutdown(int how)
        }
 }
 
+/* address of a.out headers, set in mpx386.s */
+phys_bytes aout;
+
+PUBLIC void arch_get_aout_headers(int i, struct exec *h)
+{
+       /* The bootstrap loader created an array of the a.out headers at
+        * absolute address 'aout'. Get one element to h.
+        */
+       phys_copy(aout + i * A_MINHDR, vir2phys(h), (phys_bytes) A_MINHDR);
+}
+
 PUBLIC void system_init(void)
 {
        prot_init();
@@ -122,7 +169,7 @@ PUBLIC void ser_dump_proc()
                        pp->p_priority, pp->p_max_priority,
                        pp->p_user_time, pp->p_sys_time, 
                        pp->p_reg.pc);
-               stacktrace(pp);
+               proc_stacktrace(pp);
        }
 }
 
@@ -219,3 +266,23 @@ PUBLIC void cons_seth(int pos, int n)
        else
                cons_setc(pos, 'A'+(n-10));
 }
+
+/* Saved by mpx386.s into these variables. */
+u32_t params_size, params_offset, mon_ds;
+
+PUBLIC int arch_get_params(char *params, int maxsize)
+{
+       phys_copy(seg2phys(mon_ds) + params_offset, vir2phys(params),
+               MIN(maxsize, params_size));
+       params[maxsize-1] = '\0';
+       return OK;
+}
+
+PUBLIC int arch_set_params(char *params, int size)
+{
+       if(size > params_size)
+               return E2BIG;
+       phys_copy(vir2phys(params), seg2phys(mon_ds) + params_offset, size);
+       return OK;
+}
+
diff --git a/kernel/arch/i386/vm.h b/kernel/arch/i386/vm.h
new file mode 100644 (file)
index 0000000..1707ac9
--- /dev/null
@@ -0,0 +1,27 @@
+
+.define _load_kernel_cr3
+.define _last_cr3
+
+#define LOADKERNELCR3                  ;\
+       inc     (_cr3switch)            ;\
+       mov     eax,    (_kernel_cr3)   ;\
+       cmp     (_last_cr3), eax        ;\
+       jz      9f                      ;\
+       push    _load_kernel_cr3        ;\
+       call    _level0                 ;\
+       pop     eax                     ;\
+       mov     eax,    (_kernel_cr3)   ;\
+       mov     (_last_cr3), eax        ;\
+       inc     (_cr3reload)            ;\
+9:
+
+#define LOADCR3WITHEAX(type, newcr3)   ;\
+sseg   inc     (_cr3switch)            ;\
+sseg   mov     eax,    newcr3          ;\
+sseg   cmp     (_last_cr3), eax        ;\
+       jz      8f                      ;\
+       mov     cr3, eax                ;\
+sseg   inc     (_cr3reload)            ;\
+sseg   mov     (_last_cr3), eax        ;\
+8:
+
index 16866eb72258769f7e83e14e9c63c73be673f523..80cc4c47489685dc92a4b2bb557742068d11cd9c 100755 (executable)
@@ -75,7 +75,7 @@ PUBLIC void clock_task()
        result = receive(ANY, &m);
 
        if(result != OK)
-               panic("receive() failed", result);
+               minix_panic("receive() failed", result);
 
        /* Handle the request. Only clock ticks are expected. */
        switch (m.m_type) {
@@ -181,6 +181,8 @@ irq_hook_t *hook;
  */
   register unsigned ticks;
 
+  if(minix_panicing) return;
+
   /* Get number of ticks and update realtime. */
   ticks = lost_ticks + 1;
   lost_ticks = 0;
@@ -201,8 +203,10 @@ irq_hook_t *hook;
       bill_ptr->p_ticks_left -= ticks;
   }
 
+#if 0
   /* Update load average. */
   load_update();
+#endif
   
   /* Check if do_clocktick() must be called. Done for alarms and scheduling.
    * Some processes, such as the kernel tasks, cannot be preempted. 
index 371dcae354068f9dfa36c377e7c7dfe35c1a7b6c..0fb906db77a5a22a5102c5a7c33f0608aa65d260 100644 (file)
  */
 #define P_NAME_LEN        8
 
-/* Kernel diagnostics are written to a circular buffer. After each message, 
- * a system server is notified and a copy of the buffer can be retrieved to 
- * display the message. The buffers size can safely be reduced.  
- */
-#define KMESS_BUF_SIZE   256           
-
 /* Buffer to gather randomness. This is used to generate a random stream by 
  * the MEMORY driver when reading from /dev/random. 
  */
 
 #define K_PARAM_SIZE     512
 
-/* This section allows to enable kernel debugging and timing functionality.
- * For normal operation all options should be disabled.
- */
-#define DEBUG_SCHED_CHECK  0   /* sanity check of scheduling queues */
-#define DEBUG_TIME_LOCKS   0   /* measure time spent in locks */
-
 #endif /* CONFIG_H */
 
index b8cd35263199d2f0d00b4142495117a40402b551..1ef59762923680f811865583d3bbbdc6d58e5365 100755 (executable)
@@ -6,6 +6,7 @@
 #include <minix/bitmap.h>
 
 #include "config.h"
+#include "debug.h"
 
 /* Map a process number to a privilege structure id. */
 #define s_nr_to_id(n)  (NR_TASKS + (n) + 1)
        ( MAP_CHUNK(map.chunk,bit) &= ~(1 << CHUNK_OFFSET(bit) )
 #define NR_SYS_CHUNKS  BITMAP_CHUNKS(NR_SYS_PROCS)
 
-#if DEBUG_LOCK_CHECK
-#define reallock(c, v)  { if(intr_disabled()) { kinfo.relocking++; } else { intr_disable(); } }
-#else
-#define reallock(c, v)  intr_disable()
-#endif
+#define reallock  do { int d; d = intr_disabled(); intr_disable(); locklevel++; if(d && locklevel == 1) { minix_panic("reallock while interrupts disabled first time", __LINE__); } } while(0)
 
-#define realunlock(c)   intr_enable()
+#define realunlock   do { if(!intr_disabled()) { minix_panic("realunlock while interrupts enabled", __LINE__); } if(locklevel < 1) { minix_panic("realunlock while locklevel below 1", __LINE__); } locklevel--; if(locklevel == 0) { intr_enable(); } } while(0)
 
-#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)
-#endif
+#define lock      reallock
+#define unlock    realunlock
 
 /* args to intr_init() */
 #define INTS_ORIG      0       /* restore interrupts */
index eeb3b775e07578fdfb66ea1948280dd71c4bef82..16b96905e61d01737ecfbea77a82134cc4e97d68 100644 (file)
@@ -6,12 +6,13 @@
 #include "kernel.h"
 #include "proc.h"
 #include "debug.h"
+
+#include <minix/sysutil.h>
 #include <limits.h>
+#include <string.h>
 
-#if DEBUG_TIME_LOCKS           /* only include code if enabled */
 
 /* Data structures to store lock() timing data. */
-struct lock_timingdata timingdata[TIMING_CATEGORIES];
 static unsigned long starttimes[TIMING_CATEGORIES][2];
 
 #define HIGHCOUNT      0
@@ -100,69 +101,75 @@ void timer_end(int cat)
        return;
 }
 
-#endif /* DEBUG_TIME_LOCKS */
-
 #if DEBUG_SCHED_CHECK          /* only include code if enabled */
 
 #define MAX_LOOP (NR_PROCS + NR_TASKS)
 
 PUBLIC void
-check_runqueues(char *when)
+check_runqueues_f(char *file, int line)
 {
   int q, l = 0;
   register struct proc *xp;
+#define MYPANIC(msg) {         \
+       static char buf[100];   \
+       strcpy(buf, file);      \
+       strcat(buf, ": ");      \
+       util_nstrcat(buf, line);\
+       strcat(buf, ": ");      \
+       strcat(buf, msg);       \
+       minix_panic(buf, NO_NUM);       \
+       }
 
   for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
        xp->p_found = 0;
-       if (l++ > MAX_LOOP) {  panic("check error", NO_NUM); }
+       if (l++ > MAX_LOOP) {  MYPANIC("check error"); }
   }
 
   for (q=l=0; q < NR_SCHED_QUEUES; q++) {
     if (rdy_head[q] && !rdy_tail[q]) {
-       kprintf("head but no tail in %d: %s", q, when);
-                panic("scheduling error", NO_NUM);
+       kprintf("head but no tail in %d\n", q);
+                MYPANIC("scheduling error");
     }
     if (!rdy_head[q] && rdy_tail[q]) {
-       kprintf("tail but no head in %d: %s", q, when);
-                panic("scheduling error", NO_NUM);
+       kprintf("tail but no head in %d\n", q);
+                MYPANIC("scheduling error");
     }
     if (rdy_tail[q] && rdy_tail[q]->p_nextready != NIL_PROC) {
-       kprintf("tail and tail->next not null in %d: %s", q, when);
-                panic("scheduling error", NO_NUM);
+       kprintf("tail and tail->next not null in %d\n", q);
+                MYPANIC("scheduling error");
     }
     for(xp = rdy_head[q]; xp != NIL_PROC; xp = xp->p_nextready) {
         if (!xp->p_ready) {
-               kprintf("scheduling error: unready on runq %d proc %d: %s\n",
-                       q, xp->p_nr, when);
-               panic("found unready process on run queue", NO_NUM);
+               kprintf("scheduling error: unready on runq %d proc %d\n",
+                       q, xp->p_nr);
+               MYPANIC("found unready process on run queue");
         }
         if (xp->p_priority != q) {
-               kprintf("scheduling error: wrong priority q %d proc %d: %s\n",
-                       q, xp->p_nr, when);
-               panic("wrong priority", NO_NUM);
+               kprintf("scheduling error: wrong priority q %d proc %d\n",
+                       q, xp->p_nr);
+               MYPANIC("wrong priority");
        }
        if (xp->p_found) {
-               kprintf("scheduling error: double sched q %d proc %d: %s\n",
-                       q, xp->p_nr, when);
-               panic("proc more than once on scheduling queue", NO_NUM);
+               kprintf("scheduling error: double sched q %d proc %d\n",
+                       q, xp->p_nr);
+               MYPANIC("proc more than once on scheduling queue");
        }
        xp->p_found = 1;
        if (xp->p_nextready == NIL_PROC && rdy_tail[q] != xp) {
-               kprintf("sched err: last element not tail q %d proc %d: %s\n",
-                       q, xp->p_nr, when);
-               panic("scheduling error", NO_NUM);
+               kprintf("sched err: last element not tail q %d proc %d\n",
+                       q, xp->p_nr);
+               MYPANIC("scheduling error");
        }
-       if (l++ > MAX_LOOP) panic("loop in schedule queue?", NO_NUM);
+       if (l++ > MAX_LOOP) MYPANIC("loop in schedule queue?");
     }
   }    
 
   l = 0;
   for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
        if (! isemptyp(xp) && xp->p_ready && ! xp->p_found) {
-               kprintf("sched error: ready proc %d not on queue: %s\n",
-                       xp->p_nr, when);
-               panic("ready proc not on scheduling queue", NO_NUM);
-               if (l++ > MAX_LOOP) { panic("loop in proc.t?", NO_NUM); }
+               kprintf("sched error: ready proc %d not on queue\n", xp->p_nr);
+               MYPANIC("ready proc not on scheduling queue");
+               if (l++ > MAX_LOOP) { MYPANIC("loop in debug.c?"); }
        }
   }
 }
index 2cfb905d0ad85dd7595fd98bba37088ad6da78f5..b114a4a3ac5dc7933a1e57dce78bfb2975ed8e27 100644 (file)
  */
 #define DEBUG_ENABLE_IPC_WARNINGS      0
 #define DEBUG_STACKTRACE               1
+#define DEBUG_VMASSERT                 1
+#define DEBUG_SCHED_CHECK              1
+#define DEBUG_TIME_LOCKS               1
 
 /* It's interesting to measure the time spent withing locked regions, because
  * this is the time that the system is deaf to interrupts.
  */
-#if DEBUG_TIME_LOCKS
 
 #define TIMING_POINTS          20      /* timing resolution */
 #define TIMING_CATEGORIES      20
 #define TIMING_NAME            10
 
-/* Definition of the data structure to store lock() timing data. */ 
-struct lock_timingdata {
-       char names[TIMING_NAME];
-       unsigned long lock_timings[TIMING_POINTS];
-       unsigned long lock_timings_range[2];
-       unsigned long binsize, resets, misses, measurements;
-};
-
-/* The data is declared here, but allocated in debug.c. */
-extern struct lock_timingdata timingdata[TIMING_CATEGORIES];
-
-/* Prototypes for the timing functionality. */
-_PROTOTYPE( void timer_start, (int cat, char *name) );
-_PROTOTYPE( void timer_end, (int cat) );
-
-#define locktimestart(c, v) timer_start(c, v)
-#define locktimeend(c) timer_end(c)
-#else
-#define locktimestart(c, v)
-#define locktimeend(c)
-#endif /* DEBUG_TIME_LOCKS */
-
 #endif /* DEBUG_H */
index 4566739b14f26d4c25bd8dfc357059308321ebe5..30468ab353b5e2761d5c155ebe838136ba0a4113 100755 (executable)
@@ -20,7 +20,6 @@ EXTERN char kernel_exception;         /* TRUE after system exceptions */
 EXTERN char shutdown_started;          /* TRUE after shutdowns / reboots */
 
 /* Kernel information structures. This groups vital kernel information. */
-EXTERN phys_bytes aout;                        /* address of a.out headers */
 EXTERN struct kinfo kinfo;             /* kernel information for users */
 EXTERN struct machine machine;         /* machine information for users */
 EXTERN struct kmessages kmess;         /* diagnostic messages in kernel */
@@ -32,6 +31,10 @@ EXTERN struct proc *prev_ptr;        /* previously running process */
 EXTERN struct proc *proc_ptr;  /* pointer to currently running process */
 EXTERN struct proc *next_ptr;  /* next process to run after restart() */
 EXTERN struct proc *bill_ptr;  /* process to bill for clock ticks */
+EXTERN struct proc *vmrestart;  /* first process on vmrestart queue */
+EXTERN struct proc *vmrequest;  /* first process on vmrequest queue */
+EXTERN struct proc *pagefaults; /* first process on pagefault queue */
+EXTERN struct proc *softnotify;        /* first process on softnotify queue */
 EXTERN char k_reenter;         /* kernel reentry count (entry count less 1) */
 EXTERN unsigned lost_ticks;    /* clock ticks counted outside clock task */
 
@@ -75,11 +78,25 @@ EXTERN endpoint_t who_e;            /* message source endpoint */
 EXTERN int who_p;                      /* message source proc */
 EXTERN int sys_call_code;              /* kernel call number in SYSTEM */
 EXTERN time_t boottime;
+EXTERN char params_buffer[512];                /* boot monitor parameters */
+EXTERN int minix_panicing;
+EXTERN int locklevel;
+
+EXTERN unsigned long cr3switch;
+EXTERN unsigned long cr3reload;
 
 /* VM */
 EXTERN phys_bytes vm_base;
 EXTERN phys_bytes vm_size;
 EXTERN phys_bytes vm_mem_high;
+EXTERN int vm_running;
+EXTERN int must_notify_vm;
+
+/* Verbose flags (debugging). */
+EXTERN int verbose_vm;
+
+/* Timing measurements. */
+EXTERN struct lock_timingdata timingdata[TIMING_CATEGORIES];
 
 /* Variables that are initialized elsewhere are just extern here. */
 extern struct boot_image image[];      /* system image processes */
index 6d54fab22df188981f5891ec7ab18dadda006bb4..3dffb72b6b7e3a848fba8e20a1191da8529d8233 100644 (file)
@@ -30,7 +30,7 @@ PUBLIC void put_irq_handler( irq_hook_t* hook, int irq, irq_handler_t handler)
   irq_hook_t **line;
   
   if( irq < 0 || irq >= NR_IRQ_VECTORS )
-       panic("invalid call to put_irq_handler", irq);
+       minix_panic("invalid call to put_irq_handler", irq);
 
   line = &irq_handlers[irq];
   id = 1;
@@ -42,7 +42,7 @@ PUBLIC void put_irq_handler( irq_hook_t* hook, int irq, irq_handler_t handler)
   }
   
   if(id == 0)
-       panic("Too many handlers for irq", irq);
+       minix_panic("Too many handlers for irq", irq);
 
   hook->next = NULL;
   hook->handler = handler;
@@ -68,7 +68,7 @@ PUBLIC void rm_irq_handler( irq_hook_t* hook ) {
   irq_hook_t **line;
 
   if( irq < 0 || irq >= NR_IRQ_VECTORS ) 
-       panic("invalid call to rm_irq_handler", irq);
+       minix_panic("invalid call to rm_irq_handler", irq);
 
   /* disable the irq.  */
   intr_mask(hook);
index d315b852b483364145f5b3084d51649b8b22508c..15c83afdcfc801e77735657df8decd4789f70a78 100644 (file)
 #define RECEIVE                   2    /* blocking receive */
 #define SENDREC                   3    /* SEND + RECEIVE */
 #define NOTIFY            4    /* asynchronous notify */
-#define SENDNB            5    /* nonblocking send */
+#define SENDNB             5    /* nonblocking send */
 #define SENDA             16   /* asynchronous send */
 
 /* The following bit masks determine what checks that should be done. */
 #define CHECK_DEADLOCK  0x03   /* 0000 0011 : check for deadlock */
 
+#define WILLRECEIVE(target, source_ep) \
+  ((RTS_ISSET(target, RECEIVING) && !RTS_ISSET(target, SENDING)) &&    \
+    (target->p_getfrom_e == ANY || target->p_getfrom_e == source_ep))
+
+
 #endif /* IPC_H */
index f9ec99e20e423427fc7e2d5ed38c00c0132f393e..00aa32d147e6fd77719a12aadadb1505c25f38ce 100755 (executable)
@@ -20,7 +20,6 @@
 
 /* Prototype declarations for PRIVATE functions. */
 FORWARD _PROTOTYPE( void announce, (void));    
-FORWARD _PROTOTYPE( void shutdown, (timer_t *));       
 
 /*===========================================================================*
  *                             main                                         *
@@ -115,11 +114,11 @@ PUBLIC void main()
                hdrindex = 1 + i-NR_TASKS;      /* servers, drivers, INIT */
        }
 
-       /* The bootstrap loader created an array of the a.out headers at
-        * absolute address 'aout'. Get one element to e_hdr.
+       /* Architecture-specific way to find out aout header of this
+        * boot process.
         */
-       phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr),
-                                               (phys_bytes) A_MINHDR);
+       arch_get_aout_headers(hdrindex, &e_hdr);
+
        /* Convert addresses to clicks and build process memory map */
        text_base = e_hdr.a_syms >> CLICK_SHIFT;
        text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
@@ -156,8 +155,8 @@ PUBLIC void main()
        }
        
        /* Set ready. The HARDWARE task is never ready. */
-       if (rp->p_nr == HARDWARE) RTS_LOCK_SET(rp, NO_PRIORITY);
-       RTS_LOCK_UNSET(rp, SLOT_FREE); /* remove SLOT_FREE and schedule */
+       if (rp->p_nr == HARDWARE) RTS_SET(rp, NO_PRIORITY);
+       RTS_UNSET(rp, SLOT_FREE); /* remove SLOT_FREE and schedule */
 
        /* Code and data segments must be allocated in protected mode. */
        alloc_segments(rp);
@@ -170,6 +169,8 @@ PUBLIC void main()
   cprof_procs_no = 0;  /* init nr of hash table slots used */
 #endif /* CPROFILE */
 
+  vm_running = 0;
+
   /* MINIX is now ready. All boot image processes are on the ready queue.
    * Return to the assembly code to start running the current process. 
    */
@@ -203,34 +204,19 @@ int how;
   register struct proc *rp; 
   message m;
 
-  /* Send a signal to all system processes that are still alive to inform 
-   * them that the MINIX kernel is shutting down. A proper shutdown sequence
-   * should be implemented by a user-space server. This mechanism is useful
-   * as a backup in case of system panics, so that system processes can still
-   * run their shutdown code, e.g, to synchronize the FS or to let the TTY
-   * switch to the first console. 
-   */
-#if DEAD_CODE
-  kprintf("Sending SIGKSTOP to system processes ...\n"); 
-  for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
-      if (!isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && !iskernelp(rp))
-          send_sig(proc_nr(rp), SIGKSTOP);
-  }
-#endif
-
   /* Continue after 1 second, to give processes a chance to get scheduled to 
    * do shutdown work.  Set a watchog timer to call shutdown(). The timer 
    * argument passes the shutdown status. 
    */
   kprintf("MINIX will now be shut down ...\n");
   tmr_arg(&shutdown_timer)->ta_int = how;
-  set_timer(&shutdown_timer, get_uptime() + HZ, shutdown);
+  set_timer(&shutdown_timer, get_uptime() + 5*HZ, minix_shutdown);
 }
 
 /*===========================================================================*
  *                             shutdown                                     *
  *===========================================================================*/
-PRIVATE void shutdown(tp)
+PUBLIC void minix_shutdown(tp)
 timer_t *tp;
 {
 /* This function is called from prepare_shutdown or stop_sequence to bring 
@@ -239,6 +225,6 @@ timer_t *tp;
  */
   intr_init(INTS_ORIG);
   clock_stop();
-  arch_shutdown(tmr_arg(tp)->ta_int);
+  arch_shutdown(tp ? tmr_arg(tp)->ta_int : RBT_PANIC);
 }
 
index c405a2c91d1b4922caaf67616d241434e6c94efe..692eafb4c4a749e5f4303b2541baf5ee8dc2218a 100755 (executable)
 #include <minix/com.h>
 #include <minix/callnr.h>
 #include <minix/endpoint.h>
-#include "debug.h"
-#include "kernel.h"
-#include "proc.h"
 #include <stddef.h>
 #include <signal.h>
 #include <minix/portio.h>
 #include <minix/u64.h>
 
+#include "debug.h"
+#include "kernel.h"
+#include "proc.h"
+#include "vm.h"
+
 /* Scheduling and message passing functions. The functions are available to 
  * other parts of the kernel through lock_...(). The lock temporarily disables 
  * interrupts to prevent race conditions. 
  */
 FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst_e,
-               message *m_ptr, unsigned flags));
+               message *m_ptr, int flags));
 FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, int src,
-               message *m_ptr, unsigned flags));
+               message *m_ptr, int flags));
 FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst));
 FORWARD _PROTOTYPE( int mini_senda, (struct proc *caller_ptr,
        asynmsg_t *table, size_t size));
@@ -62,8 +64,6 @@ FORWARD _PROTOTYPE( int deadlock, (int function,
                register struct proc *caller, int src_dst));
 FORWARD _PROTOTYPE( int try_async, (struct proc *caller_ptr));
 FORWARD _PROTOTYPE( int try_one, (struct proc *src_ptr, struct proc *dst_ptr));
-FORWARD _PROTOTYPE( void enqueue, (struct proc *rp));
-FORWARD _PROTOTYPE( void dequeue, (struct proc *rp));
 FORWARD _PROTOTYPE( void sched, (struct proc *rp, int *queue, int *front));
 FORWARD _PROTOTYPE( void pick_proc, (void));
 
@@ -82,10 +82,51 @@ FORWARD _PROTOTYPE( void pick_proc, (void));
                break;                                                  \
        }
 
-#define CopyMess(s,sp,sm,dp,dm) \
-       cp_mess(proc_addr(s)->p_endpoint, \
-               (sp)->p_memmap[D].mem_phys,     \
-               (vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm)
+#define CopyMess(s,sp,sm,dp,dm) do {                   \
+       vir_bytes dstlin;                               \
+       endpoint_t e = proc_addr(s)->p_endpoint;        \
+       struct vir_addr src, dst;                       \
+       int r;                                          \
+       timer_start(0, "copymess");                     \
+       if((dstlin = umap_local((dp), D, (vir_bytes) dm, sizeof(message))) == 0){\
+               minix_panic("CopyMess: umap_local failed", __LINE__);   \
+       }                                               \
+                       \
+       if(vm_running &&        \
+        (r=vm_checkrange((dp), (dp), dstlin, sizeof(message), 1, 0)) != OK) { \
+               if(r != VMSUSPEND)                      \
+                 minix_panic("CopyMess: vm_checkrange error", __LINE__); \
+               (dp)->p_vmrequest.saved.msgcopy.dst = (dp);     \
+               (dp)->p_vmrequest.saved.msgcopy.dst_v = (vir_bytes) dm; \
+               if(data_copy((sp)->p_endpoint,  \
+                       (vir_bytes) (sm), SYSTEM,       \
+                       (vir_bytes) &(dp)->p_vmrequest.saved.msgcopy.msgbuf, \
+                       sizeof(message)) != OK) {               \
+                               minix_panic("CopyMess: data_copy failed", __LINE__);\
+                       }                               \
+                       (dp)->p_vmrequest.saved.msgcopy.msgbuf.m_source = e; \
+                       (dp)->p_vmrequest.type = VMSTYPE_MSGCOPY; \
+       } else  {                                       \
+               src.proc_nr_e = (sp)->p_endpoint;               \
+               dst.proc_nr_e = (dp)->p_endpoint;               \
+               src.segment = dst.segment = D;                  \
+               src.offset = (vir_bytes) (sm);                  \
+               dst.offset = (vir_bytes) (dm);                  \
+               if(virtual_copy(&src, &dst, sizeof(message)) != OK) {   \
+                       kprintf("copymess: copy %d:%lx to %d:%lx failed\n",\
+                               (sp)->p_endpoint, (sm), (dp)->p_endpoint, dm);\
+                       minix_panic("CopyMess: virtual_copy (1) failed", __LINE__); \
+               }               \
+               src.proc_nr_e = SYSTEM;                         \
+               src.offset = (vir_bytes) &e;                    \
+               if(virtual_copy(&src, &dst, sizeof(e)) != OK) {         \
+                       kprintf("copymess: copy %d:%lx to %d:%lx\n",    \
+                               (sp)->p_endpoint, (sm), (dp)->p_endpoint, dm);\
+                       minix_panic("CopyMess: virtual_copy (2) failed", __LINE__); \
+               }                                       \
+       }       \
+       timer_end(0);   \
+} while(0)
 
 /*===========================================================================*
  *                             sys_call                                     * 
@@ -105,11 +146,25 @@ long bit_map;                     /* notification event set or flags */
   int group_size;                              /* used for deadlock check */
   int result;                                  /* the system call's result */
   int src_dst_p;                               /* Process slot number */
-  vir_clicks vlo, vhi;         /* virtual clicks containing message to send */
+  size_t msg_size;
 
   if (caller_ptr->p_endpoint == ipc_stats_target)
        ipc_stats.total= add64u(ipc_stats.total, 1);
 
+#if 0
+  if(src_dst_e != 4 && src_dst_e != 5 &&
+       caller_ptr->p_endpoint != 4 && caller_ptr->p_endpoint != 5) {
+       if(call_nr == SEND)
+               kprintf("(%d SEND to %d) ", caller_ptr->p_endpoint, src_dst_e);
+       else if(call_nr == RECEIVE)
+               kprintf("(%d RECEIVE from %d) ", caller_ptr->p_endpoint, src_dst_e);
+       else if(call_nr == SENDREC)
+               kprintf("(%d SENDREC to %d) ", caller_ptr->p_endpoint, src_dst_e);
+       else
+               kprintf("(%d %d to/from %d) ", caller_ptr->p_endpoint, call_nr, src_dst_e);
+  }
+#endif
+
 #if 1
   if (RTS_ISSET(caller_ptr, SLOT_FREE))
   {
@@ -122,10 +177,10 @@ long bit_map;                     /* notification event set or flags */
 
   /* Check destination. SENDA is special because its argument is a table and
    * not a single destination. RECEIVE is the only call that accepts ANY (in
-   * addition to a real endpoint). The other calls (SEND, SENDNB, SENDREC,
+   * addition to a real endpoint). The other calls (SEND, SENDREC,
    * and NOTIFY) require an endpoint to corresponds to a process. In addition,
-   * it is necessary to check whether a process is allow to send to a given
-   * destination. For SENDREC we check s_ipc_sendrec, and for SEND, SENDNB,
+   * it is necessary to check whether a process is allowed to send to a given
+   * destination. For SENDREC we check s_ipc_sendrec, and for SEND,
    * and NOTIFY we check s_ipc_to.
    */
   if (call_nr == SENDA)
@@ -150,7 +205,6 @@ long bit_map;                       /* notification event set or flags */
   {
        /* Require a valid source and/or destination process. */
        if(!isokendpt(src_dst_e, &src_dst_p)) {
-if (src_dst_e == 0) panic("sys_call: no PM", NO_NUM);
 #if DEBUG_ENABLE_IPC_WARNINGS
                kprintf("sys_call: trap %d by %d with bad endpoint %d\n", 
                        call_nr, proc_nr(caller_ptr), src_dst_e);
@@ -160,7 +214,7 @@ if (src_dst_e == 0) panic("sys_call: no PM", NO_NUM);
                return EDEADSRCDST;
        }
 
-       /* If the call is to send to a process, i.e., for SEND, SENDNB,
+       /* If the call is to send to a process, i.e., for SEND,
         * SENDREC or NOTIFY, verify that the caller is allowed to send to
         * the given destination. 
         */
@@ -224,40 +278,85 @@ if (src_dst_e == 0) panic("sys_call: no PM", NO_NUM);
   if ((iskerneln(src_dst_p) && call_nr != SENDREC && call_nr != RECEIVE)) {
 #if DEBUG_ENABLE_IPC_WARNINGS
       kprintf("sys_call: trap %d not allowed, caller %d, src_dst %d\n", 
-          call_nr, proc_nr(caller_ptr), src_dst);
+          call_nr, proc_nr(caller_ptr), src_dst_e);
 #endif
        if (caller_ptr->p_endpoint == ipc_stats_target)
                ipc_stats.call_not_allowed++;
        return(ETRAPDENIED);            /* trap denied by mask or kernel */
   }
 
-  /* If the call involves a message buffer, i.e., for SEND, SENDNB, SENDREC, 
+  /* Get and check the size of the argument in bytes.
+   * Normally this is just the size of a regular message, but in the
+   * case of SENDA the argument is a table.
+   */
+  if(call_nr == SENDA) {
+       msg_size = (size_t) src_dst_e;
+
+       /* Limit size to something reasonable. An arbitrary choice is 16
+        * times the number of process table entries.
+        */
+       if (msg_size > 16*(NR_TASKS + NR_PROCS))
+               return EDOM;
+       msg_size *= sizeof(asynmsg_t);  /* convert to bytes */
+  } else {
+       msg_size = sizeof(*m_ptr);
+  }
+
+  /* If the call involves a message buffer, i.e., for SEND, SENDREC, 
    * or RECEIVE, check the message pointer. This check allows a message to be 
    * anywhere in data or stack or gap. It will have to be made more elaborate 
    * for machines which don't have the gap mapped. 
+   *
+   * We use msg_size decided above.
    */
-  if (call_nr == SEND || call_nr == SENDNB || call_nr == SENDREC ||
-       call_nr == RECEIVE) {
-       vlo = (vir_bytes) m_ptr >> CLICK_SHIFT;         
-       vhi = ((vir_bytes) m_ptr + MESS_SIZE - 1) >> CLICK_SHIFT;
-       if (vlo < caller_ptr->p_memmap[D].mem_vir || vlo > vhi ||
-               vhi >= caller_ptr->p_memmap[S].mem_vir + 
-               caller_ptr->p_memmap[S].mem_len) {
-#if DEBUG_ENABLE_IPC_WARNINGS
-               kprintf(
-               "sys_call: invalid message pointer, trap %d, caller %d\n",
-                       call_nr, proc_nr(caller_ptr));
-#endif
-               if (caller_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.bad_buffer++;
-               return(EFAULT);                 /* invalid message pointer */
+  if (call_nr == SEND || call_nr == SENDREC ||
+       call_nr == RECEIVE || call_nr == SENDA || call_nr == SENDNB) {
+       int r;
+       phys_bytes lin;
+
+       /* Map to linear address. */
+       if((lin = umap_local(caller_ptr, D, (vir_bytes) m_ptr, msg_size)) == 0)
+               return EFAULT;
+
+       /* Check if message pages in calling process are mapped.
+        * We don't have to check the recipient if this is a send,
+        * because this code will do that before its receive() starts.
+        *
+        * It is important the range is verified as _writable_, because
+        * the kernel will want to write to the SENDA buffer in the future,
+        * and those pages may not be shared between processes.
+        */
+
+       if(vm_running &&
+        (r=vm_checkrange(caller_ptr, caller_ptr, lin, msg_size, 1, 0)) != OK) {
+               if(r != VMSUSPEND) {
+                       kprintf("SYSTEM:sys_call:vm_checkrange: err %d\n", r);
+                       return r;
+               }
+               minix_panic("vmsuspend", __LINE__);
+               
+               /* We can't go ahead with this call. Caller is suspended
+                * and we have to save the state in its process struct.
+                */
+               caller_ptr->p_vmrequest.saved.sys_call.call_nr = call_nr;
+               caller_ptr->p_vmrequest.saved.sys_call.m_ptr = m_ptr;
+               caller_ptr->p_vmrequest.saved.sys_call.src_dst_e = src_dst_e;
+               caller_ptr->p_vmrequest.saved.sys_call.bit_map = bit_map;
+               caller_ptr->p_vmrequest.type = VMSTYPE_SYS_CALL;
+
+               kprintf("SYSTEM: %s:%d: suspending call 0x%lx on ipc buffer 0x%lx\n",
+                       caller_ptr->p_name, caller_ptr->p_endpoint, call_nr, m_ptr);
+
+               /* vm_checkrange() will have suspended caller with VMREQUEST. */
+               return OK;
        }
-  }
+
+  } 
 
   /* Check for a possible deadlock for blocking SEND(REC) and RECEIVE. */
   if (call_nr == SEND || call_nr == SENDREC || call_nr == RECEIVE) {
       if (group_size = deadlock(call_nr, caller_ptr, src_dst_p)) {
-#if DEBUG_ENABLE_IPC_WARNINGS
+#if 0
           kprintf("sys_call: trap %d from %d to %d deadlocked, group size %d\n",
               call_nr, proc_nr(caller_ptr), src_dst_p, group_size);
 #endif
@@ -273,7 +372,6 @@ if (src_dst_e == 0) panic("sys_call: no PM", NO_NUM);
    *   - SEND:    sender blocks until its message has been delivered
    *   - RECEIVE: receiver blocks until an acceptable message has arrived
    *   - NOTIFY:  asynchronous call; deliver notification or mark pending
-   *   - SENDNB:  nonblocking send
    *   - SENDA:   list of asynchronous send requests
    */
   switch(call_nr) {
@@ -282,21 +380,21 @@ if (src_dst_e == 0) panic("sys_call: no PM", NO_NUM);
        caller_ptr->p_misc_flags |= REPLY_PENDING;
        /* fall through */
   case SEND:                   
-       result = mini_send(caller_ptr, src_dst_e, m_ptr, 0 /*flags*/);
+       result = mini_send(caller_ptr, src_dst_e, m_ptr, 0);
        if (call_nr == SEND || result != OK)
                break;                          /* done, or SEND failed */
        /* fall through for SENDREC */
   case RECEIVE:                        
        if (call_nr == RECEIVE)
                caller_ptr->p_misc_flags &= ~REPLY_PENDING;
-       result = mini_receive(caller_ptr, src_dst_e, m_ptr, 0 /*flags*/);
+       result = mini_receive(caller_ptr, src_dst_e, m_ptr, 0);
        break;
   case NOTIFY:
        result = mini_notify(caller_ptr, src_dst_p);
        break;
-  case SENDNB:                 
-       result = mini_send(caller_ptr, src_dst_e, m_ptr, NON_BLOCKING);
-       break;
+  case SENDNB:
+        result = mini_send(caller_ptr, src_dst_e, m_ptr, NON_BLOCKING);
+        break;
   case SENDA:
        result = mini_senda(caller_ptr, (asynmsg_t *)m_ptr, (size_t)src_dst_e);
        break;
@@ -325,10 +423,17 @@ int src_dst;                                      /* src or dst process */
   register struct proc *xp;                    /* process pointer */
   int group_size = 1;                          /* start with only caller */
   int trap_flags;
+#if DEBUG_ENABLE_IPC_WARNINGS
+  static struct proc *processes[NR_PROCS + NR_TASKS];
+  processes[0] = cp;
+#endif
 
   while (src_dst != ANY) {                     /* check while process nr */
       int src_dst_e;
       xp = proc_addr(src_dst);                 /* follow chain of processes */
+#if DEBUG_ENABLE_IPC_WARNINGS
+      processes[group_size] = xp;
+#endif
       group_size ++;                           /* extra process in group */
 
       /* Check whether the last process in the chain has a dependency. If it 
@@ -354,12 +459,38 @@ int src_dst;                                      /* src or dst process */
                  return(0);                    /* not a deadlock */
              }
          }
+#if DEBUG_ENABLE_IPC_WARNINGS
+         {
+               int i;
+               kprintf("deadlock between these processes:\n");
+               for(i = 0; i < group_size; i++) {
+                       kprintf(" %10s ", processes[i]->p_name);
+                       proc_stacktrace(processes[i]);
+               }
+         }
+#endif
           return(group_size);                  /* deadlock found */
       }
   }
   return(0);                                   /* not a deadlock */
 }
 
+/*===========================================================================*
+ *                             sys_call_restart                             * 
+ *===========================================================================*/
+PUBLIC void sys_call_restart(caller)
+struct proc *caller;
+{
+       int r;
+       minix_panic("sys_call_restart", NO_NUM);
+       kprintf("restarting sys_call code 0x%lx, "
+               "m_ptr 0x%lx, srcdst %d, bitmap 0x%lx, but not really\n",
+               caller->p_vmrequest.saved.sys_call.call_nr,
+               caller->p_vmrequest.saved.sys_call.m_ptr,
+               caller->p_vmrequest.saved.sys_call.src_dst_e,
+               caller->p_vmrequest.saved.sys_call.bit_map);
+       caller->p_reg.retreg = r;
+}
 
 /*===========================================================================*
  *                             mini_send                                    * 
@@ -368,7 +499,7 @@ PRIVATE int mini_send(caller_ptr, dst_e, m_ptr, flags)
 register struct proc *caller_ptr;      /* who is trying to send a message? */
 int dst_e;                             /* to whom is message being sent? */
 message *m_ptr;                                /* pointer to message buffer */
-unsigned flags;                                /* system call flags */
+int flags;
 {
 /* Send a message from 'caller_ptr' to 'dst'. If 'dst' is blocked waiting
  * for this message, copy the message to it and unblock 'dst'. If 'dst' is
@@ -391,14 +522,18 @@ unsigned flags;                           /* system call flags */
   /* Check if 'dst' is blocked waiting for this message. The destination's 
    * SENDING flag may be set when its SENDREC call blocked while sending.  
    */
-  if ( (RTS_ISSET(dst_ptr, RECEIVING) && !RTS_ISSET(dst_ptr, SENDING)) &&
-       (dst_ptr->p_getfrom_e == ANY
-         || dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) {
+  if (WILLRECEIVE(dst_ptr, caller_ptr->p_endpoint)) {
        /* Destination is indeed waiting for this message. */
        CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr,
                 dst_ptr->p_messbuf);
        RTS_UNSET(dst_ptr, RECEIVING);
-  } else if ( ! (flags & NON_BLOCKING)) {
+  } else {
+       if(flags & NON_BLOCKING) {
+               if (caller_ptr->p_endpoint == ipc_stats_target)
+                       ipc_stats.not_ready++;
+               return(ENOTREADY);
+       }
+
        /* Destination is not waiting.  Block and dequeue caller. */
        caller_ptr->p_messbuf = m_ptr;
        RTS_SET(caller_ptr, SENDING);
@@ -409,10 +544,6 @@ unsigned flags;                            /* system call flags */
        while (*xpp != NIL_PROC) xpp = &(*xpp)->p_q_link;       
        *xpp = caller_ptr;                      /* add caller to end */
        caller_ptr->p_q_link = NIL_PROC;        /* mark new end of list */
-  } else {
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               ipc_stats.not_ready++;
-       return(ENOTREADY);
   }
   return(OK);
 }
@@ -424,11 +555,11 @@ PRIVATE int mini_receive(caller_ptr, src_e, m_ptr, flags)
 register struct proc *caller_ptr;      /* process trying to get message */
 int src_e;                             /* which message source is wanted */
 message *m_ptr;                                /* pointer to message buffer */
-unsigned flags;                                /* system call flags */
+int flags;
 {
 /* A process or task wants to get a message.  If a message is already queued,
  * acquire it and deblock the sender.  If no message from the desired source
- * is available block the caller, unless the flags don't allow blocking.  
+ * is available block the caller.
  */
   register struct proc **xpp;
   register struct notification **ntf_q_pp;
@@ -491,7 +622,9 @@ unsigned flags;                             /* system call flags */
 #if 1
            if (RTS_ISSET(*xpp, SLOT_FREE))
            {
-               kprintf("listening to the dead?!?\n");
+               kprintf("%d: receive from %d; found dead %d (%s)?\n",
+                       caller_ptr->p_endpoint, src_e, (*xpp)->p_endpoint,
+                       (*xpp)->p_name);
                if (caller_ptr->p_endpoint == ipc_stats_target)
                        ipc_stats.deadproc++;
                return EINVAL;
@@ -580,6 +713,28 @@ int dst;                           /* which process to notify */
   return(OK);
 }
 
+#define ASCOMPLAIN(caller, entry, field)       \
+       kprintf("kernel:%s:%d: asyn failed for %s in %s "       \
+       "(%d/%d, tab 0x%lx)\n",__FILE__,__LINE__,       \
+field, caller->p_name, entry, priv(caller)->s_asynsize, priv(caller)->s_asyntab)
+
+#define A_RETRIEVE(entry, field)       \
+  if(data_copy(caller_ptr->p_endpoint, \
+        table_v + (entry)*sizeof(asynmsg_t) + offsetof(struct asynmsg,field),\
+               SYSTEM, (vir_bytes) &tabent.field,      \
+                       sizeof(tabent.field)) != OK) {\
+               ASCOMPLAIN(caller_ptr, entry, #field);  \
+               return EFAULT; \
+       }
+
+#define A_INSERT(entry, field) \
+  if(data_copy(SYSTEM, (vir_bytes) &tabent.field, \
+       caller_ptr->p_endpoint, \
+       table_v + (entry)*sizeof(asynmsg_t) + offsetof(struct asynmsg,field),\
+               sizeof(tabent.field)) != OK) {\
+               ASCOMPLAIN(caller_ptr, entry, #field);  \
+               return EFAULT; \
+       }
 
 /*===========================================================================*
  *                             mini_senda                                   *
@@ -591,11 +746,11 @@ size_t size;
 {
        int i, dst_p, done, do_notify;
        unsigned flags;
-       phys_bytes tab_phys;
        struct proc *dst_ptr;
        struct priv *privp;
        message *m_ptr;
        asynmsg_t tabent;
+       vir_bytes table_v = (vir_bytes) table;
 
        privp= priv(caller_ptr);
        if (!(privp->s_flags & SYS_PROC))
@@ -619,6 +774,9 @@ size_t size;
 
        /* Limit size to something reasonable. An arbitrary choice is 16
         * times the number of process table entries.
+        *
+        * (this check has been duplicated in sys_call but is left here
+        * as a sanity check)
         */
        if (size > 16*(NR_TASKS + NR_PROCS))
        {
@@ -627,26 +785,14 @@ size_t size;
                return EDOM;
        }
        
-       /* Map table */
-       tab_phys= umap_local(caller_ptr, D, (vir_bytes)table,
-               size*sizeof(table[0]));
-       if (tab_phys == 0)
-       {
-               kprintf("mini_senda: got bad table pointer/size\n");
-               if (caller_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.bad_buffer++;
-               return EFAULT;
-       }
-
        /* Scan the table */
        do_notify= FALSE;       
        done= TRUE;
        for (i= 0; i<size; i++)
        {
+
                /* Read status word */
-               phys_copy(tab_phys + i*sizeof(table[0]) +
-                       offsetof(struct asynmsg, flags),
-                       vir2phys(&tabent.flags), sizeof(tabent.flags));
+               A_RETRIEVE(i, flags);
                flags= tabent.flags;
 
                /* Skip empty entries */
@@ -662,28 +808,20 @@ size_t size;
                        return EINVAL;
                }
 
-               /* Skip entry is AMF_DONE is already set */
+               /* Skip entry if AMF_DONE is already set */
                if (flags & AMF_DONE)
                        continue;
 
                /* Get destination */
-               phys_copy(tab_phys + i*sizeof(table[0]) +
-                       offsetof(struct asynmsg, dst),
-                       vir2phys(&tabent.dst), sizeof(tabent.dst));
+               A_RETRIEVE(i, dst);
 
                if (!isokendpt(tabent.dst, &dst_p))
                {
                        /* Bad destination, report the error */
                        tabent.result= EDEADSRCDST;
-                       phys_copy(vir2phys(&tabent.result),
-                               tab_phys + i*sizeof(table[0]) +
-                               offsetof(struct asynmsg, result),
-                               sizeof(tabent.result));
+                       A_INSERT(i, result);
                        tabent.flags= flags | AMF_DONE;
-                       phys_copy(vir2phys(&tabent.flags),
-                               tab_phys + i*sizeof(table[0]) +
-                               offsetof(struct asynmsg, flags),
-                               sizeof(tabent.flags));
+                       A_INSERT(i, flags);
 
                        if (flags & AMF_NOTIFY)
                                do_notify= 1;
@@ -701,15 +839,9 @@ size_t size;
                if (dst_ptr->p_rts_flags & NO_ENDPOINT)
                {
                        tabent.result= EDSTDIED;
-                       phys_copy(vir2phys(&tabent.result),
-                               tab_phys + i*sizeof(table[0]) +
-                               offsetof(struct asynmsg, result),
-                               sizeof(tabent.result));
+                       A_INSERT(i, result);
                        tabent.flags= flags | AMF_DONE;
-                       phys_copy(vir2phys(&tabent.flags),
-                               tab_phys + i*sizeof(table[0]) +
-                               offsetof(struct asynmsg, flags),
-                               sizeof(tabent.flags));
+                       A_INSERT(i, flags);
 
                        if (flags & AMF_NOTIFY)
                                do_notify= TRUE;
@@ -732,19 +864,12 @@ size_t size;
                        CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr,
                                dst_ptr->p_messbuf);
 
-                       if ((dst_ptr->p_rts_flags &= ~RECEIVING) == 0)
-                               enqueue(dst_ptr);
+                       RTS_UNSET(dst_ptr, RECEIVING);
 
                        tabent.result= OK;
-                       phys_copy(vir2phys(&tabent.result),
-                               tab_phys + i*sizeof(table[0]) +
-                               offsetof(struct asynmsg, result),
-                               sizeof(tabent.result));
+                       A_INSERT(i, result);
                        tabent.flags= flags | AMF_DONE;
-                       phys_copy(vir2phys(&tabent.flags),
-                               tab_phys + i*sizeof(table[0]) +
-                               offsetof(struct asynmsg, flags),
-                               sizeof(tabent.flags));
+                       A_INSERT(i, flags);
 
                        if (flags & AMF_NOTIFY)
                                do_notify= 1;
@@ -759,11 +884,18 @@ size_t size;
                } 
        }
        if (do_notify)
-               kprintf("mini_senda: should notifiy caller\n");
+               kprintf("mini_senda: should notify caller\n");
        if (!done)
        {
                privp->s_asyntab= (vir_bytes)table;
                privp->s_asynsize= size;
+#if 0
+               if(caller_ptr->p_endpoint > INIT_PROC_NR) {
+                       kprintf("kernel: %s (%d) asynsend table at 0x%lx, %d\n", 
+                               caller_ptr->p_name, caller_ptr->p_endpoint,
+                               table, size);
+               }
+#endif
        }
        return OK;
 }
@@ -814,38 +946,27 @@ struct proc *dst_ptr;
        unsigned flags;
        size_t size;
        endpoint_t dst_e;
-       phys_bytes tab_phys;
        asynmsg_t *table_ptr;
        message *m_ptr;
        struct priv *privp;
        asynmsg_t tabent;
+       vir_bytes table_v;
+       struct proc *caller_ptr;
 
        privp= priv(src_ptr);
        size= privp->s_asynsize;
+       table_v = privp->s_asyntab;
+       caller_ptr = src_ptr;
 
        dst_e= dst_ptr->p_endpoint;
 
-       /* Map table */
-       tab_phys= umap_local(src_ptr, D, privp->s_asyntab,
-               size*sizeof(tabent));
-       if (tab_phys == 0)
-       {
-               kprintf("try_one: got bad table pointer/size\n");
-               privp->s_asynsize= 0;
-               if (src_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.bad_buffer++;
-               return EFAULT;
-       }
-
        /* Scan the table */
        do_notify= FALSE;       
        done= TRUE;
        for (i= 0; i<size; i++)
        {
                /* Read status word */
-               phys_copy(tab_phys + i*sizeof(tabent) +
-                       offsetof(struct asynmsg, flags),
-                       vir2phys(&tabent.flags), sizeof(tabent.flags));
+               A_RETRIEVE(i, flags);
                flags= tabent.flags;
 
                /* Skip empty entries */
@@ -877,9 +998,7 @@ struct proc *dst_ptr;
                done= FALSE;
 
                /* Get destination */
-               phys_copy(tab_phys + i*sizeof(tabent) +
-                       offsetof(struct asynmsg, dst),
-                       vir2phys(&tabent.dst), sizeof(tabent.dst));
+               A_RETRIEVE(i, dst);
 
                if (tabent.dst != dst_e)
                {
@@ -895,15 +1014,9 @@ struct proc *dst_ptr;
                        dst_ptr->p_messbuf);
 
                tabent.result= OK;
-               phys_copy(vir2phys(&tabent.result),
-                       tab_phys + i*sizeof(tabent) +
-                       offsetof(struct asynmsg, result),
-                       sizeof(tabent.result));
+               A_INSERT(i, result);
                tabent.flags= flags | AMF_DONE;
-               phys_copy(vir2phys(&tabent.flags),
-                       tab_phys + i*sizeof(tabent) +
-                       offsetof(struct asynmsg, flags),
-                       sizeof(tabent.flags));
+               A_INSERT(i, flags);
 
                if (flags & AMF_NOTIFY)
                {
@@ -941,17 +1054,54 @@ int dst_e;                       /* (endpoint) who is to be notified */
 
   /* Call from task level, locking is required. */
   else {
-      lock(0, "notify");
+      lock;
       result = mini_notify(proc_addr(src), dst); 
-      unlock(0);
+      unlock;
   }
   return(result);
 }
 
+/*===========================================================================*
+ *                             soft_notify                                  *
+ *===========================================================================*/
+PUBLIC int soft_notify(dst_e)
+int dst_e;                     /* (endpoint) who is to be notified */
+{
+       int dst, u = 0;
+       struct proc *dstp, *sys = proc_addr(SYSTEM);
+
+/* Delayed interface to notify() from SYSTEM that is safe/easy to call
+ * from more places than notify().
+ */
+       if(!intr_disabled()) { lock; u = 1; }
+
+       {
+               if(!isokendpt(dst_e, &dst))
+                       minix_panic("soft_notify to dead ep", dst_e);
+
+               dstp = proc_addr(dst);
+
+               if(!dstp->p_softnotified) {
+                       dstp->next_soft_notify = softnotify;
+                       softnotify = dstp;
+                       dstp->p_softnotified = 1;
+       
+                       if (RTS_ISSET(sys, RECEIVING)) {
+                               sys->p_messbuf->m_source = SYSTEM;
+                               RTS_UNSET(sys, RECEIVING);
+                       }
+               }
+       }
+
+       if(u) { unlock; }
+
+       return OK;
+}
+
 /*===========================================================================*
  *                             enqueue                                      * 
  *===========================================================================*/
-PRIVATE void enqueue(rp)
+PUBLIC void enqueue(rp)
 register struct proc *rp;      /* this process is now runnable */
 {
 /* Add 'rp' to one of the queues of runnable processes.  This function is 
@@ -963,8 +1113,9 @@ register struct proc *rp;  /* this process is now runnable */
   int front;                                   /* add to front or back */
 
 #if DEBUG_SCHED_CHECK
-  check_runqueues("enqueue1");
-  if (rp->p_ready) kprintf("enqueue() already ready process\n");
+  if(!intr_disabled()) { minix_panic("enqueue with interrupts enabled", NO_NUM); }
+  CHECK_RUNQUEUES;
+  if (rp->p_ready) minix_panic("enqueue already ready process", NO_NUM);
 #endif
 
   /* Determine where to insert to process. */
@@ -996,14 +1147,14 @@ register struct proc *rp;        /* this process is now runnable */
 
 #if DEBUG_SCHED_CHECK
   rp->p_ready = 1;
-  check_runqueues("enqueue2");
+  CHECK_RUNQUEUES;
 #endif
 }
 
 /*===========================================================================*
  *                             dequeue                                      * 
  *===========================================================================*/
-PRIVATE void dequeue(rp)
+PUBLIC void dequeue(rp)
 register struct proc *rp;      /* this process is no longer runnable */
 {
 /* A process must be removed from the scheduling queues, for example, because
@@ -1017,12 +1168,13 @@ register struct proc *rp;       /* this process is no longer runnable */
   /* Side-effect for kernel: check if the task's stack still is ok? */
   if (iskernelp(rp)) {                                 
        if (*priv(rp)->s_stack_guard != STACK_GUARD)
-               panic("stack overrun by task", proc_nr(rp));
+               minix_panic("stack overrun by task", proc_nr(rp));
   }
 
 #if DEBUG_SCHED_CHECK
-  check_runqueues("dequeue1");
-  if (! rp->p_ready) kprintf("dequeue() already unready process\n");
+  CHECK_RUNQUEUES;
+  if(!intr_disabled()) { minix_panic("dequeue with interrupts enabled", NO_NUM); }
+  if (! rp->p_ready) minix_panic("dequeue() already unready process", NO_NUM);
 #endif
 
   /* Now make sure that the process is not in its ready queue. Remove the 
@@ -1045,7 +1197,7 @@ register struct proc *rp; /* this process is no longer runnable */
 
 #if DEBUG_SCHED_CHECK
   rp->p_ready = 0;
-  check_runqueues("dequeue2");
+  CHECK_RUNQUEUES;
 #endif
 }
 
@@ -1101,12 +1253,16 @@ PRIVATE void pick_proc()
   for (q=0; q < NR_SCHED_QUEUES; q++) {        
       if ( (rp = rdy_head[q]) != NIL_PROC) {
           next_ptr = rp;                       /* run process 'rp' next */
+#if 0
+         if(rp->p_endpoint != 4 && rp->p_endpoint != 5 && rp->p_endpoint != IDLE && rp->p_endpoint != SYSTEM)
+               kprintf("[run %s]",  rp->p_name);
+#endif
           if (priv(rp)->s_flags & BILLABLE)            
               bill_ptr = rp;                   /* bill for system time */
           return;                               
       }
   }
-  panic("no ready process", NO_NUM);
+  minix_panic("no ready process", NO_NUM);
 }
 
 /*===========================================================================*
@@ -1127,7 +1283,7 @@ timer_t *tp;                                      /* watchdog timer pointer */
 
   for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
       if (! isemptyp(rp)) {                            /* check slot use */
-         lock(5,"balance_queues");
+         lock;
          if (rp->p_priority > rp->p_max_priority) {    /* update priority? */
              if (rp->p_rts_flags == 0) dequeue(rp);    /* take off queue */
              ticks_added += rp->p_quantum_size;        /* do accounting */
@@ -1138,7 +1294,7 @@ timer_t *tp;                                      /* watchdog timer pointer */
              ticks_added += rp->p_quantum_size - rp->p_ticks_left;
               rp->p_ticks_left = rp->p_quantum_size;   /* give new quantum */
          }
-         unlock(5);
+         unlock;
       }
   }
 #if DEBUG
@@ -1161,9 +1317,9 @@ message *m_ptr;                   /* pointer to message buffer */
 {
 /* Safe gateway to mini_send() for tasks. */
   int result;
-  lock(2, "send");
-  result = mini_send(proc_ptr, dst_e, m_ptr, NON_BLOCKING);
-  unlock(2);
+  lock;
+  result = mini_send(proc_ptr, dst_e, m_ptr, 0);
+  unlock;
   return(result);
 }
 
@@ -1174,9 +1330,9 @@ PUBLIC void lock_enqueue(rp)
 struct proc *rp;               /* this process is now runnable */
 {
 /* Safe gateway to enqueue() for tasks. */
-  lock(3, "enqueue");
+  lock;
   enqueue(rp);
-  unlock(3);
+  unlock;
 }
 
 /*===========================================================================*
@@ -1192,12 +1348,24 @@ struct proc *rp;                /* this process is no longer runnable */
         */
        dequeue(rp);
   } else {
-       lock(4, "dequeue");
+       lock;
        dequeue(rp);
-       unlock(4);
+       unlock;
   }
 }
 
+/*===========================================================================*
+ *                             endpoint_lookup                              *
+ *===========================================================================*/
+PUBLIC struct proc *endpoint_lookup(endpoint_t e)
+{
+       int n;
+
+       if(!isokendpt(e, &n)) return NULL;
+
+       return proc_addr(n);
+}
+
 /*===========================================================================*
  *                             isokendpt_f                                  *
  *===========================================================================*/
@@ -1228,22 +1396,29 @@ int *p, fatalflag;
        *p = _ENDPOINT_P(e);
        if(!isokprocn(*p)) {
 #if DEBUG_ENABLE_IPC_WARNINGS
+#if 0
                kprintf("kernel:%s:%d: bad endpoint %d: proc %d out of range\n",
                file, line, e, *p);
+#endif
 #endif
        } else if(isemptyn(*p)) {
 #if DEBUG_ENABLE_IPC_WARNINGS
+#if 0
        kprintf("kernel:%s:%d: bad endpoint %d: proc %d empty\n", file, line, e, *p);
+#endif
 #endif
        } else if(proc_addr(*p)->p_endpoint != e) {
 #if DEBUG_ENABLE_IPC_WARNINGS
+#if 0
                kprintf("kernel:%s:%d: bad endpoint %d: proc %d has ept %d (generation %d vs. %d)\n", file, line,
                e, *p, proc_addr(*p)->p_endpoint,
                _ENDPOINT_G(e), _ENDPOINT_G(proc_addr(*p)->p_endpoint));
+#endif
 #endif
        } else ok = 1;
        if(!ok && fatalflag) {
-               panic("invalid endpoint ", e);
+               minix_panic("invalid endpoint ", e);
        }
        return ok;
 }
+
index 39ee9aecbc01d4aec8f4fea1c4eee7fec57d7306..ad5b2b117c58fa1f048eb6fe48fcf04491ce6138 100755 (executable)
@@ -27,6 +27,8 @@ struct proc {
   char p_quantum_size;         /* quantum size in ticks */
 
   struct mem_map p_memmap[NR_LOCAL_SEGS];   /* memory map (T, D, S) */
+  struct pagefault p_pagefault;        /* valid if PAGEFAULT in p_rts_flags set */
+  struct proc *p_nextpagefault;        /* next on PAGEFAULT chain */
 
   clock_t p_user_time;         /* user time in ticks */
   clock_t p_sys_time;          /* sys time in ticks */
@@ -44,6 +46,62 @@ struct proc {
 
   endpoint_t p_endpoint;       /* endpoint number, generation-aware */
 
+  /* If handler functions detect a process wants to do something with
+   * memory that isn't present, VM has to fix it. Until it has asked
+   * what needs to be done and fixed it, save necessary state here.
+   *
+   * The requester gets a copy of its request message in reqmsg and gets
+   * VMREQUEST set.
+   */
+  struct {
+       struct proc     *nextrestart;   /* next in vmrestart chain */
+       struct proc     *nextrequestor; /* next in vmrequest chain */
+#define VMSTYPE_SYS_NONE       0
+#define VMSTYPE_SYS_MESSAGE    1
+#define VMSTYPE_SYS_CALL       2
+#define VMSTYPE_MSGCOPY                3
+       int             type;           /* suspended operation */
+       union {
+               /* VMSTYPE_SYS_MESSAGE */
+               message         reqmsg; /* suspended request message */
+
+               /* VMSTYPE_SYS_CALL */
+               struct {
+                       int call_nr;
+                       message *m_ptr;
+                       int src_dst_e;
+                       long bit_map;
+               } sys_call;
+
+               /* VMSTYPE_MSGCOPY */
+               struct {
+                       struct proc     *dst;
+                       vir_bytes       dst_v;
+                       message         msgbuf;
+               } msgcopy;
+       } saved;
+
+       /* Parameters of request to VM */
+       vir_bytes       start, length;  /* memory range */
+       u8_t            writeflag;      /* nonzero for write access */
+       endpoint_t      who;
+
+       /* VM result when available */
+       int             vmresult;
+
+       /* Target gets this set. (But caller and target can be
+        * the same, so we can't put this in the 'saved' union.)
+       */
+       struct proc     *requestor;
+
+       /* If the suspended operation is a sys_call, its details are
+        * stored here.
+        */
+  } p_vmrequest;
+
+  struct proc *next_soft_notify;
+  int p_softnotified;
+
 #if DEBUG_SCHED_CHECK
   int p_ready, p_found;
 #endif
@@ -59,6 +117,9 @@ struct proc {
 #define P_STOP         0x40    /* set when process is being traced */
 #define NO_PRIV                0x80    /* keep forked system process from running */
 #define NO_ENDPOINT    0x100   /* process cannot send or receive messages */
+#define VMINHIBIT      0x200   /* not scheduled until released by VM */
+#define PAGEFAULT      0x400   /* process has unhandled pagefault */
+#define VMREQUEST      0x800   /* originator of vm memory request */
 
 /* These runtime flags can be tested and manipulated by these macros. */
 
@@ -108,6 +169,7 @@ struct proc {
 #define REPLY_PENDING  0x01    /* reply to IPC_REQUEST is pending */
 #define MF_VM          0x08    /* process uses VM */
 #define MF_ASYNMSG     0x10    /* Asynchrous message pending */
+#define MF_FULLVM      0x20
 
 /* Scheduling priorities for p_priority. Values must start at zero (highest
  * priority) and increment.  Priorities of the processes in the boot image 
index 7e5d6aac8e385da253231aaf04ac807fa689153c..da00010886938f3b78e1b2897c80aa65306ba47e 100644 (file)
@@ -98,14 +98,14 @@ irq_hook_t *hook;
        /* Note: k_reenter is always 0 here. */
 
        /* Store sample (process name and program counter). */
-       phys_copy(vir2phys(proc_ptr->p_name),
-               (phys_bytes) (sprof_data_addr + sprof_info.mem_used),
-               (phys_bytes) strlen(proc_ptr->p_name));
+       data_copy(SYSTEM, (vir_bytes) proc_ptr->p_name,
+               sprof_ep, sprof_data_addr_vir + sprof_info.mem_used,
+               strlen(proc_ptr->p_name));
 
-       phys_copy(vir2phys(&proc_ptr->p_reg.pc),
-               (phys_bytes) (sprof_data_addr+sprof_info.mem_used +
+       data_copy(SYSTEM, (vir_bytes) &proc_ptr->p_reg.pc, sprof_ep,
+               (vir_bytes) (sprof_data_addr_vir + sprof_info.mem_used +
                                        sizeof(proc_ptr->p_name)),
-               (phys_bytes) sizeof(proc_ptr->p_reg.pc));
+               (vir_bytes) sizeof(proc_ptr->p_reg.pc));
 
        sprof_info.mem_used += sizeof(sprof_sample);
 
@@ -159,26 +159,20 @@ PUBLIC void profile_register(ctl_ptr, tbl_ptr)
 void *ctl_ptr;
 void *tbl_ptr;
 {
-  int len, proc_nr;
+  int proc_nr;
   vir_bytes vir_dst;
   struct proc *rp;                          
 
+  if(cprof_procs_no >= NR_SYS_PROCS)
+       return;
+
   /* Store process name, control struct, table locations. */
-  proc_nr = KERNEL;
-  rp = proc_addr(proc_nr);
+  rp = proc_addr(SYSTEM);
 
   cprof_proc_info[cprof_procs_no].endpt = rp->p_endpoint;
   cprof_proc_info[cprof_procs_no].name = rp->p_name;
-
-  len = (phys_bytes) sizeof (void *);
-
-  vir_dst = (vir_bytes) ctl_ptr;
-  cprof_proc_info[cprof_procs_no].ctl =
-         numap_local(proc_nr, vir_dst, len);
-
-  vir_dst = (vir_bytes) tbl_ptr;
-  cprof_proc_info[cprof_procs_no].buf =
-         numap_local(proc_nr, vir_dst, len);
+  cprof_proc_info[cprof_procs_no].ctl_v = (vir_bytes) ctl_ptr;
+  cprof_proc_info[cprof_procs_no].buf_v = (vir_bytes) tbl_ptr;
 
   cprof_procs_no++;
 }
index 048e00c0d51fbcd97713fd0109579f11d2a9bdee..a8c29ed7d834c590e6140dd9148a7acdbaaf3ef2 100644 (file)
@@ -10,8 +10,8 @@
 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 */
-EXTERN phys_bytes sprof_data_addr;     /* user address to write data */
-EXTERN phys_bytes sprof_info_addr;     /* user address to write info struct */
+EXTERN vir_bytes sprof_data_addr_vir;  /* user address to write data */
+EXTERN endpoint_t sprof_ep;            /* user process */
 
 #endif /* SPROFILE */
 
@@ -20,14 +20,12 @@ EXTERN phys_bytes sprof_info_addr;  /* user address to write info struct */
 
 EXTERN int cprof_mem_size;             /* available user memory for data */
 EXTERN struct cprof_info_s cprof_info; /* profiling info for user program */
-EXTERN phys_bytes cprof_data_addr;     /* user address to write data */
-EXTERN phys_bytes cprof_info_addr;     /* user address to write info struct */
 EXTERN int cprof_procs_no;             /* number of profiled processes */
 EXTERN struct cprof_proc_info_s {      /* info about profiled process */
-       int endpt;                      /* endpoint */
+       endpoint_t endpt;               /* endpoint */
        char *name;                     /* name */
-       phys_bytes ctl;                 /* location of control struct */
-       phys_bytes buf;                 /* location of buffer */
+       vir_bytes ctl_v;                /* location of control struct */
+       vir_bytes buf_v;                /* location of buffer */
        int slots_used;                 /* table slots used */
 } cprof_proc_info_inst;
 EXTERN struct cprof_proc_info_s cprof_proc_info[NR_SYS_PROCS]; 
index bab60aa33b623a54814fc35ad82f53b4c459fd54..f8ea886aa15ec5ddfeadbaae03c76ec8fafbf782 100755 (executable)
@@ -5,6 +5,7 @@
 
 #include <minix/safecopies.h>
 #include <archtypes.h>
+#include <a.out.h>
 
 /* Struct declarations. */
 struct proc;
@@ -20,20 +21,26 @@ _PROTOTYPE( void ser_dump_proc, (void)                                      );
 /* main.c */
 _PROTOTYPE( void main, (void)                                          );
 _PROTOTYPE( void prepare_shutdown, (int how)                           );
+_PROTOTYPE( void minix_shutdown, (struct timer *tp)                    );
 _PROTOTYPE( void idle_task, (void)                                     );
 
 /* utility.c */
 _PROTOTYPE( int kprintf, (const char *fmt, ...)                                );
-_PROTOTYPE( void panic, (_CONST char *s, int n)                                );
+_PROTOTYPE( void minix_panic, (char *s, int n)                         );
 
 /* proc.c */
 _PROTOTYPE( int sys_call, (int call_nr, int src_dst, 
                                        message *m_ptr, long bit_map)   );
+_PROTOTYPE( void sys_call_restart, (struct proc *caller)               );
 _PROTOTYPE( int lock_notify, (int src, int dst)                                );
+_PROTOTYPE( int soft_notify, (int dst)                                 );
 _PROTOTYPE( int lock_send, (int dst, message *m_ptr)                   );
 _PROTOTYPE( void lock_enqueue, (struct proc *rp)                       );
 _PROTOTYPE( void lock_dequeue, (struct proc *rp)                       );
+_PROTOTYPE( void enqueue, (struct proc *rp)                            );
+_PROTOTYPE( void dequeue, (struct proc *rp)                            );
 _PROTOTYPE( void balance_queues, (struct timer *tp)                    );
+_PROTOTYPE( struct proc *endpoint_lookup, (endpoint_t ep)              );
 #if DEBUG_ENABLE_IPC_WARNINGS
 _PROTOTYPE( int isokendpt_f, (char *file, int line, endpoint_t e, int *p, int f));
 #define isokendpt_d(e, p, f) isokendpt_f(__FILE__, __LINE__, (e), (p), (f))
@@ -52,17 +59,16 @@ _PROTOTYPE( void send_sig, (int proc_nr, int sig_nr)                        );
 _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr)                  );
 _PROTOTYPE( void sys_task, (void)                                      );
 _PROTOTYPE( void get_randomness, (int source)                          );
-_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_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( vir_bytes vir_verify_grant, (struct proc *, endpoint_t,
+       cp_grant_id_t, vir_bytes, vir_bytes, int, endpoint_t *));
 _PROTOTYPE( void clear_endpoint, (struct proc *rc)                     );
-_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
-       vir_bytes bytes));
+_PROTOTYPE( phys_bytes umap_bios, (vir_bytes vir_addr, vir_bytes bytes));
+_PROTOTYPE( phys_bytes umap_verify_grant, (struct proc *rp, endpoint_t grantee,  cp_grant_id_t grant, vir_bytes offset, vir_bytes bytes, int access));
+
 
 /* system/do_newmap.c */
 _PROTOTYPE( int newmap, (struct proc *rp, struct mem_map *map_ptr)     );
@@ -79,11 +85,11 @@ _PROTOTYPE( void cons_seth, (int pos, int n)                                );
 
 /* debug.c */
 #if DEBUG_SCHED_CHECK
-_PROTOTYPE( void check_runqueues, (char *when) );
+#define CHECK_RUNQUEUES check_runqueues_f(__FILE__, __LINE__)
+_PROTOTYPE( void check_runqueues_f, (char *file, int line) );
 #endif
-
-/* system/do_vm.c */
-_PROTOTYPE( void vm_map_default, (struct proc *pp)                     );
+_PROTOTYPE( void timer_start, (int cat, char *name) );
+_PROTOTYPE( void timer_end, (int cat) );
 
 /* system/do_safecopy.c */
 _PROTOTYPE( int verify_grant, (endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes,
@@ -98,15 +104,27 @@ _PROTOTYPE( void stop_profile_clock, (void)                                );
 /* functions defined in architecture-dependent files. */
 _PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
                 phys_bytes count)                                       );
+#define virtual_copy(src, dst, bytes) virtual_copy_f(src, dst, bytes, 0)
+#define virtual_copy_vmcheck(src, dst, bytes) virtual_copy_f(src, dst, bytes, 1)
+_PROTOTYPE( int virtual_copy_f, (struct vir_addr *src, struct vir_addr *dst, 
+                               vir_bytes bytes, int vmcheck)           );
+_PROTOTYPE( int data_copy, (endpoint_t from, vir_bytes from_addr,
+       endpoint_t to, vir_bytes to_addr, size_t bytes));
+#define data_copy_to(d, p, v, n) data_copy(SYSTEM, (d), (p), (v), (n));
+#define data_copy_from(d, p, v, n) data_copy((p), (v), SYSTEM, (d), (n));
 _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( int vm_copy, (vir_bytes src, struct proc *srcproc,
+       vir_bytes dst, struct proc *dstproc, phys_bytes bytes));
 _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 umap_virtual, (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)                                       );
@@ -123,6 +141,7 @@ _PROTOTYPE( void idle_task, (void)                                     );
 _PROTOTYPE( void system_init, (void)                                     );
 _PROTOTYPE( void ser_putc, (char)                                              );
 _PROTOTYPE( void arch_shutdown, (int)                                  );
+_PROTOTYPE( void arch_get_aout_headers, (int i, struct exec *h)                );
 _PROTOTYPE( void restart, (void)                                        );
 _PROTOTYPE( void idle_task, (void)                                     );
 _PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low)    );
@@ -130,5 +149,16 @@ _PROTOTYPE( int arch_init_profile_clock, (u32_t freq)                      );
 _PROTOTYPE( void arch_stop_profile_clock, (void)                       );
 _PROTOTYPE( void arch_ack_profile_clock, (void)                                );
 _PROTOTYPE( void do_ser_debug, (void)                                  );
+_PROTOTYPE( int arch_get_params, (char *parm, int max));
+_PROTOTYPE( int arch_set_params, (char *parm, int max));
+_PROTOTYPE( int arch_pre_exec, (struct proc *pr, u32_t, u32_t));
+_PROTOTYPE( int arch_umap, (struct proc *pr, vir_bytes, vir_bytes,
+       int, phys_bytes *));
+_PROTOTYPE( int arch_do_vmctl, (message *m_ptr, struct proc *p)); 
+_PROTOTYPE( int vm_contiguous, (struct proc *targetproc, u32_t vir_buf, size_t count));
+_PROTOTYPE( int vm_checkrange, (struct proc *caller, struct proc *target, 
+       vir_bytes start, vir_bytes length, int writeflag, int checkonly));
+_PROTOTYPE( void proc_stacktrace, (struct proc *proc)           );
+_PROTOTYPE( int vm_lookup, (struct proc *proc, vir_bytes virtual, vir_bytes *result, u32_t *ptent));
 
 #endif /* PROTO_H */
index 4b8fedf85ba8c78d46c2ac43b8fe27b037cfaf8c..36b27d58552ecf33988ae0d5f39d356c2f493ab5 100755 (executable)
@@ -7,8 +7,6 @@
 #include <string.h>
 #include <archconst.h>
 
-PRIVATE char params[K_PARAM_SIZE];
-
 FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key));
 /*===========================================================================*
  *                             cstart                                       *
@@ -21,7 +19,6 @@ U16_t parmoff, parmsize;      /* boot parameters offset and length */
 /* Perform system initializations prior to calling main(). Most settings are
  * determined with help of the environment strings passed by MINIX' loader.
  */
-  char params[128*sizeof(char *)];             /* boot monitor parameters */
   register char *value;                                /* value in key=value pair */
   extern int etext, end;
   int h;
@@ -36,10 +33,7 @@ U16_t parmoff, parmsize;     /* boot parameters offset and length */
   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);
+  arch_get_params(params_buffer, sizeof(params_buffer));
 
   /* Record miscellaneous information for user-space servers. */
   kinfo.nr_procs = NR_PROCS;
@@ -49,8 +43,6 @@ U16_t parmoff, parmsize;      /* boot parameters offset and length */
   strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
   kinfo.version[sizeof(kinfo.version)-1] = '\0';
   kinfo.proc_addr = (vir_bytes) proc;
-  kinfo.kmem_base = vir2phys(0);
-  kinfo.kmem_size = (phys_bytes) &end; 
 
   /* Load average data initialization. */
   kloadinfo.proc_last_slot = 0;
@@ -58,10 +50,10 @@ U16_t parmoff, parmsize;    /* boot parameters offset and length */
        kloadinfo.proc_load_history[h] = 0;
 
   /* Processor? Decide if mode is protected for older machines. */
-  machine.processor=atoi(get_value(params, "processor")); 
+  machine.processor=atoi(get_value(params_buffer, "processor")); 
 
   /* XT, AT or MCA bus? */
-  value = get_value(params, "bus");
+  value = get_value(params_buffer, "bus");
   if (value == NIL_PTR || strcmp(value, "at") == 0) {
       machine.pc_at = TRUE;                    /* PC-AT compatible hardware */
   } else if (strcmp(value, "mca") == 0) {
@@ -69,7 +61,7 @@ U16_t parmoff, parmsize;      /* boot parameters offset and length */
   }
 
   /* Type of VDU: */
-  value = get_value(params, "video");          /* EGA or VGA video unit */
+  value = get_value(params_buffer, "video");   /* EGA or VGA video unit */
   if (strcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
   if (strcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
 
index 16541711b7640ec5637f49722acdfbc12d07b870..e3921075757f45f4ac08fb77be6c9c3b16792885 100755 (executable)
@@ -15,7 +15,6 @@
  *   send_sig:         send a signal directly to a system process
  *   cause_sig:                take action to cause a signal to occur via PM
  *   umap_bios:                map virtual address in BIOS_SEG 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
  *
 #include "kernel.h"
 #include "system.h"
 #include "proc.h"
+#include "vm.h"
 #include <stdlib.h>
 #include <signal.h>
 #include <unistd.h>
+#include <string.h>
 #include <sys/sigcontext.h>
 #include <minix/endpoint.h>
 #include <minix/safecopies.h>
 #include <minix/u64.h>
+#include <sys/vm_i386.h>
 
 /* Declaration of the call vector that defines the mapping of system calls 
  * to handler functions. The vector is initialized in sys_init() with map(), 
  * array size will be negative and this won't compile. 
  */
 PUBLIC int (*call_vec[NR_SYS_CALLS])(message *m_ptr);
+char *callnames[NR_SYS_CALLS];
 
 #define map(call_nr, handler) \
     {extern int dummy[NR_SYS_CALLS>(unsigned)(call_nr-KERNEL_CALL) ? 1:-1];} \
+    callnames[(call_nr-KERNEL_CALL)] = #call_nr;       \
     call_vec[(call_nr-KERNEL_CALL)] = (handler)  
 
 FORWARD _PROTOTYPE( void initialize, (void));
+FORWARD _PROTOTYPE( void softnotify_check, (void));
+FORWARD _PROTOTYPE( struct proc *vmrestart_check, (message *));
 
 /*===========================================================================*
  *                             sys_task                                     *
@@ -64,14 +70,39 @@ PUBLIC void sys_task()
   register struct proc *caller_ptr;
   int s;
   int call_nr;
+  int n = 0;
 
   /* Initialize the system task. */
   initialize();
 
   while (TRUE) {
-      int r;
-      /* Get work. Block and wait until a request message arrives. */
-      if((r=receive(ANY, &m)) != OK) panic("system: receive() failed", r);
+      struct proc *restarting;
+
+#if 0
+if(!(n++ % 100000)) {
+       int i;
+       kprintf("switch %8d reload %8d\n", cr3switch, cr3reload);
+}
+#endif
+
+      restarting = vmrestart_check(&m);
+      softnotify_check();
+       if(softnotify)
+               minix_panic("softnotify non-NULL before receive (1)", NO_NUM);
+
+      if(!restarting) {
+        int r;
+       /* Get work. Block and wait until a request message arrives. */
+       if(softnotify)
+               minix_panic("softnotify non-NULL before receive (2)", NO_NUM);
+       if((r=receive(ANY, &m)) != OK)
+               minix_panic("receive() failed", r);
+       if(m.m_source == SYSTEM)
+               continue;
+       if(softnotify)
+               minix_panic("softnotify non-NULL after receive", NO_NUM);
+      }
+
       sys_call_code = (unsigned) m.m_type;
       call_nr = sys_call_code - KERNEL_CALL;   
       who_e = m.m_source;
@@ -115,16 +146,34 @@ PUBLIC void sys_task()
           result = (*call_vec[call_nr])(&m); /* handle the system call */
       }
 
-      /* Send a reply, unless inhibited by a handler function. Use the kernel
-       * function lock_send() to prevent a system call trap. The destination
-       * is known to be blocked waiting for a message.
-       */
-      if (result != EDONTREPLY) {
-         m.m_type = result;                    /* report status of call */
-          if (OK != (s=lock_send(m.m_source, &m))) {
-              kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s);
-          }
-      }
+      if(result == VMSUSPEND) {
+       /* Special case: message has to be saved for handling
+        * until VM tells us it's allowed. VM has been notified
+        * and we must wait for its reply to restart the call.
+        */
+       memcpy(&caller_ptr->p_vmrequest.saved.reqmsg, &m, sizeof(m));
+       caller_ptr->p_vmrequest.type = VMSTYPE_SYS_MESSAGE;
+#if 0
+       kprintf("SYSTEM: suspending call from %d\n", m.m_source);
+#endif
+      } else if (result != EDONTREPLY) {
+       /* Send a reply, unless inhibited by a handler function.
+        * Use the kernel function lock_send() to prevent a system
+        * call trap.
+        */
+               if(restarting)
+                       RTS_LOCK_UNSET(restarting, VMREQUEST);
+               m.m_type = result;              /* report status of call */
+               if(WILLRECEIVE(caller_ptr, SYSTEM)) {
+                 if (OK != (s=lock_send(m.m_source, &m))) {
+                       kprintf("SYSTEM, reply to %d failed: %d\n",
+                       m.m_source, s);
+                 }
+               } else {
+                       kprintf("SYSTEM: not replying to %d; not ready\n", 
+                               caller_ptr->p_endpoint);
+               }
+       }
   }
 }
 
@@ -153,6 +202,7 @@ PRIVATE void initialize(void)
    */
   for (i=0; i<NR_SYS_CALLS; i++) {
       call_vec[i] = do_unused;
+      callnames[i] = "unused";
   }
 
   /* Process management. */
@@ -181,14 +231,14 @@ PRIVATE void initialize(void)
   map(SYS_SEGCTL, do_segctl);          /* add segment and get selector */
   map(SYS_MEMSET, do_memset);          /* write char to memory area */
   map(SYS_VM_SETBUF, do_vm_setbuf);    /* PM passes buffer for page tables */
-  map(SYS_VM_MAP, do_vm_map);          /* Map/unmap physical (device) memory */
+  map(SYS_VMCTL, do_vmctl);            /* various VM process settings */
 
   /* Copying. */
   map(SYS_UMAP, do_umap);              /* map virtual to physical address */
   map(SYS_VIRCOPY, do_vircopy);        /* use pure virtual addressing */
-  map(SYS_PHYSCOPY, do_physcopy);      /* use physical addressing */
+  map(SYS_PHYSCOPY, do_copy);          /* use physical addressing */
   map(SYS_VIRVCOPY, do_virvcopy);      /* vector with copy requests */
-  map(SYS_PHYSVCOPY, do_physvcopy);    /* vector with copy requests */
+  map(SYS_PHYSVCOPY, do_vcopy);                /* vector with copy requests */
   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 */
@@ -279,19 +329,16 @@ PUBLIC void send_sig(int proc_nr, int sig_nr)
 /* Notify a system process about a signal. This is straightforward. Simply
  * set the signal that is to be delivered in the pending signals map and 
  * send a notification with source SYSTEM.
- *
- * Process number is verified to avoid writing in random places, but we
- * don't kprintf() or panic() because that causes send_sig() invocations.
  */ 
   register struct proc *rp;
   static int n;
 
   if(!isokprocn(proc_nr) || isemptyn(proc_nr))
-       return;
+       minix_panic("send_sig to empty process", proc_nr);
 
   rp = proc_addr(proc_nr);
   sigaddset(&priv(rp)->s_sig_pending, sig_nr);
-  lock_notify(SYSTEM, rp->p_endpoint); 
+  soft_notify(rp->p_endpoint); 
 }
 
 /*===========================================================================*
@@ -317,7 +364,7 @@ int sig_nr;                 /* signal to be sent, 1 to _NSIG */
   register struct proc *rp;
 
   if (proc_nr == PM_PROC_NR)
-       panic("cause_sig: PM gets signal", NO_NUM);
+       minix_panic("cause_sig: PM gets signal", NO_NUM);
 
   /* Check if the signal is already pending. Process it otherwise. */
   rp = proc_addr(proc_nr);
@@ -335,8 +382,7 @@ int sig_nr;                 /* signal to be sent, 1 to _NSIG */
 /*===========================================================================*
  *                             umap_bios                                    *
  *===========================================================================*/
-PUBLIC phys_bytes umap_bios(rp, vir_addr, bytes)
-register struct proc *rp;      /* pointer to proc table entry for process */
+PUBLIC phys_bytes umap_bios(vir_addr, bytes)
 vir_bytes vir_addr;            /* virtual address in BIOS segment */
 vir_bytes bytes;               /* # of bytes to be copied */
 {
@@ -358,37 +404,6 @@ vir_bytes bytes;           /* # of bytes to be copied */
 }
 #endif
 
-/*===========================================================================*
- *                             umap_verify_grant                            *
- *===========================================================================*/
-PUBLIC phys_bytes umap_verify_grant(rp, grantee, grant, offset, bytes, access)
-struct proc *rp;               /* pointer to proc table entry for process */
-endpoint_t grantee;            /* who wants to do this */
-cp_grant_id_t grant;           /* grant no. */
-vir_bytes offset;              /* offset into grant */
-vir_bytes bytes;               /* size */
-int access;                    /* does grantee want to CPF_READ or _WRITE? */
-{
-       int proc_nr;
-       vir_bytes v_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, grantee, grant, bytes, access, offset,
-               &v_offset, &granter) != OK
-          || !isokendpt(granter, &proc_nr)) {
-               return 0;
-       }
-
-       /* Do the mapping from virtual to physical. */
-       return umap_local(proc_addr(proc_nr), D, v_offset, bytes);
-}
-
 /*===========================================================================*
  *                              umap_grant                                   *
  *===========================================================================*/
@@ -398,9 +413,9 @@ cp_grant_id_t grant;            /* grant no. */
 vir_bytes bytes;                /* size */
 {
         int proc_nr;
-        vir_bytes offset;
+        vir_bytes offset, ret;
         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.
@@ -409,88 +424,25 @@ vir_bytes bytes;                /* size */
          */
         if(verify_grant(rp->p_endpoint, ANY, grant, bytes, 0, 0,
                 &offset, &granter) != OK) {
+               kprintf("SYSTEM: umap_grant: verify_grant failed\n");
                 return 0;
         }
 
         if(!isokendpt(granter, &proc_nr)) {
+               kprintf("SYSTEM: umap_grant: isokendpt failed\n");
                 return 0;
         }
  
         /* Do the mapping from virtual to physical. */
-        return umap_local(proc_addr(proc_nr), D, offset, bytes);
-}
-
-/*===========================================================================*
- *                             virtual_copy                                 *
- *===========================================================================*/
-PUBLIC int virtual_copy(src_addr, dst_addr, bytes)
-struct vir_addr *src_addr;     /* source virtual address */
-struct vir_addr *dst_addr;     /* destination virtual address */
-vir_bytes bytes;               /* # of bytes to copy  */
-{
-/* Copy bytes from virtual address src_addr to virtual address dst_addr. 
- * Virtual addresses can be in ABS, LOCAL_SEG, REMOTE_SEG, or BIOS_SEG.
- */
-  struct vir_addr *vir_addr[2];        /* virtual source and destination address */
-  phys_bytes phys_addr[2];     /* absolute source and destination */ 
-  int seg_index;
-  int i;
-
-  /* Check copy count. */
-  if (bytes <= 0) return(EDOM);
-
-  /* Do some more checks and map virtual addresses to physical addresses. */
-  vir_addr[_SRC_] = src_addr;
-  vir_addr[_DST_] = dst_addr;
-  for (i=_SRC_; i<=_DST_; i++) {
-       int proc_nr, type;
-       struct proc *p;
-
-       type = vir_addr[i]->segment & SEGMENT_TYPE;
-       if(type != PHYS_SEG && isokendpt(vir_addr[i]->proc_nr_e, &proc_nr))
-          p = proc_addr(proc_nr);
-       else
-          p = NULL;
-
-      /* Get physical address. */
-      switch(type) {
-      case LOCAL_SEG:
-         if(!p) return EDEADSRCDST;
-          seg_index = vir_addr[i]->segment & SEGMENT_INDEX;
-          phys_addr[i] = umap_local(p, seg_index, vir_addr[i]->offset, bytes);
-          break;
-      case REMOTE_SEG:
-         if(!p) return EDEADSRCDST;
-          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;
-      case GRANT_SEG:
-         phys_addr[i] = umap_grant(p, vir_addr[i]->offset, bytes);
-         break;
-      default:
-          return(EINVAL);
-      }
-
-      /* Check if mapping succeeded. */
-      if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) 
-          return(EFAULT);
-  }
-
-  /* Now copy bytes between physical addresseses. */
-  phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes);
-  return(OK);
+        ret = umap_virtual(proc_addr(proc_nr), D, offset, bytes);
+       if(!ret) {
+               kprintf("SYSTEM:umap_grant:umap_virtual failed; grant %s:%d -> %s: vir 0x%lx\n",
+                       rp->p_name, grant, 
+                       proc_addr(proc_nr)->p_name, offset);
+       }
+       return ret;
 }
 
-
 /*===========================================================================*
  *                              clear_endpoint                              *
  *===========================================================================*/
@@ -499,8 +451,22 @@ 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 */
+  struct proc *np;
 
-  if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc));
+  if(isemptyp(rc)) minix_panic("clear_proc: empty process", proc_nr(rc));
+
+#if 1
+  if(rc->p_endpoint == PM_PROC_NR || rc->p_endpoint == VFS_PROC_NR) {
+       /* This test is great for debugging system processes dying,
+        * but as this happens normally on reboot, not good permanent code.
+        */
+       kprintf("process %s / %d died; stack: ", rc->p_name, rc->p_endpoint);
+       proc_stacktrace(rc);
+       kprintf("kernel trace: ");
+       util_stacktrace();
+       minix_panic("clear_proc: system process died", rc->p_endpoint);
+  }
+#endif
 
   /* Make sure that the exiting process is no longer scheduled. */
   RTS_LOCK_SET(rc, NO_ENDPOINT);
@@ -550,7 +516,8 @@ register struct proc *rc;           /* slot of process to clean up */
           rp->p_reg.retreg = ESRCDIED;         /* report source died */
          RTS_LOCK_UNSET(rp, RECEIVING);        /* no longer receiving */
 #if DEBUG_ENABLE_IPC_WARNINGS
-         kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc));
+         kprintf("Proc %d (%s) receiving from dead src %d (%s)\n",
+               proc_nr(rp), rp->p_name, proc_nr(rc), rc->p_name);
 #endif
       } 
       if (RTS_ISSET(rp, SENDING) &&
@@ -558,8 +525,147 @@ register struct proc *rc;         /* slot of process to clean up */
           rp->p_reg.retreg = EDSTDIED;         /* report destination died */
          RTS_LOCK_UNSET(rp, SENDING);
 #if DEBUG_ENABLE_IPC_WARNINGS
-         kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc));
+         kprintf("Proc %d (%s) send to dying dst %d (%s)\n",
+               proc_nr(rp), rp->p_name, proc_nr(rc), rc->p_name);
 #endif
       } 
   }
+
+  /* No pending soft notifies. */
+  for(np = softnotify; np; np = np->next_soft_notify) {
+    if(np == rc) {
+       minix_panic("dying proc was on next_soft_notify", np->p_endpoint);
+    }
+  }
+}
+
+/*===========================================================================*
+ *                              umap_verify_grant                            *
+ *===========================================================================*/
+PUBLIC phys_bytes umap_verify_grant(rp, grantee, grant, offset, bytes, access)
+struct proc *rp;                /* pointer to proc table entry for process */
+endpoint_t grantee;             /* who wants to do this */ 
+cp_grant_id_t grant;            /* grant no. */
+vir_bytes offset;               /* offset into grant */
+vir_bytes bytes;                /* size */
+int access;                     /* does grantee want to CPF_READ or _WRITE? */
+{  
+        int proc_nr;
+        vir_bytes v_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, grantee, grant, bytes, access, offset, 
+                &v_offset, &granter) != OK
+           || !isokendpt(granter, &proc_nr)) {
+                return 0;
+        }
+  
+        /* Do the mapping from virtual to physical. */
+        return umap_virtual(proc_addr(proc_nr), D, v_offset, bytes);
+} 
+
+/*===========================================================================*
+ *                              softnotify_check                            *
+ *===========================================================================*/
+PRIVATE void softnotify_check(void)
+{  
+       struct proc *np, *nextnp;
+
+       if(!softnotify) 
+               return;
+
+       for(np = softnotify; np; np = nextnp) {
+               if(!np->p_softnotified)
+                       minix_panic("softnotify but no p_softnotified", NO_NUM);
+               lock_notify(SYSTEM, np->p_endpoint);
+               nextnp = np->next_soft_notify;
+               np->next_soft_notify = NULL;
+               np->p_softnotified = 0;
+       }
+
+       softnotify = NULL;
+}
+
+/*===========================================================================*
+ *                              vmrestart_check                            *
+ *===========================================================================*/
+PRIVATE struct proc *vmrestart_check(message *m)
+{
+       int type, r;
+       struct proc *restarting;
+
+      /* Anyone waiting to be vm-restarted? */
+
+       if(!(restarting = vmrestart))
+               return NULL;
+
+       if(restarting->p_rts_flags & SLOT_FREE)
+          minix_panic("SYSTEM: VMREQUEST set for empty process", NO_NUM);
+
+       type = restarting->p_vmrequest.type;
+       restarting->p_vmrequest.type = VMSTYPE_SYS_NONE;
+       vmrestart = restarting->p_vmrequest.nextrestart;
+
+       if(!RTS_ISSET(restarting, VMREQUEST))
+          minix_panic("SYSTEM: VMREQUEST not set for process on vmrestart queue",
+               restarting->p_endpoint);
+
+       switch(type) {
+               case VMSTYPE_SYS_MESSAGE:
+                       memcpy(m, &restarting->p_vmrequest.saved.reqmsg, sizeof(*m));
+#if 0
+                       kprintf("SYSTEM: restart sys_message type %d / %lx source %d\n",
+                               m->m_type, m->m_type, m->m_source);
+#endif
+                       if(m->m_source != restarting->p_endpoint)
+                          minix_panic("SYSTEM: vmrestart source doesn't match",
+                               NO_NUM);
+                       /* Original caller could've disappeared in the meantime. */
+                       if(!isokendpt(m->m_source, &who_p)) {
+                               kprintf("SYSTEM: ignoring call %d from dead %d\n",
+                                       m->m_type, m->m_source);
+                               return NULL;
+                       }
+                       { int i;
+                               i = m->m_type - KERNEL_CALL;
+                               if(i >= 0 && i < NR_SYS_CALLS) {
+#if 0
+                                       kprintf("SYSTEM: restart %s from %d\n",
+                                       callnames[i], m->m_source);
+#endif
+                               } else {
+                                       minix_panic("call number out of range", i);
+                               }
+                       }
+                       return restarting;
+               case VMSTYPE_SYS_CALL:
+                       kprintf("SYSTEM: restart sys_call\n");
+                       /* Restarting a kernel trap. */
+                       sys_call_restart(restarting);
+
+                       /* Handled; restart system loop. */
+                       return NULL;
+               case VMSTYPE_MSGCOPY:
+                       /* Do delayed message copy. */
+                       if((r=data_copy(SYSTEM,
+                               (vir_bytes) &restarting->p_vmrequest.saved.msgcopy.msgbuf,
+                               restarting->p_vmrequest.saved.msgcopy.dst->p_endpoint,
+                               (vir_bytes) restarting->p_vmrequest.saved.msgcopy.dst_v,
+                               sizeof(message))) != OK) {
+                               minix_panic("SYSTEM: delayed msgcopy failed", r);
+                       }
+                       RTS_LOCK_UNSET(restarting, VMREQUEST);
+
+                       /* Handled; restart system loop. */
+                       return NULL;
+               default:
+                       minix_panic("strange restart type", type);
+       }
+       minix_panic("fell out of switch", NO_NUM);
 }
index 0cf60fa7dab90f6514b7d1a0e5bdada0c9d199e7..3f187ca707754c688aef969e8c9c16d3f4feb1ae 100644 (file)
@@ -71,14 +71,12 @@ _PROTOTYPE( int do_nice, (message *m_ptr) );
 
 _PROTOTYPE( int do_copy, (message *m_ptr) );   
 #define do_vircopy     do_copy
-#define do_physcopy    do_copy
 #if ! (USE_VIRCOPY || USE_PHYSCOPY)
 #define do_copy do_unused
 #endif
 
 _PROTOTYPE( int do_vcopy, (message *m_ptr) );          
 #define do_virvcopy    do_vcopy
-#define do_physvcopy   do_vcopy
 #if ! (USE_VIRVCOPY || USE_PHYSVCOPY)
 #define do_vcopy do_unused
 #endif
@@ -178,8 +176,10 @@ _PROTOTYPE( int do_stime, (message *m_ptr) );
 _PROTOTYPE( int do_safecopy, (message *m_ptr) );       
 _PROTOTYPE( int do_vsafecopy, (message *m_ptr) );      
 _PROTOTYPE( int do_iopenable, (message *m_ptr) );      
+_PROTOTYPE( int do_vmctl, (message *m_ptr) );  
 _PROTOTYPE( int do_setgrant, (message *m_ptr) );       
 _PROTOTYPE( int do_readbios, (message *m_ptr) );       
+_PROTOTYPE( int do_mapdma, (message *m_ptr) ); 
 
 _PROTOTYPE( int do_sprofile, (message *m_ptr) );
 #if ! SPROFILE
index c6a4a0f6628a8e9d2791abb8cd91cde32decfe0b..6f65a6407ecbfaa6d26dcd1caa85337aceb03ab7 100644 (file)
@@ -50,12 +50,12 @@ OBJECTS     = \
        $(SYSTEM)(do_sigreturn.o) \
        $(SYSTEM)(do_abort.o) \
        $(SYSTEM)(do_getinfo.o) \
-       $(SYSTEM)(do_vm.o) \
        $(SYSTEM)(do_vm_setbuf.o) \
        $(SYSTEM)(do_sprofile.o) \
        $(SYSTEM)(do_cprofile.o) \
        $(SYSTEM)(do_profbuf.o) \
-       $(SYSTEM)(do_mapdma.o) 
+       $(SYSTEM)(do_mapdma.o) \
+       $(SYSTEM)(do_vmctl.o)
 
 build $(SYSTEM):       $(OBJECTS)
        aal cr $@ *.o
@@ -172,3 +172,6 @@ $(SYSTEM)(do_profbuf.o):        do_profbuf.c
 
 $(SYSTEM)(do_mapdma.o):        do_mapdma.c
        $(CC) do_mapdma.c
+
+$(SYSTEM)(do_vmctl.o):        do_vmctl.c
+       $(CC) do_vmctl.c
index d0b32b516702a0ed66d9d1fde95653ba97950579..9223dfe391706a0419ad23801a7397f18489dd98 100644 (file)
@@ -23,21 +23,25 @@ message *m_ptr;                     /* pointer to request message */
  * in the PM (normal abort or panic) or TTY (after CTRL-ALT-DEL).
  */
   int how = m_ptr->ABRT_HOW;
-  int proc_nr;
   int length;
   phys_bytes src_phys;
 
   /* See if the monitor is to run the specified instructions. */
   if (how == RBT_MONITOR) {
+      int p;
+      static char paramsbuffer[512];
+      int len;
+      len = MIN(m_ptr->ABRT_MON_LEN, sizeof(paramsbuffer)-1);
 
-      if(!isokendpt(m_ptr->ABRT_MON_ENDPT, &proc_nr)) return(EDEADSRCDST);
-      length = m_ptr->ABRT_MON_LEN + 1;
-      if (length > kinfo.params_size) return(E2BIG);
-      src_phys = numap_local(proc_nr,(vir_bytes)m_ptr->ABRT_MON_ADDR,length);
-      if (! src_phys) return(EFAULT);
+      if((p=data_copy(m_ptr->ABRT_MON_ENDPT, (vir_bytes) m_ptr->ABRT_MON_ADDR,
+               SYSTEM, (vir_bytes) paramsbuffer, len)) != OK) {
+               return p;
+      }
+      paramsbuffer[len] = '\0';
 
       /* Parameters seem ok, copy them and prepare shutting down. */
-      phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
+      if((p = arch_set_params(paramsbuffer, len+1)) != OK)
+       return p;
   }
 
   /* Now prepare to shutdown MINIX. */
index 716ec1a85989341d4be829d703ddcd5634e1916d..93df4b7f177b83fe8cc971aaab13fd501773208b 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include "../system.h"
+#include "../vm.h"
 #include <minix/type.h>
 
 #if (USE_VIRCOPY || USE_PHYSCOPY)
@@ -30,8 +31,9 @@ register message *m_ptr;      /* pointer to request message */
   phys_bytes bytes;            /* number of bytes to copy */
   int i;
 
-  if (m_ptr->m_source != 0 && m_ptr->m_source != 1 &&
-       m_ptr->m_source != 2 && m_ptr->m_source != 3)
+  if (m_ptr->m_source != PM_PROC_NR && m_ptr->m_source != VFS_PROC_NR &&
+       m_ptr->m_source != RS_PROC_NR && m_ptr->m_source != MEM_PROC_NR &&
+       m_ptr->m_source != VM_PROC_NR)
   {
        static int first=1;
        if (first)
@@ -64,9 +66,13 @@ register message *m_ptr;     /* pointer to request message */
       /* Check if process number was given implictly with SELF and is valid. */
       if (vir_addr[i].proc_nr_e == SELF)
        vir_addr[i].proc_nr_e = m_ptr->m_source;
-      if (vir_addr[i].segment != PHYS_SEG &&
-       ! isokendpt(vir_addr[i].proc_nr_e, &p))
+      if (vir_addr[i].segment != PHYS_SEG) {
+       if(! isokendpt(vir_addr[i].proc_nr_e, &p)) {
+         kprintf("do_copy: %d: seg 0x%x, %d not ok endpoint\n",
+               i, vir_addr[i].segment, vir_addr[i].proc_nr_e);
           return(EINVAL); 
+        }
+      }
 
       /* Check if physical addressing is used without SYS_PHYSCOPY. */
       if ((vir_addr[i].segment & PHYS_SEG) &&
@@ -79,7 +85,7 @@ register message *m_ptr;      /* pointer to request message */
   if (bytes != (vir_bytes) bytes) return(E2BIG);
 
   /* Now try to make the actual virtual copy. */
-  return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );
+  return( virtual_copy_vmcheck(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );
 }
 #endif /* (USE_VIRCOPY || USE_PHYSCOPY) */
 
index 5063730491a5cadbee4cf9909dc4940baf0a61c4..f247311d465ae01b467616a2f8f8e0a0c9ac5a7d 100644 (file)
@@ -25,8 +25,8 @@ PUBLIC int do_cprofile(m_ptr)
 register message *m_ptr;    /* pointer to request message */
 {
   int proc_nr, i, err = 0, k = 0;
-  vir_bytes vir_dst;
-  phys_bytes phys_src, phys_dst, len;
+  phys_bytes len;
+  vir_bytes vir_dst, vir_src;
 
   switch (m_ptr->PROF_ACTION) {
 
@@ -50,10 +50,9 @@ register message *m_ptr;    /* pointer to request message */
                }
 
                /* Set reset flag. */
-               phys_src = vir2phys((vir_bytes) &cprof_ctl_inst.reset);
-               phys_dst = (phys_bytes) cprof_proc_info[i].ctl;
-               len = (phys_bytes) sizeof(cprof_ctl_inst.reset);
-               phys_copy(phys_src, phys_dst, len);
+               data_copy(SYSTEM, (vir_bytes) &cprof_ctl_inst.reset,
+                       cprof_proc_info[i].endpt, cprof_proc_info[i].ctl_v,
+                       sizeof(cprof_ctl_inst.reset));
        }
        kprintf("\n");
        
@@ -71,14 +70,6 @@ register message *m_ptr;    /* pointer to request message */
        if(!isokendpt(m_ptr->PROF_ENDPT, &proc_nr))
                return EINVAL;
 
-       vir_dst = (vir_bytes) m_ptr->PROF_CTL_PTR;
-       len = (phys_bytes) sizeof (int *);
-       cprof_info_addr = numap_local(proc_nr, vir_dst, len);
-
-       vir_dst = (vir_bytes) m_ptr->PROF_MEM_PTR;
-       len = (phys_bytes) sizeof (char *);
-       cprof_data_addr = numap_local(proc_nr, vir_dst, len);
-
        cprof_mem_size = m_ptr->PROF_MEM_SIZE;
 
        kprintf("CPROFILE notice: getting tables:");
@@ -101,10 +92,9 @@ register message *m_ptr;    /* pointer to request message */
                }
 
                /* Copy control struct from proc to local variable. */
-               phys_src = cprof_proc_info[i].ctl;
-               phys_dst = vir2phys((vir_bytes) &cprof_ctl_inst);
-               len = (phys_bytes) sizeof(cprof_ctl_inst);
-               phys_copy(phys_src, phys_dst, len);
+               data_copy(cprof_proc_info[i].endpt, cprof_proc_info[i].ctl_v,
+                       SYSTEM, (vir_bytes) &cprof_ctl_inst,
+                       sizeof(cprof_ctl_inst));
 
                /* Calculate memory used. */
                cprof_proc_info[i].slots_used = cprof_ctl_inst.slots_used;
@@ -121,32 +111,33 @@ register message *m_ptr;    /* pointer to request message */
        if (cprof_mem_size < cprof_info.mem_used) cprof_info.mem_used = -1;
 
        /* Copy the info struct to the user process. */
-       phys_copy(vir2phys((vir_bytes) &cprof_info), cprof_info_addr,
-                                       (phys_bytes) sizeof(cprof_info));
+       data_copy(SYSTEM, (vir_bytes) &cprof_info,
+               m_ptr->PROF_ENDPT, (vir_bytes) m_ptr->PROF_CTL_PTR,
+               sizeof(cprof_info));
 
        /* If there is no space or errors occurred, don't bother copying. */
        if (cprof_info.mem_used == -1 || cprof_info.err) return OK;
 
        /* For each profiled process, copy its name, slots_used and profiling
         * table to the user process. */
-       phys_dst = cprof_data_addr;
+       vir_dst = (vir_bytes) m_ptr->PROF_MEM_PTR;
        for (i=0; i<cprof_procs_no; i++) {
-               phys_src = vir2phys((vir_bytes) cprof_proc_info[i].name);
                len = (phys_bytes) strlen(cprof_proc_info[i].name);
-               phys_copy(phys_src, phys_dst, len);
-               phys_dst += CPROF_PROCNAME_LEN;
+               data_copy(SYSTEM, (vir_bytes) cprof_proc_info[i].name,
+                       m_ptr->PROF_ENDPT, vir_dst, len);
+               vir_dst += CPROF_PROCNAME_LEN;
 
-               phys_src = cprof_proc_info[i].ctl +
-                                               sizeof(cprof_ctl_inst.reset);
                len = (phys_bytes) sizeof(cprof_ctl_inst.slots_used);
-               phys_copy(phys_src, phys_dst, len);
-               phys_dst += len;
+               data_copy(cprof_proc_info[i].endpt,
+                 cprof_proc_info[i].ctl_v + sizeof(cprof_ctl_inst.reset),
+                 m_ptr->PROF_ENDPT, vir_dst, len);
+               vir_dst += len;
 
-               phys_src = cprof_proc_info[i].buf;
                len = (phys_bytes)
                (sizeof(cprof_tbl_inst) * cprof_proc_info[i].slots_used);
-               phys_copy(phys_src, phys_dst, len);
-               phys_dst += len;
+               data_copy(cprof_proc_info[i].endpt, cprof_proc_info[i].buf_v,
+                 m_ptr->PROF_ENDPT, vir_dst, len);
+               vir_dst += len;
        }
 
        return OK;
index c9ef7a855e432bf10bf662d8ebafa4151ffd1bbb..ee7e0a912ed444b5fe0567685ad2385cba9e8742 100644 (file)
@@ -110,9 +110,9 @@ doit:
       } 
     } else { 
       switch (io_type) {
-       case _DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;  
-        case _DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;  
-        case _DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
+       case _DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
+       case _DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
+       case _DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
        default: return(EINVAL);
       } 
     }
index dca66d9c1ae6ecf8c755cb88188a9866697cf2c5..1fbdd0b0fc6e56097584f79fd3618c8939751fcf 100644 (file)
@@ -22,7 +22,6 @@ register message *m_ptr;      /* pointer to request message */
 {
 /* Handle sys_exec().  A process has done a successful EXEC. Patch it up. */
   register struct proc *rp;
-  reg_t sp;                    /* new sp */
   phys_bytes phys_name;
   char *np;
   int proc;
@@ -31,27 +30,18 @@ register message *m_ptr;    /* pointer to request message */
        return EINVAL;
 
   rp = proc_addr(proc);
-  sp = (reg_t) m_ptr->PR_STACK_PTR;
-  rp->p_reg.sp = sp;           /* set the stack pointer */
-  
-#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 */
-  RTS_LOCK_UNSET(rp, RECEIVING);       /* PM does not reply to EXEC call */
+
   /* 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);  
-  if (phys_name != 0) {
-       phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1);
-       for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
-       *np = 0;                                        /* mark end */
-  } else {
+  if(data_copy(who_e, (vir_bytes) m_ptr->PR_NAME_PTR,
+       SYSTEM, (vir_bytes) rp->p_name, (phys_bytes) P_NAME_LEN - 1) != OK)
        strncpy(rp->p_name, "<unset>", P_NAME_LEN);
-  }
-  
+
+  /* Do architecture-specific exec() stuff. */
+  arch_pre_exec(rp, (u32_t) m_ptr->PR_IP_PTR, (u32_t) m_ptr->PR_STACK_PTR);
+
+  /* No reply to EXEC call */
+  RTS_LOCK_UNSET(rp, RECEIVING);
+
   return(OK);
 }
 #endif /* USE_EXEC */
index 99d6d6c68d6f26251f5d542d96f6bab5c7225bc8..543f3f8f4ade48ea762bdffaa953b16920a5edc7 100644 (file)
@@ -56,9 +56,11 @@ register struct proc *rc;            /* slot of process to clean up */
   /* Don't clear if already cleared. */
   if(isemptyp(rc)) return;
 
+
   /* Remove the process' ability to send and receive messages */
   clear_endpoint(rc);
 
+
   /* Turn off any alarm timers at the clock. */   
   reset_timer(&priv(rc)->s_alarm_timer);
 
@@ -70,10 +72,10 @@ register struct proc *rc;           /* slot of process to clean up */
   /* Check the table with IRQ hooks to see if hooks should be released. */
   for (i=0; i < NR_IRQ_HOOKS; i++) {
       int proc;
-      if (rc->p_endpoint == irq_hooks[i].proc_nr_e) { 
+      if (rc->p_endpoint == irq_hooks[i].proc_nr_e) {
         rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */
         irq_hooks[i].proc_nr_e = NONE; /* mark hook as free */
-      }
+      } 
   }
 
   /* Release the process table slot. If this is a system process, also
@@ -83,9 +85,12 @@ register struct proc *rc;            /* slot of process to clean up */
    */
   if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
 
+#if 0
   /* Clean up virtual memory */
-  if (rc->p_misc_flags & MF_VM)
+  if (rc->p_misc_flags & MF_VM) {
        vm_map_default(rc);
+  }
+#endif
 }
 
 #endif /* USE_EXIT */
index 63016e1463b4f2dbc19f13f00948b841366b6abc..7e6b30388645dce33a49b12a8e6f74c1ce3b2922 100644 (file)
@@ -41,10 +41,10 @@ register message *m_ptr;    /* pointer to request message */
   gen = _ENDPOINT_G(rpc->p_endpoint);
 #if (_MINIX_CHIP == _CHIP_INTEL)
   old_ldt_sel = rpc->p_seg.p_ldt_sel;  /* backup local descriptors */
+#endif
   *rpc = *rpp;                         /* copy 'proc' struct */
+#if (_MINIX_CHIP == _CHIP_INTEL)
   rpc->p_seg.p_ldt_sel = old_ldt_sel;  /* restore descriptors */
-#else
-  *rpc = *rpp;                         /* copy 'proc' struct */
 #endif
   if(++gen >= _ENDPOINT_MAX_GENERATION)        /* increase generation */
        gen = 1;                        /* generation number wraparound */
@@ -77,6 +77,11 @@ register message *m_ptr;     /* pointer to request message */
   /* Install new map */
   r = newmap(rpc, map_ptr);
 
+  /* Don't schedule process in VM mode until it has a new pagetable. */
+  if(m_ptr->PR_FORK_FLAGS & PFF_VMINHIBIT) {
+       RTS_LOCK_SET(rpc, VMINHIBIT);
+  }
+
   /* Only one in group should have SIGNALED, child doesn't inherit tracing. */
   RTS_LOCK_UNSET(rpc, (SIGNALED | SIG_PENDING | P_STOP));
   sigemptyset(&rpc->p_pending);
index d51e227aecb606ed3962be1f12880f93d915dffd..433e49fc0a0978af37a868ec54d9ca66e445c732 100644 (file)
  */
 
 #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 ) */
+#include "../vm.h"
 
 
 #if USE_GETINFO
@@ -31,35 +25,44 @@ register message *m_ptr;    /* pointer to request message */
  * call simply copies entire data structures to the caller.
  */
   size_t length;
-  phys_bytes src_phys; 
-  phys_bytes dst_phys; 
-  int proc_nr, nr_e, nr;
+  vir_bytes src_vir; 
+  int proc_nr, nr_e, nr, hz;
+  struct proc *caller;
+  phys_bytes ph;
+
+  caller = proc_addr(who_p);
 
   /* Set source address and length based on request type. */
   switch (m_ptr->I_REQUEST) {
     case GET_MACHINE: {
         length = sizeof(struct machine);
-        src_phys = vir2phys(&machine);
+        src_vir = (vir_bytes) &machine;
         break;
     }
     case GET_KINFO: {
         length = sizeof(struct kinfo);
-        src_phys = vir2phys(&kinfo);
+        src_vir = (vir_bytes) &kinfo;
         break;
     }
     case GET_LOADINFO: {
         length = sizeof(struct loadinfo);
-        src_phys = vir2phys(&kloadinfo);
+        src_vir = (vir_bytes) &kloadinfo;
+        break;
+    }
+    case GET_HZ: {
+        length = sizeof(hz);
+        src_vir = (vir_bytes) &hz;
+       hz = HZ;
         break;
     }
     case GET_IMAGE: {
         length = sizeof(struct boot_image) * NR_BOOT_PROCS;
-        src_phys = vir2phys(image);
+        src_vir = (vir_bytes) image;
         break;
     }
     case GET_IRQHOOKS: {
         length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
-        src_phys = vir2phys(irq_hooks);
+        src_vir = (vir_bytes) irq_hooks;
         break;
     }
     case GET_SCHEDINFO: {
@@ -67,36 +70,44 @@ register message *m_ptr;    /* pointer to request message */
          * at once, otherwise the scheduling information may be incorrect.
          * Copy the queue heads and fall through to copy the process table. 
          */
+       if((ph=umap_local(caller, D, (vir_bytes) m_ptr->I_VAL_PTR2,length)) == 0)
+               return EFAULT;
         length = sizeof(struct proc *) * NR_SCHED_QUEUES;
-        src_phys = vir2phys(rdy_head);
-       okendpt(m_ptr->m_source, &proc_nr);
-        dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR2,
-                length); 
-        if (src_phys == 0 || dst_phys == 0) return(EFAULT);
-        phys_copy(src_phys, dst_phys, length);
-        /* fall through */
+       CHECKRANGE_OR_SUSPEND(proc_addr(who_p), ph, length, 1);
+       data_copy(SYSTEM, (vir_bytes) rdy_head,
+               who_e, (vir_bytes) m_ptr->I_VAL_PTR2, length);
+        /* fall through to GET_PROCTAB */
     }
     case GET_PROCTAB: {
         length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
-        src_phys = vir2phys(proc);
+        src_vir = (vir_bytes) proc;
         break;
     }
     case GET_PRIVTAB: {
         length = sizeof(struct priv) * (NR_SYS_PROCS);
-        src_phys = vir2phys(priv);
+        src_vir = (vir_bytes) priv;
         break;
     }
     case GET_PROC: {
         nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
-               m_ptr->m_source : m_ptr->I_VAL_LEN2_E;
+               who_e : m_ptr->I_VAL_LEN2_E;
        if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
         length = sizeof(struct proc);
-        src_phys = vir2phys(proc_addr(nr));
+        src_vir = (vir_bytes) proc_addr(nr);
         break;
     }
+    case GET_WHOAMI: {
+       int len;
+       /* GET_WHOAMI uses m3 and only uses the message contents for info. */
+       m_ptr->GIWHO_EP = who_e;
+       len = MIN(sizeof(m_ptr->GIWHO_NAME), sizeof(caller->p_name))-1;
+       strncpy(m_ptr->GIWHO_NAME, caller->p_name, len);
+       m_ptr->GIWHO_NAME[len] = '\0';
+       return OK;
+    }
     case GET_MONPARAMS: {
-        src_phys = kinfo.params_base;          /* already is a physical */
-        length = kinfo.params_size;
+        src_vir = (vir_bytes) params_buffer;
+       length = sizeof(params_buffer);
         break;
     }
     case GET_RANDOMNESS: {             
@@ -109,44 +120,25 @@ register message *m_ptr;  /* pointer to request message */
                krandom.bin[i].r_next = 0;
        }
        length = sizeof(struct randomness);
-       src_phys = vir2phys(&copy);
+       src_vir = (vir_bytes) &copy;
        break;
     }
     case GET_KMESSAGES: {
         length = sizeof(struct kmessages);
-        src_phys = vir2phys(&kmess);
+        src_vir = (vir_bytes) &kmess;
         break;
     }
 #if DEBUG_TIME_LOCKS
     case GET_LOCKTIMING: {
     length = sizeof(timingdata);
-    src_phys = vir2phys(timingdata);
+    src_vir = (vir_bytes) timingdata;
     break;
     }
 #endif
 
-#if !( POWERPC )        
-    case GET_BIOSBUFFER:
-       bios_buf_vir = (vir_bytes)bios_buf;
-       bios_buf_len = sizeof(bios_buf);
-
-       length = sizeof(bios_buf_len);
-       src_phys = vir2phys(&bios_buf_len);
-       if (length != m_ptr->I_VAL_LEN2_E) return (EINVAL);
-       if(!isokendpt(m_ptr->m_source, &proc_nr))
-               panic("bogus source", m_ptr->m_source);
-       dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR2, length); 
-       if (src_phys == 0 || dst_phys == 0) return(EFAULT);
-       phys_copy(src_phys, dst_phys, length);
-
-       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);
+        src_vir = (vir_bytes) irq_actids;
         break;
     }
 
@@ -162,11 +154,10 @@ register message *m_ptr;  /* pointer to request message */
 
   /* Try to make the actual copy for the requested data. */
   if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG);
-  if(!isokendpt(m_ptr->m_source, &proc_nr)) 
-       panic("bogus source", m_ptr->m_source);
-  dst_phys = numap_local(proc_nr, (vir_bytes) m_ptr->I_VAL_PTR, length); 
-  if (src_phys == 0 || dst_phys == 0) return(EFAULT);
-  phys_copy(src_phys, dst_phys, length);
+  if((ph=umap_local(caller, D, (vir_bytes) m_ptr->I_VAL_PTR,length)) == 0)
+       return EFAULT;
+  CHECKRANGE_OR_SUSPEND(caller, ph, length, 1);
+  data_copy(SYSTEM, src_vir, who_e, (vir_bytes) m_ptr->I_VAL_PTR, length);
   return(OK);
 }
 
index 260cc4cdee82b32ae5eaf72f2eaa10c2762c99d3..9625a9825e14b787839129f4838858a1bd74cbfc 100644 (file)
@@ -46,8 +46,9 @@ register message *m_ptr;      /* pointer to request message */
       if (irq_hook_id >= NR_IRQ_HOOKS || irq_hook_id < 0 ||
           irq_hooks[irq_hook_id].proc_nr_e == NONE) return(EINVAL);
       if (irq_hooks[irq_hook_id].proc_nr_e != m_ptr->m_source) return(EPERM);
-      if (m_ptr->IRQ_REQUEST == IRQ_ENABLE)
+      if (m_ptr->IRQ_REQUEST == IRQ_ENABLE) {
           enable_irq(&irq_hooks[irq_hook_id]); 
+      }
       else 
           disable_irq(&irq_hooks[irq_hook_id]);        
       break;
@@ -64,7 +65,7 @@ register message *m_ptr;      /* pointer to request message */
       privp= priv(rp);
       if (!privp)
       {
-       kprintf("no priv structure!\n");
+       kprintf("do_irqctl: no priv structure!\n");
        return EPERM;
       }
       if (privp->s_flags & CHECK_IRQ)
@@ -143,14 +144,12 @@ irq_hook_t *hook;
    */
   get_randomness(hook->irq);
 
-  /* Check if the handler is still alive. If not, forget about the
-   * interrupt. This should never happen, as processes that die 
+  /* Check if the handler is still alive.
+   * If it's dead, this should never happen, as processes that die 
    * automatically get their interrupt hooks unhooked.
    */
-  if(!isokendpt(hook->proc_nr_e, &proc)) {
-     hook->proc_nr_e = NONE;
-     return 0;
-  }
+  if(!isokendpt(hook->proc_nr_e, &proc))
+     minix_panic("invalid interrupt handler", hook->proc_nr_e);
 
   /* Add a bit for this interrupt to the process' pending interrupts. When 
    * sending the notification message, this bit map will be magically set
index 47f0c43ca9d0dc75432e451f75042897ccd56efc..449ab0c9176d146cdf643295606b59554c35d3ad 100644 (file)
@@ -31,14 +31,13 @@ register message *m_ptr;    /* pointer to request message */
 
        proc = proc_addr(proc_p);
 
-       phys_base= umap_local(proc, D, base, size);
-       if (!phys_base)
-       {
-               kprintf("do_mapdma: umap_local failed\n");
+        phys_base= umap_virtual(proc, D, base, size);
+        if (!phys_base)
+        {
+                kprintf("do_mapdma: umap_virtual failed\n");
                return EFAULT;
        }
 
        m_ptr->CP_DST_ADDR = phys_base;
        return OK;
 }
-
index a179f5631a8e1c9693372af7280a0f9f627ce61b..028cd290b0adb3bcfdd299c78c759db078112ab3 100644 (file)
 PUBLIC int do_newmap(m_ptr)
 message *m_ptr;                        /* pointer to request message */
 {
-/* Handle sys_newmap().  Fetch the memory map from PM. */
+/* Handle sys_newmap().  Fetch the memory map. */
   register struct proc *rp;    /* process whose map is to be loaded */
-  struct mem_map *map_ptr;     /* virtual address of map inside caller (PM) */
-  phys_bytes src_phys;         /* physical address of map at the PM */
+  struct mem_map *map_ptr;     /* virtual address of map inside caller */
+  phys_bytes src_phys;         /* physical address of map at the */
   int proc;
 
   map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
@@ -36,18 +36,15 @@ message *m_ptr;                     /* pointer to request message */
  *===========================================================================*/
 PUBLIC int newmap(rp, map_ptr)
 struct proc *rp;               /* process whose map is to be loaded */
-struct mem_map *map_ptr;       /* virtual address of map inside caller (PM) */
+struct mem_map *map_ptr;       /* virtual address of map inside caller */
 {
-/* Fetch the memory map from PM. */
-  phys_bytes src_phys;         /* physical address of map at the PM */
-  int proc;
-
-  /* Copy the map from 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));
+  int r;
+/* Fetch the memory map. */
+  if((r=data_copy(who_e, (vir_bytes) map_ptr,
+       SYSTEM, (vir_bytes) rp->p_memmap, sizeof(rp->p_memmap))) != OK) {
+       kprintf("newmap: data_copy failed! (%d)\n", r);
+       return r;
+  }
 
   alloc_segments(rp);
 
index d1affc6df796d14ea666b8dce4b5bb1b6e926eac..c76706dc921b628aaceb9028723316fda706a37b 100644 (file)
@@ -28,8 +28,7 @@ message *m_ptr;                       /* pointer to request message */
   register struct priv *sp;
   int proc_nr;
   int priv_id;
-  int i;
-  phys_bytes caller_phys, kernel_phys;
+  int i, r;
   struct io_range io_range;
   struct mem_range mem_range;
   struct priv priv;
@@ -100,12 +99,9 @@ message *m_ptr;                     /* pointer to request message */
        if (m_ptr->CTL_ARG_PTR)
        {
                /* Copy privilege structure from caller */
-               caller_phys = umap_local(caller_ptr, D,
-                       (vir_bytes) m_ptr->CTL_ARG_PTR, sizeof(priv));
-               if (caller_phys == 0)
-                       return EFAULT;
-               kernel_phys = vir2phys(&priv);
-               phys_copy(caller_phys, kernel_phys, sizeof(priv));
+               if((r=data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
+                       SYSTEM, (vir_bytes) &priv, sizeof(priv))) != OK)
+                       return r;
 
                /* Copy the call mask */
                for (i= 0; i<CALL_MASK_SIZE; i++)
@@ -180,12 +176,8 @@ message *m_ptr;                    /* pointer to request message */
 #endif
 
        /* Get the I/O range */
-       caller_phys = umap_local(caller_ptr, D, (vir_bytes) m_ptr->CTL_ARG_PTR,
-               sizeof(io_range));
-       if (caller_phys == 0)
-               return EFAULT;
-       kernel_phys = vir2phys(&io_range);
-       phys_copy(caller_phys, kernel_phys, sizeof(io_range));
+       data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
+               SYSTEM, (vir_bytes) &io_range, sizeof(io_range));
        priv(rp)->s_flags |= CHECK_IO_PORT;     /* Check I/O accesses */
        i= priv(rp)->s_nr_io_range;
        if (i >= NR_IO_RANGE)
@@ -206,12 +198,9 @@ message *m_ptr;                    /* pointer to request message */
                return EPERM;
 
        /* Get the memory range */
-       caller_phys = umap_local(caller_ptr, D, (vir_bytes) m_ptr->CTL_ARG_PTR,
-               sizeof(mem_range));
-       if (caller_phys == 0)
-               return EFAULT;
-       kernel_phys = vir2phys(&mem_range);
-       phys_copy(caller_phys, kernel_phys, sizeof(mem_range));
+       if((r=data_copy(who_e, (vir_bytes) m_ptr->CTL_ARG_PTR,
+               SYSTEM, (vir_bytes) &mem_range, sizeof(mem_range))) != OK)
+               return r;
        priv(rp)->s_flags |= CHECK_MEM; /* Check I/O accesses */
        i= priv(rp)->s_nr_mem_range;
        if (i >= NR_MEM_RANGE)
index 7638e046d0937baa088446c470af020a0c545f82..334c8ff2178b6a2cf8528c5a4aedf32f57b787db 100644 (file)
@@ -25,26 +25,24 @@ register message *m_ptr;    /* pointer to request message */
  * about the location of their profiling table and the control structure
  * which is used to enable the kernel to have the tables cleared.
  */ 
-  int proc_nr, len;
+  int proc_nr;
   vir_bytes vir_dst;
   struct proc *rp;                          
 
   /* Store process name, control struct, table locations. */
-  isokendpt(m_ptr->m_source, &proc_nr);
+  if(!isokendpt(m_ptr->m_source, &proc_nr))
+       return EDEADSRCDST;
+
+  if(cprof_procs_no >= NR_SYS_PROCS)
+       return ENOSPC;
+
   rp = proc_addr(proc_nr);
 
   cprof_proc_info[cprof_procs_no].endpt = who_e;
   cprof_proc_info[cprof_procs_no].name = rp->p_name;
 
-  len = (phys_bytes) sizeof (void *);
-
-  vir_dst = (vir_bytes) m_ptr->PROF_CTL_PTR;
-  cprof_proc_info[cprof_procs_no].ctl =
-         numap_local(proc_nr, vir_dst, len);
-
-  vir_dst = (vir_bytes) m_ptr->PROF_MEM_PTR;
-  cprof_proc_info[cprof_procs_no].buf =
-         numap_local(proc_nr, vir_dst, len);
+  cprof_proc_info[cprof_procs_no].ctl_v = (vir_bytes) m_ptr->PROF_CTL_PTR;
+  cprof_proc_info[cprof_procs_no].buf_v = (vir_bytes) m_ptr->PROF_MEM_PTR;
 
   cprof_procs_no++;
 
index 5178c3fc8caddd7a1ce5723bb854492298e4be46..55744b7144543ecd710ac37a4e815942f6fc4e7d 100644 (file)
  *      VSCP_VEC_SIZE   number of significant elements in vector
  */
 
-#include "../system.h"
 #include <minix/type.h>
 #include <minix/safecopies.h>
 
+#include "../system.h"
+#include "../vm.h"
+
 #define MEM_TOP 0xFFFFFFFFUL
 
 FORWARD _PROTOTYPE(int safecopy, (endpoint_t, endpoint_t, cp_grant_id_t, int, int, size_t, vir_bytes, vir_bytes, int));
 
+#define HASGRANTTABLE(gr) \
+       (!RTS_ISSET(gr, NO_PRIV) && priv(gr) && priv(gr)->s_grant_table > 0)
+
 /*===========================================================================*
  *                             verify_grant                                 *
  *===========================================================================*/
@@ -38,7 +43,7 @@ endpoint_t *e_granter;                /* new granter (magic grants) */
        static cp_grant_t g;
        static int proc_nr;
        static struct proc *granter_proc;
-       static phys_bytes phys_grant;
+       int r;
 
        /* Get granter process slot (if valid), and check range of
         * grant id.
@@ -51,23 +56,9 @@ endpoint_t *e_granter;               /* new granter (magic grants) */
 
        /* If there is no priv. structure, or no grant table in the
         * priv. structure, or the grant table in the priv. structure
-        * is too small for the grant,
-        *
-        * then there exists no such grant, so
-        *
-        * return EPERM.
-        *
-        * (Don't leak how big the grant table is by returning
-        * EINVAL for grant-out-of-range, in case this turns out to be
-        * interesting information.)
+        * is too small for the grant, return EPERM.
         */
-       if(RTS_ISSET(granter_proc, NO_PRIV) || !(priv(granter_proc)) ||
-         priv(granter_proc)->s_grant_table < 1) {
-               kprintf("verify_grant: grant verify failed in ep %d proc %d: "
-               "no priv table, or no grant table\n",
-                       granter, proc_nr);
-               return(EPERM);
-       }
+       if(!HASGRANTTABLE(granter_proc)) return EPERM;
 
        if(priv(granter_proc)->s_grant_entries <= grant) {
                static int curr= 0, limit= 100, extra= 20;
@@ -94,25 +85,25 @@ endpoint_t *e_granter;              /* new granter (magic grants) */
         * (presumably) set an invalid grant table entry by returning
         * EPERM, just like with an invalid grant id.
         */
-       if(!(phys_grant = umap_local(granter_proc, D,
-         priv(granter_proc)->s_grant_table + sizeof(g)*grant, sizeof(g)))) {
-               kprintf("verify_grant: grant verify failed: umap failed\n");
+       if((r=data_copy(granter,
+               priv(granter_proc)->s_grant_table + sizeof(g)*grant,
+               SYSTEM, (vir_bytes) &g, sizeof(g))) != OK) {
+               kprintf("verify_grant: grant verify: data_copy failed\n");
                return EPERM;
        }
 
-       phys_copy(phys_grant, vir2phys(&g), sizeof(g));
-
        /* Check validity. */
        if((g.cp_flags & (CPF_USED | CPF_VALID)) != (CPF_USED | CPF_VALID)) {
                kprintf(
-               "verify_grant: grant verify failed: unused or invalid\n");
+               "verify_grant: grant failed: invalid (%d flags 0x%lx)\n",
+                       grant, g.cp_flags);
                return EPERM;
        }
 
        /* Check access of grant. */
        if(((g.cp_flags & access) != access)) {
                kprintf(
-       "verify_grant: grant verify failed: access invalid; want %x, have %x\n",
+       "verify_grant: grant verify failed: access invalid; want 0x%x, have 0x%x\n",
                        access, g.cp_flags);
                return EPERM;
        }
@@ -210,6 +201,11 @@ int access;                        /* CPF_READ for a copy from granter to grantee, CPF_WRITE
        static vir_bytes v_offset;
        int r;
        endpoint_t new_granter, *src, *dst;
+       struct proc *granter_p;
+
+       /* See if there is a reasonable grant table. */
+       if(!(granter_p = endpoint_lookup(granter))) return EINVAL;
+       if(!HASGRANTTABLE(granter_p)) return EPERM;
 
        /* Decide who is src and who is dst. */
        if(access & CPF_READ) {
@@ -227,9 +223,11 @@ int access;                        /* CPF_READ for a copy from granter to grantee, CPF_WRITE
 
                if (curr < limit+extra)
                {
+#if 0
                        kprintf(
                "grant %d verify to copy %d->%d by %d failed: err %d\n",
                                grantid, *src, *dst, grantee, r);
+#endif
                } else if (curr == limit+extra)
                {
                        kprintf(
@@ -265,7 +263,7 @@ int access;                 /* CPF_READ for a copy from granter to grantee, CPF_WRITE
        }
 
        /* Do the regular copy. */
-       return virtual_copy(&v_src, &v_dst, bytes);
+       return virtual_copy_vmcheck(&v_src, &v_dst, bytes);
 
 }
 
@@ -288,7 +286,7 @@ register message *m_ptr;    /* pointer to request message */
                src_seg = SCP_INFO2SEG(m_ptr->SCP_INFO);
                dst_seg = D;
                access = CPF_WRITE;
-       } else panic("Impossible system call nr. ", sys_call_code);
+       } else minix_panic("Impossible system call nr. ", sys_call_code);
 
        return safecopy(m_ptr->SCP_FROM_TO, who_e, m_ptr->SCP_GID,
                src_seg, dst_seg, m_ptr->SCP_BYTES, m_ptr->SCP_OFFSET,
@@ -304,6 +302,7 @@ register message *m_ptr;    /* pointer to request message */
        static struct vscp_vec vec[SCPVEC_NR];
        static struct vir_addr src, dst;
        int r, i, els;
+       size_t bytes;
 
        /* Set vector copy parameters. */
        src.proc_nr_e = who_e;
@@ -314,9 +313,10 @@ register message *m_ptr;   /* pointer to request message */
 
        /* No. of vector elements. */
        els = m_ptr->VSCP_VEC_SIZE;
+       bytes = els * sizeof(struct vscp_vec);
 
        /* Obtain vector of copies. */
-       if((r=virtual_copy(&src, &dst, els * sizeof(struct vscp_vec))) != OK)
+       if((r=virtual_copy_vmcheck(&src, &dst, bytes)) != OK)
                return r;
 
        /* Perform safecopies. */
index 894260d44c95cd615faeab68874dc3018a81df1d..aedf2a6038d0b338b2e998c0b27bebeb799510cb 100644 (file)
@@ -26,18 +26,16 @@ message *m_ptr;                     /* pointer to request message */
  */
   struct sigcontext sc;
   register struct proc *rp;
-  phys_bytes src_phys;
-  int proc;
+  int proc, r;
 
   if (! isokendpt(m_ptr->SIG_ENDPT, &proc)) return(EINVAL);
   if (iskerneln(proc)) return(EPERM);
   rp = proc_addr(proc);
 
   /* Copy in the sigcontext structure. */
-  src_phys = umap_local(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
-      (vir_bytes) sizeof(struct sigcontext));
-  if (src_phys == 0) return(EFAULT);
-  phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
+  if((r=data_copy(m_ptr->SIG_ENDPT, (vir_bytes) m_ptr->SIG_CTXT_PTR,
+       SYSTEM, (vir_bytes) &sc, sizeof(struct sigcontext))) != OK)
+       return r;
 
   /* Restore user bits of psw from sc, maintain system bits from proc. */
   sc.sc_psw  =  (sc.sc_psw & X86_FLAGS_USER) |
index 0b37bac8958ffbda311d82b8524adec452427830..fc19800633be9eb1511c0f50cae4ce9b08d451f9 100644 (file)
@@ -25,20 +25,18 @@ message *m_ptr;                     /* pointer to request message */
 
   struct sigmsg smsg;
   register struct proc *rp;
-  phys_bytes src_phys, dst_phys;
   struct sigcontext sc, *scp;
   struct sigframe fr, *frp;
-  int proc;
+  int proc, r;
 
   if (!isokendpt(m_ptr->SIG_ENDPT, &proc)) return(EINVAL);
   if (iskerneln(proc)) return(EPERM);
   rp = proc_addr(proc);
 
   /* Get the sigmsg structure into our address space.  */
-  src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes) 
-      m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg));
-  if (src_phys == 0) return(EFAULT);
-  phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg));
+  if((r=data_copy(PM_PROC_NR, (vir_bytes) m_ptr->SIG_CTXT_PTR,
+       SYSTEM, (vir_bytes) &smsg, (phys_bytes) sizeof(struct sigmsg))) != OK)
+       return r;
 
   /* Compute the user stack pointer where sigcontext will be stored. */
   scp = (struct sigcontext *) smsg.sm_stkptr - 1;
@@ -56,10 +54,9 @@ message *m_ptr;                      /* pointer to request message */
   sc.sc_mask = smsg.sm_mask;
 
   /* Copy the sigcontext structure to the user's stack. */
-  dst_phys = umap_local(rp, D, (vir_bytes) scp,
-      (vir_bytes) sizeof(struct sigcontext));
-  if (dst_phys == 0) return(EFAULT);
-  phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
+  if((r=data_copy(SYSTEM, (vir_bytes) &sc, m_ptr->SIG_ENDPT, (vir_bytes) scp,
+      (vir_bytes) sizeof(struct sigcontext))) != OK)
+      return r;
 
   /* Initialize the sigframe structure. */
   frp = (struct sigframe *) scp - 1;
@@ -73,10 +70,10 @@ message *m_ptr;                     /* pointer to request message */
   fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
 
   /* Copy the sigframe structure to the user's stack. */
-  dst_phys = umap_local(rp, D, (vir_bytes) frp, 
-      (vir_bytes) sizeof(struct sigframe));
-  if (dst_phys == 0) return(EFAULT);
-  phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
+  if((r=data_copy(SYSTEM, (vir_bytes) &fr, m_ptr->SIG_ENDPT, (vir_bytes) frp, 
+      (vir_bytes) sizeof(struct sigframe))) != OK)
+      return r;
+
 
 #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
@@ -95,8 +92,13 @@ message *m_ptr;                      /* pointer to request message */
   /* Reschedule if necessary. */
   if(RTS_ISSET(rp, NO_PRIORITY))
        RTS_LOCK_UNSET(rp, NO_PRIORITY);
-  else
+  else {
+       struct proc *caller;
+       caller = proc_addr(who_p);
        kprintf("system: warning: sigsend a running process\n");
+       kprintf("caller stack: ");
+       proc_stacktrace(caller);
+  }
 
   return(OK);
 }
index 6c6198735d7cbcad3b5a358cbe2752112b6b0c21..323caa49859ed6790b661705b51d2ea9bf6d10cc 100644 (file)
@@ -17,6 +17,9 @@
 
 #if SPROFILE
 
+/* user address to write info struct */
+PRIVATE vir_bytes sprof_info_addr_vir;
+
 /*===========================================================================*
  *                             do_sprofile                                  *
  *===========================================================================*/
@@ -41,15 +44,14 @@ register message *m_ptr;    /* pointer to request message */
                return EBUSY;
        }
 
-       isokendpt(m_ptr->PROF_ENDPT, &proc_nr);
-
-       vir_dst = (vir_bytes) m_ptr->PROF_CTL_PTR;
-       length = (phys_bytes) sizeof (int *);
-       sprof_info_addr = numap_local(proc_nr, vir_dst, length);
+       /* Test endpoint number. */
+       if(!isokendpt(m_ptr->PROF_ENDPT, &proc_nr))
+               return EINVAL;
 
-       vir_dst = (vir_bytes) m_ptr->PROF_MEM_PTR;
-       length = (phys_bytes) sizeof (char *);
-       sprof_data_addr = numap_local(proc_nr, vir_dst, length);
+       /* Set parameters for statistical profiler. */
+       sprof_ep = m_ptr->PROF_ENDPT;
+       sprof_info_addr_vir = (vir_bytes) m_ptr->PROF_CTL_PTR;
+       sprof_data_addr_vir = (vir_bytes) m_ptr->PROF_MEM_PTR;
 
        sprof_info.mem_used = 0;
        sprof_info.total_samples = 0;
@@ -80,8 +82,8 @@ register message *m_ptr;    /* pointer to request message */
 
        stop_profile_clock();
 
-       phys_copy(vir2phys((vir_bytes) &sprof_info),
-               sprof_info_addr, (phys_bytes) sizeof(sprof_info));
+       data_copy(SYSTEM, (vir_bytes) &sprof_info,
+               sprof_ep, sprof_info_addr_vir, sizeof(sprof_info));
 
        return OK;
 
index 0e12f0ba5fdacd0eb417b213827c54dbbe0c4c52..988a3b99c6a50de20df98b895985829876570e47 100644 (file)
@@ -40,7 +40,6 @@ register message *m_ptr;
  */
 
   register struct proc *rp;
-  phys_bytes src, dst;
   vir_bytes tr_addr = (vir_bytes) m_ptr->CTL_ADDRESS;
   long tr_data = m_ptr->CTL_DATA;
   int tr_request = m_ptr->CTL_REQUEST;
@@ -48,6 +47,26 @@ register message *m_ptr;
   unsigned char ub;
   int i;
 
+#define COPYTOPROC(seg, addr, myaddr, length) {                \
+       struct vir_addr fromaddr, toaddr;               \
+       fromaddr.proc_nr_e = SYSTEM;                    \
+       toaddr.proc_nr_e = tr_proc_nr_e;                \
+       fromaddr.offset = (myaddr);                     \
+       toaddr.offset = (addr);                         \
+       fromaddr.segment = D;                           \
+       toaddr.segment = (seg);                         \
+}
+
+#define COPYFROMPROC(seg, addr, myaddr, length) {      \
+       struct vir_addr fromaddr, toaddr;               \
+       fromaddr.proc_nr_e = tr_proc_nr_e;              \
+       toaddr.proc_nr_e = SYSTEM;                      \
+       fromaddr.offset = (addr);                       \
+       toaddr.offset = (myaddr);                       \
+       fromaddr.segment = (seg);                       \
+       toaddr.segment = D;                             \
+}
+
   if(!isokendpt(tr_proc_nr_e, &tr_proc_nr)) return(EINVAL);
   if (iskerneln(tr_proc_nr)) return(EPERM);
 
@@ -61,16 +80,14 @@ register message *m_ptr;
 
   case T_GETINS:               /* return value from instruction space */
        if (rp->p_memmap[T].mem_len != 0) {
-               if ((src = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
-               phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
+               COPYTOPROC(T, tr_addr, (vir_bytes) &tr_data, sizeof(long));
                m_ptr->CTL_DATA = tr_data;
                break;
        }
        /* Text space is actually data space - fall through. */
 
   case T_GETDATA:              /* return value from data space */
-       if ((src = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
-       phys_copy(src, vir2phys(&tr_data), (phys_bytes) sizeof(long));
+       COPYTOPROC(D, tr_addr, (vir_bytes) &tr_data, sizeof(long));
        m_ptr->CTL_DATA= tr_data;
        break;
 
@@ -83,16 +100,14 @@ register message *m_ptr;
 
   case T_SETINS:               /* set value in instruction space */
        if (rp->p_memmap[T].mem_len != 0) {
-               if ((dst = umap_local(rp, T, tr_addr, TR_VLSIZE)) == 0) return(EIO);
-               phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
+               COPYFROMPROC(T, tr_addr, (vir_bytes) &tr_data, sizeof(long));
                m_ptr->CTL_DATA = 0;
                break;
        }
        /* Text space is actually data space - fall through. */
 
   case T_SETDATA:                      /* set value in data space */
-       if ((dst = umap_local(rp, D, tr_addr, TR_VLSIZE)) == 0) return(EIO);
-       phys_copy(vir2phys(&tr_data), dst, (phys_bytes) sizeof(long));
+       COPYFROMPROC(D, tr_addr, (vir_bytes) &tr_data, sizeof(long));
        m_ptr->CTL_DATA = 0;
        break;
 
@@ -136,28 +151,12 @@ register message *m_ptr;
        break;
 
   case T_READB_INS:            /* get value from instruction space */
-       if (rp->p_memmap[T].mem_len != 0) {
-               if ((dst = umap_local(rp, T, tr_addr, 1)) == 0) return(EFAULT);
-               phys_copy(dst, vir2phys(&ub), (phys_bytes) 1);
-               m_ptr->CTL_DATA = ub;
-               break;
-       }
-  
-       if ((dst = umap_local(rp, D, tr_addr, 1)) == 0) return(EFAULT);
-       phys_copy(dst, vir2phys(&ub), (phys_bytes) 1);
+       COPYFROMPROC(rp->p_memmap[T].mem_len > 0 ? T : D, tr_addr, (vir_bytes) &ub, 1);
        m_ptr->CTL_DATA = ub;
        break;
 
   case T_WRITEB_INS:           /* set value in instruction space */
-       if (rp->p_memmap[T].mem_len != 0) {
-               if ((dst = umap_local(rp, T, tr_addr, 1)) == 0) return(EFAULT);
-               phys_copy(vir2phys(&tr_data), dst, (phys_bytes) 1);
-               m_ptr->CTL_DATA = 0;
-               break;
-       }
-  
-       if ((dst = umap_local(rp, D, tr_addr, 1)) == 0) return(EFAULT);
-       phys_copy(vir2phys(&tr_data), dst, (phys_bytes) 1);
+       COPYTOPROC(rp->p_memmap[T].mem_len > 0 ? T : D,tr_addr, (vir_bytes) &tr_data, 1);
        m_ptr->CTL_DATA = 0;
        break;
 
index 93360952313e3395ff86576a2257ad541dd47e20..7c235ba460c1438f9ff21e59277da8d250eaf60c 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include "../system.h"
+#include "../vm.h"
 
 #if USE_UMAP
 
@@ -25,8 +26,11 @@ register message *m_ptr;     /* pointer to request message */
   vir_bytes offset = m_ptr->CP_SRC_ADDR;
   int count = m_ptr->CP_NR_BYTES;
   int endpt = (int) m_ptr->CP_SRC_ENDPT;
-  int proc_nr;
-  phys_bytes phys_addr;
+  int proc_nr, r;
+  int naughty = 0;
+  phys_bytes phys_addr = 0, lin_addr = 0;
+  int caller_pn;
+  struct proc *targetpr, *caller;
 
   /* Verify process number. */
   if (endpt == SELF)
@@ -34,27 +38,88 @@ register message *m_ptr;    /* pointer to request message */
   else
        if (! isokendpt(endpt, &proc_nr))
                return(EINVAL);
+  targetpr = proc_addr(proc_nr);
+
+  okendpt(who_e, &caller_pn);
+  caller = proc_addr(caller_pn);
 
   /* See which mapping should be made. */
   switch(seg_type) {
   case LOCAL_SEG:
-      phys_addr = umap_local(proc_addr(proc_nr), seg_index, offset, count); 
+      phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count); 
+      if(!lin_addr) return EFAULT;
+      CHECKRANGE_OR_SUSPEND(targetpr, lin_addr, count, 1);
+      naughty = 1;
       break;
   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); 
+      phys_addr = lin_addr = umap_remote(targetpr, seg_index, offset, count); 
+      if(!lin_addr) return EFAULT;
+      CHECKRANGE_OR_SUSPEND(targetpr, lin_addr, count, 1);
+      naughty = 1;
       break;
-#endif
   case GRANT_SEG:
-      phys_addr = umap_grant(proc_addr(proc_nr), offset, count); 
+      naughty = 1;
+  case LOCAL_VM_SEG:
+    if(seg_index == MEM_GRANT || seg_type == GRANT_SEG) {
+       vir_bytes newoffset;
+       endpoint_t newep;
+       int new_proc_nr;
+
+        if(verify_grant(targetpr->p_endpoint, ANY, offset, count, 0, 0,
+                &newoffset, &newep) != OK) {
+                kprintf("SYSTEM: do_umap: verify_grant in %s, grant %d, bytes 0x%lx, failed, caller %s\n", targetpr->p_name, offset, count, caller->p_name);
+               proc_stacktrace(caller);
+                return EFAULT;
+        }
+
+        if(!isokendpt(newep, &new_proc_nr)) {
+                kprintf("SYSTEM: do_umap: isokendpt failed\n");
+                return EFAULT;
+        }
+
+       /* New lookup. */
+       offset = newoffset;
+       targetpr = proc_addr(new_proc_nr);
+       seg_index = D;
+      }
+
+      if(seg_index == T || seg_index == D || seg_index == S) {
+        phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count); 
+      } else {
+       kprintf("SYSTEM: bogus seg type 0x%lx\n", seg_index);
+       return EFAULT;
+      }
+      if(!lin_addr) {
+       kprintf("SYSTEM:do_umap: umap_local failed\n");
+       return EFAULT;
+      }
+      CHECKRANGE_OR_SUSPEND(targetpr, lin_addr, count, 1);
+      if(vm_lookup(targetpr, lin_addr, &phys_addr, NULL) != OK) {
+       kprintf("SYSTEM:do_umap: vm_lookup failed\n");
+       return EFAULT;
+      }
+      if(phys_addr == 0)
+       minix_panic("vm_lookup returned zero physical address", NO_NUM);
       break;
   default:
-      return(EINVAL);
+      if((r=arch_umap(targetpr, offset, count, seg_type, &lin_addr))
+       != OK)
+       return r;
+      phys_addr = lin_addr;
+  }
+
+  if(vm_running && !vm_contiguous(targetpr, lin_addr, count)) {
+       kprintf("SYSTEM:do_umap: not contiguous\n");
+       return EFAULT;
   }
+
   m_ptr->CP_DST_ADDR = phys_addr;
+  if(naughty || phys_addr == 0) {
+         kprintf("kernel: umap 0x%x done by %d / %s, pc 0x%lx, 0x%lx -> 0x%lx\n",
+               seg_type, who_e, caller->p_name, caller->p_reg.pc, offset, phys_addr);
+       kprintf("caller stack: ");
+       proc_stacktrace(caller);
+  }
   return (phys_addr == 0) ? EFAULT: OK;
 }
 
index 4e2b0001b259c2264a555d0fd67937448fac8196..2a9163308b3035a0fbd3bdfc379fee56a122ab6d 100644 (file)
@@ -10,7 +10,7 @@
 PUBLIC int do_unused(m)
 message *m;                            /* pointer to request message */
 {
-  kprintf("SYSTEM: got unused request %d from %d", m->m_type, m->m_source);
+  kprintf("SYSTEM: got unused request %d from %d\n", m->m_type, m->m_source);
   return(EBADREQUEST);                 /* illegal message type */
 }
 
index efdc7f65cbeeec0605d729d2607b010b1f718316..b43d50f6f61d20a834ef019d0949bd6b3babed85 100644 (file)
@@ -25,13 +25,13 @@ register message *m_ptr;    /* pointer to request message */
  * requests. Although a single handler function is used, there are two
  * different kernel calls so that permissions can be checked.
  */
-  int nr_req;
+  int nr_req, r;
   vir_bytes caller_vir;
-  phys_bytes caller_phys;
-  phys_bytes kernel_phys;
   phys_bytes bytes;
   int i,s;
   struct vir_cp_req *req;
+  struct vir_addr src, dst;
+  struct proc *pr;
 
   { static int first=1;
        if (first)
@@ -41,17 +41,23 @@ register message *m_ptr;    /* pointer to request message */
        }
   }
 
+  if(!(pr = endpoint_lookup(who_e)))
+       minix_panic("do_vcopy: caller doesn't exist", who_e);
+
   /* Check if request vector size is ok. */
   nr_req = (unsigned) m_ptr->VCP_VEC_SIZE;
   if (nr_req > VCOPY_VEC_SIZE) return(EINVAL);
   bytes = nr_req * sizeof(struct vir_cp_req);
 
   /* Calculate physical addresses and copy (port,value)-pairs from user. */
-  caller_vir = (vir_bytes) m_ptr->VCP_VEC_ADDR;
-  caller_phys = umap_local(proc_addr(who_p), D, caller_vir, bytes);
-  if (0 == caller_phys) return(EFAULT);
-  kernel_phys = vir2phys(vir_cp_req);
-  phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
+  src.segment = dst.segment = D;
+  src.proc_nr_e = who_e;
+  dst.proc_nr_e = SYSTEM;
+  dst.offset = (vir_bytes) vir_cp_req;
+  src.offset = (vir_bytes) m_ptr->VCP_VEC_ADDR;
+
+  if((r=virtual_copy_vmcheck(&src, &dst, bytes)) != OK)
+       return r;
 
   /* Assume vector with requests is correct. Try to copy everything. */
   m_ptr->VCP_NR_OK = 0;
@@ -62,7 +68,7 @@ register message *m_ptr;      /* pointer to request message */
       /* Check if physical addressing is used without SYS_PHYSVCOPY. */
       if (((req->src.segment | req->dst.segment) & PHYS_SEG) &&
               m_ptr->m_type != SYS_PHYSVCOPY) return(EPERM);
-      if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK) 
+      if ((s=virtual_copy_vmcheck(&req->src, &req->dst, req->count)) != OK) 
           return(s);
       m_ptr->VCP_NR_OK ++;
   }
index 268d25baa59c2adbcf38037941e5b6181d4dd245..9fe1a3c64b68bf99c6d9d4ce47a776315ca163e6 100644 (file)
@@ -36,14 +36,13 @@ register message *m_ptr;    /* pointer to request message */
   int vec_size;               /* size of vector */
   int io_in;                  /* true if input */
   size_t bytes;               /* # bytes to be copied */
-  vir_bytes caller_vir;       /* virtual address at caller */
-  phys_bytes caller_phys;     /* physical address at caller */
   port_t port;
   int i, j, io_size, nr_io_range;
   int io_dir, io_type;
   struct proc *rp;
   struct priv *privp;
   struct io_range *iorp;
+  int r;
     
   /* Get the request, size of the request vector, and check the values. */
   io_dir = m_ptr->DIO_REQUEST & _DIO_DIRMASK;
@@ -69,11 +68,10 @@ register message *m_ptr;    /* pointer to request message */
   }
   if (bytes > sizeof(vdevio_buf))  return(E2BIG);
 
-  /* Calculate physical addresses and copy (port,value)-pairs from user. */
-  caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
-  caller_phys = umap_local(proc_addr(who_p), D, caller_vir, bytes);
-  if (0 == caller_phys) return(EFAULT);
-  phys_copy(caller_phys, vir2phys(vdevio_buf), (phys_bytes) bytes);
+  /* Copy (port,value)-pairs from user. */
+  if((r=data_copy(who_e, (vir_bytes) m_ptr->DIO_VEC_ADDR,
+    SYSTEM, (vir_bytes) vdevio_buf, bytes)) != OK)
+       return r;
 
   rp= proc_addr(who_p);
   privp= priv(rp);
@@ -110,7 +108,20 @@ register message *m_ptr;   /* pointer to request message */
    * the entire switch is wrapped in lock() and unlock() to prevent the I/O
    * batch from being interrupted. 
    */  
-  lock(13, "do_vdevio");
+#if 0
+  if(who_e == 71091)  {
+       static int vd = 0;
+       if(vd++ < 100) {
+                 kprintf("proc %d does vdevio no %d; type %d, direction %s\n",
+               who_e, vd, io_type, io_in ? "input" : "output");
+               kprintf("(");
+               for (i=0; i<vec_size; i++) 
+                       kprintf("%2d:0x%x,0x%x  ", i, pvb[i].port, pvb[i].value); 
+               kprintf(")\n");
+       }
+  }
+#endif
+  lock;
   switch (io_type) {
   case _DIO_BYTE:                                       /* byte values */
       if (io_in) for (i=0; i<vec_size; i++) 
@@ -158,14 +169,18 @@ register message *m_ptr;  /* pointer to request message */
        }
       }
   }
-  unlock(13);
+  unlock;
     
   /* Almost done, copy back results for input requests. */
-  if (io_in) phys_copy(vir2phys(vdevio_buf), caller_phys, (phys_bytes) bytes);
+  if (io_in) 
+       if((r=data_copy(SYSTEM, (vir_bytes) vdevio_buf, 
+         who_e, (vir_bytes) m_ptr->DIO_VEC_ADDR,
+         (phys_bytes) bytes)) != OK)
+               return r;
   return(OK);
 
 bad:
-       panic("do_vdevio: unaligned port\n", port);
+       minix_panic("do_vdevio: unaligned port", port);
        return EPERM;
 }
 
diff --git a/kernel/system/do_vm.c b/kernel/system/do_vm.c
deleted file mode 100644 (file)
index 0dc837a..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* The system call implemented in this file:
- *   m_type:   SYS_VM_MAP
- *
- * The parameters for this system call are:
- *    m4_l1:   Process that requests map (VM_MAP_ENDPT)
- *    m4_l2:   Map (TRUE) or unmap (FALSE) (VM_MAP_MAPUNMAP)
- *    m4_l3:   Base address (VM_MAP_BASE)
- *    m4_l4:   Size  (VM_MAP_SIZE)
- *    m4_l5:   address  (VM_MAP_ADDR)
- */
-#include "../system.h"
-
-PRIVATE int vm_needs_init= 1;
-
-#include <sys/vm.h>
-
-/*===========================================================================*
- *                             do_vm_map                                    *
- *===========================================================================*/
-PUBLIC int do_vm_map(m_ptr)
-message *m_ptr;                        /* pointer to request message */
-{
-       int proc_nr, do_map;
-       phys_bytes base, size, offset, p_phys;
-       struct proc *pp;
-
-       /* do_serial_debug= 1; */
-       if (vm_needs_init)
-       {
-               vm_needs_init= 0;
-               vm_init();
-       }
-
-       if (m_ptr->VM_MAP_ENDPT == SELF) {
-               proc_nr = who_p;
-       } else {
-               if(!isokendpt(m_ptr->VM_MAP_ENDPT, &proc_nr))
-                       return EINVAL;
-       }
-
-       do_map= m_ptr->VM_MAP_MAPUNMAP;
-       base= m_ptr->VM_MAP_BASE;
-       size= m_ptr->VM_MAP_SIZE;
-       offset= m_ptr->VM_MAP_ADDR;
-
-       pp= proc_addr(proc_nr);
-       p_phys= umap_local(pp, D, base, size);
-       if (p_phys == 0)
-               return EFAULT;
-
-       if (do_map)
-       {
-               pp->p_misc_flags |= MF_VM;
-
-               vm_map_range(p_phys, size, offset);
-       }
-       else
-       {
-               vm_map_range(p_phys, size, p_phys);
-       }
-
-       return OK;
-}
-
-
-/*===========================================================================*
- *                             vm_map_default                               *
- *===========================================================================*/
-PUBLIC void vm_map_default(pp)
-struct proc *pp;
-{
-       phys_bytes base_clicks, size_clicks;
-
-       if (vm_needs_init)
-               panic("vm_map_default: VM not initialized?", NO_NUM);
-       pp->p_misc_flags &= ~MF_VM;
-       base_clicks= pp->p_memmap[D].mem_phys;
-       size_clicks= pp->p_memmap[S].mem_phys+pp->p_memmap[S].mem_len -
-               base_clicks;
-       vm_map_range(base_clicks << CLICK_SHIFT,
-               size_clicks << CLICK_SHIFT, base_clicks << CLICK_SHIFT);
-}
-
diff --git a/kernel/system/do_vmctl.c b/kernel/system/do_vmctl.c
new file mode 100644 (file)
index 0000000..8517c57
--- /dev/null
@@ -0,0 +1,104 @@
+/* The kernel call implemented in this file:
+ *   m_type:   SYS_VMCTL
+ *
+ * The parameters for this kernel call are:
+ *     SVMCTL_WHO      which process
+ *     SVMCTL_PARAM    set this setting (VMCTL_*)
+ *     SVMCTL_VALUE    to this value
+ */
+
+#include "../system.h"
+#include "../vm.h"
+#include "../debug.h"
+#include <minix/type.h>
+
+/*===========================================================================*
+ *                             do_vmctl                                     *
+ *===========================================================================*/
+PUBLIC int do_vmctl(m_ptr)
+register message *m_ptr;       /* pointer to request message */
+{
+  int proc_nr, i;
+  endpoint_t ep = m_ptr->SVMCTL_WHO;
+  struct proc *p, *rp;
+
+  if(ep == SELF) { ep = m_ptr->m_source; }
+
+  vm_init();
+
+  if(m_ptr->m_source != VM_PROC_NR) {
+       kprintf("do_vmctl: source %d, not VM\n", m_ptr->m_source);
+       return ENOSYS;
+  }
+
+  if(!isokendpt(ep, &proc_nr)) {
+       kprintf("do_vmctl: unexpected endpoint %d from VM\n", ep);
+       return EINVAL;
+  }
+
+  p = proc_addr(proc_nr);
+
+  switch(m_ptr->SVMCTL_PARAM) {
+       case VMCTL_CLEAR_PAGEFAULT:
+               RTS_LOCK_UNSET(p, PAGEFAULT);
+               return OK;
+       case VMCTL_MEMREQ_GET:
+               /* Send VM the information about the memory request.  */
+               if(!(rp = vmrequest))
+                       return ESRCH;
+               if(!RTS_ISSET(rp, VMREQUEST))
+                       minix_panic("do_vmctl: no VMREQUEST set", NO_NUM);
+
+               /* Reply with request fields. */
+               m_ptr->SVMCTL_MRG_ADDR = (char *) rp->p_vmrequest.start;
+               m_ptr->SVMCTL_MRG_LEN = rp->p_vmrequest.length;
+               m_ptr->SVMCTL_MRG_WRITE = rp->p_vmrequest.writeflag;
+               m_ptr->SVMCTL_MRG_EP = rp->p_vmrequest.who;
+               rp->p_vmrequest.vmresult = VMSUSPEND;
+
+               /* Remove from request chain. */
+               vmrequest = vmrequest->p_vmrequest.nextrequestor;
+
+               return OK;
+       case VMCTL_MEMREQ_REPLY:
+               if(!(rp = p->p_vmrequest.requestor))
+                       minix_panic("do_vmctl: no requestor set", ep);
+               p->p_vmrequest.requestor = NULL;
+               if(!RTS_ISSET(rp, VMREQUEST))
+                       minix_panic("do_vmctl: no VMREQUEST set", ep);
+               if(rp->p_vmrequest.vmresult != VMSUSPEND)
+                       minix_panic("do_vmctl: result not VMSUSPEND set",
+                               rp->p_vmrequest.vmresult);
+               rp->p_vmrequest.vmresult = m_ptr->SVMCTL_VALUE;
+               if(rp->p_vmrequest.vmresult == VMSUSPEND)
+                       minix_panic("VM returned VMSUSPEND?", NO_NUM);
+               if(rp->p_vmrequest.vmresult != OK)
+                       kprintf("SYSTEM: VM replied %d to mem request\n",
+                               rp->p_vmrequest.vmresult);
+
+               /* Put on restart chain. */
+               rp->p_vmrequest.nextrestart = vmrestart;
+               vmrestart = rp;
+
+#if DEBUG_VMASSERT
+               /* Sanity check. */
+               if(rp->p_vmrequest.vmresult == OK) {
+                       if(CHECKRANGE(p,
+                               rp->p_vmrequest.start,
+                               rp->p_vmrequest.length,
+                               rp->p_vmrequest.writeflag) != OK) {
+kprintf("SYSTEM: request %d:0x%lx-0x%lx, wrflag %d, failed\n",
+       rp->p_endpoint,
+       rp->p_vmrequest.start,  rp->p_vmrequest.start + rp->p_vmrequest.length,
+       rp->p_vmrequest.writeflag); 
+       
+                               minix_panic("SYSTEM: fail but VM said OK", NO_NUM);
+                       }
+               }
+#endif
+               return OK;
+  }
+
+  /* Try architecture-specific vmctls. */
+  return arch_do_vmctl(m_ptr, p);
+}
index dd2e5c2edb29163267b904660ddb58bf17566be9..594370af5abb12854d7ff807cd7243a49794b52c 100755 (executable)
@@ -68,7 +68,8 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
 #define NUL_M   0
 #define SRV_M  (~0)
 #define SYS_M  (~0)
-#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(SYSTEM))
+#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(SYSTEM) | \
+       s(VM_PROC_NR))
 #define DRV_M (USR_M | s(SYSTEM) | s(CLOCK) | s(DS_PROC_NR) | s(LOG_PROC_NR) | s(TTY_PROC_NR))
 
 /* Define kernel calls that processes are allowed to make. This is not looking
@@ -90,10 +91,11 @@ PRIVATE int
   pm_c[] = { SYS_ALL_CALLS },
   rs_c[] = { SYS_ALL_CALLS },
   ds_c[] = { SYS_ALL_CALLS },
+  vm_c[] = { SYS_ALL_CALLS },
   drv_c[] = { DRV_C },
-  tty_c[] = { DRV_C, SYS_PHYSCOPY, SYS_ABORT, SYS_VM_MAP, SYS_IOPENABLE,
+  tty_c[] = { DRV_C, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
                SYS_READBIOS },
-  mem_c[] = { DRV_C, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_VM_MAP, SYS_IOPENABLE };
+  mem_c[] = { DRV_C, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_IOPENABLE };
 
 /* The system image table lists all programs that are part of the boot image. 
  * The order of the entries here MUST agree with the order of the programs
@@ -122,6 +124,7 @@ PUBLIC struct boot_image image[] = {
 {MEM_PROC_NR,   0,SRV_F,  4,      2, 0,     SRV_T, SYS_M,c(mem_c),"memory"},
 {LOG_PROC_NR,   0,SRV_F,  4,      2, 0,     SRV_T, SYS_M,c(drv_c),"log"   },
 {MFS_PROC_NR,   0,SRV_F, 32,      4, 0,     SRV_T, SRV_M, c(fs_c),"mfs"   },
+{VM_PROC_NR,    0,SRV_F, 32,      3, 0,     SRV_T, SRV_M, c(vm_c),"vm"    },
 {INIT_PROC_NR,  0,USR_F,  8, USER_Q, 0,     USR_T, USR_M, no_c,"init"  },
 };
 
index 6f3bff9d101d1745a68e7605eea4fc544859efb0..98687b0897a038478a7210fdd45a6ec4057884c0 100755 (executable)
@@ -27,13 +27,6 @@ struct boot_image {
   endpoint_t endpoint;                 /* endpoint number when started */
 };
 
-/* The kernel outputs diagnostic messages in a circular buffer. */
-struct kmessages {
-  int km_next;                         /* next index to write */
-  int km_size;                         /* current size in buffer */
-  char km_buf[KMESS_BUF_SIZE];         /* buffer for messages */
-};
-
 struct randomness {
   struct {
        int r_next;                             /* next index to write */
@@ -57,4 +50,14 @@ typedef struct irq_hook {
 
 typedef int (*irq_handler_t)(struct irq_hook *);
 
+/* Timing measurements. */
+struct lock_timingdata {
+        char names[TIMING_NAME];
+        unsigned long lock_timings[TIMING_POINTS];
+        unsigned long lock_timings_range[2];
+        unsigned long binsize, resets, misses, measurements;
+};
+EXTERN struct lock_timingdata timingdata[TIMING_CATEGORIES];
+
+
 #endif /* TYPE_H */
index 07c8a2744df45052937970db5b65e262923a2549..b7377b1cc9b5748dff46795e28ba699715fa6299 100755 (executable)
@@ -1,5 +1,5 @@
 /* This file contains a collection of miscellaneous procedures:
- *   panic:        abort MINIX due to a fatal error
+ *   minix_panic:    abort MINIX due to a fatal error
  *   kprintf:       (from lib/sysutil/kprintf.c)
  *   kputc:         buffered putc used by kernel kprintf
  */
@@ -9,26 +9,32 @@
 
 #include <unistd.h>
 #include <signal.h>
+#include <string.h>
+
+#include <minix/sysutil.h>
+#include <minix/sys_config.h>
 
 /*===========================================================================*
- *                             panic                                        *
+ *                     minix_panic                                        *
  *===========================================================================*/
-PUBLIC void panic(mess,nr)
-_CONST char *mess;
+PUBLIC void minix_panic(mess,nr)
+char *mess;
 int nr;
 {
 /* The system has run aground of a fatal kernel error. Terminate execution. */
-  static int panicking = 0;
-  if (panicking ++) return;            /* prevent recursive panics */
+  if (minix_panicing ++) return;               /* prevent recursive panics */
 
   if (mess != NULL) {
-       kprintf("\nKernel panic: %s", mess);
-       if (nr != NO_NUM) kprintf(" %d", nr);
+       kprintf("kernel panic: %s", mess);
+       if(nr != NO_NUM)
+               kprintf(" %d", nr);
        kprintf("\n");
+       kprintf("kernel stacktrace: ");
+       util_stacktrace();
   }
 
   /* Abort MINIX. */
-  prepare_shutdown(RBT_PANIC);
+  minix_shutdown(NULL);
 }
 
 
@@ -36,6 +42,7 @@ int nr;
 
 #define printf kprintf
 #include "../lib/sysutil/kprintf.c"
+
 #define END_OF_KMESS   0
 
 /*===========================================================================*
@@ -54,11 +61,12 @@ int c;                                      /* character to append */
        ser_putc(c);
       }
       kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
-      if (kmess.km_size < KMESS_BUF_SIZE)
+      if (kmess.km_size < sizeof(kmess.km_buf))
           kmess.km_size += 1;          
-      kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
+      kmess.km_next = (kmess.km_next + 1) % _KMESS_BUF_SIZE;
   } else {
       int p, outprocs[] = OUTPUT_PROCS_ARRAY;
+      if(minix_panicing) return;
       for(p = 0; outprocs[p] != NONE; p++) {
         if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
            send_sig(outprocs[p], SIGKMESS);
diff --git a/kernel/vm.h b/kernel/vm.h
new file mode 100644 (file)
index 0000000..9e0b615
--- /dev/null
@@ -0,0 +1,20 @@
+
+#ifndef _VM_H
+#define _VM_H 1
+
+#define CHECKRANGE_OR_SUSPEND(pr, start, length, wr)  { int mr; \
+       if(vm_running && (mr=vm_checkrange(proc_addr(who_p), pr, start, length, wr, 0)) != OK) { \
+               return mr;                                       \
+       } }
+
+#define CHECKRANGE(pr, start, length, wr)   \
+       vm_checkrange(proc_addr(who_p), pr, start, length, wr, 1)
+
+/* Pseudo error code indicating a process request has to be
+ * restarted after an OK from VM.
+ */
+#define VMSUSPEND       -996
+
+#endif
+
+
index 2bf999a2291b9917f1452dadf2d0d39064e7c84d..61f6c87adff223f7107c052931d097873e9692ff 100644 (file)
@@ -27,6 +27,7 @@ libc_FILES=" \
        _sprofile.c \
        _svrctl.c \
        _sysuname.c \
+       _vm_dmacalls.c \
        asynchio.c \
        basename.c \
        bcmp.c \
index 0dde289221661cfd197c65da2fa2eeb22ac9c98f..d86813cb2b1864071a6190ab142761b309a11391 100644 (file)
@@ -6,9 +6,10 @@
 PUBLIC int getnprocnr(pid_t pid)
 {
   message m;
+  int t = GETPROCNR;
   m.m1_i1 = pid;               /* pass pid >=0 to search for */
   m.m1_i2 = 0;                 /* don't pass name to search for */
-  if (_syscall(PM_PROC_NR, GETPROCNR, &m) < 0) return(-1);
+  if (_syscall(PM_PROC_NR, t, &m) < 0) return(-1);
   return(m.m1_i1);             /* return search result */
 }
 
diff --git a/lib/other/_vm_dmacalls.c b/lib/other/_vm_dmacalls.c
new file mode 100644 (file)
index 0000000..1723408
--- /dev/null
@@ -0,0 +1,62 @@
+
+#include <lib.h>
+#define vm_adddma      _vm_adddma
+#define vm_deldma      _vm_deldma
+#define vm_getdma      _vm_getdma
+#include <minix/vm.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+int vm_adddma(req_proc_e, proc_e, start, size)
+endpoint_t req_proc_e;
+endpoint_t proc_e;
+phys_bytes start;
+phys_bytes size;
+{
+  message m;
+
+  m.VMAD_REQ= req_proc_e;
+  m.VMAD_EP= proc_e;
+  m.VMAD_START= start;
+  m.VMAD_SIZE= size;
+
+  return _syscall(VM_PROC_NR, VM_ADDDMA, &m);
+}
+
+int vm_deldma(req_proc_e, proc_e, start, size)
+endpoint_t req_proc_e;
+endpoint_t proc_e;
+phys_bytes start;
+phys_bytes size;
+{
+  message m;
+
+  m.VMDD_REQ= proc_e;
+  m.VMDD_EP= proc_e;
+  m.VMDD_START= start;
+  m.VMDD_SIZE= size;
+
+  return _syscall(VM_PROC_NR, VM_DELDMA, &m);
+}
+
+int vm_getdma(req_proc_e, procp, basep, sizep)
+endpoint_t req_proc_e;
+endpoint_t *procp;
+phys_bytes *basep;
+phys_bytes *sizep;
+{
+  int r;
+  message m;
+
+  m.VMGD_REQ = req_proc_e;
+
+  r= _syscall(VM_PROC_NR, VM_GETDMA, &m);
+  if (r == 0)
+  {
+       *procp= m.VMGD_PROCP;
+       *basep= m.VMGD_BASEP;
+       *sizep= m.VMGD_SIZEP;
+  }
+  return r;
+}
+
index 21c313f12c982f79625b1491dfd79cd6e350b3e6..1e2bee8b3163a7a91a2e5c3b611ba62b77a3ffd0 100644 (file)
@@ -55,6 +55,7 @@ libc_FILES=" \
        _mkfifo.c \
        _mknod.c \
        _mount.c \
+       _mmap.c \
        _open.c \
        _opendir.c \
        _pathconf.c \
@@ -101,6 +102,7 @@ libc_FILES=" \
        getloadavg.c \
        getopt.c \
        gettimeofday.c \
+       glob.c \
        nice.c \
        priority.c \
        usleep.c"
diff --git a/lib/posix/_mmap.c b/lib/posix/_mmap.c
new file mode 100755 (executable)
index 0000000..4dbbbc8
--- /dev/null
@@ -0,0 +1,40 @@
+#define _SYSTEM 1
+#include <lib.h>
+#define mmap   _mmap
+#define munmap _munmap
+#include <sys/mman.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+PUBLIC void *mmap(void *addr, size_t len, int prot, int flags,
+       int fd, off_t offset)
+{
+       message m;
+       int r;
+
+       m.VMM_ADDR = (vir_bytes) addr;
+       m.VMM_LEN = len;
+       m.VMM_PROT = prot;
+       m.VMM_FLAGS = flags;
+       m.VMM_FD = fd;
+       m.VMM_OFFSET = offset;
+
+       r = _syscall(VM_PROC_NR, VM_MMAP, &m);
+
+       if(r != OK) {
+               return MAP_FAILED;
+       }
+
+       return (void *) m.VMM_RETADDR;
+}
+
+PUBLIC int munmap(void *addr, size_t len)
+{
+       message m;
+
+       m.VMUM_ADDR = addr;
+       m.VMUM_LEN = len;
+
+       return _syscall(VM_PROC_NR, VM_UNMAP, &m);
+}
index 2d6976d198c397ade3425019b9ed2c93eaebca99..82fceba1c4e5d96cd1d244076402eaba85895281 100755 (executable)
@@ -28,7 +28,7 @@ int getloadavg(double *loadavg, int nelem)
        nelem = PERIODS;
 
   /* How many ticks are missing from the newest-filled slot? */
-#define TICKSPERSLOT (_LOAD_UNIT_SECS * HZ)
+#define TICKSPERSLOT (_LOAD_UNIT_SECS * sys_hz())
   unfilled_ticks = TICKSPERSLOT - (loadinfo.last_clock % TICKSPERSLOT);
 
   for(p = 0; p < nelem; p++) {
index ea657d580d68c6c8d5fb71527aaa736e929bad26..3efdcb25556ffa45afef84c9be5065a34df9c4cd 100644 (file)
@@ -2,7 +2,7 @@
 
 Z=../../commands/zoneinfo
 
-CFLAGS="-O -D_MINIX -D_POSIX_SOURCE -D__USG -I$Z"
+CFLAGS="-D_MINIX -D_POSIX_SOURCE -D__USG -I$Z"
 
 LIBRARIES=libc
 libc_FILES="
index 7ccfc22fd450f4e59107d56a50bfcc3f8024d59a..403883f386a783a36740a60f9663c4b90ba0338b 100644 (file)
@@ -67,6 +67,7 @@ libc_FILES=" \
        mkdir.s \
        mkfifo.s \
        mknod.s \
+       mmap.s \
        mount.s \
        open.s \
        opendir.s \
@@ -119,6 +120,7 @@ libc_FILES=" \
        uname.s \
        unlink.s \
        utime.s \
+       vm_dmacalls.s \
        wait.s \
        waitpid.s \
        write.s"
diff --git a/lib/syscall/mmap.s b/lib/syscall/mmap.s
new file mode 100755 (executable)
index 0000000..6066432
--- /dev/null
@@ -0,0 +1,7 @@
+.sect .text
+.extern        __mmap
+.define        _mmap
+.align 2
+
+_mmap:
+       jmp     __mmap
diff --git a/lib/syscall/vm_dmacalls.s b/lib/syscall/vm_dmacalls.s
new file mode 100644 (file)
index 0000000..920af0d
--- /dev/null
@@ -0,0 +1,16 @@
+.sect .text
+.extern        __vm_adddma
+.define        _vm_adddma
+.extern        __vm_deldma
+.define        _vm_deldma
+.extern        __vm_getdma
+.define        _vm_getdma
+.align 2
+
+_vm_adddma:
+       jmp     __vm_adddma
+_vm_deldma:
+       jmp     __vm_deldma
+_vm_getdma:
+       jmp     __vm_getdma
+
index 2a33f6e660e0d7c35e0b4bf962bb5224aaaf7cee..76d246b0465355b3310a1b1b8c7f74ae712ace5e 100644 (file)
@@ -5,6 +5,7 @@ CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
 LIBRARIES=libsys
 
 libsys_FILES=" \
+       alloc_util.c \
        assert.c \
        panic.c \
        pci_attr_r16.c \
@@ -64,12 +65,20 @@ libsys_FILES=" \
        sys_vinl.c \
        sys_vinw.c \
        sys_vircopy.c \
-       sys_vm_map.c \
        sys_vm_setbuf.c \
+       sys_vmctl.c \
        sys_voutb.c \
        sys_voutl.c \
        sys_voutw.c \
        taskcall.c \
-       ds.c"
+       ds.c    \
+       vm_allocmem.c \
+       vm_brk.c \
+       vm_exec_newmem.c \
+       vm_exit.c \
+       vm_fork.c \
+       vm_map_phys.c \
+       vm_umap.c \
+       vm_push_sig.c"
 
 TYPE=both
diff --git a/lib/syslib/alloc_util.c b/lib/syslib/alloc_util.c
new file mode 100644 (file)
index 0000000..269b3b4
--- /dev/null
@@ -0,0 +1,69 @@
+
+#include "syslib.h"
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <minix/sysutil.h>
+
+int sys_umap_data_fb(endpoint_t ep, vir_bytes buf, vir_bytes len, phys_bytes *phys)
+{
+       int r;
+
+        if((r=sys_umap(ep, VM_D, buf, len, phys)) != OK) {
+               if(r != EINVAL)
+                       return r;
+               r = sys_umap(ep, D, buf, len, phys);
+       }
+
+
+       return r;
+}
+
+
+void *alloc_contig(size_t len, int flags, phys_bytes *phys)
+{
+       int r;
+       vir_bytes buf;
+       int mmapflags = MAP_PREALLOC|MAP_CONTIG|MAP_ANON;
+
+       if(flags & AC_LOWER16M)
+               mmapflags |= MAP_LOWER16M;
+
+       /* First try to get memory with mmap. This is gauranteed
+        * to be page-aligned, and we can tell VM it has to be
+        * pre-allocated and contiguous.
+        */
+       errno = 0;
+       buf = (vir_bytes) mmap(0, len, PROT_READ|PROT_WRITE, mmapflags, -1, 0);
+
+       /* If that failed, maybe we're not running in paged mode.
+        * If that's the case, ENXIO will be returned.
+        * Memory returned with malloc() will be preallocated and 
+        * contiguous, so fallback on that, and ask for a little extra
+        * so we can page align it ourselves.
+        */
+       if(buf == (vir_bytes) MAP_FAILED) {
+               if(errno != (_SIGN ENXIO)) {
+                       return NULL;
+               }
+#define ALIGN 4096
+               if(flags & AC_ALIGN4K) {
+                       if(len + ALIGN < len)
+                               return NULL;
+                       len += ALIGN;
+               }
+               if(!(buf = (vir_bytes) malloc(len))) {
+                       return NULL;
+               }
+               if(flags & AC_ALIGN4K)
+                       buf += ALIGN - (buf % ALIGN);
+       }
+
+       /* Get physical address. */
+        if(sys_umap_data_fb(SELF, buf, len, phys) != OK)
+               panic("alloc_contig.c", "sys_umap_data_fb failed", NO_NUM);
+
+       return (void *) buf;
+}
+
index d2b3696412864b4a78304636b965cc7bbc8fb982..833fd943ed0d10a6ba723d94cfe20dfdd6870717 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "syslib.h"
 
+#define GRANTBAD -1001
+
 int
 ds_subscribe(ds_name_regexp, type, flags)
 char *ds_name_regexp;
@@ -20,7 +22,7 @@ int flags;
                (vir_bytes) ds_name_regexp, len, CPF_READ);
 
        if(!GRANT_VALID(g)) 
-               return -1;
+               return GRANTBAD;
 
        flags &= DS_INITIAL;
 
@@ -49,7 +51,7 @@ u32_t value;
                (vir_bytes) ds_name, len, CPF_READ);
 
        if(!GRANT_VALID(g)) 
-               return -1;
+               return GRANTBAD;
 
        m.DS_KEY_GRANT = (char *) g;
        m.DS_KEY_LEN = len;
@@ -78,7 +80,7 @@ char *value;
        g_key = cpf_grant_direct(DS_PROC_NR,
                (vir_bytes) ds_name, len_key, CPF_READ);
        if(!GRANT_VALID(g_key)) 
-               return -1;
+               return GRANTBAD;
 
        /* Grant for value. */
        len_str = strlen(value)+1;
@@ -87,7 +89,7 @@ char *value;
 
        if(!GRANT_VALID(g_str))  {
                cpf_revoke(g_key);
-               return -1;
+               return GRANTBAD;
        }
 
        m.DS_KEY_GRANT = (char *) g_key;
@@ -118,7 +120,7 @@ u32_t *value;
        g_key = cpf_grant_direct(DS_PROC_NR,
                (vir_bytes) ds_name, len_key, CPF_READ);
        if(!GRANT_VALID(g_key)) 
-               return -1;
+               return GRANTBAD;
 
        /* Do request. */
        m.DS_KEY_GRANT = (char *) g_key;
@@ -150,7 +152,7 @@ size_t len_str;
        g_key = cpf_grant_direct(DS_PROC_NR,
                (vir_bytes) ds_name, len_key, CPF_READ);
        if(!GRANT_VALID(g_key)) 
-               return -1;
+               return GRANTBAD;
 
        /* Grant for value. */
        g_str = cpf_grant_direct(DS_PROC_NR,
@@ -158,7 +160,7 @@ size_t len_str;
 
        if(!GRANT_VALID(g_str))  {
                cpf_revoke(g_key);
-               return -1;
+               return GRANTBAD;
        }
 
        /* Do request. */
@@ -187,13 +189,13 @@ size_t len_str;
        message m;
        cp_grant_id_t g_key, g_str;
 
-       if(len_key < 1 || len_str < 1) return -1;
+       if(len_key < 1 || len_str < 1) return -1002;
 
        /* Grant for key. */
        g_key = cpf_grant_direct(DS_PROC_NR,
                (vir_bytes) ds_key, len_key, CPF_WRITE);
        if(!GRANT_VALID(g_key)) 
-               return -1;
+               return GRANTBAD;
 
        /* Grant for value. */
        g_str = cpf_grant_direct(DS_PROC_NR,
@@ -201,7 +203,7 @@ size_t len_str;
 
        if(!GRANT_VALID(g_str))  {
                cpf_revoke(g_key);
-               return -1;
+               return GRANTBAD;
        }
 
        /* Do request. */
@@ -238,7 +240,7 @@ u32_t *value;
        g_key = cpf_grant_direct(DS_PROC_NR,
                (vir_bytes) ds_key, len_key, CPF_WRITE);
        if(!GRANT_VALID(g_key)) 
-               return -1;
+               return GRANTBAD;
 
        /* Do request. */
        m.DS_KEY_GRANT = (char *) g_key;
index 89d3a41ac7c1da5b7da1825cbd4d1b7b4d83f1dd..a40cab8ae6b7b708fa6a5240522678c471ce8d35 100644 (file)
@@ -19,9 +19,19 @@ int num;                     /* number to go with format string */
  * value of a defined constant.
  */
   message m;
+  endpoint_t me = NONE;
+  char name[20];
   void (*suicide)(void);
-
+  if(panicing) return;
   panicing= 1;
+
+  if(sys_whoami(&me, name, sizeof(name)) == OK && me != NONE)
+       printf("%s(%d): ", name, me);
+  else
+       printf("(sys_whoami failed): ");
+  printf("syslib:panic.c: stacktrace: ");
+  util_stacktrace();
+
   if (NULL != who && NULL != mess) {
       if (num != NO_NUM) {
           printf("Panic in %s: %s: %d\n", who, mess, num); 
@@ -39,12 +49,10 @@ int num;                    /* number to go with format string */
   /* If exiting nicely through PM fails for some reason, try to
    * commit suicide. E.g., message to PM might fail due to deadlock.
    */
-  printf("panic: trying exception\n");
   suicide = (void (*)(void)) -1;
   suicide();
 
   /* If committing suicide fails for some reason, hang. */
-  printf("panic: for ever and ever\n");
   for(;;) { }
 }
 
index 845afc451f228922fff2f0ee60d6f23d14a1c5a1..d09a789e5db750425a4f4dd928c7baae373c6ac5 100644 (file)
@@ -52,8 +52,9 @@ cpf_grow(void)
        assert(new_size > ngrants);
 
        /* Allocate a block of new size. */
-       if(!(new_grants=malloc(new_size * sizeof(grants[0]))))
+       if(!(new_grants=malloc(new_size * sizeof(grants[0])))) {
                return;
+       }
 
        /* Copy old block to new block. */
        if(grants && ngrants > 0)
index fb0117d5fb596372821b7caf6935173e45d4fd99..8aef1b8caa5af25d81fdeaf0eccca4fb0ad25b80 100755 (executable)
@@ -1,10 +1,11 @@
 #include "syslib.h"
 
-PUBLIC int sys_fork(parent, child, child_endpoint, map_ptr)
-int parent;                    /* process doing the fork */
-int child;                     /* which proc has been created by the fork */
+PUBLIC int sys_fork(parent, child, child_endpoint, map_ptr, flags)
+endpoint_t parent;             /* process doing the fork */
+endpoint_t child;              /* which proc has been created by the fork */
 int *child_endpoint;
 struct mem_map *map_ptr;
+u32_t flags;
 {
 /* A process has forked.  Tell the kernel. */
 
@@ -14,6 +15,7 @@ struct mem_map *map_ptr;
   m.PR_ENDPT = parent;
   m.PR_SLOT = child;
   m.PR_MEM_PTR = (char *) map_ptr;
+  m.PR_FORK_FLAGS = flags;
   r = _taskcall(SYSTASK, SYS_FORK, &m);
   *child_endpoint = m.PR_ENDPT;
   return r;
index dd4bc43b9beafb9fb26af47bb637d558c70b5ae8..b712c6beecc22c513b2c224217cc07ac8f08f497 100644 (file)
@@ -1,3 +1,6 @@
+
+#include <string.h>
+
 #include "syslib.h"
 
 /*===========================================================================*
@@ -22,4 +25,29 @@ int len2;                            /* length or process nr */
     return(_taskcall(SYSTASK, SYS_GETINFO, &m));
 }
 
+/*===========================================================================*
+ *                                sys_whoami                                *
+ *===========================================================================*/
+PUBLIC int sys_whoami(endpoint_t *who_ep, char *who_name, int len)
+{
+       message m;
+       int r;
+       int lenmin;
+
+       m.I_REQUEST = GET_WHOAMI;
+
+       if(len < 2)
+               return EINVAL;
+
+       if((r = _taskcall(SYSTASK, SYS_GETINFO, &m)) != OK)
+               return r;
+
+       lenmin = MIN(len, sizeof(m.GIWHO_NAME)) - 1;
+
+       strncpy(who_name, m.GIWHO_NAME, lenmin);
+       who_name[lenmin] = '\0';
+       *who_ep = m.GIWHO_EP;
+
+       return OK;
+}
 
diff --git a/lib/syslib/sys_vm_map.c b/lib/syslib/sys_vm_map.c
deleted file mode 100644 (file)
index 6f4296d..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#include "syslib.h"
-
-/*===========================================================================*
- *                                sys_vm_map                                *
- *===========================================================================*/
-PUBLIC int sys_vm_map(proc_nr, do_map, base, size, offset)
-int proc_nr;
-int do_map;
-phys_bytes base;
-phys_bytes size;
-phys_bytes offset;
-{
-    message m;
-    int result;
-
-    m.m4_l1= proc_nr;
-    m.m4_l2= do_map;
-    m.m4_l3= base;
-    m.m4_l4= size;
-    m.m4_l5= offset;
-
-    result = _taskcall(SYSTASK, SYS_VM_MAP, &m);
-    return(result);
-}
-
diff --git a/lib/syslib/sys_vmctl.c b/lib/syslib/sys_vmctl.c
new file mode 100755 (executable)
index 0000000..8339a73
--- /dev/null
@@ -0,0 +1,61 @@
+#include "syslib.h"
+
+PUBLIC int sys_vmctl(endpoint_t who, int param, u32_t value)
+{
+  message m;
+  int r;
+
+  m.SVMCTL_WHO = who;
+  m.SVMCTL_PARAM = param;
+  m.SVMCTL_VALUE = value;
+  r = _taskcall(SYSTASK, SYS_VMCTL, &m);
+  return(r);
+}
+
+PUBLIC int sys_vmctl_get_pagefault_i386(endpoint_t *who, u32_t *cr2, u32_t *err)
+{
+  message m;
+  int r;
+
+  m.SVMCTL_WHO = SELF;
+  m.SVMCTL_PARAM = VMCTL_GET_PAGEFAULT;
+  r = _taskcall(SYSTASK, SYS_VMCTL, &m);
+  if(r == OK) {
+       *who = m.SVMCTL_PF_WHO;
+       *cr2 = m.SVMCTL_PF_I386_CR2;
+       *err = m.SVMCTL_PF_I386_ERR;
+  }
+  return(r);
+}
+
+PUBLIC int sys_vmctl_get_cr3_i386(endpoint_t who, u32_t *cr3)
+{
+  message m;
+  int r;
+
+  m.SVMCTL_WHO = who;
+  m.SVMCTL_PARAM = VMCTL_I386_GETCR3;
+  r = _taskcall(SYSTASK, SYS_VMCTL, &m);
+  if(r == OK) {
+       *cr3 = m.SVMCTL_VALUE;
+  }
+  return(r);
+}
+
+PUBLIC int sys_vmctl_get_memreq(endpoint_t *who, vir_bytes *mem,
+       vir_bytes *len, int *wrflag)
+{
+  message m;
+  int r;
+
+  m.SVMCTL_WHO = SELF;
+  m.SVMCTL_PARAM = VMCTL_MEMREQ_GET;
+  r = _taskcall(SYSTASK, SYS_VMCTL, &m);
+  if(r == OK) {
+       *who = m.SVMCTL_MRG_EP;
+       *mem = (vir_bytes) m.SVMCTL_MRG_ADDR;
+       *len = m.SVMCTL_MRG_LEN;
+       *wrflag = m.SVMCTL_MRG_WRITE;
+  }
+  return r;
+}
diff --git a/lib/syslib/vm_allocmem.c b/lib/syslib/vm_allocmem.c
new file mode 100644 (file)
index 0000000..64e1a79
--- /dev/null
@@ -0,0 +1,21 @@
+
+#include "syslib.h"
+
+#include <minix/vm.h>
+
+/*===========================================================================*
+ *                                vm_allocmem                               *
+ *===========================================================================*/
+PUBLIC int vm_allocmem(phys_clicks clicks, phys_clicks *retmembase)
+{
+    message m;
+    int result;
+
+    m.VMAM_CLICKS = clicks;
+    result = _taskcall(VM_PROC_NR, VM_ALLOCMEM, &m);
+    if(result == OK)
+           *retmembase = m.VMAM_MEMBASE;
+
+    return result;
+}
+
diff --git a/lib/syslib/vm_brk.c b/lib/syslib/vm_brk.c
new file mode 100644 (file)
index 0000000..f17da63
--- /dev/null
@@ -0,0 +1,19 @@
+
+#include "syslib.h"
+
+#include <minix/vm.h>
+
+/*===========================================================================*
+ *                                vm_brk                                    *
+ *===========================================================================*/
+PUBLIC int vm_brk(endpoint_t ep, char *addr)
+{
+    message m;
+    int result;
+
+    m.VMB_ENDPOINT = ep;
+    m.VMB_ADDR = (void *) addr;
+
+    return _taskcall(VM_PROC_NR, VM_BRK, &m);
+}
+
diff --git a/lib/syslib/vm_exec_newmem.c b/lib/syslib/vm_exec_newmem.c
new file mode 100644 (file)
index 0000000..3f13947
--- /dev/null
@@ -0,0 +1,26 @@
+
+#include "syslib.h"
+
+#include <minix/vm.h>
+
+/*===========================================================================*
+ *                                vm_exec_newmem                            *
+ *===========================================================================*/
+PUBLIC int vm_exec_newmem(endpoint_t ep, struct exec_newmem *args,
+       int argssize, char **ret_stack_top, int *ret_flags)
+{
+    message m;
+    int result;
+
+    m.VMEN_ENDPOINT = ep;
+    m.VMEN_ARGSPTR = (void *) args;
+    m.VMEN_ARGSSIZE = argssize;
+
+    result = _taskcall(VM_PROC_NR, VM_EXEC_NEWMEM, &m);
+
+    *ret_stack_top = m.VMEN_STACK_TOP;
+    *ret_flags = m.VMEN_FLAGS;
+
+    return result;
+}
+
diff --git a/lib/syslib/vm_exit.c b/lib/syslib/vm_exit.c
new file mode 100644 (file)
index 0000000..77500b2
--- /dev/null
@@ -0,0 +1,34 @@
+
+#include "syslib.h"
+
+#include <minix/vm.h>
+
+/*===========================================================================*
+ *                                vm_exit                                   *
+ *===========================================================================*/
+PUBLIC int vm_exit(endpoint_t ep)
+{
+    message m;
+    int result;
+
+    m.VME_ENDPOINT = ep;
+
+    result = _taskcall(VM_PROC_NR, VM_EXIT, &m);
+    return(result);
+}
+
+
+/*===========================================================================*
+ *                                vm_willexit                               *
+ *===========================================================================*/
+PUBLIC int vm_willexit(endpoint_t ep)
+{
+    message m;
+    int result;
+
+    m.VMWE_ENDPOINT = ep;
+
+    result = _taskcall(VM_PROC_NR, VM_WILLEXIT, &m);
+    return(result);
+}
+
diff --git a/lib/syslib/vm_fork.c b/lib/syslib/vm_fork.c
new file mode 100644 (file)
index 0000000..c67e2cb
--- /dev/null
@@ -0,0 +1,23 @@
+
+#include "syslib.h"
+
+#include <minix/vm.h>
+
+/*===========================================================================*
+ *                                vm_fork                                   *
+ *===========================================================================*/
+PUBLIC int vm_fork(endpoint_t ep, int slot, int *childep)
+{
+    message m;
+    int result;
+
+    m.VMF_ENDPOINT = ep;
+    m.VMF_SLOTNO = slot;
+
+    result = _taskcall(VM_PROC_NR, VM_FORK, &m);
+
+    *childep = m.VMF_CHILD_ENDPOINT;
+
+    return(result);
+}
+
diff --git a/lib/syslib/vm_map_phys.c b/lib/syslib/vm_map_phys.c
new file mode 100644 (file)
index 0000000..5eef161
--- /dev/null
@@ -0,0 +1,37 @@
+#define _SYSTEM 1
+#include <lib.h>
+#define vm_map_phys    _vm_map_phys
+#define vm_unmap_phys  _vm_unmap_phys
+#include <sys/mman.h>
+#include <minix/vm.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+PUBLIC void *vm_map_phys(endpoint_t who, size_t len, void *phaddr)
+{
+       message m;
+       int r;
+
+       m.VMMP_EP = who;
+       m.VMMP_PHADDR = phaddr;
+       m.VMMP_LEN = len;
+
+       r = _syscall(VM_PROC_NR, VM_MAP_PHYS, &m);
+
+       if(r != OK) return MAP_FAILED;
+
+       return (void *) m.VMMP_VADDR_REPLY;
+}
+
+PUBLIC int vm_unmap_phys(endpoint_t who, void *vaddr, size_t len)
+{
+       message m;
+       int r;
+
+       m.VMUP_EP = who;
+       m.VMUP_VADDR = vaddr;
+
+       return _syscall(VM_PROC_NR, VM_UNMAP_PHYS, &m);
+}
+
diff --git a/lib/syslib/vm_push_sig.c b/lib/syslib/vm_push_sig.c
new file mode 100644 (file)
index 0000000..1f994e5
--- /dev/null
@@ -0,0 +1,20 @@
+
+#include "syslib.h"
+
+#include <minix/vm.h>
+
+/*===========================================================================*
+ *                                vm_push_sig                       *
+ *===========================================================================*/
+PUBLIC int vm_push_sig(endpoint_t ep, vir_bytes *old_sp)
+{
+    message m;
+    int result;
+
+    m.VMPS_ENDPOINT = ep;
+    result = _taskcall(VM_PROC_NR, VM_PUSH_SIG, &m);
+    *old_sp = (vir_bytes)  m.VMPS_OLD_SP;
+
+    return result;
+}
+
diff --git a/lib/syslib/vm_umap.c b/lib/syslib/vm_umap.c
new file mode 100644 (file)
index 0000000..73db2fc
--- /dev/null
@@ -0,0 +1,22 @@
+
+#include "syslib.h"
+
+#include <minix/vm.h>
+
+/*===========================================================================*
+ *                                vm_umap                                   *
+ *===========================================================================*/
+PUBLIC int vm_umap(int seg, vir_bytes offset, vir_bytes len, phys_bytes *addr)
+{
+    message m;
+    int result;
+
+    m.VMU_SEG = seg;
+    m.VMU_OFFSET = offset;
+    m.VMU_LENGTH = len;
+    result = _taskcall(VM_PROC_NR, VM_UMAP, &m);
+    *addr = m.VMU_RETADDR;
+
+    return result;
+}
+
index 74717497eaa59ef96644298a1bc6adf1566a75ee..3082a19098363895c5a89244982bcb47fa429c58 100644 (file)
@@ -1,10 +1,11 @@
-# Makefile for lib/utils.
+# Makefile for lib/sysutil.
 
 CFLAGS="-O -D_MINIX -D_POSIX_SOURCE"
 
-LIBRARIES=libsysutil
+LIBRARIES=libsys
 
-libsysutil_FILES=" \
+libsys_FILES=" \
+       asynsend.c \
        kmalloc.c \
        kprintf.c \
        kputc.c \
@@ -21,6 +22,8 @@ libsysutil_FILES=" \
        taskcall.c \
        read_tsc.s \
        read_tsc_64.c \
+       stacktrace.c \
+       sys_hz.c \
        profile_extern.c \
        profile.c"
 
index 47309b50eaee9a5bdd567753ad9325d8028248d8..9f22547daf5cb0cd57a23199b0d50257d21a8f04 100644 (file)
@@ -9,7 +9,7 @@
 
 #include "sysutil.h"
 
-static char print_buf[80];     /* output is buffered here */
+static char print_buf[80*25];  /* output is buffered here */
 
 int kputc_use_private_grants= 0;
 
@@ -56,15 +56,22 @@ int c;
 
        for(p = 0; procs[p] != NONE; p++) {
                /* Send the buffer to this output driver. */
+               int may_asyn = 0;
                m.DIAG_BUF_COUNT = buf_count;
                if(GRANT_VALID(printgrants[p])) {
                        m.m_type = DIAGNOSTICS_S;
                        m.DIAG_PRINT_BUF_G = (char *) printgrants[p];
+                       may_asyn = 1;
                } else {
                        m.m_type = DIAGNOSTICS;
                        m.DIAG_PRINT_BUF_G = print_buf;
                }
-               (void) _sendrec(procs[p], &m);
+               if(may_asyn && procs[p] == LOG_PROC_NR) {
+                       m.m_type = ASYN_DIAGNOSTICS;
+                       (void) asynsend(procs[p], &m);
+               } else {
+                       sendrec(procs[p], &m);
+               }
        }
 
        buf_count = 0;
index 9789bfd81525244be4eb9e52ad7e9b3f24382199..773897943936957bb5c2c2e8be69433a75ebad3c 100644 (file)
 
 #include "sysutil.h"
 
-#define CALIBRATE_TICKS (HZ/5)
+#define CALIBRATE_TICKS(h) ((h)/5)
 #define MICROHZ                1000000         /* number of micros per second */
-#define MICROSPERTICK  (MICROHZ/HZ)    /* number of micros per HZ tick */
+#define MICROSPERTICK(h)       (MICROHZ/(h))   /* number of micros per HZ tick */
 
-static u32_t calib_tsc;
+#define CALIBRATE                                              \
+       if(!calibrated) {                                       \
+               int r;                                          \
+               if((r=micro_delay_calibrate()) != OK)           \
+                       panic(__FILE__, "micro_delay: calibrate failed\n", r); \
+       }
+
+static u32_t calib_tsc, Hz = 0;
 static int calibrated = 0;
 
 int
 micro_delay_calibrate(void)
 {
-       u64_t start, end, diff, hz;
+       u64_t start, end, diff;
        struct tms tms;
        unsigned long t = 0;
 
+       /* Get HZ. */
+       if(sys_getinfo(GET_HZ, &Hz, sizeof(Hz), 0, 0) != OK)
+               Hz = HZ;
+
        /* Wait for clock to tick. */
        while(!t || (t == times(&tms)))
                t = times(&tms);
@@ -34,7 +45,7 @@ micro_delay_calibrate(void)
         * this using the TSC.
         */
        read_tsc_64(&start);
-       while(times(&tms) < t+CALIBRATE_TICKS) ;
+       while(times(&tms) < t+CALIBRATE_TICKS(Hz)) ;
        read_tsc_64(&end);
 
        diff = sub64(end, start);
@@ -43,10 +54,12 @@ micro_delay_calibrate(void)
                "micro_delay_calibrate: CALIBRATE_TICKS too high "
                        "for TSC frequency\n", NO_NUM);
        calib_tsc = ex64lo(diff);
+#if 0
        printf("micro_delay_calibrate: "
                "%lu cycles/%d ticks of %d Hz; %lu cycles/s\n",
-                       calib_tsc, CALIBRATE_TICKS, HZ,
-                       div64u(mul64u(calib_tsc, HZ), CALIBRATE_TICKS));
+                       calib_tsc, CALIBRATE_TICKS(Hz), Hz,
+                       div64u(mul64u(calib_tsc, Hz), CALIBRATE_TICKS(Hz)));
+#endif
        calibrated = 1;
 
        return OK;
@@ -60,17 +73,11 @@ micro_delay(u32_t micros)
        /* Start of delay. */
        read_tsc_64(&now);
 
-       /* We have to be calibrated. */
-       if(!calibrated) {
-               int r;
-               printf("micro_delay: calibrating\n");
-               if((r=micro_delay_calibrate()) != OK)
-                       panic(__FILE__, "micro_delay: calibrate failed\n", r);
-       }
+       CALIBRATE;
 
        /* We have to know when to end the delay. */
        end = add64u(now, div64u(mul64u(calib_tsc,
-               micros * HZ / CALIBRATE_TICKS), MICROHZ));
+               micros * Hz / CALIBRATE_TICKS(Hz)), MICROHZ));
 
        /* If we have to wait for at least one HZ tick, use the regular
         * tickdelay first. Round downwards on purpose, so the average
@@ -78,8 +85,8 @@ micro_delay(u32_t micros)
         * we call tickdelay). We can correct for both overhead of tickdelay
         * itself and the short wait in the busywait later.
         */
-       if(micros >= MICROSPERTICK)
-               tickdelay(micros*HZ/MICROHZ);
+       if(micros >= MICROSPERTICK(Hz))
+               tickdelay(micros*Hz/MICROHZ);
 
        /* Wait (the rest) of the delay time using busywait. */
        while(cmp64(now, end) < 0)
@@ -87,3 +94,4 @@ micro_delay(u32_t micros)
 
        return OK;
 }
+
diff --git a/lib/sysutil/stacktrace.c b/lib/sysutil/stacktrace.c
new file mode 100644 (file)
index 0000000..377215d
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+stacktrace.c
+
+Created:       Jan 19, 1993 by Philip Homburg
+
+Copyright 1995 Philip Homburg
+*/
+
+typedef unsigned int reg_t;
+
+#define FUNC_STACKTRACE(statement)                             \
+{                                                              \
+       reg_t bp, pc, hbp;                                      \
+       extern reg_t get_bp(void);                              \
+                                                               \
+       bp= get_bp();                                           \
+       while(bp)                                               \
+       {                                                       \
+               pc= ((reg_t *)bp)[1];                           \
+               hbp= ((reg_t *)bp)[0];                          \
+               statement;                                      \
+               if (hbp != 0 && hbp <= bp)                      \
+               {                                               \
+                       pc = -1;                                \
+                       statement;                              \
+                       break;                                  \
+               }                                               \
+               bp= hbp;                                        \
+       }                                                       \
+}
+
+void util_nstrcat(char *str, unsigned long number)
+{
+       int n = 10, lead = 1;
+       char nbuf[12], *p;
+       p = nbuf;
+       *p++ = '0';
+       *p++ = 'x';
+       for(n = 0; n < 8; n++) {
+               int i;
+               i = (number >> ((7-n)*4)) & 0xF;
+               if(!lead || i) {
+                       *p++ = i < 10 ? '0' + i : 'a' + i - 10;
+                       lead = 0;
+               }
+       }
+       if(lead) *p++ = '0';
+       *p++ = ' ';
+       *p++ = '\0';
+       strcat(str, nbuf);
+}
+
+void util_stacktrace(void)
+{
+       FUNC_STACKTRACE(printf("0x%lx ", (unsigned long) pc));
+       printf("\n");
+}
+
+void util_stacktrace_strcat(char *str)
+{
+       FUNC_STACKTRACE(util_nstrcat(str, pc));
+}
+
diff --git a/lib/sysutil/sys_hz.c b/lib/sysutil/sys_hz.c
new file mode 100644 (file)
index 0000000..1013017
--- /dev/null
@@ -0,0 +1,41 @@
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <minix/u64.h>
+#include <minix/config.h>
+#include <minix/const.h>
+
+#include "sysutil.h"
+
+static u32_t Hz;
+
+u32_t
+sys_hz(void)
+{
+       if(Hz <= 0) {
+               int r;
+               /* Get HZ. */
+               if((r=sys_getinfo(GET_HZ, &Hz, sizeof(Hz), 0, 0)) != OK) {
+                       Hz = HZ;
+                       printf("sys_hz: %d: reverting to HZ = %d\n", r, Hz);
+               }
+       }
+
+       return Hz;
+}
+
+u32_t
+micros_to_ticks(u32_t micros)
+{
+        u32_t ticks;
+
+        ticks = div64u(mul64u(micros, sys_hz()), 1000000);
+        if(ticks < 1) ticks = 1;
+
+        return ticks;
+}
+
+
index a534e56868292391243047e8d33f09fa7dbc1d1e..8316c740541f6413064b89071d9e67349f59e367 100644 (file)
@@ -21,6 +21,7 @@ all install depend clean:
        cd ./rs && $(MAKE) $@
        cd ./ds && $(MAKE) $@
        cd ./is && $(MAKE) $@
+       cd ./vm && $(MAKE) $@
        cd ./init && $(MAKE) $@
        cd ./inet && $(MAKE) $@
 
@@ -30,6 +31,6 @@ image:
        cd ./mfs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
        cd ./rs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
        cd ./ds && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
+       cd ./vm && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
        cd ./init && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
 
-
index 9ea37eb7532b0a086f0b6792c008e6f5123a992c..b92f429dfde98c63c88eebba975b8d065245458b 100644 (file)
@@ -15,7 +15,7 @@ f = $u/src/servers/fs
 CC =   exec cc
 CFLAGS = -I$i $(CPROFILE)
 LDFLAGS = -i
-LIBS = -lsysutil -lsys
+LIBS = -lsys 
 
 OBJ = main.o store.o 
 
@@ -27,8 +27,6 @@ $(SERVER):    $(OBJ)
 
 # install with other servers
 install: $(SERVER)
-       install -o root -c $? /sbin/$(SERVER)
-#      install -o root -cs $? $@
 
 # clean up local files
 clean:
index c2e6559e5b6c34cbb9a87aef131c399a363a381a..2a8c65c66da6ffec17e9bdec2409ef5ea1b26d6b 100644 (file)
@@ -8,7 +8,7 @@ CC =            cc
 CPPFLAGS =     -I. -D_MINIX
 CFLAGS =       $(OPT) $(CPPFLAGS) $(CPROFILE)
 LDFLAGS =
-LIBS =          -lsysutil -lsys
+LIBS =           -lsys 
 
 .c.o:
        $(CC) $(CFLAGS) -o $@ -c $<
@@ -29,7 +29,7 @@ inet: $(OBJ)
        $(CC) -o $@ $(LDFLAGS) $(OBJ) version.c $(LIBS)
 
 install: inet
-       install -c $? /usr/sbin/inet
+       install -c $< /usr/sbin/inet
 
 clean:
        rm -f $(OBJ) inet *.bak
index 8d132ba0ec558cbbbc05c0ec31a4851ce4e619c9..fba51879c7e44a82f1123aefde41bca8bce01f44 100644 (file)
@@ -342,8 +342,10 @@ ioreq_t req;
 
                        if (!(eth_port->etp_flags & EPF_GOT_ADDR))
                        {
+#if 0
                                printf(
                                "eth_ioctl: suspending NWIOGETHSTAT ioctl\n");
+#endif
 
                                eth_fd->ef_ioctl_req= req;
                                assert(!(eth_fd->ef_flags & EFF_IOCTL_IP));
@@ -372,14 +374,18 @@ ioreq_t req;
                                        &ethstat->nwes_stat);
                                if (result == SUSPEND)
                                {
+#if 0
                                        printf(
                                "eth_ioctl: eth_get_stat returned SUSPEND\n");
+#endif
                                        eth_fd->ef_ioctl_req= req;
                                        assert(!(eth_fd->ef_flags &
                                                EFF_IOCTL_IP));
                                        eth_fd->ef_flags |= EFF_IOCTL_IP;
+#if 0
 printf("eth_ioctl: setting etp_getstat in port %d to %p\n",
        eth_port-eth_port_table, acc);
+#endif
                                        eth_port->etp_getstat= acc;
                                        acc= NULL;
                                        return NW_SUSPEND;
@@ -1049,7 +1055,9 @@ eth_port_t *eth_port;
        eth_fd_t *eth_fd;
        acc_t *acc;
 
+#if 0
        printf("in eth_restart_ioctl\n");
+#endif
 
        /* eth_restart_ioctl is called on too occasions: when a device
         * driver registers with inet and when a eth_get_stat call has
@@ -1069,12 +1077,16 @@ eth_port_t *eth_port;
                if (eth_fd->ef_ioctl_req != NWIOGETHSTAT)
                        continue;
 
+#if 0
 printf("eth_restart_ioctl: etp_getstat in port %d is %p\n",
        eth_port-eth_port_table, acc);
+#endif
 
                if (acc != NULL)
                {
+#if 0
                        printf("eth_restart_ioctl: completed getstat\n");
+#endif
                        acc->acc_linkC++;
                        r= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, 0,
                                acc, TRUE);
@@ -1092,8 +1104,10 @@ printf("eth_restart_ioctl: etp_getstat in port %d is %p\n",
 
        if (acc != NULL)
        {
+#if 0
 printf("eth_restart_ioctl: clearing etp_getstat in port %d\n",
        eth_port-eth_port_table);
+#endif
                assert(acc == eth_port->etp_getstat);
 
                bf_afree(acc);
index 037bd7dc0fef5f6e5560bade6b958653c9b282df..88d03068117e6d061087960f1396eea37620232b 100644 (file)
@@ -34,7 +34,9 @@ FORWARD _PROTOTYPE( eth_port_t *find_port, (message *m) );
 FORWARD _PROTOTYPE( void eth_restart, (eth_port_t *eth_port, int tasknr) );
 FORWARD _PROTOTYPE( void send_getstat, (eth_port_t *eth_port) );
 
+#if 0
 FORWARD _PROTOTYPE( int asynsend, (endpoint_t dst, message *mp) );
+#endif
 
 PUBLIC void osdep_eth_init()
 {
@@ -339,7 +341,9 @@ message *m;
                if (!(loc_port->etp_flags & EPF_GOT_ADDR))
                {
                        loc_port->etp_flags |= EPF_GOT_ADDR;
+#if 0
                        printf("eth_rec: calling eth_restart_ioctl\n");
+#endif
                        eth_restart_ioctl(loc_port);
 
                        /* Also update any VLANs on this device */
@@ -359,6 +363,7 @@ message *m;
                if (!(loc_port->etp_flags & EPF_READ_IP))
                        setup_read (loc_port);
 
+#if 0
                if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
                {
                        printf("eth_rec(conf): OEPF_NEED_SEND is set\n");
@@ -371,6 +376,7 @@ message *m;
                {
                        printf("eth_rec(conf): OEPF_NEED_STAT is set\n");
                }
+#endif
 
                return;
        }
@@ -404,6 +410,7 @@ message *m;
                assert(loc_port->etp_flags & EPF_GOT_ADDR);
                eth_restart_ioctl(loc_port);
 
+#if 0
                if (loc_port->etp_osdep.etp_flags & OEPF_NEED_SEND)
                {
                        printf("eth_rec(stat): OEPF_NEED_SEND is set\n");
@@ -416,6 +423,8 @@ message *m;
                {
                        printf("eth_rec(stat): OEPF_NEED_CONF is set\n");
                }
+#endif
+
 #if 0
                if (loc_port->etp_osdep.etp_state == OEPS_IDLE &&
                        (loc_port->etp_osdep.etp_flags & OEPF_NEED_CONF))
@@ -549,7 +558,9 @@ u32_t flags;
        if (!(eth_port->etp_flags & EPF_GOT_ADDR))
        {
                /* We have never seen the device. */
+#if 0
                printf("eth_set_rec_conf: waiting for device to appear\n");
+#endif
                return;
        }
 
@@ -1002,6 +1013,7 @@ eth_port_t *eth_port;
                ip_panic(( "eth_get_stat: asynsend failed: %d", r));
 }
 
+#if 0
 PRIVATE asynmsg_t *msgtable= NULL;
 PRIVATE size_t msgtable_n= 0;
 
@@ -1050,6 +1062,7 @@ message *mp;
        /* Tell the kernel to rescan the table */
        return senda(msgtable, msgtable_n);
 }
+#endif
 
 /*
  * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $
index 7eb05c74cef55f12d5d54c09918bedfb0589ee87..2ac270721972e7b6f67056032faa23d1ec4379dd 100644 (file)
@@ -18,7 +18,7 @@ OBJ =         init.o
 # build local binary
 all build:     $(SERVER)
 $(SERVER):     $(OBJ)
-       $(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(OBJ) -lsysutil
+       $(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(OBJ) -lsys
        install -S 8k $@
 
 # install with other servers
index 1ad889105f0e9aee5f12bfc89c103c323582947f..5edfab3ff3f5b0cdc4148f4d770ef5b730d730fc 100644 (file)
@@ -18,7 +18,7 @@ CC =  exec cc
 CPPFLAGS=-I../../kernel/arch/$(ARCH)/include -I$i 
 CFLAGS = $(CPROFILE) $(CPPFLAGS)
 LDFLAGS = -i
-LIBS = -lsysutil -lsys
+LIBS = -lsys 
 
 OBJ = main.o dmp.o dmp_kernel.o dmp_pm.o dmp_fs.o dmp_rs.o dmp_ds.o 
 
@@ -30,7 +30,7 @@ $(SERVER):    $(OBJ)
 
 # install with other servers
 install:       $(SERVER)
-       install -o root -c $? /sbin/$(SERVER) 
+       install -o root -c $< /sbin/$(SERVER) 
 
 # clean up local files
 clean:
index 483a9c51c14397afdd63afc5313db16f8bf8e3a9..18405d1d2f79f82f9f07368a5e07942821c5a192 100644 (file)
@@ -35,7 +35,6 @@ struct hook_entry {
        { SF4,  dtab_dmp, "Device/Driver mapping" },
        { SF5,  mapping_dmp, "Print key mappings" },
        { SF6,  rproc_dmp, "Reincarnation server process table" },
-       { SF7,  holes_dmp, "Memory free list" },
        { SF8,  data_store_dmp, "Data store contents" },
 };
 
index f677ed4ee2cc8740077044021a9d22eeed302b0f..1a0b4987d307903697f85e2fc346b367208626f9 100644 (file)
@@ -12,6 +12,8 @@
 #include "../../kernel/proc.h"
 #include "../../kernel/ipc.h"
 
+#define LINES 22
+
 #define click_to_round_k(n) \
        ((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024))
 
@@ -34,9 +36,6 @@ PUBLIC struct boot_image image[NR_BOOT_PROCS];
  *===========================================================================*/
 PUBLIC void timing_dmp()
 {
-#if ! DEBUG_TIME_LOCKS
-  printf("Enable the DEBUG_TIME_LOCKS definition in src/kernel/config.h\n");
-#else
   static struct lock_timingdata timingdata[TIMING_CATEGORIES];
   int r, c, f, skipped = 0, printed = 0, maxlines = 23, x = 0;
   static int offsetlines = 0;
@@ -66,7 +65,6 @@ PUBLIC void timing_dmp()
        }
        if (x > 0) printf("\n");
   }
-#endif
 }
 
 /*===========================================================================*
@@ -75,7 +73,7 @@ PUBLIC void timing_dmp()
 PUBLIC void kmessages_dmp()
 {
   struct kmessages kmess;              /* get copy of kernel messages */
-  char print_buf[KMESS_BUF_SIZE+1];    /* this one is used to print */
+  char print_buf[_KMESS_BUF_SIZE+1];   /* this one is used to print */
   int start;                           /* calculate start of messages */
   int r;
 
@@ -89,10 +87,10 @@ PUBLIC void kmessages_dmp()
    * buffer into a print-buffer. This is done because the messages in the
    * copy may wrap (the kernel buffer is circular).
    */
-  start = ((kmess.km_next + KMESS_BUF_SIZE) - kmess.km_size) % KMESS_BUF_SIZE;
+  start = ((kmess.km_next + _KMESS_BUF_SIZE) - kmess.km_size) % _KMESS_BUF_SIZE;
   r = 0;
   while (kmess.km_size > 0) {
-       print_buf[r] = kmess.km_buf[(start+r) % KMESS_BUF_SIZE];
+       print_buf[r] = kmess.km_buf[(start+r) % _KMESS_BUF_SIZE];
        r ++;
        kmess.km_size --;
   }
@@ -283,14 +281,10 @@ PUBLIC void kenv_dmp()
     printf("- data_base:  %5u\n", kinfo.data_base); 
     printf("- data_size:  %5u\n", kinfo.data_size); 
     printf("- proc_addr:  %5u\n", kinfo.proc_addr); 
-    printf("- kmem_base:  %5u\n", kinfo.kmem_base); 
-    printf("- kmem_size:  %5u\n", kinfo.kmem_size); 
     printf("- bootdev_base:  %5u\n", kinfo.bootdev_base); 
     printf("- bootdev_size:  %5u\n", kinfo.bootdev_size); 
     printf("- ramdev_base:   %5u\n", kinfo.ramdev_base); 
     printf("- ramdev_size:   %5u\n", kinfo.ramdev_size); 
-    printf("- params_base:   %5u\n", kinfo.params_base); 
-    printf("- params_size:   %5u\n", kinfo.params_size); 
     printf("- nr_procs:     %3u\n", kinfo.nr_procs); 
     printf("- nr_tasks:     %3u\n", kinfo.nr_tasks); 
     printf("- release:      %.6s\n", kinfo.release); 
@@ -351,7 +345,7 @@ PUBLIC void privileges_dmp()
 
   for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
        if (isemptyp(rp)) continue;
-       if (++n > 23) break;
+       if (++n > LINES) break;
        if (proc_nr(rp) == IDLE)        printf("(%2d) ", proc_nr(rp));  
        else if (proc_nr(rp) < 0)       printf("[%2d] ", proc_nr(rp));
        else                            printf(" %2d  ", proc_nr(rp));
@@ -414,7 +408,7 @@ PUBLIC void sendmask_dmp()
 
   for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
         if (isemptyp(rp)) continue;
-        if (++n > 20) break;
+        if (++n > LINES) break;
 
        printf("%8s ", rp->p_name);
        if (proc_nr(rp) == IDLE)        printf("(%2d) ", proc_nr(rp));  
@@ -467,11 +461,11 @@ 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--rts flags\n");
 
   for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
        if (isemptyp(rp)) continue;
-       if (++n > 23) break;
+       if (++n > LINES) break;
        text = rp->p_memmap[T].mem_phys;
        data = rp->p_memmap[D].mem_phys;
        size = rp->p_memmap[T].mem_len
@@ -480,12 +474,11 @@ 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 %5uK %s",
+       printf("%-8.8s %02u/%02u %02d/%02u %6lu %6lu %s",
               rp->p_name,
               rp->p_priority, rp->p_max_priority,
               rp->p_ticks_left, rp->p_quantum_size, 
               rp->p_user_time, rp->p_sys_time,
-              click_to_round_k(size),
               p_rts_flags_str(rp->p_rts_flags));
        if (rp->p_rts_flags & (SENDING|RECEIVING)) {
                printf(" %-7.7s", proc_name(_ENDPOINT_P(rp->p_getfrom_e)));
@@ -513,22 +506,22 @@ PUBLIC void memmap_dmp()
       return;
   }
 
-  printf("\n-nr/name--- --pc-- --sp-- -----text----- -----data----- ----stack----- --size-\n");
+  printf("\n-nr/name--- --pc--   --sp-- -text---- -data---- -stack--- -cr3-\n");
   for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
        if (isemptyp(rp)) continue;
-       if (++n > 23) break;
+       if (++n > LINES) break;
        size = rp->p_memmap[T].mem_len
                + ((rp->p_memmap[S].mem_phys + rp->p_memmap[S].mem_len)
                                                - rp->p_memmap[D].mem_phys);
-       printf("%3d %-7.7s%7lx%7lx %4x %4x %4x %4x %4x %4x %4x %4x %4x %5uK\n",
+       printf("%3d %-7.7s%7lx %8lx %4x %4x %4x %4x %5x %5x %8lx\n",
               proc_nr(rp),
               rp->p_name,
               (unsigned long) rp->p_reg.pc,
               (unsigned long) rp->p_reg.sp,
-              rp->p_memmap[T].mem_vir, rp->p_memmap[T].mem_phys, rp->p_memmap[T].mem_len,
-              rp->p_memmap[D].mem_vir, rp->p_memmap[D].mem_phys, rp->p_memmap[D].mem_len,
-              rp->p_memmap[S].mem_vir, rp->p_memmap[S].mem_phys, rp->p_memmap[S].mem_len,
-              click_to_round_k(size));
+              rp->p_memmap[T].mem_phys, rp->p_memmap[T].mem_len,
+              rp->p_memmap[D].mem_phys, rp->p_memmap[D].mem_len,
+              rp->p_memmap[S].mem_phys, rp->p_memmap[S].mem_len,
+              rp->p_seg.p_cr3);
   }
   if (rp == END_PROC_ADDR) rp = proc; 
   else printf("--more--\r");
@@ -542,6 +535,11 @@ PRIVATE char *proc_name(proc_nr)
 int proc_nr;
 {
   if (proc_nr == ANY) return "ANY";
+  /*
+  if(proc_nr < 0 || proc_nr >= NR_TASKS+NR_PROCS) {
+       return "BAD";
+  }
+  */
   return cproc_addr(proc_nr)->p_name;
 }
 
index 2853aec2cfca6d88968950c5eaf4c81f235e681f..739d1162a9237519bc22aab1a295ae6337c0caf1 100644 (file)
@@ -29,9 +29,6 @@ PRIVATE char *flags_str(int flags)
        str[5] = (flags & STOPPED)  ? 'S' : '-';
        str[6] = (flags & SIGSUSPENDED)  ? 'U' : '-';
        str[7] = (flags & REPLY)  ? 'R' : '-';
-       str[8] = (flags & ONSWAP)  ? 'O' : '-';
-       str[9] = (flags & SWAPIN)  ? 'I' : '-';
-       str[10] = (flags & DONT_SWAP)  ? 'D' : '-';
        str[11] = (flags & PRIV_PROC)  ? 'P' : '-';
        str[12] = '\0';
 
@@ -48,14 +45,14 @@ PUBLIC void mproc_dmp()
 
   getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc);
 
-  printf("-process- -nr-prnt- -pid/ppid/grp- -uid--gid- -nice- -flags------\n");
+  printf("-process- -nr-prnt- -pid   ppid   grp-  -uid--gid-        -nice- -flags------\n");
   for (i=prev_i; i<NR_PROCS; i++) {
        mp = &mproc[i];
        if (mp->mp_pid == 0 && i != PM_PROC_NR) continue;
        if (++n > 22) break;
-       printf("%8.8s %4d%4d  %4d%4d%4d    ", 
+       printf("%8.8s %4d%4d  %5d %5d %5d     ", 
                mp->mp_name, i, mp->mp_parent, mp->mp_pid, mproc[mp->mp_parent].mp_pid, mp->mp_procgrp);
-       printf("%d(%d)  %d(%d)  ",
+       printf("%2d(%2d)  %2d(%2d)  ",
                mp->mp_realuid, mp->mp_effuid, mp->mp_realgid, mp->mp_effgid);
        printf(" %3d  %s  ", 
                mp->mp_nice, flags_str(mp->mp_flags)); 
@@ -99,42 +96,4 @@ PUBLIC void sigaction_dmp()
   prev_i = i;
 }
 
-/*===========================================================================*
- *                             holes_dmp                                    *
- *===========================================================================*/
-PUBLIC void holes_dmp(void)
-{
-       static struct pm_mem_info pmi;
-       int h;
-       int largest_bytes = 0, total_bytes = 0;
-
-       if(getsysinfo(PM_PROC_NR, SI_MEM_ALLOC, &pmi) != OK) {
-               printf("Obtaining memory hole list failed.\n");
-               return;
-       }
-       printf("Available memory stats\n");
-
-       for(h = 0; h < _NR_HOLES; h++) {
-               if(pmi.pmi_holes[h].h_base && pmi.pmi_holes[h].h_len) {
-                       int bytes;
-                       bytes = (pmi.pmi_holes[h].h_len << CLICK_SHIFT);
-                       printf("%08lx: %6d kB\n",
-                               pmi.pmi_holes[h].h_base << CLICK_SHIFT, bytes / 1024);
-                       if(bytes > largest_bytes) largest_bytes = bytes;
-                       total_bytes += bytes;
-               }
-       }
-       printf("\n"
-               "Total memory free:     %7d kB\n"
-               "Largest chunk:         %7d kB\n"
-               "Uncontiguous rest:     %7d kB (%d%% of total free)\n"
-               "Memory high watermark: %7d kB\n",
-               total_bytes/1024,
-               largest_bytes/1024,
-               (total_bytes-largest_bytes)/1024,
-               100*(total_bytes/100-largest_bytes/100)/total_bytes,
-               (pmi.pmi_hi_watermark/1024 << CLICK_SHIFT));
-
-       return;
-}
 
index da01de2704f41cc32f16e8eb0c78b042717d7802..db17cdaef5f34d53afb09de63475baaca10e3fe5 100644 (file)
@@ -9,10 +9,6 @@
 
 #include "inc.h"
 
-/* Set debugging level to 0, 1, or 2 to see no, some, all debug output. */
-#define DEBUG_LEVEL    1
-#define DPRINTF                if (DEBUG_LEVEL > 0) printf
-
 /* Allocate space for the global variables. */
 message m_in;          /* the input message itself */
 message m_out;         /* the output message used for reply */
@@ -43,7 +39,6 @@ PUBLIC int main(int argc, char **argv)
 
   /* Main loop - get work and do it, forever. */         
   while (TRUE) {              
-
       /* Wait for incoming message, sets 'callnr' and 'who'. */
       get_work();
 
index 1f97664ed1ba53cd0c84200b0e2d4aeb69aae6ce..dc22f25d9b94137341355e6c767704b1611ae729 100644 (file)
@@ -1,5 +1,8 @@
 # Makefile for File System (FS)
 SERVER = mfs
+DEST=/sbin/$(SERVER)
+NR_BUFS=1024
+BS=4096
 
 # directories
 u = /usr
@@ -9,9 +12,9 @@ h = $i/minix
 
 # programs, flags, etc.
 CC =   exec cc
-CFLAGS = -I$i $(EXTRA_OPTS) $(CPROFILE)
+CFLAGS = -I$i $(EXTRA_OPTS) $(CPROFILE) -DNR_BUFS=$(NR_BUFS)
 LDFLAGS = -i
-LIBS = -lsysutil  -lsys -ltimers
+LIBS =  -lsys -ltimers
 
 OBJ =  cache.o device.o link.o \
        mount.o misc.o open.o pipe.o protect.o read.o \
@@ -22,10 +25,11 @@ OBJ =       cache.o device.o link.o \
 all build:     $(SERVER)
 $(SERVER):     $(OBJ)
        $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
-       install -S 64k $(SERVER)
+       install -S `expr $(NR_BUFS) \* $(BS) \* 2.2` $(SERVER)
 
 install: $(SERVER)
-       install $(SERVER) /sbin/$(SERVER)
+       -mv $(DEST) $(DEST).prev
+       install $(SERVER) $(DEST)
 
 # clean up local files
 clean:
index a17513683440bae3e817b9eeed0143bc1a8ec5ff..c703442aa20809e1249d121312e356232978460a 100644 (file)
@@ -14,9 +14,7 @@
 #include <sys/dir.h>                   /* need struct direct */
 #include <dirent.h>
 
-EXTERN struct buf {
-  /* Data portion of the buffer. */
-  union {
+union fsdata_u {
     char b__data[_MAX_BLOCK_SIZE];                  /* ordinary user data */
 /* directory block */
     struct direct b__dir[NR_DIR_ENTRIES(_MAX_BLOCK_SIZE)];    
@@ -30,32 +28,22 @@ EXTERN struct buf {
     d2_inode b__v2_ino[V2_INODES_PER_BLOCK(_MAX_BLOCK_SIZE)]; 
 /* bit map block */
     bitchunk_t b__bitmap[FS_BITMAP_CHUNKS(_MAX_BLOCK_SIZE)];  
-  } b;
-
-  /* Header portion of the buffer. */
-  struct buf *b_next;          /* used to link all free bufs in a chain */
-  struct buf *b_prev;          /* used to link all free bufs the other way */
-  struct buf *b_hash;          /* used to link bufs on hash chains */
-  block_t b_blocknr;           /* block number of its (minor) device */
-  dev_t b_dev;                 /* major | minor device where block resides */
-  char b_dirt;                 /* CLEAN or DIRTY */
-  char b_count;                        /* number of users of this buffer */
-} buf[NR_BUFS];
+};
 
 /* A block is free if b_dev == NO_DEV. */
 
 #define NIL_BUF ((struct buf *) 0)     /* indicates absence of a buffer */
 
 /* These defs make it possible to use to bp->b_data instead of bp->b.b__data */
-#define b_data   b.b__data
-#define b_dir    b.b__dir
-#define b_v1_ind b.b__v1_ind
-#define b_v2_ind b.b__v2_ind
-#define b_v1_ino b.b__v1_ino
-#define b_v2_ino b.b__v2_ino
-#define b_bitmap b.b__bitmap
+#define b_data   bp->b__data
+#define b_dir    bp->b__dir
+#define b_v1_ind bp->b__v1_ind
+#define b_v2_ind bp->b__v2_ind
+#define b_v1_ino bp->b__v1_ino
+#define b_v2_ino bp->b__v2_ino
+#define b_bitmap bp->b__bitmap
 
-EXTERN struct buf *buf_hash[NR_BUF_HASH];      /* the buffer hash table */
+#define BUFHASH(b) ((b) % NR_BUFS)
 
 EXTERN struct buf *front;      /* points to least recently used free block */
 EXTERN struct buf *rear;       /* points to most recently used free block */
@@ -72,4 +60,3 @@ EXTERN int bufs_in_use;               /* # bufs currently in use (not on free list)*/
 #define FULL_DATA_BLOCK    5                            /* data, fully used */
 #define PARTIAL_DATA_BLOCK 6                            /* data, partly used*/
 
-#define HASH_MASK (NR_BUF_HASH - 1)    /* mask for hashing block numbers */
index 352295387234ff3206c0d8172b4379401bd67fd1..ed04fc364c85c678089d97c61b80c27102e957b3 100644 (file)
 #include <minix/u64.h>
 #include "buf.h"
 #include "super.h"
+#include "inode.h"
 
 FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
 FORWARD _PROTOTYPE( int rw_block, (struct buf *, int) );
 
-#define ENABLE_CACHE2 0
-
 /*===========================================================================*
  *                             get_block                                    *
  *===========================================================================*/
@@ -51,20 +50,24 @@ int only_search;            /* if NO_READ, don't read, else act normal */
   int b;
   register struct buf *bp, *prev_ptr;
 
+  ASSERT(fs_block_size > 0);
+
   /* Search the hash chain for (dev, block). Do_read() can use 
    * get_block(NO_DEV ...) to get an unnamed block to fill with zeros when
    * someone wants to read from a hole in a file, in which case this search
    * is skipped
    */
   if (dev != NO_DEV) {
-       b = (int) block & HASH_MASK;
+       b = BUFHASH(block);
        bp = buf_hash[b];
        while (bp != NIL_BUF) {
                if (bp->b_blocknr == block && bp->b_dev == dev) {
                        /* Block needed has been found. */
                        if (bp->b_count == 0) rm_lru(bp);
                        bp->b_count++;  /* record that block is in use */
-
+                       ASSERT(bp->b_dev == dev);
+                       ASSERT(bp->b_dev != NO_DEV);
+                       ASSERT(bp->bp);
                        return(bp);
                } else {
                        /* This block is not the one sought. */
@@ -78,7 +81,7 @@ int only_search;              /* if NO_READ, don't read, else act normal */
   rm_lru(bp);
 
   /* Remove the block that was just taken from its hash chain. */
-  b = (int) bp->b_blocknr & HASH_MASK;
+  b = BUFHASH(bp->b_blocknr);
   prev_ptr = buf_hash[b];
   if (prev_ptr == bp) {
        buf_hash[b] = bp->b_hash;
@@ -98,31 +101,42 @@ int only_search;           /* if NO_READ, don't read, else act normal */
    */
   if (bp->b_dev != NO_DEV) {
        if (bp->b_dirt == DIRTY) flushall(bp->b_dev);
-#if ENABLE_CACHE2
-       put_block2(bp);
-#endif
   }
 
   /* Fill in block's parameters and add it to the hash chain where it goes. */
   bp->b_dev = dev;             /* fill in device number */
   bp->b_blocknr = block;       /* fill in block number */
   bp->b_count++;               /* record that block is being used */
-  b = (int) bp->b_blocknr & HASH_MASK;
+  b = BUFHASH(bp->b_blocknr);
   bp->b_hash = buf_hash[b];
+  if(bp->b_bytes < fs_block_size) {
+       static int n = 0;
+       phys_bytes ph;
+       if(bp->b_bytes > 0)
+               printf("MFS: WARNING: throwing away %d bytes!\n",
+                       bp->b_bytes);
+       if(!(bp->bp = alloc_contig(fs_block_size, 0, &ph)))
+               panic(__FILE__,"couldn't allocate FS buffer", n);
+       bp->b_bytes = fs_block_size;
+       n++;
+  }
+
   buf_hash[b] = bp;            /* add to hash list */
 
+  SANITYCHECK;
+
   /* Go get the requested block unless searching or prefetching. */
   if (dev != NO_DEV) {
-#if ENABLE_CACHE2
-       if (get_block2(bp, only_search)) /* in 2nd level cache */;
-       else
-#endif
        if (only_search == PREFETCH) bp->b_dev = NO_DEV;
        else
        if (only_search == NORMAL) {
+               SANITYCHECK;
                rw_block(bp, READING);
        }
   }
+
+  ASSERT(bp->bp);
+
   return(bp);                  /* return the newly acquired block */
 }
 
@@ -262,15 +276,14 @@ int rw_flag;                      /* READING or WRITING */
   int r, op;
   u64_t pos;
   dev_t dev;
-  int block_size;
-
-  block_size = get_block_size(bp->b_dev);
 
   if ( (dev = bp->b_dev) != NO_DEV) {
-         pos = mul64u(bp->b_blocknr, block_size);
+         pos = mul64u(bp->b_blocknr, fs_block_size);
          op = (rw_flag == READING ? MFS_DEV_READ : MFS_DEV_WRITE);
-         r = block_dev_io(op, dev, SELF_E, bp->b_data, pos, block_size, 0);
-         if (r != block_size) {
+         SANITYCHECK;
+         r = block_dev_io(op, dev, SELF_E, bp->b_data, pos, fs_block_size, 0);
+         SANITYCHECK;
+         if (r != fs_block_size) {
                  if (r >= 0) r = END_OF_FILE;
                  if (r != END_OF_FILE)
                        printf("MFS(%d) I/O error on device %d/%d, block %ld\n",
@@ -282,6 +295,14 @@ int rw_flag;                       /* READING or WRITING */
                  /* Report read errors to interested parties. */
                  if (rw_flag == READING) rdwt_err = r;
          }
+         if(op == MFS_DEV_READ) {
+               int i;
+#if 0
+               printf("mfsread after contents: 0x%lx, ", bp->b_data);
+               for(i = 0; i < 10; i++) printf("%02lx ", (unsigned char) bp->b_data[i]);
+               printf("\n");
+#endif
+         }
   }
 
   bp->b_dirt = CLEAN;
@@ -301,10 +322,6 @@ dev_t device;                      /* device whose blocks are to be purged */
 
   for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
        if (bp->b_dev == device) bp->b_dev = NO_DEV;
-
-#if ENABLE_CACHE2
-  invalidate2(device);
-#endif
 }
 
 /*===========================================================================*
@@ -316,9 +333,11 @@ dev_t dev;                 /* device to flush */
 /* Flush all dirty blocks for one device. */
 
   register struct buf *bp;
-  static struct buf *dirty[NR_BUFS];   /* static so it isn't on stack */
+  static struct buf **dirty;   /* static so it isn't on stack */
   int ndirty;
 
+  STATICINIT(dirty, NR_BUFS);
+
   for (bp = &buf[0], ndirty = 0; bp < &buf[NR_BUFS]; bp++)
        if (bp->b_dirt == DIRTY && bp->b_dev == dev) dirty[ndirty++] = bp;
   rw_scattered(dev, dirty, ndirty, WRITING);
@@ -339,11 +358,10 @@ int rw_flag;                      /* READING or WRITING */
   int gap;
   register int i;
   register iovec_t *iop;
-  static iovec_t iovec[NR_IOREQS];  /* static so it isn't on stack */
+  static iovec_t *iovec = NULL;
   int j, r;
-  int block_size;
 
-  block_size = get_block_size(dev);
+  STATICINIT(iovec, NR_IOREQS);
 
   /* (Shell) sort buffers on b_blocknr. */
   gap = 1;
@@ -371,11 +389,11 @@ int rw_flag;                      /* READING or WRITING */
                bp = bufq[j];
                if (bp->b_blocknr != bufq[0]->b_blocknr + j) break;
                iop->iov_addr = (vir_bytes) bp->b_data;
-               iop->iov_size = block_size;
+               iop->iov_size = fs_block_size;
        }
        r = block_dev_io(rw_flag == WRITING ? MFS_DEV_SCATTER : MFS_DEV_GATHER,
                dev, SELF_E, iovec,
-               mul64u(bufq[0]->b_blocknr, block_size), j, 0);
+               mul64u(bufq[0]->b_blocknr, fs_block_size), j, 0);
 
        /* Harvest the results.  Dev_io reports the first error it may have
         * encountered, but we only care if it's the first block that failed.
@@ -444,3 +462,58 @@ struct buf *bp;
   else
        rear = prev_ptr;        /* this block was at rear of chain */
 }
+
+/*===========================================================================*
+ *                             set_blocksize                                *
+ *===========================================================================*/
+PUBLIC void set_blocksize(int blocksize)
+{
+       struct buf *bp;
+       struct inode *rip;
+
+       ASSERT(blocksize > 0);
+
+        for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
+               if(bp->b_count != 0)
+                       panic("MFS", "change blocksize with buffer in use",
+                               NO_NUM);
+
+       for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
+               if (rip->i_count > 0)
+                       panic("MFS", "change blocksize with inode in use",
+                               NO_NUM);
+
+       fs_sync();
+
+       buf_pool();
+       fs_block_size = blocksize;
+}
+
+/*===========================================================================*
+ *                              buf_pool                                     *
+ *===========================================================================*/
+PUBLIC void buf_pool(void)
+{
+/* Initialize the buffer pool. */
+  register struct buf *bp;
+
+  bufs_in_use = 0;
+  front = &buf[0];
+  rear = &buf[NR_BUFS - 1];
+
+  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
+        bp->b_blocknr = NO_BLOCK;
+        bp->b_dev = NO_DEV;
+        bp->b_next = bp + 1;
+        bp->b_prev = bp - 1;
+        bp->bp = NULL;
+        bp->b_bytes = 0;
+  }
+  buf[0].b_prev = NIL_BUF;
+  buf[NR_BUFS - 1].b_next = NIL_BUF;
+
+  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) bp->b_hash = bp->b_next;
+  buf_hash[0] = front;
+
+}
+
index c592d9d636151d1443524b861b4f241c0cbb723c..e3584908be0654d25800605a1d173b090a983d31 100644 (file)
@@ -5,7 +5,6 @@
 #define V2_NR_TZONES      10   /* total # zone numbers in a V2 inode */
 
 #define NR_INODES        256   /* # slots in "in core" inode table */
-#define NR_SUPERS          1   /* # slots in super block table */
 
 #define INODE_HASH_LOG2   7     /* 2 based logarithm of the inode hash size */
 #define INODE_HASH_SIZE   ((unsigned long)1<<INODE_HASH_LOG2)
index d9dd389ee07333de76e5045268e07d3aa7e411cb..15e0e4134356c58cef1bac30088983d62e805bb4 100644 (file)
@@ -83,7 +83,9 @@ vir_bytes bytes;
        int access = 0, size;
        int j;
        iovec_t *v;
-       static iovec_t new_iovec[NR_IOREQS];
+       static iovec_t *new_iovec;
+
+       STATICINIT(new_iovec, NR_IOREQS);
 
        /* Number of grants allocated in vector I/O. */
        *vec_grants = 0;
@@ -195,9 +197,11 @@ int flags;                 /* special flags, like O_NONBLOCK */
   int vec_grants;
   int op_used;
   void *buf_used;
-  static cp_grant_id_t gids[NR_IOREQS];
+  static cp_grant_id_t *gids;
   endpoint_t driver_e;
 
+  STATICINIT(gids, NR_IOREQS);
+
   /* Determine driver endpoint for this device */
   driver_e = driver_endpoints[(dev >> MAJOR) & BYTE].driver_e;
   
index e5595a85204c51ac7ee4210c84628d61d9e6884d..bde97a4e3523c98d44f374610f494fc6197de929 100644 (file)
@@ -45,3 +45,10 @@ EXTERN char fs_dev_label[16];        /* Name of the device driver that is handled
                                 * by this FS proc.
                                 */
 
+/* our block size. */
+EXTERN int fs_block_size;
+
+/* Buffer cache. */
+EXTERN struct buf buf[NR_BUFS];
+EXTERN struct buf *buf_hash[NR_BUFS];   /* the buffer hash table */
+
index 32f7cc41b4e1445e9f75996721e85372ae2b7dfb..6118748e65cc7e7ffbc7dfa4651ed2269e3bbc6b 100644 (file)
@@ -117,33 +117,6 @@ PUBLIC int main(void)
   }
 }
 
-/*===========================================================================*
- *                             buf_pool                                     *
- *===========================================================================*/
-PRIVATE void buf_pool(void)
-{
-/* Initialize the buffer pool. */
-  register struct buf *bp;
-
-  bufs_in_use = 0;
-  front = &buf[0];
-  rear = &buf[NR_BUFS - 1];
-
-  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
-       bp->b_blocknr = NO_BLOCK;
-       bp->b_dev = NO_DEV;
-       bp->b_next = bp + 1;
-       bp->b_prev = bp - 1;
-  }
-  buf[0].b_prev = NIL_BUF;
-  buf[NR_BUFS - 1].b_next = NIL_BUF;
-
-  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) bp->b_hash = bp->b_next;
-  buf_hash[0] = front;
-
-}
-
-
 /*===========================================================================*
  *                             init_server                                  *
  *===========================================================================*/
@@ -165,6 +138,7 @@ PRIVATE void init_server(void)
        
    SELF_E = getprocnr();
    buf_pool();
+   fs_block_size = _MIN_BLOCK_SIZE;
 }
 
 /*===========================================================================*
index 2a802b9259c16f8527ddc37f0c32ac666de1d260..f3a11b9ba41e1cd46ff569084196347a4fe157f2 100644 (file)
@@ -25,7 +25,7 @@ PUBLIC int fs_readsuper_s()
  * so that the VFS knows that it has to find the vnode on which this FS 
  * process' partition is mounted on.
  */
-  struct super_block *xp, *sp;
+  struct super_block *xp;
   struct inode *root_ip;
   cp_grant_id_t label_gid;
   size_t label_len;
@@ -60,11 +60,6 @@ PUBLIC int fs_readsuper_s()
        return EINVAL;
   }
 
-#if 0
-  printf("mfs:fs_readsuper: got tasknr %d for label '%s'\n",
-       tasknr, fs_dev_label);
-#endif
-
   driver_e= tasknr;
 
   /* Map the driver endpoint for this major */
@@ -76,8 +71,6 @@ PUBLIC int fs_readsuper_s()
                                                 * with old lookup code.
                                                 */;
 
-  sp = &super_block[0];
-
   /* Open the device the file system lives on. */
   if (dev_open(driver_e, fs_dev, driver_e,
        fs_m_in.REQ_READONLY ? R_BIT : (R_BIT|W_BIT)) != OK) {
@@ -85,32 +78,37 @@ PUBLIC int fs_readsuper_s()
   }
   
   /* Fill in the super block. */
-  sp->s_dev = fs_dev;          /* read_super() needs to know which dev */
-  r = read_super(sp);
+  superblock.s_dev = fs_dev;   /* read_super() needs to know which dev */
+  r = read_super(&superblock);
 
   /* Is it recognized as a Minix filesystem? */
   if (r != OK) {
-       sp->s_dev = NO_DEV;
+       printf("MFS: bad superblock\n");
+       superblock.s_dev = NO_DEV;
        dev_close(driver_e, fs_dev);
        return(r);
   }
+
+  set_blocksize(superblock.s_block_size);
   
   /* Get the root inode of the mounted file system. */
   if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE)  {
-       sp->s_dev = NO_DEV;
+       printf("MFS: couldn't get root inode?!\n");
+       superblock.s_dev = NO_DEV;
        dev_close(driver_e, fs_dev);
-       return err_code;
+       return EINVAL;
   }
   
   if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
+       printf("MFS: zero mode for root inode?!\n");
         put_inode(root_ip);
-       sp->s_dev = NO_DEV;
+       superblock.s_dev = NO_DEV;
        dev_close(driver_e, fs_dev);
        return EINVAL;
   }
 
-  sp->s_rd_only = fs_m_in.REQ_READONLY;
-  sp->s_is_root = fs_m_in.REQ_ISROOT;
+  superblock.s_rd_only = fs_m_in.REQ_READONLY;
+  superblock.s_is_root = fs_m_in.REQ_ISROOT;
   
   /* Root inode properties */
   fs_m_out.RES_INODE_NR = root_ip->i_num;
@@ -135,9 +133,10 @@ PUBLIC int fs_readsuper_o()
  * so that the VFS knows that it has to find the vnode on which this FS 
  * process' partition is mounted on.
  */
-  struct super_block *xp, *sp;
+  struct super_block *xp;
   struct inode *root_ip;
   int r = OK;
+  phys_bytes ph;
 
   fs_dev = fs_m_in.REQ_DEV;
 
@@ -146,17 +145,17 @@ PUBLIC int fs_readsuper_o()
   boottime = fs_m_in.REQ_BOOTTIME;
   vfs_slink_storage = fs_m_in.REQ_SLINK_STORAGE;
 
-  sp = &super_block[0];
-  
   /* Fill in the super block. */
-  sp->s_dev = fs_dev;          /* read_super() needs to know which dev */
-  r = read_super(sp);
+  superblock.s_dev = fs_dev;           /* read_super() needs to know which dev */
+  r = read_super(&superblock);
 
   /* Is it recognized as a Minix filesystem? */
   if (r != OK) {
-       sp->s_dev = NO_DEV;
+       superblock.s_dev = NO_DEV;
        return(r);
   }
+
+  set_blocksize(superblock.s_block_size);
   
   /* Get the root inode of the mounted file system. */
   root_ip = NIL_INODE;         /* if 'r' not OK, make sure this is defined */
@@ -171,8 +170,8 @@ PUBLIC int fs_readsuper_o()
   }
 
   if (r != OK) return r;
-  sp->s_rd_only = fs_m_in.REQ_READONLY;
-  sp->s_is_root = fs_m_in.REQ_ISROOT;
+  superblock.s_rd_only = fs_m_in.REQ_READONLY;
+  superblock.s_is_root = fs_m_in.REQ_ISROOT;
   
   /* Root inode properties */
   fs_m_out.RES_INODE_NR = root_ip->i_num;
@@ -180,8 +179,8 @@ PUBLIC int fs_readsuper_o()
   fs_m_out.RES_FILE_SIZE = root_ip->i_size;
 
   /* Partition properties */
-  fs_m_out.RES_MAXSIZE = sp->s_max_size;
-  fs_m_out.RES_BLOCKSIZE = sp->s_block_size;
+  fs_m_out.RES_MAXSIZE = superblock.s_max_size;
+  fs_m_out.RES_BLOCKSIZE = superblock.s_block_size;
   
   return r;
 }
@@ -280,26 +279,15 @@ printf("MFS(%d) get_inode by fs_mountpoint() failed\n", SELF_E);
 PUBLIC int fs_unmount()
 {
 /* Unmount a file system by device number. */
-  struct super_block *sp, *sp1;
+  struct super_block *sp1;
   int count;
   register struct inode *rip;
 
   /* Close the device the file system lives on. */
   dev_close(driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e, fs_dev);
 
-  /* !!!!!!!!!!!!! REMOVE THIS LATER !!!!!!!!!!!!!!!!!!!!!!! */
-  /* Find the super block. */
-  sp = NIL_SUPER;
-  for (sp1 = &super_block[0]; sp1 < &super_block[NR_SUPERS]; sp1++) {
-       if (sp1->s_dev == fs_dev) {
-               sp = sp1;
-               break;
-       }
-  }
-  if (sp == NIL_SUPER) {
-       return(EINVAL);
-  }
-  /* !!!!!!!!!!!!! REMOVE THIS LATER !!!!!!!!!!!!!!!!!!!!!!! */
+  if(superblock.s_dev != fs_dev)
+       return EINVAL;
   
   /* See if the mounted device is busy.  Only 1 inode using it should be
    * open -- the root inode -- and that inode only 1 time.
@@ -314,7 +302,6 @@ PUBLIC int fs_unmount()
   }
   
   if (count > 1) {
-      printf("MFS(%d) unmount: filesystem is busy %d\n", SELF_E, count);
       return(EBUSY);   /* can't umount a busy file system */
   }
 
@@ -325,10 +312,9 @@ PUBLIC int fs_unmount()
 
   /* Sync the disk, and invalidate cache. */
   (void) fs_sync();            /* force any cached blocks out of memory */
-  /*invalidate(fs_dev);*/      /* invalidate cache entries for this dev */
 
   /* Finish off the unmount. */
-  sp->s_dev = NO_DEV;
+  superblock.s_dev = NO_DEV;
   
 
   return OK;
index cea152dd382c9d9e0994fe1ce82de3a19533fc0a..3e85a0225ad81ac91c9505b4cb53c75c37c385ec 100644 (file)
@@ -39,16 +39,10 @@ _PROTOTYPE( void free_zone, (Dev_t dev, zone_t numb)                        );
 _PROTOTYPE( struct buf *get_block, (Dev_t dev, block_t block,int only_search));
 _PROTOTYPE( void invalidate, (Dev_t device)                            );
 _PROTOTYPE( void put_block, (struct buf *bp, int block_type)           );
+_PROTOTYPE( void set_blocksize, (int blocksize)                                );
 _PROTOTYPE( void rw_scattered, (Dev_t dev,
                        struct buf **bufq, int bufqsize, int rw_flag)   );
-
-#if ENABLE_CACHE2
-/* cache2.c */
-_PROTOTYPE( void init_cache2, (unsigned long size)                     );
-_PROTOTYPE( int get_block2, (struct buf *bp, int only_search)          );
-_PROTOTYPE( void put_block2, (struct buf *bp)                          );
-_PROTOTYPE( void invalidate2, (Dev_t device)                           );
-#endif
+_PROTOTYPE( void buf_pool, (void)                              );
 
 /* device.c */
 _PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf,
@@ -200,9 +194,11 @@ _PROTOTYPE( long conv4, (int norm, long x)                         );
 _PROTOTYPE( int fetch_name, (char *path, int len, int flag)            );
 _PROTOTYPE( int no_sys, (void)                                         );
 _PROTOTYPE( int isokendpt_f, (char *f, int l, int e, int *p, int ft));
-_PROTOTYPE( void panic, (char *who, char *mess, int num)               );
 _PROTOTYPE( void mfs_nul_f, (char *file, int line, char *str, int len, int maxlen));
 _PROTOTYPE( int mfs_min_f, (char *file, int line, int len1, int len2)  );
+_PROTOTYPE( void sanitycheck, (char *file, int line)   );
+
+#define SANITYCHECK sanitycheck(__FILE__, __LINE__)
 
 #define okendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 1)
 #define isokendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 0)
index 6c789bdc8d0a927c625d84ebbd679785bd8d0ba8..063461dbb9234e0aced3688a6631935155524177 100644 (file)
@@ -675,8 +675,11 @@ off_t position;                    /* position in file whose blk wanted */
        if ( (z = rip->i_zone[dzones+1]) == NO_ZONE) return(NO_BLOCK);
        excess -= nr_indirects;                 /* single indir doesn't count*/
        b = (block_t) z << scale;
+       ASSERT(rip->i_dev != NO_DEV);
        bp = get_block(rip->i_dev, b, NORMAL);  /* get double indirect block */
        index = (int) (excess/nr_indirects);
+       ASSERT(bp->b_dev != NO_DEV);
+       ASSERT(bp->b_dev == rip->i_dev);
        z = rd_indir(bp, index);                /* z= zone for single*/
        put_block(bp, INDIRECT_BLOCK);          /* release double ind block */
        excess = excess % nr_indirects;         /* index into single ind blk */
@@ -773,7 +776,9 @@ unsigned bytes_ahead;               /* bytes beyond position for immediate use */
   off_t ind1_pos;
   dev_t dev;
   struct buf *bp;
-  static struct buf *read_q[NR_BUFS];
+  static struct buf **read_q;
+
+  STATICINIT(read_q, NR_BUFS);
 
   block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
   if (block_spec) {
index 466ff98ad99e2d4b0fbb4c251b8a51f25bae0a6d..4715b6c7c3652a9d490df0d8008838ec9da286ce 100644 (file)
@@ -148,21 +148,13 @@ bit_t bit_returned;               /* number of bit to insert into the map */
 PUBLIC struct super_block *get_super(dev)
 dev_t dev;                     /* device number whose super_block is sought */
 {
-/* Search the superblock table for this device.  It is supposed to be there. */
-
-  register struct super_block *sp;
-
   if (dev == NO_DEV)
        panic(__FILE__,"request for super_block of NO_DEV", NO_NUM);
 
-  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
-       if (sp->s_dev == dev) return(sp);
-printf("MFS(%d)get_super: sp->s_dev: %d, dev: %d\n", SELF_E, sp->s_dev, dev);  
+  if(superblock.s_dev != dev)
+       panic(__FILE__,"wrong superblock", (int) dev);
 
-  /* Search failed.  Something wrong. */
-  panic(__FILE__,"can't find superblock for device (in decimal)", (int) dev);
-
-  return(NIL_SUPER);           /* to keep the compiler and lint quiet */
+  return &superblock;
 }
 
 /*===========================================================================*
@@ -170,21 +162,24 @@ printf("MFS(%d)get_super: sp->s_dev: %d, dev: %d\n", SELF_E, sp->s_dev, dev);
  *===========================================================================*/
 PUBLIC int get_block_size(dev_t dev)
 {
-/* Search the superblock table for this device. */
-
-  register struct super_block *sp;
-
   if (dev == NO_DEV)
        panic(__FILE__,"request for block size of NO_DEV", NO_NUM);
 
-  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) {
-       if (sp->s_dev == dev) {
-               return(sp->s_block_size);
+  return fs_block_size;
+
+#if 0
+  if(superblock.s_dev == dev) {
+       if(superblock.s_block_size != fs_block_size) {
+               printf("mounted blocksize: %d  my blocksize: %d\n", 
+                       superblock.s_block_size, fs_block_size);
        }
+       ASSERT(superblock.s_block_size == fs_block_size);
+       return(superblock.s_block_size);
   }
 
-  /* no mounted filesystem? use this block size then. */
+  /* not the mounted filesystem? use this block size then. */
   return _MIN_BLOCK_SIZE;
+#endif
 }
 
 /*===========================================================================*
@@ -196,14 +191,13 @@ PUBLIC int mounted(rip)
 register struct inode *rip;
 {
 
-  register struct super_block *sp;
   register dev_t dev;
 
   dev = (dev_t) rip->i_zone[0];
   if (dev == root_dev) return(TRUE);
 
-  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
-       if (sp->s_dev == dev) return(TRUE);
+  if(superblock.s_dev == dev)
+       return TRUE;
 
   return(FALSE);
 }
@@ -218,7 +212,9 @@ register struct super_block *sp; /* pointer to a superblock */
   dev_t dev;
   int magic;
   int version, native, r;
-  static char sbbuf[_MIN_BLOCK_SIZE];
+  static char *sbbuf;
+
+  STATICINIT(sbbuf, _MIN_BLOCK_SIZE);
 
   dev = sp->s_dev;             /* save device (will be overwritten by copy) */
   if (dev == NO_DEV)
index c9e4761a2ec2f03d6ede04feacb28333063cb351..f86db36ad3f88132244b89860b7c4b9e27aaf5d0 100644 (file)
@@ -54,7 +54,7 @@ EXTERN struct super_block {
   bit_t s_isearch;             /* inodes below this bit number are in use */
   bit_t s_zsearch;             /* all zones below this bit number are in use*/
   char s_is_root;
-} super_block[NR_SUPERS];
+} superblock;
 
 #define NIL_SUPER (struct super_block *) 0
 #define IMAP           0       /* operating on the inode bit map */
index 19749fef0ed021c408c754cc5effaa725a0e8518..63576838dc2ae7a0bc0eb159f56fc03534f5fb16 100644 (file)
@@ -21,3 +21,19 @@ typedef struct {             /* V2.x disk inode */
   time_t d2_ctime;             /* when was inode data last changed */
   zone_t d2_zone[V2_NR_TZONES];        /* block nums for direct, ind, and dbl ind */
 } d2_inode;
+
+struct buf {
+  /* Data portion of the buffer. */
+  union fsdata_u *bp;
+
+  /* Header portion of the buffer. */
+  struct buf *b_next;           /* used to link all free bufs in a chain */
+  struct buf *b_prev;           /* used to link all free bufs the other way */
+  struct buf *b_hash;           /* used to link bufs on hash chains */
+  block_t b_blocknr;            /* block number of its (minor) device */
+  dev_t b_dev;                  /* major | minor device where block resides */
+  char b_dirt;                  /* CLEAN or DIRTY */
+  char b_count;                 /* number of users of this buffer */
+  int b_bytes;                  /* Number of bytes allocated in bp */
+};
+
index f4af5cfd844872e4718a0c3de6ee23f1c75a0e9a..24ca6bac18343365352d034d988c00a54970d14e 100644 (file)
@@ -12,8 +12,6 @@
 
 #include <minix/vfsif.h>
 
-static int panicking;
-
 /*===========================================================================*
  *                             no_sys                                       *
  *===========================================================================*/
@@ -24,29 +22,6 @@ PUBLIC int no_sys()
   return(EINVAL);
 }
 
-/*===========================================================================*
- *                             panic                                        *
- *===========================================================================*/
-PUBLIC void panic(who, mess, num)
-char *who;                     /* who caused the panic */
-char *mess;                    /* panic message string */
-int num;                       /* number to go with it */
-{
-/* Something awful has happened.  Panics are caused when an internal
- * inconsistency is detected, e.g., a programming error or illegal value of a
- * defined constant.
- */
-  if (!panicking) {            /* do not panic during a sync */
-       panicking = TRUE;               /* prevent another panic during the sync */
-
-       printf("MFS panic (%s): %s ", who, mess);
-       if (num != NO_NUM) printf("%d",num); 
-       printf("\n"); 
-       (void) fs_sync();               /* flush everything to the disk */
-  } else printf("MFS re-panic\n");
-  exit(1);
-}
-
 /*===========================================================================*
  *                             conv2                                        *
  *===========================================================================*/
@@ -100,7 +75,7 @@ PUBLIC time_t clock_time()
        if ( (k=getuptime(&uptime)) != OK)
                panic(__FILE__,"clock_time err", k);
   }
-  return( (time_t) (boottime + (uptime/HZ)));
+  return( (time_t) (boottime + (uptime/sys_hz())));
 }
 
 int mfs_min_f(char *file, int line, int v1, int v2)
@@ -130,3 +105,18 @@ void mfs_nul_f(char *file, int line, char *str, int len, int maxlen)
                        file, line, len, maxlen);
        }
 }
+
+#define MYASSERT(c) if(!(c)) { printf("MFS:%s:%d: sanity check: %s failed\n", \
+  file, line, #c); panic("MFS", "sanity check " #c " failed", __LINE__); }
+
+void sanitycheck(char *file, int line)
+{
+       MYASSERT(SELF_E > 0);
+       if(superblock.s_dev != NO_DEV) {
+               MYASSERT(superblock.s_dev == fs_dev);
+               MYASSERT(superblock.s_block_size == fs_block_size);
+       } else {
+               MYASSERT(_MIN_BLOCK_SIZE == fs_block_size);
+       }
+}
+
index 638dc2c9c5bb3f199b724b409e409701dc2dd143..73b2b923ee23900a0b2eb91637d8d5d8f3298a92 100644 (file)
@@ -330,7 +330,9 @@ PUBLIC void zero_block(bp)
 register struct buf *bp;       /* pointer to buffer to zero */
 {
 /* Zero a block. */
-  memset(bp->b_data, 0, _MAX_BLOCK_SIZE);
+  ASSERT(bp->b_bytes > 0);
+  ASSERT(bp->bp);
+  memset(bp->b_data, 0, bp->b_bytes);
   bp->b_dirt = DIRTY;
 }
 
index 8ae60194f0a563712b5dc825eb63ccc17369a761..d82db2cffb5c7014c19660f36f44e513b1c9cb62 100644 (file)
@@ -17,14 +17,14 @@ CFLAGS = $(CPROFILE) $(CPPFLAGS)
 LDFLAGS = -i
 
 OBJ =  main.o forkexit.o break.o exec.o time.o timers.o \
-       signal.o alloc.o utility.o table.o trace.o getset.o misc.o \
-       profile.o asynsend.o kputc.o
+       signal.o utility.o table.o trace.o getset.o misc.o \
+       profile.o kputc.o dma.o
 
 # build local binary
 all build:     $(SERVER)
 $(SERVER):     $(OBJ)
-       $(CC) -o $@ $(LDFLAGS) $(OBJ) -lsysutil  -lsys -ltimers
-       install -S 8k $@
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) -lsys -ltimers
+       install -S 32k $@
 
 # install with other servers
 install:       /usr/sbin/$(SERVER)
diff --git a/servers/pm/alloc.c b/servers/pm/alloc.c
deleted file mode 100644 (file)
index d36c963..0000000
+++ /dev/null
@@ -1,655 +0,0 @@
-/* This file is concerned with allocating and freeing arbitrary-size blocks of
- * physical memory on behalf of the FORK and EXEC system calls.  The key data
- * structure used is the hole table, which maintains a list of holes in memory.
- * It is kept sorted in order of increasing memory address. The addresses
- * it contains refers to physical memory, starting at absolute address 0
- * (i.e., they are not relative to the start of PM).  During system
- * initialization, that part of memory containing the interrupt vectors,
- * kernel, and PM are "allocated" to mark them as not available and to
- * remove them from the hole list.
- *
- * The entry points into this file are:
- *   alloc_mem:        allocate a given sized chunk of memory
- *   free_mem: release a previously allocated chunk of memory
- *   mem_init: initialize the tables when PM start up
- *   max_hole: returns the largest hole currently available
- *   mem_holes_copy: for outsiders who want a copy of the hole-list
- */
-
-#include "pm.h"
-#include <minix/com.h>
-#include <minix/callnr.h>
-#include <minix/type.h>
-#include <minix/config.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <archconst.h>
-#include "mproc.h"
-#include "../../kernel/const.h"
-#include "../../kernel/config.h"
-#include "../../kernel/type.h"
-
-#define NIL_HOLE (struct hole *) 0
-
-PRIVATE struct hole hole[_NR_HOLES];
-PRIVATE u32_t high_watermark = 0;
-
-PRIVATE struct hole *hole_head;        /* pointer to first hole */
-PRIVATE struct hole *free_slots;/* ptr to list of unused table slots */
-#if ENABLE_SWAP
-PRIVATE int swap_fd = -1;      /* file descriptor of open swap file/device */
-PRIVATE u32_t swap_offset;     /* offset to start of swap area on swap file */
-PRIVATE phys_clicks swap_base; /* memory offset chosen as swap base */
-PRIVATE phys_clicks swap_maxsize;/* maximum amount of swap "memory" possible */
-PRIVATE struct mproc *in_queue;        /* queue of processes wanting to swap in */
-PRIVATE struct mproc *outswap = &mproc[0];      /* outswap candidate? */
-#else /* ! ENABLE_SWAP */
-#define swap_base ((phys_clicks) -1)
-#endif /* ENABLE_SWAP */
-
-FORWARD _PROTOTYPE( void del_slot, (struct hole *prev_ptr, struct hole *hp) );
-FORWARD _PROTOTYPE( void merge, (struct hole *hp)                          );
-#if ENABLE_SWAP
-FORWARD _PROTOTYPE( int swap_out, (void)                                   );
-#else
-#define swap_out()     (0)
-#endif
-
-/*===========================================================================*
- *                             alloc_mem                                    *
- *===========================================================================*/
-PUBLIC phys_clicks alloc_mem(clicks)
-phys_clicks clicks;            /* amount of memory requested */
-{
-/* Allocate a block of memory from the free list using first fit. The block
- * consists of a sequence of contiguous bytes, whose length in clicks is
- * given by 'clicks'.  A pointer to the block is returned.  The block is
- * always on a click boundary.  This procedure is called when memory is
- * needed for FORK or EXEC.  Swap other processes out if needed.
- */
-  register struct hole *hp, *prev_ptr;
-  phys_clicks old_base;
-
-  do {
-        prev_ptr = NIL_HOLE;
-       hp = hole_head;
-       while (hp != NIL_HOLE && hp->h_base < swap_base) {
-               if (hp->h_len >= clicks) {
-                       /* We found a hole that is big enough.  Use it. */
-                       old_base = hp->h_base;  /* remember where it started */
-                       hp->h_base += clicks;   /* bite a piece off */
-                       hp->h_len -= clicks;    /* ditto */
-
-                       /* Remember new high watermark of used memory. */
-                       if(hp->h_base > high_watermark)
-                               high_watermark = hp->h_base;
-
-                       /* Delete the hole if used up completely. */
-                       if (hp->h_len == 0) del_slot(prev_ptr, hp);
-
-                       /* Return the start address of the acquired block. */
-                       return(old_base);
-               }
-
-               prev_ptr = hp;
-               hp = hp->h_next;
-       }
-  } while (swap_out());                /* try to swap some other process out */
-  return(NO_MEM);
-}
-
-/*===========================================================================*
- *                             free_mem                                     *
- *===========================================================================*/
-PUBLIC void free_mem(base, clicks)
-phys_clicks base;              /* base address of block to free */
-phys_clicks clicks;            /* number of clicks to free */
-{
-/* Return a block of free memory to the hole list.  The parameters tell where
- * the block starts in physical memory and how big it is.  The block is added
- * to the hole list.  If it is contiguous with an existing hole on either end,
- * it is merged with the hole or holes.
- */
-  register struct hole *hp, *new_ptr, *prev_ptr;
-
-  if (clicks == 0) return;
-  if ( (new_ptr = free_slots) == NIL_HOLE) 
-       panic(__FILE__,"hole table full", NO_NUM);
-  new_ptr->h_base = base;
-  new_ptr->h_len = clicks;
-  free_slots = new_ptr->h_next;
-  hp = hole_head;
-
-  /* If this block's address is numerically less than the lowest hole currently
-   * available, or if no holes are currently available, put this hole on the
-   * front of the hole list.
-   */
-  if (hp == NIL_HOLE || base <= hp->h_base) {
-       /* Block to be freed goes on front of the hole list. */
-       new_ptr->h_next = hp;
-       hole_head = new_ptr;
-       merge(new_ptr);
-       return;
-  }
-
-  /* Block to be returned does not go on front of hole list. */
-  prev_ptr = NIL_HOLE;
-  while (hp != NIL_HOLE && base > hp->h_base) {
-       prev_ptr = hp;
-       hp = hp->h_next;
-  }
-
-  /* We found where it goes.  Insert block after 'prev_ptr'. */
-  new_ptr->h_next = prev_ptr->h_next;
-  prev_ptr->h_next = new_ptr;
-  merge(prev_ptr);             /* sequence is 'prev_ptr', 'new_ptr', 'hp' */
-}
-
-/*===========================================================================*
- *                             del_slot                                     *
- *===========================================================================*/
-PRIVATE void del_slot(prev_ptr, hp)
-/* pointer to hole entry just ahead of 'hp' */
-register struct hole *prev_ptr;
-/* pointer to hole entry to be removed */
-register struct hole *hp;      
-{
-/* Remove an entry from the hole list.  This procedure is called when a
- * request to allocate memory removes a hole in its entirety, thus reducing
- * the numbers of holes in memory, and requiring the elimination of one
- * entry in the hole list.
- */
-  if (hp == hole_head)
-       hole_head = hp->h_next;
-  else
-       prev_ptr->h_next = hp->h_next;
-
-  hp->h_next = free_slots;
-  hp->h_base = hp->h_len = 0;
-  free_slots = hp;
-}
-
-/*===========================================================================*
- *                             merge                                        *
- *===========================================================================*/
-PRIVATE void merge(hp)
-register struct hole *hp;      /* ptr to hole to merge with its successors */
-{
-/* Check for contiguous holes and merge any found.  Contiguous holes can occur
- * when a block of memory is freed, and it happens to abut another hole on
- * either or both ends.  The pointer 'hp' points to the first of a series of
- * three holes that can potentially all be merged together.
- */
-  register struct hole *next_ptr;
-
-  /* If 'hp' points to the last hole, no merging is possible.  If it does not,
-   * try to absorb its successor into it and free the successor's table entry.
-   */
-  if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
-  if (hp->h_base + hp->h_len == next_ptr->h_base) {
-       hp->h_len += next_ptr->h_len;   /* first one gets second one's mem */
-       del_slot(hp, next_ptr);
-  } else {
-       hp = next_ptr;
-  }
-
-  /* If 'hp' now points to the last hole, return; otherwise, try to absorb its
-   * successor into it.
-   */
-  if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
-  if (hp->h_base + hp->h_len == next_ptr->h_base) {
-       hp->h_len += next_ptr->h_len;
-       del_slot(hp, next_ptr);
-  }
-}
-
-/*===========================================================================*
- *                             mem_init                                     *
- *===========================================================================*/
-PUBLIC void mem_init(chunks, free)
-struct memory *chunks;         /* list of free memory chunks */
-phys_clicks *free;             /* memory size summaries */
-{
-/* Initialize hole lists.  There are two lists: 'hole_head' points to a linked
- * list of all the holes (unused memory) in the system; 'free_slots' points to
- * a linked list of table entries that are not in use.  Initially, the former
- * list has one entry for each chunk of physical memory, and the second
- * list links together the remaining table slots.  As memory becomes more
- * fragmented in the course of time (i.e., the initial big holes break up into
- * smaller holes), new table slots are needed to represent them.  These slots
- * are taken from the list headed by 'free_slots'.
- */
-  int i;
-  register struct hole *hp;
-
-  /* Put all holes on the free list. */
-  for (hp = &hole[0]; hp < &hole[_NR_HOLES]; hp++) {
-       hp->h_next = hp + 1;
-       hp->h_base = hp->h_len = 0;
-  }
-  hole[_NR_HOLES-1].h_next = NIL_HOLE;
-  hole_head = NIL_HOLE;
-  free_slots = &hole[0];
-
-  /* Use the chunks of physical memory to allocate holes. */
-  *free = 0;
-  for (i=NR_MEMS-1; i>=0; i--) {
-       if (chunks[i].size > 0) {
-               free_mem(chunks[i].base, chunks[i].size);
-               *free += chunks[i].size;
-#if ENABLE_SWAP
-               if (swap_base < chunks[i].base + chunks[i].size) 
-                       swap_base = chunks[i].base + chunks[i].size;
-#endif
-       }
-  }
-
-#if ENABLE_SWAP
-  /* The swap area is represented as a hole above and separate of regular
-   * memory.  A hole at the size of the swap file is allocated on "swapon".
-   */
-  swap_base++;                         /* make separate */
-  swap_maxsize = 0 - swap_base;                /* maximum we can possibly use */
-#endif
-}
-
-/*===========================================================================*
- *                             mem_holes_copy                               *
- *===========================================================================*/
-PUBLIC int mem_holes_copy(struct hole *holecopies, size_t *bytes, u32_t *hi)
-{
-       if(*bytes < sizeof(hole)) return ENOSPC;
-       memcpy(holecopies, hole, sizeof(hole));
-       *bytes = sizeof(hole);
-       *hi = high_watermark;
-       return OK;
-}
-
-#define NR_DMA 16
-
-PRIVATE struct dmatab
-{
-       int dt_flags;
-       endpoint_t dt_proc;
-       phys_bytes dt_base;
-       phys_bytes dt_size;
-       phys_clicks dt_seg_base;
-       phys_clicks dt_seg_size;
-} dmatab[NR_DMA];
-
-#define DTF_INUSE      1
-#define DTF_RELEASE_DMA        2
-#define DTF_RELEASE_SEG        4
-
-PRIVATE endpoint_t iommu_proc_e= ANY;
-
-/*===========================================================================*
- *                             do_adddma                                    *
- *===========================================================================*/
-PUBLIC int do_adddma()
-{
-       endpoint_t req_proc_e, target_proc_e;
-       int i, proc_n;
-       phys_bytes base, size;
-       struct mproc *rmp;
-
-       if (mp->mp_effuid != SUPER_USER)
-               return EPERM;
-
-       req_proc_e= m_in.m_source;
-       target_proc_e= m_in.m2_i1;
-       base= m_in.m2_l1;
-       size= m_in.m2_l2;
-
-       iommu_proc_e= req_proc_e;
-
-       /* Find empty slot */
-       for (i= 0; i<NR_DMA; i++)
-       {
-               if (!(dmatab[i].dt_flags & DTF_INUSE))
-                       break;
-       }
-       if (i >= NR_DMA)
-       {
-               printf("pm:do_adddma: dma table full\n");
-               for (i= 0; i<NR_DMA; i++)
-               {
-                       printf("%d: flags 0x%x proc %d base 0x%x size 0x%x\n",
-                               i, dmatab[i].dt_flags,
-                               dmatab[i].dt_proc,
-                               dmatab[i].dt_base,
-                               dmatab[i].dt_size);
-               }
-               panic(__FILE__, "adddma: table full", NO_NUM);
-               return ENOSPC;
-       }
-
-       /* Find target process */
-       if (pm_isokendpt(target_proc_e, &proc_n) != OK)
-       {
-               printf("pm:do_adddma: endpoint %d not found\n", target_proc_e);
-               return EINVAL;
-       }
-       rmp= &mproc[proc_n];
-       rmp->mp_flags |= HAS_DMA;
-
-       dmatab[i].dt_flags= DTF_INUSE;
-       dmatab[i].dt_proc= target_proc_e;
-       dmatab[i].dt_base= base;
-       dmatab[i].dt_size= size;
-
-       return OK;
-}
-
-/*===========================================================================*
- *                             do_deldma                                    *
- *===========================================================================*/
-PUBLIC int do_deldma()
-{
-       endpoint_t req_proc_e, target_proc_e;
-       int i, j, proc_n;
-       phys_bytes base, size;
-       struct mproc *rmp;
-
-       if (mp->mp_effuid != SUPER_USER)
-               return EPERM;
-
-       req_proc_e= m_in.m_source;
-       target_proc_e= m_in.m2_i1;
-       base= m_in.m2_l1;
-       size= m_in.m2_l2;
-
-       iommu_proc_e= req_proc_e;
-
-       /* Find slot */
-       for (i= 0; i<NR_DMA; i++)
-       {
-               if (!(dmatab[i].dt_flags & DTF_INUSE))
-                       continue;
-               if (dmatab[i].dt_proc == target_proc_e &&
-                       dmatab[i].dt_base == base &&
-                       dmatab[i].dt_size == size)
-               {
-                       break;
-               }
-       }
-       if (i >= NR_DMA)
-       {
-               printf("pm:do_deldma: slot not found\n");
-               return ESRCH;
-       }
-
-       if (dmatab[i].dt_flags & DTF_RELEASE_SEG)
-       {
-               /* Check if we have to release the segment */
-               for (j= 0; j<NR_DMA; j++)
-               {
-                       if (j == i)
-                               continue;
-                       if (!(dmatab[j].dt_flags & DTF_INUSE))
-                               continue;
-                       if (!(dmatab[j].dt_flags & DTF_RELEASE_SEG))
-                               continue;
-                       if (dmatab[i].dt_proc == target_proc_e)
-                               break;
-               }
-               if (j >= NR_DMA)
-               {
-                       /* Last segment */
-                       free_mem(dmatab[i].dt_seg_base,
-                               dmatab[i].dt_seg_size);
-               }
-       }
-
-       dmatab[i].dt_flags &= ~DTF_INUSE;
-
-       return OK;
-}
-
-/*===========================================================================*
- *                             do_getdma                                    *
- *===========================================================================*/
-PUBLIC int do_getdma()
-{
-       endpoint_t req_proc_e, target_proc_e;
-       int i, proc_n;
-       phys_bytes base, size;
-       struct mproc *rmp;
-
-       if (mp->mp_effuid != SUPER_USER)
-               return EPERM;
-
-       req_proc_e= m_in.m_source;
-       iommu_proc_e= req_proc_e;
-
-       /* Find slot to report */
-       for (i= 0; i<NR_DMA; i++)
-       {
-               if (!(dmatab[i].dt_flags & DTF_INUSE))
-                       continue;
-               if (!(dmatab[i].dt_flags & DTF_RELEASE_DMA))
-                       continue;
-
-               printf("do_getdma: setting reply to 0x%x@0x%x proc %d\n",
-                       dmatab[i].dt_size, dmatab[i].dt_base,
-                       dmatab[i].dt_proc);
-               mp->mp_reply.m2_i1= dmatab[i].dt_proc;
-               mp->mp_reply.m2_l1= dmatab[i].dt_base;
-               mp->mp_reply.m2_l2= dmatab[i].dt_size;
-
-               return OK;
-       }
-
-       /* Nothing */
-       return EAGAIN;
-}
-
-
-
-/*===========================================================================*
- *                             release_dma                                  *
- *===========================================================================*/
-PUBLIC void release_dma(proc_e, base, size)
-endpoint_t proc_e;
-phys_clicks base;
-phys_clicks size;
-{
-       int i, found_one;;
-
-       found_one= FALSE;
-       for (i= 0; i<NR_DMA; i++)
-       {
-               if (!(dmatab[i].dt_flags & DTF_INUSE))
-                       continue;
-               if (dmatab[i].dt_proc != proc_e)
-                       continue;
-               dmatab[i].dt_flags |= DTF_RELEASE_DMA | DTF_RELEASE_SEG;
-               dmatab[i].dt_seg_base= base;
-               dmatab[i].dt_seg_size= size;
-               found_one= TRUE;
-       }
-       if (found_one)
-               notify(iommu_proc_e);
-       else
-               free_mem(base, size);
-}
-
-#if ENABLE_SWAP
-/*===========================================================================*
- *                             swap_on                                      *
- *===========================================================================*/
-PUBLIC int swap_on(file, offset, size)
-char *file;                            /* file to swap on */
-u32_t offset, size;                    /* area on swap file to use */
-{
-/* Turn swapping on. */
-
-  if (swap_fd != -1) return(EBUSY);    /* already have swap? */
-
-  tell_fs(CHDIR, who_e, FALSE, 0);     /* be like the caller for open() */
-  if ((swap_fd = open(file, O_RDWR)) < 0) return(-errno);
-  swap_offset = offset;
-  size >>= CLICK_SHIFT;
-  if (size > swap_maxsize) size = swap_maxsize;
-  if (size > 0) free_mem(swap_base, (phys_clicks) size);
-  return(OK);
-}
-
-/*===========================================================================*
- *                             swap_off                                     *
- *===========================================================================*/
-PUBLIC int swap_off()
-{
-/* Turn swapping off. */
-  struct mproc *rmp;
-  struct hole *hp, *prev_ptr;
-
-  if (swap_fd == -1) return(OK);       /* can't turn off what isn't on */
-
-  /* Put all swapped out processes on the inswap queue and swap in. */
-  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
-       if (rmp->mp_flags & ONSWAP) swap_inqueue(rmp);
-  }
-  swap_in();
-
-  /* All in memory? */
-  for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
-       if (rmp->mp_flags & ONSWAP) return(ENOMEM);
-  }
-
-  /* Yes.  Remove the swap hole and close the swap file descriptor. */
-  for (hp = hole_head; hp != NIL_HOLE; prev_ptr = hp, hp = hp->h_next) {
-       if (hp->h_base >= swap_base) {
-               del_slot(prev_ptr, hp);
-               hp = hole_head;
-       }
-  }
-  close(swap_fd);
-  swap_fd = -1;
-  return(OK);
-}
-
-/*===========================================================================*
- *                             swap_inqueue                                 *
- *===========================================================================*/
-PUBLIC void swap_inqueue(rmp)
-register struct mproc *rmp;            /* process to add to the queue */
-{
-/* Put a swapped out process on the queue of processes to be swapped in.  This
- * happens when such a process gets a signal, or if a reply message must be
- * sent, like when a process doing a wait() has a child that exits.
- */
-  struct mproc **pmp;
-
-  if (rmp->mp_flags & SWAPIN) return;  /* already queued */
-
-  
-  for (pmp = &in_queue; *pmp != NULL; pmp = &(*pmp)->mp_swapq) {}
-  *pmp = rmp;
-  rmp->mp_swapq = NULL;
-  rmp->mp_flags |= SWAPIN;
-}
-
-/*===========================================================================*
- *                             swap_in                                      *
- *===========================================================================*/
-PUBLIC void swap_in()
-{
-/* Try to swap in a process on the inswap queue.  We want to send it a message,
- * interrupt it, or something.
- */
-  struct mproc **pmp, *rmp;
-  phys_clicks old_base, new_base, size;
-  off_t off;
-  int proc_nr;
-
-  pmp = &in_queue;
-  while ((rmp = *pmp) != NULL) {
-       proc_nr = (rmp - mproc);
-       size = rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len
-               - rmp->mp_seg[D].mem_vir;
-
-       if (!(rmp->mp_flags & SWAPIN)) {
-               /* Guess it got killed.  (Queue is cleaned here.) */
-               *pmp = rmp->mp_swapq;
-               continue;
-       } else
-       if ((new_base = alloc_mem(size)) == NO_MEM) {
-               /* No memory for this one, try the next. */
-               pmp = &rmp->mp_swapq;
-       } else {
-               /* We've found memory.  Update map and swap in. */
-               old_base = rmp->mp_seg[D].mem_phys;
-               rmp->mp_seg[D].mem_phys = new_base;
-               rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + 
-                       (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
-               sys_newmap(rmp->mp_endpoint, rmp->mp_seg);
-               off = swap_offset + ((off_t) (old_base-swap_base)<<CLICK_SHIFT);
-               lseek(swap_fd, off, SEEK_SET);
-               rw_seg(0, swap_fd, rmp->mp_endpoint, D, (phys_bytes)size << CLICK_SHIFT);
-               free_mem(old_base, size);
-               rmp->mp_flags &= ~(ONSWAP|SWAPIN);
-               *pmp = rmp->mp_swapq;
-               check_pending(rmp);     /* a signal may have waked this one */
-       }
-  }
-}
-
-/*===========================================================================*
- *                             swap_out                                     *
- *===========================================================================*/
-PRIVATE int swap_out()
-{
-/* Try to find a process that can be swapped out.  Candidates are those blocked
- * on a system call that PM handles, like wait(), pause() or sigsuspend().
- */
-  struct mproc *rmp;
-  struct hole *hp, *prev_ptr;
-  phys_clicks old_base, new_base, size;
-  off_t off;
-  int proc_nr;
-
-  rmp = outswap;
-  do {
-       if (++rmp == &mproc[NR_PROCS]) rmp = &mproc[0];
-
-       /* A candidate? */
-       if (!(rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED))) continue;
-
-       /* Already on swap or otherwise to be avoided? */
-       if (rmp->mp_flags & (DONT_SWAP | TRACED | REPLY | ONSWAP)) continue;
-
-       /* Got one, find a swap hole and swap it out. */
-       proc_nr = (rmp - mproc);
-       size = rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len
-               - rmp->mp_seg[D].mem_vir;
-
-       prev_ptr = NIL_HOLE;
-       for (hp = hole_head; hp != NIL_HOLE; prev_ptr = hp, hp = hp->h_next) {
-               if (hp->h_base >= swap_base && hp->h_len >= size) break;
-       }
-       if (hp == NIL_HOLE) continue;   /* oops, not enough swapspace */
-       new_base = hp->h_base;
-       hp->h_base += size;
-       hp->h_len -= size;
-       if (hp->h_len == 0) del_slot(prev_ptr, hp);
-
-       off = swap_offset + ((off_t) (new_base - swap_base) << CLICK_SHIFT);
-       lseek(swap_fd, off, SEEK_SET);
-       rw_seg(1, swap_fd, rmp->mp_endpoint, D, (phys_bytes)size << CLICK_SHIFT);
-       old_base = rmp->mp_seg[D].mem_phys;
-       rmp->mp_seg[D].mem_phys = new_base;
-       rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + 
-               (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
-       sys_newmap(rmp->mp_endpoint, rmp->mp_seg);
-       free_mem(old_base, size);
-       rmp->mp_flags |= ONSWAP;
-
-       outswap = rmp;          /* next time start here */
-       return(TRUE);
-  } while (rmp != outswap);
-
-  return(FALSE);       /* no candidate found */
-}
-#endif /* SWAP */
diff --git a/servers/pm/asynsend.c b/servers/pm/asynsend.c
deleted file mode 100644 (file)
index de7e5d1..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-
-#include "pm.h"
-
-#define ASYN_NR        100
-PRIVATE asynmsg_t msgtable[ASYN_NR];
-PRIVATE int first_slot= 0, next_slot= 0;
-
-PUBLIC int asynsend(dst, mp)
-endpoint_t dst;
-message *mp;
-{
-       int r, src_ind, dst_ind;
-       unsigned flags;
-
-       /* Update first_slot */
-       for (; first_slot < next_slot; first_slot++)
-       {
-               flags= msgtable[first_slot].flags;
-               if ((flags & (AMF_VALID|AMF_DONE)) == (AMF_VALID|AMF_DONE))
-               {
-                       if (msgtable[first_slot].result != OK)
-                       {
-                               printf(
-                       "asynsend: found completed entry %d with error %d\n",
-                                       first_slot,
-                                       msgtable[first_slot].result);
-                       }
-                       continue;
-               }
-               if (flags != AMF_EMPTY)
-                       break;
-       }
-
-       if (first_slot >= next_slot)
-       {
-               /* Reset first_slot and next_slot */
-               next_slot= first_slot= 0;
-       }
-
-       if (next_slot >= ASYN_NR)
-       {
-               /* Tell the kernel to stop processing */
-               r= senda(NULL, 0);
-               if (r != OK)
-                       panic(__FILE__, "asynsend: senda failed", r);
-
-               dst_ind= 0;
-               for (src_ind= first_slot; src_ind<next_slot; src_ind++)
-               {
-                       flags= msgtable[src_ind].flags;
-                       if ((flags & (AMF_VALID|AMF_DONE)) ==
-                               (AMF_VALID|AMF_DONE))
-                       {
-                               if (msgtable[src_ind].result != OK)
-                               {
-                                       printf(
-                       "asynsend: found completed entry %d with error %d\n",
-                                               src_ind,
-                                               msgtable[src_ind].result);
-                               }
-                               continue;
-                       }
-                       if (flags == AMF_EMPTY)
-                               continue;
-#if 0
-                       printf("asynsend: copying entry %d to %d\n",
-                               src_ind, dst_ind);
-#endif
-                       if (src_ind != dst_ind)
-                               msgtable[dst_ind]= msgtable[src_ind];
-                       dst_ind++;
-               }
-               first_slot= 0;
-               next_slot= dst_ind;
-               if (next_slot >= ASYN_NR)
-                       panic(__FILE__, "asynsend: msgtable full", NO_NUM);
-       }
-
-       msgtable[next_slot].dst= dst;
-       msgtable[next_slot].msg= *mp;
-       msgtable[next_slot].flags= AMF_VALID;   /* Has to be last. The kernel 
-                                                * scans this table while we
-                                                * are sleeping.
-                                                */
-       next_slot++;
-
-       /* Tell the kernel to rescan the table */
-       return senda(msgtable+first_slot, next_slot-first_slot);
-}
-
index cf87dfe0e01d3bc856cef65f8a8111b8212fb70b..b2afdf82314d27f02c66ec777824b4cbba630d98 100644 (file)
-/* The MINIX model of memory allocation reserves a fixed amount of memory for
- * the combined text, data, and stack segments.  The amount used for a child
- * process created by FORK is the same as the parent had.  If the child does
- * an EXEC later, the new size is taken from the header of the file EXEC'ed.
- *
- * The layout in memory consists of the text segment, followed by the data
- * segment, followed by a gap (unused memory), followed by the stack segment.
- * The data segment grows upward and the stack grows downward, so each can
- * take memory from the gap.  If they meet, the process must be killed.  The
- * procedures in this file deal with the growth of the data and stack segments.
- *
- * The entry points into this file are:
- *   do_brk:     BRK/SBRK system calls to grow or shrink the data segment
- *   adjust:     see if a proposed segment adjustment is allowed
- *   size_ok:    see if the segment sizes are feasible (i86 only)
- */
 
 #include "pm.h"
-#include <signal.h>
-#include "mproc.h"
 #include "param.h"
+#include "glo.h"
+#include "mproc.h"
 
-#define DATA_CHANGED       1   /* flag value when data segment size changed */
-#define STACK_CHANGED      2   /* flag value when stack size changed */
+#include <minix/vm.h>
 
 /*===========================================================================*
  *                             do_brk                                       *
  *===========================================================================*/
 PUBLIC int do_brk()
 {
-/* Entry point to brk(addr) system call. real_brk() does the real work,
- * as that is called from elsewhere too.
- */
   int r;
-  r = real_brk(mp, (vir_bytes) m_in.addr);
+/* Entry point to brk(addr) system call.  */
+  r = vm_brk(mp->mp_endpoint, m_in.addr);
   mp->mp_reply.reply_ptr = (r == OK ? m_in.addr : (char *) -1);
   return r;
 }
 
-/*===========================================================================*
- *                             do_brk                                       *
- *===========================================================================*/
-PUBLIC int real_brk(struct mproc *rmp, vir_bytes v)
-{
-/* Perform the brk(addr) system call.
- *
- * The call is complicated by the fact that on some machines (e.g., 8088),
- * the stack pointer can grow beyond the base of the stack segment without
- * anybody noticing it.
- * The parameter, 'addr' is the new virtual address in D space.
- *
- * This call can also be performed on PM itself from brk() in misc.c.
- */
-  int r;
-  vir_bytes new_sp;
-  vir_clicks new_clicks;
-
-  new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT);
-  if (new_clicks < rmp->mp_seg[D].mem_vir) {
-       rmp->mp_reply.reply_ptr = (char *) -1;
-       return(ENOMEM);
-  }
-  new_clicks -= rmp->mp_seg[D].mem_vir;
-  if ((r=get_stack_ptr(rmp->mp_endpoint, &new_sp)) != OK) /* get sp value */
-       panic(__FILE__,"couldn't get stack pointer", r);
-  r = adjust(rmp, new_clicks, new_sp);
-  return(r);                   /* return new address or -1 */
-}
-
-/*===========================================================================*
- *                             adjust                                       *
- *===========================================================================*/
-PUBLIC int adjust(rmp, data_clicks, sp)
-register struct mproc *rmp;    /* whose memory is being adjusted? */
-vir_clicks data_clicks;                /* how big is data segment to become? */
-vir_bytes sp;                  /* new value of sp */
-{
-/* See if data and stack segments can coexist, adjusting them if need be.
- * Memory is never allocated or freed.  Instead it is added or removed from the
- * gap between data segment and stack segment.  If the gap size becomes
- * negative, the adjustment of data or stack fails and ENOMEM is returned.
- */
-
-  register struct mem_map *mem_sp, *mem_dp;
-  vir_clicks sp_click, gap_base, lower, old_clicks;
-  int changed, r, ft;
-  long base_of_stack, delta;   /* longs avoid certain problems */
-
-  mem_dp = &rmp->mp_seg[D];    /* pointer to data segment map */
-  mem_sp = &rmp->mp_seg[S];    /* pointer to stack segment map */
-  changed = 0;                 /* set when either segment changed */
-
-  /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
-  base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
-  sp_click = sp >> CLICK_SHIFT;        /* click containing sp */
-  if (sp_click >= base_of_stack)
-  {
-       return(ENOMEM); /* sp too high */
-  }
-
-  /* Compute size of gap between stack and data segments. */
-  delta = (long) mem_sp->mem_vir - (long) sp_click;
-  lower = (delta > 0 ? sp_click : mem_sp->mem_vir);
-
-  /* Add a safety margin for future stack growth. Impossible to do right. */
-#define SAFETY_BYTES  (384 * sizeof(char *))
-#define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
-  gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
-  if (lower < gap_base)
-  {
-       return(ENOMEM); /* data and stack collided */
-  }
-
-  /* Update data length (but not data orgin) on behalf of brk() system call. */
-  old_clicks = mem_dp->mem_len;
-  if (data_clicks != mem_dp->mem_len) {
-       mem_dp->mem_len = data_clicks;
-       changed |= DATA_CHANGED;
-  }
-
-  /* Update stack length and origin due to change in stack pointer. */
-  if (delta > 0) {
-       mem_sp->mem_vir -= delta;
-       mem_sp->mem_phys -= delta;
-       mem_sp->mem_len += delta;
-       changed |= STACK_CHANGED;
-  }
-
-  /* Do the new data and stack segment sizes fit in the address space? */
-  ft = (rmp->mp_flags & SEPARATE);
-#if (CHIP == INTEL && _WORD_SIZE == 2)
-  r = size_ok(ft, rmp->mp_seg[T].mem_len, rmp->mp_seg[D].mem_len, 
-       rmp->mp_seg[S].mem_len, rmp->mp_seg[D].mem_vir, rmp->mp_seg[S].mem_vir);
-#else
-  r = (rmp->mp_seg[D].mem_vir + rmp->mp_seg[D].mem_len > 
-          rmp->mp_seg[S].mem_vir) ? ENOMEM : OK;
-#endif
-  if (r == OK) {
-       int r2;
-       if (changed && (r2=sys_newmap(rmp->mp_endpoint, rmp->mp_seg)) != OK)
-               panic(__FILE__,"couldn't sys_newmap in adjust", r2);
-       return(OK);
-  }
-
-  /* New sizes don't fit or require too many page/segment registers. Restore.*/
-  if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks;
-  if (changed & STACK_CHANGED) {
-       mem_sp->mem_vir += delta;
-       mem_sp->mem_phys += delta;
-       mem_sp->mem_len -= delta;
-  }
-  return(ENOMEM);
-}
-
-#if (CHIP == INTEL && _WORD_SIZE == 2)
-/*===========================================================================*
- *                             size_ok                                      *
- *===========================================================================*/
-PUBLIC int size_ok(file_type, tc, dc, sc, dvir, s_vir)
-int file_type;                 /* SEPARATE or 0 */
-vir_clicks tc;                 /* text size in clicks */
-vir_clicks dc;                 /* data size in clicks */
-vir_clicks sc;                 /* stack size in clicks */
-vir_clicks dvir;               /* virtual address for start of data seg */
-vir_clicks s_vir;              /* virtual address for start of stack seg */
-{
-/* Check to see if the sizes are feasible and enough segmentation registers
- * exist.  On a machine with eight 8K pages, text, data, stack sizes of
- * (32K, 16K, 16K) will fit, but (33K, 17K, 13K) will not, even though the
- * former is bigger (64K) than the latter (63K).  Even on the 8088 this test
- * is needed, since the data and stack may not exceed 4096 clicks.
- * Note this is not used for 32-bit Intel Minix, the test is done in-line.
- */
-
-  int pt, pd, ps;              /* segment sizes in pages */
-
-  pt = ( (tc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
-  pd = ( (dc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
-  ps = ( (sc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
-
-  if (file_type == SEPARATE) {
-       if (pt > MAX_PAGES || pd + ps > MAX_PAGES) return(ENOMEM);
-  } else {
-       if (pt + pd + ps > MAX_PAGES) return(ENOMEM);
-  }
-
-  if (dvir + dc > s_vir) return(ENOMEM);
-
-  return(OK);
-}
-#endif
-
index 200dfe8375d9ba009647b0bac14f4e576d908b71..886380a7c6169e9c9767ccaadabcfb54ccc6e62b 100644 (file)
@@ -1,16 +1,5 @@
 /* Constants used by the Process Manager. */
 
-#define NO_MEM ((phys_clicks) 0)  /* returned by alloc_mem() with mem is up */
-
-#if (CHIP == INTEL && _WORD_SIZE == 2)
-/* These definitions are used in size_ok and are not needed for 386.
- * The 386 segment granularity is 1 for segments smaller than 1M and 4096
- * above that.  
- */
-#define PAGE_SIZE        16    /* how many bytes in a page (s.b.HCLICK_SIZE)*/
-#define MAX_PAGES       4096   /* how many pages in the virtual addr space */
-#endif
-
 #define NR_PIDS               30000    /* process ids range from 0 to NR_PIDS-1.
                                 * (magic constant: some old applications use
                                 * a 'short' instead of pid_t.)
index 0190bb7b957a36ef269bc78bbbd1b6f37e590492..62dd5f678150fa620ecf314a167adf4c6df671cb 100644 (file)
 #include <minix/callnr.h>
 #include <minix/endpoint.h>
 #include <minix/com.h>
+#include <minix/vm.h>
 #include <a.out.h>
 #include <signal.h>
 #include <string.h>
 #include "mproc.h"
 #include "param.h"
 
-FORWARD _PROTOTYPE( int new_mem, (struct mproc *rmp, struct mproc *sh_mp,
-       vir_bytes text_bytes, vir_bytes data_bytes, vir_bytes bss_bytes,
-       vir_bytes stk_bytes, phys_bytes tot_bytes)                      );
-
 #define ESCRIPT        (-2000) /* Returned by read_header for a #! script. */
 #define PTRSIZE        sizeof(char *) /* Size of pointers in argv[] and envp[]. */
 
@@ -69,12 +66,12 @@ PUBLIC int do_exec()
  *===========================================================================*/
 PUBLIC int exec_newmem()
 {
-       int r, proc_e, proc_n, allow_setuid;
-       vir_bytes stack_top;
-       vir_clicks tc, dc, sc, totc, dvir, s_vir;
-       struct mproc *rmp, *sh_mp;
+       int proc_e, proc_n, allow_setuid;
        char *ptr;
+       struct mproc *rmp;
        struct exec_newmem args;
+       int r, flags;
+       char *stack_top;
 
        if (who_e != FS_PROC_NR && who_e != RS_PROC_NR)
                return EPERM;
@@ -86,84 +83,40 @@ PUBLIC int exec_newmem()
                        proc_e);
        }
        rmp= &mproc[proc_n];
-
        ptr= m_in.EXC_NM_PTR;
        r= sys_datacopy(who_e, (vir_bytes)ptr,
                SELF, (vir_bytes)&args, sizeof(args));
        if (r != OK)
                panic(__FILE__, "exec_newmem: sys_datacopy failed", r);
 
-       /* Check to see if segment sizes are feasible. */
-       tc = ((unsigned long) args.text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
-       dc = (args.data_bytes+args.bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
-       totc = (args.tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
-       sc = (args.args_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
-       if (dc >= totc) return(ENOEXEC); /* stack must be at least 1 click */
-
-       dvir = (args.sep_id ? 0 : tc);
-       s_vir = dvir + (totc - sc);
-#if (CHIP == INTEL && _WORD_SIZE == 2)
-       r = size_ok(*ft, tc, dc, sc, dvir, s_vir);
-#else
-       r = (dvir + dc > s_vir) ? ENOMEM : OK;
-#endif
-       if (r != OK)
-               return r;
-
-       /* Can the process' text be shared with that of one already running? */
-       sh_mp = find_share(rmp, args.st_ino, args.st_dev, args.st_ctime);
+       if((r=vm_exec_newmem(proc_e, &args, sizeof(args), &stack_top, &flags)) == OK) {
+               allow_setuid= 0;                /* Do not allow setuid execution */  
 
-       /* Allocate new memory and release old memory.  Fix map and tell
-        * kernel.
-        */
-       r = new_mem(rmp, sh_mp, args.text_bytes, args.data_bytes,
-               args.bss_bytes, args.args_bytes, args.tot_bytes);
-       if (r != OK) return(r);
-
-       rmp->mp_flags |= PARTIAL_EXEC;  /* Kill process if something goes
-                                        * wrong after this point.
-                                        */
-
-       /* Save file identification to allow it to be shared. */
-       rmp->mp_ino = args.st_ino;
-       rmp->mp_dev = args.st_dev;
-       rmp->mp_ctime = args.st_ctime;
+               if ((rmp->mp_flags & TRACED) == 0) {
+                       /* Okay, setuid execution is allowed */
+                       allow_setuid= 1;
+                       rmp->mp_effuid = args.new_uid;
+                       rmp->mp_effgid = args.new_gid;
+               }
 
-       stack_top= ((vir_bytes)rmp->mp_seg[S].mem_vir << CLICK_SHIFT) +
-               ((vir_bytes)rmp->mp_seg[S].mem_len << CLICK_SHIFT);
+               /* System will save command line for debugging, ps(1) output, etc. */
+               strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1);
+               rmp->mp_name[PROC_NAME_LEN-1] = '\0';
 
-       /* Save offset to initial argc (for ps) */
-       rmp->mp_procargs = stack_top - args.args_bytes;
+               /* Save offset to initial argc (for ps) */
+               rmp->mp_procargs = (vir_bytes) stack_top - args.args_bytes;
 
-       /* set/clear separate I&D flag */
-       if (args.sep_id)
-               rmp->mp_flags |= SEPARATE;      
-       else
-               rmp->mp_flags &= ~SEPARATE;
+               /* Kill process if something goes wrong after this point. */
+               rmp->mp_flags |= PARTIAL_EXEC;
 
-       allow_setuid= 0;                /* Do not allow setuid execution */
-       if ((rmp->mp_flags & TRACED) == 0) {
-               /* Okay, setuid execution is allowed */
-               allow_setuid= 1;
-               rmp->mp_effuid = args.new_uid;
-               rmp->mp_effgid = args.new_gid;
+               mp->mp_reply.reply_res2= (vir_bytes) stack_top;
+               mp->mp_reply.reply_res3= flags;
+               if (allow_setuid)
+                       mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID;
        }
-
-       /* System will save command line for debugging, ps(1) output, etc. */
-       strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1);
-       rmp->mp_name[PROC_NAME_LEN-1] = '\0';
-
-       mp->mp_reply.reply_res2= stack_top;
-       mp->mp_reply.reply_res3= 0;
-       if (!sh_mp)                      /* Load text if sh_mp = NULL */
-               mp->mp_reply.reply_res3 |= EXC_NM_RF_LOAD_TEXT;
-       if (allow_setuid)
-               mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID;
-
-       return OK;
+       return r;
 }
 
-
 /*===========================================================================*
  *                             do_execrestart                               *
  *===========================================================================*/
@@ -239,140 +192,3 @@ int result;
        if (rmp->mp_flags & TRACED) check_sig(rmp->mp_pid, SIGTRAP);
 }
 
-/*===========================================================================*
- *                             find_share                                   *
- *===========================================================================*/
-PUBLIC struct mproc *find_share(mp_ign, ino, dev, ctime)
-struct mproc *mp_ign;          /* process that should not be looked at */
-ino_t ino;                     /* parameters that uniquely identify a file */
-dev_t dev;
-time_t ctime;
-{
-/* Look for a process that is the file <ino, dev, ctime> in execution.  Don't
- * accidentally "find" mp_ign, because it is the process on whose behalf this
- * call is made.
- */
-  struct mproc *sh_mp;
-  for (sh_mp = &mproc[0]; sh_mp < &mproc[NR_PROCS]; sh_mp++) {
-
-       if (!(sh_mp->mp_flags & SEPARATE)) continue;
-       if (sh_mp == mp_ign) continue;
-       if (sh_mp->mp_ino != ino) continue;
-       if (sh_mp->mp_dev != dev) continue;
-       if (sh_mp->mp_ctime != ctime) continue;
-       return sh_mp;
-  }
-  return(NULL);
-}
-
-/*===========================================================================*
- *                             new_mem                                      *
- *===========================================================================*/
-PRIVATE int new_mem(rmp, sh_mp, text_bytes, data_bytes,
-       bss_bytes,stk_bytes,tot_bytes)
-struct mproc *rmp;             /* process to get a new memory map */
-struct mproc *sh_mp;           /* text can be shared with this process */
-vir_bytes text_bytes;          /* text segment size in bytes */
-vir_bytes data_bytes;          /* size of initialized data in bytes */
-vir_bytes bss_bytes;           /* size of bss in bytes */
-vir_bytes stk_bytes;           /* size of initial stack segment in bytes */
-phys_bytes tot_bytes;          /* total memory to allocate, including gap */
-{
-/* Allocate new memory and release the old memory.  Change the map and report
- * the new map to the kernel.  Zero the new core image's bss, gap and stack.
- */
-
-  vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
-  phys_clicks new_base;
-  phys_bytes bytes, base, bss_offset;
-  int s, r2;
-
-  /* No need to allocate text if it can be shared. */
-  if (sh_mp != NULL) text_bytes = 0;
-
-  /* Allow the old data to be swapped out to make room.  (Which is really a
-   * waste of time, because we are going to throw it away anyway.)
-   */
-  rmp->mp_flags |= WAITING;
-
-  /* Acquire the new memory.  Each of the 4 parts: text, (data+bss), gap,
-   * and stack occupies an integral number of clicks, starting at click
-   * boundary.  The data and bss parts are run together with no space.
-   */
-  text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
-  data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
-  stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
-  tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
-  gap_clicks = tot_clicks - data_clicks - stack_clicks;
-  if ( (int) gap_clicks < 0) return(ENOMEM);
-
-  /* Try to allocate memory for the new process. */
-  new_base = alloc_mem(text_clicks + tot_clicks);
-  if (new_base == NO_MEM) return(ENOMEM);
-
-  /* We've got memory for the new core image.  Release the old one. */
-  if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
-       /* No other process shares the text segment, so free it. */
-       free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
-  }
-  /* Free the data and stack segments. */
-  free_mem(rmp->mp_seg[D].mem_phys,
-   rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
-
-  /* We have now passed the point of no return.  The old core image has been
-   * forever lost, memory for a new core image has been allocated.  Set up
-   * and report new map.
-   */
-  if (sh_mp != NULL) {
-       /* Share the text segment. */
-       rmp->mp_seg[T] = sh_mp->mp_seg[T];
-  } else {
-       rmp->mp_seg[T].mem_phys = new_base;
-       rmp->mp_seg[T].mem_vir = 0;
-       rmp->mp_seg[T].mem_len = text_clicks;
-
-       if (text_clicks > 0)
-       {
-               /* Zero the last click of the text segment. Otherwise the
-                * part of that click may remain unchanged.
-                */
-               base = (phys_bytes)(new_base+text_clicks-1) << CLICK_SHIFT;
-               if ((s= sys_memset(0, base, CLICK_SIZE)) != OK)
-                       panic(__FILE__, "new_mem: sys_memset failed", s);
-       }
-  }
-  rmp->mp_seg[D].mem_phys = new_base + text_clicks;
-  rmp->mp_seg[D].mem_vir = 0;
-  rmp->mp_seg[D].mem_len = data_clicks;
-  rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;
-  rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;
-  rmp->mp_seg[S].mem_len = stack_clicks;
-
-#if (CHIP == M68000)
-  rmp->mp_seg[T].mem_vir = 0;
-  rmp->mp_seg[D].mem_vir = rmp->mp_seg[T].mem_len;
-  rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir 
-       + rmp->mp_seg[D].mem_len + gap_clicks;
-#endif
-
-  if((r2=sys_newmap(rmp->mp_endpoint, rmp->mp_seg)) != OK) {
-       /* report new map to the kernel */
-       panic(__FILE__,"sys_newmap failed", r2);
-  }
-
-  /* The old memory may have been swapped out, but the new memory is real. */
-  rmp->mp_flags &= ~(WAITING|ONSWAP|SWAPIN);
-
-  /* Zero the bss, gap, and stack segment. */
-  bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
-  base = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
-  bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT;
-  base += bss_offset;
-  bytes -= bss_offset;
-
-  if ((s=sys_memset(0, base, bytes)) != OK) {
-       panic(__FILE__,"new_mem can't zero", s);
-  }
-
-  return(OK);
-}
index 1352472738d2edcdfb450e53f271f513e0eb32dc..63656ad6be8af251f0e6c43356d351049daf527f 100644 (file)
@@ -18,6 +18,7 @@
 #include <sys/wait.h>
 #include <minix/callnr.h>
 #include <minix/com.h>
+#include <minix/vm.h>
 #include <sys/resource.h>
 #include <signal.h>
 #include "mproc.h"
@@ -35,12 +36,10 @@ PUBLIC int do_fork()
 /* The process pointed to by 'mp' has forked.  Create a child process. */
   register struct mproc *rmp;  /* pointer to parent */
   register struct mproc *rmc;  /* pointer to child */
-  int child_nr, s;
-  phys_clicks prog_clicks, child_base;
-  phys_bytes prog_bytes, parent_abs, child_abs;        /* Intel only */
   pid_t new_pid;
   static int next_child;
-  int n = 0, r;
+  int n = 0, r, s;
+  endpoint_t child_ep;
 
  /* If tables might fill up during FORK, don't even start since recovery half
   * way through is such a nuisance.
@@ -53,20 +52,6 @@ PUBLIC int do_fork()
        return(EAGAIN);
   }
 
-  /* Determine how much memory to allocate.  Only the data and stack need to
-   * be copied, because the text segment is either shared or of zero length.
-   */
-  prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
-  prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
-  prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT;
-  if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(ENOMEM);
-
-  /* Create a copy of the parent's core image for the child. */
-  child_abs = (phys_bytes) child_base << CLICK_SHIFT;
-  parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
-  s = sys_abscopy(parent_abs, child_abs, prog_bytes);
-  if (s < 0) panic(__FILE__,"do_fork can't copy", s);
-
   /* Find a slot in 'mproc' for the child process.  A slot must exist. */
   do {
         next_child = (next_child+1) % NR_PROCS;
@@ -78,36 +63,31 @@ PUBLIC int do_fork()
  || (mproc[next_child].mp_flags & IN_USE))
        panic(__FILE__,"do_fork finds wrong child slot", next_child);
 
+  /* Memory part of the forking. */
+  if((s=vm_fork(rmp->mp_endpoint, next_child, &child_ep)) != OK) {
+       printf("PM: vm_fork failed: %d\n", s);
+       return s;
+  }
+
+  /* PM may not fail fork after call to vm_fork(), as VM calls sys_fork(). */
+
   rmc = &mproc[next_child];
   /* Set up the child and its memory map; copy its 'mproc' slot from parent. */
-  child_nr = (int)(rmc - mproc);       /* slot number of the child */
   procs_in_use++;
   *rmc = *rmp;                 /* copy parent's process slot to child's */
   rmc->mp_parent = who_p;                      /* record child's parent */
   /* inherit only these flags */
-  rmc->mp_flags &= (IN_USE|SEPARATE|PRIV_PROC|DONT_SWAP);
+  rmc->mp_flags &= (IN_USE|PRIV_PROC);
   rmc->mp_child_utime = 0;             /* reset administration */
   rmc->mp_child_stime = 0;             /* reset administration */
-
-  /* A separate I&D child keeps the parents text segment.  The data and stack
-   * segments must refer to the new copy.
-   */
-  if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base;
-  rmc->mp_seg[D].mem_phys = child_base;
-  rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + 
-                       (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
   rmc->mp_exitstatus = 0;
   rmc->mp_sigstatus = 0;
+  rmc->mp_endpoint = child_ep;         /* passed back by VM */
 
   /* Find a free pid for the child and put it in the table. */
   new_pid = get_free_pid();
   rmc->mp_pid = new_pid;       /* assign pid to child */
 
-  /* Tell kernel and file system about the (now successful) FORK. */
-  if((r=sys_fork(who_e, child_nr, &rmc->mp_endpoint, rmc->mp_seg)) != OK) {
-       panic(__FILE__,"do_fork can't sys_fork", r);
-  }
-
   if (rmc->mp_fs_call != PM_IDLE)
        panic("pm", "do_fork: not idle", rmc->mp_fs_call);
   rmc->mp_fs_call= PM_FORK;
@@ -128,12 +108,11 @@ PUBLIC int do_fork_nb()
 /* The process pointed to by 'mp' has forked.  Create a child process. */
   register struct mproc *rmp;  /* pointer to parent */
   register struct mproc *rmc;  /* pointer to child */
-  int child_nr, s;
-  phys_clicks prog_clicks, child_base;
-  phys_bytes prog_bytes, parent_abs, child_abs;        /* Intel only */
+  int s;
   pid_t new_pid;
   static int next_child;
   int n = 0, r;
+  endpoint_t child_ep;
 
   /* Only system processes are allowed to use fork_nb */
   if (!(mp->mp_flags & PRIV_PROC))
@@ -150,20 +129,6 @@ PUBLIC int do_fork_nb()
        return(EAGAIN);
   }
 
-  /* Determine how much memory to allocate.  Only the data and stack need to
-   * be copied, because the text segment is either shared or of zero length.
-   */
-  prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
-  prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
-  prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT;
-  if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(ENOMEM);
-
-  /* Create a copy of the parent's core image for the child. */
-  child_abs = (phys_bytes) child_base << CLICK_SHIFT;
-  parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
-  s = sys_abscopy(parent_abs, child_abs, prog_bytes);
-  if (s < 0) panic(__FILE__,"do_fork can't copy", s);
-
   /* Find a slot in 'mproc' for the child process.  A slot must exist. */
   do {
         next_child = (next_child+1) % NR_PROCS;
@@ -175,36 +140,26 @@ PUBLIC int do_fork_nb()
  || (mproc[next_child].mp_flags & IN_USE))
        panic(__FILE__,"do_fork finds wrong child slot", next_child);
 
+  if((s=vm_fork(rmp->mp_endpoint, next_child, &child_ep)) != OK) {
+       printf("PM: vm_fork failed: %d\n", s);
+       return s;
+  }
+
   rmc = &mproc[next_child];
   /* Set up the child and its memory map; copy its 'mproc' slot from parent. */
-  child_nr = (int)(rmc - mproc);       /* slot number of the child */
   procs_in_use++;
   *rmc = *rmp;                 /* copy parent's process slot to child's */
   rmc->mp_parent = who_p;                      /* record child's parent */
   /* inherit only these flags */
-  rmc->mp_flags &= (IN_USE|SEPARATE|PRIV_PROC|DONT_SWAP);
+  rmc->mp_flags &= (IN_USE|PRIV_PROC);
   rmc->mp_child_utime = 0;             /* reset administration */
   rmc->mp_child_stime = 0;             /* reset administration */
-
-  /* A separate I&D child keeps the parents text segment.  The data and stack
-   * segments must refer to the new copy.
-   */
-  if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base;
-  rmc->mp_seg[D].mem_phys = child_base;
-  rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + 
-                       (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
-  rmc->mp_exitstatus = 0;
-  rmc->mp_sigstatus = 0;
+  rmc->mp_endpoint = child_ep;         /* passed back by VM */
 
   /* Find a free pid for the child and put it in the table. */
   new_pid = get_free_pid();
   rmc->mp_pid = new_pid;       /* assign pid to child */
 
-  /* Tell kernel and file system about the (now successful) FORK. */
-  if((r=sys_fork(who_e, child_nr, &rmc->mp_endpoint, rmc->mp_seg)) != OK) {
-       panic(__FILE__,"do_fork can't sys_fork", r);
-  }
-
   if (rmc->mp_fs_call != PM_IDLE)
        panic("pm", "do_fork: not idle", rmc->mp_fs_call);
   rmc->mp_fs_call= PM_FORK_NB;
@@ -271,6 +226,9 @@ int for_trace;
    * such as copying to/ from the exiting process, before it is gone.
    */
   sys_nice(proc_nr_e, PRIO_STOP);      /* stop the process */
+  if(vm_willexit(proc_nr_e) != OK) {
+       panic(__FILE__, "pm_exit: vm_willexit failed", proc_nr_e);
+  }
 
   if (proc_nr_e == INIT_PROC_NR)
   {
@@ -392,7 +350,9 @@ PUBLIC int do_waitpid()
   /* No qualifying child has exited.  Wait for one, unless none exists. */
   if (children > 0) {
        /* At least 1 child meets the pid test exists, but has not exited. */
-       if (options & WNOHANG) return(0);    /* parent does not want to wait */
+       if (options & WNOHANG) {
+               return(0);    /* parent does not want to wait */
+       }
        mp->mp_flags |= WAITING;             /* parent wants to wait */
        mp->mp_wpid = (pid_t) pidarg;        /* save pid for later */
        return(SUSPEND);                     /* do not reply, let it wait */
index b0c53b0992b11fce359aa6e3ba7724ba0d8b9b9e..e764581b635ffeb73adcaa229b84d10ab033350c 100644 (file)
@@ -15,7 +15,7 @@
 
 #define PRINTPROCS (sizeof(procs)/sizeof(procs[0]))
 
-static char print_buf[80];     /* output is buffered here */
+static char print_buf[800];    /* output is buffered here */
 
 int kputc_use_private_grants= 0;
 
index 4a60bd1e757bbd92757d7247c772da9c99e6e41a..8f603a7b9a60793bf15443caad6bb54611c3493f 100644 (file)
@@ -18,6 +18,7 @@
 #include <minix/endpoint.h>
 #include <minix/minlib.h>
 #include <minix/type.h>
+#include <minix/vm.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -41,10 +42,6 @@ EXTERN unsigned long calls_stats[NCALLS];
 FORWARD _PROTOTYPE( void get_work, (void)                              );
 FORWARD _PROTOTYPE( void pm_init, (void)                               );
 FORWARD _PROTOTYPE( int get_nice_value, (int queue)                    );
-FORWARD _PROTOTYPE( void get_mem_chunks, (struct memory *mem_chunks)   );
-FORWARD _PROTOTYPE( void patch_mem_chunks, (struct memory *mem_chunks, 
-       struct mem_map *map_ptr)        );
-FORWARD _PROTOTYPE( void do_x86_vm, (struct memory mem_chunks[NR_MEMS])        );
 FORWARD _PROTOTYPE( void send_work, (void)                             );
 FORWARD _PROTOTYPE( void handle_fs_reply, (message *m_ptr)             );
 
@@ -138,7 +135,9 @@ PUBLIC int main()
 #if ENABLE_SYSCALL_STATS
                        calls_stats[call_nr]++;
 #endif
+
                        result = (*call_vec[call_nr])();
+
                }
                break;
        }
@@ -146,10 +145,8 @@ PUBLIC int main()
        /* Send the results back to the user to indicate completion. */
        if (result != SUSPEND) setreply(who_p, result);
 
-       swap_in();              /* maybe a process can be swapped in? */
-
        /* Send out all pending reply messages, including the answer to
-        * the call just made above.  The processes must not be swapped out.
+        * the call just made above.
         */
        for (proc_nr=0, rmp=mproc; proc_nr < NR_PROCS; proc_nr++, rmp++) {
                /* In the meantime, the process may have been killed by a
@@ -157,7 +154,7 @@ PUBLIC int main()
                 * without the PM realizing it. If the slot is no longer in
                 * use or just a zombie, don't try to reply.
                 */
-               if ((rmp->mp_flags & (REPLY | ONSWAP | IN_USE | ZOMBIE)) ==
+               if ((rmp->mp_flags & (REPLY | IN_USE | ZOMBIE)) ==
                   (REPLY | IN_USE)) {
                        s=sendnb(rmp->mp_endpoint, &rmp->mp_reply);
                        if (s != OK) {
@@ -213,9 +210,6 @@ int result;                 /* result of call (usually OK or error #) */
 
   rmp->mp_reply.reply_res = result;
   rmp->mp_flags |= REPLY;      /* reply pending */
-
-  if (rmp->mp_flags & ONSWAP)
-       swap_inqueue(rmp);      /* must swap this process back in */
 }
 
 /*===========================================================================*
@@ -223,6 +217,8 @@ int result;                 /* result of call (usually OK or error #) */
  *===========================================================================*/
 PRIVATE void pm_init()
 {
+       int failed = 0;
+       int f = 0;
 /* Initialize the process manager. 
  * Memory use info is collected from the boot monitor, the kernel, and
  * all processes compiled into the system image. Initially this information
@@ -244,10 +240,7 @@ PRIVATE void pm_init()
   static char mess_sigs[] = { SIGTERM, SIGHUP, SIGABRT, SIGQUIT };
   register struct mproc *rmp;
   register char *sig_ptr;
-  phys_clicks total_clicks, minix_clicks, free_clicks;
   message mess;
-  struct mem_map mem_map[NR_LOCAL_SEGS];
-  struct memory mem_chunks[NR_MEMS];
 
   /* Initialize process table, including timers. */
   for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) {
@@ -273,30 +266,25 @@ PRIVATE void pm_init()
    */
   if ((s=sys_getmonparams(monitor_params, sizeof(monitor_params))) != OK)
       panic(__FILE__,"get monitor params failed",s);
-  get_mem_chunks(mem_chunks);
   if ((s=sys_getkinfo(&kinfo)) != OK)
       panic(__FILE__,"get kernel info failed",s);
 
-  /* Get the memory map of the kernel to see how much memory it uses. */
-  if ((s=get_mem_map(SYSTASK, mem_map)) != OK)
-       panic(__FILE__,"couldn't get memory map of SYSTASK",s);
-  minix_clicks = (mem_map[S].mem_phys+mem_map[S].mem_len)-mem_map[T].mem_phys;
-  patch_mem_chunks(mem_chunks, mem_map);
-
   /* Initialize PM's process table. Request a copy of the system image table 
    * that is defined at the kernel level to see which slots to fill in.
    */
   if (OK != (s=sys_getimage(image))) 
        panic(__FILE__,"couldn't get image table: %d\n", s);
   procs_in_use = 0;                            /* start populating table */
-  for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) {             
+  for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) {
        if (ip->proc_nr >= 0) {                 /* task have negative nrs */
                procs_in_use += 1;              /* found user process */
 
                /* Set process details found in the image table. */
                rmp = &mproc[ip->proc_nr];      
                strncpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN); 
+#if 0
                rmp->mp_parent = RS_PROC_NR;
+#endif
                rmp->mp_nice = get_nice_value(ip->priority);
                sigemptyset(&rmp->mp_sig2mess);
                sigemptyset(&rmp->mp_ignore);   
@@ -308,7 +296,7 @@ PRIVATE void pm_init()
                }
                else {                                  /* system process */
                        rmp->mp_pid = get_free_pid();
-                       rmp->mp_flags |= IN_USE | DONT_SWAP | PRIV_PROC; 
+                       rmp->mp_flags |= IN_USE | PRIV_PROC; 
                        for (sig_ptr = mess_sigs; 
                                sig_ptr < mess_sigs+sizeof(mess_sigs); 
                                sig_ptr++)
@@ -318,14 +306,6 @@ PRIVATE void pm_init()
                /* Get kernel endpoint identifier. */
                rmp->mp_endpoint = ip->endpoint;
 
-               /* Get memory map for this process from the kernel. */
-               if ((s=get_mem_map(ip->proc_nr, rmp->mp_seg)) != OK)
-                       panic(__FILE__,"couldn't get process entry",s);
-               if (rmp->mp_seg[T].mem_len != 0) rmp->mp_flags |= SEPARATE;
-               minix_clicks += rmp->mp_seg[S].mem_phys + 
-                       rmp->mp_seg[S].mem_len - rmp->mp_seg[T].mem_phys;
-               patch_mem_chunks(mem_chunks, rmp->mp_seg);
-
                /* Tell FS about this system process. */
                mess.PR_SLOT = ip->proc_nr;
                mess.PR_PID = rmp->mp_pid;
@@ -336,17 +316,19 @@ PRIVATE void pm_init()
                /* Register proces with ds */
                s= ds_publish_u32(rmp->mp_name, rmp->mp_endpoint);
                if (s != OK)
-               {
-                       printf(
-                       "pm_init: unable to register '%s' with ds: %d\n",
-                               rmp->mp_name, s);
-               }
+                       failed++;
        }
   }
 
+  if(failed > 0)
+       printf("PM: failed to register %d/%d boot processes\n",
+               failed, NR_BOOT_PROCS);
+
   /* Override some details. INIT, PM, FS and RS are somewhat special. */
   mproc[PM_PROC_NR].mp_pid = PM_PID;           /* PM has magic pid */
+#if 0
   mproc[RS_PROC_NR].mp_parent = INIT_PROC_NR;  /* INIT is root */
+#endif
   sigfillset(&mproc[PM_PROC_NR].mp_ignore);    /* guard against signals */
 
   /* Tell FS that no more system processes follow and synchronize. */
@@ -354,30 +336,12 @@ PRIVATE void pm_init()
   if (sendrec(FS_PROC_NR, &mess) != OK || mess.m_type != OK)
        panic(__FILE__,"can't sync up with FS", NO_NUM);
 
-#if ENABLE_BOOTDEV
-  /* Possibly we must correct the memory chunks for the boot device. */
-  if (kinfo.bootdev_size > 0) {
-      mem_map[T].mem_phys = kinfo.bootdev_base >> CLICK_SHIFT;
-      mem_map[T].mem_len = 0;
-      mem_map[D].mem_len = (kinfo.bootdev_size+CLICK_SIZE-1) >> CLICK_SHIFT;
-      patch_mem_chunks(mem_chunks, mem_map);
-  }
-#endif /* ENABLE_BOOTDEV */
-
-  /* Withhold some memory from x86 VM */
-  do_x86_vm(mem_chunks);
-
-  /* Initialize tables to all physical memory and print memory information. */
-  printf("Physical memory:");
-  mem_init(mem_chunks, &free_clicks);
-  total_clicks = minix_clicks + free_clicks;
-  printf(" total %u KB,", click_to_round_k(total_clicks));
-  printf(" system %u KB,", click_to_round_k(minix_clicks));
-  printf(" free %u KB.\n", click_to_round_k(free_clicks));
 #if (CHIP == INTEL)
-  uts_val.machine[0] = 'i';
-  strcpy(uts_val.machine + 1, itoa(getprocessor()));
-#endif
+        uts_val.machine[0] = 'i';
+        strcpy(uts_val.machine + 1, itoa(getprocessor()));
+#endif  
+
+ if(f > 0) printf("PM: failed to register %d processes with DS.\n", f);
 }
 
 /*===========================================================================*
@@ -397,132 +361,24 @@ int queue;                               /* store mem chunks here */
   return nice_val;
 }
 
-/*===========================================================================*
- *                             get_mem_chunks                               *
- *===========================================================================*/
-PRIVATE void get_mem_chunks(mem_chunks)
-struct memory *mem_chunks;                     /* store mem chunks here */
-{
-/* Initialize the free memory list from the 'memory' boot variable.  Translate
- * the byte offsets and sizes in this list to clicks, properly truncated.
- */
-  long base, size, limit;
-  int i;
-  struct memory *memp;
-  
-  /* Obtain and parse memory from system environment. */
-  if(env_memory_parse(mem_chunks, NR_MEMS) != OK)
-       panic(__FILE__,"couldn't obtain memory chunks", NO_NUM);
-
-  /* Round physical memory to clicks. */
-  for (i = 0; i < NR_MEMS; i++) {
-       memp = &mem_chunks[i];          /* next mem chunk is stored here */
-       base = mem_chunks[i].base;
-       size = mem_chunks[i].size;
-       limit = base + size;    
-       base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
-       limit &= ~(long)(CLICK_SIZE-1);
-       if (limit <= base) {
-               memp->base = memp->size = 0;
-       } else {
-               memp->base = base >> CLICK_SHIFT;
-               memp->size = (limit - base) >> CLICK_SHIFT;
-       }
-  }
-}
-
-/*===========================================================================*
- *                             patch_mem_chunks                             *
- *===========================================================================*/
-PRIVATE void patch_mem_chunks(mem_chunks, map_ptr)
-struct memory *mem_chunks;                     /* store mem chunks here */
-struct mem_map *map_ptr;                       /* memory to remove */
-{
-/* Remove server memory from the free memory list. The boot monitor
- * promises to put processes at the start of memory chunks. The 
- * tasks all use same base address, so only the first task changes
- * the memory lists. The servers and init have their own memory
- * spaces and their memory will be removed from the list. 
- */
-  struct memory *memp;
-  for (memp = mem_chunks; memp < &mem_chunks[NR_MEMS]; memp++) {
-       if (memp->base == map_ptr[T].mem_phys) {
-               memp->base += map_ptr[T].mem_len + map_ptr[S].mem_vir;
-               memp->size -= map_ptr[T].mem_len + map_ptr[S].mem_vir;
-               break;
-       }
-  }
-  if (memp >= &mem_chunks[NR_MEMS])
-  {
-       panic(__FILE__,"patch_mem_chunks: can't find map in mem_chunks, start",
-               map_ptr[T].mem_phys);
-  }
-}
-
-#define PAGE_SIZE      4096
-#define PAGE_DIR_SIZE  (1024*PAGE_SIZE)        
-#define PAGE_TABLE_COVER (1024*PAGE_SIZE)
-/*=========================================================================*
- *                             do_x86_vm                                  *
- *=========================================================================*/
-PRIVATE void do_x86_vm(mem_chunks)
-struct memory mem_chunks[NR_MEMS];
+void checkme(char *str, int line)
 {
-       phys_bytes high, bytes;
-       phys_clicks clicks, base_click;
-       unsigned pages;
-       int i, r;
-
-       /* Compute the highest memory location */
-       high= 0;
-       for (i= 0; i<NR_MEMS; i++)
-       {
-               if (mem_chunks[i].size == 0)
-                       continue;
-               if (mem_chunks[i].base + mem_chunks[i].size > high)
-                       high= mem_chunks[i].base + mem_chunks[i].size;
-       }
-
-       high <<= CLICK_SHIFT;
-#if VERBOSE_VM
-       printf("do_x86_vm: found high 0x%x\n", high);
-#endif
-       
-       /* Rounding up */
-       high= (high-1+PAGE_DIR_SIZE) & ~(PAGE_DIR_SIZE-1);
-
-       /* The number of pages we need is one for the page directory, enough
-        * page tables to cover the memory, and one page for alignement.
-        */
-       pages= 1 + (high + PAGE_TABLE_COVER-1)/PAGE_TABLE_COVER + 1;
-       bytes= pages*PAGE_SIZE;
-       clicks= (bytes + CLICK_SIZE-1) >> CLICK_SHIFT;
-
-#if VERBOSE_VM
-       printf("do_x86_vm: need %d pages\n", pages);
-       printf("do_x86_vm: need %d bytes\n", bytes);
-       printf("do_x86_vm: need %d clicks\n", clicks);
-#endif
-
-       for (i= 0; i<NR_MEMS; i++)
-       {
-               if (mem_chunks[i].size <= clicks)
-                       continue;
-               break;
+       struct mproc *trmp;
+       int boned = 0;
+       int proc_nr;
+       for (proc_nr=0, trmp=mproc; proc_nr < NR_PROCS; proc_nr++, trmp++) {
+               if ((trmp->mp_flags & (REPLY | IN_USE | ZOMBIE)) ==
+                  (REPLY | IN_USE)) {
+                       int tp;
+                       if(pm_isokendpt(trmp->mp_endpoint, &tp) != OK) {
+                          printf("PM: %s:%d: reply %d to %s is bogus endpoint %d after call %d by %d\n",
+                               str, line, trmp->mp_reply.m_type,
+                               trmp->mp_name, trmp->mp_endpoint, call_nr, who_e);
+                          boned=1;
+                       }
+               }
+               if(boned) panic(__FILE__, "corrupt mp_endpoint?", NO_NUM);
        }
-       if (i >= NR_MEMS)
-               panic("PM", "not enough memory for VM page tables?", NO_NUM);
-       base_click= mem_chunks[i].base;
-       mem_chunks[i].base += clicks;
-       mem_chunks[i].size -= clicks;
-
-#if VERBOSE_VM
-       printf("do_x86_vm: using 0x%x clicks @ 0x%x\n", clicks, base_click);
-#endif
-       r= sys_vm_setbuf(base_click << CLICK_SHIFT, clicks << CLICK_SHIFT,
-               high);
-       if (r != 0)
-               printf("do_x86_vm: sys_vm_setbuf failed: %d\n", r);
 }
 
 /*=========================================================================*
@@ -625,8 +481,14 @@ PRIVATE void send_work()
                        /* Ask the kernel to deliver the signal */
                        r= sys_sigsend(rmp->mp_endpoint,
                                &rmp->mp_sigmsg);
-                       if (r != OK)
+                       if (r != OK) {
+#if 0
                                panic(__FILE__,"sys_sigsend failed",r);
+#else
+                               printf("PM: PM_UNPAUSE: sys_sigsend failed to %d: %d\n",
+                                       rmp->mp_endpoint, r);
+#endif
+                       }
 
                        break;
 
@@ -674,7 +536,9 @@ PRIVATE void send_work()
                case PM_DUMPCORE:
                        m.m_type= call;
                        m.PM_CORE_PROC= rmp->mp_endpoint;
+                       /* XXX
                        m.PM_CORE_SEGPTR= (char *)rmp->mp_seg;
+                       */
 
                        /* Mark the process as busy */
                        rmp->mp_fs_call= PM_BUSY;
@@ -715,9 +579,8 @@ PRIVATE void send_work()
 PRIVATE void handle_fs_reply(m_ptr)
 message *m_ptr;
 {
-       int r, proc_e, proc_n;
+       int r, proc_e, proc_n, s;
        struct mproc *rmp;
-       phys_clicks base, size;
 
        switch(m_ptr->m_type)
        {
@@ -746,30 +609,8 @@ message *m_ptr;
                }
 
                /* Release the memory occupied by the child. */
-               if (find_share(rmp, rmp->mp_ino, rmp->mp_dev,
-                       rmp->mp_ctime) == NULL) {
-                       /* No other process shares the text segment,
-                        * so free it.
-                        */
-                       free_mem(rmp->mp_seg[T].mem_phys,       
-                               rmp->mp_seg[T].mem_len);
-               }
-
-               base= rmp->mp_seg[D].mem_phys;
-               size= rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len -
-                       rmp->mp_seg[D].mem_vir;
-
-               if (rmp->mp_flags & HAS_DMA)
-               {
-                       /* Delay freeing the memory segmented until the
-                        * DMA buffers have been released.
-                        */
-                       release_dma(rmp->mp_endpoint, base, size);
-               }
-               else
-               {
-                       /* Free the data and stack segments. */
-                       free_mem(base, size);
+               if((s=vm_exit(rmp->mp_endpoint)) != OK) {
+                       panic(__FILE__, "vm_exit() failed", s);
                }
 
                if (m_ptr->m_type == PM_EXIT_REPLY_TR &&
@@ -883,30 +724,8 @@ message *m_ptr;
                }
 
                /* Release the memory occupied by the child. */
-               if (find_share(rmp, rmp->mp_ino, rmp->mp_dev,
-                       rmp->mp_ctime) == NULL) {
-                       /* No other process shares the text segment,
-                        * so free it.
-                        */
-                       free_mem(rmp->mp_seg[T].mem_phys,       
-                               rmp->mp_seg[T].mem_len);
-               }
-
-               base= rmp->mp_seg[D].mem_phys;
-               size= rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len -
-                       rmp->mp_seg[D].mem_vir;
-
-               if (rmp->mp_flags & HAS_DMA)
-               {
-                       /* Delay freeing the memory segmented until the
-                        * DMA buffers have been released.
-                        */
-                       release_dma(rmp->mp_endpoint, base, size);
-               }
-               else
-               {
-                       /* Free the data and stack segments. */
-                       free_mem(base, size);
+               if((s=vm_exit(rmp->mp_endpoint)) != OK) {
+                       panic(__FILE__, "vm_exit() failed", s);
                }
 
                /* Clean up if the parent has collected the exit
index d27d70270e1b1385b487ed97bc1328321076c1c0..5508d80142e150e45b0fea691e47fe406029003f 100644 (file)
@@ -24,6 +24,7 @@
 #include <minix/config.h>
 #include <minix/sysinfo.h>
 #include <minix/type.h>
+#include <minix/vm.h>
 #include <string.h>
 #include <archconst.h>
 #include <archtypes.h>
@@ -66,24 +67,13 @@ PUBLIC unsigned long calls_stats[NCALLS];
  *===========================================================================*/
 PUBLIC int do_allocmem()
 {
-  vir_clicks mem_clicks;
-  phys_clicks mem_base;
-
-  /* This call is dangerous. Memory will be lost of the requesting process
-   * forgets about it.
-   */
-  if (mp->mp_effuid != 0)
-  {
-       printf("PM: unauthorized call of do_allocmem by proc %d\n",
-               mp->mp_endpoint);
-       return EPERM;
-  }
-
-  mem_clicks = (m_in.memsize + CLICK_SIZE -1 ) >> CLICK_SHIFT;
-  mem_base = alloc_mem(mem_clicks);
-  if (mem_base == NO_MEM) return(ENOMEM);
-  mp->mp_reply.membase =  (phys_bytes) (mem_base << CLICK_SHIFT);
-  return(OK);
+       int r;
+       phys_bytes retmembase;
+       r = vm_allocmem(m_in.memsize, &retmembase);
+       if(r == OK)
+               mp->mp_reply.membase = retmembase;
+       printf("PM: do_allocmem: %d\n", r);
+       return r;
 }
 
 /*===========================================================================*
@@ -91,6 +81,9 @@ PUBLIC int do_allocmem()
  *===========================================================================*/
 PUBLIC int do_freemem()
 {
+#if 1
+       return ENOSYS;
+#else
   vir_clicks mem_clicks;
   phys_clicks mem_base;
 
@@ -108,6 +101,7 @@ PUBLIC int do_freemem()
   mem_base = (m_in.membase + CLICK_SIZE -1 ) >> CLICK_SHIFT;
   free_mem(mem_base, mem_clicks);
   return(OK);
+#endif
 }
 
 /*===========================================================================*
@@ -215,9 +209,7 @@ PUBLIC int do_getsysinfo()
   struct loadinfo loadinfo;
   static struct proc proctab[NR_PROCS+NR_TASKS];
   size_t len;
-  static struct pm_mem_info pmi;
   int s, r;
-  size_t holesize;
 
   /* This call leaks important information (the contents of registers).
    * harmless data (such as the load should get their own calls)
@@ -251,14 +243,6 @@ PUBLIC int do_getsysinfo()
        src_addr = (vir_bytes) proctab;
        len = sizeof(proctab);
         break;
-  case SI_MEM_ALLOC:
-       holesize = sizeof(pmi.pmi_holes);
-       if((r=mem_holes_copy(pmi.pmi_holes, &holesize,
-          &pmi.pmi_hi_watermark)) != OK)
-               return r;
-       src_addr = (vir_bytes) &pmi;
-       len = sizeof(pmi);
-       break;
   case SI_LOADINFO:                    /* loadinfo is obtained via PM */
         sys_getloadinfo(&loadinfo);
         src_addr = (vir_bytes) &loadinfo;
@@ -329,12 +313,18 @@ PUBLIC int do_getprocnr()
        return EPERM;
   }
 
-  printf("PM: do_getprocnr call from endpoint %d\n", mp->mp_endpoint);
+#if 0
+  printf("PM: do_getprocnr(%d) call from endpoint %d, %s\n",
+       m_in.pid, mp->mp_endpoint, mp->mp_name);
+#endif
 
   if (m_in.pid >= 0) {                 /* lookup process by pid */
        for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
                if ((rmp->mp_flags & IN_USE) && (rmp->mp_pid==m_in.pid)) {
                        mp->mp_reply.endpt = rmp->mp_endpoint;
+#if 0
+                       printf("PM: pid result: %d\n", rmp->mp_endpoint);
+#endif
                        return(OK);
                } 
        }
@@ -349,11 +339,17 @@ PUBLIC int do_getprocnr()
                if (((rmp->mp_flags & (IN_USE | ZOMBIE)) == IN_USE) && 
                        strncmp(rmp->mp_name, search_key, key_len)==0) {
                        mp->mp_reply.endpt = rmp->mp_endpoint;
+                       printf("PM: name %s result: %d\n", search_key, 
+                                       rmp->mp_endpoint);
                        return(OK);
                } 
        }
+       printf("PM: name %s result: ESRCH\n", search_key);
        return(ESRCH);                  
   } else {                     /* return own/parent process number */
+#if 0
+       printf("PM: endpt result: %d\n", mp->mp_reply.endpt);
+#endif
        mp->mp_reply.endpt = who_e;
        mp->mp_reply.pendpt = mproc[mp->mp_parent].mp_endpoint;
   }
@@ -526,7 +522,7 @@ PUBLIC int do_svrctl()
                        return s;
           if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.val,
             SELF, (vir_bytes) local_param_overrides[local_params].value,
-              sysgetenv.keylen)) != OK)
+              sysgetenv.vallen)) != OK)
                        return s;
             local_param_overrides[local_params].name[sysgetenv.keylen] = '\0';
             local_param_overrides[local_params].value[sysgetenv.vallen] = '\0';
@@ -576,24 +572,6 @@ PUBLIC int do_svrctl()
       return OK;
   }
 
-#if ENABLE_SWAP
-  case MMSWAPON: {
-       struct mmswapon swapon;
-
-       if (mp->mp_effuid != SUPER_USER) return(EPERM);
-
-       if (sys_datacopy(who_e, (phys_bytes) ptr,
-               PM_PROC_NR, (phys_bytes) &swapon,
-               (phys_bytes) sizeof(swapon)) != OK) return(EFAULT);
-
-       return(swap_on(swapon.file, swapon.offset, swapon.size)); }
-
-  case MMSWAPOFF: {
-       if (mp->mp_effuid != SUPER_USER) return(EPERM);
-
-       return(swap_off()); }
-#endif /* SWAP */
-
   default:
        return(EINVAL);
   }
@@ -607,8 +585,13 @@ extern char *_brksize;
 PUBLIC int brk(brk_addr)
 char *brk_addr;
 {
+       int r;
 /* PM wants to call brk() itself. */
-       if(real_brk(&mproc[PM_PROC_NR], (vir_bytes) brk_addr) != OK) {
+       if((r=vm_brk(PM_PROC_NR, brk_addr)) != OK) {
+#if 0
+               printf("PM: own brk(%p) failed: vm_brk() returned %d\n",
+                       brk_addr, r);
+#endif
                return -1;
        }
        _brksize = brk_addr;
index 624e6e6f15d0650366760f553c1b10aee7b82c37..d6110bf6c418c17fddc4d1a08ba8d905cb296187 100644 (file)
@@ -5,9 +5,9 @@
  * of corresponding slots referring to the same process in all three.
  */
 #include <timers.h>
+#include <signal.h>
 
 EXTERN struct mproc {
-  struct mem_map mp_seg[NR_LOCAL_SEGS]; /* points to text, data, stack */
   char mp_exitstatus;          /* storage for status when process exits */
   char mp_sigstatus;           /* storage for signal # for killed procs */
   pid_t mp_pid;                        /* process id */
@@ -26,11 +26,6 @@ EXTERN struct mproc {
   gid_t mp_realgid;            /* process' real gid */
   gid_t mp_effgid;             /* process' effective gid */
 
-  /* File identification for sharing. */
-  ino_t mp_ino;                        /* inode number of file */
-  dev_t mp_dev;                        /* device number of file system */
-  time_t mp_ctime;             /* inode changed time */
-
   /* Signal handling information. */
   sigset_t mp_ignore;          /* 1 means ignore the signal, 0 means don't */
   sigset_t mp_catch;           /* 1 means catch the signal, 0 means don't */
@@ -73,14 +68,10 @@ EXTERN struct mproc {
 #define ZOMBIE          0x004  /* set by EXIT, cleared by WAIT */
 #define PAUSED          0x008  /* set by PAUSE system call */
 #define ALARM_ON        0x010  /* set when SIGALRM timer started */
-#define SEPARATE       0x020   /* set if file is separate I & D space */
 #define        TRACED          0x040   /* set if process is to be traced */
 #define STOPPED                0x080   /* set if process stopped for tracing */
 #define SIGSUSPENDED   0x100   /* set by SIGSUSPEND system call */
 #define REPLY          0x200   /* set if a reply message is pending */
-#define ONSWAP         0x400   /* set if data segment is swapped out */
-#define SWAPIN         0x800   /* set if on the "swap this in" queue */
-#define DONT_SWAP      0x1000   /* never swap out this process */
 #define PRIV_PROC      0x2000   /* system process, special privileges */
 #define PM_SIG_PENDING 0x4000  /* process got a signal while waiting for FS */
 #define PARTIAL_EXEC   0x8000  /* Process got a new map but no content */
index 5853039914127188b2b235bb9426c87b3f27a71a..b63d48b508cbb2b04e42cd7092ff261529edd622 100644 (file)
@@ -97,13 +97,13 @@ int info_size;
 
   /* Check if supplied pointers point into user process. */
   if ((r = sys_umap(who_e, D, (vir_bytes) m_in.PROF_CTL_PTR,
-                                                info_size, &p)) != OK) {
+                                                1, &p)) != OK) {
        printf("PM: PROFILE: umap failed for process %d\n", who_e);
        return r;                                    
   }  
 
   if ((r =sys_umap(who_e, D, (vir_bytes) m_in.PROF_MEM_PTR,
-                                        m_in.PROF_MEM_SIZE, &p)) != OK) {
+                                        1, &p)) != OK) {
        printf("PM: PROFILE: umap failed for process %d\n", who_e);
        return r;                                    
   }  
index ac8919efb695e658fff9f03188d57cb1b1557d69..ef6e6045e3635dc9980d79459be9f732634c8bff 100644 (file)
@@ -7,41 +7,20 @@ struct memory;
 
 #include <timers.h>
 
-/* alloc.c */
-_PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks)                        );
-_PROTOTYPE( void free_mem, (phys_clicks base, phys_clicks clicks)      );
-_PROTOTYPE( void mem_init, (struct memory *chunks, phys_clicks *free)  );
-_PROTOTYPE( int do_adddma, (void)                                      );
-_PROTOTYPE( int do_deldma, (void)                                      );
-_PROTOTYPE( int do_getdma, (void)                                      );
-_PROTOTYPE( void release_dma, (endpoint_t proc_e, phys_clicks base,
-                                               phys_clicks size)       );
-#if ENABLE_SWAP
-_PROTOTYPE( int swap_on, (char *file, u32_t offset, u32_t size)        );
-_PROTOTYPE( int swap_off, (void)                                       );
-_PROTOTYPE( void swap_in, (void)                                       );
-_PROTOTYPE( void swap_inqueue, (struct mproc *rmp)                     );
-#else /* !SWAP */
-#define swap_in()                      ((void)0)
-#define swap_inqueue(rmp)              ((void)0)
-#endif /* !SWAP */
-_PROTOTYPE(int mem_holes_copy, (struct hole *, size_t *, u32_t *)      );
-
-/* asynsend.c */
-_PROTOTYPE( int asynsend, (endpoint_t dst, message *mp)                        );
-
 /* break.c */
-_PROTOTYPE( int adjust, (struct mproc *rmp,
-                       vir_clicks data_clicks, vir_bytes sp)           );
 _PROTOTYPE( int do_brk, (void)                                         );
-_PROTOTYPE( int real_brk, (struct mproc *pr, vir_bytes v)              );
-_PROTOTYPE( int size_ok, (int file_type, vir_clicks tc, vir_clicks dc,
-                       vir_clicks sc, vir_clicks dvir, vir_clicks s_vir) );
 
 /* devio.c */
 _PROTOTYPE( int do_dev_io, (void) );
 _PROTOTYPE( int do_dev_io, (void) );
 
+/* dma.c */
+_PROTOTYPE( int do_adddma, (void)                                      );
+_PROTOTYPE( int do_deldma, (void)                                      );
+_PROTOTYPE( int do_getdma, (void)                                      );
+_PROTOTYPE( void release_dma, (endpoint_t proc_e, phys_clicks base,
+                                               phys_clicks size)       );
+
 /* dmp.c */
 _PROTOTYPE( int do_fkey_pressed, (void)                                                );
 
@@ -50,8 +29,6 @@ _PROTOTYPE( int do_exec, (void)                                               );
 _PROTOTYPE( int exec_newmem, (void)                                    );
 _PROTOTYPE( int do_execrestart, (void)                                 );
 _PROTOTYPE( void exec_restart, (struct mproc *rmp, int result)         );
-_PROTOTYPE( struct mproc *find_share, (struct mproc *mp_ign, Ino_t ino,
-                       Dev_t dev, time_t ctime)                        );
 
 /* forkexit.c */
 _PROTOTYPE( int do_fork, (void)                                                );
@@ -131,8 +108,6 @@ _PROTOTYPE( void stop_proc, (struct mproc *rmp, int sig_nr)         );
 _PROTOTYPE( pid_t get_free_pid, (void)                                 );
 _PROTOTYPE( int no_sys, (void)                                         );
 _PROTOTYPE( void panic, (char *who, char *mess, int num)               );
-_PROTOTYPE( int get_stack_ptr, (int proc_nr, vir_bytes *sp)            );
-_PROTOTYPE( int get_mem_map, (int proc_nr, struct mem_map *mem_map)    );
 _PROTOTYPE( char *find_param, (const char *key));
 _PROTOTYPE( int proc_from_pid, (pid_t p));
 _PROTOTYPE( int pm_isokendpt, (int ep, int *proc));
index def9e093ded6981833ba5dc70c53e9d6469c079d..db3f288ad703c8ff2e4718d67bd5fed4ccf5f85b 100644 (file)
@@ -26,6 +26,7 @@
 #include <minix/callnr.h>
 #include <minix/endpoint.h>
 #include <minix/com.h>
+#include <minix/vm.h>
 #include <signal.h>
 #include <sys/resource.h>
 #include <sys/sigcontext.h>
@@ -251,11 +252,15 @@ sigset_t sig_map;
   int i, proc_nr;
   pid_t proc_id, id;
 
-  if(pm_isokendpt(proc_nr_e, &proc_nr) != OK || proc_nr < 0)
+  if(pm_isokendpt(proc_nr_e, &proc_nr) != OK || proc_nr < 0) {
+       printf("PM: handle_ksig: %d?? not ok\n", proc_nr_e);
        return;
+  }
   rmp = &mproc[proc_nr];
-  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE)
+  if ((rmp->mp_flags & (IN_USE | ZOMBIE)) != IN_USE) {
+       printf("PM: handle_ksig: %d?? zombie / not in use\n", proc_nr_e);
        return;
+}
   proc_id = rmp->mp_pid;
   mp = &mproc[0];                      /* pretend signals are from PM */
   mp->mp_procgrp = rmp->mp_procgrp;    /* get process group right */
@@ -269,6 +274,10 @@ sigset_t sig_map;
    */
   for (i = 1; i <= _NSIG; i++) {
        if (!sigismember(&sig_map, i)) continue;
+#if 0
+       printf("PM: sig %d for %d from kernel\n", 
+               i, proc_nr_e);
+#endif
        switch (i) {
            case SIGINT:
            case SIGQUIT:
@@ -409,7 +418,7 @@ int signo;                  /* signal to send to process (1 to _NSIG) */
  * If there is insufficient stack space, kill the process.
  */
 
-  vir_bytes new_sp;
+  vir_bytes cur_sp;
   int s;
   int slot;
   int sigflags;
@@ -444,18 +453,8 @@ int signo;                 /* signal to send to process (1 to _NSIG) */
        sigaddset(&rmp->mp_sigpending, signo);
        return;
   }
-#if ENABLE_SWAP
-  if (rmp->mp_flags & ONSWAP) {
-       /* Process is swapped out, leave signal pending. */
-       sigaddset(&rmp->mp_sigpending, signo);
-       swap_inqueue(rmp);
-       return;
-  }
-#endif
   sigflags = rmp->mp_sigact[signo].sa_flags;
   if (sigismember(&rmp->mp_catch, signo)) {
-       /* Stop process from running before we do stack calculations. */
-       sys_nice(rmp->mp_endpoint, PRIO_STOP);
        if (rmp->mp_flags & SIGSUSPENDED)
                rmp->mp_sigmsg.sm_mask = rmp->mp_sigmask2;
        else
@@ -464,18 +463,8 @@ int signo;                 /* signal to send to process (1 to _NSIG) */
        rmp->mp_sigmsg.sm_sighandler =
                (vir_bytes) rmp->mp_sigact[signo].sa_handler;
        rmp->mp_sigmsg.sm_sigreturn = rmp->mp_sigreturn;
-       if ((s=get_stack_ptr(rmp->mp_endpoint, &new_sp)) != OK)
-               panic(__FILE__,"couldn't get new stack pointer (for sig)",s);
-       rmp->mp_sigmsg.sm_stkptr = new_sp;
-
-       /* Make room for the sigcontext and sigframe struct. */
-       new_sp -= sizeof(struct sigcontext)
-                                + 3 * sizeof(char *) + 2 * sizeof(int);
-
-       if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)
-               goto doterminate;
-
        rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;
+
        if (sigflags & SA_NODEFER)
                sigdelset(&rmp->mp_sigmask, signo);
        else
@@ -487,6 +476,13 @@ int signo;                 /* signal to send to process (1 to _NSIG) */
        }
        sigdelset(&rmp->mp_sigpending, signo);
 
+       /* Stop process from running before we fiddle with its stack. */
+       sys_nice(rmp->mp_endpoint, PRIO_STOP);
+       if(vm_push_sig(rmp->mp_endpoint, &cur_sp) != OK)
+               goto doterminate;
+
+        rmp->mp_sigmsg.sm_stkptr = cur_sp;
+
        /* Check to see if process is hanging on a PAUSE, WAIT or SIGSUSPEND
         * call.
         */
@@ -519,22 +515,24 @@ int signo;                        /* signal to send to process (1 to _NSIG) */
 
 doterminate:
   /* Signal should not or cannot be caught.  Take default action. */
-  if (sigismember(&ign_sset, signo)) return;
+  if (sigismember(&ign_sset, signo)) {
+       return;
+}
+
+  /* This process will exit, with or without dumping core. 
+   * Announce this fact to VM.
+   */
+  if((s=vm_willexit(rmp->mp_endpoint)) != OK) {
+       panic(__FILE__,"sig_proc: vm_willexit failed", s);
+  }
 
   rmp->mp_sigstatus = (char) signo;
   if (sigismember(&core_sset, signo) && slot != FS_PROC_NR) {
-#if ENABLE_SWAP
-       if (rmp->mp_flags & ONSWAP) {
-               /* Process is swapped out, leave signal pending. */
-               sigaddset(&rmp->mp_sigpending, signo);
-               swap_inqueue(rmp);
-               return;
-       }
-#endif
-
+       printf("PM: signal %d for %d / %s\n", signo, rmp->mp_pid, rmp->mp_name);
        s= dump_core(rmp);
-       if (s == SUSPEND)
+       if (s == SUSPEND) {
                return;
+       }
 
        /* Not dumping core, just call exit */
   }
@@ -689,13 +687,13 @@ register struct mproc *rmp;       /* whose core is to be dumped */
 
   int r, proc_nr, proc_nr_e, parent_waiting;
   pid_t procgrp;
+#if 0
   vir_bytes current_sp;
+#endif
   struct mproc *p_mp;
   clock_t user_time, sys_time;
 
-#if 0
   printf("dumpcore for %d / %s\n", rmp->mp_pid, rmp->mp_name);
-#endif
 
   /* Do not create core files for set uid execution */
   if (rmp->mp_realuid != rmp->mp_effuid) return OK;
@@ -706,9 +704,11 @@ register struct mproc *rmp;        /* whose core is to be dumped */
    * the adjust() for sending a signal to fail due to safety checking.  
    * Maybe make SAFETY_BYTES a parameter.
    */
+#if 0
   if ((r= get_stack_ptr(rmp->mp_endpoint, &current_sp)) != OK)
        panic(__FILE__,"couldn't get new stack pointer (for core)", r);
   adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
+#endif
 
   /* Tell FS about the exiting process. */
   if (rmp->mp_fs_call != PM_IDLE)
@@ -732,7 +732,7 @@ register struct mproc *rmp; /* whose core is to be dumped */
 
   /* Do accounting: fetch usage times and accumulate at parent. */
   if((r=sys_times(proc_nr_e, &user_time, &sys_time, NULL)) != OK)
-       panic(__FILE__,"pm_exit: sys_times failed", r);
+       panic(__FILE__,"dump_core: sys_times failed", r);
 
   p_mp = &mproc[rmp->mp_parent];                       /* process' parent */
   p_mp->mp_child_utime += user_time + rmp->mp_child_utime; /* add user time */
@@ -752,7 +752,7 @@ register struct mproc *rmp; /* whose core is to be dumped */
        {
                /* destroy system processes without waiting for FS */
                if((r= sys_exit(rmp->mp_endpoint)) != OK)
-                       panic(__FILE__, "pm_exit: sys_exit failed", r);
+                       panic(__FILE__, "dump_core: sys_exit failed", r);
 
                /* Just send a SIGCHLD. Dealing with waidpid is too complicated
                 * here.
index 2618097354ea182328aa65b3fa3cc1b002398218..943169602f787e8065f9020ddf16f524ad2a1393 100644 (file)
@@ -69,6 +69,7 @@ PUBLIC int do_trace()
        if ((child=find_proc(m_in.pid))==NIL_MPROC)
                return(ESRCH);
 
+#if 0
        /* Should check for shared text */
 
        /* Make sure the text segment is not used as a source for shared
@@ -77,6 +78,7 @@ PUBLIC int do_trace()
        child->mp_ino= 0;
        child->mp_dev= 0;
        child->mp_ctime= 0;
+#endif
 
        r= sys_trace(m_in.request,child->mp_endpoint,m_in.taddr,&m_in.data);
        if (r != OK) return(r);
index 23adbdcfe718cf081d63578496b7e04e1d5379f2..405c7fdc86b93972042fe1afd5736373055f01dc 100644 (file)
@@ -6,7 +6,6 @@
  *   allowed:          see if an access is permitted
  *   no_sys:           called for invalid system call numbers
  *   panic:            PM has run aground of a fatal error 
- *   get_mem_map:      get memory map of given process
  *   get_stack_ptr:    get stack pointer of given process      
  *   proc_from_pid:    return process pointer from pid number
  */
@@ -105,38 +104,6 @@ const char *name;
   return(NULL);
 }
 
-/*===========================================================================*
- *                             get_mem_map                                  *
- *===========================================================================*/
-PUBLIC int get_mem_map(proc_nr, mem_map)
-int proc_nr;                                   /* process to get map of */
-struct mem_map *mem_map;                       /* put memory map here */
-{
-  struct proc p;
-  int s;
-
-  if ((s=sys_getproc(&p, proc_nr)) != OK)
-       return(s);
-  memcpy(mem_map, p.p_memmap, sizeof(p.p_memmap));
-  return(OK);
-}
-
-/*===========================================================================*
- *                             get_stack_ptr                                *
- *===========================================================================*/
-PUBLIC int get_stack_ptr(proc_nr_e, sp)
-int proc_nr_e;                                 /* process to get sp of */
-vir_bytes *sp;                                 /* put stack pointer here */
-{
-  struct proc p;
-  int s;
-
-  if ((s=sys_getproc(&p, proc_nr_e)) != OK)
-       return(s);
-  *sp = p.p_reg.sp;
-  return(OK);
-}
-
 /*===========================================================================*
  *                             proc_from_pid                                *
  *===========================================================================*/
index 94f466551e90e057c1e369eacf9716c22ebb20d0..5bccbacc4cbe65ad5a8d7bcfc81059fdb409ccae 100644 (file)
@@ -16,7 +16,7 @@ CC =  exec cc
 CPPFLAGS = -I../../kernel/arch/$(ARCH)/include
 CFLAGS = -I$i $(CPROFILE) $(CPPFLAGS)
 LDFLAGS = -i
-LIBS = -lsys -lsysutil 
+LIBS = -lsys 
 
 UTIL_OBJ = service.o
 OBJ = exec.o main.o manager.o 
index 9f02d96ec37c45a76276a7e72e568f0de0cab498..d7ce232569e2adb48796f81a238cab97a0c5a05a 100644 (file)
@@ -171,7 +171,11 @@ static void do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
        patch_ptr(frame, vsp);
        r = sys_datacopy(SELF, (vir_bytes) frame,
                proc_e, (vir_bytes) vsp, (phys_bytes)frame_len);
-       if (r != OK) panic(__FILE__,"pm_exec stack copy err on", proc_e);
+       if (r != OK) {
+               printf("RS: stack_top is 0x%lx; tried to copy to 0x%lx in %d\n",
+                       stack_top, vsp);
+               panic("RS", "do_exec: stack copy err on", proc_e);
+       }
 
        off = hdrlen;
 
@@ -261,8 +265,8 @@ int *allow_setuidp;
        *load_textp= !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT);
        *allow_setuidp= !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID);
 #if 0
-       printf("exec_newmem: stack_top = 0x%x\n", *stack_topp);
-       printf("exec_newmem: load_text = %d\n", *load_textp);
+       printf("RS: exec_newmem: stack_top = 0x%x\n", *stack_topp);
+       printf("RS: exec_newmem: load_text = %d\n", *load_textp);
 #endif
        return m.m_type;
 }
index 0b749573419136e313071fa8b969af3f895a9bae..fb6b03b85112c86b630df4822c621e36746167fa 100644 (file)
@@ -309,10 +309,12 @@ message *m_ptr;                                   /* request message pointer */
        rp->r_priv.s_io_tab[i].ior_base= rs_start.rss_io[i].base;
        rp->r_priv.s_io_tab[i].ior_limit=
                rs_start.rss_io[i].base+rs_start.rss_io[i].len-1;
+#if 0
        if(rs_verbose)
           printf("RS: do_start: I/O [%x..%x]\n",
                rp->r_priv.s_io_tab[i].ior_base,
                rp->r_priv.s_io_tab[i].ior_limit);
+#endif
   }
 
   if (rs_start.rss_nr_pci_id > MAX_NR_PCI_ID)
@@ -532,12 +534,18 @@ PUBLIC void do_exit(message *m_ptr)
   while ( (exit_pid = waitpid(-1, &exit_status, WNOHANG)) != 0 ) {
 
     if(rs_verbose) {
+#if 0
       printf("RS: pid %d, ", exit_pid); 
+#endif
       if (WIFSIGNALED(exit_status)) {
+#if 0
           printf("killed, signal number %d\n", WTERMSIG(exit_status));
+#endif
       } 
       else if (WIFEXITED(exit_status)) {
+#if 0
           printf("normal exit, status %d\n", WEXITSTATUS(exit_status));
+#endif
       }
     }
 
@@ -649,7 +657,7 @@ rp->r_restarts= 0;
              break;
          }
       }
-  }
+  } 
 }
 
 /*===========================================================================*
@@ -748,11 +756,15 @@ endpoint_t *endpoint;
 
   use_copy= (rp->r_exec != NULL);
 
+
   /* Now fork and branch for parent and child process (and check for error). */
-  if (use_copy)
+  if (use_copy) {
+  if(rs_verbose) printf("RS: fork_nb..\n");
        child_pid= fork_nb();
-  else
+  } else {
+  if(rs_verbose) printf("RS: fork regular..\n");
        child_pid = fork();
+  }
 
   switch(child_pid) {                                  /* see fork(2) */
   case -1:                                             /* fork failed */
@@ -783,7 +795,13 @@ endpoint_t *endpoint;
       exit(1);                                         /* terminate child */
 
   default:                                             /* parent process */
+#if 0
+  if(rs_verbose) printf("RS: parent forked, pid %d..\n", child_pid);
+#endif
       child_proc_nr_e = getnprocnr(child_pid);         /* get child slot */ 
+#if 0
+  if(rs_verbose) printf("RS: forked into %d..\n", child_proc_nr_e);
+#endif
       break;                                           /* continue below */
   }
 
@@ -817,7 +835,10 @@ endpoint_t *endpoint;
 
   s= ds_publish_u32(rp->r_label, child_proc_nr_e);
   if (s != OK)
-       printf("start_service: ds_publish_u32 failed: %d\n", s);
+       printf("RS: start_service: ds_publish_u32 failed: %d\n", s);
+ else if(rs_verbose)
+       printf("RS: start_service: ds_publish_u32 done: %s -> %d\n", 
+               rp->r_label, child_proc_nr_e);
 
   if (rp->r_dev_nr > 0) {                              /* set driver map */
       if ((s=mapdriver5(rp->r_label, strlen(rp->r_label),
@@ -1054,8 +1075,10 @@ struct priv *privp;
                        if (!(rp->r_call_mask[src_word] & mask))
                                continue;
                        call_nr= src_word*src_bits_per_word+src_bit;
+#if 0
                        if(rs_verbose)
                          printf("RS: init_privs: system call %d\n", call_nr);
+#endif
                        dst_word= call_nr / dst_bits_per_word;
                        mask= (1UL << (call_nr % dst_bits_per_word));
                        if (dst_word >= CALL_MASK_SIZE)
index 71d355490a9ef40751e2a1d1cc97b54879648f73..0a173f9852a2f98b117b429285698b21ea80755d 100644 (file)
@@ -680,8 +680,8 @@ struct
        { "VSAFECOPY",          SYS_VSAFECOPY },
        { "SETGRANT",           SYS_SETGRANT },
        { "READBIOS",           SYS_READBIOS },
-       { "VM_MAP",             SYS_VM_MAP },
        { "MAPDMA",             SYS_MAPDMA },
+       { "VMCTL",              SYS_VMCTL },
        { NULL,         0 }
 };
 
@@ -725,7 +725,9 @@ PRIVATE void do_ipc(config_t *cpe)
                strcat(list, " ");
                strcat(list, cpe->word);
        }
+#if 0
        printf("do_ipc: got list '%s'\n", list);
+#endif
 
        if (req_ipc)
                fatal("do_ipc: req_ipc is set");
index f6957645839f21ccb010677df51c57ebb9c01d72..ebee1bd80be2a12a2e305669645f42a1bad38e1d 100644 (file)
@@ -11,13 +11,13 @@ h = $i/minix
 CC =   exec cc
 CFLAGS = -I$i $(EXTRA_OPTS) $(CPROFILE)
 LDFLAGS = -i
-LIBS = -lsysutil -lsys -ltimers
+LIBS = -lsys -ltimers
 
 OBJ =  main.o open.o read.o write.o pipe.o dmap.o \
        path.o device.o mount.o link.o exec.o \
        filedes.o stadir.o protect.o time.o \
        lock.o misc.o utility.o select.o timers.o table.o \
-       vnode.o vmnt.o request.o kputc.o
+       vnode.o vmnt.o request.o kputc.o mmap.o
 
 # build local binary 
 install all build:     $(SERVER)
diff --git a/servers/vfs/buf.h b/servers/vfs/buf.h
deleted file mode 100644 (file)
index a175136..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Buffer (block) cache.  To acquire a block, a routine calls get_block(),
- * telling which block it wants.  The block is then regarded as "in use"
- * and has its 'b_count' field incremented.  All the blocks that are not
- * in use are chained together in an LRU list, with 'front' pointing
- * to the least recently used block, and 'rear' to the most recently used
- * block.  A reverse chain, using the field b_prev is also maintained.
- * Usage for LRU is measured by the time the put_block() is done.  The second
- * parameter to put_block() can violate the LRU order and put a block on the
- * front of the list, if it will probably not be needed soon.  If a block
- * is modified, the modifying routine must set b_dirt to DIRTY, so the block
- * will eventually be rewritten to the disk.
- */
-
-#include <sys/dir.h>                   /* need struct direct */
-#include <dirent.h>
-
-EXTERN struct buf {
-  /* Data portion of the buffer. */
-  union {
-    char b__data[_MAX_BLOCK_SIZE];                  /* ordinary user data */
-/* directory block */
-    struct direct b__dir[NR_DIR_ENTRIES(_MAX_BLOCK_SIZE)];    
-/* V1 indirect block */
-    zone1_t b__v1_ind[V1_INDIRECTS];        
-/* V2 indirect block */
-    zone_t  b__v2_ind[V2_INDIRECTS(_MAX_BLOCK_SIZE)];       
-/* V1 inode block */
-    d1_inode b__v1_ino[V1_INODES_PER_BLOCK]; 
-/* V2 inode block */
-    d2_inode b__v2_ino[V2_INODES_PER_BLOCK(_MAX_BLOCK_SIZE)]; 
-/* bit map block */
-    bitchunk_t b__bitmap[FS_BITMAP_CHUNKS(_MAX_BLOCK_SIZE)];  
-  } b;
-
-  /* Header portion of the buffer. */
-  struct buf *b_next;          /* used to link all free bufs in a chain */
-  struct buf *b_prev;          /* used to link all free bufs the other way */
-  struct buf *b_hash;          /* used to link bufs on hash chains */
-  block_t b_blocknr;           /* block number of its (minor) device */
-  dev_t b_dev;                 /* major | minor device where block resides */
-  char b_dirt;                 /* CLEAN or DIRTY */
-  char b_count;                        /* number of users of this buffer */
-} buf[NR_BUFS];
-
-/* A block is free if b_dev == NO_DEV. */
-
-#define NIL_BUF ((struct buf *) 0)     /* indicates absence of a buffer */
-
-/* These defs make it possible to use to bp->b_data instead of bp->b.b__data */
-#define b_data   b.b__data
-#define b_dir    b.b__dir
-#define b_v1_ind b.b__v1_ind
-#define b_v2_ind b.b__v2_ind
-#define b_v1_ino b.b__v1_ino
-#define b_v2_ino b.b__v2_ino
-#define b_bitmap b.b__bitmap
-
-EXTERN struct buf *buf_hash[NR_BUF_HASH];      /* the buffer hash table */
-
-EXTERN struct buf *front;      /* points to least recently used free block */
-EXTERN struct buf *rear;       /* points to most recently used free block */
-EXTERN int bufs_in_use;                /* # bufs currently in use (not on free list)*/
-
-/* When a block is released, the type of usage is passed to put_block(). */
-#define WRITE_IMMED   0100 /* block should be written to disk now */
-#define ONE_SHOT      0200 /* set if block not likely to be needed soon */
-
-#define INODE_BLOCK        0                            /* inode block */
-#define DIRECTORY_BLOCK    1                            /* directory block */
-#define INDIRECT_BLOCK     2                            /* pointer block */
-#define MAP_BLOCK          3                            /* bit map */
-#define FULL_DATA_BLOCK    5                            /* data, fully used */
-#define PARTIAL_DATA_BLOCK 6                            /* data, partly used*/
-
-#define HASH_MASK (NR_BUF_HASH - 1)    /* mask for hashing block numbers */
index 58ceabbe517969b1a200edeea48598858c253ed3..14719ec81b9dad41e4f0a6367fc5e4e0176f5ceb 100644 (file)
@@ -633,6 +633,10 @@ message *mess_ptr;         /* pointer to message for task */
 
   int r, proc_e;
 
+  if(task_nr == SYSTEM) {
+       printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type);
+  }
+
   proc_e = mess_ptr->IO_ENDPT;
 
   r = sendrec(task_nr, mess_ptr);
@@ -1117,6 +1121,7 @@ PUBLIC void reopen_reply()
        restart_reopen(maj);
 }
 
+#if 0
 #define ASYN_NR        100
 PRIVATE asynmsg_t msgtable[ASYN_NR];
 PRIVATE int first_slot= 0, next_slot= 0;
@@ -1203,4 +1208,5 @@ message *mp;
        /* Tell the kernel to rescan the table */
        return senda(msgtable+first_slot, next_slot-first_slot);
 }
+#endif
 
index f86c10129c0e8044a658cc763467f86c87cc1766..e55da6bbde06cb97eb5970c253609aee76f207fe 100644 (file)
@@ -221,7 +221,10 @@ printf("return at %s, %d\n", __FILE__, __LINE__);
     patch_ptr(mbuf, vsp);
     r = sys_datacopy(SELF, (vir_bytes) mbuf,
             proc_e, (vir_bytes) vsp, (phys_bytes)frame_len);
-    if (r != OK) panic(__FILE__,"pm_exec stack copy err on", proc_e);
+    if (r != OK) {
+       printf("vfs: datacopy returns %d trying to copy to %p\n", r, vsp);
+       panic(__FILE__,"pm_exec stack copy err on", proc_e);
+    }
 
     off = hdrlen;
 
@@ -255,7 +258,6 @@ printf("return at %s, %d\n", __FILE__, __LINE__);
     /* Check if this is a driver that can now be useful. */
     dmap_endpt_up(rfp->fp_endpoint);
 
-/*printf("VFSpm_exec: %s OK\n", user_fullpath);*/
     return OK;
 }
 
@@ -432,7 +434,7 @@ vir_bytes *stk_bytes;               /* size of initial stack */
   unsigned int cum_io_incr;
   char buf[_MAX_BLOCK_SIZE];
 
-  /* Make user_path the new argv[0]. */
+  /* Make user_fullpath the new argv[0]. */
   if (!insert_arg(stack, stk_bytes, user_fullpath, REPLACE)) return(ENOMEM);
 
   pos = 0;     /* Read from the start of the file */
@@ -451,7 +453,7 @@ vir_bytes *stk_bytes;               /* size of initial stack */
   n -= 2;
   if (n > PATH_MAX) n = PATH_MAX;
 
-  /* Use the user_path variable for temporary storage */
+  /* Use the user_fullpath variable for temporary storage */
   memcpy(user_fullpath, sp, n);
 
   if ((sp = memchr(user_fullpath, '\n', n)) == NULL) /* must be a proper line */
index 0e901f4b3e8b05a292556be40bad1e6e595aff26..e1cbc30477424d7f23c0243fb76cf67ee7508cbd 100644 (file)
@@ -261,10 +261,13 @@ PUBLIC int do_truncate()
 PUBLIC int do_ftruncate()
 {
 /* As with do_truncate(), truncate_inode() does the actual work. */
+  int r;
   struct filp *rfilp;
   
   if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP)
         return err_code;
+  if ( (r = forbidden(rfilp->filp_vno, W_BIT, 0 /*!use_realuid*/)) != OK)
+       return r;
   return truncate_vn(rfilp->filp_vno, m_in.m2_l1);
 }
 
index 52186f77a380de2aa6fc2d9a7a8c52557137035d..9060a7257174d7bfb249102e15898025c43b596c 100644 (file)
@@ -1,4 +1,4 @@
-/* This file contains the main program of the File System.  It consists of
+/*
  * a loop that gets messages requesting work, carries out the work, and sends
  * replies.
  *
@@ -60,8 +60,6 @@ PUBLIC int main()
   /* This is the main loop that gets work, processes it, and sends replies. */
   while (TRUE) {
        get_work();             /* sets who and call_nr */
-       fp = &fproc[who_p];     /* pointer to proc table struct */
-       super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
 
        if (who_e == PM_PROC_NR && call_nr != PROC_EVENT)
                printf("FS: strange, got message %d from PM\n", call_nr);
@@ -143,24 +141,60 @@ PUBLIC int main()
                continue;
        }
 
-       switch(call_nr)
-       {
-       case DEVCTL:
+       /* We only expect notify()s from tasks. */
+       if(who_p < 0) {
+               printf("FS: ignoring message from %d (%d)\n",
+                       who_e, m_in.m_type);
+               continue;
+       }
+
+       /* Now it's safe to set and check fp. */
+       fp = &fproc[who_p];     /* pointer to proc table struct */
+       super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
+
+       /* Calls from VM. */
+       if(who_e == VM_PROC_NR) {
+           int caught = 1;
+           switch(call_nr)
+           {
+               case VM_VFS_OPEN:
+                       error = do_vm_open();
+                       break;
+               case VM_VFS_CLOSE:
+                       error = do_vm_close();
+                       break;
+               case VM_VFS_MMAP:
+                       error = do_vm_mmap();
+                       break;
+               default:
+                       caught = 0;
+                       break;
+          }
+          if(caught) {
+               reply(who_e, error);
+               continue;
+          }
+       }
+
+         /* Other calls. */
+         switch(call_nr)
+         {
+             case DEVCTL:
                error= do_devctl();
                if (error != SUSPEND) reply(who_e, error);
                break;
 
-       case MAPDRIVER:
+             case MAPDRIVER:
                error= do_mapdriver();
                if (error != SUSPEND) reply(who_e, error);
                break;
 
-       default:
+             default:
                /* Call the internal function that does the work. */
                if (call_nr < 0 || call_nr >= NCALLS) { 
                        error = SUSPEND;
                        /* Not supposed to happen. */
-                       printf("FS, warning illegal %d system call by %d\n",
+                       printf("VFS: illegal %d system call by %d\n",
                                call_nr, who_e);
                } else if (fp->fp_pid == PID_FREE) {
                        error = ENOSYS;
@@ -176,7 +210,6 @@ PUBLIC int main()
 
                /* Copy the results back to the user and send reply. */
                if (error != SUSPEND) { reply(who_e, error); }
-               
        }
 #if 0
        if (!check_vrefs())
@@ -336,13 +369,6 @@ PRIVATE void fs_init()
    * extra block_size requirements are checked at super-block-read-in time.
    */
   if (OPEN_MAX > 127) panic(__FILE__,"OPEN_MAX > 127", NO_NUM);
-  /*
-  if (NR_BUFS < 6) panic(__FILE__,"NR_BUFS < 6", NO_NUM);
-  if (V1_INODE_SIZE != 32) panic(__FILE__,"V1 inode size != 32", NO_NUM);
-  if (V2_INODE_SIZE != 64) panic(__FILE__,"V2 inode size != 64", NO_NUM);
-  if (OPEN_MAX > 8 * sizeof(long))
-        panic(__FILE__,"Too few bits in fp_cloexec", NO_NUM);
-  */
   
   /* The following initializations are needed to let dev_opcl succeed .*/
   fp = (struct fproc *) NULL;
index f1a41b07fdb550dcfc40f07969be80349aa0716c..143018f3e8bacca6182bbbe5746f1f2a20fabb81 100644 (file)
@@ -219,6 +219,9 @@ PUBLIC int do_fcntl()
                return EINVAL;
        }
 
+       if ( (r = forbidden(f->filp_vno, W_BIT, 0 /*!use_realuid*/)) != OK)
+         return r;
+
        /* Copy flock data from userspace. */
        if((r = sys_datacopy(who_e, (vir_bytes) m_in.name1, 
          SELF, (vir_bytes) &flock_arg,
@@ -369,6 +372,7 @@ int cpid;   /* Child process id */
 
   /* Increase the counters in the 'filp' table. */
   cp = &fproc[childno];
+  fp = &fproc[parentno];
   for (i = 0; i < OPEN_MAX; i++)
        if (cp->fp_filp[i] != NIL_FILP) cp->fp_filp[i]->filp_count++;
 
@@ -379,8 +383,14 @@ int cpid;  /* Child process id */
   /* A forking process never has an outstanding grant,
    * as it isn't blocking on i/o.
    */
-  assert(!GRANT_VALID(fp->fp_grant));
-  assert(!GRANT_VALID(cp->fp_grant));
+  if(GRANT_VALID(fp->fp_grant)) {
+       printf("vfs: fork: fp (endpoint %d) has grant %d\n", fp->fp_endpoint, fp->fp_grant);
+       panic(__FILE__, "fp contains valid grant", NO_NUM);
+  }
+  if(GRANT_VALID(cp->fp_grant)) {
+       printf("vfs: fork: cp (endpoint %d) has grant %d\n", cp->fp_endpoint, cp->fp_grant);
+       panic(__FILE__, "cp contains valid grant", NO_NUM);
+  }
 
   /* A child is not a process leader. */
   cp->fp_sesldr = 0;
@@ -554,7 +564,9 @@ PUBLIC int do_svrctl()
                */
                if(fproc[proc_nr_n].fp_execced) {
                        /* Reply before calling dev_up */
+#if 0
                        printf("do_svrctl: replying before dev_up\n");
+#endif
                        reply(who_e, r);
                        dev_up(major);
                        r= SUSPEND;
diff --git a/servers/vfs/mmap.c b/servers/vfs/mmap.c
new file mode 100644 (file)
index 0000000..101ae0d
--- /dev/null
@@ -0,0 +1,32 @@
+/* mmap implementation in VFS
+ *
+ * The entry points into this file are
+ *   do_vm_mmap:       VM calls VM_VFS_MMAP
+ */
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/u64.h>
+#include "file.h"
+#include "fproc.h"
+#include "lock.h"
+#include "param.h"
+#include <dirent.h>
+#include <assert.h>
+
+#include <minix/vfsif.h>
+#include "vnode.h"
+#include "vmnt.h"
+
+/*===========================================================================*
+ *                             do_vm_mmap                              *
+ *===========================================================================*/
+PUBLIC int do_vm_mmap()
+{
+}
+
index 193ee40e1e858b1193f67e38981a7dc9118f8153..a7135d20a354e8788135bbd11438f94932b680c2 100644 (file)
@@ -311,8 +311,6 @@ PRIVATE int mount_fs(endpoint_t fs_e)
   root_node->v_dev = vmp->m_dev;
   
   if (replace_root) {
-      printf("Replacing root\n");
-
       /* Superblock and root node already read. 
        * Nothing else can go wrong. Perform the mount. */
       vmp->m_root_node = root_node;
index d32fb57de5a6b9aad5951e3e702266f38b011f30..5eb7e3390831120827e69f72ac8113654d155753 100644 (file)
@@ -795,3 +795,77 @@ PUBLIC void close_reply()
 }
 
 
+/*===========================================================================*
+ *                             do_vm_open                                   *
+ *===========================================================================*/
+PUBLIC int do_vm_open()
+{
+       int len, r, n;
+       endpoint_t ep;
+
+       len = m_in.VMVO_NAME_LENGTH;
+       m_out.VMV_ENDPOINT = ep = m_in.VMVO_ENDPOINT;
+
+       /* Do open() call on behalf of any process, performed by VM. */ 
+       if(len < 2 || len > sizeof(user_fullpath)) {
+               printf("do_vm_open: strange length %d\n", len);
+               m_out.VMVRO_FD = EINVAL;
+               return VM_VFS_REPLY_OPEN;
+       }
+
+       /* Do open on behalf of which process? */
+       if(isokendpt(ep, &n) != OK) {
+               printf("do_vm_open: strange endpoint %d\n", ep);
+               m_out.VMVRO_FD = EINVAL;
+               return VM_VFS_REPLY_OPEN;
+       }
+
+       /* XXX - do open on behalf of this process */
+       fp = &fproc[n];
+
+       /* Get path name from VM address space. */
+       if((r=sys_safecopyfrom(VM_PROC_NR, m_in.VMVO_NAME_GRANT, 0,
+               (vir_bytes) user_fullpath, len, D)) != OK) {
+               printf("do_vm_open: sys_safecopyfrom failed: %d\n", r);
+               m_out.VMVRO_FD = EPERM;
+               return VM_VFS_REPLY_OPEN;
+       }
+
+       /* Check if path is null-terminated. */
+       if(user_fullpath[len-1] != '\0') {
+               printf("do_vm_open: name (len %d) not 0-terminated\n", len);
+               m_out.VMVRO_FD = EINVAL;
+               return VM_VFS_REPLY_OPEN;
+       }
+
+       /* Perform open(). */
+       m_out.VMVRO_FD = common_open(m_in.VMVO_FLAGS, m_in.VMVO_MODE);
+       m_out.VMV_ENDPOINT = ep;
+
+       /* Send open() reply. */
+       return VM_VFS_REPLY_OPEN;
+}
+
+/*===========================================================================*
+ *                             do_vm_close                                  *
+ *===========================================================================*/
+PUBLIC int do_vm_close()
+{
+       int len, r, n;
+       endpoint_t ep;
+
+       len = m_in.VMVO_NAME_LENGTH;
+
+       /* Do close() call on behalf of any process, performed by VM. */ 
+       m_out.VMV_ENDPOINT = ep = m_in.VMVC_ENDPOINT;
+       if(isokendpt(ep, &n) != OK) {
+               printf("do_vm_close: strange endpoint %d\n", ep);
+               return VM_VFS_REPLY_CLOSE;
+       }
+
+       /* Perform close(). */
+       r = close_fd(&fproc[n], m_in.VMVC_FD);
+
+       return VM_VFS_REPLY_CLOSE;
+}
+
index 407b9d5a5a00d07bd500cdd046124bf1b53d6659..82ece30f12c9ad328eceab6e1e7986db0f82373f 100644 (file)
@@ -462,7 +462,11 @@ int proc_nr_e;
   dev_t dev;
   message mess;
 
-  okendpt(proc_nr_e, &proc_nr_p);
+  if(isokendpt(proc_nr_e, &proc_nr_p) != OK) {
+       printf("VFS: ignoring unpause for bogus endpoint %d\n", proc_nr_e);
+       return;
+  }
+
   rfp = &fproc[proc_nr_p];
   if (rfp->fp_suspended == NOT_SUSPENDED)
        return;
index 0812ec0e267b74e1d1d2d25b825b6d6a9a4830f3..abd92dd550b2b3ca9085ab186cb6c5509bce131e 100644 (file)
@@ -31,7 +31,6 @@ _PROTOTYPE( void dev_up, (int major)                                  );
 _PROTOTYPE( endpoint_t suspended_ep, (endpoint_t driver,
                                                cp_grant_id_t g)        );
 _PROTOTYPE( void reopen_reply, (void)                                  );
-_PROTOTYPE( int asynsend, (endpoint_t dst, message *mp)                        );
 
 /* dmap.c */
 _PROTOTYPE( int do_devctl, (void)                                      );
@@ -52,7 +51,7 @@ _PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
 /* filedes.c */
 _PROTOTYPE( struct filp *find_filp, (struct vnode *vp, mode_t bits)    );
 _PROTOTYPE( int get_fd, (int start, mode_t bits, int *k, 
-            struct filp **fpt)                                          );
+            struct filp **fpt)                                             );
 _PROTOTYPE( struct filp *get_filp, (int fild)                          );
 _PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild)      );
 _PROTOTYPE( int inval_filp, (struct filp *)                            );
@@ -90,6 +89,9 @@ _PROTOTYPE( int do_svrctl, (void)                                     );
 _PROTOTYPE( int do_getsysinfo, (void)                                  );
 _PROTOTYPE( int pm_dumpcore, (int proc_e, struct mem_map *seg_ptr)     );
 
+/* mmap.c */
+_PROTOTYPE( int do_vm_mmap, (void)                                     );
+
 /* mount.c */
 _PROTOTYPE( int do_fslogin, (void)                                      );
 _PROTOTYPE( int do_mount, (void)                                       );
@@ -108,14 +110,16 @@ _PROTOTYPE( int do_mknod, (void)                                  );
 _PROTOTYPE( int do_mkdir, (void)                                       );
 _PROTOTYPE( int do_open, (void)                                                );
 _PROTOTYPE( int do_slink, (void)                                        );
+_PROTOTYPE( int do_vm_open, (void)                                     );
+_PROTOTYPE( int do_vm_close, (void)                                    );
 
 /* path.c */
 _PROTOTYPE( int lookup_rel_vp, (struct vnode *start_node, int flags,
-                               int use_realuid, struct vnode **vpp)    );
+                       int use_realuid, struct vnode **vpp)    );
 _PROTOTYPE( int lookup_vp, (int flags, int use_realuid,
-                                               struct vnode **vpp)     );
+                       struct vnode **vpp)     );
 _PROTOTYPE( int lookup_lastdir_rel, (struct vnode *start_node,
-                               int use_realuid, struct vnode **vpp)    );
+                       int use_realuid, struct vnode **vpp)    );
 _PROTOTYPE( int lookup_lastdir, (int use_realuid, struct vnode **vpp)  );
 
 /* pipe.c */
index d58f7421d12598c07be45974b25df8c7fb728d29..43fbba8b83c62712a7a88b63b71e79c94001918c 100644 (file)
 #include <minix/endpoint.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <assert.h>
 #include "file.h"
 #include "fproc.h"
 #include "param.h"
 #include "vmnt.h"
 
-PRIVATE int panicking;         /* inhibits recursive panics during sync */
-
 /*===========================================================================*
  *                             fetch_name                                   *
  *===========================================================================*/
@@ -30,7 +29,7 @@ char *path;                   /* pointer to the path in user space */
 int len;                       /* path length, including 0 byte */
 int flag;                      /* M3 means path may be in message */
 {
-/* Go get path and put it in 'user_path'.
+/* Go get path and put it in 'user_fullpath'.
  * If 'flag' = M3 and 'len' <= M3_STRING, the path is present in 'message'.
  * If it is not, go copy it from user space.
  */
@@ -38,6 +37,8 @@ int flag;                     /* M3 means path may be in message */
   int r;
 
   if (len > PATH_MAX) {
+       printf("VFS: fetch_name: len (%d) > %d\n", len, PATH_MAX);
+       util_stacktrace();
        err_code = ENAMETOOLONG;
        return(EGENERIC);
   }
@@ -50,11 +51,12 @@ int flag;                   /* M3 means path may be in message */
   if (len <= 0) {
        err_code = EINVAL;
        printf("vfs: fetch_name: len %d?\n", len);
+       util_stacktrace();
        return(EGENERIC);
   }
 
   if (flag == M3 && len <= M3_STRING) {
-       /* Just copy the path from the message to 'user_path'. */
+       /* Just copy the path from the message to 'user_fullpath'. */
        rpu = &user_fullpath[0];
        rpm = m_in.pathname;            /* contained in input message */
        do { *rpu++ = *rpm++; } while (--len);
@@ -88,40 +90,32 @@ PUBLIC int no_sys()
   return(SUSPEND);
 }
 
-/*===========================================================================*
- *                              panic                                        *
- *===========================================================================*/
-PUBLIC void panic(who, mess, num)
-char *who;                      /* who caused the panic */
-char *mess;                     /* panic message string */
-int num;                        /* number to go with it */
-{
-  if (!panicking) {             /* do not panic during a sync */
-        panicking = TRUE;       /* prevent another panic during the sync */
-
-        printf("VFS panic (%s): %s ", who, mess);
-        if (num != NO_NUM) printf("%d",num); 
-        printf("\n"); 
-        (void) do_sync();               /* flush everything to the disk */
-  } else printf("VFS re-panic\n");
-  exit(1);
-}
-
 /*===========================================================================*
  *                             isokendpt_f                                  *
  *===========================================================================*/
 PUBLIC int isokendpt_f(char *file, int line, int endpoint, int *proc, int fatal)
 {
     int failed = 0;
+    endpoint_t ke;
     *proc = _ENDPOINT_P(endpoint);
-    if(*proc < 0 || *proc >= NR_PROCS) {
+    if(endpoint == NONE) {
+        printf("vfs:%s: endpoint is NONE\n", file, line, endpoint);
+        failed = 1;
+    } else if(*proc < 0 || *proc >= NR_PROCS) {
         printf("vfs:%s:%d: proc (%d) from endpoint (%d) out of range\n",
                 file, line, *proc, endpoint);
         failed = 1;
-    } else if(fproc[*proc].fp_endpoint != endpoint) {
-        printf("vfs:%s:%d: proc (%d) from endpoint (%d) doesn't match "
-                "known endpoint (%d)\n",
-                file, line, *proc, endpoint, fproc[*proc].fp_endpoint);
+    } else if((ke=fproc[*proc].fp_endpoint) != endpoint) {
+       if(ke == NONE) {
+               printf("vfs:%s:%d: endpoint (%d) points to NONE slot (%d)\n",
+                       file, line, endpoint, *proc);
+               assert(fproc[*proc].fp_pid == PID_FREE);
+       } else {
+               printf("vfs:%s:%d: proc (%d) from endpoint (%d) doesn't match "
+                        "known endpoint (%d)\n",
+                        file, line, *proc, endpoint, fproc[*proc].fp_endpoint);
+               assert(fproc[*proc].fp_pid != PID_FREE);
+       }
         failed = 1;
     }
 
diff --git a/servers/vm/Makefile b/servers/vm/Makefile
new file mode 100644 (file)
index 0000000..29e7e56
--- /dev/null
@@ -0,0 +1,33 @@
+# Makefile for VM server
+SERVER = vm
+
+include /etc/make.conf
+
+OBJ = main.o alloc.o utility.o exec.o exit.o fork.o break.o \
+       signal.o vfs.o mmap.o slaballoc.o region.o pagefaults.o
+ARCHOBJ =  $(ARCH)/vm.o $(ARCH)/pagetable.o $(ARCH)/arch_pagefaults.o $(ARCH)/util.o 
+
+CPPFLAGS=-I../../kernel/arch/$(ARCH)/include -I$(ARCH)
+CFLAGS = $(CPROFILE) $(CPPFLAGS)
+
+# build local binary
+
+all build install:     $(SERVER)
+       #install $(SERVER)
+
+$(SERVER):     $(OBJ) $(ARCHOBJ)
+       cd $(ARCH) && $(MAKE)
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) $(ARCHOBJ)  -lsys  
+
+# clean up local files
+clean:
+       rm -f $(SERVER) *.o *.bak 
+       cd $(ARCH) && $(MAKE) $@
+
+depend: 
+       cd $(ARCH) && $(MAKE) $@
+       mkdep "$(CC) -E $(CPPFLAGS)" *.c $(ARCH)/*.c > .depend
+
+# Include generated dependencies.
+include .depend
+
diff --git a/servers/vm/alloc.c b/servers/vm/alloc.c
new file mode 100644 (file)
index 0000000..196556e
--- /dev/null
@@ -0,0 +1,832 @@
+/* This file is concerned with allocating and freeing arbitrary-size blocks of
+ * physical memory on behalf of the FORK and EXEC system calls.  The key data
+ * structure used is the hole table, which maintains a list of holes in memory.
+ * It is kept sorted in order of increasing memory address. The addresses
+ * it contains refers to physical memory, starting at absolute address 0
+ * (i.e., they are not relative to the start of PM).  During system
+ * initialization, that part of memory containing the interrupt vectors,
+ * kernel, and PM are "allocated" to mark them as not available and to
+ * remove them from the hole list.
+ *
+ * The entry points into this file are:
+ *   alloc_mem:        allocate a given sized chunk of memory
+ *   free_mem: release a previously allocated chunk of memory
+ *   mem_init: initialize the tables when PM start up
+ */
+
+#define _SYSTEM 1
+
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include <minix/type.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+#include <sys/mman.h>
+
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <memory.h>
+
+#include "vm.h"
+#include "proto.h"
+#include "util.h"
+#include "glo.h"
+
+/* Initially, no free pages are known. */
+PRIVATE phys_bytes free_pages_head = NO_MEM;   /* Physical address in bytes. */
+
+/* Used for sanity check. */
+PRIVATE phys_bytes mem_low, mem_high;
+#define vm_assert_range(addr, len)                     \
+       vm_assert((addr) >= mem_low);                   \
+       vm_assert((addr) + (len) - 1 <= mem_high);
+
+struct hole {
+       struct hole *h_next;          /* pointer to next entry on the list */
+       phys_clicks h_base;           /* where does the hole begin? */
+       phys_clicks h_len;            /* how big is the hole? */
+       int freelist;
+       int holelist;
+};
+
+#define NIL_HOLE (struct hole *) 0
+
+#define _NR_HOLES (_NR_PROCS*2)  /* No. of memory holes maintained by VM */
+
+PRIVATE struct hole hole[_NR_HOLES];
+
+PRIVATE struct hole *hole_head;        /* pointer to first hole */
+PRIVATE struct hole *free_slots;/* ptr to list of unused table slots */
+
+FORWARD _PROTOTYPE( void del_slot, (struct hole *prev_ptr, struct hole *hp) );
+FORWARD _PROTOTYPE( void merge, (struct hole *hp)                          );
+FORWARD _PROTOTYPE( void free_pages, (phys_bytes addr, int pages)          );
+FORWARD _PROTOTYPE( phys_bytes alloc_pages, (int pages, int flags)         );
+
+#if SANITYCHECKS
+FORWARD _PROTOTYPE( void holes_sanity_f, (char *fn, int line)              );
+#define CHECKHOLES holes_sanity_f(__FILE__, __LINE__)
+#else
+#define CHECKHOLES 
+#endif
+
+/* Sanity check for parameters of node p. */
+#define vm_assert_params(p, bytes, next) { \
+       vm_assert((p) != NO_MEM);       \
+       vm_assert(!((bytes) % VM_PAGE_SIZE)); \
+       vm_assert(!((next) % VM_PAGE_SIZE)); \
+       vm_assert((bytes) > 0); \
+       vm_assert((p) + (bytes) > (p)); \
+       vm_assert((next) == NO_MEM || ((p) + (bytes) <= (next))); \
+       vm_assert_range((p), (bytes)); \
+       vm_assert_range((next), 1); \
+}
+
+/* Retrieve size of free block and pointer to next block from physical
+ * address (page) p.
+ */
+#define GET_PARAMS(p, bytes, next) { \
+       phys_readaddr((p), &(bytes), &(next));  \
+       vm_assert_params((p), (bytes), (next)); \
+}
+
+/* Write parameters to physical page p. */
+#define SET_PARAMS(p, bytes, next) { \
+       vm_assert_params((p), (bytes), (next)); \
+       phys_writeaddr((p), (bytes), (next));   \
+}
+
+
+void availbytes(vir_bytes *bytes, vir_bytes *chunks)
+{
+       phys_bytes p, nextp;
+       *bytes = 0;
+       *chunks = 0;
+       for(p = free_pages_head; p != NO_MEM; p = nextp) {
+               phys_bytes thissize, ret;
+               GET_PARAMS(p, thissize, nextp);
+               (*bytes) += thissize;
+               (*chunks)++;
+               if(nextp != NO_MEM)     {
+                       vm_assert(nextp > p);
+                       vm_assert(nextp > p + thissize);
+               }
+       }
+
+       return;
+}
+
+
+#if SANITYCHECKS
+
+/*===========================================================================*
+ *                             holes_sanity_f                               *
+ *===========================================================================*/
+PRIVATE void holes_sanity_f(file, line)
+char *file;
+int line;
+{
+#define myassert(c) { \
+  if(!(c)) { \
+       printf("holes_sanity_f:%s:%d: %s failed\n", file, line, #c); \
+       util_stacktrace();      \
+       vm_panic("assert failed.", NO_NUM); } \
+  }    
+
+       int h, c = 0, n = 0;
+       struct hole *hp;
+
+       /* Reset flags */
+       for(h = 0; h < _NR_HOLES; h++) {
+               hole[h].freelist = 0;
+               hole[h].holelist = 0;
+       }
+
+       /* Mark all holes on freelist. */
+       for(hp = free_slots; hp; hp = hp->h_next) {
+               myassert(!hp->freelist);
+               myassert(!hp->holelist);
+               hp->freelist = 1;
+               myassert(c < _NR_HOLES);
+               c++;
+               n++;
+       }
+
+       /* Mark all holes on holelist. */
+       c = 0;
+       for(hp = hole_head; hp; hp = hp->h_next) {
+               myassert(!hp->freelist);
+               myassert(!hp->holelist);
+               hp->holelist = 1;
+               myassert(c < _NR_HOLES);
+               c++;
+               n++;
+       }
+
+       /* Check there are exactly the right number of nodes. */
+       myassert(n == _NR_HOLES);
+
+       /* Make sure each slot is on exactly one of the list. */
+       c = 0;
+       for(h = 0; h < _NR_HOLES; h++) {
+               hp = &hole[h];
+               myassert(hp->holelist || hp->freelist);
+               myassert(!(hp->holelist && hp->freelist));
+               myassert(c < _NR_HOLES);
+               c++;
+       }
+
+       /* Make sure no holes overlap. */
+       for(hp = hole_head; hp && hp->h_next; hp = hp->h_next) {
+               myassert(hp->holelist);
+               hp->holelist = 1;
+               /* No holes overlap. */
+               myassert(hp->h_base + hp->h_len <= hp->h_next->h_base);
+
+               /* No uncoalesced holes. */
+               myassert(hp->h_base + hp->h_len < hp->h_next->h_base);
+       }
+}
+#endif
+
+/*===========================================================================*
+ *                             alloc_mem_f                                  *
+ *===========================================================================*/
+PUBLIC phys_clicks alloc_mem_f(phys_clicks clicks, u32_t memflags)
+{
+/* Allocate a block of memory from the free list using first fit. The block
+ * consists of a sequence of contiguous bytes, whose length in clicks is
+ * given by 'clicks'.  A pointer to the block is returned.  The block is
+ * always on a click boundary.  This procedure is called when memory is
+ * needed for FORK or EXEC.
+ */
+  register struct hole *hp, *prev_ptr;
+  phys_clicks old_base;
+  int s;
+
+  if(vm_paged) {
+       vm_assert(CLICK_SIZE == VM_PAGE_SIZE);
+       return alloc_pages(clicks, memflags);
+  }
+
+CHECKHOLES;
+
+  {
+        prev_ptr = NIL_HOLE;
+       hp = hole_head;
+       while (hp != NIL_HOLE) {
+               if (hp->h_len >= clicks) {
+                       /* We found a hole that is big enough.  Use it. */
+                       old_base = hp->h_base;  /* remember where it started */
+                       hp->h_base += clicks;   /* bite a piece off */
+                       hp->h_len -= clicks;    /* ditto */
+
+                       /* Delete the hole if used up completely. */
+                       if (hp->h_len == 0) del_slot(prev_ptr, hp);
+
+                       /* Anything special needs to happen? */
+                       if(memflags & PAF_CLEAR) {
+                         if ((s= sys_memset(0, CLICK_SIZE*old_base,
+                               CLICK_SIZE*clicks)) != OK)   {
+                               vm_panic("alloc_mem: sys_memset failed", s);
+                         }
+                       }
+
+                       /* Return the start address of the acquired block. */
+CHECKHOLES;
+                       return(old_base);
+               }
+
+               prev_ptr = hp;
+               hp = hp->h_next;
+       }
+  }
+CHECKHOLES;
+  return(NO_MEM);
+}
+
+/*===========================================================================*
+ *                             free_mem_f                                   *
+ *===========================================================================*/
+PUBLIC void free_mem_f(phys_clicks base, phys_clicks clicks)
+{
+/* Return a block of free memory to the hole list.  The parameters tell where
+ * the block starts in physical memory and how big it is.  The block is added
+ * to the hole list.  If it is contiguous with an existing hole on either end,
+ * it is merged with the hole or holes.
+ */
+  register struct hole *hp, *new_ptr, *prev_ptr;
+CHECKHOLES;
+
+  if (clicks == 0) return;
+
+  if(vm_paged) {
+       vm_assert(CLICK_SIZE == VM_PAGE_SIZE);
+       free_pages(base, clicks);
+       return;
+  }
+
+  if ( (new_ptr = free_slots) == NIL_HOLE) 
+       vm_panic("hole table full", NO_NUM);
+  new_ptr->h_base = base;
+  new_ptr->h_len = clicks;
+  free_slots = new_ptr->h_next;
+  hp = hole_head;
+
+  /* If this block's address is numerically less than the lowest hole currently
+   * available, or if no holes are currently available, put this hole on the
+   * front of the hole list.
+   */
+  if (hp == NIL_HOLE || base <= hp->h_base) {
+       /* Block to be freed goes on front of the hole list. */
+       new_ptr->h_next = hp;
+       hole_head = new_ptr;
+       merge(new_ptr);
+CHECKHOLES;
+       return;
+  }
+
+  /* Block to be returned does not go on front of hole list. */
+  prev_ptr = NIL_HOLE;
+  while (hp != NIL_HOLE && base > hp->h_base) {
+       prev_ptr = hp;
+       hp = hp->h_next;
+  }
+
+  /* We found where it goes.  Insert block after 'prev_ptr'. */
+  new_ptr->h_next = prev_ptr->h_next;
+  prev_ptr->h_next = new_ptr;
+  merge(prev_ptr);             /* sequence is 'prev_ptr', 'new_ptr', 'hp' */
+CHECKHOLES;
+}
+
+/*===========================================================================*
+ *                             del_slot                                     *
+ *===========================================================================*/
+PRIVATE void del_slot(prev_ptr, hp)
+/* pointer to hole entry just ahead of 'hp' */
+register struct hole *prev_ptr;
+/* pointer to hole entry to be removed */
+register struct hole *hp;      
+{
+/* Remove an entry from the hole list.  This procedure is called when a
+ * request to allocate memory removes a hole in its entirety, thus reducing
+ * the numbers of holes in memory, and requiring the elimination of one
+ * entry in the hole list.
+ */
+  if (hp == hole_head)
+       hole_head = hp->h_next;
+  else
+       prev_ptr->h_next = hp->h_next;
+
+  hp->h_next = free_slots;
+  hp->h_base = hp->h_len = 0;
+  free_slots = hp;
+}
+
+/*===========================================================================*
+ *                             merge                                        *
+ *===========================================================================*/
+PRIVATE void merge(hp)
+register struct hole *hp;      /* ptr to hole to merge with its successors */
+{
+/* Check for contiguous holes and merge any found.  Contiguous holes can occur
+ * when a block of memory is freed, and it happens to abut another hole on
+ * either or both ends.  The pointer 'hp' points to the first of a series of
+ * three holes that can potentially all be merged together.
+ */
+  register struct hole *next_ptr;
+
+  /* If 'hp' points to the last hole, no merging is possible.  If it does not,
+   * try to absorb its successor into it and free the successor's table entry.
+   */
+  if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
+  if (hp->h_base + hp->h_len == next_ptr->h_base) {
+       hp->h_len += next_ptr->h_len;   /* first one gets second one's mem */
+       del_slot(hp, next_ptr);
+  } else {
+       hp = next_ptr;
+  }
+
+  /* If 'hp' now points to the last hole, return; otherwise, try to absorb its
+   * successor into it.
+   */
+  if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
+  if (hp->h_base + hp->h_len == next_ptr->h_base) {
+       hp->h_len += next_ptr->h_len;
+       del_slot(hp, next_ptr);
+  }
+}
+
+/*===========================================================================*
+ *                             mem_init                                     *
+ *===========================================================================*/
+PUBLIC void mem_init(chunks)
+struct memory *chunks;         /* list of free memory chunks */
+{
+/* Initialize hole lists.  There are two lists: 'hole_head' points to a linked
+ * list of all the holes (unused memory) in the system; 'free_slots' points to
+ * a linked list of table entries that are not in use.  Initially, the former
+ * list has one entry for each chunk of physical memory, and the second
+ * list links together the remaining table slots.  As memory becomes more
+ * fragmented in the course of time (i.e., the initial big holes break up into
+ * smaller holes), new table slots are needed to represent them.  These slots
+ * are taken from the list headed by 'free_slots'.
+ */
+  int i, first = 0;
+  register struct hole *hp;
+
+  /* Put all holes on the free list. */
+  for (hp = &hole[0]; hp < &hole[_NR_HOLES]; hp++) {
+       hp->h_next = hp + 1;
+       hp->h_base = hp->h_len = 0;
+  }
+  hole[_NR_HOLES-1].h_next = NIL_HOLE;
+  hole_head = NIL_HOLE;
+  free_slots = &hole[0];
+
+  /* Use the chunks of physical memory to allocate holes. */
+  for (i=NR_MEMS-1; i>=0; i--) {
+       if (chunks[i].size > 0) {
+               phys_bytes from = CLICK2ABS(chunks[i].base),
+                       to = CLICK2ABS(chunks[i].base+chunks[i].size)-1;
+               if(first || from < mem_low) mem_low = from;
+               if(first || to > mem_high) mem_high = to;
+               FREE_MEM(chunks[i].base, chunks[i].size);
+               first = 0;
+       }
+  }
+
+  CHECKHOLES;
+}
+
+/*===========================================================================*
+ *                             alloc_pages                                  *
+ *===========================================================================*/
+PRIVATE PUBLIC phys_bytes alloc_pages(int pages, int memflags)
+{
+       phys_bytes bytes, p, nextp, prevp = NO_MEM;
+       phys_bytes prevsize = 0;
+
+#if SANITYCHECKS
+       vir_bytes avail1, avail2, chunks1, chunks2;
+       availbytes(&avail1, &chunks1);
+#endif
+
+       vm_assert(pages > 0);
+       bytes = CLICK2ABS(pages);
+       vm_assert(ABS2CLICK(bytes) == pages);
+
+#if SANITYCHECKS
+#define ALLOCRETURNCHECK                       \
+       availbytes(&avail2, &chunks2);          \
+       vm_assert(avail1 - bytes == avail2);    \
+       vm_assert(chunks1 == chunks2 || chunks1-1 == chunks2);  \
+       if(verbosealloc)                                        \
+               printf("memory: 0x%lx bytes in %d chunks\n", avail2, chunks2);
+#else
+#define ALLOCRETURNCHECK
+#endif
+
+
+       for(p = free_pages_head; p != NO_MEM; p = nextp) {
+               phys_bytes thissize, ret;
+               GET_PARAMS(p, thissize, nextp);
+               if(thissize >= bytes) {
+                       /* We found a chunk that's big enough. */
+
+                       ret = p + thissize - bytes;
+                       thissize -= bytes;
+
+                       if(thissize == 0) {
+                               /* Special case: remove this link entirely. */
+                               if(prevp == NO_MEM)
+                                       free_pages_head = nextp;
+                               else {
+                                       vm_assert(prevsize > 0);
+                                       SET_PARAMS(prevp, prevsize, nextp);
+                               }
+                       } else {
+                               /* Remove memory from this chunk. */
+                               SET_PARAMS(p, thissize, nextp);
+                       }
+
+                       /* Clear memory if requested. */
+                       if(memflags & PAF_CLEAR) {
+                         int s;
+                         if ((s= sys_memset(0, ret, bytes)) != OK)   {
+                               vm_panic("alloc_pages: sys_memset failed", s);
+                         }
+                       }
+
+                       /* Check if returned range is actual good memory. */
+                       vm_assert_range(ret, bytes);
+
+                       ALLOCRETURNCHECK;
+
+                       /* Return it in clicks. */
+                       return ABS2CLICK(ret);
+               }
+               prevp = p;
+               prevsize = thissize;
+       }
+       return NO_MEM;
+}
+
+/*===========================================================================*
+ *                             free_pages                                   *
+ *===========================================================================*/
+PRIVATE PUBLIC void free_pages(phys_bytes pageno, int npages)
+{
+       phys_bytes p, origsize,
+               size, nextaddr, thissize, prevp = NO_MEM, pageaddr;
+
+#if SANITYCHECKS
+       vir_bytes avail1, avail2, chunks1, chunks2;
+       availbytes(&avail1, &chunks1);
+#endif
+
+#if SANITYCHECKS
+#define FREERETURNCHECK                                                                \
+       availbytes(&avail2, &chunks2);                                          \
+       vm_assert(avail1 + origsize  == avail2);                                \
+       vm_assert(chunks1 == chunks2 || chunks1+1 == chunks2 || chunks1-1 == chunks2);  \
+       if(verbosealloc)                                                        \
+               printf("memory: 0x%lx bytes in %d chunks\n", avail2, chunks2);
+#else
+#define FREERETURNCHECK
+#endif
+
+       /* Basic sanity check. */
+       vm_assert(npages > 0);
+       vm_assert(pageno != NO_MEM);    /* Page number must be reasonable. */
+
+       /* Convert page and pages to bytes. */
+       pageaddr = CLICK2ABS(pageno);
+       origsize = size = npages * VM_PAGE_SIZE;        /* Size in bytes. */
+       vm_assert(pageaddr != NO_MEM);
+       vm_assert(ABS2CLICK(pageaddr) == pageno);
+       vm_assert_range(pageaddr, size);
+
+       /* More sanity checks. */
+       vm_assert(ABS2CLICK(size) == npages);   /* Sanity. */
+       vm_assert(pageaddr + size > pageaddr);          /* Must not overflow. */
+
+       /* Special case: no free pages. */
+       if(free_pages_head == NO_MEM) {
+               free_pages_head = pageaddr;
+               SET_PARAMS(pageaddr, size, NO_MEM);
+               FREERETURNCHECK;
+               return;
+       }
+
+       /* Special case: the free block is before the current head. */
+       if(pageaddr < free_pages_head) {
+               phys_bytes newsize, newnext, headsize, headnext;
+               vm_assert(pageaddr + size <= free_pages_head);
+               GET_PARAMS(free_pages_head, headsize, headnext);
+               newsize = size;
+               if(pageaddr + size == free_pages_head) {
+                       /* Special case: contiguous. */
+                       newsize += headsize;
+                       newnext = headnext;
+               } else {
+                       newnext = free_pages_head;
+               }
+               SET_PARAMS(pageaddr, newsize, newnext);
+               free_pages_head = pageaddr;
+               FREERETURNCHECK;
+               return;
+       }
+
+       /* Find where to put the block in the free list. */
+       for(p = free_pages_head; p < pageaddr; p = nextaddr) {
+               GET_PARAMS(p, thissize, nextaddr);
+
+               if(nextaddr == NO_MEM) {
+                       /* Special case: page is at the end of the list. */
+                       if(p + thissize == pageaddr) {
+                               /* Special case: contiguous. */
+                               SET_PARAMS(p, thissize + size, NO_MEM);
+                               FREERETURNCHECK;
+                       } else {
+                               SET_PARAMS(p, thissize, pageaddr);
+                               SET_PARAMS(pageaddr, size, NO_MEM);
+                               FREERETURNCHECK;
+                       }
+                       return;
+               }
+
+               prevp = p;
+       }
+
+       /* Normal case: insert page block between two others.
+        * The first block starts at 'prevp' and is 'thissize'.
+        * The second block starts at 'p' and is 'nextsize'.
+        * The block that has to come in between starts at
+        * 'pageaddr' and is size 'size'.
+        */
+       vm_assert(p != NO_MEM);
+       vm_assert(prevp != NO_MEM);
+       vm_assert(prevp < p);
+       vm_assert(p == nextaddr);
+
+#if SANITYCHECKS
+  {
+       vir_bytes prevpsize, prevpnext;
+       GET_PARAMS(prevp, prevpsize, prevpnext);
+       vm_assert(prevpsize == thissize);
+       vm_assert(prevpnext == p);
+
+       availbytes(&avail2, &chunks2);
+       vm_assert(avail1 == avail2);
+  }
+#endif
+
+       if(prevp + thissize == pageaddr) {
+               /* Special case: first block is contiguous with freed one. */
+               phys_bytes newsize = thissize + size;
+               SET_PARAMS(prevp, newsize, p);
+               pageaddr = prevp;
+               size = newsize;
+       } else {
+               SET_PARAMS(prevp, thissize, pageaddr);
+       }
+
+       /* The block has been inserted (and possibly merged with the
+        * first one). Check if it has to be merged with the second one.
+        */
+
+       if(pageaddr + size == p) {
+               phys_bytes nextsize, nextnextaddr;
+               /* Special case: freed block is contiguous with next one. */
+               GET_PARAMS(p, nextsize, nextnextaddr);
+               SET_PARAMS(pageaddr, size+nextsize, nextnextaddr);
+               FREERETURNCHECK;
+       } else {
+               SET_PARAMS(pageaddr, size, p);
+               FREERETURNCHECK;
+       }
+
+       return;
+}
+
+
+#define NR_DMA 16
+
+PRIVATE struct dmatab
+{
+       int dt_flags;
+       endpoint_t dt_proc;
+       phys_bytes dt_base;
+       phys_bytes dt_size;
+       phys_clicks dt_seg_base;
+       phys_clicks dt_seg_size;
+} dmatab[NR_DMA];
+
+#define DTF_INUSE      1
+#define DTF_RELEASE_DMA        2
+#define DTF_RELEASE_SEG        4
+
+/*===========================================================================*
+ *                             do_adddma                                    *
+ *===========================================================================*/
+PUBLIC int do_adddma(message *msg)
+{
+       endpoint_t req_proc_e, target_proc_e;
+       int i, proc_n;
+       phys_bytes base, size;
+       struct vmproc *vmp;
+
+       req_proc_e= msg->VMAD_REQ;
+       target_proc_e= msg->VMAD_EP;
+       base= msg->VMAD_START;
+       size= msg->VMAD_SIZE;
+
+       /* Find empty slot */
+       for (i= 0; i<NR_DMA; i++)
+       {
+               if (!(dmatab[i].dt_flags & DTF_INUSE))
+                       break;
+       }
+       if (i >= NR_DMA)
+       {
+               printf("vm:do_adddma: dma table full\n");
+               for (i= 0; i<NR_DMA; i++)
+               {
+                       printf("%d: flags 0x%x proc %d base 0x%x size 0x%x\n",
+                               i, dmatab[i].dt_flags,
+                               dmatab[i].dt_proc,
+                               dmatab[i].dt_base,
+                               dmatab[i].dt_size);
+               }
+               vm_panic("adddma: table full", NO_NUM);
+               return ENOSPC;
+       }
+
+       /* Find target process */
+       if (vm_isokendpt(target_proc_e, &proc_n) != OK)
+       {
+               printf("vm:do_adddma: endpoint %d not found\n", target_proc_e);
+               return EINVAL;
+       }
+       vmp= &vmproc[proc_n];
+       vmp->vm_flags |= VMF_HAS_DMA;
+
+       dmatab[i].dt_flags= DTF_INUSE;
+       dmatab[i].dt_proc= target_proc_e;
+       dmatab[i].dt_base= base;
+       dmatab[i].dt_size= size;
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             do_deldma                                    *
+ *===========================================================================*/
+PUBLIC int do_deldma(message *msg)
+{
+       endpoint_t req_proc_e, target_proc_e;
+       int i, j, proc_n;
+       phys_bytes base, size;
+       struct vmproc *vmp;
+
+       req_proc_e= msg->VMDD_REQ;
+       target_proc_e= msg->VMDD_EP;
+       base= msg->VMDD_START;
+       size= msg->VMDD_SIZE;
+
+       /* Find slot */
+       for (i= 0; i<NR_DMA; i++)
+       {
+               if (!(dmatab[i].dt_flags & DTF_INUSE))
+                       continue;
+               if (dmatab[i].dt_proc == target_proc_e &&
+                       dmatab[i].dt_base == base &&
+                       dmatab[i].dt_size == size)
+               {
+                       break;
+               }
+       }
+       if (i >= NR_DMA)
+       {
+               printf("vm:do_deldma: slot not found\n");
+               return ESRCH;
+       }
+
+       if (dmatab[i].dt_flags & DTF_RELEASE_SEG)
+       {
+               /* Check if we have to release the segment */
+               for (j= 0; j<NR_DMA; j++)
+               {
+                       if (j == i)
+                               continue;
+                       if (!(dmatab[j].dt_flags & DTF_INUSE))
+                               continue;
+                       if (!(dmatab[j].dt_flags & DTF_RELEASE_SEG))
+                               continue;
+                       if (dmatab[i].dt_proc == target_proc_e)
+                               break;
+               }
+               if (j >= NR_DMA)
+               {
+                       /* Last segment */
+                       FREE_MEM(dmatab[i].dt_seg_base,
+                               dmatab[i].dt_seg_size);
+               }
+       }
+
+       dmatab[i].dt_flags &= ~DTF_INUSE;
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             do_getdma                                    *
+ *===========================================================================*/
+PUBLIC int do_getdma(message *msg)
+{
+       endpoint_t target_proc_e;
+       int i, proc_n;
+       phys_bytes base, size;
+       struct vmproc *vmp;
+
+       /* Find slot to report */
+       for (i= 0; i<NR_DMA; i++)
+       {
+               if (!(dmatab[i].dt_flags & DTF_INUSE))
+                       continue;
+               if (!(dmatab[i].dt_flags & DTF_RELEASE_DMA))
+                       continue;
+
+               printf("do_getdma: setting reply to 0x%x@0x%x proc %d\n",
+                       dmatab[i].dt_size, dmatab[i].dt_base,
+                       dmatab[i].dt_proc);
+               msg->VMGD_PROCP= dmatab[i].dt_proc;
+               msg->VMGD_BASEP= dmatab[i].dt_base;
+               msg->VMGD_SIZEP= dmatab[i].dt_size;
+
+               return OK;
+       }
+
+       /* Nothing */
+       return EAGAIN;
+}
+
+
+
+/*===========================================================================*
+ *                             release_dma                                  *
+ *===========================================================================*/
+PUBLIC void release_dma(struct vmproc *vmp)
+{
+       int i, found_one;
+
+       vm_panic("release_dma not done", NO_NUM);
+#if 0
+
+       found_one= FALSE;
+       for (i= 0; i<NR_DMA; i++)
+       {
+               if (!(dmatab[i].dt_flags & DTF_INUSE))
+                       continue;
+               if (dmatab[i].dt_proc != vmp->vm_endpoint)
+                       continue;
+               dmatab[i].dt_flags |= DTF_RELEASE_DMA | DTF_RELEASE_SEG;
+               dmatab[i].dt_seg_base= base;
+               dmatab[i].dt_seg_size= size;
+               found_one= TRUE;
+       }
+
+       if (!found_one)
+               FREE_MEM(base, size);
+
+       msg->VMRD_FOUND = found_one;
+#endif
+
+       return;
+}
+
+/*===========================================================================*
+ *                             do_allocmem                                  *
+ *===========================================================================*/
+PUBLIC int do_allocmem(message *m)
+{
+       phys_clicks mem;
+
+       if((mem=ALLOC_MEM((phys_clicks) m->VMAM_CLICKS, PAF_CLEAR)) == NO_MEM) {
+               return ENOMEM;
+       }
+
+       m->VMAM_MEMBASE = mem;
+
+       printf("VM: do_allocmem: 0x%lx clicks OK at 0x%lx\n", m->VMAM_CLICKS, mem);
+
+       return OK;
+}
+
diff --git a/servers/vm/asynsend.c b/servers/vm/asynsend.c
new file mode 100644 (file)
index 0000000..19e0419
--- /dev/null
@@ -0,0 +1,67 @@
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+#include <errno.h>
+#include <string.h>
+#include <env.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "proto.h"
+#include "util.h"
+
+#define SENDSLOTS _NR_PROCS
+
+PRIVATE asynmsg_t msgtable[SENDSLOTS];
+PRIVATE size_t msgtable_n= SENDSLOTS;
+
+PUBLIC int asynsend(dst, mp)
+endpoint_t dst;
+message *mp;
+{
+        int i;
+        unsigned flags;
+
+        /* Find slot in table */
+        for (i= 0; i<msgtable_n; i++)
+        {
+                flags= msgtable[i].flags;
+                if ((flags & (AMF_VALID|AMF_DONE)) == (AMF_VALID|AMF_DONE))
+                {
+                        if (msgtable[i].result != OK)
+                        {
+                                printf(
+                      "VM: asynsend: found completed entry %d with error %d\n",
+                                        i, msgtable[i].result);
+                        }
+                        break;
+                }
+                if (flags == AMF_EMPTY)
+                        break;
+        }
+        if (i >= msgtable_n)
+                vm_panic("asynsend: should resize table", i);
+        msgtable[i].dst= dst;
+        msgtable[i].msg= *mp;
+        msgtable[i].flags= AMF_VALID;   /* Has to be last. The kernel
+                                         * scans this table while we are
+                                         * sleeping.
+                                         */
+
+        /* Tell the kernel to rescan the table */
+        return senda(msgtable, msgtable_n);
+}
+
diff --git a/servers/vm/break.c b/servers/vm/break.c
new file mode 100644 (file)
index 0000000..0c68222
--- /dev/null
@@ -0,0 +1,179 @@
+/* The MINIX model of memory allocation reserves a fixed amount of memory for
+ * the combined text, data, and stack segments.  The amount used for a child
+ * process created by FORK is the same as the parent had.  If the child does
+ * an EXEC later, the new size is taken from the header of the file EXEC'ed.
+ *
+ * The layout in memory consists of the text segment, followed by the data
+ * segment, followed by a gap (unused memory), followed by the stack segment.
+ * The data segment grows upward and the stack grows downward, so each can
+ * take memory from the gap.  If they meet, the process must be killed.  The
+ * procedures in this file deal with the growth of the data and stack segments.
+ *
+ * The entry points into this file are:
+ *   do_brk:      BRK/SBRK system calls to grow or shrink the data segment
+ *   adjust:      see if a proposed segment adjustment is allowed
+ */
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+#include <errno.h>
+#include <env.h>
+
+#include "glo.h"
+#include "vm.h"
+#include "proto.h"
+#include "util.h"
+
+#define DATA_CHANGED       1    /* flag value when data segment size changed */
+#define STACK_CHANGED      2    /* flag value when stack size changed */
+
+/*===========================================================================*
+ *                             do_brk                                       *
+ *===========================================================================*/
+PUBLIC int do_brk(message *msg)
+{
+/* Perform the brk(addr) system call.
+ * The parameter, 'addr' is the new virtual address in D space.
+ */
+       int proc;
+
+       if(vm_isokendpt(msg->VMB_ENDPOINT, &proc) != OK) {
+               printf("VM: bogus endpoint VM_BRK %d\n", msg->VMB_ENDPOINT);
+               return EINVAL;
+       }
+
+       return real_brk(&vmproc[proc], (vir_bytes) msg->VMB_ADDR);
+}
+
+/*===========================================================================*
+ *                             adjust                                       *
+ *===========================================================================*/
+PUBLIC int adjust(rmp, data_clicks, sp)
+struct vmproc *rmp;            /* whose memory is being adjusted? */
+vir_clicks data_clicks;                /* how big is data segment to become? */
+vir_bytes sp;                  /* new value of sp */
+{
+/* See if data and stack segments can coexist, adjusting them if need be.
+ * Memory is never allocated or freed.  Instead it is added or removed from the
+ * gap between data segment and stack segment.  If the gap size becomes
+ * negative, the adjustment of data or stack fails and ENOMEM is returned.
+ */
+
+  register struct mem_map *mem_sp, *mem_dp;
+  vir_clicks sp_click, gap_base, sp_lower, old_clicks;
+  int changed, r;
+  long base_of_stack, sp_delta;        /* longs avoid certain problems */
+
+  mem_dp = &rmp->vm_arch.vm_seg[D];    /* pointer to data segment map */
+  mem_sp = &rmp->vm_arch.vm_seg[S];    /* pointer to stack segment map */
+  changed = 0;                 /* set when either segment changed */
+
+  /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
+  base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
+  sp_click = sp >> CLICK_SHIFT;        /* click containing sp */
+  if (sp_click >= base_of_stack)
+  {
+       return(ENOMEM); /* sp too high */
+  }
+
+  /* Compute size of gap between stack and data segments. */
+  sp_delta = (long) mem_sp->mem_vir - (long) sp_click;
+  sp_lower = (sp_delta > 0 ? sp_click : mem_sp->mem_vir);
+
+  /* Add a safety margin for future stack growth. Impossible to do right. */
+#define SAFETY_BYTES  (384 * sizeof(char *))
+#define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
+  gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
+  if (sp_lower < gap_base)
+  {
+       return(ENOMEM); /* data and stack collided */
+  }
+
+  /* Update data length (but not data orgin) on behalf of brk() system call. */
+  old_clicks = mem_dp->mem_len;
+  if (data_clicks != mem_dp->mem_len) {
+       mem_dp->mem_len = data_clicks;
+       changed |= DATA_CHANGED;
+  }
+
+  /* Update stack length and origin due to change in stack pointer. */
+  if (sp_delta > 0) {
+       mem_sp->mem_vir -= sp_delta;
+       mem_sp->mem_phys -= sp_delta;
+       mem_sp->mem_len += sp_delta;
+       changed |= STACK_CHANGED;
+  }
+
+  /* Do the new data and stack segment sizes fit in the address space? */
+  r = (rmp->vm_arch.vm_seg[D].mem_vir + rmp->vm_arch.vm_seg[D].mem_len > 
+          rmp->vm_arch.vm_seg[S].mem_vir) ? ENOMEM : OK;
+
+  if(r == OK && (rmp->vm_flags & VMF_HASPT) &&
+     rmp->vm_endpoint != VM_PROC_NR) {
+       vm_assert(rmp->vm_heap);
+       if(old_clicks < data_clicks) {
+               vir_bytes more;
+               more = (data_clicks - old_clicks) << CLICK_SHIFT;
+               if(map_region_extend(rmp->vm_heap, more) != OK) {
+                       printf("VM: brk: map_region_extend failed\n");
+                       return ENOMEM;
+               }
+       } else if(old_clicks > data_clicks) {
+               vir_bytes less;
+               less = (old_clicks - data_clicks) << CLICK_SHIFT;
+               if(map_region_shrink(rmp->vm_heap, less) != OK) {
+                       printf("VM: brk: map_region_shrink failed\n");
+                       return ENOMEM;
+               }
+       }
+  }
+
+  if (r == OK)
+       return(OK);
+
+  /* New sizes don't fit or require too many page/segment registers. Restore.*/
+  if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks;
+  if (changed & STACK_CHANGED) {
+       mem_sp->mem_vir += sp_delta;
+       mem_sp->mem_phys += sp_delta;
+       mem_sp->mem_len -= sp_delta;
+  }
+  return(ENOMEM);
+}
+
+/*===========================================================================*
+ *                             real_brk                                     *
+ *===========================================================================*/
+PUBLIC int real_brk(vmp, v)
+struct vmproc *vmp;
+vir_bytes v;
+{
+       vir_bytes new_sp;
+       vir_clicks new_clicks;
+       int r;
+
+       new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT);
+       if (new_clicks < vmp->vm_arch.vm_seg[D].mem_vir) {
+               printf("VM: real_brk failed because new_clicks too high: %d\n",
+                       new_clicks);
+               return(ENOMEM);
+       }
+       new_clicks -= vmp->vm_arch.vm_seg[D].mem_vir;
+       if ((r=get_stack_ptr(vmp->vm_endpoint, &new_sp)) != OK)
+               vm_panic("couldn't get stack pointer", r);
+       r = adjust(vmp, new_clicks, new_sp);
+       return r;
+}
diff --git a/servers/vm/exec.c b/servers/vm/exec.c
new file mode 100644 (file)
index 0000000..44649d5
--- /dev/null
@@ -0,0 +1,413 @@
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+#include <minix/const.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <env.h>
+#include <pagetable.h>
+
+#include "glo.h"
+#include "proto.h"
+#include "util.h"
+#include "vm.h"
+#include "region.h"
+#include "sanitycheck.h"
+
+#include "memory.h"
+
+FORWARD _PROTOTYPE( int new_mem, (struct vmproc *vmp, struct vmproc *sh_vmp,
+       vir_bytes text_bytes, vir_bytes data_bytes, vir_bytes bss_bytes,
+       vir_bytes stk_bytes, phys_bytes tot_bytes)      );
+FORWARD _PROTOTYPE( u32_t find_kernel_top, (void));
+
+/*===========================================================================*
+ *                              find_share                                   *
+ *===========================================================================*/
+PUBLIC struct vmproc *find_share(vmp_ign, ino, dev, ctime)
+struct vmproc *vmp_ign;         /* process that should not be looked at */
+ino_t ino;                      /* parameters that uniquely identify a file */
+dev_t dev;
+time_t ctime;
+{
+/* Look for a process that is the file <ino, dev, ctime> in execution.  Don't
+ * accidentally "find" vmp_ign, because it is the process on whose behalf this
+ * call is made.
+ */
+  struct vmproc *vmp;
+  for (vmp = &vmproc[0]; vmp < &vmproc[NR_PROCS]; vmp++) {
+        if (!(vmp->vm_flags & VMF_INUSE)) continue;
+        if (!(vmp->vm_flags & VMF_SEPARATE)) continue;
+        if (vmp->vm_flags & VMF_HASPT) continue;
+        if (vmp == vmp_ign) continue;
+        if (vmp->vm_ino != ino) continue;
+        if (vmp->vm_dev != dev) continue;
+        if (vmp->vm_ctime != ctime) continue;
+        return vmp;
+  }
+  return(NULL);
+}
+
+
+/*===========================================================================*
+ *                             exec_newmem                                  *
+ *===========================================================================*/
+PUBLIC int do_exec_newmem(message *msg)
+{
+       int r, proc_e, proc_n;
+       vir_bytes stack_top;
+       vir_clicks tc, dc, sc, totc, dvir, s_vir;
+       struct vmproc *vmp, *sh_mp;
+       char *ptr;
+       struct exec_newmem args;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       proc_e= msg->VMEN_ENDPOINT;
+       if (vm_isokendpt(proc_e, &proc_n) != OK)
+       {
+               printf("VM:exec_newmem: bad endpoint %d from %d\n",
+                       proc_e, msg->m_source);
+               return ESRCH;
+       }
+       vmp= &vmproc[proc_n];
+       ptr= msg->VMEN_ARGSPTR;
+
+       if(msg->VMEN_ARGSSIZE != sizeof(args)) {
+               printf("VM:exec_newmem: args size %d != %ld\n",
+                       msg->VMEN_ARGSSIZE, sizeof(args));
+               return EINVAL;
+       }
+SANITYCHECK(SCL_DETAIL);
+
+       r= sys_datacopy(msg->m_source, (vir_bytes)ptr,
+               SELF, (vir_bytes)&args, sizeof(args));
+       if (r != OK)
+               vm_panic("exec_newmem: sys_datacopy failed", r);
+
+       /* Check to see if segment sizes are feasible. */
+       tc = ((unsigned long) args.text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+       dc = (args.data_bytes+args.bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+       totc = (args.tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+       sc = (args.args_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+       if (dc >= totc) return(ENOEXEC); /* stack must be at least 1 click */
+
+       dvir = (args.sep_id ? 0 : tc);
+       s_vir = dvir + (totc - sc);
+       r = (dvir + dc > s_vir) ? ENOMEM : OK;
+       if (r != OK)
+               return r;
+
+       /* Can the process' text be shared with that of one already running? */
+       if(!vm_paged) {
+               sh_mp = find_share(vmp, args.st_ino, args.st_dev, args.st_ctime);
+       } else {
+               sh_mp = NULL;
+       }
+
+       /* Allocate new memory and release old memory.  Fix map and tell
+        * kernel.
+        */
+       r = new_mem(vmp, sh_mp, args.text_bytes, args.data_bytes,
+               args.bss_bytes, args.args_bytes, args.tot_bytes);
+       if (r != OK) return(r);
+
+       /* Save file identification to allow it to be shared. */
+       vmp->vm_ino = args.st_ino;
+       vmp->vm_dev = args.st_dev;
+       vmp->vm_ctime = args.st_ctime;
+
+       stack_top= ((vir_bytes)vmp->vm_arch.vm_seg[S].mem_vir << CLICK_SHIFT) +
+               ((vir_bytes)vmp->vm_arch.vm_seg[S].mem_len << CLICK_SHIFT);
+
+       /* set/clear separate I&D flag */
+       if (args.sep_id)
+               vmp->vm_flags |= VMF_SEPARATE;  
+       else
+               vmp->vm_flags &= ~VMF_SEPARATE;
+
+       
+       msg->VMEN_STACK_TOP = (void *) stack_top;
+       msg->VMEN_FLAGS = 0;
+       if (!sh_mp)                      /* Load text if sh_mp = NULL */
+               msg->VMEN_FLAGS |= EXC_NM_RF_LOAD_TEXT;
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             new_mem                                      *
+ *===========================================================================*/
+PRIVATE int new_mem(rmp, sh_mp, text_bytes, data_bytes,
+       bss_bytes,stk_bytes,tot_bytes)
+struct vmproc *rmp;            /* process to get a new memory map */
+struct vmproc *sh_mp;          /* text can be shared with this process */
+vir_bytes text_bytes;          /* text segment size in bytes */
+vir_bytes data_bytes;          /* size of initialized data in bytes */
+vir_bytes bss_bytes;           /* size of bss in bytes */
+vir_bytes stk_bytes;           /* size of initial stack segment in bytes */
+phys_bytes tot_bytes;          /* total memory to allocate, including gap */
+{
+/* Allocate new memory and release the old memory.  Change the map and report
+ * the new map to the kernel.  Zero the new core image's bss, gap and stack.
+ */
+
+  vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
+  phys_bytes bytes, base, bss_offset;
+  int s, r2;
+  static u32_t kernel_top = 0;
+
+  SANITYCHECK(SCL_FUNCTIONS);
+
+  /* No need to allocate text if it can be shared. */
+  if (sh_mp != NULL) {
+       text_bytes = 0;
+       vm_assert(!vm_paged);
+  }
+
+  /* Acquire the new memory.  Each of the 4 parts: text, (data+bss), gap,
+   * and stack occupies an integral number of clicks, starting at click
+   * boundary.  The data and bss parts are run together with no space.
+   */
+  text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
+  gap_clicks = tot_clicks - data_clicks - stack_clicks;
+  if ( (int) gap_clicks < 0) return(ENOMEM);
+
+SANITYCHECK(SCL_DETAIL);
+
+
+  /* We've got memory for the new core image.  Release the old one. */
+
+  if(rmp->vm_flags & VMF_HASPT) {
+       /* Free page table and memory allocated by pagetable functions. */
+       rmp->vm_flags &= ~VMF_HASPT;
+       free_proc(rmp);
+  } else {
+
+       if (find_share(rmp, rmp->vm_ino, rmp->vm_dev, rmp->vm_ctime) == NULL) {
+               /* No other process shares the text segment, so free it. */
+               FREE_MEM(rmp->vm_arch.vm_seg[T].mem_phys, rmp->vm_arch.vm_seg[T].mem_len);
+       }
+
+       /* Free the data and stack segments. */
+       FREE_MEM(rmp->vm_arch.vm_seg[D].mem_phys,
+               rmp->vm_arch.vm_seg[S].mem_vir
+               + rmp->vm_arch.vm_seg[S].mem_len
+               - rmp->vm_arch.vm_seg[D].mem_vir);
+  }
+
+  /* We have now passed the point of no return.  The old core image has been
+   * forever lost, memory for a new core image has been allocated.  Set up
+   * and report new map.
+   */
+
+  if(vm_paged) {
+       vir_bytes hole_clicks;
+
+       if(pt_new(&rmp->vm_pt) != OK)
+               vm_panic("exec_newmem: no new pagetable", NO_NUM);
+       SANITYCHECK(SCL_DETAIL);
+
+       if(!map_proc_kernel(rmp)) {
+               printf("VM: exec: map_proc_kernel failed\n");
+               return ENOMEM;
+       }
+
+       if(!kernel_top)
+               kernel_top = find_kernel_top();
+
+       /* Place text at kernel top. */
+       rmp->vm_arch.vm_seg[T].mem_phys = kernel_top;
+       rmp->vm_arch.vm_seg[T].mem_vir = 0;
+       rmp->vm_arch.vm_seg[T].mem_len = text_clicks;
+
+       rmp->vm_offset = CLICK2ABS(kernel_top);
+
+       vm_assert(!sh_mp);
+       /* page mapping flags for code */
+#define TEXTFLAGS (PTF_PRESENT | PTF_USER | PTF_WRITE)
+       SANITYCHECK(SCL_DETAIL);
+       if(text_clicks > 0) {
+               if(!map_page_region(rmp, CLICK2ABS(kernel_top), 0,
+                 CLICK2ABS(rmp->vm_arch.vm_seg[T].mem_len), 0,
+                 VR_ANON | VR_WRITABLE, 0)) {
+                       SANITYCHECK(SCL_DETAIL);
+                       printf("VM: map_page_region failed (text)\n");
+                       return(ENOMEM);
+               }
+               SANITYCHECK(SCL_DETAIL);
+       }
+       SANITYCHECK(SCL_DETAIL);
+
+       /* Allocate memory for data (including bss, but not including gap
+        * or stack), make sure it's cleared, and map it in after text
+        * (if any).
+        */
+       if(!(rmp->vm_heap = map_page_region(rmp,
+         CLICK2ABS(kernel_top + text_clicks), 0,
+         CLICK2ABS(data_clicks), 0, VR_ANON | VR_WRITABLE, 0))) {
+               printf("VM: exec: map_page_region for data failed\n");
+               return ENOMEM;
+       }
+
+       map_region_set_tag(rmp->vm_heap, VRT_HEAP);
+
+       /* How many address space clicks between end of data
+        * and start of stack?
+        * VM_STACKTOP is the first address after the stack, as addressed
+        * from within the user process.
+        */
+       hole_clicks = VM_STACKTOP >> CLICK_SHIFT;
+       hole_clicks -= data_clicks + stack_clicks + gap_clicks;
+
+       if(!map_page_region(rmp,
+         CLICK2ABS(kernel_top + text_clicks + data_clicks + hole_clicks),
+         0, CLICK2ABS(stack_clicks+gap_clicks), 0,
+         VR_ANON | VR_WRITABLE, 0) != OK) {
+               vm_panic("map_page_region failed for stack", NO_NUM);
+       }
+
+       rmp->vm_arch.vm_seg[D].mem_phys = kernel_top + text_clicks;
+       rmp->vm_arch.vm_seg[D].mem_vir = 0;
+       rmp->vm_arch.vm_seg[D].mem_len = data_clicks;
+
+
+       rmp->vm_arch.vm_seg[S].mem_phys = kernel_top +
+               text_clicks + data_clicks + gap_clicks + hole_clicks;
+       rmp->vm_arch.vm_seg[S].mem_vir = data_clicks + gap_clicks + hole_clicks;
+       
+       /* Pretend the stack is the full size of the data segment, so 
+        * we get a full-sized data segment, up to VM_DATATOP.
+        * After sys_newmap(),, change the stack to what we know the
+        * stack to be (up to VM_STACKTOP).
+        */
+       rmp->vm_arch.vm_seg[S].mem_len = (VM_DATATOP >> CLICK_SHIFT) -
+               rmp->vm_arch.vm_seg[S].mem_vir - kernel_top - text_clicks;
+
+       /* Where are we allowed to start using the rest of the virtual
+        * address space?
+        */
+       rmp->vm_stacktop = VM_STACKTOP;
+
+       /* What is the final size of the data segment in bytes? */
+       rmp->vm_arch.vm_data_top = 
+               (rmp->vm_arch.vm_seg[S].mem_vir + 
+               rmp->vm_arch.vm_seg[S].mem_len) << CLICK_SHIFT;
+
+       rmp->vm_flags |= VMF_HASPT;
+
+       if((s=sys_newmap(rmp->vm_endpoint, rmp->vm_arch.vm_seg)) != OK) {
+               vm_panic("sys_newmap (vm) failed", s);
+       }
+
+
+       /* This is the real stack clicks. */
+       rmp->vm_arch.vm_seg[S].mem_len = stack_clicks;
+
+  } else {
+       phys_clicks new_base;
+
+       new_base = ALLOC_MEM(text_clicks + tot_clicks, 0);
+       if (new_base == NO_MEM) return(ENOMEM);
+
+       if (sh_mp != NULL) {
+               /* Share the text segment. */
+               rmp->vm_arch.vm_seg[T] = sh_mp->vm_arch.vm_seg[T];
+       } else {
+               rmp->vm_arch.vm_seg[T].mem_phys = new_base;
+               rmp->vm_arch.vm_seg[T].mem_vir = 0;
+               rmp->vm_arch.vm_seg[T].mem_len = text_clicks;
+       
+               if (text_clicks > 0)
+               {
+                       /* Zero the last click of the text segment. Otherwise the
+                        * part of that click may remain unchanged.
+                        */
+                       base = (phys_bytes)(new_base+text_clicks-1) << CLICK_SHIFT;
+                       if ((s= sys_memset(0, base, CLICK_SIZE)) != OK)
+                               vm_panic("new_mem: sys_memset failed", s);
+               }
+       }
+
+       /* No paging stuff. */
+       rmp->vm_flags &= ~VMF_HASPT;
+       rmp->vm_regions = NULL;
+
+         rmp->vm_arch.vm_seg[D].mem_phys = new_base + text_clicks;
+         rmp->vm_arch.vm_seg[D].mem_vir = 0;
+         rmp->vm_arch.vm_seg[D].mem_len = data_clicks;
+         rmp->vm_arch.vm_seg[S].mem_phys = rmp->vm_arch.vm_seg[D].mem_phys +
+               data_clicks + gap_clicks;
+         rmp->vm_arch.vm_seg[S].mem_vir = rmp->vm_arch.vm_seg[D].mem_vir +
+               data_clicks + gap_clicks;
+         rmp->vm_arch.vm_seg[S].mem_len = stack_clicks;
+       rmp->vm_stacktop =
+               CLICK2ABS(rmp->vm_arch.vm_seg[S].mem_vir +
+                       rmp->vm_arch.vm_seg[S].mem_len);
+
+       rmp->vm_arch.vm_data_top = 
+               (rmp->vm_arch.vm_seg[S].mem_vir + 
+               rmp->vm_arch.vm_seg[S].mem_len) << CLICK_SHIFT;
+
+         if((r2=sys_newmap(rmp->vm_endpoint, rmp->vm_arch.vm_seg)) != OK) {
+               /* report new map to the kernel */
+               vm_panic("sys_newmap failed", r2);
+         }
+
+         /* Zero the bss, gap, and stack segment. */
+         bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
+         base = (phys_bytes) rmp->vm_arch.vm_seg[D].mem_phys << CLICK_SHIFT;
+         bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT;
+         base += bss_offset;
+         bytes -= bss_offset;
+
+         if ((s=sys_memset(0, base, bytes)) != OK) {
+               vm_panic("new_mem can't zero", s);
+         }
+  }
+
+  /* Whether vm_pt is NULL or a new pagetable, tell kernel about it. */
+  if((s=pt_bind(&rmp->vm_pt, rmp)) != OK)
+       vm_panic("exec_newmem: pt_bind failed", s);
+
+SANITYCHECK(SCL_FUNCTIONS);
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *                             find_kernel_top                              *
+ *===========================================================================*/
+PRIVATE u32_t find_kernel_top(void)
+{
+/* Find out where the kernel is, so we know where to start mapping
+ * user processes.
+ */
+       u32_t kernel_top = 0;
+#define MEMTOP(v, i) \
+  (vmproc[v].vm_arch.vm_seg[i].mem_phys + vmproc[v].vm_arch.vm_seg[i].mem_len)
+       vm_assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE);
+       kernel_top = MEMTOP(VMP_SYSTEM, T);
+       kernel_top = MAX(kernel_top, MEMTOP(VMP_SYSTEM, D));
+       kernel_top = MAX(kernel_top, MEMTOP(VMP_SYSTEM, S));
+       vm_assert(kernel_top);
+
+       return kernel_top;
+}
+
diff --git a/servers/vm/exit.c b/servers/vm/exit.c
new file mode 100644 (file)
index 0000000..9c80a9d
--- /dev/null
@@ -0,0 +1,118 @@
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+#include <errno.h>
+#include <env.h>
+
+#include "glo.h"
+#include "proto.h"
+#include "util.h"
+#include "sanitycheck.h"
+
+PUBLIC void free_proc(struct vmproc *vmp)
+{
+       vmp->vm_flags &= ~VMF_HASPT;
+       pt_free(&vmp->vm_pt);
+       map_free_proc(vmp);
+       vmp->vm_regions = NULL;
+#if VMSTATS
+       vmp->vm_bytecopies = 0;
+#endif
+}
+
+PUBLIC void clear_proc(struct vmproc *vmp)
+{
+       vmp->vm_regions = NULL;
+       vmp->vm_callback = NULL;        /* No pending vfs callback. */
+       vmp->vm_flags = 0;              /* Clear INUSE, so slot is free. */
+       vmp->vm_count = 0;
+       vmp->vm_heap = NULL;
+#if VMSTATS
+       vmp->vm_bytecopies = 0;
+#endif
+}
+
+/*===========================================================================*
+ *                             do_exit                                      *
+ *===========================================================================*/
+PUBLIC int do_exit(message *msg)
+{
+       int proc;
+       struct vmproc *vmp;
+
+SANITYCHECK(SCL_FUNCTIONS);
+
+       if(vm_isokendpt(msg->VME_ENDPOINT, &proc) != OK) {
+               printf("VM: bogus endpoint VM_EXIT %d\n", msg->VME_ENDPOINT);
+               return EINVAL;
+       }
+       vmp = &vmproc[proc];
+       if(!(vmp->vm_flags & VMF_EXITING)) {
+               printf("VM: unannounced VM_EXIT %d\n", msg->VME_ENDPOINT);
+               return EINVAL;
+       }
+
+       if(vmp->vm_flags & VMF_HAS_DMA) {
+               release_dma(vmp);
+       } else if(vmp->vm_flags & VMF_HASPT) {
+               /* Free pagetable and pages allocated by pt code. */
+SANITYCHECK(SCL_DETAIL);
+               free_proc(vmp);
+SANITYCHECK(SCL_DETAIL);
+       } else {
+               /* Free the data and stack segments. */
+               FREE_MEM(vmp->vm_arch.vm_seg[D].mem_phys,
+                       vmp->vm_arch.vm_seg[S].mem_vir +
+                       vmp->vm_arch.vm_seg[S].mem_len -
+                       vmp->vm_arch.vm_seg[D].mem_vir);
+
+               if (find_share(vmp, vmp->vm_ino, vmp->vm_dev, vmp->vm_ctime) == NULL) {
+                       /* No other process shares the text segment,
+                        * so free it.
+                        */
+                       FREE_MEM(vmp->vm_arch.vm_seg[T].mem_phys,
+                       vmp->vm_arch.vm_seg[T].mem_len);
+               }
+       }
+SANITYCHECK(SCL_DETAIL);
+
+       /* Reset process slot fields. */
+       clear_proc(vmp);
+
+SANITYCHECK(SCL_FUNCTIONS);
+       return OK;
+}
+
+/*===========================================================================*
+ *                             do_willexit                                  *
+ *===========================================================================*/
+PUBLIC int do_willexit(message *msg)
+{
+       int proc;
+       struct vmproc *vmp;
+
+       if(vm_isokendpt(msg->VMWE_ENDPOINT, &proc) != OK) {
+               printf("VM: bogus endpoint VM_EXITING %d\n",
+                       msg->VMWE_ENDPOINT);
+               return EINVAL;
+       }
+       vmp = &vmproc[proc];
+
+       vmp->vm_flags |= VMF_EXITING;
+
+       return OK;
+}
+
diff --git a/servers/vm/fork.c b/servers/vm/fork.c
new file mode 100644 (file)
index 0000000..8a5aa6a
--- /dev/null
@@ -0,0 +1,145 @@
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+#include <errno.h>
+#include <env.h>
+
+#include "glo.h"
+#include "vm.h"
+#include "proto.h"
+#include "util.h"
+#include "sanitycheck.h"
+#include "region.h"
+
+/*===========================================================================*
+ *                             do_fork                                      *
+ *===========================================================================*/
+PUBLIC int do_fork(message *msg)
+{
+  int r, proc, s, childproc, fullvm;
+  struct vmproc *vmp, *vmc;
+
+  SANITYCHECK(SCL_FUNCTIONS);
+
+  if(vm_isokendpt(msg->VMF_ENDPOINT, &proc) != OK) {
+       printf("VM: bogus endpoint VM_FORK %d\n", msg->VMF_ENDPOINT);
+  SANITYCHECK(SCL_FUNCTIONS);
+       return EINVAL;
+  }
+
+  childproc = msg->VMF_SLOTNO;
+  if(childproc < 0 || childproc >= NR_PROCS) {
+       printf("VM: bogus slotno VM_FORK %d\n", msg->VMF_SLOTNO);
+  SANITYCHECK(SCL_FUNCTIONS);
+       return EINVAL;
+  }
+
+  vmp = &vmproc[proc];         /* parent */
+  vmc = &vmproc[childproc];    /* child */
+
+  if(vmp->vm_flags & VMF_HAS_DMA) {
+       printf("VM: %d has DMA memory and may not fork\n", msg->VMF_ENDPOINT);
+       return EINVAL;
+  }
+
+  fullvm = vmp->vm_flags & VMF_HASPT;
+
+  /* The child is basically a copy of the parent. */
+  *vmc = *vmp;
+  vmc->vm_regions = NULL;
+  vmc->vm_endpoint = NONE;     /* In case someone tries to use it. */
+
+#if VMSTATS
+  vmc->vm_bytecopies = 0;
+#endif
+
+  if(fullvm) {
+       SANITYCHECK(SCL_DETAIL);
+
+       if(pt_new(&vmc->vm_pt) != OK) {
+               printf("VM: fork: pt_new failed\n");
+               return ENOMEM;
+       }
+
+       SANITYCHECK(SCL_DETAIL);
+
+       if(map_proc_copy(vmc, vmp) != OK) {
+               printf("VM: fork: map_proc_copy failed\n");
+               pt_free(&vmc->vm_pt);
+               return(ENOMEM);
+       }
+
+       if(vmp->vm_heap) {
+               vmc->vm_heap = map_region_lookup_tag(vmc, VRT_HEAP);
+               vm_assert(vmc->vm_heap);
+       }
+
+       SANITYCHECK(SCL_DETAIL);
+  } else {
+        phys_bytes prog_bytes, parent_abs, child_abs; /* Intel only */
+        phys_clicks prog_clicks, child_base;
+
+       /* Determine how much memory to allocate.  Only the data and stack
+        * need to be copied, because the text segment is either shared or
+        * of zero length.
+        */
+
+       prog_clicks = (phys_clicks) vmp->vm_arch.vm_seg[S].mem_len;
+       prog_clicks += (vmp->vm_arch.vm_seg[S].mem_vir - vmp->vm_arch.vm_seg[D].mem_vir);
+       prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT;
+       if ( (child_base = ALLOC_MEM(prog_clicks, 0)) == NO_MEM) {
+  SANITYCHECK(SCL_FUNCTIONS);
+               return(ENOMEM);
+       }
+
+       /* Create a copy of the parent's core image for the child. */
+       child_abs = (phys_bytes) child_base << CLICK_SHIFT;
+       parent_abs = (phys_bytes) vmp->vm_arch.vm_seg[D].mem_phys << CLICK_SHIFT;
+       s = sys_abscopy(parent_abs, child_abs, prog_bytes);
+       if (s < 0) vm_panic("do_fork can't copy", s);
+
+       /* A separate I&D child keeps the parents text segment.  The data and stack
+       * segments must refer to the new copy.
+       */
+       if (!(vmc->vm_flags & VMF_SEPARATE))
+               vmc->vm_arch.vm_seg[T].mem_phys = child_base;
+       vmc->vm_arch.vm_seg[D].mem_phys = child_base;
+       vmc->vm_arch.vm_seg[S].mem_phys = vmc->vm_arch.vm_seg[D].mem_phys +
+           (vmp->vm_arch.vm_seg[S].mem_vir - vmp->vm_arch.vm_seg[D].mem_vir);
+  }
+
+  /* Only inherit these flags. */
+  vmc->vm_flags &= (VMF_INUSE|VMF_SEPARATE|VMF_HASPT);
+
+  /* Tell kernel about the (now successful) FORK. */
+  if((r=sys_fork(vmp->vm_endpoint, childproc,
+       &vmc->vm_endpoint, vmc->vm_arch.vm_seg,
+       fullvm ? PFF_VMINHIBIT : 0)) != OK) {
+        vm_panic("do_fork can't sys_fork", r);
+  }
+
+  if(fullvm) {
+       if((r=pt_bind(&vmc->vm_pt, vmc)) != OK)
+               vm_panic("fork can't pt_bind", r);
+  }
+
+  /* Inform caller of new child endpoint. */
+  msg->VMF_CHILD_ENDPOINT = vmc->vm_endpoint;
+
+  SANITYCHECK(SCL_FUNCTIONS);
+  return OK;
+}
+
diff --git a/servers/vm/glo.h b/servers/vm/glo.h
new file mode 100644 (file)
index 0000000..3d5153b
--- /dev/null
@@ -0,0 +1,29 @@
+
+#include <minix/sys_config.h>
+#include <sys/stat.h>
+#include <a.out.h>
+#include <tools.h>
+
+#include "vm.h"
+#include "vmproc.h"
+
+#if _MAIN
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN struct vmproc vmproc[_NR_PROCS+1];
+
+#if SANITYCHECKS
+u32_t data1[200];
+#define CHECKADDR 0
+EXTERN long vm_sanitychecklevel;
+#endif
+
+int verbosealloc;
+
+#define VMP_SYSTEM     _NR_PROCS
+
+/* vm operation mode state and values */
+EXTERN long vm_paged;
+
diff --git a/servers/vm/i386/Makefile b/servers/vm/i386/Makefile
new file mode 100644 (file)
index 0000000..805296e
--- /dev/null
@@ -0,0 +1,19 @@
+
+include /etc/make.conf
+
+OBJ = vm.o pagetable.o arch_pagefaults.o util.o
+
+CPPFLAGS=-I../../../kernel/arch/$(ARCH)/include -I.
+CFLAGS = $(CPROFILE) $(CPPFLAGS)
+
+all:   $(OBJ)
+
+clean:
+       rm -f $(OBJ)
+
+depend: 
+       mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
diff --git a/servers/vm/i386/arch_pagefaults.c b/servers/vm/i386/arch_pagefaults.c
new file mode 100644 (file)
index 0000000..9ec3246
--- /dev/null
@@ -0,0 +1,38 @@
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+#include <minix/safecopies.h>
+
+#include <errno.h>
+#include <string.h>
+#include <env.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "../glo.h"
+#include "../proto.h"
+#include "../util.h"
+
+/*===========================================================================*
+ *                             arch_handle_pagefaults                       *
+ *===========================================================================*/
+PUBLIC int arch_get_pagefault(who, addr, err)
+endpoint_t *who;
+vir_bytes *addr;
+u32_t *err;
+{
+       return sys_vmctl_get_pagefault_i386(who, addr, err);
+}
+
diff --git a/servers/vm/i386/arch_vmproc.h b/servers/vm/i386/arch_vmproc.h
new file mode 100644 (file)
index 0000000..cab2803
--- /dev/null
@@ -0,0 +1,15 @@
+
+#include <archtypes.h>
+
+struct vm_arch {
+       struct mem_map  vm_seg[NR_LOCAL_SEGS];  /* text, data, stack */
+
+       /* vm_data_top points to top of data address space, as visible
+        * from user-space, in bytes.
+        * for segments processes this is the same 
+        * as the top of vm_seg[S] segment. for paged processes this
+        * can be much higher (so more memory is available above the
+        * stack).
+        */
+       u32_t           vm_data_top;    /* virtual process space in bytes */
+};
diff --git a/servers/vm/i386/memory.h b/servers/vm/i386/memory.h
new file mode 100644 (file)
index 0000000..b770aff
--- /dev/null
@@ -0,0 +1,25 @@
+#include <sys/vm_i386.h>
+
+/* As visible from the user space process, where is the top of the
+ * stack (first non-stack byte), when in paged mode?
+ */
+#define VM_STACKTOP     0x80000000
+
+/* And what is the highest addressable piece of memory, when in paged
+ * mode? Some data for kernel and stack are subtracted from this, the
+ * final results stored in bytes in arch.vm_data_top.
+ */
+#define VM_DATATOP     0xFFFFF000
+
+#define SLAB_PAGESIZE  I386_PAGE_SIZE
+#define VM_PAGE_SIZE   I386_PAGE_SIZE
+
+#define CLICKSPERPAGE (I386_PAGE_SIZE/CLICK_SIZE)
+
+/* Where is the kernel? */
+#define KERNEL_TEXT    CLICK2ABS(vmproc[VMP_SYSTEM].vm_arch.vm_seg[T].mem_phys)
+#define KERNEL_TEXT_LEN        CLICK2ABS(vmproc[VMP_SYSTEM].vm_arch.vm_seg[T].mem_len)
+#define KERNEL_DATA    CLICK2ABS(vmproc[VMP_SYSTEM].vm_arch.vm_seg[D].mem_phys)
+#define KERNEL_DATA_LEN        CLICK2ABS(vmproc[VMP_SYSTEM].vm_arch.vm_seg[D].mem_len \
+       + vmproc[VMP_SYSTEM].vm_arch.vm_seg[S].mem_len)
+
diff --git a/servers/vm/i386/pagefaults.h b/servers/vm/i386/pagefaults.h
new file mode 100644 (file)
index 0000000..d9aab9d
--- /dev/null
@@ -0,0 +1,13 @@
+
+#ifndef _PAGEFAULTS_H
+#define _PAGEFAULTS_H 1
+
+#include <sys/vm_i386.h>
+
+#define PFERR_NOPAGE(e)        (!((e) & I386_VM_PFE_P))
+#define PFERR_PROT(e)  (((e) & I386_VM_PFE_P))
+#define PFERR_WRITE(e) ((e) & I386_VM_PFE_W)
+#define PFERR_READ(e)  (!((e) & I386_VM_PFE_W))
+
+#endif
+
diff --git a/servers/vm/i386/pagetable.c b/servers/vm/i386/pagetable.c
new file mode 100644 (file)
index 0000000..e80a5e3
--- /dev/null
@@ -0,0 +1,944 @@
+
+#define _SYSTEM 1
+
+#define VERBOSE 0
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+#include <minix/safecopies.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <env.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "../proto.h"
+#include "../glo.h"
+#include "../util.h"
+#include "../vm.h"
+#include "../sanitycheck.h"
+
+#include "memory.h"
+
+/* Location in our virtual address space where we can map in 
+ * any physical page we want.
+*/
+static unsigned char *varmap = NULL;   /* Our address space. */
+static u32_t varmap_loc;               /* Our page table. */
+
+/* Our process table entry. */
+struct vmproc *vmp = &vmproc[VM_PROC_NR];
+
+/* Spare memory, ready to go after initialization, to avoid a
+ * circular dependency on allocating memory and writing it into VM's
+ * page table.
+ */
+#define SPAREPAGES 3
+static struct {
+       void *page;
+       u32_t phys;
+} sparepages[SPAREPAGES];
+
+/* Clicks must be pages, as
+ *  - they must be page aligned to map them
+ *  - they must be a multiple of the page size
+ *  - it's inconvenient to have them bigger than pages, because we often want
+ *    just one page
+ * May as well require them to be equal then.
+ */
+#if CLICK_SIZE != I386_PAGE_SIZE
+#error CLICK_SIZE must be page size.
+#endif
+
+/* Bytes of virtual address space one pde controls. */
+#define BYTESPERPDE (I386_VM_PT_ENTRIES * I386_PAGE_SIZE)
+
+/* Nevertheless, introduce these macros to make the code readable. */
+#define CLICK2PAGE(c) ((c) / CLICKSPERPAGE)
+
+#if SANITYCHECKS
+#define PT_SANE(p) { pt_sanitycheck((p), __FILE__, __LINE__); SANITYCHECK(SCL_DETAIL); }
+/*===========================================================================*
+ *                             pt_sanitycheck                               *
+ *===========================================================================*/
+PUBLIC void pt_sanitycheck(pt_t *pt, char *file, int line)
+{
+/* Basic pt sanity check. */
+       int i;
+
+       MYASSERT(pt);
+       MYASSERT(pt->pt_dir);
+       MYASSERT(pt->pt_dir_phys);
+
+       for(i = 0; i < I386_VM_DIR_ENTRIES; i++) {
+               if(pt->pt_pt[i]) {
+                       MYASSERT(pt->pt_dir[i] & I386_VM_PRESENT);
+               } else {
+                       MYASSERT(!(pt->pt_dir[i] & I386_VM_PRESENT));
+               }
+       }
+}
+#else
+#define PT_SANE(p)
+#endif
+
+/*===========================================================================*
+ *                             aalloc                                       *
+ *===========================================================================*/
+PRIVATE void *aalloc(size_t bytes)
+{
+/* Page-aligned malloc(). only used if vm_allocpages can't be used.  */
+       u32_t b;
+
+       b = (u32_t) malloc(I386_PAGE_SIZE + bytes);
+       if(!b) vm_panic("aalloc: out of memory", bytes);
+       b += I386_PAGE_SIZE - (b % I386_PAGE_SIZE);
+
+       return (void *) b;
+}
+
+/*===========================================================================*
+ *                             findhole                                     *
+ *===========================================================================*/
+PRIVATE u32_t findhole(pt_t *pt, u32_t virbytes, u32_t vmin, u32_t vmax)
+{
+/* Find a space in the virtual address space of pageteble 'pt',
+ * between page-aligned BYTE offsets vmin and vmax, to fit
+ * 'virbytes' in. Return byte offset.
+ *
+ * As a simple way to speed up the search a bit, we start searching
+ * after the location we found the previous hole, if that's in range.
+ * If that's not in range (or if that doesn't work), search the entire
+ * range (as well). try_restart controls whether we have to restart
+ * the search if it fails. (Just once of course.)
+ */
+       u32_t freeneeded, freefound = 0, freestart = 0, curv;
+       int pde = 0, try_restart;
+
+       /* Input sanity check. */
+       vm_assert(vmin + virbytes >= vmin);
+       vm_assert(vmax >= vmin + virbytes);
+       vm_assert((virbytes % I386_PAGE_SIZE) == 0);
+       vm_assert((vmin % I386_PAGE_SIZE) == 0);
+       vm_assert((vmax % I386_PAGE_SIZE) == 0);
+
+       /* How many pages do we need? */
+       freeneeded = virbytes / I386_PAGE_SIZE;
+
+       if(pt->pt_virtop >= vmin && pt->pt_virtop <= vmax - virbytes) {
+               curv = pt->pt_virtop;
+               try_restart = 1;
+       } else {
+               curv = vmin;
+               try_restart = 0;
+       }
+
+
+       /* Start looking for a consecutive block of free pages
+        * starting at vmin.
+        */
+       for(freestart = curv; curv < vmax; ) {
+               int pte;
+               pde = I386_VM_PDE(curv);
+               pte = I386_VM_PTE(curv);
+
+               if(!(pt->pt_dir[pde] & I386_VM_PRESENT)) {
+                       int rempte;
+                       rempte = I386_VM_PT_ENTRIES - pte;
+                       freefound += rempte;
+                       curv += rempte * I386_PAGE_SIZE;
+               } else {
+                       if(pt->pt_pt[pde][pte] & I386_VM_PRESENT) {
+                               freefound = 0;
+                               freestart = curv + I386_PAGE_SIZE;
+                       } else {
+                               freefound++;
+                       }
+                       curv+=I386_PAGE_SIZE;
+               }
+
+               if(freefound >= freeneeded) {
+                       u32_t v;
+                       v = freestart;
+                       vm_assert(v != NO_MEM);
+                       vm_assert(v >= vmin);
+                       vm_assert(v < vmax);
+
+                       /* Next time, start looking here. */
+                       pt->pt_virtop = v + virbytes;
+
+                       return v;
+               }
+
+               if(curv >= vmax && try_restart) {
+                       curv = vmin;
+                       try_restart = 0;
+               }
+       }
+
+       printf("VM: out of virtual address space in a process\n");
+
+       return NO_MEM;
+}
+
+/*===========================================================================*
+ *                             vm_freepages                                 *
+ *===========================================================================*/
+PRIVATE void vm_freepages(vir_bytes vir, vir_bytes phys, int pages, int reason)
+{
+       vm_assert(reason >= 0 && reason < VMP_CATEGORIES);
+       if(vir >= vmp->vm_stacktop) {
+               vm_assert(!(vir % I386_PAGE_SIZE)); 
+               vm_assert(!(phys % I386_PAGE_SIZE)); 
+               FREE_MEM(ABS2CLICK(phys), pages);
+               if(pt_writemap(&vmp->vm_pt,
+                       vir + CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys),
+                       0, pages*I386_PAGE_SIZE, 0, WMF_OVERWRITE) != OK)
+                               vm_panic("vm_freepages: pt_writemap failed",
+                                       NO_NUM);
+       } else {
+               printf("VM: vm_freepages not freeing VM heap pages (%d)\n",
+                       pages);
+       }
+}
+
+/*===========================================================================*
+ *                             vm_getsparepage                              *
+ *===========================================================================*/
+PRIVATE void *vm_getsparepage(u32_t *phys)
+{
+       int s;
+       for(s = 0; s < SPAREPAGES; s++) {
+               if(sparepages[s].page) {
+                       void *sp;
+                       sp = sparepages[s].page;
+                       *phys = sparepages[s].phys;
+                       sparepages[s].page = NULL;
+                       return sp;
+               }
+       }
+       vm_panic("VM: out of spare pages", NO_NUM);
+       return NULL;
+}
+
+/*===========================================================================*
+ *                             vm_checkspares                               *
+ *===========================================================================*/
+PRIVATE void *vm_checkspares(void)
+{
+       int s, n = 0;
+       static int total = 0, worst = 0;
+       for(s = 0; s < SPAREPAGES; s++)
+           if(!sparepages[s].page) {
+               n++;
+               sparepages[s].page = vm_allocpages(&sparepages[s].phys, 1,
+                       VMP_SPARE);
+       }
+       if(worst < n) worst = n;
+       total += n;
+#if 0
+       if(n > 0)
+               printf("VM: made %d spares, total %d, worst %d\n", n, total, worst);
+#endif
+       return NULL;
+}
+
+/*===========================================================================*
+ *                             vm_allocpages                                *
+ *===========================================================================*/
+PUBLIC void *vm_allocpages(phys_bytes *phys, int pages, int reason)
+{
+/* Allocate a number of pages for use by VM itself. */
+       phys_bytes newpage;
+       vir_bytes loc;
+       pt_t *pt;
+       int r;
+       vir_bytes bytes = pages * I386_PAGE_SIZE;
+       static int level = 0;
+#define MAXDEPTH 10
+       static int reasons[MAXDEPTH];
+
+       pt = &vmp->vm_pt;
+       vm_assert(reason >= 0 && reason < VMP_CATEGORIES);
+       vm_assert(pages > 0);
+
+       reasons[level++] = reason;
+
+       vm_assert(level >= 1);
+       vm_assert(level <= 2);
+
+       if(level > 1 || !(vmp->vm_flags & VMF_HASPT)) {
+               int r;
+               void *s;
+               vm_assert(pages == 1);
+               s=vm_getsparepage(phys);
+               level--;
+               return s;
+       }
+
+       /* VM does have a pagetable, so get a page and map it in there.
+        * Where in our virtual address space can we put it?
+        */
+       loc = findhole(pt, I386_PAGE_SIZE * pages,
+               CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys) + vmp->vm_stacktop,
+               vmp->vm_arch.vm_data_top);
+       if(loc == NO_MEM) {
+               level--;
+               return NULL;
+       }
+
+       /* Allocate 'pages' pages of memory for use by VM. As VM
+        * is trusted, we don't have to pre-clear it.
+        */
+       if((newpage = ALLOC_MEM(CLICKSPERPAGE * pages, 0)) == NO_MEM) {
+               level--;
+               return NULL;
+       }
+
+       *phys = CLICK2ABS(newpage);
+
+       /* Map this page into our address space. */
+       if((r=pt_writemap(pt, loc, *phys, bytes,
+               I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, 0)) != OK) {
+               FREE_MEM(newpage, CLICKSPERPAGE * pages / I386_PAGE_SIZE);
+               return NULL;
+       }
+
+       level--;
+
+       /* Return user-space-ready pointer to it. */
+       return (void *) (loc - CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys));
+}
+
+/*===========================================================================*
+ *                             pt_ptalloc                                   *
+ *===========================================================================*/
+PRIVATE int pt_ptalloc(pt_t *pt, int pde, u32_t flags)
+{
+/* Allocate a page table and write its address into the page directory. */
+       int i;
+       u32_t pt_phys;
+
+       /* Argument must make sense. */
+       vm_assert(pde >= 0 && pde < I386_VM_DIR_ENTRIES);
+       vm_assert(!(flags & ~(PTF_ALLFLAGS | PTF_MAPALLOC)));
+
+       /* We don't expect to overwrite page directory entry, nor
+        * storage for the page table.
+        */
+       vm_assert(!(pt->pt_dir[pde] & I386_VM_PRESENT));
+       vm_assert(!pt->pt_pt[pde]);
+       PT_SANE(pt);
+
+       /* Get storage for the page table. */
+        if(!(pt->pt_pt[pde] = vm_allocpages(&pt_phys, 1, VMP_PAGETABLE)))
+               return ENOMEM;
+
+       for(i = 0; i < I386_VM_PT_ENTRIES; i++)
+               pt->pt_pt[pde][i] = 0;  /* Empty entry. */
+
+       /* Make page directory entry.
+        * The PDE is always 'present,' 'writable,' and 'user accessible,'
+        * relying on the PTE for protection.
+        */
+       pt->pt_dir[pde] = (pt_phys & I386_VM_ADDR_MASK) | flags
+               | I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE;
+       vm_assert(flags & I386_VM_PRESENT);
+       PT_SANE(pt);
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             pt_writemap                                  *
+ *===========================================================================*/
+PUBLIC int pt_writemap(pt_t *pt, vir_bytes v, phys_bytes physaddr,
+       size_t bytes, u32_t flags, u32_t writemapflags)
+{
+/* Write mapping into page table. Allocate a new page table if necessary. */
+/* Page directory and table entries for this virtual address. */
+       int p, pages, pde;
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       vm_assert(!(bytes % I386_PAGE_SIZE));
+       vm_assert(!(flags & ~(PTF_ALLFLAGS | PTF_MAPALLOC)));
+
+       pages = bytes / I386_PAGE_SIZE;
+
+#if SANITYCHECKS
+       if(physaddr && !(flags & I386_VM_PRESENT)) {
+               vm_panic("pt_writemap: writing dir with !P\n", NO_NUM);
+       }
+       if(!physaddr && flags) {
+               vm_panic("pt_writemap: writing 0 with flags\n", NO_NUM);
+       }
+#endif
+
+       PT_SANE(pt);
+
+       /* First make sure all the necessary page tables are allocated,
+        * before we start writing in any of them, because it's a pain
+        * to undo our work properly. Walk the range in page-directory-entry
+        * sized leaps.
+        */
+       for(pde = I386_VM_PDE(v); pde <= I386_VM_PDE(v + I386_PAGE_SIZE * pages); pde++) {
+               vm_assert(pde >= 0 && pde < I386_VM_DIR_ENTRIES);
+               if(!(pt->pt_dir[pde] & I386_VM_PRESENT)) {
+                       int r;
+                       vm_assert(!pt->pt_dir[pde]);
+                       if((r=pt_ptalloc(pt, pde, flags)) != OK) {
+                               /* Couldn't do (complete) mapping.
+                                * Don't bother freeing any previously
+                                * allocated page tables, they're
+                                * still writable, don't point to nonsense,
+                                * and pt_ptalloc leaves the directory
+                                * and other data in a consistent state.
+                                */
+                               return r;
+                       }
+               }
+               vm_assert(pt->pt_dir[pde] & I386_VM_PRESENT);
+       }
+
+       PT_SANE(pt);
+
+       /* Now write in them. */
+       for(p = 0; p < pages; p++) {
+               int pde = I386_VM_PDE(v);
+               int pte = I386_VM_PTE(v);
+       PT_SANE(pt);
+
+               vm_assert(!(v % I386_PAGE_SIZE));
+               vm_assert(pte >= 0 && pte < I386_VM_PT_ENTRIES);
+               vm_assert(pde >= 0 && pde < I386_VM_DIR_ENTRIES);
+
+               /* Page table has to be there. */
+               vm_assert(pt->pt_dir[pde] & I386_VM_PRESENT);
+
+               /* Make sure page directory entry for this page table
+                * is marked present and page table entry is available.
+                */
+               vm_assert((pt->pt_dir[pde] & I386_VM_PRESENT) && pt->pt_pt[pde]);
+
+       PT_SANE(pt);
+#if SANITYCHECKS
+               /* We don't expect to overwrite a page. */
+               if(!(writemapflags & WMF_OVERWRITE))
+                       vm_assert(!(pt->pt_pt[pde][pte] & I386_VM_PRESENT));
+#endif
+
+               /* Write pagetable entry. */
+               pt->pt_pt[pde][pte] = (physaddr & I386_VM_ADDR_MASK) | flags;
+
+               physaddr += I386_PAGE_SIZE;
+               v += I386_PAGE_SIZE;
+       PT_SANE(pt);
+       }
+       SANITYCHECK(SCL_FUNCTIONS);
+       PT_SANE(pt);
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             pt_new                                       *
+ *===========================================================================*/
+PUBLIC int pt_new(pt_t *pt)
+{
+/* Allocate a pagetable root. On i386, allocate a page-aligned page directory
+ * and set them to 0 (indicating no page tables are allocated). Lookup
+ * its physical address as we'll need that in the future. Verify it's
+ * page-aligned.
+ */
+       int i;
+
+        if(!(pt->pt_dir = vm_allocpages(&pt->pt_dir_phys, 1, VMP_PAGEDIR))) {
+               return ENOMEM;
+       }
+
+       for(i = 0; i < I386_VM_DIR_ENTRIES; i++) {
+               pt->pt_dir[i] = 0; /* invalid entry (I386_VM_PRESENT bit = 0) */
+               pt->pt_pt[i] = NULL;
+       }
+
+       /* Where to start looking for free virtual address space? */
+       pt->pt_virtop = VM_STACKTOP +
+               CLICK2ABS(vmproc[VMP_SYSTEM].vm_arch.vm_seg[D].mem_phys);
+
+       return OK;
+}
+
+
+
+/*===========================================================================*
+ *                             pt_allocmap                                  *
+ *===========================================================================*/
+PUBLIC int pt_allocmap(pt_t *pt, vir_bytes v_min, vir_bytes v_max,
+       size_t bytes, u32_t pageflags, u32_t memflags, vir_bytes *v_final)
+{
+/* Allocate new memory, and map it into the page table. */
+       u32_t newpage;
+       u32_t v;
+       int r;
+
+       /* Input sanity check. */
+       PT_SANE(pt);
+       vm_assert(!(pageflags & ~PTF_ALLFLAGS));
+
+       /* Valid no-op. */
+       if(bytes == 0) return OK;
+
+       /* Round no. of bytes up to a page. */
+       if(bytes % I386_PAGE_SIZE) {
+               bytes += I386_PAGE_SIZE - (bytes % I386_PAGE_SIZE);
+       }
+
+       /* Special case; if v_max is 0, the request is to map the memory
+        * into v_min at exactly that location. We raise v_max as necessary,
+        * so the check to see if the virtual space is free does happen.
+        */
+       if(v_max == 0) {
+               v_max = v_min + bytes;
+
+               /* Sanity check. */
+               if(v_max < v_min) {
+                       printf("pt_allocmap: v_min 0x%lx and bytes 0x%lx\n",
+                               v_min, bytes);
+                       return ENOMEM;
+               }
+       }
+
+       /* Basic sanity check. */
+       if(v_max < v_min) {
+               printf("pt_allocmap: v_min 0x%lx, v_max 0x%lx\n", v_min, v_max);
+               return ENOMEM;
+       }
+
+       /* v_max itself may not be used. Bytes may be 0. */
+       if(v_max < v_min + bytes) {
+               printf("pt_allocmap: v_min 0x%lx, bytes 0x%lx, v_max 0x%lx\n",
+                       v_min, bytes, v_max);
+               return ENOMEM;
+       }
+
+       /* Find where to fit this into the virtual address space. */
+       v = findhole(pt, bytes, v_min, v_max);
+       if(v == NO_MEM) {
+               printf("pt_allocmap: no hole found to map 0x%lx bytes into\n",
+                       bytes);
+               return ENOSPC;
+       }
+
+       vm_assert(!(v % I386_PAGE_SIZE));
+
+       if(v_final) *v_final = v;
+
+       /* Memory is currently always allocated contiguously physically,
+        * but if that were to change, note the setting of
+        * PAF_CONTIG in memflags.
+        */
+
+       newpage = ALLOC_MEM(CLICKSPERPAGE * bytes / I386_PAGE_SIZE, memflags);
+       if(newpage == NO_MEM) {
+               printf("pt_allocmap: out of memory\n");
+               return ENOMEM;
+       }
+
+       /* Write into the page table. */
+       if((r=pt_writemap(pt, v, CLICK2ABS(newpage), bytes,
+               pageflags | PTF_MAPALLOC, 0)) != OK) {
+               FREE_MEM(newpage, CLICKSPERPAGE * bytes / I386_PAGE_SIZE);
+               return r;
+       }
+
+       /* Sanity check result. */
+       PT_SANE(pt);
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             raw_readmap                                  *
+ *===========================================================================*/
+PRIVATE int raw_readmap(phys_bytes root, u32_t v, u32_t *phys, u32_t *flags)
+{
+       u32_t dir[I386_VM_DIR_ENTRIES];
+       u32_t tab[I386_VM_PT_ENTRIES];
+       int pde, pte, r;
+
+       /* Sanity check. */
+       vm_assert((root % I386_PAGE_SIZE) == 0);
+       vm_assert((v % I386_PAGE_SIZE) == 0);
+
+       /* Get entry in page directory. */
+       pde = I386_VM_PDE(v);
+       if((r=sys_physcopy(SYSTEM, PHYS_SEG, root,
+               SELF, VM_D, (phys_bytes) dir, sizeof(dir))) != OK) {
+               printf("VM: raw_readmap: sys_physcopy failed (dir) (%d)\n", r);
+               return EFAULT;
+       }
+
+       if(!(dir[pde] & I386_VM_PRESENT)) {
+               printf("raw_readmap: 0x%lx: pde %d not present: 0x%lx\n",
+                       v, pde, dir[pde]);
+               return EFAULT;
+       }
+
+       /* Get entry in page table. */
+       if((r=sys_physcopy(SYSTEM, PHYS_SEG, I386_VM_PFA(dir[pde]),
+               SELF, VM_D, (vir_bytes) tab, sizeof(tab))) != OK) {
+               printf("VM: raw_readmap: sys_physcopy failed (tab) (r)\n");
+               return EFAULT;
+       }
+       pte = I386_VM_PTE(v);
+       if(!(tab[pte] & I386_VM_PRESENT)) {
+               printf("raw_readmap: 0x%lx: pde %d not present: 0x%lx\n",
+                       v, pte, tab[pte]);
+               return EFAULT;
+       }
+
+       /* Get address and flags. */
+       *phys = I386_VM_PFA(tab[pte]);
+       *flags = tab[pte] & PTF_ALLFLAGS;
+       
+       return OK;
+}
+
+/*===========================================================================*
+ *                             pt_init                                      *
+ *===========================================================================*/
+PUBLIC void pt_init(void)
+{
+/* By default, the kernel gives us a data segment with pre-allocated
+ * memory that then can't grow. We want to be able to allocate memory
+ * dynamically, however. So here we copy the part of the page table
+ * that's ours, so we get a private page table. Then we increase the
+ * hardware segment size so we can allocate memory above our stack.
+ */
+       u32_t my_cr3;
+       pt_t *newpt;
+       int s, r;
+       vir_bytes v;
+       phys_bytes lo, hi;
+       vir_bytes extra_clicks;
+
+       /* Retrieve current CR3 - shared page table. */
+       if((r=sys_vmctl_get_cr3_i386(SELF, &my_cr3)) != OK)
+               vm_panic("pt_init: sys_vmctl_get_cr3_i386 failed", r);
+
+       /* Shorthand. */
+       newpt = &vmp->vm_pt;
+
+       /* Get ourselves a spare page. */
+       for(s = 0; s < SPAREPAGES; s++) {
+               if(!(sparepages[s].page = aalloc(I386_PAGE_SIZE)))
+                       vm_panic("pt_init: aalloc for spare failed", NO_NUM);
+               if((r=sys_umap(SELF, VM_D, (vir_bytes) sparepages[s].page,
+                       I386_PAGE_SIZE, &sparepages[s].phys)) != OK)
+                       vm_panic("pt_init: sys_umap failed", r);
+       }
+
+       /* Make new page table for ourselves, partly copied
+        * from the current one.
+        */
+       if(pt_new(newpt) != OK)
+               vm_panic("pt_init: pt_new failed", NO_NUM);
+
+       /* Initial (current) range of our virtual address space. */
+       lo = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys);
+       hi = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_phys +
+               vmp->vm_arch.vm_seg[S].mem_len);
+
+       /* Copy the mappings from the shared page table to our private one. */
+       for(v = lo; v < hi; v += I386_PAGE_SIZE)  {
+               phys_bytes addr;
+               u32_t flags;
+               if(raw_readmap(my_cr3, v, &addr, &flags) != OK)
+                       vm_panic("pt_init: raw_readmap failed", NO_NUM);
+               if(pt_writemap(newpt, v, addr, I386_PAGE_SIZE, flags, 0) != OK)
+                       vm_panic("pt_init: pt_writemap failed", NO_NUM);
+       }
+
+       /* Map in kernel. */
+       if(pt_mapkernel(newpt) != OK)
+               vm_panic("pt_init: pt_mapkernel failed", NO_NUM);
+
+       /* Give our process the new, copied, private page table. */
+       pt_bind(newpt, vmp);
+
+       /* Increase our hardware data segment to create virtual address
+        * space above our stack. We want to increase it to VM_DATATOP,
+        * like regular processes have.
+        */
+       extra_clicks = ABS2CLICK(VM_DATATOP - hi);
+       vmp->vm_arch.vm_seg[S].mem_len += extra_clicks;
+
+       /* We pretend to the kernel we have a huge stack segment to
+        * increase our data segment.
+        */
+        vmp->vm_arch.vm_data_top =
+               (vmp->vm_arch.vm_seg[S].mem_vir +
+               vmp->vm_arch.vm_seg[S].mem_len) << CLICK_SHIFT;
+
+       if((s=sys_newmap(VM_PROC_NR, vmp->vm_arch.vm_seg)) != OK)
+               vm_panic("VM: pt_init: sys_newmap failed", s);
+
+       /* Back to reality - this is where the stack actually is. */
+       vmp->vm_arch.vm_seg[S].mem_len -= extra_clicks;
+
+       /* Where our free virtual address space starts.
+        * This is only a hint to the VM system.
+        */
+       newpt->pt_virtop = (vmp->vm_arch.vm_seg[S].mem_vir +
+               vmp->vm_arch.vm_seg[S].mem_len) << CLICK_SHIFT;
+
+       /* Let other functions know VM now has a private page table. */
+       vmp->vm_flags |= VMF_HASPT;
+
+       /* Reserve a page in our virtual address space that we
+        * can use to map in arbitrary physical pages.
+        */
+       varmap_loc = findhole(newpt, I386_PAGE_SIZE,
+               CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys) + vmp->vm_stacktop,
+               vmp->vm_arch.vm_data_top);
+       if(varmap_loc == NO_MEM) {
+               vm_panic("no virt addr for vm mappings", NO_NUM);
+       }
+       varmap = (unsigned char *) (varmap_loc -
+               CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys));
+
+       /* All OK. */
+       return;
+}
+
+/*===========================================================================*
+ *                             pt_bind                                      *
+ *===========================================================================*/
+PUBLIC int pt_bind(pt_t *pt, struct vmproc *who)
+{
+       /* Basic sanity checks. */
+       vm_assert(who);
+       vm_assert(who->vm_flags & VMF_INUSE);
+       if(pt) PT_SANE(pt);
+
+       /* Tell kernel about new page table root. */
+       return sys_vmctl(who->vm_endpoint, VMCTL_I386_SETCR3,
+               pt ? pt->pt_dir_phys : 0);
+}
+
+/*===========================================================================*
+ *                             pt_free                                      *
+ *===========================================================================*/
+PUBLIC void pt_free(pt_t *pt)
+{
+/* Free memory associated with this pagetable. */
+       int i;
+
+       PT_SANE(pt);
+
+       for(i = 0; i < I386_VM_DIR_ENTRIES; i++) {
+               int p;
+               if(pt->pt_pt[i]) {
+                  for(p = 0; p < I386_VM_PT_ENTRIES; p++) {
+                       if((pt->pt_pt[i][p] & (PTF_MAPALLOC | I386_VM_PRESENT)) 
+                        == (PTF_MAPALLOC | I386_VM_PRESENT)) {
+                                       u32_t pa = I386_VM_PFA(pt->pt_pt[i][p]);
+                                       FREE_MEM(ABS2CLICK(pa), CLICKSPERPAGE);
+                               }
+                 }
+                 vm_freepages((vir_bytes) pt->pt_pt[i],
+                       I386_VM_PFA(pt->pt_dir[i]), 1, VMP_PAGETABLE);
+               }
+       }
+
+       vm_freepages((vir_bytes) pt->pt_dir, pt->pt_dir_phys, 1, VMP_PAGEDIR);
+
+       return;
+}
+
+/*===========================================================================*
+ *                             pt_mapkernel                                 *
+ *===========================================================================*/
+PUBLIC int pt_mapkernel(pt_t *pt)
+{
+       int r;
+
+        /* Any i386 page table needs to map in the kernel address space. */
+        vm_assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE);
+
+        /* Map in text. flags: don't write, supervisor only */
+        if((r=pt_writemap(pt, KERNEL_TEXT, KERNEL_TEXT, KERNEL_TEXT_LEN,
+                 I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, 0)) != OK)
+               return r;
+        /* Map in data. flags: read-write, supervisor only */
+        if((r=pt_writemap(pt, KERNEL_DATA, KERNEL_DATA, KERNEL_DATA_LEN,
+                I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, 0)) != OK)
+               return r;
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             pt_freerange                                 *
+ *===========================================================================*/
+PUBLIC void pt_freerange(pt_t *pt, vir_bytes low, vir_bytes high)
+{
+/* Free memory allocated by pagetable functions in this range. */
+       int pde;
+       u32_t v;
+
+       PT_SANE(pt);
+
+       for(v = low; v < high; v += I386_PAGE_SIZE) {
+               int pte;
+               pde = I386_VM_PDE(v);
+               pte = I386_VM_PTE(v);
+               if(!(pt->pt_dir[pde] & I386_VM_PRESENT))
+                       continue;
+               if((pt->pt_pt[pde][pte] & (PTF_MAPALLOC | I386_VM_PRESENT)) 
+                == (PTF_MAPALLOC | I386_VM_PRESENT)) {
+                       u32_t pa = I386_VM_PFA(pt->pt_pt[pde][pte]);
+                       FREE_MEM(ABS2CLICK(pa), CLICKSPERPAGE);
+                       pt->pt_pt[pde][pte] = 0;
+               }
+       }
+
+       PT_SANE(pt);
+
+       return;
+}
+
+/*===========================================================================*
+ *                             pt_cycle                                     *
+ *===========================================================================*/
+PUBLIC void pt_cycle(void)
+{
+       vm_checkspares();
+}
+
+/*===========================================================================*
+ *                             pt_copy                                      *
+ *===========================================================================*/
+PUBLIC int pt_copy(pt_t *src, pt_t *dst)
+{
+       int i, r;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+       PT_SANE(src);
+
+       if((r=pt_new(dst)) != OK)
+               return r;
+
+       for(i = 0; i < I386_VM_DIR_ENTRIES; i++) {
+               int p; 
+               if(!(src->pt_dir[i] & I386_VM_PRESENT))
+                       continue;
+               for(p = 0; p < I386_VM_PT_ENTRIES; p++) {
+                       u32_t v = i * I386_VM_PT_ENTRIES * I386_PAGE_SIZE +
+                               p * I386_PAGE_SIZE;
+                       u32_t pa1, pa2, flags;
+                       if(!(src->pt_pt[i][p] & I386_VM_PRESENT))
+                               continue;
+#if 0
+                       if((dst->pt_pt[i] &&
+                          (dst->pt_pt[i][p] & I386_VM_PRESENT)))
+                               continue;
+#endif
+                       flags = src->pt_pt[i][p] & (PTF_WRITE | PTF_USER);
+                       flags |= I386_VM_PRESENT;
+                       pa1 = I386_VM_PFA(src->pt_pt[i][p]);
+                       if(PTF_MAPALLOC & src->pt_pt[i][p]) {
+                               PT_SANE(dst);
+                               if(pt_allocmap(dst, v, 0,
+                                       I386_PAGE_SIZE, flags, 0, NULL) != OK) {
+                                       pt_free(dst);
+                                       return ENOMEM;
+                               }
+                               pa2 = I386_VM_PFA(dst->pt_pt[i][p]);
+                               sys_abscopy(pa1, pa2, I386_PAGE_SIZE);
+                       } else {
+                               PT_SANE(dst);
+                               if(pt_writemap(dst, v, pa1, I386_PAGE_SIZE, flags, 0) != OK) {
+                                       pt_free(dst);
+                                       return ENOMEM;
+                               }
+                       }
+               }
+       }
+
+       PT_SANE(src);
+       PT_SANE(dst);
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       return OK;
+}
+
+#define PHYS_MAP(a, o)                                                 \
+{      int r;                                                          \
+       vm_assert(varmap);                                              \
+       (o) = (a) % I386_PAGE_SIZE;                                     \
+       r = pt_writemap(&vmp->vm_pt, varmap_loc, (a) - (o), I386_PAGE_SIZE, \
+               I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE, 0);     \
+       if(r != OK)                                                     \
+               vm_panic("PHYS_MAP: pt_writemap failed", NO_NUM);       \
+       /* pt_bind() flushes TLB. */                                    \
+       pt_bind(&vmp->vm_pt, vmp);                                      \
+}
+
+#define PHYSMAGIC 0x7b9a0590
+
+#define PHYS_UNMAP if(OK != pt_writemap(&vmp->vm_pt, varmap_loc, 0,    \
+       I386_PAGE_SIZE, 0, WMF_OVERWRITE)) {                            \
+               vm_panic("PHYS_UNMAP: pt_writemap failed", NO_NUM); }
+
+#define PHYS_VAL(o) (* (phys_bytes *) (varmap + (o)))
+
+/*===========================================================================*
+ *                              phys_writeaddr                               *
+ *===========================================================================*/
+PUBLIC void phys_writeaddr(phys_bytes addr, phys_bytes v1, phys_bytes v2)
+{
+       phys_bytes offset;
+
+       SANITYCHECK(SCL_DETAIL);
+       PHYS_MAP(addr, offset);
+       PHYS_VAL(offset) = v1;
+       PHYS_VAL(offset + sizeof(phys_bytes)) = v2;
+#if SANITYCHECKS
+       PHYS_VAL(offset + 2*sizeof(phys_bytes)) = PHYSMAGIC;
+#endif
+       PHYS_UNMAP;
+       SANITYCHECK(SCL_DETAIL);
+}
+
+/*===========================================================================*
+ *                              phys_readaddr                                *
+ *===========================================================================*/
+PUBLIC void phys_readaddr(phys_bytes addr, phys_bytes *v1, phys_bytes *v2)
+{
+       phys_bytes offset;
+
+       SANITYCHECK(SCL_DETAIL);
+       PHYS_MAP(addr, offset);
+       *v1 = PHYS_VAL(offset);
+       *v2 = PHYS_VAL(offset + sizeof(phys_bytes));
+#if SANITYCHECKS
+       vm_assert(PHYS_VAL(offset + 2*sizeof(phys_bytes)) == PHYSMAGIC);
+#endif
+       PHYS_UNMAP;
+       SANITYCHECK(SCL_DETAIL);
+}
diff --git a/servers/vm/i386/pagetable.h b/servers/vm/i386/pagetable.h
new file mode 100644 (file)
index 0000000..e4934c7
--- /dev/null
@@ -0,0 +1,37 @@
+
+#ifndef _PAGETABLE_H
+#define _PAGETABLE_H 1
+
+#include <stdint.h>
+#include <sys/vm_i386.h>
+
+/* An i386 pagetable. */
+typedef struct {
+       /* Directory entries in VM addr space - root of page table.  */
+       u32_t *pt_dir;          /* page aligned (I386_VM_DIR_ENTRIES) */
+       u32_t pt_dir_phys;      /* physical address of pt_dir */
+
+       /* Pointers to page tables in VM address space. */
+       u32_t *pt_pt[I386_VM_DIR_ENTRIES];
+
+       /* When looking for a hole in virtual address space, start
+        * looking here. This is in linear addresses, i.e.,
+        * not as the process sees it but the position in the page
+        * page table. This is just a hint.
+        */
+       u32_t pt_virtop;
+} pt_t;
+
+/* Mapping flags. */
+#define PTF_WRITE      I386_VM_WRITE
+#define PTF_PRESENT    I386_VM_PRESENT
+#define PTF_USER       I386_VM_USER
+#define PTF_MAPALLOC   I386_VM_PTAVAIL1 /* Page allocated by pt code. */
+
+/* For arch-specific PT routines to check if no bits outside
+ * the regular flags are set.
+ */
+#define PTF_ALLFLAGS   (PTF_WRITE|PTF_PRESENT|PTF_USER)
+
+#endif
+
diff --git a/servers/vm/i386/util.s b/servers/vm/i386/util.s
new file mode 100644 (file)
index 0000000..7b31227
--- /dev/null
@@ -0,0 +1,23 @@
+
+.sect .text; .sect .rom; .sect .data; .sect .bss                             
+
+.define _i386_invlpg
+
+.sect .text
+
+!*===========================================================================*
+!*                              i386_invlpg                                  *
+!*===========================================================================*
+! PUBLIC void i386_invlpg(u32_t addr)
+! Tell the processor to invalidate a tlb entry at virtual address addr.
+_i386_invlpg:
+       push    ebp
+       mov     ebp, esp
+       push    eax
+
+       mov     eax, 8(ebp)
+       invlpg  eax
+
+       pop     eax
+       pop     ebp
+       ret
diff --git a/servers/vm/i386/vm.c b/servers/vm/i386/vm.c
new file mode 100644 (file)
index 0000000..1f55874
--- /dev/null
@@ -0,0 +1,115 @@
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <env.h>
+
+#include "../proto.h"
+#include "../vm.h"
+#include "../util.h"
+
+#include "memory.h"
+
+#define PAGE_SIZE      4096
+#define PAGE_DIR_SIZE  (1024*PAGE_SIZE)        
+#define PAGE_TABLE_COVER (1024*PAGE_SIZE)
+/*=========================================================================*
+ *                             arch_init_vm                               *
+ *=========================================================================*/
+PUBLIC void arch_init_vm(mem_chunks)
+struct memory mem_chunks[NR_MEMS];
+{
+       phys_bytes high, bytes;
+       phys_clicks clicks, base_click;
+       unsigned pages;
+       int i, r;
+
+       /* Compute the highest memory location */
+       high= 0;
+       for (i= 0; i<NR_MEMS; i++)
+       {
+               if (mem_chunks[i].size == 0)
+                       continue;
+               if (mem_chunks[i].base + mem_chunks[i].size > high)
+                       high= mem_chunks[i].base + mem_chunks[i].size;
+       }
+
+       high <<= CLICK_SHIFT;
+#if VERBOSE_VM
+       printf("do_x86_vm: found high 0x%x\n", high);
+#endif
+       
+       /* Rounding up */
+       high= (high-1+PAGE_DIR_SIZE) & ~(PAGE_DIR_SIZE-1);
+
+       /* The number of pages we need is one for the page directory, enough
+        * page tables to cover the memory, and one page for alignement.
+        */
+       pages= 1 + (high + PAGE_TABLE_COVER-1)/PAGE_TABLE_COVER + 1;
+       bytes= pages*PAGE_SIZE;
+       clicks= (bytes + CLICK_SIZE-1) >> CLICK_SHIFT;
+
+#if VERBOSE_VM
+       printf("do_x86_vm: need %d pages\n", pages);
+       printf("do_x86_vm: need %d bytes\n", bytes);
+       printf("do_x86_vm: need %d clicks\n", clicks);
+#endif
+
+       for (i= 0; i<NR_MEMS; i++)
+       {
+               if (mem_chunks[i].size <= clicks)
+                       continue;
+               break;
+       }
+       if (i >= NR_MEMS)
+               panic("VM", "not enough memory for VM page tables?", NO_NUM);
+       base_click= mem_chunks[i].base;
+       mem_chunks[i].base += clicks;
+       mem_chunks[i].size -= clicks;
+
+#if VERBOSE_VM
+       printf("do_x86_vm: using 0x%x clicks @ 0x%x\n", clicks, base_click);
+#endif
+       r= sys_vm_setbuf(base_click << CLICK_SHIFT, clicks << CLICK_SHIFT,
+               high);
+       if (r != 0)
+               printf("do_x86_vm: sys_vm_setbuf failed: %d\n", r);
+
+}
+
+/*===========================================================================*
+ *                             arch_map2vir                                 *
+ *===========================================================================*/
+PUBLIC vir_bytes arch_map2vir(struct vmproc *vmp, vir_bytes addr)
+{
+       vir_bytes bottom = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys);
+
+       vm_assert(bottom <= addr);
+
+       return addr - bottom;
+}
+
+/*===========================================================================*
+ *                             arch_vir2map                                 *
+ *===========================================================================*/
+PUBLIC vir_bytes arch_vir2map(struct vmproc *vmp, vir_bytes addr)
+{
+       vir_bytes bottom = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys);
+
+       return addr + bottom;
+}
diff --git a/servers/vm/main.c b/servers/vm/main.c
new file mode 100644 (file)
index 0000000..02bf87b
--- /dev/null
@@ -0,0 +1,274 @@
+
+#define _SYSTEM 1
+
+#define VERBOSE 0
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+#include <errno.h>
+#include <string.h>
+#include <env.h>
+#include <stdio.h>
+
+#define _MAIN 1
+#include "glo.h"
+#include "proto.h"
+#include "util.h"
+#include "vm.h"
+#include "sanitycheck.h"
+
+#include <archtypes.h>
+#include "../../kernel/const.h"
+#include "../../kernel/config.h" 
+#include "../../kernel/proc.h"
+
+/* Table of calls and a macro to test for being in range. */
+struct {
+       endpoint_t vmc_caller;          /* Process that does this, or ANY */
+       int (*vmc_func)(message *);     /* Call handles message. */
+       char *vmc_name;                 /* Human-readable string. */
+} vm_calls[VM_NCALLS];
+
+/* Macro to verify call range and map 'high' range to 'base' range
+ * (starting at 0) in one. Evaluates to zero-based call number if call
+ * number is valid, returns -1 otherwise.
+ */
+#define CALLNUMBER(c) (((c) >= VM_RQ_BASE &&                           \
+                       (c) < VM_RQ_BASE + ELEMENTS(vm_calls)) ?        \
+                       ((c) - VM_RQ_BASE) : -1)
+
+FORWARD _PROTOTYPE(void vm_init, (void));
+
+#if SANITYCHECKS
+extern int kputc_use_private_grants;
+#endif
+
+/*===========================================================================*
+ *                             main                                         *
+ *===========================================================================*/
+PUBLIC int main(void)
+{
+  message msg;
+  int result, who_e;
+
+#if SANITYCHECKS
+  memcpy(data1, CHECKADDR, sizeof(data1));    
+#endif
+       SANITYCHECK(SCL_TOP);
+
+  vm_paged = 0;
+  env_parse("vm_paged", "d", 0, &vm_paged, 0, 1);
+#if SANITYCHECKS
+  env_parse("vm_sanitychecklevel", "d", 0, &vm_sanitychecklevel, 0, SCL_MAX);
+#endif
+
+       SANITYCHECK(SCL_TOP);
+
+  vm_init();
+       SANITYCHECK(SCL_TOP);
+
+  /* This is VM's main loop. */
+  while (TRUE) {
+       int r, c;
+
+       SANITYCHECK(SCL_TOP);
+       pt_cycle();     /* pagetable code wants to be called */
+#if SANITYCHECKS
+       slabstats();
+#endif
+       SANITYCHECK(SCL_DETAIL);
+
+       if ((r=receive(ANY, &msg)) != OK)
+               vm_panic("receive() error", r);
+
+       if(msg.m_source == LOG_PROC_NR ||
+               msg.m_source == TTY_PROC_NR)
+               continue;
+
+       SANITYCHECK(SCL_DETAIL);
+
+       if(msg.m_type & NOTIFY_MESSAGE) {
+               switch(msg.m_source) {
+                       case SYSTEM:
+                               /* Kernel wants to have memory ranges
+                                * verified.
+                                */
+                               handle_memory();
+                               break;
+                       case PM_PROC_NR:
+                               /* PM sends a notify() on shutdown, which
+                                * is OK and we ignore.
+                                */
+                               break;
+                       case HARDWARE:
+                               /* This indicates a page fault has happened,
+                                * which we have to handle.
+                                */
+                               handle_pagefaults();
+                               break;
+                       default:
+                               /* No-one else should send us notifies. */
+                               printf("VM: ignoring notify() from %d\n",
+                                       msg.m_source);
+                               break;
+               }
+               continue;
+       }
+       who_e = msg.m_source;
+       c = msg.m_type - VM_RQ_BASE;
+       result = ENOSYS; /* Out of range or restricted calls return this. */
+       if((c=CALLNUMBER(msg.m_type)) < 0 || !vm_calls[c].vmc_func) {
+               printf("VM: out of range or missing callnr %d from %d\n",
+                       msg.m_type, msg.m_source);
+       } else if(vm_calls[c].vmc_caller != ANY &&
+               vm_calls[c].vmc_caller != msg.m_source) {
+               printf("VM: restricted callnr %d (%s) from %d instead of %d\n",
+                       c,
+                       vm_calls[c].vmc_name, msg.m_source,
+                       vm_calls[c].vmc_caller);
+       } else {
+       SANITYCHECK(SCL_FUNCTIONS);
+               result = vm_calls[c].vmc_func(&msg);
+       SANITYCHECK(SCL_FUNCTIONS);
+       }
+
+       /* Send reply message, unless the return code is SUSPEND,
+        * which is a pseudo-result suppressing the reply message.
+        */
+       if(result != SUSPEND) {
+       SANITYCHECK(SCL_DETAIL);
+               msg.m_type = result;
+               if((r=send(who_e, &msg)) != OK) {
+                       printf("VM: couldn't send %d to %d (err %d)\n",
+                               msg.m_type, who_e, r);
+                       vm_panic("send() error", NO_NUM);
+               }
+       SANITYCHECK(SCL_DETAIL);
+       }
+       SANITYCHECK(SCL_DETAIL);
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *                             vm_init                                      *
+ *===========================================================================*/
+PRIVATE void vm_init(void)
+{
+       int s;
+       struct memory mem_chunks[NR_MEMS];
+       struct boot_image image[NR_BOOT_PROCS];
+       struct boot_image *ip;
+       struct vmproc *vmp;
+
+       /* Get chunks of available memory. */
+       get_mem_chunks(mem_chunks);
+
+       /* Initialize VM's process table. Request a copy of the system
+        * image table that is defined at the kernel level to see which
+        * slots to fill in.
+        */
+       if (OK != (s=sys_getimage(image)))
+               vm_panic("couldn't get image table: %d\n", s);
+
+       /* Set table to 0. This invalidates all slots (clear VMF_INUSE). */
+       memset(vmproc, 0, sizeof(vmproc));
+
+       /* Walk through boot-time system processes that are alive
+        * now and make valid slot entries for them.
+        */
+       for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) {
+               if(ip->proc_nr >= _NR_PROCS) { vm_panic("proc", ip->proc_nr); }
+               if(ip->proc_nr < 0 && ip->proc_nr != SYSTEM) continue;
+
+               /* Initialize normal process table slot or special SYSTEM
+                * table slot. Kernel memory is already reserved.
+                */
+               if(ip->proc_nr >= 0) {
+                       vmp = &vmproc[ip->proc_nr];
+               } else if(ip->proc_nr == SYSTEM) {
+                       vmp = &vmproc[VMP_SYSTEM];
+               } else {
+                       vm_panic("init: crazy proc_nr", ip->proc_nr);
+               }
+
+               /* reset fields as if exited */
+               clear_proc(vmp);
+
+               /* Get memory map for this process from the kernel. */
+               if ((s=get_mem_map(ip->proc_nr, vmp->vm_arch.vm_seg)) != OK)
+                       vm_panic("couldn't get process mem_map",s);
+
+               /* Remove this memory from the free list. */
+               reserve_proc_mem(mem_chunks, vmp->vm_arch.vm_seg);
+
+               vmp->vm_flags = VMF_INUSE;
+               vmp->vm_endpoint = ip->endpoint;
+               vmp->vm_stacktop =
+                       CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_vir +
+                               vmp->vm_arch.vm_seg[S].mem_len);
+
+               if (vmp->vm_arch.vm_seg[T].mem_len != 0)
+                       vmp->vm_flags |= VMF_SEPARATE;
+       }
+
+
+       /* Let architecture-dependent VM initialization use some memory. */
+       arch_init_vm(mem_chunks);
+
+       /* Architecture-dependent initialization. */
+       pt_init();
+
+       /* Initialize tables to all physical memory. */
+       mem_init(mem_chunks);
+
+       /* Set up table of calls. */
+#define CALLMAP(code, func, thecaller) { int i;                              \
+       if((i=CALLNUMBER(code)) < 0) { vm_panic(#code " invalid", (code)); } \
+       if(vm_calls[i].vmc_func) { vm_panic("dup " #code , (code)); }  \
+       vm_calls[i].vmc_func = (func);                                \
+       vm_calls[i].vmc_name = #code;                                 \
+       vm_calls[i].vmc_caller = (thecaller);                         \
+}
+
+       /* Set call table to 0. This invalidates all calls (clear
+        * vmc_func).
+        */
+       memset(vm_calls, 0, sizeof(vm_calls));
+
+       /* Requests from PM (restricted to be from PM only). */
+       CALLMAP(VM_EXIT, do_exit, PM_PROC_NR);
+       CALLMAP(VM_FORK, do_fork, PM_PROC_NR);
+       CALLMAP(VM_BRK, do_brk, PM_PROC_NR);
+       CALLMAP(VM_EXEC_NEWMEM, do_exec_newmem, PM_PROC_NR);
+       CALLMAP(VM_PUSH_SIG, do_push_sig, PM_PROC_NR);
+       CALLMAP(VM_WILLEXIT, do_willexit, PM_PROC_NR);
+       CALLMAP(VM_ADDDMA, do_adddma, PM_PROC_NR);
+       CALLMAP(VM_DELDMA, do_deldma, PM_PROC_NR);
+       CALLMAP(VM_GETDMA, do_getdma, PM_PROC_NR);
+       CALLMAP(VM_ALLOCMEM, do_allocmem, PM_PROC_NR);
+
+       /* Requests from tty device driver (/dev/video). */
+       CALLMAP(VM_MAP_PHYS, do_map_phys, TTY_PROC_NR);
+       CALLMAP(VM_UNMAP_PHYS, do_unmap_phys, TTY_PROC_NR);
+
+       /* Requests from userland (source unrestricted). */
+       CALLMAP(VM_MMAP, do_mmap, ANY);
+
+       /* Requests (actually replies) from VFS (restricted to VFS only). */
+       CALLMAP(VM_VFS_REPLY_OPEN, do_vfs_reply, VFS_PROC_NR);
+       CALLMAP(VM_VFS_REPLY_MMAP, do_vfs_reply, VFS_PROC_NR);
+       CALLMAP(VM_VFS_REPLY_CLOSE, do_vfs_reply, VFS_PROC_NR);
+}
+
diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c
new file mode 100644 (file)
index 0000000..2c07a0b
--- /dev/null
@@ -0,0 +1,161 @@
+
+#define _SYSTEM 1
+
+#define VERBOSE 0
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+#include <minix/safecopies.h>
+
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <string.h>
+#include <env.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <memory.h>
+
+#include "glo.h"
+#include "proto.h"
+#include "util.h"
+#include "region.h"
+
+/*===========================================================================*
+ *                             do_mmap                                      *
+ *===========================================================================*/
+PUBLIC int do_mmap(message *m)
+{
+       int r, n;
+       struct vmproc *vmp;
+       int mfflags = 0;
+       struct vir_region *vr = NULL;
+
+       if((r=vm_isokendpt(m->m_source, &n)) != OK) {
+               vm_panic("do_mmap: message from strange source", m->m_source);
+       }
+
+       vmp = &vmproc[n];
+
+       if(m->VMM_FLAGS & MAP_LOWER16M)
+               printf("VM: warning for %d: MAP_LOWER16M not implemented\n",
+                       m->m_source);
+
+       if(!(vmp->vm_flags & VMF_HASPT))
+               return ENXIO;
+
+       if(m->VMM_FD == -1 || (m->VMM_FLAGS & MAP_ANON)) {
+               int s;
+               vir_bytes v;
+               size_t len = (vir_bytes) m->VMM_LEN;
+
+               if(m->VMM_FD != -1) {
+                       return EINVAL;
+               }
+
+               if(m->VMM_FLAGS & MAP_CONTIG) mfflags |= MF_CONTIG;
+               if(m->VMM_FLAGS & MAP_PREALLOC) mfflags |= MF_PREALLOC;
+
+               if(len % VM_PAGE_SIZE)
+                       len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);
+
+               if(!(vr = map_page_region(vmp, vmp->vm_stacktop,
+                       VM_DATATOP, len, 0,
+                       VR_ANON | VR_WRITABLE, mfflags))) {
+                       return ENOMEM;
+               }
+       } else {
+               return ENOSYS;
+       }
+
+       /* Return mapping, as seen from process. */
+       vm_assert(vr);
+       m->VMM_RETADDR = arch_map2vir(vmp, vr->vaddr);
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             do_map_phys                                  *
+ *===========================================================================*/
+PUBLIC int do_map_phys(message *m)
+{
+       int r, n;
+       struct vmproc *vmp;
+       endpoint_t target;
+       struct vir_region *vr;
+
+       target = m->VMMP_EP;
+       if(target == SELF)
+               target = m->m_source;
+
+       if((r=vm_isokendpt(target, &n)) != OK) {
+               printf("do_map_phys: bogus target %d\n", target);
+               return EINVAL;
+       }
+
+       vmp = &vmproc[n];
+
+       if(!(vmp->vm_flags & VMF_HASPT))
+               return ENXIO;
+
+       if(!(vr = map_page_region(vmp, vmp->vm_stacktop, VM_DATATOP,
+               (vir_bytes) m->VMMP_LEN, (vir_bytes)m->VMMP_PHADDR,
+               VR_DIRECT | VR_NOPF | VR_WRITABLE, 0))) {
+               printf("VM:do_map_phys: map_page_region failed\n");
+               return ENOMEM;
+       }
+
+       m->VMMP_VADDR_REPLY = (void *) arch_map2vir(vmp, vr->vaddr);
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             do_unmap_phys                                *
+ *===========================================================================*/
+PUBLIC int do_unmap_phys(message *m)
+{
+       int r, n;
+       struct vmproc *vmp;
+       endpoint_t target;
+       struct vir_region *region;
+
+       target = m->VMUP_EP;
+       if(target == SELF)
+               target = m->m_source;
+
+       if((r=vm_isokendpt(target, &n)) != OK) {
+               printf("VM:do_unmap_phys: bogus target %d\n", target);
+               return EINVAL;
+       }
+
+       vmp = &vmproc[n];
+
+       if(!(region = map_lookup(vmp, (vir_bytes) m->VMUM_ADDR))) {
+               printf("VM:do_unmap_phys: map_lookup failed\n");
+               return EINVAL;
+       }
+
+       if(!(region->flags & VR_DIRECT)) {
+               printf("VM:do_unmap_phys: region not a DIRECT mapping\n");
+               return EINVAL;
+       }
+
+       if(map_unmap_region(vmp, region) != OK) {
+               printf("VM:do_unmap_phys: map_unmap_region failed\n");
+               return EINVAL;
+       }
+
+       return OK;
+}
diff --git a/servers/vm/pagefaults.c b/servers/vm/pagefaults.c
new file mode 100644 (file)
index 0000000..2f70d7c
--- /dev/null
@@ -0,0 +1,175 @@
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+#include <minix/safecopies.h>
+
+#include <errno.h>
+#include <string.h>
+#include <env.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <pagefaults.h>
+
+#include "glo.h"
+#include "proto.h"
+#include "memory.h"
+#include "util.h"
+#include "region.h"
+
+static char *pferr(int err)
+{
+       static char buf[100];
+
+       sprintf(buf, "err 0x%lx ", err);
+       if(PFERR_NOPAGE(err)) strcat(buf, "nopage ");
+       if(PFERR_PROT(err)) strcat(buf, "protection ");
+       if(PFERR_WRITE(err)) strcat(buf, "write");
+       if(PFERR_READ(err)) strcat(buf, "read");
+
+       return buf;
+}
+
+/*===========================================================================*
+ *                             handle_pagefaults                            *
+ *===========================================================================*/
+PUBLIC void handle_pagefaults(void)
+{
+       endpoint_t ep;
+       u32_t addr, err;
+       struct vmproc *vmp;
+       int r, s;
+
+       while((r=arch_get_pagefault(&ep, &addr, &err)) == OK) {
+               struct vir_region *region;
+               vir_bytes offset;
+               int p, wr = PFERR_WRITE(err);
+
+               if(vm_isokendpt(ep, &p) != OK)
+                       vm_panic("handle_pagefaults: endpoint wrong", ep);
+
+               vmp = &vmproc[p];
+               vm_assert(vmp->vm_flags & VMF_INUSE);
+
+               /* See if address is valid at all. */
+               if(!(region = map_lookup(vmp, addr))) {
+                       vm_assert(PFERR_NOPAGE(err));
+                       printf("VM: SIGSEGV %d bad addr 0x%lx error 0x%lx\n", 
+                               ep, addr, err);
+                       if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
+                               vm_panic("sys_kill failed", s);
+                       continue;
+               }
+
+               /* Make sure this isn't a region that isn't supposed
+                * to cause pagefaults.
+                */
+               vm_assert(!(region->flags & VR_NOPF));
+
+               /* If process was writing, see if it's writable. */
+               if(!(region->flags & VR_WRITABLE) && wr) {
+                       printf("VM: SIGSEGV %d ro map 0x%lx error 0x%lx\n", 
+                               ep, addr, err);
+                       if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
+                               vm_panic("sys_kill failed", s);
+                       continue;
+               }
+
+               vm_assert(addr > region->vaddr);
+               offset = addr - region->vaddr;
+
+               /* Access is allowed; handle it. */
+               if((r=map_pagefault(vmp, region, offset, wr)) != OK) {
+                       printf("VM: SIGSEGV %d pagefault not handled\n", ep);
+                       if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
+                               vm_panic("sys_kill failed", s);
+                       continue;
+               }
+
+
+               /* Pagefault is handled, so now reactivate the process. */
+               if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
+                       vm_panic("handle_pagefaults: sys_vmctl failed", ep);
+       }
+
+       return;
+}
+
+/*===========================================================================*
+ *                             handle_memory                        *
+ *===========================================================================*/
+PUBLIC void handle_memory(void)
+{
+       int r, s;
+       endpoint_t who;
+       vir_bytes mem;
+       vir_bytes len;
+       int wrflag;
+
+       while((r=sys_vmctl_get_memreq(&who, &mem, &len, &wrflag)) == OK) {
+               int p, r = OK;
+               struct vir_region *region;
+               struct vmproc *vmp;
+               vir_bytes o;
+
+               if(vm_isokendpt(who, &p) != OK)
+                       vm_panic("handle_memory: endpoint wrong", who);
+               vmp = &vmproc[p];
+
+               /* Page-align memory and length. */
+               o = mem % VM_PAGE_SIZE;
+               mem -= o;
+               len += o;
+               o = len % VM_PAGE_SIZE;
+               if(o > 0) len += VM_PAGE_SIZE - o;
+
+               if(!(region = map_lookup(vmp, mem))) {
+                       printf("VM: handle_memory: memory doesn't exist\n");
+                       r = EFAULT;
+               } else if(mem + len > region->vaddr + region->length) {
+                       vm_assert(region->vaddr <= mem);
+                       vm_panic("handle_memory: not contained", NO_NUM);
+               } else if(!(region->flags & VR_WRITABLE) && wrflag) {
+                       printf("VM: handle_memory: write to unwritable map\n");
+                       r = EFAULT;
+               } else {
+                       vir_bytes offset;
+                       vm_assert(region->vaddr <= mem);
+                       vm_assert(!(region->flags & VR_NOPF));
+                       vm_assert(!(region->vaddr % VM_PAGE_SIZE));
+                       offset = mem - region->vaddr;
+
+                       r = map_handle_memory(vmp, region, offset, len, wrflag);
+               }
+
+               if(r != OK) {
+                       printf("VM: SIGSEGV %d, memory range not available\n",
+                               vmp->vm_endpoint);
+                       if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
+                               vm_panic("sys_kill failed", s);
+               }
+
+               if(sys_vmctl(who, VMCTL_MEMREQ_REPLY, r) != OK)
+                       vm_panic("handle_memory: sys_vmctl failed", r);
+
+               if(r != OK) {
+                       printf("VM: killing %d\n", vmp->vm_endpoint);
+                       if((s=sys_kill(vmp->vm_endpoint, SIGSEGV)) != OK)
+                               vm_panic("sys_kill failed", s);
+               }
+       }
+}
+
diff --git a/servers/vm/proto.h b/servers/vm/proto.h
new file mode 100644 (file)
index 0000000..9e0aa2b
--- /dev/null
@@ -0,0 +1,139 @@
+/* Function prototypes. */
+
+struct vmproc;
+struct stat;
+struct mem_map;
+struct memory;
+
+#include <minix/ipc.h>
+#include <minix/endpoint.h>
+#include <minix/safecopies.h>
+#include <timers.h>
+#include <stdio.h>
+#include <pagetable.h>
+#include "vmproc.h"
+#include "vm.h"
+
+/* alloc.c */
+_PROTOTYPE( phys_clicks alloc_mem_f, (phys_clicks clicks, u32_t flags) );
+_PROTOTYPE( int do_adddma, (message *msg)                              );
+_PROTOTYPE( int do_deldma, (message *msg)                              );
+_PROTOTYPE( int do_getdma, (message *msg)                              );
+_PROTOTYPE( int do_allocmem, (message *msg)                              );
+_PROTOTYPE( void release_dma, (struct vmproc *vmp)                     );
+
+_PROTOTYPE( void free_mem_f, (phys_clicks base, phys_clicks clicks)    );
+
+#define ALLOC_MEM(clicks, flags) alloc_mem_f(clicks, flags)
+#define FREE_MEM(base, clicks) free_mem_f(base, clicks)
+
+_PROTOTYPE( void mem_init, (struct memory *chunks)                     );
+_PROTOTYPE( void memstats, (void)                                      );
+
+/* utility.c */
+_PROTOTYPE( int get_mem_map, (int proc_nr, struct mem_map *mem_map)     );
+_PROTOTYPE( void get_mem_chunks, (struct memory *mem_chunks));
+_PROTOTYPE( void reserve_proc_mem, (struct memory *mem_chunks,
+        struct mem_map *map_ptr));
+_PROTOTYPE( int vm_isokendpt, (endpoint_t ep, int *proc)            );
+_PROTOTYPE( int get_stack_ptr, (int proc_nr, vir_bytes *sp)             );
+
+/* exit.c */
+_PROTOTYPE( void clear_proc, (struct vmproc *vmp)                      );
+_PROTOTYPE( int do_exit, (message *msg)                                        );
+_PROTOTYPE( int do_willexit, (message *msg)                            );
+_PROTOTYPE( void free_proc, (struct vmproc *vmp)                       );
+
+/* fork.c */
+_PROTOTYPE( int do_fork, (message *msg)                                        );
+
+/* exec.c */
+_PROTOTYPE( struct vmproc *find_share, (struct vmproc *vmp_ign, Ino_t ino,
+                        Dev_t dev, time_t ctime)                        );
+_PROTOTYPE( int do_exec_newmem, (message *msg)                         );
+
+/* break.c */
+_PROTOTYPE( int do_brk, (message *msg)                                 );
+_PROTOTYPE( int adjust, (struct vmproc *rmp,
+       vir_clicks data_clicks, vir_bytes sp)           );
+_PROTOTYPE( int real_brk, (struct vmproc *vmp, vir_bytes v));
+
+/* signal.c */
+_PROTOTYPE( int do_push_sig, (message *msg)                            );
+
+/* vfs.c */
+_PROTOTYPE( int do_vfs_reply, (message *msg)                           );
+_PROTOTYPE( int vfs_open, (struct vmproc *for_who, callback_t callback,
+        cp_grant_id_t filename_gid, int filename_len, int flags, int mode));
+_PROTOTYPE( int vfs_close, (struct vmproc *for_who, callback_t callback,
+       int fd));
+
+/* mmap.c */
+_PROTOTYPE(int do_mmap, (message *msg)                                 );
+_PROTOTYPE(int do_map_phys, (message *msg)                              );
+_PROTOTYPE(int do_unmap_phys, (message *msg)                            );
+
+/* pagefaults.c */
+_PROTOTYPE( void handle_pagefaults, (void)                             );
+_PROTOTYPE( void handle_memory, (void)                         );
+
+/* $(ARCH)/pagetable.c */
+_PROTOTYPE( void pt_init, (void)                                       );
+_PROTOTYPE( int pt_new, (pt_t *pt)                                     );
+_PROTOTYPE( int pt_copy, (pt_t *src, pt_t *dst)                                );
+_PROTOTYPE( void pt_free, (pt_t *pt)                                   );
+_PROTOTYPE( void pt_freerange, (pt_t *pt, vir_bytes lo, vir_bytes hi)  );
+_PROTOTYPE( int pt_allocmap, (pt_t *pt, vir_bytes minv, vir_bytes maxv,
+       size_t bytes, u32_t pageflags, u32_t allocflags, vir_bytes *newv));
+_PROTOTYPE( int pt_writemap, (pt_t *pt, vir_bytes v, phys_bytes physaddr, 
+        size_t bytes, u32_t flags, u32_t writemapflags));
+_PROTOTYPE( int pt_bind, (pt_t *pt, struct vmproc *who)                        );
+_PROTOTYPE( void *vm_allocpages, (phys_bytes *p, int pages, int cat));
+_PROTOTYPE( void pt_cycle, (void));
+_PROTOTYPE( int pt_mapkernel, (pt_t *pt));
+_PROTOTYPE( void phys_readaddr, (phys_bytes addr, phys_bytes *v1, phys_bytes *v2));
+_PROTOTYPE( void phys_writeaddr, (phys_bytes addr, phys_bytes v1, phys_bytes v2));
+#if SANITYCHECKS
+_PROTOTYPE( void pt_sanitycheck, (pt_t *pt, char *file, int line)      );
+#endif
+
+/* $(ARCH)/pagefaults.c */
+_PROTOTYPE( int arch_get_pagefault, (endpoint_t *who, vir_bytes *addr, u32_t *err));
+
+/* slaballoc.c */
+_PROTOTYPE(void *slaballoc,(int bytes));
+_PROTOTYPE(void slabfree,(void *mem, int bytes));
+_PROTOTYPE(void slabstats,(void));
+#define SLABALLOC(var) (var = slaballoc(sizeof(*var)))
+#define SLABFREE(ptr) slabfree(ptr, sizeof(*(ptr)))
+
+/* region.c */
+_PROTOTYPE(struct vir_region * map_page_region,(struct vmproc *vmp, \
+       vir_bytes min, vir_bytes max, vir_bytes length, vir_bytes what, \
+       u32_t flags, int mapflags));
+_PROTOTYPE(struct vir_region * map_proc_kernel,(struct vmproc *dst));
+_PROTOTYPE(int map_region_extend,(struct vir_region *vr, vir_bytes delta));
+_PROTOTYPE(int map_region_shrink,(struct vir_region *vr, vir_bytes delta));
+_PROTOTYPE(int map_unmap_region,(struct vmproc *vmp, struct vir_region *vr));
+_PROTOTYPE(int map_free_proc,(struct vmproc *vmp));
+_PROTOTYPE(int map_proc_copy,(struct vmproc *dst, struct vmproc *src));
+_PROTOTYPE(struct vir_region *map_lookup,(struct vmproc *vmp, vir_bytes addr));
+_PROTOTYPE(int map_pagefault,(struct vmproc *vmp,
+       struct vir_region *region, vir_bytes offset, int write));
+_PROTOTYPE(int map_handle_memory,(struct vmproc *vmp,
+       struct vir_region *region, vir_bytes offset, vir_bytes len, int write));
+
+_PROTOTYPE(struct vir_region * map_region_lookup_tag, (struct vmproc *vmp, u32_t tag));
+_PROTOTYPE(void map_region_set_tag, (struct vir_region *vr, u32_t tag));
+_PROTOTYPE(u32_t map_region_get_tag, (struct vir_region *vr));
+
+
+#if SANITYCHECKS
+_PROTOTYPE(void map_sanitycheck,(char *file, int line));
+#endif
+
+/* $(ARCH)/vm.c */
+_PROTOTYPE( void arch_init_vm, (struct memory mem_chunks[NR_MEMS]));
+_PROTOTYPE( vir_bytes, arch_map2vir(struct vmproc *vmp, vir_bytes addr));
+_PROTOTYPE( vir_bytes, arch_vir2map(struct vmproc *vmp, vir_bytes addr));
+
diff --git a/servers/vm/region.c b/servers/vm/region.c
new file mode 100644 (file)
index 0000000..66f9778
--- /dev/null
@@ -0,0 +1,929 @@
+
+#define _SYSTEM 1
+
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include <minix/type.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+#include <sys/mman.h>
+
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdint.h>
+#include <memory.h>
+
+#include "vm.h"
+#include "proto.h"
+#include "util.h"
+#include "glo.h"
+#include "region.h"
+#include "sanitycheck.h"
+
+FORWARD _PROTOTYPE(int map_new_physblock, (struct vmproc *vmp,
+       struct vir_region *region, vir_bytes offset, vir_bytes length,
+       phys_bytes what, struct phys_region *physhint));
+
+FORWARD _PROTOTYPE(int map_copy_ph_block, (struct vmproc *vmp, struct vir_region *region, struct phys_region *ph));
+FORWARD _PROTOTYPE(struct vir_region *map_copy_region, (struct vir_region *));
+
+#if SANITYCHECKS
+
+FORWARD _PROTOTYPE(void map_printmap, (struct vmproc *vmp));
+
+PRIVATE char *map_name(struct vir_region *vr)
+{
+       int type = vr->flags & (VR_ANON|VR_DIRECT);
+       switch(type) {
+               case VR_ANON:
+                       return "anonymous";
+               case VR_DIRECT:
+                       return "direct";
+               default:
+                       vm_panic("unknown mapping type", type);
+       }
+
+       return "NOTREACHED";
+}
+
+
+/*===========================================================================*
+ *                             map_printmap                                 *
+ *===========================================================================*/
+PRIVATE void map_printmap(vmp)
+struct vmproc *vmp;
+{
+       struct vir_region *vr;
+       printf("%d:\n", vmp->vm_endpoint);
+       for(vr = vmp->vm_regions; vr; vr = vr->next) {
+               struct phys_region *ph;
+               printf("\t0x%08lx - 0x%08lx: %s  (0x%lx)\n",
+                       vr->vaddr, vr->vaddr + vr->length, map_name(vr), vr);
+               for(ph = vr->first; ph; ph = ph->next) {
+                       printf("0x%lx-0x%lx(%d) ",
+                               vr->vaddr + ph->ph->offset,
+                               vr->vaddr + ph->ph->offset + ph->ph->length,
+                               ph->ph->refcount);
+               }
+               printf("\n");
+       }
+}
+
+/*===========================================================================*
+ *                             map_sanitycheck                      *
+ *===========================================================================*/
+PUBLIC void map_sanitycheck(char *file, int line)
+{
+       struct vmproc *vmp;
+
+/* Macro for looping over all physical blocks of all regions of
+ * all processes.
+ */
+#define ALLREGIONS(regioncode, physcode)                       \
+       for(vmp = vmproc; vmp <= &vmproc[_NR_PROCS]; vmp++) {   \
+               struct vir_region *vr;                          \
+               if(!(vmp->vm_flags & VMF_INUSE))                \
+                       continue;                               \
+               for(vr = vmp->vm_regions; vr; vr = vr->next) {  \
+                       struct phys_region *pr;                 \
+                       regioncode;                             \
+                       for(pr = vr->first; pr; pr = pr->next) { \
+                               physcode;                       \
+                       }                                       \
+               }                                               \
+       }
+
+       /* Do counting for consistency check. */
+       ALLREGIONS(;,pr->ph->seencount = 0;);
+       ALLREGIONS(;,pr->ph->seencount++;);
+
+       /* Do consistency check. */
+       ALLREGIONS(if(vr->next) {
+                       MYASSERT(vr->vaddr < vr->next->vaddr);
+                       MYASSERT(vr->vaddr + vr->length <= vr->next->vaddr);
+               }
+               MYASSERT(!(vr->vaddr % VM_PAGE_SIZE));, 
+               if(pr->ph->refcount != pr->ph->seencount) {
+                       map_printmap(vmp);
+                       printf("ph in vr 0x%lx: 0x%lx-0x%lx  refcount %d "
+                               "but seencount %lu\n", 
+                               vr, pr->ph->offset,
+                               pr->ph->offset + pr->ph->length,
+                               pr->ph->refcount, pr->ph->seencount);
+               }
+               MYASSERT(pr->ph->refcount == pr->ph->seencount);
+               MYASSERT(!(pr->ph->offset % VM_PAGE_SIZE));
+               MYASSERT(!(pr->ph->length % VM_PAGE_SIZE)););
+}
+#endif
+
+
+/*=========================================================================*
+ *                             map_ph_writept                          *
+ *=========================================================================*/
+PUBLIC int map_ph_writept(struct vmproc *vmp, struct vir_region *vr,
+       struct phys_block *pb, int *ropages, int *rwpages)
+{
+       int rw;
+
+       vm_assert(!(vr->vaddr % VM_PAGE_SIZE));
+       vm_assert(!(pb->length % VM_PAGE_SIZE));
+       vm_assert(!(pb->offset % VM_PAGE_SIZE));
+       vm_assert(pb->refcount > 0);
+
+       if((vr->flags & VR_WRITABLE)
+       && (pb->refcount == 1 || (vr->flags & VR_DIRECT)))
+               rw = PTF_WRITE;
+       else
+               rw = 0;
+
+#if SANITYCHECKS
+       if(rwpages && ropages && (vr->flags & VR_ANON)) {
+               int pages;
+               pages = pb->length / VM_PAGE_SIZE;
+               if(rw)
+                       (*rwpages) += pages;
+               else
+                       (*ropages) += pages;
+       }
+#endif
+
+       if(pt_writemap(&vmp->vm_pt, vr->vaddr + pb->offset,
+         pb->phys, pb->length, PTF_PRESENT | PTF_USER | rw,
+               WMF_OVERWRITE) != OK) {
+           printf("VM: map_writept: pt_writemap failed\n");
+           return ENOMEM;
+       }
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             map_region                                   *
+ *===========================================================================*/
+PUBLIC struct vir_region *map_page_region(vmp, minv, maxv, length,
+       what, flags, mapflags)
+struct vmproc *vmp;
+vir_bytes minv;
+vir_bytes maxv;
+vir_bytes length;
+vir_bytes what;
+u32_t flags;
+int mapflags;
+{
+       struct vir_region *vr, *prevregion = NULL, *newregion,
+               *firstregion = vmp->vm_regions;
+       vir_bytes startv;
+       int foundflag = 0;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       /* We must be in paged mode to be able to do this. */
+       vm_assert(vm_paged);
+
+       /* Length must be reasonable. */
+       vm_assert(length > 0);
+
+       /* Special case: allow caller to set maxv to 0 meaning 'I want
+        * it to be mapped in right here.'
+        */
+        if(maxv == 0) {
+                maxv = minv + length;
+
+                /* Sanity check. */
+                if(maxv <= minv) {
+                        printf("map_page_region: minv 0x%lx and bytes 0x%lx\n",
+                                minv, length);
+                        return NULL;
+                }
+        }
+
+       /* Basic input sanity checks. */
+       vm_assert(!(length % VM_PAGE_SIZE));
+       if(minv >= maxv) {
+               printf("VM: 1 minv: 0x%lx maxv: 0x%lx length: 0x%lx\n",
+                       minv, maxv, length);
+       }
+       vm_assert(minv < maxv);
+       vm_assert(minv + length <= maxv);
+
+#define FREEVRANGE(rangestart, rangeend, foundcode) {          \
+       vir_bytes frstart = (rangestart), frend = (rangeend);   \
+       frstart = MAX(frstart, minv);                           \
+       frend   = MIN(frend, maxv);                             \
+       if(frend > frstart && (frend - frstart) >= length) {    \
+               startv = frstart;                               \
+               foundflag = 1;                                  \
+               foundcode;                                      \
+       } }
+
+       /* This is the free virtual address space before the first region. */
+       FREEVRANGE(0, firstregion ? firstregion->vaddr : VM_DATATOP, ;);
+
+       if(!foundflag) {
+               for(vr = vmp->vm_regions; vr && !foundflag; vr = vr->next) {
+                       FREEVRANGE(vr->vaddr + vr->length,
+                         vr->next ? vr->next->vaddr : VM_DATATOP,
+                               prevregion = vr;);
+               }
+       }
+
+       if(!foundflag) {
+               printf("VM: map_page_region: no 0x%lx bytes found for %d between 0x%lx and 0x%lx\n",
+                       length, vmp->vm_endpoint, minv, maxv);
+               return NULL;
+       }
+
+#if SANITYCHECKS
+       if(prevregion) vm_assert(prevregion->vaddr < startv);
+#endif
+
+       /* However we got it, startv must be in the requested range. */
+       vm_assert(startv >= minv);
+       vm_assert(startv < maxv);
+       vm_assert(startv + length <= maxv);
+
+       /* Now we want a new region. */
+       if(!SLABALLOC(newregion)) {
+               printf("VM: map_page_region: allocating region failed\n");
+               return NULL;
+       }
+
+       /* Fill in node details. */
+       newregion->vaddr = startv;
+       newregion->length = length;
+       newregion->first = NULL;
+       newregion->flags = flags;
+       newregion->tag = VRT_NONE;
+
+       /* If this is a 'direct' mapping, try to actually map it. */
+       if(flags & VR_DIRECT) {
+               vm_assert(!(length % VM_PAGE_SIZE));
+               vm_assert(!(startv % VM_PAGE_SIZE));
+               vm_assert(!newregion->first);
+               vm_assert(!(mapflags & MF_PREALLOC));
+               if(map_new_physblock(vmp, newregion, 0, length, what, NULL) != OK) {
+                       printf("VM: map_new_physblock failed\n");
+                       SLABFREE(newregion);
+                       return NULL;
+               }
+               vm_assert(newregion->first);
+               vm_assert(!newregion->first->next);
+               if(map_ph_writept(vmp, newregion, newregion->first->ph, NULL, NULL) != OK) {
+                       printf("VM: map_region_writept failed\n");
+                       SLABFREE(newregion);
+                       return NULL;
+               }
+       }
+
+       if((flags & VR_ANON) && (mapflags & MF_PREALLOC)) {
+               if(map_handle_memory(vmp, newregion, 0, length, 1) != OK) {
+                       printf("VM:map_page_region: prealloc failed\n");
+                       SLABFREE(newregion);
+                       return NULL;
+               }
+       }
+
+       /* Link it. */
+       if(prevregion) {
+               vm_assert(prevregion->vaddr < newregion->vaddr);
+               newregion->next = prevregion->next;
+               prevregion->next = newregion;
+       } else {
+               newregion->next = vmp->vm_regions;
+               vmp->vm_regions = newregion;
+       }
+
+#if SANITYCHECKS
+       vm_assert(startv == newregion->vaddr);
+       if(newregion->next) {
+               vm_assert(newregion->vaddr < newregion->next->vaddr);
+       }
+#endif
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       return newregion;
+}
+
+
+/*===========================================================================*
+ *                             map_free                                     *
+ *===========================================================================*/
+PRIVATE int map_free(struct vir_region *region)
+{
+       struct phys_region *pr, *nextpr;
+
+       for(pr = region->first; pr; pr = nextpr) {
+               vm_assert(pr->ph->refcount > 0);
+               pr->ph->refcount--;
+               nextpr = pr->next;
+               region->first = nextpr; /* For sanity checks. */
+               if(pr->ph->refcount == 0) {
+                       if(region->flags & VR_ANON) {
+                               FREE_MEM(ABS2CLICK(pr->ph->phys),
+                                       ABS2CLICK(pr->ph->length));
+                       } else if(region->flags & VR_DIRECT) {
+                               ; /* No action required. */
+                       } else {
+                               vm_panic("strange phys flags", NO_NUM);
+                       }
+                       SLABFREE(pr->ph);
+               }
+               SLABFREE(pr);
+       }
+
+       SLABFREE(region);
+
+       return OK;
+}
+
+/*========================================================================*
+ *                             map_free_proc                             *
+ *========================================================================*/
+PUBLIC int map_free_proc(vmp)
+struct vmproc *vmp;
+{
+       struct vir_region *r, *nextr;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       for(r = vmp->vm_regions; r; r = nextr) {
+               nextr = r->next;
+               map_free(r);
+               vmp->vm_regions = nextr;        /* For sanity checks. */
+       }
+
+       vmp->vm_regions = NULL;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             map_lookup                                   *
+ *===========================================================================*/
+PUBLIC struct vir_region *map_lookup(vmp, offset)
+struct vmproc *vmp;
+vir_bytes offset;
+{
+       struct vir_region *r;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       if(!vmp->vm_regions)
+               vm_panic("process has no regions", vmp->vm_endpoint);
+
+       for(r = vmp->vm_regions; r; r = r->next) {
+               if(offset >= r->vaddr && offset < r->vaddr + r->length)
+                       return r;
+       }
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       return NULL;
+}
+
+
+/*===========================================================================*
+ *                             map_new_physblock                            *
+ *===========================================================================*/
+PRIVATE int map_new_physblock(vmp, region, offset, length, what_mem, physhint)
+struct vmproc *vmp;
+struct vir_region *region;
+vir_bytes offset;
+vir_bytes length;
+phys_bytes what_mem;
+struct phys_region *physhint;
+{
+       struct phys_region *physr, *newphysr;
+       struct phys_block *newpb;
+       phys_bytes mem_clicks, clicks;
+       vir_bytes mem;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       vm_assert(!(length % VM_PAGE_SIZE));
+       if(!physhint) physhint = region->first;
+
+       /* Allocate things necessary for this chunk of memory. */
+       if(!SLABALLOC(newphysr))
+               return ENOMEM;
+       if(!SLABALLOC(newpb)) {
+               SLABFREE(newphysr);
+               return ENOMEM;
+       }
+
+       /* Memory for new physical block. */
+       clicks = CLICKSPERPAGE * length / VM_PAGE_SIZE;
+       if(!what_mem) {
+               if((mem_clicks = ALLOC_MEM(clicks, PAF_CLEAR)) == NO_MEM) {
+                       SLABFREE(newpb);
+                       SLABFREE(newphysr);
+                       return ENOMEM;
+               }
+               mem = CLICK2ABS(mem_clicks);
+       } else {
+               mem = what_mem;
+       }
+
+       /* New physical block. */
+       newpb->phys = mem;
+       newpb->refcount = 1;
+       newpb->offset = offset;
+       newpb->length = length;
+
+       /* New physical region. */
+       newphysr->ph = newpb;
+
+       /* Update pagetable. */
+       vm_assert(!(length % VM_PAGE_SIZE));
+       vm_assert(!(newpb->length % VM_PAGE_SIZE));
+       if(map_ph_writept(vmp, region, newpb, NULL, NULL) != OK) {
+               if(!what_mem)
+                       FREE_MEM(mem_clicks, clicks);
+               SLABFREE(newpb);
+               SLABFREE(newphysr);
+               return ENOMEM;
+       }
+
+       if(!region->first || offset < region->first->ph->offset) {
+               /* Special case: offset is before start. */
+               if(region->first) {
+                       vm_assert(offset + length <= region->first->ph->offset);
+               }
+               newphysr->next = region->first;
+               region->first = newphysr;
+       } else {
+               for(physr = physhint; physr; physr = physr->next) {
+                       if(!physr->next || physr->next->ph->offset > offset) {
+                               newphysr->next = physr->next;
+                               physr->next = newphysr;
+                               break;
+                       }
+               }
+
+               /* Loop must have put the node somewhere. */
+               vm_assert(physr->next == newphysr);
+       }
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       return OK;
+}
+
+
+/*===========================================================================*
+ *                             map_copy_ph_block                            *
+ *===========================================================================*/
+PRIVATE int map_copy_ph_block(vmp, region, ph)
+struct vmproc *vmp;
+struct vir_region *region;
+struct phys_region *ph;
+{
+       int r;
+       phys_bytes newmem, newmem_cl, clicks;
+       struct phys_block *newpb;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       /* This is only to be done if there is more than one copy. */
+       vm_assert(ph->ph->refcount > 1);
+
+       /* Do actal copy on write; allocate new physblock. */
+       if(!SLABALLOC(newpb)) {
+               printf("VM: map_copy_ph_block: couldn't allocate newpb\n");
+               SANITYCHECK(SCL_FUNCTIONS);
+               return ENOMEM;
+       }
+
+       clicks = CLICKSPERPAGE * ph->ph->length / VM_PAGE_SIZE;
+       vm_assert(CLICK2ABS(clicks) == ph->ph->length);
+       if((newmem_cl = ALLOC_MEM(clicks, 0)) == NO_MEM) {
+               SLABFREE(newpb);
+               return ENOMEM;
+       }
+       newmem = CLICK2ABS(newmem_cl);
+
+       ph->ph->refcount--;
+       vm_assert(ph->ph->refcount > 0);
+       newpb->length = ph->ph->length;
+       newpb->offset = ph->ph->offset;
+       newpb->refcount = 1;
+       newpb->phys = newmem;
+
+       /* Copy old memory to new memory. */
+       if((r=sys_abscopy(ph->ph->phys, newpb->phys, newpb->length)) != OK) {
+               printf("VM: map_copy_ph_block: sys_abscopy failed\n");
+               SANITYCHECK(SCL_FUNCTIONS);
+               return r;
+       }
+
+#if VMSTATS
+       vmp->vm_bytecopies += newpb->length;
+#endif
+
+       /* Reference new block. */
+       ph->ph = newpb;
+
+       /* Check reference counts. */
+       SANITYCHECK(SCL_DETAIL);
+
+       /* Update pagetable with new address.
+        * This will also make it writable.
+        */
+       r = map_ph_writept(vmp, region, ph->ph, NULL, NULL);
+       if(r != OK)
+               vm_panic("map_copy_ph_block: map_ph_writept failed", r);
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       return OK;
+}
+
+/*===========================================================================*
+ *                             map_pagefault                        *
+ *===========================================================================*/
+PUBLIC int map_pagefault(vmp, region, offset, write)
+struct vmproc *vmp;
+struct vir_region *region;
+vir_bytes offset;
+int write;
+{
+       vir_bytes virpage;
+       struct phys_region *ph;
+       int r;
+
+       vm_assert(offset >= 0);
+       vm_assert(offset < region->length);
+
+       vm_assert(region->flags & VR_ANON);
+       vm_assert(!(region->vaddr % VM_PAGE_SIZE));
+
+       virpage = offset - offset % VM_PAGE_SIZE;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       for(ph = region->first; ph; ph = ph->next)
+               if(ph->ph->offset <= offset && offset < ph->ph->offset + ph->ph->length)
+                       break;
+
+       if(ph) {
+               /* Pagefault in existing block. Do copy-on-write. */
+               vm_assert(write);
+               vm_assert(region->flags & VR_WRITABLE);
+               vm_assert(ph->ph->refcount > 0);
+
+               if(ph->ph->refcount == 1)
+                       r = map_ph_writept(vmp, region, ph->ph, NULL, NULL);
+               else
+                       r = map_copy_ph_block(vmp, region, ph);
+       } else {
+               /* Pagefault in non-existing block. Map in new block. */
+#if 0
+               if(!write) {
+                       printf("VM: read from uninitialized memory by %d\n",
+                               vmp->vm_endpoint);
+               }
+#endif
+               r = map_new_physblock(vmp, region, virpage, VM_PAGE_SIZE, 0,
+                       region->first);
+       }
+
+       if(r != OK)
+               printf("VM: map_pagefault: failed (%d)\n", r);
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       return r;
+}
+
+/*===========================================================================*
+ *                             map_handle_memory                            *
+ *===========================================================================*/
+PUBLIC int map_handle_memory(vmp, region, offset, length, write)
+struct vmproc *vmp;
+struct vir_region *region;
+vir_bytes offset, length;
+int write;
+{
+       struct phys_region *physr;
+       int changes = 0;
+
+#define FREE_RANGE_HERE(er1, er2) {                                    \
+       struct phys_region *r1 = (er1), *r2 = (er2);                    \
+       vir_bytes start = offset, end = offset + length;                \
+       if(r1) { start = MAX(start, r1->ph->offset + r1->ph->length); } \
+       if(r2) { end   = MIN(end, r2->ph->offset); }                    \
+       if(start < end) {                                               \
+               int r;                                                  \
+               SANITYCHECK(SCL_DETAIL);                                \
+               if((r=map_new_physblock(vmp, region, start,             \
+                       end-start, 0, r1 ? r1 : r2)) != OK) {           \
+                       SANITYCHECK(SCL_DETAIL);                        \
+                       return r;                                       \
+               }                                                       \
+               changes++;                                              \
+       } }
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       vm_assert(region->flags & VR_ANON);
+       vm_assert(!(region->vaddr % VM_PAGE_SIZE));
+       vm_assert(!(offset % VM_PAGE_SIZE));
+       vm_assert(!(length % VM_PAGE_SIZE));
+       vm_assert(!write || (region->flags & VR_WRITABLE));
+
+       FREE_RANGE_HERE(NULL, region->first);
+
+       for(physr = region->first; physr; physr = physr->next) {
+               int r;
+
+               SANITYCHECK(SCL_DETAIL);
+
+               if(write) {
+                 vm_assert(physr->ph->refcount > 0);
+                 if(physr->ph->refcount > 1) {
+                       SANITYCHECK(SCL_DETAIL);
+                       r = map_copy_ph_block(vmp, region, physr);
+                       if(r != OK) {
+                               printf("VM: map_handle_memory: no copy\n");
+                               return r;
+                       }
+                       changes++;
+                       SANITYCHECK(SCL_DETAIL);
+                 } else {
+                       SANITYCHECK(SCL_DETAIL);
+                       if((r=map_ph_writept(vmp, region, physr->ph, NULL, NULL)) != OK) {
+                               printf("VM: map_ph_writept failed\n");
+                               return r;
+                       }
+                       changes++;
+                       SANITYCHECK(SCL_DETAIL);
+                 }
+               }
+
+               SANITYCHECK(SCL_DETAIL);
+               FREE_RANGE_HERE(physr, physr->next);
+               SANITYCHECK(SCL_DETAIL);
+       }
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+#if SANITYCHECKS
+       if(changes == 0)  {
+               vm_panic("no changes?!", changes);
+       }
+#endif
+
+       return OK;
+}
+
+#if SANITYCHECKS
+static int countregions(struct vir_region *vr)
+{
+       int n = 0;
+       struct phys_region *ph;
+       for(ph = vr->first; ph; ph = ph->next)
+               n++;
+       return n;
+}
+#endif
+
+/*===========================================================================*
+ *                             map_copy_region                         *
+ *===========================================================================*/
+PRIVATE struct vir_region *map_copy_region(struct vir_region *vr)
+{
+       struct vir_region *newvr;
+       struct phys_region *ph, *prevph = NULL;
+#if SANITYCHECKS
+       int cr;
+       cr = countregions(vr);
+#endif
+       if(!SLABALLOC(newvr))
+               return NULL;
+       *newvr = *vr;
+       newvr->first = NULL;
+       newvr->next = NULL;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       for(ph = vr->first; ph; ph = ph->next) {
+               struct phys_region *newph;
+               if(!SLABALLOC(newph)) {
+                       map_free(newvr);
+                       return NULL;
+               }
+               newph->next = NULL;
+               newph->ph = ph->ph;
+               if(prevph) prevph->next = newph;
+               else newvr->first = newph;
+               prevph = newph;
+               SANITYCHECK(SCL_DETAIL);
+               vm_assert(countregions(vr) == cr);
+       }
+
+       vm_assert(countregions(vr) == countregions(newvr));
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       return newvr;
+}
+
+/*=========================================================================*
+ *                             map_writept                             *
+ *=========================================================================*/
+PUBLIC int map_writept(struct vmproc *vmp)
+{
+       struct vir_region *vr;
+       struct phys_region *ph;
+       int ropages = 0, rwpages = 0;
+
+       for(vr = vmp->vm_regions; vr; vr = vr->next)
+               for(ph = vr->first; ph; ph = ph->next) {
+                       map_ph_writept(vmp, vr, ph->ph, &ropages, &rwpages);
+               }
+
+       return OK;
+}
+
+/*========================================================================*
+ *                             map_proc_copy                             *
+ *========================================================================*/
+PUBLIC int map_proc_copy(dst, src)
+struct vmproc *dst;
+struct vmproc *src;
+{
+       struct vir_region *vr, *prevvr = NULL;
+       dst->vm_regions = NULL;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+       for(vr = src->vm_regions; vr; vr = vr->next) {
+               struct vir_region *newvr;
+               struct phys_region *ph;
+       SANITYCHECK(SCL_DETAIL);
+               if(!(newvr = map_copy_region(vr))) {
+                       map_free_proc(dst);
+       SANITYCHECK(SCL_FUNCTIONS);
+                       return ENOMEM;
+               }
+               SANITYCHECK(SCL_DETAIL);
+               if(prevvr) { prevvr->next = newvr; }
+               else { dst->vm_regions = newvr; }
+               for(ph = vr->first; ph; ph = ph->next) {
+                       vm_assert(ph->ph->refcount > 0);
+                       ph->ph->refcount++;
+                       vm_assert(ph->ph->refcount > 1);
+               }
+               SANITYCHECK(SCL_DETAIL);
+               prevvr = newvr;
+       SANITYCHECK(SCL_DETAIL);
+       }
+       SANITYCHECK(SCL_DETAIL);
+
+       map_writept(src);
+       map_writept(dst);
+
+       SANITYCHECK(SCL_FUNCTIONS);
+       return OK;
+}
+
+/*========================================================================*
+ *                             map_proc_kernel                         *
+ *========================================================================*/
+PUBLIC struct vir_region *map_proc_kernel(struct vmproc *vmp)
+{
+       struct vir_region *vr;
+
+       /* We assume these are the first regions to be mapped to
+        * make the function a bit simpler (free all regions on error).
+        */
+       vm_assert(!vmp->vm_regions);
+       vm_assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE);
+       vm_assert(!(KERNEL_TEXT % VM_PAGE_SIZE));
+       vm_assert(!(KERNEL_TEXT_LEN % VM_PAGE_SIZE));
+       vm_assert(!(KERNEL_DATA % VM_PAGE_SIZE));
+       vm_assert(!(KERNEL_DATA_LEN % VM_PAGE_SIZE));
+
+       if(!(vr = map_page_region(vmp, KERNEL_TEXT, 0, KERNEL_TEXT_LEN, 
+               KERNEL_TEXT, VR_DIRECT | VR_WRITABLE | VR_NOPF, 0)) ||
+          !(vr = map_page_region(vmp, KERNEL_DATA, 0, KERNEL_DATA_LEN, 
+               KERNEL_DATA, VR_DIRECT | VR_WRITABLE | VR_NOPF, 0))) {
+               map_free_proc(vmp);
+               return NULL;
+       }
+
+       return vr; /* Return pointer not useful, just non-NULL. */
+}
+
+/*========================================================================*
+ *                             map_region_extend                       *
+ *========================================================================*/
+PUBLIC int map_region_extend(struct vir_region *vr, vir_bytes delta)
+{
+       vir_bytes end;
+
+       vm_assert(vr);
+       vm_assert(vr->flags & VR_ANON);
+       vm_assert(!(delta % VM_PAGE_SIZE));
+
+       if(!delta) return OK;
+       end = vr->vaddr + vr->length;
+       vm_assert(end >= vr->vaddr);
+
+       if(end + delta <= end) {
+               printf("VM: strange delta 0x%lx\n", delta);
+               return ENOMEM;
+       }
+
+       if(!vr->next || end + delta <= vr->next->vaddr) {
+               vr->length += delta;
+               return OK;
+       }
+
+       return ENOMEM;
+}
+
+/*========================================================================*
+ *                             map_region_shrink                       *
+ *========================================================================*/
+PUBLIC int map_region_shrink(struct vir_region *vr, vir_bytes delta)
+{
+       vm_assert(vr);
+       vm_assert(vr->flags & VR_ANON);
+       vm_assert(!(delta % VM_PAGE_SIZE));
+
+       printf("VM: ignoring region shrink\n");
+
+       return OK;
+}
+
+PUBLIC struct vir_region *map_region_lookup_tag(vmp, tag)
+struct vmproc *vmp;
+u32_t tag;
+{
+       struct vir_region *vr;
+
+       for(vr = vmp->vm_regions; vr; vr = vr->next)
+               if(vr->tag == tag)
+                       return vr;
+
+       return NULL;
+}
+
+PUBLIC void map_region_set_tag(struct vir_region *vr, u32_t tag)
+{
+       vr->tag = tag;
+}
+
+PUBLIC u32_t map_region_get_tag(struct vir_region *vr)
+{
+       return vr->tag;
+}
+
+/*========================================================================*
+ *                             map_unmap_region                        *
+ *========================================================================*/
+PUBLIC int map_unmap_region(struct vmproc *vmp, struct vir_region *region)
+{
+       struct vir_region *r, *nextr, *prev = NULL;
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       for(r = vmp->vm_regions; r; r = r->next) {
+               if(r == region)
+                       break;
+
+               prev = r;
+       }
+
+       SANITYCHECK(SCL_DETAIL);
+
+       if(r == NULL)
+               vm_panic("map_unmap_region: region not found\n", NO_NUM);
+
+       if(!prev)
+               vmp->vm_regions = r->next;
+       else
+               prev->next = r->next;
+       map_free(r);
+
+       SANITYCHECK(SCL_DETAIL);
+
+       if(pt_writemap(&vmp->vm_pt, r->vaddr,
+         0, r->length, 0, WMF_OVERWRITE) != OK) {
+           printf("VM: map_unmap_region: pt_writemap failed\n");
+           return ENOMEM;
+       }
+
+       SANITYCHECK(SCL_FUNCTIONS);
+
+       return OK;
+}
diff --git a/servers/vm/region.h b/servers/vm/region.h
new file mode 100644 (file)
index 0000000..a134ef7
--- /dev/null
@@ -0,0 +1,46 @@
+
+#ifndef _REGION_H
+#define _REGION_H 1
+
+struct phys_block {
+#if SANITYCHECKS
+       u32_t                   seencount;
+#endif
+       vir_bytes               offset; /* offset from start of vir region */
+       vir_bytes               length; /* no. of contiguous bytes */
+       phys_bytes              phys;   /* physical memory */
+       u8_t                    refcount;       /* Refcount of these pages */
+};
+
+struct phys_region {
+       struct phys_region      *next;  /* next contiguous block */
+       struct phys_block       *ph;
+};
+
+struct vir_region {
+       struct vir_region *next; /* next virtual region in this process */
+       vir_bytes       vaddr;  /* virtual address, offset from pagetable */
+       vir_bytes       length; /* length in bytes */
+       struct  phys_region *first; /* phys regions in vir region */
+       u16_t           flags;
+       u32_t tag;              /* Opaque to mapping code. */
+};
+
+/* Mapping flags: */
+#define VR_WRITABLE    0x01    /* Process may write here. */
+#define VR_NOPF                0x02    /* May not generate page faults. */
+
+/* Mapping type: */
+#define VR_ANON                0x10    /* Memory to be cleared and allocated */
+#define VR_DIRECT      0x20    /* Mapped, but not managed by VM */
+
+/* Tag values: */
+#define VRT_NONE       0xBEEF0000
+#define VRT_HEAP       0xBEEF0001
+
+/* map_page_region flags */
+#define MF_PREALLOC    0x01
+#define MF_CONTIG      0x02
+
+#endif
+
diff --git a/servers/vm/sanitycheck.h b/servers/vm/sanitycheck.h
new file mode 100644 (file)
index 0000000..cc53879
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _SANITYCHECK_H
+#define _SANITYCHECK_H 1
+
+#include "vm.h"
+#include "glo.h"
+
+#if SANITYCHECKS
+
+/* This macro is used in the sanity check functions, where file and 
+ * line are function arguments.
+ */
+#define MYASSERT(c) do { if(!(c)) { \
+        printf("VM:%s:%d: %s failed\n", file, line, #c); \
+       vm_panic("sanity check failed", NO_NUM); } } while(0)
+
+#define SANITYCHECK(l) if((l) <= vm_sanitychecklevel) {  \
+               int failflag = 0; \
+               u32_t *origptr = CHECKADDR;\
+               int _sanep; \
+               struct vmproc *vmp;     \
+                                       \
+                for(_sanep = 0; _sanep < sizeof(data1) / sizeof(*origptr); \
+                       _sanep++) {    \
+                        if(origptr[_sanep] != data1[_sanep]) {    \
+                                printf("%d: %08lx != %08lx  ", \
+               _sanep, origptr[_sanep], data1[_sanep]); failflag = 1;   \
+                        }                       \
+                }                               \
+        if(failflag) {                         \
+               printf("%s:%d: memory corruption test failed\n", \
+                       __FILE__, __LINE__);            \
+               vm_panic("memory corruption", NO_NUM);  \
+       }  \
+       for(vmp = vmproc; vmp <= &vmproc[_NR_PROCS]; vmp++) { \
+               if((vmp->vm_flags & (VMF_INUSE | VMF_HASPT)) == \
+                       (VMF_INUSE | VMF_HASPT)) { \
+                       pt_sanitycheck(&vmp->vm_pt, __FILE__, __LINE__); \
+               } \
+       } \
+       map_sanitycheck(__FILE__, __LINE__); \
+       } 
+#else
+#define SANITYCHECK 
+#endif
+
+#endif
diff --git a/servers/vm/signal.c b/servers/vm/signal.c
new file mode 100644 (file)
index 0000000..a43e769
--- /dev/null
@@ -0,0 +1,64 @@
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+#include <sys/sigcontext.h>
+
+#include <errno.h>
+#include <env.h>
+
+#include "glo.h"
+#include "vm.h"
+#include "proto.h"
+#include "util.h"
+
+#define DATA_CHANGED       1    /* flag value when data segment size changed */
+#define STACK_CHANGED      2    /* flag value when stack size changed */
+
+/*===========================================================================*
+ *                             do_push_sig                                  *
+ *===========================================================================*/
+PUBLIC int do_push_sig(message *msg)
+{
+       int r, n;
+       endpoint_t ep;
+       vir_bytes sp;
+       struct vmproc *vmp;
+
+       ep = msg->VMPS_ENDPOINT;
+
+       if((r=vm_isokendpt(ep, &n)) != OK) {
+               printf("VM: bogus endpoint %d from %d\n", ep, msg->m_source);
+               return r;
+       }
+       vmp = &vmproc[n];
+
+        if ((r=get_stack_ptr(ep, &sp)) != OK)
+                vm_panic("couldn't get new stack pointer (for sig)",r);
+       
+       /* Save old SP for caller */
+       msg->VMPS_OLD_SP = (char *) sp;
+   
+        /* Make room for the sigcontext and sigframe struct. */
+        sp -= sizeof(struct sigcontext)
+                                 + 3 * sizeof(char *) + 2 * sizeof(int);
+
+        if ((r=adjust(vmp, vmp->vm_arch.vm_seg[D].mem_len, sp)) != OK) {
+               printf("VM: do_push_sig: adjust() failed: %d\n", r);
+               return r;
+       }
+
+       return OK;
+}
+
diff --git a/servers/vm/slaballoc.c b/servers/vm/slaballoc.c
new file mode 100644 (file)
index 0000000..87b3661
--- /dev/null
@@ -0,0 +1,399 @@
+
+#define _SYSTEM 1
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+
+#include <errno.h>
+#include <string.h>
+#include <env.h>
+
+#include <memory.h>
+
+#include "glo.h"
+#include "proto.h"
+#include "util.h"
+#include "sanitycheck.h"
+
+#define SLABSIZES 60
+
+#define ITEMSPERPAGE(s, bytes) (DATABYTES / (bytes))
+
+#define ELBITS         (sizeof(element_t)*8)
+#define BITPAT(b)      (1UL << ((b) %  ELBITS))
+#define BITEL(f, b)    (f)->sdh.usebits[(b)/ELBITS]
+
+
+#define OFF(f, b) vm_assert(!GETBIT(f, b))
+#define ON(f, b)  vm_assert(GETBIT(f, b))
+
+#define GETBIT(f, b)     (BITEL(f,b) &   BITPAT(b))
+#define SETBIT(f, b)   {OFF(f,b); (BITEL(f,b)|= BITPAT(b)); (f)->sdh.nused++; }
+#define CLEARBIT(f, b) {ON(f, b); (BITEL(f,b)&=~BITPAT(b)); (f)->sdh.nused--; (f)->sdh.freeguess = (b); }
+
+#define MINSIZE 8
+#define MAXSIZE (SLABSIZES-1+MINSIZE)
+#define USEELEMENTS (1+(VM_PAGE_SIZE/MINSIZE/8))
+
+PRIVATE int pages = 0;
+
+typedef u8_t element_t;
+#define BITS_FULL (~(element_t)0)
+typedef element_t elements_t[USEELEMENTS];
+
+/* This file is too low-level to have global SANITYCHECKs everywhere,
+ * as the (other) data structures are often necessarily in an
+ * inconsistent state during a slaballoc() / slabfree(). So only do
+ * our own sanity checks here, with SLABSANITYCHECK.
+ */
+#if SANITYCHECKS
+#define SLABSANITYCHECK(l) if((l) <= vm_sanitychecklevel) { \
+       slab_sanitycheck(__FILE__, __LINE__); }
+#else
+#define SLABSANITYCHECK(l)
+#endif
+
+struct sdh {
+       u8_t list;
+       u16_t nused;    /* Number of data items used in this slab. */
+#if SANITYCHECKS
+       u32_t magic;
+#endif
+       int freeguess;
+       struct slabdata *next, *prev;
+       elements_t usebits;
+       phys_bytes phys;
+};
+
+#define DATABYTES      (VM_PAGE_SIZE-sizeof(struct sdh))
+
+#define MAGIC 0x1f5b842f
+#define JUNK  0xdeadbeef
+#define NOJUNK 0xc0ffee
+
+#define LIST_UNUSED    0
+#define LIST_FREE      1
+#define LIST_USED      2
+#define LIST_FULL      3
+#define LIST_NUMBER    4
+
+PRIVATE struct slabheader {
+       struct slabdata {
+               struct  sdh sdh;
+               u8_t    data[DATABYTES];
+       } *list_head[LIST_NUMBER];
+} slabs[SLABSIZES];
+
+#define GETSLAB(b, s) {                        \
+       int i;                          \
+       vm_assert((b) >= MINSIZE);      \
+       i = (b) - MINSIZE;              \
+       vm_assert((i) < SLABSIZES);     \
+       vm_assert((i) >= 0);            \
+       s = &slabs[i];                  \
+}
+
+#define LH(sl, l) (sl)->list_head[l]
+
+#define MOVEHEAD(sl, l1, l2) {         \
+       struct slabdata *t;             \
+       vm_assert(LH(sl,l1));           \
+       REMOVEHEAD(sl, l1, t);          \
+       ADDHEAD(t, sl, l2);             \
+}
+
+#define REMOVEHEAD(sl, list, to) {     \
+       (to) = LH(sl, list);            \
+       vm_assert(to);                  \
+       LH(sl, list) = (to)->sdh.next;  \
+       if(LH(sl, list)) LH(sl, list) = NULL; \
+       vm_assert((to)->sdh.magic == MAGIC);\
+       vm_assert(!(to)->sdh.prev);             \
+}
+
+#define ADDHEAD(nw, sl, l) {                   \
+       vm_assert((nw)->sdh.magic == MAGIC);    \
+       (nw)->sdh.next = LH(sl, l);                     \
+       (nw)->sdh.prev = NULL;                  \
+       (nw)->sdh.list = l;                             \
+       LH(sl, l) = (nw);                       \
+       if((nw)->sdh.next) (nw)->sdh.next->sdh.prev = (nw);     \
+}
+
+#define UNLINKNODE(n)  {                               \
+       if((f)->sdh.prev) (f)->sdh.prev->sdh.next = (f)->sdh.next;      \
+       if((f)->sdh.next) (f)->sdh.next->sdh.prev = (f)->sdh.prev;      \
+       }
+
+struct slabdata *newslabdata(int list)
+{
+       struct slabdata *n;
+       phys_bytes p;
+
+       vm_assert(sizeof(*n) == VM_PAGE_SIZE);
+
+       if(!(n = vm_allocpages(&p, 1, VMP_SLAB)))
+               return NULL;
+       memset(n->sdh.usebits, 0, sizeof(n->sdh.usebits));
+       pages++;
+
+       n->sdh.phys = p;
+#if SANITYCHECKS
+       n->sdh.magic = MAGIC;
+#endif
+       n->sdh.nused = 0;
+       n->sdh.freeguess = 0;
+       n->sdh.list = list;
+
+       return n;
+}
+
+#if SANITYCHECKS
+
+/*===========================================================================*
+ *                             checklist                                    *
+ *===========================================================================*/
+PRIVATE int checklist(char *file, int line,
+       struct slabheader *s, int l, int bytes)
+{
+       struct slabdata *n = s->list_head[l];
+       int ch = 0;
+
+       while(n) {
+               int count = 0, i;
+               MYASSERT(n->sdh.list == l);
+               MYASSERT(n->sdh.magic == MAGIC);
+               if(n->sdh.prev)
+                       MYASSERT(n->sdh.prev->sdh.next == n);
+               else
+                       MYASSERT(s->list_head[l] == n);
+               if(n->sdh.next) MYASSERT(n->sdh.next->sdh.prev == n);
+               for(i = 0; i < USEELEMENTS*8; i++)
+                       if(i >= ITEMSPERPAGE(s, bytes))
+                               MYASSERT(!GETBIT(n, i));
+                       else
+                               if(GETBIT(n,i))
+                                       count++;
+               MYASSERT(count == n->sdh.nused);
+               ch += count;
+               n = n->sdh.next;
+       }
+
+       return ch;
+}
+
+/*===========================================================================*
+ *                             void slab_sanitycheck                        *
+ *===========================================================================*/
+PUBLIC void slab_sanitycheck(char *file, int line)
+{
+       int s;
+       for(s = 0; s < SLABSIZES; s++) {
+               int l;
+               for(l = 0; l < LIST_NUMBER; l++) {
+                       checklist(file, line, &slabs[s], l, s + MINSIZE);
+               }
+       }
+}
+
+#endif
+
+/*===========================================================================*
+ *                             void *slaballoc                              *
+ *===========================================================================*/
+PUBLIC void *slaballoc(int bytes)
+{
+       int i, n = 0;
+       struct slabheader *s;
+       struct slabdata *firstused;
+
+       SLABSANITYCHECK(SCL_FUNCTIONS);
+
+       /* Retrieve entry in slabs[]. */
+       GETSLAB(bytes, s);
+       vm_assert(s);
+
+       /* To make the common case more common, make space in the 'used'
+        * queue first.
+        */
+       if(!LH(s, LIST_USED)) {
+               /* Make sure there is something on the freelist. */
+       SLABSANITYCHECK(SCL_DETAIL);
+               if(!LH(s, LIST_FREE)) {
+                       struct slabdata *n = newslabdata(LIST_FREE);
+       SLABSANITYCHECK(SCL_DETAIL);
+                       if(!n) return NULL;
+                       ADDHEAD(n, s, LIST_FREE);
+       SLABSANITYCHECK(SCL_DETAIL);
+               }
+
+
+       SLABSANITYCHECK(SCL_DETAIL);
+               MOVEHEAD(s, LIST_FREE, LIST_USED);
+       SLABSANITYCHECK(SCL_DETAIL);
+
+       }
+       SLABSANITYCHECK(SCL_DETAIL);
+
+       vm_assert(s);
+       firstused = LH(s, LIST_USED);
+       vm_assert(firstused);
+       vm_assert(firstused->sdh.magic == MAGIC);
+
+       for(i = firstused->sdh.freeguess; n < ITEMSPERPAGE(s, bytes); n++, i++) {
+       SLABSANITYCHECK(SCL_DETAIL);
+               i = i % ITEMSPERPAGE(s, bytes);
+
+               if(!GETBIT(firstused, i)) {
+                       struct slabdata *f;
+                       char *ret;
+                       SETBIT(firstused, i);
+       SLABSANITYCHECK(SCL_DETAIL);
+                       if(firstused->sdh.nused == ITEMSPERPAGE(s, bytes)) {
+       SLABSANITYCHECK(SCL_DETAIL);
+                               MOVEHEAD(s, LIST_USED, LIST_FULL);
+       SLABSANITYCHECK(SCL_DETAIL);
+                       }
+       SLABSANITYCHECK(SCL_DETAIL);
+                       ret = ((char *) firstused->data) + i*bytes;
+
+#if SANITYCHECKS
+                       f = (struct slabdata *) ((char *) ret - (vir_bytes) ret % VM_PAGE_SIZE);
+                       if(f->sdh.magic != MAGIC) {
+                               printf("slaballoc bogus pointer 0x%lx, "
+                                       "rounded 0x%lx, bad magic 0x%lx\n",
+                                       ret, f, f->sdh.magic);
+                               vm_panic("slaballoc check failed", NO_NUM);
+                       }
+                       *(u32_t *) ret = NOJUNK;
+#endif
+                       SLABSANITYCHECK(SCL_FUNCTIONS);
+                       firstused->sdh.freeguess = i+1;
+                       return ret;
+               }
+
+       SLABSANITYCHECK(SCL_DETAIL);
+
+       }
+       SLABSANITYCHECK(SCL_FUNCTIONS);
+
+       vm_panic("slaballoc: no space in 'used' slabdata", NO_NUM);
+
+       /* Not reached. */
+       return NULL;
+}
+
+/*===========================================================================*
+ *                             void *slabfree                               *
+ *===========================================================================*/
+PUBLIC void slabfree(void *mem, int bytes)
+{
+       int i;
+       struct slabheader *s;
+       struct slabdata *f;
+
+       SLABSANITYCHECK(SCL_FUNCTIONS);
+
+#if SANITYCHECKS
+       if(*(u32_t *) mem == JUNK) {
+               printf("VM: WARNING: likely double free, JUNK seen\n");
+       }
+#endif
+
+       /* Retrieve entry in slabs[]. */
+       GETSLAB(bytes, s);
+
+       /* Round address down to VM_PAGE_SIZE boundary to get header. */
+       f = (struct slabdata *) ((char *) mem - (vir_bytes) mem % VM_PAGE_SIZE);
+
+       vm_assert(f->sdh.magic == MAGIC);
+       vm_assert(f->sdh.list == LIST_USED || f->sdh.list == LIST_FULL);
+
+       /* Make sure it's in range. */
+       vm_assert((char *) mem >= (char *) f->data);
+       vm_assert((char *) mem < (char *) f->data + sizeof(f->data));
+
+       /* Get position. */
+       i = (char *) mem - (char *) f->data;
+       vm_assert(!(i % bytes));
+       i = i / bytes;
+
+       /* Make sure it _was_ allocated. */
+       vm_assert(GETBIT(f, i));
+
+       /* Free this data. */
+       CLEARBIT(f, i);
+
+#if SANITYCHECKS
+       *(u32_t *) mem = JUNK;
+#endif
+
+       /* Check if this slab changes lists. */
+       if(f->sdh.nused == 0) {
+               /* Now become FREE; must've been USED */
+               vm_assert(f->sdh.list == LIST_USED);
+               UNLINKNODE(f);
+               if(f == LH(s, LIST_USED))
+                       LH(s, LIST_USED) = f->sdh.next;
+               ADDHEAD(f, s, LIST_FREE);
+               SLABSANITYCHECK(SCL_DETAIL);
+       } else if(f->sdh.nused == ITEMSPERPAGE(s, bytes)-1) {
+               /* Now become USED; must've been FULL */
+               vm_assert(f->sdh.list == LIST_FULL);
+               UNLINKNODE(f);
+               if(f == LH(s, LIST_FULL))
+                       LH(s, LIST_FULL) = f->sdh.next;
+               ADDHEAD(f, s, LIST_USED);
+               SLABSANITYCHECK(SCL_DETAIL);
+       } else {
+               /* Stay USED */
+               vm_assert(f->sdh.list == LIST_USED);
+       }
+
+       SLABSANITYCHECK(SCL_FUNCTIONS);
+
+       return;
+}
+
+#if SANITYCHECKS
+/*===========================================================================*
+ *                             void slabstats                               *
+ *===========================================================================*/
+PUBLIC void slabstats(void)
+{
+       int s, total = 0, totalbytes = 0;
+       static int n;
+       n++;
+       if(n%1000) return;
+       for(s = 0; s < SLABSIZES; s++) {
+               int l;
+               for(l = 0; l < LIST_NUMBER; l++) {
+                       int b, t;
+                       b = s + MINSIZE;
+                       t = checklist(__FILE__, __LINE__, &slabs[s], l, b);
+
+                       if(t > 0) {
+                               int bytes = t * b;
+                               printf("VMSTATS: %2d slabs: %d (%dkB)\n", b, t, bytes/1024);
+                               totalbytes += bytes;
+                       }
+               }
+       }
+
+       if(pages > 0) {
+               printf("VMSTATS: %dK net used in slab objects in %d pages (%dkB): %d%% utilization\n",
+                       totalbytes/1024, pages, pages*VM_PAGE_SIZE/1024,
+                               100 * totalbytes / (pages*VM_PAGE_SIZE));
+       }
+}
+#endif
diff --git a/servers/vm/util.h b/servers/vm/util.h
new file mode 100644 (file)
index 0000000..2b5bd63
--- /dev/null
@@ -0,0 +1,28 @@
+
+#ifndef _UTIL_H
+#define _UTIL_H 1
+
+#include "vm.h"
+#include "glo.h"
+
+#define ELEMENTS(a) (sizeof(a)/sizeof((a)[0]))
+
+#if SANITYCHECKS
+#define vm_assert(cond) {                              \
+       if(vm_sanitychecklevel > 0 && !(cond)) {        \
+               printf("VM:%s:%d: assert failed: %s\n", \
+                       __FILE__, __LINE__, #cond);     \
+               panic("VM", "assert failed", NO_NUM);   \
+       }                                               \
+       }
+#else
+#define vm_assert(cond)        ;
+#endif
+
+#define vm_panic(str, n) { char _pline[100]; \
+       sprintf(_pline, "%s:%d: %s", __FILE__, __LINE__, (str));        \
+       panic("VM", _pline, (n));                                       \
+       }
+
+#endif
+
diff --git a/servers/vm/utility.c b/servers/vm/utility.c
new file mode 100644 (file)
index 0000000..7ddd253
--- /dev/null
@@ -0,0 +1,165 @@
+
+/* This file contains some utility routines for VM.  */
+
+#define _SYSTEM 1
+
+#define _MINIX 1       /* To get the brk() prototype (as _brk()). */
+#define brk _brk       /* Our brk() must redefine _brk(). */
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+#include <minix/type.h>
+#include <string.h>
+#include <errno.h>
+#include <env.h>
+#include <unistd.h>
+
+#include "proto.h"
+#include "glo.h"
+#include "util.h"
+
+#include <archconst.h>
+#include <archtypes.h>
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+
+/*===========================================================================*
+ *                              get_mem_map                                  *
+ *===========================================================================*/
+PUBLIC int get_mem_map(proc_nr, mem_map)
+int proc_nr;                                    /* process to get map of */
+struct mem_map *mem_map;                        /* put memory map here */
+{
+       struct proc p;
+       int s;
+
+       if ((s=sys_getproc(&p, proc_nr)) != OK)
+               return(s);
+
+       memcpy(mem_map, p.p_memmap, sizeof(p.p_memmap));
+       return(OK);
+}
+
+/*===========================================================================*
+ *                              get_mem_chunks                               *
+ *===========================================================================*/
+PUBLIC void get_mem_chunks(mem_chunks)
+struct memory *mem_chunks;                      /* store mem chunks here */ 
+{  
+/* Initialize the free memory list from the 'memory' boot variable.  Translate
+ * the byte offsets and sizes in this list to clicks, properly truncated.
+ */
+  long base, size, limit;
+  int i;
+  struct memory *memp;
+
+  /* Obtain and parse memory from system environment. */
+  if(env_memory_parse(mem_chunks, NR_MEMS) != OK) 
+        vm_panic("couldn't obtain memory chunks", NO_NUM); 
+   
+  /* Round physical memory to clicks. Round start up, round end down. */
+  for (i = 0; i < NR_MEMS; i++) {
+        memp = &mem_chunks[i];          /* next mem chunk is stored here */
+        base = mem_chunks[i].base;
+        size = mem_chunks[i].size;
+        limit = base + size;
+        base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
+        limit &= ~(long)(CLICK_SIZE-1);
+        if (limit <= base) {
+                memp->base = memp->size = 0;
+        } else { 
+                memp->base = base >> CLICK_SHIFT;
+                memp->size = (limit - base) >> CLICK_SHIFT;
+        }
+  }
+}  
+
+/*===========================================================================*
+ *                              reserve_proc_mem                             *
+ *===========================================================================*/
+PUBLIC void reserve_proc_mem(mem_chunks, map_ptr)
+struct memory *mem_chunks;                      /* store mem chunks here */
+struct mem_map *map_ptr;                        /* memory to remove */
+{
+/* Remove server memory from the free memory list. The boot monitor
+ * promises to put processes at the start of memory chunks. The 
+ * tasks all use same base address, so only the first task changes
+ * the memory lists. The servers and init have their own memory
+ * spaces and their memory will be removed from the list.
+ */
+  struct memory *memp;
+  for (memp = mem_chunks; memp < &mem_chunks[NR_MEMS]; memp++) {
+        if (memp->base == map_ptr[T].mem_phys) {
+                memp->base += map_ptr[T].mem_len + map_ptr[S].mem_vir;
+                memp->size -= map_ptr[T].mem_len + map_ptr[S].mem_vir;
+                break;
+        }
+  }
+  if (memp >= &mem_chunks[NR_MEMS])
+  {
+        vm_panic("reserve_proc_mem: can't find map in mem_chunks ",
+                map_ptr[T].mem_phys);
+  }
+} 
+
+/*===========================================================================*
+ *                              vm_isokendpt                                        *
+ *===========================================================================*/
+PUBLIC int vm_isokendpt(endpoint_t endpoint, int *proc)
+{
+        *proc = _ENDPOINT_P(endpoint);
+        if(*proc < -NR_TASKS || *proc >= NR_PROCS)
+                return EINVAL;
+        if(*proc >= 0 && endpoint != vmproc[*proc].vm_endpoint)
+                return EDEADSRCDST;
+        if(*proc >= 0 && !(vmproc[*proc].vm_flags & VMF_INUSE))
+                return EDEADSRCDST;
+        return OK;
+}
+
+
+struct proc mytmpproc;
+
+/*===========================================================================*
+ *                              get_stack_ptr                                *
+ *===========================================================================*/
+PUBLIC int get_stack_ptr(proc_nr_e, sp)
+int proc_nr_e;                                  /* process to get sp of */   
+vir_bytes *sp;                                  /* put stack pointer here */
+{
+  int s; 
+  
+  if ((s=sys_getproc(&mytmpproc, proc_nr_e)) != OK)     
+        return(s);
+  *sp = mytmpproc.p_reg.sp;
+  return(OK);
+}       
+
+/*===========================================================================*
+ *                              _brk                                         *
+ *===========================================================================*/
+extern char *_brksize;
+PUBLIC int brk(brk_addr)
+char *brk_addr;
+{
+        int r;
+       struct vmproc *vmm = &vmproc[VM_PROC_NR];
+
+/* VM wants to call brk() itself. */
+        if((r=real_brk(vmm, (vir_bytes) brk_addr)) != OK)
+               vm_panic("VM: brk() on myself failed\n", NO_NUM);
+        _brksize = brk_addr;
+        return 0;
+}
+
diff --git a/servers/vm/vfs.c b/servers/vm/vfs.c
new file mode 100644 (file)
index 0000000..62f89fe
--- /dev/null
@@ -0,0 +1,140 @@
+
+#define _SYSTEM 1
+
+#define VERBOSE 0
+
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <minix/ds.h>
+#include <minix/endpoint.h>
+#include <minix/keymap.h>
+#include <minix/minlib.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/sysutil.h>
+#include <minix/syslib.h>
+#include <minix/safecopies.h>
+
+#include <errno.h>
+#include <string.h>
+#include <env.h>
+#include <stdio.h>
+
+#include "glo.h"
+#include "proto.h"
+#include "util.h"
+
+/*===========================================================================*
+ *                             register_callback                            *
+ *===========================================================================*/
+PRIVATE void register_callback(struct vmproc *for_who, callback_t callback,
+       int callback_type)
+{
+       if(for_who->vm_callback) {
+               vm_panic("register_callback: callback already registered",
+                       for_who->vm_callback_type);
+       }
+       for_who->vm_callback = callback;
+       for_who->vm_callback_type = callback_type;
+
+       return;
+}
+
+/*===========================================================================*
+ *                             vfs_open                                     *
+ *===========================================================================*/
+PUBLIC int vfs_open(struct vmproc *for_who, callback_t callback,
+       cp_grant_id_t filename_gid, int filename_len, int flags, int mode)
+{
+       static message m;
+       int r;
+
+       register_callback(for_who, callback, VM_VFS_REPLY_OPEN);
+
+       m.m_type = VM_VFS_OPEN;
+       m.VMVO_NAME_GRANT = filename_gid;
+       m.VMVO_NAME_LENGTH = filename_len;
+       m.VMVO_FLAGS = flags;
+       m.VMVO_MODE = mode;
+       m.VMVO_ENDPOINT = for_who->vm_endpoint;
+
+       if((r=asynsend(VFS_PROC_NR, &m)) != OK) {
+               vm_panic("vfs_open: asynsend failed", r);
+       }
+
+       return r;
+}
+
+/*===========================================================================*
+ *                             vfs_close                                    *
+ *===========================================================================*/
+PUBLIC int vfs_close(struct vmproc *for_who, callback_t callback, int fd)
+{
+       static message m;
+       int r;
+
+       register_callback(for_who, callback, VM_VFS_REPLY_CLOSE);
+
+       m.m_type = VM_VFS_CLOSE;
+       m.VMVC_ENDPOINT = for_who->vm_endpoint;
+       m.VMVC_FD = fd;
+
+       if((r=asynsend(VFS_PROC_NR, &m)) != OK) {
+               vm_panic("vfs_close: asynsend failed", r);
+       }
+
+       return r;
+}
+
+/*===========================================================================*
+ *                             do_vfs_reply                            *
+ *===========================================================================*/
+PUBLIC int do_vfs_reply(message *m)
+{
+/* Reply to a request has been received from vfs. Handle it. First verify
+ * and look up which process, identified by endpoint, this is about.
+ * Then call the callback function that was registered when the request
+ * was done. Return result to vfs.
+ */
+       endpoint_t ep;
+       struct vmproc *vmp;
+       int procno;
+       callback_t cb;
+       ep = m->VMV_ENDPOINT;
+       if(vm_isokendpt(ep, &procno) != OK) {
+               printf("VM:do_vfs_reply: reply %d about invalid endpoint %d\n",
+                       m->m_type, ep);
+               vm_panic("do_vfs_reply: invalid endpoint from vfs", NO_NUM);
+       }
+       vmp = &vmproc[procno];
+       if(!vmp->vm_callback) {
+               printf("VM:do_vfs_reply: reply %d: endpoint %d not waiting\n",
+                       m->m_type, ep);
+               vm_panic("do_vfs_reply: invalid endpoint from vfs", NO_NUM);
+       }
+       if(vmp->vm_callback_type != m->m_type) {
+               printf("VM:do_vfs_reply: reply %d unexpected for endpoint %d\n"
+                 " (expecting %d)\n", m->m_type, ep, vmp->vm_callback_type);
+               vm_panic("do_vfs_reply: invalid reply from vfs", NO_NUM);
+       }
+       if(vmp->vm_flags & VMF_EXITING) {
+               /* This is not fatal or impossible, but the callback
+                * function has to realize it shouldn't do any PM or
+                * VFS calls for this process.
+                */
+               printf("VM:do_vfs_reply: reply %d for EXITING endpoint %d\n",
+                 m->m_type, ep);
+       }
+
+       /* All desired callback state has been used, so save and reset
+        * the callback. This allows the callback to register another
+        * one.
+        */
+       cb = vmp->vm_callback;
+       vmp->vm_callback = NULL;
+       cb(vmp, m);
+       return SUSPEND;
+}
+
diff --git a/servers/vm/vm.h b/servers/vm/vm.h
new file mode 100644 (file)
index 0000000..323f4a7
--- /dev/null
@@ -0,0 +1,33 @@
+
+#define NO_MEM ((phys_clicks) 0)  /* returned by alloc_mem() with mem is up */
+
+/* Memory flags to pt_allocmap() and alloc_mem(). */
+#define PAF_CLEAR      0x01    /* Clear physical memory. */
+#define PAF_CONTIG     0x02    /* Physically contiguous. */
+
+/* special value for v in pt_allocmap */
+#define AM_AUTO         ((u32_t) -1)
+
+#define CLICK2ABS(v) ((v) << CLICK_SHIFT)
+#define ABS2CLICK(a) ((a) >> CLICK_SHIFT)
+
+/* Compile in asserts and custom sanity checks at all? */
+#define SANITYCHECKS   0
+#define VMSTATS                1
+
+/* If so, this level: */
+#define SCL_NONE       0       /* No sanity checks - vm_assert()s only. */
+#define SCL_TOP                1       /* Main loop and other high-level places. */
+#define SCL_FUNCTIONS  2       /* Function entry/exit. */
+#define SCL_DETAIL     3       /* Detailled steps. */
+#define SCL_MAX                3       /* Highest value. */
+
+/* Type of page allocations. */
+#define VMP_SPARE      0
+#define VMP_PAGETABLE  1
+#define VMP_PAGEDIR    2
+#define VMP_SLAB       3
+#define VMP_CATEGORIES 4
+
+/* Flags to pt_writemap(). */
+#define WMF_OVERWRITE  0x01    /* Caller knows map may overwrite. */
diff --git a/servers/vm/vmproc.h b/servers/vm/vmproc.h
new file mode 100644 (file)
index 0000000..66a8305
--- /dev/null
@@ -0,0 +1,59 @@
+
+#ifndef _VMPROC_H 
+#define _VMPROC_H 1
+
+#include <pagetable.h>
+#include <arch_vmproc.h>
+
+#include "vm.h"
+
+struct vmproc;
+
+typedef void (*callback_t)(struct vmproc *who, message *m);
+
+struct vmproc {
+       struct vm_arch  vm_arch; /* architecture-specific data */
+       int             vm_flags;
+       endpoint_t      vm_endpoint;
+       pt_t            vm_pt;  /* page table data, if VMF_HASPT is set */
+       vir_bytes       vm_stacktop;    /* top of stack as seen from process */
+       vir_bytes       vm_offset;      /* offset of addr 0 for process */
+
+       /* File identification for cs sharing. */
+       ino_t vm_ino;           /* inode number of file */
+       dev_t vm_dev;           /* device number of file system */
+       time_t vm_ctime;        /* inode changed time */
+
+       /* Regions in virtual address space. */
+       struct vir_region *vm_regions;
+       int vm_count;
+
+       /* Heap for brk() to extend. */
+       struct vir_region *vm_heap;
+
+       /* State for requests pending to be done to vfs on behalf of
+        * this process.
+        */
+       callback_t vm_callback;   /* function to call on vfs reply */
+       int vm_callback_type; /* expected message type */
+
+       union {
+               struct {
+                       cp_grant_id_t gid;
+               } open; /* VM_VFS_OPEN */
+       } vm_state;             /* Callback state. */
+#if VMSTATS
+       int vm_bytecopies;
+#endif
+};
+
+/* Bits for vm_flags */
+#define VMF_INUSE      0x001   /* slot contains a process */
+#define VMF_SEPARATE   0x002   /* separate i&d */
+#define VMF_HASPT      0x004   /* has private page table */
+#define VMF_EXITING    0x008   /* PM is cleaning up this process */
+#define VMF_HAS_DMA    0x010   /* Process directly or indirectly granted
+                                * DMA buffers.
+                                */
+
+#endif
index 3b38786231143b7250081a99acbbfe1b1e4bf65e..e0f465a7376e0974db3a2daa501d2a11c0b489c4 100755 (executable)
@@ -15,6 +15,7 @@ PROGRAMS=     ../kernel/kernel \
        ../drivers/memory/memory \
        ../drivers/log/log \
        ../servers/mfs/mfs \
+       ../servers/vm/vm \
        ../servers/init/init
 
 usage: