]> Zhao Yanbai Git Server - minix.git/commitdiff
beng work in progress, to be explained in a future commit message :).
authorBen Gras <ben@minix3.org>
Thu, 28 May 2009 13:47:20 +0000 (13:47 +0000)
committerBen Gras <ben@minix3.org>
Thu, 28 May 2009 13:47:20 +0000 (13:47 +0000)
50 files changed:
drivers/memory/memory.c
drivers/tty/keyboard.c
include/minix/com.h
include/minix/config.h
include/minix/debug.h [new file with mode: 0644]
include/minix/type.h
include/sys/vm_i386.h
kernel/arch/i386/arch_do_vmctl.c
kernel/arch/i386/do_sdevio.c
kernel/arch/i386/exception.c
kernel/arch/i386/klib386.s
kernel/arch/i386/memory.c
kernel/arch/i386/mpx386.s
kernel/arch/i386/proto.h
kernel/arch/i386/system.c
kernel/arch/i386/vm.h
kernel/debug.c
kernel/debug.h
kernel/glo.h
kernel/main.c
kernel/proc.c
kernel/proc.h
kernel/proto.h
kernel/system.c
kernel/system.h
kernel/system/do_exec.c
kernel/system/do_fork.c
kernel/system/do_memset.c
kernel/system/do_vm_setbuf.c
kernel/system/do_vmctl.c
kernel/table.c
kernel/utility.c
kernel/vm.h
lib/sysutil/Makefile.in
servers/init/init.c
servers/mfs/cache.c
servers/pm/main.c
servers/vfs/fs.h
servers/vfs/main.c
servers/vm/exit.c
servers/vm/fork.c
servers/vm/i386/pagetable.c
servers/vm/i386/pagetable.h
servers/vm/i386/vm.c
servers/vm/main.c
servers/vm/pagefaults.c
servers/vm/proto.h
servers/vm/region.c
servers/vm/sanitycheck.h
servers/vm/vm.h

index 560508744c3cd651d3f97dc8425951bac66b29c0..4b57ade429fa682e030c2b11fe2f8497280e909d 100644 (file)
@@ -403,7 +403,8 @@ int safe;
 #endif
 
        /* Try to allocate a piece of memory for the RAM disk. */
-       if((mem = mmap(0, ramdev_size, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0)) == MAP_FAILED) {
+       if((mem = mmap(0, ramdev_size, PROT_READ|PROT_WRITE,
+               MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) {
            printf("MEM: failed to get memory for ramdisk\n");
             return(ENOMEM);
         } 
index 018ce01189eaa16b3a1a4bf1af4eabef2e355c24..bdc27770d5741f72c1170b3043831d0970df7374 100644 (file)
@@ -766,8 +766,22 @@ int scode;                 /* scan code of key just struck or released */
                        return -1;
                if(ch)
                        return ch;
-               printf("tty: ignoring unrecognized %s scancode 0x%x\n",
-                       escape ? "escaped" : "straight", scode);
+               {
+                       static char seen[2][NR_SCAN_CODES];
+                       int notseen = 0, ei;
+                       ei = escape ? 1 : 0;
+                       if(scode >= 0 && scode < NR_SCAN_CODES) {
+                               notseen = !seen[ei][scode];
+                               seen[ei][scode] = 1;
+                       } else {
+                               printf("tty: scode %d makes no sense\n", scode);
+                       }
+                       if(notseen) {
+                               printf("tty: ignoring unrecognized %s "
+                                       "scancode 0x%x\n",
+                               escape ? "escaped" : "straight", scode);
+                       }
+               }
                return -1;
   }
 
index aecb857339099c3713a32b13dc3e19bf8ef78a65..0c838685af6650546957d5aaa96c022776d4637a 100755 (executable)
 #  define SYS_GETINFO    (KERNEL_CALL + 26)    /* sys_getinfo() */
 #  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_SAFECOPYFROM (KERNEL_CALL + 31)  /* sys_safecopyfrom() */
 #  define SYS_SAFECOPYTO   (KERNEL_CALL + 32)  /* sys_safecopyto() */
 #  define SYS_VSAFECOPY  (KERNEL_CALL + 33)    /* sys_vsafecopy() */
 #define VMCTL_NOPAGEZERO       18
 #define VMCTL_I386_KERNELLIMIT 19
 #define VMCTL_I386_PAGEDIRS    20
-#define VMCTL_I386_PDE         21
-#define VMCTL_I386_PDEVAL      22
 #define VMCTL_I386_FREEPDE     23
+#define VMCTL_ENABLE_PAGING    24
+#define VMCTL_I386_INVLPG      25
 
 /*===========================================================================*
  *                Messages for the Reincarnation Server                     *
index c4b3b969042b49adbd61e0372713e54f33ff51d1..788a9bce6d4ae56c9cbd4723f93dec28bf22e3d4 100755 (executable)
@@ -95,7 +95,4 @@
 #define SPROFILE          1    /* statistical profiling */
 #define CPROFILE          0    /* call profiling */
 
-/* Compile kernel so that first page of code and data can be unmapped. */
-#define VM_KERN_NOPAGEZERO      0
-
 #endif /* _CONFIG_H */
diff --git a/include/minix/debug.h b/include/minix/debug.h
new file mode 100644 (file)
index 0000000..808d735
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _MINIX_DEBUG_H
+#define _MINIX_DEBUG_H 1
+
+/* For reminders of things to be fixed. */
+#define FIXME(str) { static int fixme_warned = 0; \
+       if(!fixme_warned) { \
+               printf("FIXME: %s:%d: %s\n", __FILE__, __LINE__, str);\
+               fixme_warned = 1; \
+       } \
+}
+
+#endif /* _MINIX_DEBUG_H */
+
index 7d182348dc7e7727376933f4b3b9acdbdb361c8d..a6429c6b51b6b05cd0bd05d09eb4e097a8676f24 100755 (executable)
@@ -97,9 +97,6 @@ struct kinfo {
   int nr_tasks;                        /* number of kernel tasks */
   char release[6];             /* kernel release number */
   char version[6];             /* kernel version number */
-#if DEBUG_LOCK_CHECK
-  int relocking;               /* interrupt locking depth (should be 0) */
-#endif
 };
 
 /* Load data accounted every this no. of seconds. */
index 1ab6d4c126e3e04cf09ce46867b684c44ccb1f39..02485f83ac74b15ece09ef7806db8a21634c4a54 100644 (file)
@@ -36,6 +36,12 @@ sys/vm_i386.h
 #define I386_VM_PFA_SHIFT      22      /* Page frame address shift */
 
 /* CR0 bits */
+#define I386_CR0_PE            0x00000001      /* Protected mode  */
+#define I386_CR0_MP            0x00000002      /* Monitor Coprocessor  */
+#define I386_CR0_EM            0x00000004      /* Emulate  */
+#define I386_CR0_TS            0x00000008      /* Task Switched  */
+#define I386_CR0_ET            0x00000010      /* Extension Type  */
+#define I386_CR0_WP            0x00010000      /* Enable paging */
 #define I386_CR0_PG            0x80000000      /* Enable paging */
 
 /* some CR4 bits */
index 7ab5aa3ee71e2acc52af9e889832beaa4a534e80..71a0469aa5b191e975ec77aa7af89c9194a650df 100644 (file)
@@ -12,7 +12,6 @@
 
 #include "proto.h"
 
-extern u32_t kernel_cr3;
 extern u32_t *vm_pagedirs;
 
 /*===========================================================================*
@@ -22,10 +21,6 @@ PUBLIC int arch_do_vmctl(m_ptr, p)
 register message *m_ptr;       /* pointer to request message */
 struct proc *p;
 {
-
-  static int vmpde = -1;
-  static u32_t pdeval = -1;
-
   switch(m_ptr->SVMCTL_PARAM) {
        case VMCTL_I386_GETCR3:
                /* Get process CR3. */
@@ -37,7 +32,7 @@ struct proc *p;
                        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_seg.p_cr3 = 0;
                        p->p_misc_flags &= ~MF_FULLVM;
                }
                RTS_LOCK_UNSET(p, VMINHIBIT);
@@ -58,6 +53,8 @@ struct proc *p;
                 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;
+               printf("kernel: returning pagefault for %s / %d\n",
+                       rp->p_name, rp->p_endpoint);
                return OK;
        }
        case VMCTL_I386_KERNELLIMIT:
@@ -74,25 +71,14 @@ struct proc *p;
                kprintf("kernel: pagedirs now 0x%lx\n", vm_pagedirs);
                return OK;
        }
-       case VMCTL_I386_PDE:
-       {
-               vmpde = m_ptr->SVMCTL_VALUE;
-               kprintf("kernel: HACK: vmpde %d\n", vmpde);
-               return OK;
-       }
-       case VMCTL_I386_PDEVAL:
+       case VMCTL_I386_FREEPDE:
        {
-               pdeval = m_ptr->SVMCTL_VALUE;
-               kprintf("kernel: HACK: vmpde %d, set val 0x%x\n",
-                       vmpde, pdeval);
-               i386_updatepde(vmpde, pdeval);
-               kprintf("kernel: HACK: vmpde %d, set val 0x%x done\n",
-                       vmpde, pdeval);
+               i386_freepde(m_ptr->SVMCTL_VALUE);
                return OK;
        }
-       case VMCTL_I386_FREEPDE:
+       case VMCTL_I386_INVLPG:
        {
-               i386_freepde(m_ptr->SVMCTL_VALUE);
+               invlpg_range(m_ptr->SVMCTL_VALUE, 1);
                return OK;
        }
   }
index 5028d9e650a3df3192506ec026a9c94af927e465..1beefa499792a0f7471bc6ebe4fa11170fae7fd9 100644 (file)
@@ -33,6 +33,10 @@ register message *m_ptr;     /* pointer to request message */
   struct priv *privp;
   struct io_range *iorp;
 
+  kprintf("kernel: no sdevio\n");
+  return EIO;
+
+#if 0
   /* Allow safe copies and accesses to SELF */
   if ((m_ptr->DIO_REQUEST & _DIO_SAFEMASK) != _DIO_SAFE &&
        proc_nr_e != SELF)
@@ -141,6 +145,7 @@ register message *m_ptr;    /* pointer to request message */
       return(EINVAL);
   }
   return(OK);
+#endif
 }
 
 #endif /* USE_SDEVIO */
index 2657482deb9276e4eec3fd55e7a8525de18d13fa..0e137755df5caa57cc32662c65dab2a3d30d8550 100755 (executable)
 #include <minix/sysutil.h>
 #include "../../proc.h"
 
-extern int vm_copy_in_progress;
+extern int vm_copy_in_progress, catch_pagefaults;
 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;
+extern u32_t catchrange_lo, catchrange_hi;
 
 u32_t pagefault_cr2, pagefault_count = 0;
 
@@ -24,15 +25,33 @@ void pagefault(struct proc *pr, int trap_errno)
        vir_bytes ph;
        u32_t pte;
 
-       if(pagefault_count != 1)
-               minix_panic("recursive pagefault", pagefault_count);
+       vmassert(pagefault_count == 1);
+
+       if((iskernelp(pr) || k_reenter) && catch_pagefaults
+               && (pr->p_reg.pc > (vir_bytes) _memcpy_k &&
+                  pr->p_reg.pc < (vir_bytes) _memcpy_k_fault) &&
+                  pagefault_cr2 >= catchrange_lo &&
+                  pagefault_cr2 < catchrange_hi) {
+               kprintf("handling pagefault during copy\n");
+               pr->p_reg.pc = (vir_bytes) _memcpy_k_fault;
+               pr->p_reg.retreg = pagefault_cr2;
+               pagefault_count = 0;
+               return;
+       }
 
-       /* 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);
+       proc_stacktrace(pr);
+
+       if(catch_pagefaults) {
+               printf("k_reenter: %d addr: 0x%lx range: 0x%lx-0x%lx\n",
+                       k_reenter, pagefault_cr2, catchrange_lo, catchrange_hi);
+       }
 
-       if(pr->p_endpoint <= INIT_PROC_NR && !(pr->p_misc_flags & MF_FULLVM)) {
+       /* System processes that don't have their own page table can't
+        * have page faults. VM does have its own page table but also
+        * can't have page faults (because VM has to handle them).
+        */
+       if(k_reenter || (pr->p_endpoint <= INIT_PROC_NR &&
+        !(pr->p_misc_flags & MF_FULLVM)) || pr->p_endpoint == VM_PROC_NR) {
                /* Page fault we can't / don't want to
                 * handle.
                 */
@@ -45,6 +64,11 @@ void pagefault(struct proc *pr, int trap_errno)
                return;
        }
 
+       /* Don't schedule this process until pagefault is handled. */
+       vmassert(pr->p_seg.p_cr3 == read_cr3());
+       vmassert(!RTS_ISSET(pr, PAGEFAULT));
+       RTS_LOCK_SET(pr, PAGEFAULT);
+
        /* Save pagefault details, suspend process,
         * add process to pagefault chain,
         * and tell VM there is a pagefault to be
@@ -54,7 +78,7 @@ void pagefault(struct proc *pr, int trap_errno)
        pr->p_pagefault.pf_flags = trap_errno;
        pr->p_nextpagefault = pagefaults;
        pagefaults = pr;
-       lock_notify(HARDWARE, VM_PROC_NR);
+       soft_notify(VM_PROC_NR);
 
        pagefault_count = 0;
 
@@ -184,17 +208,20 @@ PUBLIC void proc_stacktrace(struct proc *proc)
 
        v_bp = proc->p_reg.fp;
 
-       kprintf("%8.8s %6d 0x%lx ",
+       kprintf("%-8.8s %6d 0x%lx ",
                proc->p_name, proc->p_endpoint, proc->p_reg.pc);
 
        while(v_bp) {
-               if(data_copy(proc->p_endpoint, v_bp,
-                       SYSTEM, (vir_bytes) &v_hbp, sizeof(v_hbp)) != OK) {
+
+#define PRCOPY(pr, pv, v, n) \
+  (iskernelp(pr) ? (memcpy(v, pv, n), OK) : \
+     data_copy(pr->p_endpoint, pv, SYSTEM, (vir_bytes) (v), n))
+
+               if(PRCOPY(proc, v_bp, &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) {
+               if(PRCOPY(proc, v_bp + sizeof(v_pc), &v_pc, sizeof(v_pc)) != OK) {
                        kprintf("(v_pc 0x%lx ?)", v_pc);
                        break;
                }
index dfec1dbb9d11685701aeae2b1bb929cb8586333d..fda2f3f393637cd337d0b63cdc3613de61d8f3ce 100755 (executable)
 .define        __exit          ! dummy for library routines
 .define        ___exit         ! dummy for library routines
 .define        ___main         ! dummy for GCC
-.define        _phys_insw      ! transfer data from (disk controller) port to memory
-.define        _phys_insb      ! likewise byte by byte
-.define        _phys_outsw     ! transfer data from memory to (disk controller) port
-.define        _phys_outsb     ! likewise byte by byte
+!.define       _phys_insw      ! transfer data from (disk controller) port to memory
+!.define       _phys_insb      ! likewise byte by byte
+!.define       _phys_outsw     ! transfer data from memory to (disk controller) port
+!.define       _phys_outsb     ! likewise byte by byte
 .define        _intr_unmask    ! enable an irq at the 8259 controller
 .define        _intr_mask      ! disable an irq
 .define        _phys_copy      ! copy data from anywhere to anywhere in memory
 .define        _read_cpu_flags ! read the cpu flags
 .define        _read_cr0       ! read cr0
 .define        _write_cr3      ! write cr3
+.define        _getcr3val
 .define _last_cr3
 .define        _write_cr0      ! write a value in cr0
 .define        _read_cr4
+.define        _thecr3
 .define        _write_cr4
 .define _i386_invlpg_addr
 .define _i386_invlpg_level0
-
-.define        _kernel_cr3     
+.define __memcpy_k
+.define __memcpy_k_fault
 
 ! The routines only guarantee to preserve the registers the C compiler
 ! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
@@ -158,55 +160,6 @@ csinit:    mov     eax, DS_SELECTOR
        ret
 
 
-!*===========================================================================*
-!*                             cp_mess                                      *
-!*===========================================================================*
-! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
-!                    phys_clicks dst_clicks, vir_bytes dst_offset);
-! This routine makes a fast copy of a message from anywhere in the address
-! space to anywhere else.  It also copies the source address provided as a
-! parameter to the call into the first word of the destination message.
-!
-! 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!
-!
-
 !*===========================================================================*
 !*                             exit                                         *
 !*===========================================================================*
@@ -230,56 +183,52 @@ ___main:
 !*===========================================================================*
 ! PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count);
 ! Input an array from an I/O port.  Absolute address version of insw().
-
-_phys_insw:
-       push    ebp
-       mov     ebp, esp
-       cld
-       push    edi
-       push    es
-
-       LOADKERNELCR3
-
-       mov     ecx, FLAT_DS_SELECTOR
-       mov     es, cx
-       mov     edx, 8(ebp)             ! port to read from
-       mov     edi, 12(ebp)            ! destination addr
-       mov     ecx, 16(ebp)            ! byte count
-       shr     ecx, 1                  ! word count
-rep o16        ins                             ! input many words
-       pop     es
-       pop     edi
-       pop     ebp
-       ret
-
+!
+!_phys_insw:
+!      push    ebp
+!      mov     ebp, esp
+!      cld
+!      push    edi
+!      push    es
+!
+!      mov     ecx, FLAT_DS_SELECTOR
+!      mov     es, cx
+!      mov     edx, 8(ebp)             ! port to read from
+!      mov     edi, 12(ebp)            ! destination addr
+!      mov     ecx, 16(ebp)            ! byte count
+!      shr     ecx, 1                  ! word count
+!rep o16       ins                             ! input many words
+!      pop     es
+!      pop     edi
+!      pop     ebp
+!      ret
+!
 
 !*===========================================================================*
 !*                             phys_insb                                    *
 !*===========================================================================*
 ! PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count);
 ! Input an array from an I/O port.  Absolute address version of insb().
-
-_phys_insb:
-       push    ebp
-       mov     ebp, esp
-       cld
-       push    edi
-       push    es
-
-       LOADKERNELCR3
-
-       mov     ecx, FLAT_DS_SELECTOR
-       mov     es, cx
-       mov     edx, 8(ebp)             ! port to read from
-       mov     edi, 12(ebp)            ! destination addr
-       mov     ecx, 16(ebp)            ! byte count
-!      shr     ecx, 1                  ! word count
-   rep insb                            ! input many bytes
-       pop     es
-       pop     edi
-       pop     ebp
-       ret
-
+!
+!_phys_insb:
+!      push    ebp
+!      mov     ebp, esp
+!      cld
+!      push    edi
+!      push    es
+!
+!      mov     ecx, FLAT_DS_SELECTOR
+!      mov     es, cx
+!      mov     edx, 8(ebp)             ! port to read from
+!      mov     edi, 12(ebp)            ! destination addr
+!      mov     ecx, 16(ebp)            ! byte count
+!!     shr     ecx, 1                  ! word count
+!   rep        insb                            ! input many bytes
+!      pop     es
+!      pop     edi
+!      pop     ebp
+!      ret
+!
 
 !*===========================================================================*
 !*                             phys_outsw                                   *
@@ -287,55 +236,51 @@ _phys_insb:
 ! PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count);
 ! Output an array to an I/O port.  Absolute address version of outsw().
 
-       .align  16
-_phys_outsw:
-       push    ebp
-       mov     ebp, esp
-       cld
-       push    esi
-       push    ds
-
-       LOADKERNELCR3
-
-       mov     ecx, FLAT_DS_SELECTOR
-       mov     ds, cx
-       mov     edx, 8(ebp)             ! port to write to
-       mov     esi, 12(ebp)            ! source addr
-       mov     ecx, 16(ebp)            ! byte count
-       shr     ecx, 1                  ! word count
-rep o16        outs                            ! output many words
-       pop     ds
-       pop     esi
-       pop     ebp
-       ret
-
+!      .align  16
+!_phys_outsw:
+!      push    ebp
+!      mov     ebp, esp
+!      cld
+!      push    esi
+!      push    ds
+!
+!      mov     ecx, FLAT_DS_SELECTOR
+!      mov     ds, cx
+!      mov     edx, 8(ebp)             ! port to write to
+!      mov     esi, 12(ebp)            ! source addr
+!      mov     ecx, 16(ebp)            ! byte count
+!      shr     ecx, 1                  ! word count
+!rep o16       outs                            ! output many words
+!      pop     ds
+!      pop     esi
+!      pop     ebp
+!      ret
+!
 
 !*===========================================================================*
 !*                             phys_outsb                                   *
 !*===========================================================================*
 ! PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count);
 ! Output an array to an I/O port.  Absolute address version of outsb().
-
-       .align  16
-_phys_outsb:
-       push    ebp
-       mov     ebp, esp
-       cld
-       push    esi
-       push    ds
-
-       LOADKERNELCR3
-
-       mov     ecx, FLAT_DS_SELECTOR
-       mov     ds, cx
-       mov     edx, 8(ebp)             ! port to write to
-       mov     esi, 12(ebp)            ! source addr
-       mov     ecx, 16(ebp)            ! byte count
-   rep outsb                           ! output many bytes
-       pop     ds
-       pop     esi
-       pop     ebp
-       ret
+!
+!      .align  16
+!_phys_outsb:
+!      push    ebp
+!      mov     ebp, esp
+!      cld
+!      push    esi
+!      push    ds
+!
+!      mov     ecx, FLAT_DS_SELECTOR
+!      mov     ds, cx
+!      mov     edx, 8(ebp)             ! port to write to
+!      mov     esi, 12(ebp)            ! source addr
+!      mov     ecx, 16(ebp)            ! byte count
+!   rep        outsb                           ! output many bytes
+!      pop     ds
+!      pop     esi
+!      pop     ebp
+!      ret
 
 
 !*==========================================================================*
@@ -432,8 +377,6 @@ _phys_copy:
        push    edi
        push    es
 
-       LOADKERNELCR3
-
        mov     eax, FLAT_DS_SELECTOR
        mov     es, ax
 
@@ -479,8 +422,6 @@ _phys_memset:
        push    ebx
        push    ds
 
-       LOADKERNELCR3
-
        mov     esi, 8(ebp)
        mov     eax, 16(ebp)
        mov     ebx, FLAT_DS_SELECTOR
@@ -494,7 +435,7 @@ fill_start:
        jnz     fill_start
        ! Any remaining bytes?
        mov     eax, 16(ebp)
-       and     eax, 3
+!      and     eax, 3
 remain_fill:
        cmp     eax, 0
        jz      fill_done
@@ -642,10 +583,20 @@ _write_cr4:
 _write_cr3:
        push    ebp
        mov     ebp, esp
-       LOADCR3WITHEAX(0x22, 8(ebp))
+       mov     eax, 8(ebp)
+       mov     cr3, eax
        pop     ebp
        ret
 
+!*===========================================================================*
+!*                             getcr3val                               *
+!*===========================================================================*
+! PUBLIC unsigned long getcr3val(void);
+_getcr3val:
+       mov     eax, cr3
+       mov     (_thecr3), eax
+       ret
+
 !*===========================================================================*
 !*                             i386_invlpg                             *
 !*===========================================================================*
@@ -657,4 +608,47 @@ _i386_invlpg_level0:
        ret
 
 
-
+!*===========================================================================*
+!*                             _memcpy_k                                    *
+!*===========================================================================*
+!      _memcpy_k()                             Original Author: Kees J. Bot
+!                                                              2 Jan 1994
+! void *_memcpy_k(void *s1, const void *s2, size_t n)
+!      Copy a chunk of memory that the kernel can use to trap pagefaults.
+.define __memcpy_k
+.define __memcpy_k_fault
+       .align  16
+__memcpy_k:
+       push    ebp
+       mov     ebp, esp
+       push    esi
+       push    edi
+       mov     edi, 8(ebp)     ! String s1
+       mov     esi, 12(ebp)    ! String s2
+       mov     ecx, 16(ebp)    ! Length
+       cld                     ! Clear direction bit: upwards
+       cmp     ecx, 16
+       jb      upbyte          ! Don't bother being smart with short arrays
+       mov     eax, esi
+       or      eax, edi
+       testb   al, 1
+       jnz     upbyte          ! Bit 0 set, use byte copy
+       testb   al, 2
+       jnz     upword          ! Bit 1 set, use word copy
+uplword:shrd   eax, ecx, 2     ! Save low 2 bits of ecx in eax
+       shr     ecx, 2
+       rep
+       movs                    ! Copy longwords.
+       shld    ecx, eax, 2     ! Restore excess count
+upword:        shr     ecx, 1
+       rep
+    o16        movs                    ! Copy words
+       adc     ecx, ecx        ! One more byte?
+upbyte:        rep
+       movsb                   ! Copy bytes
+done:  mov     eax, 0
+__memcpy_k_fault:              ! Kernel can send us here with pf cr2 in eax
+       pop     edi
+       pop     esi
+       pop     ebp
+       ret
index ed5b051695cc6301c945bb42441fa1cc826fb111..c747932d6a40a1d9f7c44bca101fcc7dd8ebc809 100644 (file)
@@ -9,6 +9,10 @@
 #include <minix/cpufeature.h>
 #include <string.h>
 
+#define FREEPDE_SRC    0
+#define FREEPDE_DST    1
+#define FREEPDE_MEMSET 2
+
 #include <sys/vm_i386.h>
 
 #include <minix/portio.h>
 #include "../../proto.h"
 #include "../../debug.h"
 
+PRIVATE int psok = 0;
+
+#define PROCPDEPTR(pr, pi) ((u32_t *) ((u8_t *) vm_pagedirs +\
+                               I386_PAGE_SIZE * pr->p_nr +     \
+                               I386_VM_PT_ENT_SIZE * pi))
+
+/* Signal to exception handler that pagefaults can happen. */
+int catch_pagefaults = 0;
+u32_t catchrange_lo = 0;
+u32_t catchrange_hi = 0;
+
+#if 0
 /* VM functions and data. */
-PRIVATE u32_t vm_cr3;
 PUBLIC u32_t kernel_cr3;
+#endif
+
 extern u32_t cswitch;
 u32_t last_cr3 = 0;
 
-u32_t *vm_pagedirs = NULL;
+u8_t *vm_pagedirs = NULL;
 
 u32_t i386_invlpg_addr = 0;
 
@@ -32,122 +49,81 @@ PRIVATE int nfreepdes = 0, freepdes[WANT_FREEPDES];
 
 #define HASPT(procptr) ((procptr)->p_seg.p_cr3 != 0)
 
-FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value)    );
-FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr)                        );
+FORWARD _PROTOTYPE( u32_t phys_get32, (vir_bytes v)                    );
 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)
+PUBLIC void vm_init(struct proc *newptproc)
 {
-       int o;
-       phys_bytes p, pt_size;
-       phys_bytes vm_dir_base, vm_pt_base, phys_mem;
-       u32_t entry;
-       unsigned pages;
-       struct proc* rp;
-       struct proc *sys = proc_addr(SYSTEM);
-       static int init_done = 0;
-
-       if (!vm_size)
-               minix_panic("i386_vm_init: no space for page tables", NO_NUM);
-
-       if(init_done)
-               return;
-
-       /* Align page directory */
-       o= (vm_base % I386_PAGE_SIZE);
-       if (o != 0)
-               o= I386_PAGE_SIZE-o;
-       vm_dir_base= vm_base+o;
-
-       /* Page tables start after the page directory */
-       vm_pt_base= vm_dir_base+I386_PAGE_SIZE;
-
-       pt_size= (vm_base+vm_size)-vm_pt_base;
-       pt_size -= (pt_size % I386_PAGE_SIZE);
-
-       /* Compute the number of pages based on vm_mem_high */
-       pages= (vm_mem_high-1)/I386_PAGE_SIZE + 1;
-
-       if (pages * I386_VM_PT_ENT_SIZE > pt_size)
-               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*I386_PAGE_SIZE;
-               entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
-                       I386_VM_PRESENT;
-               if (phys_mem >= vm_mem_high)
-                       entry= 0;
-#if VM_KERN_NOPAGEZERO
-               if (phys_mem == (sys->p_memmap[T].mem_phys << CLICK_SHIFT) ||
-                   phys_mem == (sys->p_memmap[D].mem_phys << CLICK_SHIFT)) {
-                       entry = 0;
-               }
-#endif
-               phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
-       }
+       u32_t newcr3;
 
-       for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
-       {
-               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);
-       }
+       if(vm_running)
+               minix_panic("vm_init: vm_running", NO_NUM);
 
+       ptproc = newptproc;
+       newcr3 = ptproc->p_seg.p_cr3;
+       kprintf("vm_init: ptproc: %s / %d, cr3 0x%lx\n",
+               ptproc->p_name, ptproc->p_endpoint,
+               ptproc->p_seg.p_cr3);
+       vmassert(newcr3);
 
-       /* 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;
-       }
+       kprintf("vm_init thinks cr3 0x%lx is loaded, proc %d, cr3 0x%lx, actual cr3 0x%lx\n",
+               last_cr3, ptproc->p_endpoint, ptproc->p_seg.p_cr3, read_cr3());
 
-       kernel_cr3 = vm_dir_base;
+       kprintf("vm_init: writing cr3 0x%lx\n", newcr3);
 
        /* Set this cr3 now (not active until paging enabled). */
-       vm_set_cr3(vm_dir_base);
+       vm_set_cr3(newcr3);
 
+       kprintf("vm_init: writing cr3 0x%lx done; cr3: 0x%lx\n",
+               newcr3, read_cr3());
+
+       kprintf("vm_init: enabling\n");
        /* Actually enable paging (activating cr3 load above). */
        level0(vm_enable_paging);
 
+       kprintf("vm_init: enabled\n");
+
        /* Don't do this init in the future. */
-       init_done = 1;
        vm_running = 1;
+
+       kprintf("vm_init done\n");
 }
 
+#if 0
 PRIVATE void phys_put32(addr, value)
 phys_bytes addr;
 u32_t value;
 {
        phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
 }
+#endif
 
 PRIVATE u32_t phys_get32(addr)
 phys_bytes addr;
 {
-       u32_t value;
+       u32_t v;
+       int r;
 
-       phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
+       if(!vm_running) {
+               phys_copy(addr, vir2phys(&v), sizeof(v));
+               return v;
+       }
+
+       if((r=lin_lin_copy(NULL, addr, NULL, D,
+               proc_addr(SYSTEM), &v, &v, D, 
+               sizeof(v))) != OK) {
+               minix_panic("lin_lin_copy for phys_get32 failed", r);
+       }
 
-       return value;
+       return v;
 }
 
+PRIVATE u32_t vm_cr3;  /* temp arg to level0() func */
+
 PRIVATE void vm_set_cr3(value)
 u32_t value;
 {
@@ -160,10 +136,42 @@ PRIVATE void set_cr3()
        write_cr3(vm_cr3);
 }
 
+char *cr0_str(u32_t e)
+{
+       static char str[80];
+       strcpy(str, "");
+#define FLAG(v) do { if(e & (v)) { strcat(str, #v " "); e &= ~v; } } while(0)
+       FLAG(I386_CR0_PE);
+       FLAG(I386_CR0_MP);
+       FLAG(I386_CR0_EM);
+       FLAG(I386_CR0_TS);
+       FLAG(I386_CR0_ET);
+       FLAG(I386_CR0_PG);
+       FLAG(I386_CR0_WP);
+       if(e) { strcat(str, " (++)"); }
+       return str;
+}
+
+char *cr4_str(u32_t e)
+{
+       static char str[80];
+       strcpy(str, "");
+       FLAG(I386_CR4_VME);
+       FLAG(I386_CR4_PVI);
+       FLAG(I386_CR4_TSD);
+       FLAG(I386_CR4_DE);
+       FLAG(I386_CR4_PSE);
+       FLAG(I386_CR4_PAE);
+       FLAG(I386_CR4_MCE);
+       FLAG(I386_CR4_PGE);
+       if(e) { strcat(str, " (++)"); }
+       return str;
+}
+
 PRIVATE void vm_enable_paging(void)
 {
        u32_t cr0, cr4;
-       int psok, pgeok;
+       int pgeok;
 
        psok = _cpufeature(_CPUF_I386_PSE);
        pgeok = _cpufeature(_CPUF_I386_PGE);
@@ -171,22 +179,41 @@ PRIVATE void vm_enable_paging(void)
        cr0= read_cr0();
        cr4= read_cr4();
 
+       kprintf("vm_enable_paging: cr0: %s cr4: %s; want to disable\n",
+               cr0_str(cr0), cr4_str(cr4));
+
        /* First clear PG and PGE flag, as PGE must be enabled after PG. */
        write_cr0(cr0 & ~I386_CR0_PG);
-       write_cr4(cr4 & ~I386_CR4_PGE);
+       write_cr4(cr4 & ~(I386_CR4_PGE | I386_CR4_PSE));
 
        cr0= read_cr0();
        cr4= read_cr4();
 
+       kprintf("vm_enable_paging: cr0: %s cr4: %s after disabling\n",
+               cr0_str(cr0), cr4_str(cr4));
+
+       /* Our first page table contains 4MB entries. */
+       if(psok)
+               cr4 |= I386_CR4_PSE;
+
+       write_cr4(cr4);
+
        /* First enable paging, then enable global page flag. */
-       write_cr0(cr0 | I386_CR0_PG);
+       kprintf("vm_enable_paging: write PG\n");
+       cr0 |= I386_CR0_PG;
+       write_cr0(cr0 );
+       kprintf("vm_enable_paging: writing WP\n");
+       cr0 |= I386_CR0_WP;
+       write_cr0(cr0);
+       kprintf("vm_enable_paging: write WP done\n");
 
        /* May we enable these features? */
        if(pgeok)
                cr4 |= I386_CR4_PGE;
-       if(psok)
-               cr4 |= I386_CR4_PSE;
 
+       kprintf("vm_enable_paging: write cr4 0x%lx\n", cr4);
+       write_cr4(cr4);
+       kprintf("vm_enable_paging: write cr4 0x%lx done\n", cr4);
        write_cr4(cr4);
 }
 
@@ -322,6 +349,7 @@ vir_bytes bytes;                /* # of bytes to be copied */
        return phys;
 }
 
+
 /*===========================================================================*
  *                              vm_lookup                                    *
  *===========================================================================*/
@@ -330,6 +358,7 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
        u32_t *root, *pt;
        int pde, pte;
        u32_t pde_v, pte_v;
+       NOREC_ENTER(vmlookup);
 
        vmassert(proc);
        vmassert(physical);
@@ -337,7 +366,7 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
 
        if(!HASPT(proc)) {
                *physical = virtual;
-               return OK;
+               NOREC_RETURN(vmlookup, OK);
        }
 
        /* Retrieve page directory entry. */
@@ -346,6 +375,7 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
        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",
@@ -353,32 +383,33 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
                kprintf("kernel stack: ");
                util_stacktrace();
 #endif
-               return EFAULT;
+               NOREC_RETURN(vmlookup, 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;
-       }
+       /* We don't expect to ever see this. */
+       if(pde_v & I386_VM_BIGPAGE) {
+               *physical = pde_v & I386_VM_ADDR_MASK_4MB;
+               if(ptent) *ptent = pde_v;
+               *physical += virtual & I386_VM_OFFSET_MASK_4MB;
+       } else {
+               /* 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)) {
+                       NOREC_RETURN(vmlookup, EFAULT);
+               }
 
-       if(ptent) *ptent = pte_v;
+               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;
+               /* Actual address now known; retrieve it and add page offset. */
+               *physical = I386_VM_PFA(pte_v);
+               *physical += virtual % I386_PAGE_SIZE;
+       }
 
-       return OK;
+       NOREC_RETURN(vmlookup, OK);
 }
 
 /* From virtual address v in process p,
@@ -397,54 +428,6 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
                        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                                *
  *===========================================================================*/
@@ -509,6 +492,29 @@ PUBLIC int vm_contiguous(struct proc *targetproc, u32_t vir_buf, size_t bytes)
 
 int vm_checkrange_verbose = 0;
 
+/*===========================================================================*
+ *                              vm_suspend                                *
+ *===========================================================================*/
+PUBLIC int vm_suspend(struct proc *caller, struct proc *target)
+{
+       /* 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 caller in target. */                     
+       target->p_vmrequest.requestor = caller;         
+                                                       
+       /* Connect caller on vmrequest wait queue. */   
+       caller->p_vmrequest.nextrequestor = vmrequest;
+       vmrequest = caller;     
+       if(!caller->p_vmrequest.nextrequestor) {
+               soft_notify(VM_PROC_NR);                
+       }                                               
+}
+
 /*===========================================================================*
  *                              vm_checkrange                                *
  *===========================================================================*/
@@ -518,8 +524,10 @@ PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
        u32_t flags, po, v;
        int r;
 
+       NOREC_ENTER(vmcheckrange);
+
        if(!HASPT(target))
-               return OK;
+               NOREC_RETURN(vmcheckrange, OK);
 
        /* If caller has had a reply to this request, return it. */
        if(RTS_ISSET(caller, VMREQUEST)) {
@@ -531,7 +539,7 @@ PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
                        kprintf("SYSTEM: vm_checkrange: returning vmresult %d\n",
                                caller->p_vmrequest.vmresult);
 #endif
-                       return caller->p_vmrequest.vmresult;
+                       NOREC_RETURN(vmcheckrange, caller->p_vmrequest.vmresult);
                } else {
 #if 0
                        kprintf("SYSTEM: vm_checkrange: caller has a request for %d, "
@@ -558,97 +566,39 @@ PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
                 */
                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;
-               if(!caller->p_vmrequest.nextrequestor) {
-                       int n = 0;
-                       struct proc *vmr;
-                       for(vmr = vmrequest; vmr; vmr = vmr->p_vmrequest.nextrequestor)
-                               n++;
-                       soft_notify(VM_PROC_NR);
-#if 0
-                       kprintf("(%d) ", n);
-                       kprintf("%d/%d ",
-                               caller->p_endpoint, target->p_endpoint);
-                       util_stacktrace();
-#endif
-               }
-
-#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);
+               if(!checkonly) {
+                       /* Set parameters in caller. */                 
+                       vm_suspend(caller, target);
+                       caller->p_vmrequest.writeflag = wrfl;                   
+                       caller->p_vmrequest.start = vir;                        
+                       caller->p_vmrequest.length = bytes;                     
+                       caller->p_vmrequest.who = target->p_endpoint;           
                }
 
-               return VMSUSPEND;
+               /* SYSTEM loop will fill in VMSTYPE_SYS_MESSAGE. */
+               NOREC_RETURN(vmcheckrange, VMSUSPEND);
        }
 
-       return OK;
+       NOREC_RETURN(vmcheckrange, 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);
+       FLAG(I386_VM_GLOBAL);
        if(dir)
                FLAG(I386_VM_BIGPAGE);  /* Page directory entry only */
        else
                FLAG(I386_VM_DIRTY);    /* Page table entry only */
-
        return str;
 }
 
@@ -665,8 +615,9 @@ void vm_pt_print(u32_t *pagetable, u32_t v)
                if(!(pte_v & I386_VM_PRESENT))
                        continue;
                pfa = I386_VM_PFA(pte_v);
-               kprintf("%4d:%08lx:%08lx ",
-                       pte, v + I386_PAGE_SIZE*pte, pfa);
+               kprintf("%4d:%08lx:%08lx %2s ",
+                       pte, v + I386_PAGE_SIZE*pte, pfa,
+                       (pte_v & I386_VM_WRITE) ? "rw":"RO");
                col++;
                if(col == 3) { kprintf("\n"); col = 0; }
        }
@@ -675,105 +626,195 @@ void vm_pt_print(u32_t *pagetable, u32_t v)
        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++) {
+       printf("page table 0x%lx:\n", root);
+
+       for(pde = 10; 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);
+               if(pde_v & I386_VM_BIGPAGE) {
+                       kprintf("%4d: 0x%lx, flags %s\n",
+                               pde, I386_VM_PFA(pde_v), flagstr(pde_v, 1));
+               } else {
+                       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);
+                       kprintf("\n");
+               }
        }
 
 
        return;
 }
 
+/*===========================================================================*
+ *                             invlpg_range                                 *
+ *===========================================================================*/
 void invlpg_range(u32_t lin, u32_t bytes)
 {
-       u32_t o;
+/* Remove a range of translated addresses from the TLB. 
+ * Addresses are in linear, i.e., post-segment, pre-pagetable
+ * form. Parameters are byte values, any offset and any multiple.
+ */
+       u32_t cr3;
+       u32_t o, limit, addr;
+       limit = lin + bytes - 1;
        o = lin % I386_PAGE_SIZE;
        lin -= o;
-       bytes += o;
-       while(bytes >= I386_PAGE_SIZE) {
-               i386_invlpg_addr = lin;
+       limit += o;
+       limit &= I386_VM_PT_ENT_MASK;
+       FIXME("invlpg_range reloads cr3");
+       cr3 = read_cr3();
+       vm_set_cr3(cr3);
+       for(i386_invlpg_addr = lin; i386_invlpg_addr <= limit;
+           i386_invlpg_addr += I386_PAGE_SIZE)
                level0(i386_invlpg_level0);
-               lin += I386_PAGE_SIZE;
-               bytes -= I386_PAGE_SIZE;
-       }
+}
+
+u32_t thecr3;
+
+u32_t read_cr3(void)
+{
+       level0(getcr3val);
+       return thecr3;
+}
+
+/* This macro sets up a mapping from within the kernel's address
+ * space to any other area of memory, either straight physical
+ * memory (PROC == NULL) or a process view of memory, in 4MB chunks.
+ * It recognizes PROC having kernel address space as a special case.
+ *
+ * It sets PTR to the pointer within kernel address space at the start
+ * of the 4MB chunk, and OFFSET to the offset within that chunk
+ * that corresponds to LINADDR.
+ *
+ * It needs FREEPDE (available and addressable PDE within kernel
+ * address space), SEG (hardware segment), VIRT (in-datasegment
+ * address if known).
+ *
+ * TODO: don't re-make a pde that's already there.
+ */
+#define CREATEPDE(PROC, PTR, LINADDR, OFFSET, FREEPDE, VIRT, SEG, REMAIN, BYTES) { \
+       if((PROC) && iskernelp(PROC) && SEG == D) {             \
+               PTR = VIRT;                                     \
+               OFFSET = 0;                                     \
+       } else {                                                \
+               u32_t pdeval, *pdevalptr, newlin;               \
+               int pde_index;                                  \
+               vmassert(psok);                                 \
+               pde_index = I386_VM_PDE(LINADDR);               \
+               vmassert(!iskernelp(PROC));                     \
+               if(PROC) {                                      \
+                       u32_t *pdeptr; \
+                       vmassert(!iskernelp(PROC));             \
+                       vmassert(HASPT(PROC));                  \
+                       pdeptr = PROCPDEPTR(PROC, pde_index);           \
+                       pdeval = *pdeptr;       \
+                       if(!(pdeval & I386_VM_PRESENT)) {               \
+                               kprintf("kernel: pde %d 0x%lx for proc %d\n", \
+                                       pde_index, pdeval, PROC->p_endpoint); \
+                       }                                               \
+                       if(copyverbose) { kprintf("installing pde val 0x%lx from pde index %d of proc %d into my pde\n", pdeval, pde_index, PROC->p_endpoint); }        \
+               } else {                                                \
+                       pdeval = (LINADDR & I386_VM_ADDR_MASK_4MB) |    \
+                               I386_VM_BIGPAGE | I386_VM_PRESENT |     \
+                               I386_VM_WRITE | I386_VM_USER;           \
+               }                                                       \
+               *PROCPDEPTR(ptproc, FREEPDE) = pdeval;                  \
+               newlin = I386_BIG_PAGE_SIZE*FREEPDE;                    \
+               PTR = (u8_t *) phys2vir(newlin);                        \
+               OFFSET = LINADDR & I386_VM_OFFSET_MASK_4MB;             \
+               REMAIN = MIN(REMAIN, I386_BIG_PAGE_SIZE - OFFSET);      \
+               invlpg_range(newlin + OFFSET, REMAIN);                  \
+       }                                                               \
 }
 
 /*===========================================================================*
  *                             lin_lin_copy                                 *
  *===========================================================================*/
 int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
+       int srcseg,
        struct proc *dstproc, vir_bytes dstlinaddr, u8_t *vdst,
-       vir_bytes bytes)
+       int dstseg,
+       vir_bytes bytes, int copyverbose)
 {
+       u32_t addr;
+       int procslot;
+       u32_t catchrange_dst;
+       NOREC_ENTER(linlincopy);
+
+       if(srcproc && dstproc && iskernelp(srcproc) && iskernelp(dstproc)) {
+               memcpy(vdst, vsrc, bytes);
+               NOREC_RETURN(linlincopy, OK);
+       }
 
-       if(nfreepdes < 2)
-               minix_panic("vm: not enough free PDE's", NO_NUM);
+       FIXME("lin_lin_copy requires big pages");
+       vmassert(vm_running);
+       vmassert(!catch_pagefaults);
+       vmassert(nfreepdes >= 3);
 
-       util_stacktrace();
+       vmassert(ptproc);
+       vmassert(proc_ptr);
+       vmassert(read_cr3() == ptproc->p_seg.p_cr3);
 
-#define CREATEPDE(PROC, PTR, LINADDR, OFFSET, FREEPDE, VIRT) { \
-       if(iskernelp(PROC)) {                                   \
-               PTR = VIRT;                                     \
-               OFFSET = 0;                                     \
-       } else {                                                \
-               u32_t *pdevalptr;                               \
-               u32_t myphysaddr;                               \
-               int pde_index;                                  \
-               pde_index = I386_VM_PDE(LINADDR);               \
-               pdevalptr = (u32_t *) ((u8_t *) vm_pagedirs +   \
-                       I386_PAGE_SIZE * PROC->p_nr +           \
-                       I386_VM_PT_ENT_SIZE * pde_index);       \
-               kprintf("pagedirs: 0x%x p_nr: %d linaddr: 0x%x pde: %d\n", \
-                       vm_pagedirs, PROC->p_nr, LINADDR, pde_index);   \
-               kprintf("pde ptr: 0x%x\n", pdevalptr);          \
-               kprintf("value: 0x%x\n", *pdevalptr);           \
-               myphysaddr = kernel_cr3 + FREEPDE*I386_VM_PT_ENT_SIZE; \
-               phys_put32(myphysaddr, *pdevalptr);             \
-               PTR = (u8_t *) phys2vir(I386_BIG_PAGE_SIZE*FREEPDE);    \
-               kprintf("ptr: 0x%x\n", PTR);            \
-               OFFSET = LINADDR & I386_VM_OFFSET_MASK_4MB;     \
-               kprintf("offset: 0x%lx & 0x%lx -> 0x%lx\n", LINADDR, \
-                       I386_VM_OFFSET_MASK_4MB, OFFSET);       \
-               invlpg_range(LINADDR, bytes + I386_PAGE_SIZE);  \
-       }                                                       \
-}
+       procslot = ptproc->p_nr;
+
+       vmassert(procslot >= 0 && procslot < I386_VM_DIR_ENTRIES);
+       vmassert(freepdes[FREEPDE_SRC] < freepdes[FREEPDE_DST]);
+
+       catchrange_lo  = I386_BIG_PAGE_SIZE*freepdes[FREEPDE_SRC];
+       catchrange_dst = I386_BIG_PAGE_SIZE*freepdes[FREEPDE_DST];
+       catchrange_hi  = I386_BIG_PAGE_SIZE*(freepdes[FREEPDE_DST]+1);
 
        while(bytes > 0) {
                u8_t *srcptr, *dstptr;
-               vir_bytes srcoffset, dstoffset, chunk, remain;
+               vir_bytes srcoffset, dstoffset;
+               vir_bytes chunk = bytes;
 
-               /* Set up 4MB ranges. */
-               CREATEPDE(srcproc, srcptr, srclinaddr, srcoffset, freepdes[0], vsrc);
-               CREATEPDE(dstproc, dstptr, dstlinaddr, dstoffset, freepdes[1], vdst);
+               FIXME("copyverbose");
 
-               remain = I386_BIG_PAGE_SIZE - MAX(srcoffset, dstoffset);
-               chunk = MIN(bytes, remain);
+               /* Set up 4MB ranges. */
+               CREATEPDE(srcproc, srcptr, srclinaddr, srcoffset,
+                       freepdes[FREEPDE_SRC], vsrc, srcseg, chunk, bytes);
+               CREATEPDE(dstproc, dstptr, dstlinaddr, dstoffset,
+                       freepdes[FREEPDE_DST], vdst, dstseg, chunk, bytes);
 
                /* Copy pages. */
-               while(chunk > 0) {
-                       kprintf("copy %d -> %d  %d/%d using 0x%lx+0x%lx -> 0x%lx+0x%lx\n",
-                               srcproc->p_endpoint, dstproc->p_endpoint,
-                               chunk, bytes, srcptr, srcoffset,
-                               dstptr, dstoffset);
-                       memcpy(dstptr + dstoffset, srcptr + srcoffset, chunk);
-                       kprintf("done\n");
+               vmassert(intr_disabled());
+               vmassert(!catch_pagefaults);
+               catch_pagefaults = 1;
+               addr=_memcpy_k(dstptr + dstoffset, srcptr + srcoffset, chunk);
+               vmassert(intr_disabled());
+               vmassert(catch_pagefaults);
+               catch_pagefaults = 0;
+
+               if(addr) {
+                       kprintf("kernel: lin_lin copy: returning EFAULT, addr 0x%lx\n",
+                               addr);
+                       if(addr >= catchrange_lo && addr < catchrange_dst) {
+                               kprintf("src\n");
+                               NOREC_RETURN(linlincopy, EFAULT_SRC);
+                       }
+                       if(addr >= catchrange_dst && addr < catchrange_hi) {
+                               kprintf("dst\n");
+                               NOREC_RETURN(linlincopy, EFAULT_DST);
+                       }
+                       minix_panic("lin_lin_copy fault out of range", NO_NUM);
+
+                       /* Not reached. */
+                       NOREC_RETURN(linlincopy, EFAULT);
                }
+               
+               vmassert(memcmp(dstptr + dstoffset, srcptr + srcoffset, chunk) == 0);
 
                /* Update counter and addresses for next iteration, if any. */
                bytes -= chunk;
@@ -783,6 +824,43 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
                vdst += chunk;
        }
 
+       NOREC_RETURN(linlincopy, OK);
+}
+
+/*===========================================================================*
+ *                             lin_memset                                   *
+ *===========================================================================*/
+int vm_phys_memset(phys_bytes ph, u8_t c, phys_bytes bytes)
+{
+       char *v;
+
+       if(!vm_running) {
+               u32_t p;
+               p = c | (c << 8) | (c << 16) | (c << 24);
+               phys_memset(ph, p, bytes);
+               return OK;
+       }
+
+       vmassert(nfreepdes >= 3);
+
+       /* With VM, we have to map in the physical memory. 
+        * We can do this 4MB at a time.
+        */
+       while(bytes > 0) {
+               vir_bytes chunk = bytes;
+               u8_t *ptr;
+               u32_t offset;
+               int copyverbose = 0;
+               CREATEPDE(((struct proc *) NULL), ptr, ph,
+                       offset, freepdes[FREEPDE_MEMSET], 0, 0, chunk, bytes);
+               /* We can memset as many bytes as we have remaining,
+                * or as many as remain in the 4MB chunk we mapped in.
+                */
+               memset(ptr + offset, c, chunk);
+               bytes -= chunk;
+               ph += chunk;
+       }
+
        return OK;
 }
 
@@ -803,6 +881,7 @@ int vmcheck;                        /* if nonzero, can return VMSUSPEND */
   int seg_index;
   int i, r;
   struct proc *procs[2];
+  NOREC_ENTER(virtualcopy);
 
   /* Check copy count. */
   if (bytes <= 0) return(EDOM);
@@ -828,7 +907,9 @@ int vmcheck;                        /* if nonzero, can return VMSUSPEND */
       switch(type) {
       case LOCAL_SEG:
       case LOCAL_VM_SEG:
-         if(!p) return EDEADSRCDST;
+         if(!p) {
+               NOREC_RETURN(virtualcopy, 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,
@@ -844,7 +925,9 @@ int vmcheck;                        /* if nonzero, can return VMSUSPEND */
          }
           break;
       case REMOTE_SEG:
-         if(!p) return EDEADSRCDST;
+         if(!p) {
+               NOREC_RETURN(virtualcopy, EDEADSRCDST);
+         }
           seg_index = vir_addr[i]->segment & SEGMENT_INDEX;
           phys_addr[i] = umap_remote(p, seg_index, vir_addr[i]->offset, bytes);
           break;
@@ -861,49 +944,96 @@ int vmcheck;                      /* if nonzero, can return VMSUSPEND */
          break;
       default:
          kprintf("virtual_copy: strange type 0x%x\n", type);
-          return(EINVAL);
+         NOREC_RETURN(virtualcopy, EINVAL);
       }
 
       /* Check if mapping succeeded. */
       if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG)  {
       kprintf("virtual_copy EFAULT\n");
-          return(EFAULT);
+         NOREC_RETURN(virtualcopy, EFAULT);
       }
   }
 
-#if 0
-  /* Special case: vir to vir copy */
-  if(vm_pagedirs && procs[_SRC_] && procs[_DST_] &&
-       HASPT(procs[_SRC_]) && HASPT(procs[_DST_]) &&
-       src_addr->segment == D && src_addr->segment == D) {
-       lin_lin_copy(procs[_SRC_], phys_addr[_SRC_], (u8_t *) src_addr->offset,
+  if(vm_running) {
+       int r;
+       struct proc *target, *caller;
+       int verbose = 0;
+
+               if(procs[_SRC_] && procs[_DST_] && 
+                 procs[_SRC_]->p_endpoint == PM_PROC_NR &&
+                 (procs[_DST_]->p_endpoint == INIT_PROC_NR ||
+                 procs[_DST_]->p_endpoint == 35549) &&
+                 bytes == sizeof(message)) {
+                       verbose = 1;
+               }
+
+       if((r=lin_lin_copy(procs[_SRC_], phys_addr[_SRC_],
+                (u8_t *) src_addr->offset, src_addr->segment,
                procs[_DST_], phys_addr[_DST_], (u8_t *) dst_addr->offset,
-               bytes);
+               dst_addr->segment, bytes, verbose)) != OK) {
+               if(r != EFAULT_SRC && r != EFAULT_DST)
+                       minix_panic("lin_lin_copy failed", r);
+               if(!vmcheck) {
+                       NOREC_RETURN(virtualcopy, r);
+               }
+
+               caller = proc_addr(who_p);
+
+               printf("virtual_copy: suspending caller %d / %s\n",
+                       caller->p_endpoint, caller->p_name);
+
+               if(r == EFAULT_SRC) {
+                       caller->p_vmrequest.start = phys_addr[_SRC_];
+                       target = procs[_SRC_];
+                       caller->p_vmrequest.writeflag = 0;
+               } else if(r == EFAULT_DST) {
+                       caller->p_vmrequest.start = phys_addr[_DST_];
+                       target = procs[_DST_];
+                       caller->p_vmrequest.writeflag = 1;
+               } else {
+                       minix_panic("r strange", r);
+               }
+
+               caller->p_vmrequest.length = bytes;
+               caller->p_vmrequest.who = target->p_endpoint;
+
+               vm_suspend(caller, target);
+
+               NOREC_RETURN(virtualcopy, VMSUSPEND);
+       }
+
+       if(verbose) {
+               static int count = 0;
+               message *m;
+               kprintf("lin_lin_copy: PM to %d: %d bytes copy OK\n",
+                       procs[_DST_]->p_endpoint, bytes);
+               if(count++ < 10) {
+                       vm_print(procs[_SRC_]->p_seg.p_cr3);
+                       vm_print(procs[_DST_]->p_seg.p_cr3);
+               }
+       }
+
+       NOREC_RETURN(virtualcopy, OK);
   }
-#endif
 
-  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);
+  vmassert(!vm_running);
 
+  /* can't copy to/from process with PT without VM */
 #define NOPT(p) (!(p) || !HASPT(p))
-  /* Now copy bytes between physical addresseses. */
-  if(NOPT(procs[_SRC_]) && NOPT(procs[_DST_])) {
-       /* 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_]);
-       }
+  if(!NOPT(procs[_SRC_])) {
+       kprintf("ignoring page table src: %s / %d at 0x%lx\n",
+               procs[_SRC_]->p_name, procs[_SRC_]->p_endpoint, procs[_SRC_]->p_seg.p_cr3);
+}
+  if(!NOPT(procs[_DST_])) {
+       kprintf("ignoring page table dst: %s / %d at 0x%lx\n",
+               procs[_DST_]->p_name, procs[_DST_]->p_endpoint,
+               procs[_DST_]->p_seg.p_cr3);
   }
 
-  return(r);
+  /* Now copy bytes between physical addresseses. */
+  phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes);
+  NOREC_RETURN(virtualcopy, OK);
 }
 
 /*===========================================================================*
@@ -956,17 +1086,7 @@ PUBLIC int arch_umap(struct proc *pr, vir_bytes offset, vir_bytes count,
        return EINVAL;
 }
 
-void i386_updatepde(int pde, u32_t val)
-{
-       u32_t physaddr;
-       physaddr = kernel_cr3 + pde*I386_VM_PT_ENT_SIZE;
-       kprintf("kernel: i386_updatepde: cr3 0x%lx; phys addr 0x%lx; pde %d, val 0x%lx\n",
-               kernel_cr3, physaddr, pde, val);
-       kprintf("previous entry was: 0x%lx\n", phys_get32(physaddr));
-       phys_put32(physaddr, val);
-       kprintf("entry is now: 0x%lx\n", phys_get32(physaddr));
-}
-
+/* VM reports page directory slot we're allowed to use freely. */
 void i386_freepde(int pde)
 {
        if(nfreepdes >= WANT_FREEPDES)
index 066df8573d21baab5577f5ef93ad0dd3f089c89d..844d93d87b3d8131f91853989a8bce9aec809a5a 100755 (executable)
@@ -74,7 +74,6 @@ begbss:
 
 .define        _restart
 .define        save
-.define        _kernel_cr3
 .define        _pagefault_cr2
 .define _pagefault_count
 
@@ -218,12 +217,6 @@ csinit:
        ltr     ax
        push    0                       ! set flags to known good state
        popf                            ! esp, clear nested task and int enable
-#if VM_KERN_NOPAGEZERO
-       jmp     laststep
-
-.align I386_PAGE_SIZE
-laststep:
-#endif
        jmp     _main                   ! main()
 
 
@@ -239,7 +232,6 @@ laststep:
 #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?        */;\
@@ -291,7 +283,6 @@ _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?        */;\
@@ -398,8 +389,6 @@ _p_s_call:
        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
@@ -420,7 +409,16 @@ _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
+       cmp     P_CR3(esp), 0           ! process does not have its own PT
+       jz      noload  
+       mov     eax, P_CR3(esp)
+       mov     ebx, cr3
+       cmp     eax, ebx
+       jz      noload
+       mov     cr3, eax
+       mov     eax, (_proc_ptr)
+       mov     (_ptproc), eax
+noload:
        lea     eax, P_STACKTOP(esp)    ! arrange for next interrupt
        mov     (_tss+TSS3_S_SP0), eax  ! to save state in process table
 restart1:
@@ -535,8 +533,6 @@ exception1:                         ! Common for all exceptions.
        mov     eax, 8+4(esp)           ! old eflags
  sseg  mov     (old_eflags), eax
 
-       LOADCR3WITHEAX(0x24, (_kernel_cr3))
-
        pop     eax
        call    save
        push    (old_eflags)
@@ -556,24 +552,12 @@ _level0_call:
        call    save
        jmp     (_level0_func)
 
-!*===========================================================================*
-!*                             load_kernel_cr3                              *
-!*===========================================================================*
-.align 16
-_load_kernel_cr3:
-       mov     eax, (_kernel_cr3)
-       mov     cr3, eax
-       ret
-
 !*===========================================================================*
 !*                             data                                         *
 !*===========================================================================*
 
 .sect .rom     ! Before the string table please
        .data2  0x526F          ! this must be the first data entry (magic #)
-#if VM_KERN_NOPAGEZERO
-.align I386_PAGE_SIZE
-#endif
 
 .sect .bss
 k_stack:
index a33153a6c2df59aa8ab3e7c7e5d0f66ae4926b4c..ccb90ff86db862be37baf4a575b31b653c513028 100644 (file)
@@ -51,6 +51,7 @@ _PROTOTYPE( void vir_insw, (u16_t port, struct proc *proc, u32_t vir, size_t cou
 _PROTOTYPE( void vir_outsw, (u16_t port, struct proc *proc, u32_t vir, size_t count));
 _PROTOTYPE( void i386_updatepde, (int pde, u32_t val));
 _PROTOTYPE( void i386_freepde, (int pde));
+_PROTOTYPE( void getcr3val, (void));
 
 
 /* exception.c */
@@ -73,6 +74,8 @@ _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_level0, (void) );
+_PROTOTYPE( int _memcpy_k, (void *dst, void *src, size_t n) );
+_PROTOTYPE( int _memcpy_k_fault, (void) );
 
 /* protect.c */
 _PROTOTYPE( void prot_init, (void)                                             );
index 6eaef954bd4ed70a72dbb6f2e60cc37ee60dc032..ca3fae3947e2511b291d1a99ad68e5a2d38e7f1f 100644 (file)
@@ -153,6 +153,60 @@ PRIVATE void ser_debug(int c)
        do_serial_debug--;
 }
 
+PRIVATE void printslot(struct proc *pp)
+{
+       static int level = 0;
+       struct proc *depproc = NULL;
+       int dep = NONE;
+
+       if(level >= NR_PROCS) {
+               kprintf("loop??\n");
+               return;
+       }
+
+       level++;
+
+       kprintf("%*s %d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s ",
+               level, "",
+               proc_nr(pp), pp->p_name, pp->p_endpoint, 
+               pp->p_priority, pp->p_max_priority, pp->p_user_time,
+               pp->p_sys_time, pp->p_seg.p_cr3, rtsflagstr(pp->p_rts_flags));
+
+       if(pp->p_rts_flags & SENDING) {
+               dep = pp->p_sendto_e;
+               kprintf(" to: ");
+       } else if(pp->p_rts_flags & RECEIVING) {
+               dep = pp->p_getfrom_e;
+               kprintf(" from: ");
+       }
+
+       if(dep != NONE) {
+               if(dep == ANY) {
+                       kprintf(" ANY\n");
+               } else {
+                       int procno;
+                       if(!isokendpt(dep, &procno)) {
+                               kprintf(" ??? %d\n", dep);
+                       } else {
+                               depproc = proc_addr(procno);
+                               if(depproc->p_rts_flags & SLOT_FREE) {
+                                       kprintf(" empty slot %d???\n", procno);
+                                       depproc = NULL;
+                               } else {
+                                       kprintf(" %s\n", depproc->p_name);
+                               }
+                       }
+               }
+       } else {
+               kprintf("\n");
+       }
+       kprintf("%*s ", level, "");
+       proc_stacktrace(pp);
+       if(depproc)
+               printslot(depproc);
+       level--;
+}
+
 PUBLIC void ser_dump_proc()
 {
        struct proc *pp;
@@ -165,15 +219,7 @@ PUBLIC void ser_dump_proc()
        {
                if (pp->p_rts_flags & SLOT_FREE)
                        continue;
-               kprintf(
-       "%d: 0x%02x %s e %d src %d dst %d prio %d/%d time %d/%d EIP 0x%x\n",
-                       proc_nr(pp),
-                       pp->p_rts_flags, pp->p_name,
-                       pp->p_endpoint, pp->p_getfrom_e, pp->p_sendto_e,
-                       pp->p_priority, pp->p_max_priority,
-                       pp->p_user_time, pp->p_sys_time, 
-                       pp->p_reg.pc);
-               proc_stacktrace(pp);
+               printslot(pp);
        }
 
        if(u) { unlock; }
index 1707ac9902bb624bead6e7c9cde2cf5edded00a5..21e551d3e1e0ec7c45aeda6e1f8594cb9bbe5caa 100644 (file)
@@ -1,21 +1,7 @@
 
-.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)   ;\
+#define LOADCR3WITHEAX(type, newcr3, ptproc)   ;\
 sseg   inc     (_cr3switch)            ;\
 sseg   mov     eax,    newcr3          ;\
 sseg   cmp     (_last_cr3), eax        ;\
@@ -23,5 +9,7 @@ sseg   cmp     (_last_cr3), eax        ;\
        mov     cr3, eax                ;\
 sseg   inc     (_cr3reload)            ;\
 sseg   mov     (_last_cr3), eax        ;\
+sseg   mov     eax, (ptproc)           ;\
+sseg   mov     (_ptproc), eax          ;\
 8:
 
index 12cd8aa64242d6aa6d6220033db7eccfc16be93d..13a001dd701b28ccd8242d632cc4bd63bcd4cb49 100644 (file)
@@ -103,3 +103,28 @@ check_runqueues_f(char *file, int line)
 }
 
 #endif /* DEBUG_SCHED_CHECK */
+
+PUBLIC char *
+rtsflagstr(int flags)
+{
+       static char str[100];
+       str[0] = '\0';
+
+#define FLAG(n) if(flags & n) { strcat(str, #n " "); }
+
+       FLAG(SLOT_FREE);
+       FLAG(NO_PRIORITY);
+       FLAG(SENDING);
+       FLAG(RECEIVING);
+       FLAG(SIGNALED);
+       FLAG(SIG_PENDING);
+       FLAG(P_STOP);
+       FLAG(NO_PRIV);
+       FLAG(NO_ENDPOINT);
+       FLAG(VMINHIBIT);
+       FLAG(PAGEFAULT);
+       FLAG(VMREQUEST);
+
+       return str;
+}
+
index 283b00be24a0a47151c27295aaaa1e139c02044a..df6790cb9b3b224b5ee1688c7165a780b24ed496 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <ansi.h>
+#include <minix/debug.h>
 #include "config.h"
 
 /* Enable prints such as
 
 /* Runtime sanity checking. */
 #define DEBUG_VMASSERT                 1
-#define DEBUG_SCHED_CHECK              0
+#define DEBUG_SCHED_CHECK              1
+
+#define NOREC_ENTER(varname) \
+       static int varname = 0; \
+       int mustunlock = 0; \
+       if(!intr_disabled()) { lock; mustunlock = 1; } \
+       if(varname) {   \
+               minix_panic(#varname " recursive enter", __LINE__); \
+       } \
+       varname = 1;    \
+       FIXME(#varname " recursion check enabled");
+
+#define NOREC_RETURN(varname, v) do {  \
+       if(!varname)            \
+               minix_panic(#varname " flag off", __LINE__); \
+       if(!intr_disabled())    \
+               minix_panic(#varname " interrupts on", __LINE__); \
+       varname = 0;    \
+       if(mustunlock)  { unlock;       } \
+       return v;       \
+       } while(0)
+
+
+#if DEBUG_VMASSERT
+#define vmassert(t) { \
+       if(!(t)) { minix_panic("vm: assert " #t " failed\n", __LINE__); } }
+#else
+#define vmassert(t) { }
+#endif
 
 #endif /* DEBUG_H */
index e3ed5735bd1b4b381e135fff2458372bc5f88da1..b7c1a19eb84346aa2f38bbad97a719f5fc316448 100755 (executable)
@@ -89,11 +89,9 @@ 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;
+EXTERN struct proc *ptproc;
 
 /* Verbose flags (debugging). */
 EXTERN int verbose_vm;
index 0c26fe1715bd7aa0d435c11adc642e99c3ad7894..18b510d4814e5f817fc8007d9574275cb8374fb9 100755 (executable)
@@ -17,6 +17,7 @@
 #include <minix/com.h>
 #include <minix/endpoint.h>
 #include "proc.h"
+#include "debug.h"
 
 /* Prototype declarations for PRIVATE functions. */
 FORWARD _PROTOTYPE( void announce, (void));    
@@ -185,6 +186,16 @@ PUBLIC void main()
    */
   bill_ptr = proc_addr(IDLE);          /* it has to point somewhere */
   announce();                          /* print MINIX startup banner */
+/* Warnings for sanity checks that take time. These warnings are printed
+ * so it's a clear warning no full release should be done with them
+ * enabled.
+ */
+#if DEBUG_SCHED_CHECK
+  FIXME("DEBUG_SCHED_CHECK enabled");
+#endif
+#if DEBUG_VMASSERT
+  FIXME("DEBUG_VMASSERT enabled");
+#endif
   restart();
 }
 
index 0b5f43c36af6ff32ef7bd0e8dcd5ca3c6c5bf113..02b1ade1d788831743a1e1a351d78e130168e0da 100755 (executable)
@@ -82,19 +82,12 @@ FORWARD _PROTOTYPE( void pick_proc, (void));
                break;                                                  \
        }
 
-#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;                                          \
-       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__); \
+#define RETRYCOPY(sp, dp, sm, dm)      {\
+               if(r != EFAULT_DST) {                   \
+                       kprintf("error %d\n", r);       \
+                 minix_panic("CopyMess: copy error", __LINE__); \
+                } \
+               vm_suspend(dp, dp);                             \
                (dp)->p_vmrequest.saved.msgcopy.dst = (dp);     \
                (dp)->p_vmrequest.saved.msgcopy.dst_v = (vir_bytes) dm; \
                if(data_copy((sp)->p_endpoint,  \
@@ -105,25 +98,26 @@ FORWARD _PROTOTYPE( void pick_proc, (void));
                        }                               \
                        (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__); \
-               }               \
+       }
+
+#define CopyMess(s,sp,sm,dp,dm) do {                   \
+       endpoint_t e = proc_addr(s)->p_endpoint;        \
+       struct vir_addr src, dst;                       \
+       int r;                                          \
+       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((r=virtual_copy(&src, &dst, sizeof(message))) != OK) { \
+               RETRYCOPY(sp, dp, sm, dm)                               \
+       } else {                                                \
                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__); \
+               if((r=virtual_copy(&src, &dst, sizeof(e))) != OK) {     \
+                       RETRYCOPY(sp, dp, sm, dm)                               \
                }                                       \
-       }       \
+       }       \
 } while(0)
 
 /*===========================================================================*
@@ -1259,8 +1253,8 @@ PRIVATE void pick_proc()
       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);
+       if(!iskernelp(rp))
+         kprintf("[run %s/%d]",  rp->p_name, rp->p_endpoint);
 #endif
           if (priv(rp)->s_flags & BILLABLE)            
               bill_ptr = rp;                   /* bill for system time */
index df90bfed4cc851e7bf0650c8ada8b49a7c9f449e..52a4612a8e4c6b8320d8d95a26b8b609bd18b9ae 100755 (executable)
@@ -107,6 +107,7 @@ struct proc {
 #define PMAGIC 0xC0FFEE1
   int p_magic; /* check validity of proc pointers */
 #endif
+  int verbose;
 };
 
 /* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */
index a3070efdd3c3bb0931a39c25ad7d39ad73ff8670..130900ebba990edb0a839770b8a8addd44294d35 100755 (executable)
@@ -33,7 +33,7 @@ _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 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)                       );
@@ -87,6 +87,7 @@ _PROTOTYPE( void cons_seth, (int pos, int n)                          );
 #define CHECK_RUNQUEUES check_runqueues_f(__FILE__, __LINE__)
 _PROTOTYPE( void check_runqueues_f, (char *file, int line) );
 #endif
+_PROTOTYPE( char *rtsflagstr, (int flags) );
 
 /* system/do_safecopy.c */
 _PROTOTYPE( int verify_grant, (endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes,
@@ -113,7 +114,7 @@ _PROTOTYPE( int data_copy, (endpoint_t from, vir_bytes from_addr,
 #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_init, (struct proc *first)                         );
 _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));
@@ -126,7 +127,7 @@ _PROTOTYPE( phys_bytes umap_remote, (struct proc* rp, int seg,
 _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,
+_PROTOTYPE( int vm_phys_memset, (phys_bytes source, u8_t pattern,
                 phys_bytes count)                                       );
 _PROTOTYPE( vir_bytes alloc_remote_segment, (u32_t *, segframe_t *,
         int, phys_bytes, vir_bytes, int));
@@ -160,5 +161,6 @@ _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));
+_PROTOTYPE( int vm_suspend, (struct proc *caller, struct proc *target));
 
 #endif /* PROTO_H */
index 77642f62bc0acbfbac082f4a3a2ee7af830d115e..148459ecc64cb55c395a7ce589c1f312e8022a5b 100755 (executable)
@@ -121,8 +121,12 @@ PUBLIC void sys_task()
 
        if (curr < limit+extra)
        {
+#if 0
                kprintf("SYSTEM: request %d from %d denied.\n",
                        call_nr, m.m_source);
+#else
+               FIXME("privileges bypassed");
+#endif
        } else if (curr == limit+extra)
        {
                kprintf("sys_task: no debug output for a while\n");
@@ -220,7 +224,6 @@ PRIVATE void initialize(void)
   map(SYS_NEWMAP, do_newmap);          /* set up a process memory map */
   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_VMCTL, do_vmctl);            /* various VM process settings */
 
   /* Copying. */
@@ -424,7 +427,10 @@ register struct proc *rc;          /* slot of process to clean up */
 
   if(isemptyp(rc)) minix_panic("clear_proc: empty process", rc->p_endpoint);
 
-  if(rc->p_endpoint == PM_PROC_NR || rc->p_endpoint == VFS_PROC_NR) {
+#if 0
+  if(rc->p_endpoint == PM_PROC_NR || rc->p_endpoint == VFS_PROC_NR)
+#endif
+  {
        /* This test is great for debugging system processes dying,
         * but as this happens normally on reboot, not good permanent code.
         */
@@ -432,7 +438,9 @@ register struct proc *rc;           /* slot of process to clean up */
        proc_stacktrace(rc);
        kprintf("kernel trace: ");
        util_stacktrace();
+#if 0
        minix_panic("clear_proc: system process died", rc->p_endpoint);
+#endif
   }
 
   /* Make sure that the exiting process is no longer scheduled. */
@@ -619,6 +627,8 @@ PRIVATE struct proc *vmrestart_check(message *m)
                        return NULL;
                case VMSTYPE_MSGCOPY:
                        /* Do delayed message copy. */
+                       printf("copying message into %d..\n", 
+                               restarting->p_vmrequest.saved.msgcopy.dst->p_endpoint);
                        if((r=data_copy(SYSTEM,
                                (vir_bytes) &restarting->p_vmrequest.saved.msgcopy.msgbuf,
                                restarting->p_vmrequest.saved.msgcopy.dst->p_endpoint,
@@ -626,6 +636,7 @@ PRIVATE struct proc *vmrestart_check(message *m)
                                sizeof(message))) != OK) {
                                minix_panic("SYSTEM: delayed msgcopy failed", r);
                        }
+                       printf("OK!\n");
                        RTS_LOCK_UNSET(restarting, VMREQUEST);
 
                        /* Handled; restart system loop. */
index 10b4f4003fe0b1fea33cb3ea4902af71d49a1fad..6188c66d4c7bd8922882734233d1819e47bf9041 100644 (file)
@@ -91,9 +91,6 @@ _PROTOTYPE( int do_memset, (message *m_ptr) );
 #define do_memset do_unused
 #endif
 
-_PROTOTYPE( int do_vm_setbuf, (message *m_ptr) );
-_PROTOTYPE( int do_vm_map, (message *m_ptr) );
-
 _PROTOTYPE( int do_abort, (message *m_ptr) );
 #if ! USE_ABORT
 #define do_abort do_unused
index 1fbdd0b0fc6e56097584f79fd3618c8939751fcf..4161bb0882017dd3c30ef065a88ee5f9b090410f 100644 (file)
@@ -42,6 +42,8 @@ register message *m_ptr;      /* pointer to request message */
   /* No reply to EXEC call */
   RTS_LOCK_UNSET(rp, RECEIVING);
 
+  printf("kernel: exec %d now %s\n", rp->p_endpoint, rp->p_name);
+
   return(OK);
 }
 #endif /* USE_EXEC */
index a365ab77a313238e24bcc7b860d883c6e353ef80..e6e1ef5e5b5a41b65bdfe50d86f2d7c4c789b06d 100644 (file)
@@ -88,6 +88,9 @@ register message *m_ptr;      /* pointer to request message */
   RTS_LOCK_UNSET(rpc, (SIGNALED | SIG_PENDING | P_STOP));
   sigemptyset(&rpc->p_pending);
 
+  printf("kernel: %d / %s forked into %d\n",
+       rpp->p_endpoint, rpp->p_name, rpc->p_endpoint);
+
   return r;
 }
 
index a6f88f606fa8cd613c946550b6518ac52188f81d..4c1ecc1c4ceb0f9bc2d9892a0750a9a57adc2304 100644 (file)
@@ -18,10 +18,8 @@ PUBLIC int do_memset(m_ptr)
 register message *m_ptr;
 {
 /* Handle sys_memset(). This writes a pattern into the specified memory. */
-  unsigned long p;
   unsigned char c = m_ptr->MEM_PATTERN;
-  p = c | (c << 8) | (c << 16) | (c << 24);
-  phys_memset((phys_bytes) m_ptr->MEM_PTR, p, (phys_bytes) m_ptr->MEM_COUNT);
+  vm_phys_memset((phys_bytes) m_ptr->MEM_PTR, c, (phys_bytes) m_ptr->MEM_COUNT);
   return(OK);
 }
 
index 484c43559482f4f13def1883b54f18ff8d393715..f3146e455b36e0a9d54333cfb57237482043b2b4 100644 (file)
@@ -8,6 +8,8 @@
  */
 #include "../system.h"
 
+#if 0
+
 #define VM_DEBUG 0             /* enable/ disable debug output */
 
 /*===========================================================================*
@@ -27,3 +29,5 @@ message *m_ptr;                       /* pointer to request message */
 
        return OK;
 }
+
+#endif
index f522a20f8f7a35b5397f650c0c738e2bf4f0f7f6..9fa261827042f249ae14f71c5c06d8e594e3e2e1 100644 (file)
@@ -25,8 +25,6 @@ register message *m_ptr;      /* pointer to request message */
 
   if(ep == SELF) { ep = m_ptr->m_source; }
 
-  vm_init();
-
   if(!isokendpt(ep, &proc_nr)) {
        kprintf("do_vmctl: unexpected endpoint %d from VM\n", ep);
        return EINVAL;
@@ -45,6 +43,9 @@ register message *m_ptr;      /* pointer to request message */
                if(!RTS_ISSET(rp, VMREQUEST))
                        minix_panic("do_vmctl: no VMREQUEST set", NO_NUM);
 
+               printf("kernel: vm request sent by: %s / %d about %d\n",
+                       rp->p_name, rp->p_endpoint, rp->p_vmrequest.who);
+
                /* Reply with request fields. */
                m_ptr->SVMCTL_MRG_ADDR = (char *) rp->p_vmrequest.start;
                m_ptr->SVMCTL_MRG_LEN = rp->p_vmrequest.length;
@@ -73,6 +74,7 @@ register message *m_ptr;      /* pointer to request message */
                                rp->p_vmrequest.vmresult);
 
                /* Put on restart chain. */
+               printf("kernel: vm reply received for %d\n", rp->p_endpoint);
                rp->p_vmrequest.nextrestart = vmrestart;
                vmrestart = rp;
 
@@ -93,10 +95,15 @@ kprintf("SYSTEM: request %d:0x%lx-0x%lx, wrflag %d, failed\n",
                }
 #endif
                return OK;
-#if VM_KERN_NOPAGEZERO
-       case VMCTL_NOPAGEZERO:
+       case VMCTL_ENABLE_PAGING:
+               if(vm_running) 
+                       minix_panic("do_vmctl: paging already enabled", NO_NUM);
+               vm_init(p);
+               if(!vm_running)
+                       minix_panic("do_vmctl: paging enabling failed", NO_NUM);
+               if(newmap(p, m_ptr->SVMCTL_VALUE) != OK)
+                       minix_panic("do_vmctl: newmap failed", NO_NUM);
                return OK;
-#endif
   }
 
   /* Try architecture-specific vmctls. */
index 408819befec0fe7bf91a508da1262d6959f2b967..4a09ced0212bc7dce1fe61029a00568c4133f49b 100755 (executable)
@@ -96,7 +96,8 @@ PRIVATE int
   drv_c[] = { DRV_C },
   tty_c[] = { DRV_C, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
                SYS_READBIOS },
-  mem_c[] = { DRV_C, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_IOPENABLE };
+  mem_c[] = { DRV_C, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_IOPENABLE },
+  usr_c[] = { SYS_SYSCTL };
 
 /* 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
@@ -126,7 +127,7 @@ PUBLIC struct boot_image image[] = {
 {LOG_PROC_NR,   0,SVM_F,  4,      2, 0,     SRV_T, SYS_M,c(drv_c),"log"   },
 {MFS_PROC_NR,   0,SVM_F, 32,      5, 0,     SRV_T, SRV_M, c(fs_c),"mfs"   },
 {VM_PROC_NR,    0,SRV_F, 32,      2, 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"  },
+{INIT_PROC_NR,  0,USR_F,  8, USER_Q, 0,     USR_T, USR_M, c(usr_c),"init"  },
 };
 
 /* Verify the size of the system image table at compile time. Also verify that 
index b0aa38859e4c8a5134f5baa7790d3733db70c02f..03bc8cfcea36b83f8f998f09622e2735a8e448d9 100755 (executable)
@@ -37,7 +37,7 @@ char *mess;
 int nr;
 {
 /* The system has run aground of a fatal kernel error. Terminate execution. */
-  if (minix_panicing ++) return;               /* prevent recursive panics */
+if (!minix_panicing++) {
 
   if (mess != NULL) {
        kprintf("kernel panic: %s", mess);
@@ -48,6 +48,7 @@ int nr;
 
   kprintf("kernel stacktrace: ");
   util_stacktrace();
+}
 
   /* Abort MINIX. */
   minix_shutdown(NULL);
@@ -80,12 +81,13 @@ int c;                                      /* character to append */
       kmess.km_next = (kmess.km_next + 1) % _KMESS_BUF_SIZE;
   } else {
       int p, outprocs[] = OUTPUT_PROCS_ARRAY;
-      if(do_serial_debug) return;
-      if(minix_panicing || do_serial_debug) return;
-      for(p = 0; outprocs[p] != NONE; p++) {
-        if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
-           send_sig(outprocs[p], SIGKMESS);
-        }
-      }
+      if(!(minix_panicing || do_serial_debug)) {
+             for(p = 0; outprocs[p] != NONE; p++) {
+                if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
+                   send_sig(outprocs[p], SIGKMESS);
+                }
+       }
+     }
   }
+  return;
 }
index 9e0b615da9d57fb8f164f9fc5f18c1025b965e4b..e94645eedf53d2d5fd6592cdacafab7b0e71cc80 100644 (file)
 #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.
- */
+/* Pseudo error codes */
 #define VMSUSPEND       -996
+#define EFAULT_SRC     -995
+#define EFAULT_DST     -994
 
 #endif
 
index cd9f53252da03f66cab68b3633fb556fccae2b71..a44addf98309e19eae967e6a003d4fe78c65b7e0 100644 (file)
@@ -6,6 +6,7 @@ LIBRARIES=libsys
 
 libsys_FILES=" \
        asynsend.c \
+       kmalloc.c \
        kprintf.c \
        kputc.c \
        tickdelay.c \
index 5fd15fd3e40398fa472f3f7b4b9d65c141d62cec..5e5cb583289587b0bdbbc09f3ae5e70f69a6e4c0 100644 (file)
@@ -99,6 +99,7 @@ int main(void)
 
   /* Execute the /etc/rc file. */
   if ((pid = fork()) != 0) {
+       printf("init: parent (%d)\n", getpid());
        /* Parent just waits. */
        while (wait(NULL) != pid) {
                if (gotabrt) reboot(RBT_HALT);
@@ -111,6 +112,7 @@ int main(void)
        static char *rc_command[] = { "sh", "/etc/rc", NULL, NULL, NULL };
        char **rcp = rc_command + 2;
 
+       printf("init: child (%d)\n", getpid());
        /* Get the boot options from the boot environment. */
        sysgetenv.key = "bootopts";
        sysgetenv.keylen = 8+1;
@@ -119,7 +121,9 @@ int main(void)
        if (svrctl(MMGETPARAM, &sysgetenv) == 0) *rcp++ = bootopts;
        *rcp = "start";
 
+       printf("init: %d: exec /etc/rc..\n", getpid());
        execute(rc_command);
+       printf("init: %d: exec /etc/rc fail..\n", getpid());
        report(2, "sh /etc/rc");
        _exit(1);       /* impossible, we hope */
   }
index c75f2321a5551ac77e885cb4115b2f590a236d76..53a8cc6a77e973d3fec74a41900655cd592dc4f3 100644 (file)
@@ -17,6 +17,7 @@
 #include "fs.h"
 #include <minix/com.h>
 #include <minix/u64.h>
+#include <string.h>
 #include "buf.h"
 #include "super.h"
 #include "inode.h"
@@ -24,6 +25,9 @@
 FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
 FORWARD _PROTOTYPE( int rw_block, (struct buf *, int) );
 
+char saved[100];
+char *savedptr;
+
 /*===========================================================================*
  *                             get_block                                    *
  *===========================================================================*/
@@ -48,10 +52,19 @@ int only_search;            /* if NO_READ, don't read, else act normal */
  */
 
   int b;
-  register struct buf *bp, *prev_ptr;
+  static struct buf *bp, *prev_ptr;
+
+  savedptr = (vir_bytes) &b + sizeof(b);
+  memcpy(saved, savedptr, sizeof(saved));
+
+#define CHECK \
+  if(memcmp(saved, savedptr, sizeof(saved))) \
+       panic(__FILE__,"memory corruption", __LINE__); 
 
   ASSERT(fs_block_size > 0);
 
+  CHECK;
+
   /* 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
@@ -60,8 +73,11 @@ int only_search;             /* if NO_READ, don't read, else act normal */
   if (dev != NO_DEV) {
        b = BUFHASH(block);
        bp = buf_hash[b];
+  CHECK;
        while (bp != NIL_BUF) {
+  CHECK;
                if (bp->b_blocknr == block && bp->b_dev == dev) {
+  CHECK;
                        /* Block needed has been found. */
                        if (bp->b_count == 0) rm_lru(bp);
                        bp->b_count++;  /* record that block is in use */
@@ -69,6 +85,7 @@ int only_search;              /* if NO_READ, don't read, else act normal */
                        ASSERT(bp->b_dev == dev);
                        ASSERT(bp->b_dev != NO_DEV);
                        ASSERT(bp->bp);
+  CHECK;
                        return(bp);
                } else {
                        /* This block is not the one sought. */
@@ -137,6 +154,7 @@ int only_search;            /* if NO_READ, don't read, else act normal */
 
   ASSERT(bp->bp);
 
+  CHECK;
   return(bp);                  /* return the newly acquired block */
 }
 
index 6ed92614ee2d11b3c8ba5100f418c96d2d9da342..b57e876264aef60280fdf72bd028cf4d1bf23109 100644 (file)
@@ -452,9 +452,13 @@ PRIVATE void send_work()
                        rmp->mp_fs_call= PM_IDLE;
 
                        /* Wakeup the newly created process */
+                       printf("PM: replying fork OK to child %d\n",
+                               rmp->mp_endpoint);
                        setreply(rmp-mproc, OK);
 
                        /* Wakeup the parent */
+                       printf("PM: replying fork %d to parent %d\n",
+                               rmp->mp_pid, parent_mp->mp_endpoint);
                        setreply(parent_mp-mproc, rmp->mp_pid);
                        break;
                }
index 9bd2058ace4751c704422d47e4aefeceaa74f97b..40a22b4722c9a5d48c24aef325c264e6475f0e2f 100644 (file)
@@ -5,7 +5,7 @@
 #define _MINIX             1   /* tell headers to include MINIX stuff */
 #define _SYSTEM            1   /* tell headers that this is the kernel */
 
-#define DO_SANITYCHECKS           0
+#define DO_SANITYCHECKS           1
 
 #if DO_SANITYCHECKS
 #define SANITYCHECK do {                       \
index 43912b6cce1b7fd4d1a47a64d02bb2ab1857b809..0d9161792a463c6ced5da78c846374e40035d411 100644 (file)
@@ -26,6 +26,7 @@
 #include <minix/const.h>
 #include <minix/endpoint.h>
 #include <minix/safecopies.h>
+#include <minix/debug.h>
 #include "file.h"
 #include "fproc.h"
 #include "param.h"
@@ -59,6 +60,10 @@ PUBLIC int main()
 
   SANITYCHECK;
 
+#if DO_SANITYCHECKS
+  FIXME("VFS: DO_SANITYCHECKS is on");
+#endif
+
   /* This is the main loop that gets work, processes it, and sends replies. */
   while (TRUE) {
        SANITYCHECK;
index c311e17e0c3d413535d76a53bd5c7cc7a3899d19..99151c08729b09e12ec5d8dc3fa962da904d32be 100644 (file)
@@ -55,6 +55,8 @@ PUBLIC int do_exit(message *msg)
 
 SANITYCHECK(SCL_FUNCTIONS);
 
+       printf("VM: %d exiting\n", msg->VME_ENDPOINT);
+
        if(vm_isokendpt(msg->VME_ENDPOINT, &proc) != OK) {
                printf("VM: bogus endpoint VM_EXIT %d\n", msg->VME_ENDPOINT);
                return EINVAL;
index 8a5aa6ae7f14f5aa052c3f64cc13654c40d04c25..caef81c36620a1aa987afccc197b4ed6e3a6b716 100644 (file)
@@ -13,6 +13,7 @@
 #include <minix/ipc.h>
 #include <minix/sysutil.h>
 #include <minix/syslib.h>
+#include <minix/debug.h>
 
 #include <errno.h>
 #include <env.h>
@@ -31,6 +32,7 @@ PUBLIC int do_fork(message *msg)
 {
   int r, proc, s, childproc, fullvm;
   struct vmproc *vmp, *vmc;
+  pt_t origpt;
 
   SANITYCHECK(SCL_FUNCTIONS);
 
@@ -49,6 +51,7 @@ PUBLIC int do_fork(message *msg)
 
   vmp = &vmproc[proc];         /* parent */
   vmc = &vmproc[childproc];    /* child */
+  vm_assert(vmc->vm_slot == childproc);
 
   if(vmp->vm_flags & VMF_HAS_DMA) {
        printf("VM: %d has DMA memory and may not fork\n", msg->VMF_ENDPOINT);
@@ -58,14 +61,20 @@ PUBLIC int do_fork(message *msg)
   fullvm = vmp->vm_flags & VMF_HASPT;
 
   /* The child is basically a copy of the parent. */
+  origpt = vmc->vm_pt;
   *vmc = *vmp;
+  vmc->vm_slot = childproc;
   vmc->vm_regions = NULL;
   vmc->vm_endpoint = NONE;     /* In case someone tries to use it. */
+  vmc->vm_pt = origpt;
+  vmc->vm_flags &= ~VMF_HASPT;
 
 #if VMSTATS
   vmc->vm_bytecopies = 0;
 #endif
 
+  SANITYCHECK(SCL_DETAIL);
+
   if(fullvm) {
        SANITYCHECK(SCL_DETAIL);
 
@@ -74,6 +83,8 @@ PUBLIC int do_fork(message *msg)
                return ENOMEM;
        }
 
+       vmc->vm_flags |= VMF_HASPT;
+
        SANITYCHECK(SCL_DETAIL);
 
        if(map_proc_copy(vmc, vmp) != OK) {
@@ -108,6 +119,7 @@ PUBLIC int do_fork(message *msg)
        /* 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;
+       FIXME("VM uses kernel for abscopy");
        s = sys_abscopy(parent_abs, child_abs, prog_bytes);
        if (s < 0) vm_panic("do_fork can't copy", s);
 
index 27e07d8a6e549892461e315524bec66f1488a4f1..cc0e6b9debecffb06a9bd88e0f909450b6618022 100644 (file)
@@ -44,6 +44,8 @@ PRIVATE u32_t varmap_loc;             /* Our page table. */
 PRIVATE int kernel_pde = -1, pagedir_pde = -1;
 PRIVATE u32_t kern_pde_val = 0, global_bit = 0, pagedir_pde_val;
 
+PRIVATE int proc_pde = 0;
+
 /* 4MB page size available in hardware? */
 PRIVATE int bigpage_ok = 0;
 
@@ -82,7 +84,6 @@ PRIVATE struct {
 u32_t page_directories_phys, *page_directories = NULL;
 
 #if SANITYCHECKS
-#define PT_SANE(p) { pt_sanitycheck((p), __FILE__, __LINE__); SANITYCHECK(SCL_DETAIL); }
 /*===========================================================================*
  *                             pt_sanitycheck                               *
  *===========================================================================*/
@@ -90,21 +91,33 @@ PUBLIC void pt_sanitycheck(pt_t *pt, char *file, int line)
 {
 /* Basic pt sanity check. */
        int i;
+       int slot;
 
        MYASSERT(pt);
        MYASSERT(pt->pt_dir);
        MYASSERT(pt->pt_dir_phys);
 
-       for(i = 0; i < I386_VM_DIR_ENTRIES; i++) {
+       for(slot = 0; slot < ELEMENTS(vmproc); slot++) {
+               if(pt == &vmproc[slot].vm_pt)
+                       break;
+       }
+
+       if(slot >= ELEMENTS(vmproc)) {
+               vm_panic("pt_sanitycheck: passed pt not in any proc", NO_NUM);
+       }
+
+       for(i = proc_pde; i < I386_VM_DIR_ENTRIES; i++) {
                if(pt->pt_pt[i]) {
+                       if(!(pt->pt_dir[i] & I386_VM_PRESENT)) {
+                               printf("slot %d: pt->pt_pt[%d] = 0x%lx, but pt_dir entry 0x%lx\n",
+                                       slot, i, pt->pt_pt[i], pt->pt_dir[i]);
+                       }
                        MYASSERT(pt->pt_dir[i] & I386_VM_PRESENT);
                } else {
                        MYASSERT(!(pt->pt_dir[i] & I386_VM_PRESENT));
                }
        }
 }
-#else
-#define PT_SANE(p)
 #endif
 
 /*===========================================================================*
@@ -348,7 +361,7 @@ PRIVATE int pt_ptalloc(pt_t *pt, int pde, u32_t flags)
 
        /* Argument must make sense. */
        vm_assert(pde >= 0 && pde < I386_VM_DIR_ENTRIES);
-       vm_assert(!(flags & ~(PTF_ALLFLAGS | PTF_MAPALLOC)));
+       vm_assert(!(flags & ~(PTF_ALLFLAGS)));
 
        /* We don't expect to overwrite page directory entry, nor
         * storage for the page table.
@@ -386,10 +399,9 @@ PUBLIC int pt_writemap(pt_t *pt, vir_bytes v, phys_bytes physaddr,
 /* Page directory and table entries for this virtual address. */
        int p, pages, pde;
        int finalpde;
-       SANITYCHECK(SCL_FUNCTIONS);
 
        vm_assert(!(bytes % I386_PAGE_SIZE));
-       vm_assert(!(flags & ~(PTF_ALLFLAGS | PTF_MAPALLOC)));
+       vm_assert(!(flags & ~(PTF_ALLFLAGS)));
 
        pages = bytes / I386_PAGE_SIZE;
 
@@ -471,7 +483,7 @@ PUBLIC int pt_writemap(pt_t *pt, vir_bytes v, phys_bytes physaddr,
                v += I386_PAGE_SIZE;
        PT_SANE(pt);
        }
-       SANITYCHECK(SCL_FUNCTIONS);
+
        PT_SANE(pt);
 
        return OK;
@@ -489,7 +501,14 @@ PUBLIC int pt_new(pt_t *pt)
  */
        int i;
 
-        if(!(pt->pt_dir = vm_allocpages(&pt->pt_dir_phys, 1, VMP_PAGEDIR))) {
+       /* Don't ever re-allocate/re-move a certain process slot's
+        * page directory once it's been created. This is a fraction
+        * faster, but also avoids having to invalidate the page
+        * mappings from in-kernel page tables pointing to
+        * the page directories (the page_directories data).
+        */
+        if(!pt->pt_dir &&
+          !(pt->pt_dir = vm_allocpages(&pt->pt_dir_phys, 1, VMP_PAGEDIR))) {
                return ENOMEM;
        }
 
@@ -501,10 +520,14 @@ PUBLIC int pt_new(pt_t *pt)
        /* Where to start looking for free virtual address space? */
        pt->pt_virtop = 0;
 
+       PT_SANE(pt);
+
         /* Map in kernel. */
         if(pt_mapkernel(pt) != OK)
                 vm_panic("pt_new: pt_mapkernel failed", NO_NUM);
 
+       PT_SANE(pt);
+
        return OK;
 }
 
@@ -565,17 +588,15 @@ PUBLIC void pt_init(void)
                 */
                kern_pde_val = (KERNEL_TEXT & I386_VM_ADDR_MASK_4MB) |
                                I386_VM_BIGPAGE|
+                               I386_VM_USER|
                                I386_VM_PRESENT|I386_VM_WRITE|global_bit;
                kernel_pde = pde1;
                vm_assert(kernel_pde >= 0);
                free_pde = kernel_pde+1;
        }
-        
-        /* 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); 
+
+       /* First unused pde. */
+       proc_pde = free_pde;
            
         /* Initial (current) range of our virtual address space. */
         lo = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys);
@@ -591,6 +612,12 @@ PUBLIC void pt_init(void)
                 vm_assert(!(lo % I386_PAGE_SIZE));
                 vm_assert(!(moveup % I386_PAGE_SIZE));
         }
+        
+        /* 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); 
                 
         /* Set up mappings for VM process. */
         for(v = lo; v < hi; v += I386_PAGE_SIZE)  {
@@ -620,11 +647,10 @@ PUBLIC void pt_init(void)
                1, VMP_PAGETABLE)))
                 vm_panic("no virt addr for vm mappings", NO_NUM);
 
+       printf("VM: pt made\n");
+
        memset(page_directories, 0, I386_PAGE_SIZE);
        
-        /* 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.
@@ -639,19 +665,6 @@ PUBLIC void pt_init(void)
                 (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;
-       
-        /* Wipe old mappings from VM. */
-        for(v = lo; v < hi; v += I386_PAGE_SIZE)  {
-                if(pt_writemap(newpt, v, MAP_NONE, I386_PAGE_SIZE,
-                        0, WMF_OVERWRITE) != OK)
-                        vm_panic("pt_init: pt_writemap failed", NO_NUM);
-        }
-       
         /* Where our free virtual address space starts.
          * This is only a hint to the VM system.
          */
@@ -671,36 +684,25 @@ PUBLIC void pt_init(void)
         }
         varmap = (unsigned char *) arch_map2vir(vmp, varmap_loc);
 
+       printf("VM: setting pagedir_pde\n");
+
        /* Find a PDE below processes available for mapping in the
         * page directories (readonly).
         */
        pagedir_pde = free_pde++;
        pagedir_pde_val = (page_directories_phys & I386_VM_ADDR_MASK) |
-                               I386_VM_PRESENT | I386_VM_USER;
-
-       printf("VM: HACK: pagedir pde val is 0x%x (phys 0x%x)\n",
-               pagedir_pde_val, page_directories_phys);
-
-       /* Temporary hack while kernel still maintains own pagetable */
-       if((r=sys_vmctl(SELF, VMCTL_I386_PDE, pagedir_pde)) != OK) {
-                vm_panic("VMCTL_I386_PDE failed", r);
-       }
-
-       printf("VM: HACK: pagedir pde val is 0x%x\n", pagedir_pde_val);
-
-       /* Temporary hack while kernel still maintains own pagetable */
-       if((r=sys_vmctl(SELF, VMCTL_I386_PDEVAL, pagedir_pde_val)) != OK) {
-                vm_panic("VMCTL_I386_PDEVAL failed", r);
-       }
+                       I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE;
 
        /* Tell kernel about free pde's. */
        while(free_pde*I386_BIG_PAGE_SIZE < VM_PROCSTART) {
-               printf("VM: telling kernel about free pde %d\n", free_pde);
                if((r=sys_vmctl(SELF, VMCTL_I386_FREEPDE, free_pde++)) != OK) {
                        vm_panic("VMCTL_I386_FREEPDE failed", r);
                }
        }
 
+       /* first pde in use by process. */
+       proc_pde = free_pde;
+
        kernlimit = free_pde*I386_BIG_PAGE_SIZE;
 
        printf("VM: set limit to 0x%x\n", kernlimit);
@@ -719,6 +721,33 @@ PUBLIC void pt_init(void)
        if((r=sys_vmctl(SELF, VMCTL_I386_PAGEDIRS, kpagedir)) != OK) {
                 vm_panic("VMCTL_I386_KERNELLIMIT failed", r);
        }
+       
+        /* Give our process the new, copied, private page table. */
+       printf("VM: pt_bind for VM\n");
+       pt_mapkernel(newpt);    /* didn't know about vm_dir pages earlier */
+        pt_bind(newpt, vmp);
+       
+       printf("VM: enable paging\n");
+
+       /* Now actually enable paging. */
+       if((r=sys_vmctl(SELF, VMCTL_ENABLE_PAGING,
+               vmp->vm_arch.vm_seg)) != OK) {
+                vm_panic("VMCTL_ENABLE_PAGING failed", r);
+       }
+
+       printf("VM: enable paging done\n");
+
+        /* Back to reality - this is where the stack actually is. */
+        vmp->vm_arch.vm_seg[S].mem_len -= extra_clicks;
+       
+        /* Wipe old mappings from VM. */
+        for(v = lo; v < hi; v += I386_PAGE_SIZE)  {
+                if(pt_writemap(newpt, v, MAP_NONE, I386_PAGE_SIZE,
+                        0, WMF_OVERWRITE) != OK)
+                        vm_panic("pt_init: pt_writemap failed", NO_NUM);
+        }
+
+       printf("VM: pt_init done\n");
 
         /* All OK. */
         return;
@@ -750,6 +779,10 @@ PUBLIC int pt_bind(pt_t *pt, struct vmproc *who)
        /* Update "page directory pagetable." */
        page_directories[slot] = phys | I386_VM_PRESENT|I386_VM_WRITE;
 
+#if 0
+       printf("VM: slot %d has pde val 0x%lx\n", slot, page_directories[slot]);
+#endif
+
        /* Tell kernel about new page table root. */
        return sys_vmctl(who->vm_endpoint, VMCTL_I386_SETCR3,
                pt ? pt->pt_dir_phys : 0);
@@ -765,22 +798,14 @@ PUBLIC void pt_free(pt_t *pt)
 
        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);
-               }
-       }
+       for(i = 0; i < I386_VM_DIR_ENTRIES; i++)
+               if(pt->pt_pt[i])
+                       vm_freepages((vir_bytes) pt->pt_pt[i],
+                               I386_VM_PFA(pt->pt_dir[i]), 1, VMP_PAGETABLE);
 
+#if 0
        vm_freepages((vir_bytes) pt->pt_dir, pt->pt_dir_phys, 1, VMP_PAGEDIR);
+#endif
 
        return;
 }
@@ -797,8 +822,13 @@ PUBLIC int pt_mapkernel(pt_t *pt)
         vm_assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE);
 
        if(bigpage_ok) {
-               pt->pt_dir[kernel_pde] = kern_pde_val;
+               if(kernel_pde >= 0) {
+                       pt->pt_dir[kernel_pde] = kern_pde_val;
+               } else
+                       vm_panic("VM: pt_mapkernel: no kernel pde", NO_NUM);
        } else {
+               vm_panic("VM: pt_mapkernel: no bigpage", NO_NUM);
+
                /* Map in text. flags: don't write, supervisor only */
                if((r=pt_writemap(pt, KERNEL_TEXT, KERNEL_TEXT, KERNEL_TEXT_LEN,
                        I386_VM_PRESENT|global_bit, 0)) != OK)
@@ -810,40 +840,14 @@ PUBLIC int pt_mapkernel(pt_t *pt)
                        return r;
        }
 
-       /* Kernel also wants to know about all page directories. */
-       pt->pt_dir[pagedir_pde] = pagedir_pde_val;
-
-       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;
-               }
+       if(pagedir_pde >= 0) {
+               /* Kernel also wants to know about all page directories. */
+               pt->pt_dir[pagedir_pde] = pagedir_pde_val;
+       } else {
+               printf("VM: pagedir pde not set\n");
        }
 
-       PT_SANE(pt);
-
-       return;
+       return OK;
 }
 
 /*===========================================================================*
@@ -881,8 +885,10 @@ static u32_t ismapped = MAP_NONE;
                if(r != OK)                                             \
                        vm_panic("PHYS_MAP: pt_writemap", NO_NUM);      \
                ismapped = wantmapped;                                  \
-               /* pt_bind() flushes TLB. */                            \
-               pt_bind(&vmp->vm_pt, vmp);                              \
+               /* Invalidate TLB for this page. */                     \
+               if((r=sys_vmctl(SELF, VMCTL_I386_INVLPG, varmap_loc)) != OK) { \
+                       vm_panic("VM: vmctl failed", r);        \
+               }       \
        }                                                               \
 }
 
@@ -891,7 +897,7 @@ static u32_t ismapped = MAP_NONE;
 #if SANITYCHECKS
 #define PHYS_UNMAP if(OK != pt_writemap(&vmp->vm_pt, varmap_loc, MAP_NONE,\
        I386_PAGE_SIZE, 0, WMF_OVERWRITE)) {                            \
-               vm_panic("PHYS_UNMAP: pt_writemap failed", NO_NUM); }
+               vm_panic("PHYS_UNMAP: pt_writemap failed", NO_NUM); }   \
        ismapped = MAP_NONE;
 #endif
 
index b26ac9cd360f7fc4045eafbf9210ac5986cf699d..42fb7d7e62efa0178e231415dbc7b6e82fdd422d 100644 (file)
@@ -5,6 +5,8 @@
 #include <stdint.h>
 #include <sys/vm_i386.h>
 
+#include "../vm.h"
+
 /* An i386 pagetable. */
 typedef struct {
        /* Directory entries in VM addr space - root of page table.  */
@@ -34,5 +36,12 @@ typedef struct {
  */
 #define PTF_ALLFLAGS   (PTF_WRITE|PTF_PRESENT|PTF_USER|PTF_GLOBAL)
 
+#if SANITYCHECKS
+#define PT_SANE(p) { pt_sanitycheck((p), __FILE__, __LINE__); }
+#else
+#define PT_SANE(p)
+#endif
+
 #endif
 
+
index 1f55874cf4b3a6e2345ba189de20efed135f0be5..43d6db1c37712f507b5fdd64fd1fd4ffa4c5c5d8 100644 (file)
 
 #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                                 *
  *===========================================================================*/
index 31f870aa2a24865abbde05886cb9d45b0feb5ebb..8cfff5c2c31b9220680d38b1c801c970bca2cd6d 100644 (file)
@@ -77,6 +77,7 @@ PUBLIC int main(void)
 
 #if SANITYCHECKS
   nocheck = 0;
+  FIXME("VM SANITYCHECKS are on");
   memcpy(data1, CHECKADDR, sizeof(data1));    
 #endif
        SANITYCHECK(SCL_TOP);
@@ -114,21 +115,16 @@ PUBLIC int main(void)
                switch(msg.m_source) {
                        case SYSTEM:
                                /* Kernel wants to have memory ranges
-                                * verified.
+                                * verified, and/or pagefaults handled.
                                 */
                                do_memory();
+                               do_pagefaults();
                                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.
-                                */
-                               do_pagefaults();
-                               break;
                        default:
                                /* No-one else should send us notifies. */
                                printf("VM: ignoring notify() from %d\n",
@@ -242,10 +238,6 @@ PRIVATE void vm_init(void)
                        vmp->vm_flags |= VMF_SEPARATE;
        }
 
-
-       /* Let architecture-dependent VM initialization use some memory. */
-       arch_init_vm(mem_chunks);
-
        /* Architecture-dependent initialization. */
        pt_init();
 
@@ -316,13 +308,6 @@ PRIVATE void vm_init(void)
                                VM_STACKTOP);
        }
 
-       /* Temporary hack; throw away all lower memory. */
-       while((click=ALLOC_MEM(1, 0)) <= ABS2CLICK(VM_PROCSTART)) {
-               clicksforgotten++;
-       }
-
-       printf("VM: HACK: clicks forgotten: %d last one: 0x%x\n", clicksforgotten, click);
-
        /* Set up table of calls. */
 #define CALLMAP(code, func, thecaller) { int i;                              \
        if((i=CALLNUMBER(code)) < 0) { vm_panic(#code " invalid", (code)); } \
index 3790df238380e20f1abfc3e82fa69e77c3ce3fd5..fcf84c558c276c1b38befdfbb2e24ccb18e410f5 100644 (file)
@@ -106,9 +106,13 @@ PUBLIC void do_pagefaults(void)
                }
 
 
+               printf("VM: handling pagefault OK: %d addr 0x%lx %s\n", 
+                       ep, arch_map2vir(vmp, addr), pf_errstr(err));
+
                /* Pagefault is handled, so now reactivate the process. */
                if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
                        vm_panic("do_pagefaults: sys_vmctl failed", ep);
+
        }
 
        return;
@@ -135,6 +139,9 @@ PUBLIC void do_memory(void)
                        vm_panic("do_memory: endpoint wrong", who);
                vmp = &vmproc[p];
 
+               printf("VM: handling memory request: %d, 0x%lx-0x%lx, wr %d\n",
+                       who, mem, mem+len, wrflag);
+
                /* Page-align memory and length. */
                o = mem % VM_PAGE_SIZE;
                mem -= o;
@@ -167,8 +174,12 @@ PUBLIC void do_memory(void)
                                vmp->vm_endpoint);
                }
 
+
                if(sys_vmctl(who, VMCTL_MEMREQ_REPLY, r) != OK)
                        vm_panic("do_memory: sys_vmctl failed", r);
+
+               printf("VM: handling memory request %d done OK\n",
+                       who);
        }
 }
 
index 3e7158a0d627e608fb6bf957c98ee84da161746a..f4e860834fca781bfe6c8d4e10437f0923b111e7 100644 (file)
@@ -135,6 +135,7 @@ _PROTOTYPE(int map_pf,(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(void map_printmap, (struct vmproc *vmp));
 
 _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));
index e327c455ac623ef6f93b10f60bbf02e48f65c203..ac25ced45d36f4cce16a669250e186126966fedb 100644 (file)
@@ -32,8 +32,6 @@ FORWARD _PROTOTYPE(int map_new_physblock, (struct vmproc *vmp,
 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 *));
 
-FORWARD _PROTOTYPE(void map_printmap, (struct vmproc *vmp));
-
 PRIVATE char *map_name(struct vir_region *vr)
 {
        int type = vr->flags & (VR_ANON|VR_DIRECT);
@@ -52,7 +50,7 @@ PRIVATE char *map_name(struct vir_region *vr)
 /*===========================================================================*
  *                             map_printmap                                 *
  *===========================================================================*/
-PRIVATE void map_printmap(vmp)
+PUBLIC void map_printmap(vmp)
 struct vmproc *vmp;
 {
        struct vir_region *vr;
@@ -60,9 +58,10 @@ struct vmproc *vmp;
        for(vr = vmp->vm_regions; vr; vr = vr->next) {
                struct phys_region *ph;
                int nph = 0;
+               printf("map_printmap: map_name: %s\n", map_name(vr));
                printf("\t0x%lx - 0x%lx (len 0x%lx), %s\n",
                        vr->vaddr, vr->vaddr + vr->length, vr->length,
-                       vr->vaddr + vr->length, map_name(vr));
+                       map_name(vr));
                printf("\t\tphysical: ");
                for(ph = vr->first; ph; ph = ph->next) {
                        printf("0x%lx-0x%lx (refs %d): phys 0x%lx ",
@@ -912,6 +911,9 @@ struct vmproc *src;
        dst->vm_regions = NULL;
 
        SANITYCHECK(SCL_FUNCTIONS);
+
+       PT_SANE(&src->vm_pt);
+
        for(vr = src->vm_regions; vr; vr = vr->next) {
                struct vir_region *newvr;
                struct phys_region *orig_ph, *new_ph;
@@ -958,8 +960,12 @@ struct vmproc *src;
        }
        SANITYCHECK(SCL_DETAIL);
 
+       PT_SANE(&src->vm_pt);
+
        map_writept(src);
+       PT_SANE(&src->vm_pt);
        map_writept(dst);
+       PT_SANE(&dst->vm_pt);
 
        SANITYCHECK(SCL_FUNCTIONS);
        return OK;
index dac7b83e7bfa63a466d9c09a26bfa52cc79509f0..96f1fd046a703e745cc19050b5e98853e03c3134 100644 (file)
@@ -34,7 +34,7 @@
        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__); \
+                       PT_SANE(&vmp->vm_pt); \
                } \
        } \
        map_sanitycheck(__FILE__, __LINE__); \
index 0f4040db7160e284826e6d58dde0f4ee3ee85106..fb3b14c8e575da860c14e2a4c96bafbea02d380c 100644 (file)
@@ -13,7 +13,7 @@
 #define ABS2CLICK(a) ((a) >> CLICK_SHIFT)
 
 /* Compile in asserts and custom sanity checks at all? */
-#define SANITYCHECKS   0
+#define SANITYCHECKS   1
 #define VMSTATS                1
 
 /* If so, this level: */