]> Zhao Yanbai Git Server - minix.git/commitdiff
my state.
authorBen Gras <ben@minix3.org>
Sat, 6 Jun 2009 23:27:10 +0000 (23:27 +0000)
committerBen Gras <ben@minix3.org>
Sat, 6 Jun 2009 23:27:10 +0000 (23:27 +0000)
trying to get some memory optimisation (less pagetable reloading,
less tlb purging) features working smoothly.

to be documented when committing to trunk :)

30 files changed:
include/minix/com.h
include/minix/syslib.h
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 [deleted file]
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/do_devio.c
kernel/system/do_fork.c
kernel/system/do_memset.c
kernel/system/do_safecopy.c
kernel/system/do_vmctl.c
kernel/table.c
lib/syslib/sys_vmctl.c
servers/vfs/main.c
servers/vm/fork.c
servers/vm/i386/pagetable.c
servers/vm/main.c
servers/vm/pagefaults.c

index 5e629aa991e2858192f7b0fb7eed30ed9c1c8cdc..a154d0a6a2ad29b3cbcafd82a7c459761e444d21 100755 (executable)
 #define SVMCTL_MRG_LEN         m1_i1   /* MEMREQ_GET reply: length */
 #define SVMCTL_MRG_WRITE       m1_i2   /* MEMREQ_GET reply: writeflag */
 #define SVMCTL_MRG_EP          m1_i3   /* MEMREQ_GET reply: process */
+#define SVMCTL_MRG_REQUESTOR   m1_p2   /* MEMREQ_GET reply: requestor */
 
 /* Codes and field names for SYS_SYSCTL. */
 #define SYSCTL_CODE            m1_i1   /* SYSCTL_CODE_* below */
index 07b9975dfeb95994a43cbdb96d71f8a501d08699..af0e87b540788943ee622f79154ce01fd2afb755 100755 (executable)
@@ -53,9 +53,8 @@ _PROTOTYPE( int sys_vmctl, (endpoint_t who, int param, u32_t value));
 _PROTOTYPE( int sys_vmctl_get_pagefault_i386, (endpoint_t *who, u32_t *cr2, u32_t *err));
 _PROTOTYPE( int sys_vmctl_get_cr3_i386, (endpoint_t who, u32_t *cr3)  );
 _PROTOTYPE( int sys_vmctl_get_memreq, (endpoint_t *who, vir_bytes *mem,
-        vir_bytes *len, int *wrflag) );
-
-
+        vir_bytes *len, int *wrflag, endpoint_t *) );
+_PROTOTYPE( int sys_vmctl_enable_paging, (struct mem_map *));
 
 _PROTOTYPE( int sys_readbios, (phys_bytes address, void *buf, size_t size));
 _PROTOTYPE( int sys_stime, (time_t boottime));
index 2363a2c570174e0a80a69c14181ea87af2fb4601..9d0829a3a0e57dc15d4350ece426a1482346937b 100644 (file)
@@ -77,7 +77,7 @@ register message *m_ptr;      /* pointer to request message */
        return EPERM;
      }
      /* Get and check physical address. */
-     if ((phys_buf = umap_virtual(proc_addr(proc_nr), D,
+     if ((phys_buf = umap_local(proc_addr(proc_nr), D,
         (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
          return(EFAULT);
   }
index 29ab505e24be5fc283fb1702cd94bf503e97f08e..c3731f95e52ad93c8a0152bca506429e8badeef8 100755 (executable)
 #include <minix/sysutil.h>
 #include "../../proc.h"
 #include "../../proto.h"
+#include "../../vm.h"
 
 extern int vm_copy_in_progress, catch_pagefaults;
 extern struct proc *vm_copy_from, *vm_copy_to;
+extern u32_t npagefaults;
 
-u32_t pagefault_cr2, pagefault_count = 0;
-vir_bytes *old_eip_ptr = NULL, *old_eax_ptr = NULL;
+PUBLIC u32_t pagefault_count = 0;
 
-void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno)
+void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno,
+       u32_t *old_eipptr, u32_t *old_eaxptr, u32_t pagefaultcr2)
 {
        int s;
        vir_bytes ph;
        u32_t pte;
        int procok = 0, pcok = 0, rangeok = 0;
-       int in_memcpy = 0, in_physcopy = 0;
+       int in_physcopy = 0;
+       vir_bytes test_eip;
 
-       vmassert(old_eip_ptr);
-       vmassert(old_eax_ptr);
+       vmassert(old_eipptr);
+       vmassert(old_eaxptr);
 
-       vmassert(*old_eip_ptr == old_eip);
-       vmassert(old_eip_ptr != &old_eip);
+       vmassert(*old_eipptr == old_eip);
+       vmassert(old_eipptr != &old_eip);
 
        vmassert(pagefault_count == 1);
 
-       if(catch_pagefaults) {
-               vir_bytes test_eip;
-               test_eip = k_reenter ? old_eip : pr->p_reg.pc;
-               in_memcpy = (test_eip > (vir_bytes) _memcpy_k) &&
-                  (test_eip < (vir_bytes) _memcpy_k_fault);
-               in_physcopy = (test_eip > (vir_bytes) phys_copy) &&
-                  (test_eip < (vir_bytes) phys_copy_fault);
-               if((pcok = in_memcpy || in_physcopy)) {
-                       pagefault_count = 0;
-
-                       if(in_memcpy) {
-                               vmassert(!in_physcopy);
-                               *old_eip_ptr = _memcpy_k_fault;
-                       }
-                       if(in_physcopy) {
-                               vmassert(!in_memcpy);
-                               *old_eip_ptr = phys_copy_fault;
-                       }
-                       *old_eax_ptr = pagefault_cr2;
-
-                       return;
-               }
+#if 0
+       printf("kernel: pagefault in pr %d, addr 0x%lx, his cr3 0x%lx, actual cr3 0x%lx\n",
+               pr->p_endpoint, pagefaultcr2, pr->p_seg.p_cr3, read_cr3());
+#endif
+
+       if(pr->p_seg.p_cr3) {
+#if 0
+               vm_print(pr->p_seg.p_cr3);
+#endif
+               vmassert(pr->p_seg.p_cr3 == read_cr3());
+       } else {
+               vmassert(ptproc);
+               vmassert(ptproc->p_seg.p_cr3 == read_cr3());
        }
 
+       test_eip = k_reenter ? old_eip : pr->p_reg.pc;
+
+       in_physcopy = (test_eip > (vir_bytes) phys_copy) &&
+          (test_eip < (vir_bytes) phys_copy_fault);
+
+       if((k_reenter || iskernelp(pr)) &&
+               catch_pagefaults && in_physcopy) {
+#if 0
+               printf("pf caught! addr 0x%lx\n", pagefaultcr2);
+#endif
+               *old_eipptr = phys_copy_fault;
+               *old_eaxptr = pagefaultcr2;
+
+               pagefault_count = 0;
+
+               return;
+       }
+
+       npagefaults++;
+
        /* 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).
@@ -67,9 +81,9 @@ void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno)
                /* Page fault we can't / don't want to
                 * handle.
                 */
-               kprintf("pagefault for process %d ('%s'), pc = 0x%x, addr = 0x%x, flags = 0x%x\n",
+               kprintf("pagefault for process %d ('%s'), pc = 0x%x, addr = 0x%x, flags = 0x%x, k_reenter %d\n",
                        pr->p_endpoint, pr->p_name, pr->p_reg.pc,
-                       pagefault_cr2, trap_errno);
+                       pagefaultcr2, trap_errno, k_reenter);
                proc_stacktrace(pr);
                minix_panic("page fault in system process", pr->p_endpoint);
 
@@ -86,12 +100,12 @@ void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno)
         * and tell VM there is a pagefault to be
         * handled.
         */
-       pr->p_pagefault.pf_virtual = pagefault_cr2;
+       pr->p_pagefault.pf_virtual = pagefaultcr2;
        pr->p_pagefault.pf_flags = trap_errno;
        pr->p_nextpagefault = pagefaults;
        pagefaults = pr;
                
-       lock_notify(SYSTEM, VM_PROC_NR);
+       lock_notify(HARDWARE, VM_PROC_NR);
 
        pagefault_count = 0;
 
@@ -101,12 +115,16 @@ void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno)
 /*===========================================================================*
  *                             exception                                    *
  *===========================================================================*/
-PUBLIC void exception(vec_nr, trap_errno, old_eip, old_cs, old_eflags)
+PUBLIC void exception(vec_nr, trap_errno, old_eip, old_cs, old_eflags,
+       old_eipptr, old_eaxptr, pagefaultcr2)
 unsigned vec_nr;
 u32_t trap_errno;
 u32_t old_eip;
 U16_t old_cs;
 u32_t old_eflags;
+u32_t *old_eipptr;
+u32_t *old_eaxptr;
+u32_t pagefaultcr2;
 {
 /* An exception or unexpected interrupt has occurred. */
 
@@ -141,6 +159,8 @@ struct proc *t;
 
   /* Save proc_ptr, because it may be changed by debug statements. */
   saved_proc = proc_ptr;       
+  
+  CHECK_RUNQUEUES;
 
   ep = &ex_data[vec_nr];
 
@@ -150,8 +170,9 @@ struct proc *t;
   }
 
   if(vec_nr == PAGE_FAULT_VECTOR) {
-               pagefault(old_eip, saved_proc, trap_errno);
-               return;
+       pagefault(old_eip, saved_proc, trap_errno,
+               old_eipptr, old_eaxptr, pagefaultcr2);
+       return;
   }
 
   /* If an exception occurs while running a process, the k_reenter variable 
@@ -222,7 +243,7 @@ PUBLIC void proc_stacktrace(struct proc *proc)
                        break;
                }
                if(PRCOPY(proc, v_bp + sizeof(v_pc), &v_pc, sizeof(v_pc)) != OK) {
-                       kprintf("(v_pc 0x%lx ?)", v_pc);
+                       kprintf("(v_pc 0x%lx ?)", v_bp + sizeof(v_pc));
                        break;
                }
                kprintf("0x%lx ", (unsigned long) v_pc);
index 18a602846988da35af6f0ae6d86595bfb6dc8220..19c8b9cdbda02d83c8d7d6f8b0ff83718156de99 100755 (executable)
@@ -383,8 +383,6 @@ _phys_copy:
        mov     edi, PC_ARGS+4(esp)
        mov     eax, PC_ARGS+4+4(esp)
 
-       mov     (_catch_pagefaults), 1
-
        cmp     eax, 10                 ! avoid align overhead for small counts
        jb      pc_small
        mov     ecx, esi                ! align source, hope target is too
@@ -403,12 +401,11 @@ pc_small:
        rep
    eseg        movsb
 
+       mov     eax, 0                  ! 0 means: no fault
+_phys_copy_fault:                      ! kernel can send us here
        pop     es
        pop     edi
        pop     esi
-       mov     eax, 0                  ! 0 means: no fault
-_phys_copy_fault:                      ! kernel can send us here
-       mov     (_catch_pagefaults), 0
        ret
 
 !*===========================================================================*
@@ -439,7 +436,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
index 1c3f6d6c6b10fdc3191fc8691ea5baffd588ac77..9d5910e5a15a519a7c24edde76ad86316afdf3a6 100644 (file)
@@ -9,21 +9,21 @@
 #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 "../../proto.h"
+#include "../../proto.h"
 #include "../../debug.h"
 
 PRIVATE int psok = 0;
 
-extern u32_t createpde, linlincopies, physzero;
+int verifyrange = 0;
+
+extern u32_t newpde, overwritepde, linlincopies,
+       physzero, invlpgs, vmcheckranges, straightpdes;
 
 #define PROCPDEPTR(pr, pi) ((u32_t *) ((u8_t *) vm_pagedirs +\
                                I386_PAGE_SIZE * pr->p_nr +     \
@@ -37,12 +37,15 @@ u8_t *vm_pagedirs = NULL;
 u32_t i386_invlpg_addr = 0;
 
 #define WANT_FREEPDES 4
-PRIVATE int nfreepdes = 0, freepdes[WANT_FREEPDES];
+#define NOPDE -1
+#define PDEMASK(n) (1L << (n))
+PRIVATE int nfreepdes = 0, freepdes[WANT_FREEPDES], inusepde = NOPDE;
+PUBLIC u32_t dirtypde;
 
 #define HASPT(procptr) ((procptr)->p_seg.p_cr3 != 0)
 
 FORWARD _PROTOTYPE( u32_t phys_get32, (vir_bytes v)                    );
-FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value)                     );
+FORWARD _PROTOTYPE( void vm_set_cr3, (struct proc *pr)                 );
 FORWARD _PROTOTYPE( void set_cr3, (void)                               );
 FORWARD _PROTOTYPE( void vm_enable_paging, (void)                      );
 
@@ -50,34 +53,13 @@ FORWARD _PROTOTYPE( void vm_enable_paging, (void)                   );
 
 PUBLIC void vm_init(struct proc *newptproc)
 {
-       u32_t newcr3;
-
+       int i;
        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 now (not active until paging enabled). */
-       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). */
+       vm_set_cr3(newptproc);
        level0(vm_enable_paging);
-
-       kprintf("vm_init: enabled\n");
-
-       /* Don't do this init in the future. */
        vm_running = 1;
 
-       kprintf("vm_init done\n");
 }
 
 PRIVATE u32_t phys_get32(addr)
@@ -91,9 +73,8 @@ phys_bytes addr;
                return v;
        }
 
-       if((r=lin_lin_copy(NULL, addr, NULL, D,
-               proc_addr(SYSTEM), &v, &v, D, 
-               sizeof(v))) != OK) {
+       if((r=lin_lin_copy(NULL, addr, 
+               proc_addr(SYSTEM), vir2phys(&v), sizeof(v))) != OK) {
                minix_panic("lin_lin_copy for phys_get32 failed", r);
        }
 
@@ -102,11 +83,16 @@ phys_bytes addr;
 
 PRIVATE u32_t vm_cr3;  /* temp arg to level0() func */
 
-PRIVATE void vm_set_cr3(value)
-u32_t value;
+PRIVATE void vm_set_cr3(struct proc *newptproc)
 {
-       vm_cr3= value;
-       level0(set_cr3);
+       int u = 0;
+       if(!intr_disabled()) { lock; u = 1; }
+       vm_cr3= newptproc->p_seg.p_cr3;
+       if(vm_cr3) {
+               level0(set_cr3);
+               ptproc = newptproc;
+       }
+       if(u) { unlock; }
 }
 
 PRIVATE void set_cr3()
@@ -343,11 +329,13 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
        pde_v = phys_get32((u32_t) (root + pde));
 
        if(!(pde_v & I386_VM_PRESENT)) {
-#if 0
+#if 1
+         if(verifyrange) {
                kprintf("vm_lookup: %d:%s:0x%lx: cr3 0x%lx: pde %d not present\n",
                        proc->p_endpoint, proc->p_name, virtual, root, pde);
                kprintf("kernel stack: ");
                util_stacktrace();
+       }
 #endif
                NOREC_RETURN(vmlookup, EFAULT);
        }
@@ -365,6 +353,14 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
                vmassert(pte >= 0 && pte < I386_VM_PT_ENTRIES);
                pte_v = phys_get32((u32_t) (pt + pte));
                if(!(pte_v & I386_VM_PRESENT)) {
+#if 1
+         if(verifyrange) {
+               kprintf("vm_lookup: %d:%s:0x%lx: cr3 0x%lx: pte %d not present\n",
+                       proc->p_endpoint, proc->p_name, virtual, root, pte);
+               kprintf("kernel stack: ");
+               util_stacktrace();
+       }
+#endif
                        NOREC_RETURN(vmlookup, EFAULT);
                }
 
@@ -449,35 +445,90 @@ PUBLIC int vm_contiguous(struct proc *targetproc, u32_t vir_buf, size_t bytes)
                boundaries++;
        }
 
-       if(verbose_vm)
-               kprintf("vm_contiguous: yes (%d boundaries tested)\n",
-                       boundaries);
-
        return 1;
 }
 
 int vm_checkrange_verbose = 0;
 
+extern u32_t vmreqs;
+
 /*===========================================================================*
  *                              vm_suspend                                *
  *===========================================================================*/
-PUBLIC int vm_suspend(struct proc *caller, struct proc *target)
+PUBLIC int vm_suspend(struct proc *caller, struct proc *target,
+       vir_bytes linaddr, vir_bytes len, int wrflag, int type)
 {
        /* 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);                
+       vmassert(!RTS_ISSET(caller, VMREQUEST));
+       vmassert(!RTS_ISSET(caller, VMREQTARGET));
+       vmassert(!RTS_ISSET(target, VMREQUEST));
+       vmassert(!RTS_ISSET(target, VMREQTARGET));
+
+       RTS_LOCK_SET(caller, VMREQUEST);
+       RTS_LOCK_SET(target, VMREQTARGET);
+
+#if DEBUG_VMASSERT
+       caller->p_vmrequest.stacktrace[0] = '\0';
+       util_stacktrace_strcat(caller->p_vmrequest.stacktrace);
+#endif
+
+       vmreqs++;
                        
-       /* Set caller in target. */                     
-       target->p_vmrequest.requestor = caller;         
+       caller->p_vmrequest.writeflag = 1;
+       caller->p_vmrequest.start = linaddr;
+       caller->p_vmrequest.length = len;
+       caller->p_vmrequest.who = target->p_endpoint;
+       caller->p_vmrequest.type = type;
                                                        
        /* Connect caller on vmrequest wait queue. */   
-       caller->p_vmrequest.nextrequestor = vmrequest;
-       vmrequest = caller;     
-       if(!caller->p_vmrequest.nextrequestor)
+       if(!(caller->p_vmrequest.nextrequestor = vmrequest))
                lock_notify(SYSTEM, VM_PROC_NR);                
+       vmrequest = caller;
+}
+
+/*===========================================================================*
+ *                              delivermsg                                *
+ *===========================================================================*/
+int delivermsg(struct proc *rp)
+{
+       phys_bytes addr;  
+       int r;
+       NOREC_ENTER(deliver);
+
+       vmassert(rp->p_misc_flags & MF_DELIVERMSG);
+       vmassert(rp->p_delivermsg.m_source != NONE);
+
+       vmassert(rp->p_delivermsg_lin);
+       vmassert(rp->p_delivermsg_lin ==
+               umap_local(rp, D, rp->p_delivermsg_vir, sizeof(message)));
+
+       vm_set_cr3(rp);
+
+       vmassert(intr_disabled());
+       vmassert(!catch_pagefaults);
+       catch_pagefaults = 1;
+       addr = phys_copy(vir2phys(&rp->p_delivermsg),
+               rp->p_delivermsg_lin, sizeof(message));
+       vmassert(catch_pagefaults);
+       catch_pagefaults = 0;
+
+       if(addr) {
+               printf("phys_copy failed - addr 0x%lx\n", addr);
+               vm_suspend(rp, rp, rp->p_delivermsg_lin, sizeof(message), 1,
+                       VMSTYPE_DELIVERMSG);
+               r = VMSUSPEND;
+       } else {
+#if DEBUG_VMASSERT
+               rp->p_delivermsg.m_source = NONE;
+               rp->p_delivermsg_lin = 0;
+#endif
+               rp->p_misc_flags &= ~MF_DELIVERMSG;
+               r = OK;
+       }
+
+       NOREC_RETURN(deliver, r);
 }
 
 /*===========================================================================*
@@ -491,22 +542,23 @@ PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
 
        NOREC_ENTER(vmcheckrange);
 
+       vmcheckranges++;
+
        if(!HASPT(target))
                NOREC_RETURN(vmcheckrange, OK);
 
        /* If caller has had a reply to this request, return it. */
-       if(RTS_ISSET(caller, VMREQUEST)) {
+       if(!verifyrange && RTS_ISSET(caller, VMREQUEST)) {
                if(caller->p_vmrequest.who == target->p_endpoint) {
-                       if(caller->p_vmrequest.vmresult == VMSUSPEND)
-                               minix_panic("check sees VMSUSPEND?", NO_NUM);
+                       vmassert(caller->p_vmrequest.vmresult != VMSUSPEND);
                        RTS_LOCK_UNSET(caller, VMREQUEST);
-#if 0
+#if 1
                        kprintf("SYSTEM: vm_checkrange: returning vmresult %d\n",
                                caller->p_vmrequest.vmresult);
 #endif
                        NOREC_RETURN(vmcheckrange, caller->p_vmrequest.vmresult);
                } else {
-#if 0
+#if 1
                        kprintf("SYSTEM: vm_checkrange: caller has a request for %d, "
                                "but our target is %d\n",
                                caller->p_vmrequest.who, target->p_endpoint);
@@ -525,25 +577,29 @@ PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
 
        for(v = vir; v < vir + bytes;  v+= I386_PAGE_SIZE) {
                u32_t phys;
+               int r;
 
                /* If page exists and it's writable if desired, we're OK
                 * for this page.
                 */
-               if(vm_lookup(target, v, &phys, &flags) == OK &&
+               if((r=vm_lookup(target, v, &phys, &flags)) == OK &&
                        !(wrfl && !(flags & I386_VM_WRITE))) {
                        continue;
                }
 
+               if(verifyrange) {
+                       int wrok;
+                       wrok = !(wrfl && !(flags & I386_VM_WRITE));
+                       printf("checkrange failed; lookup: %d; write ok: %d\n",
+                               r, wrok);
+               }
+
                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;           
+                       vmassert(k_reenter == -1);
+                       vm_suspend(caller, target, vir, bytes, wrfl,
+                               VMSTYPE_KERNELCALL);
                }
 
-               /* SYSTEM loop will fill in VMSTYPE_SYS_MESSAGE. */
                NOREC_RETURN(vmcheckrange, VMSUSPEND);
        }
 
@@ -636,9 +692,17 @@ void invlpg_range(u32_t lin, u32_t bytes)
        o = lin % I386_PAGE_SIZE;
        lin -= o;
        limit = (limit + o) & I386_VM_ADDR_MASK;
+#if 0
        for(i386_invlpg_addr = lin; i386_invlpg_addr <= limit;
-           i386_invlpg_addr += I386_PAGE_SIZE)
+           i386_invlpg_addr += I386_PAGE_SIZE) {
+               invlpgs++;
                level0(i386_invlpg_level0);
+       }
+#else
+       vm_cr3= ptproc->p_seg.p_cr3;
+       vmassert(vm_cr3);
+       level0(set_cr3);
+#endif
 }
 
 u32_t thecr3;
@@ -662,79 +726,77 @@ u32_t read_cr3(void)
  * address space), SEG (hardware segment), VIRT (in-datasegment
  * address if known).
  */
-#define CREATEPDE(PROC, PTR, LINADDR, OFFSET, FREEPDE, VIRT, SEG, REMAIN, BYTES) { \
+#define CREATEPDE(PROC, PTR, LINADDR, REMAIN, BYTES) { \
+       int proc_pde_index;                                     \
        FIXME("CREATEPDE: check if invlpg is necessary");       \
-       if(PROC == ptproc) {                                    \
-               FIXME("CREATEPDE: use in-memory process");      \
-       }                                                       \
-       if((PROC) && iskernelp(PROC) && SEG == D) {             \
-               PTR = VIRT;                                     \
-               OFFSET = 0;                                     \
+       proc_pde_index = I386_VM_PDE(LINADDR);                  \
+       if((PROC) && (((PROC) == ptproc) || iskernelp(PROC))) { \
+               PTR = LINADDR;                                  \
+               straightpdes++;                                 \
        } else {                                                \
-               u32_t pdeval, *pdevalptr, newlin;               \
-               int pde_index;                                  \
+               int use_pde = NOPDE;                            \
+               int fp;                                         \
+               int mustinvl;                                   \
+               u32_t pdeval, *pdevalptr, mask;                 \
+               phys_bytes offset;                              \
                vmassert(psok);                                 \
-               pde_index = I386_VM_PDE(LINADDR);               \
-               vmassert(!iskernelp(PROC));                     \
-               createpde++;                                    \
                if(PROC) {                                      \
-                       u32_t *pdeptr; \
+                       u32_t *pdeptr;                          \
                        vmassert(!iskernelp(PROC));             \
                        vmassert(HASPT(PROC));                  \
-                       pdeptr = PROCPDEPTR(PROC, pde_index);           \
-                       pdeval = *pdeptr;       \
-               } else {                                                \
+                       pdeptr = PROCPDEPTR(PROC, proc_pde_index);      \
+                       pdeval = *pdeptr;                       \
+               } else {                                        \
+                       vmassert(!iskernelp(PROC));             \
                        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);                  \
+               for(fp = 0; fp < nfreepdes; fp++) {                     \
+                       int k = freepdes[fp];                           \
+                       if(inusepde == k)                               \
+                               continue;                               \
+                       use_pde = k;                                    \
+                       mask = PDEMASK(k);                              \
+                       vmassert(mask);                                 \
+                       if(dirtypde & mask)                             \
+                               continue;                               \
+                       break;                                          \
+               }                                                       \
+               vmassert(use_pde != NOPDE);                             \
+               vmassert(mask);                                         \
+               if(dirtypde & mask) {                                   \
+                       mustinvl = 1;                                   \
+                       overwritepde++;                                 \
+               } else {                                                \
+                       mustinvl = 0;                                   \
+                       dirtypde |= mask;                               \
+                       newpde++;                                       \
+               }                                                       \
+               inusepde = use_pde;                                     \
+               *PROCPDEPTR(ptproc, use_pde) = pdeval;                  \
+               offset = LINADDR & I386_VM_OFFSET_MASK_4MB;             \
+               PTR = I386_BIG_PAGE_SIZE*use_pde + offset;              \
+               REMAIN = MIN(REMAIN, I386_BIG_PAGE_SIZE - offset);      \
+               if(1 || mustinvl) {                                     \
+                       invlpg_range(PTR, REMAIN);                      \
+               }                                                       \
        }                                                               \
 }
 
 
-/*===========================================================================*
- *                             arch_switch_copymsg                          *
- *===========================================================================*/
-phys_bytes arch_switch_copymsg(struct proc *rp, message *m, phys_bytes lin)
-{
-       phys_bytes r;
-       int u = 0;
-       if(!intr_disabled()) { lock; u = 1; }
-       if(rp->p_seg.p_cr3 && ptproc != rp) {
-               vm_set_cr3(rp->p_seg.p_cr3);
-               ptproc = rp;
-       }
-       r = phys_copy(vir2phys(m), lin, sizeof(message));
-       if(u) { unlock; }
-}
-
 /*===========================================================================*
  *                             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,
-       int dstseg,
-       vir_bytes bytes)
+int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, 
+       struct proc *dstproc, vir_bytes dstlinaddr, vir_bytes bytes)
 {
        u32_t addr;
        int procslot;
-       u32_t catchrange_dst, catchrange_lo, catchrange_hi;
        NOREC_ENTER(linlincopy);
 
        linlincopies++;
 
-       if(srcproc && dstproc && iskernelp(srcproc) && iskernelp(dstproc)) {
-               memcpy(vdst, vsrc, bytes);
-               NOREC_RETURN(linlincopy, OK);
-       }
-
        FIXME("lin_lin_copy requires big pages");
        vmassert(vm_running);
        vmassert(!catch_pagefaults);
@@ -747,37 +809,30 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
        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;
+               phys_bytes srcptr, dstptr;
                vir_bytes chunk = bytes;
 
                /* 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);
+               inusepde = NOPDE;
+               CREATEPDE(srcproc, srcptr, srclinaddr, chunk, bytes);
+               CREATEPDE(dstproc, dstptr, dstlinaddr, chunk, bytes);
 
                /* Copy pages. */
                vmassert(intr_disabled());
                vmassert(!catch_pagefaults);
                catch_pagefaults = 1;
-               addr=_memcpy_k(dstptr + dstoffset, srcptr + srcoffset, chunk);
+               addr=phys_copy(srcptr, dstptr, chunk);
                vmassert(intr_disabled());
                vmassert(catch_pagefaults);
                catch_pagefaults = 0;
 
                if(addr) {
-                       if(addr >= catchrange_lo && addr < catchrange_dst) {
+                       if(addr >= srcptr && addr < (srcptr + chunk)) {
                                NOREC_RETURN(linlincopy, EFAULT_SRC);
                        }
-                       if(addr >= catchrange_dst && addr < catchrange_hi) {
+                       if(addr >= dstptr && addr < (dstptr + chunk)) {
                                NOREC_RETURN(linlincopy, EFAULT_DST);
                        }
                        minix_panic("lin_lin_copy fault out of range", NO_NUM);
@@ -785,15 +840,11 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
                        /* 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;
                srclinaddr += chunk;
                dstlinaddr += chunk;
-               vsrc += chunk;
-               vdst += chunk;
        }
 
        NOREC_RETURN(linlincopy, OK);
@@ -805,12 +856,12 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
 int vm_phys_memset(phys_bytes ph, u8_t c, phys_bytes bytes)
 {
        char *v;
+       u32_t p;
+       p = c | (c << 8) | (c << 16) | (c << 24);
 
        physzero++;
 
        if(!vm_running) {
-               u32_t p;
-               p = c | (c << 8) | (c << 16) | (c << 24);
                phys_memset(ph, p, bytes);
                return OK;
        }
@@ -822,14 +873,13 @@ int vm_phys_memset(phys_bytes ph, u8_t c, phys_bytes bytes)
         */
        while(bytes > 0) {
                vir_bytes chunk = bytes;
-               u8_t *ptr;
-               u32_t offset;
-               CREATEPDE(((struct proc *) NULL), ptr, ph,
-                       offset, freepdes[FREEPDE_MEMSET], 0, 0, chunk, bytes);
+               phys_bytes ptr;
+               inusepde = NOPDE;
+               CREATEPDE(((struct proc *) NULL), ptr, ph, 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);
+               phys_memset(ptr, p, chunk);
                bytes -= chunk;
                ph += chunk;
        }
@@ -930,30 +980,43 @@ int vmcheck;                      /* if nonzero, can return VMSUSPEND */
 
   if(vm_running) {
        int r;
-       struct proc *target, *caller;
+       struct proc *caller;
+
+       caller = proc_addr(who_p);
+
+       if(RTS_ISSET(caller, VMREQUEST)) {
+               struct proc *target;
+               int pn;
+               vmassert(caller->p_vmrequest.vmresult != VMSUSPEND);
+               RTS_LOCK_UNSET(caller, VMREQUEST);
+               if(caller->p_vmrequest.vmresult != OK) {
+                       printf("virtual_copy: returning VM error %d\n",
+                               caller->p_vmrequest.vmresult);
+                       NOREC_RETURN(virtualcopy, caller->p_vmrequest.vmresult);
+               }
+       }
 
        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,
-               dst_addr->segment, bytes)) != OK) {
+               procs[_DST_], phys_addr[_DST_], bytes)) != OK) {
+               struct proc *target;
+               int wr;
+               phys_bytes lin;
                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);
-
                vmassert(procs[_SRC_] && procs[_DST_]);
 
                if(r == EFAULT_SRC) {
-                       caller->p_vmrequest.start = phys_addr[_SRC_];
+                       lin = phys_addr[_SRC_];
                        target = procs[_SRC_];
-                       caller->p_vmrequest.writeflag = 0;
+                       wr = 0;
                } else if(r == EFAULT_DST) {
-                       caller->p_vmrequest.start = phys_addr[_DST_];
+                       lin = phys_addr[_DST_];
                        target = procs[_DST_];
-                       caller->p_vmrequest.writeflag = 1;
+                       wr = 1;
                } else {
                        minix_panic("r strange", r);
                }
@@ -964,10 +1027,9 @@ int vmcheck;                      /* if nonzero, can return VMSUSPEND */
                        target->p_endpoint, target->p_name);
 #endif
 
-               caller->p_vmrequest.length = bytes;
-               caller->p_vmrequest.who = target->p_endpoint;
-
-               vm_suspend(caller, target);
+               vmassert(k_reenter == -1);
+               vmassert(proc_ptr->p_endpoint == SYSTEM);
+               vm_suspend(caller, target, lin, bytes, wr, VMSTYPE_KERNELCALL);
 
                NOREC_RETURN(virtualcopy, VMSUSPEND);
        }
@@ -990,7 +1052,8 @@ int vmcheck;                       /* if nonzero, can return VMSUSPEND */
   }
 
   /* Now copy bytes between physical addresseses. */
-  phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes);
+  if(phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes))
+       NOREC_RETURN(virtualcopy, EFAULT);
  
   NOREC_RETURN(virtualcopy, OK);
 }
index 241df7330acf60cc18d0583cecc0af1e13652825..35447af2a6a5f869f025e4acabc88bfc61081946 100755 (executable)
@@ -73,10 +73,7 @@ begbss:
 
 .define        _restart
 .define        save
-.define        _pagefault_cr2
 .define _pagefault_count
-.define _old_eip_ptr
-.define _old_eax_ptr
 .define _cr3_test
 .define _cr3_reload
 .define        _write_cr3      ! write cr3
@@ -104,6 +101,8 @@ begbss:
 .define        _params_size
 .define _params_offset
 .define _mon_ds
+.define _schedcheck
+.define _dirtypde
 
 .define        _hwint00        ! handlers for hardware interrupts
 .define        _hwint01
@@ -395,7 +394,7 @@ _p_s_call:
 
        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
+       mov     AXREG(esi), eax
 
 ! Fall into code to restart proc/task running.
 
@@ -406,25 +405,22 @@ _restart:
 
 ! Restart the current process or the next process if it is set. 
 
-       cmp     (_next_ptr), 0          ! see if another process is scheduled
-       jz      0f
-       mov     eax, (_next_ptr)
-       mov     (_proc_ptr), eax        ! schedule new process 
-       mov     (_next_ptr), 0
-0:     mov     esp, (_proc_ptr)        ! will assume P_STACKBASE == 0
+       call    _schedcheck             ! ask C function who we're running
+       mov     esp, (_proc_ptr)        ! will assume P_STACKBASE == 0
        lldt    P_LDT_SEL(esp)          ! enable process' segment descriptors 
        inc     (_cr3_test)
        cmp     P_CR3(esp), 0           ! process does not have its own PT
-       jz      noload  
+       jz      0f      
        mov     eax, P_CR3(esp)
        cmp     eax, (loadedcr3)
-       jz      noload
+       jz      0f
        inc     (_cr3_reload)
        mov     cr3, eax
        mov     (loadedcr3), eax
        mov     eax, (_proc_ptr)
        mov     (_ptproc), eax
-noload:
+!      mov     (_dirtypde), 0
+0:
        lea     eax, P_STACKTOP(esp)    ! arrange for next interrupt
        mov     (_tss+TSS3_S_SP0), eax  ! to save state in process table
 restart1:
@@ -500,7 +496,7 @@ _page_fault:
        push    PAGE_FAULT_VECTOR
        push    eax
        mov     eax, cr2
-sseg   mov     (_pagefault_cr2), eax
+sseg   mov     (pagefaultcr2), eax
 sseg   inc     (_pagefault_count)
        pop     eax
        jmp     errexception
@@ -530,8 +526,8 @@ errexception:
  sseg  pop     (ex_number)
  sseg  pop     (trap_errno)
 exception1:                            ! Common for all exceptions.
- sseg  mov     (_old_eax_ptr), esp     ! where will eax be saved?
- sseg  sub     (_old_eax_ptr), PCREG-AXREG     ! here
+ sseg  mov     (old_eax_ptr), esp      ! where will eax be saved?
+ sseg  sub     (old_eax_ptr), PCREG-AXREG      ! here
 
        push    eax                     ! eax is scratch register
 
@@ -539,7 +535,7 @@ exception1:                         ! Common for all exceptions.
  sseg  mov     (old_eip), eax
        mov     eax, esp
        add     eax, 4
- sseg  mov     (_old_eip_ptr), eax
+ sseg  mov     (old_eip_ptr), eax
        movzx   eax, 4+4(esp)           ! old cs
  sseg  mov     (old_cs), eax
        mov     eax, 8+4(esp)           ! old eflags
@@ -547,6 +543,9 @@ exception1:                         ! Common for all exceptions.
 
        pop     eax
        call    save
+       push    (pagefaultcr2)
+       push    (old_eax_ptr)
+       push    (old_eip_ptr)
        push    (old_eflags)
        push    (old_cs)
        push    (old_eip)
@@ -554,7 +553,7 @@ exception1:                         ! Common for all exceptions.
        push    (ex_number)
        call    _exception              ! (ex_number, trap_errno, old_eip,
                                        !       old_cs, old_eflags)
-       add     esp, 5*4
+       add     esp, 8*4
        ret
 
 
@@ -566,8 +565,14 @@ _write_cr3:
        push    ebp
        mov     ebp, esp
        mov     eax, 8(ebp)
+       inc     (_cr3_test)
+!      cmp     eax, (loadedcr3)
+!      jz      0f
+       inc     (_cr3_reload)
        mov     cr3, eax
        mov     (loadedcr3), eax
+!      mov     (_dirtypde), 0
+0:
        pop     ebp
        ret
 
@@ -591,8 +596,11 @@ k_stack:
 k_stktop:                      ! top of kernel stack
        .comm   ex_number, 4
        .comm   trap_errno, 4
+       .comm   old_eip_ptr, 4
+       .comm   old_eax_ptr, 4
        .comm   old_eip, 4
        .comm   old_cs, 4
        .comm   old_eflags, 4
+       .comm   pagefaultcr2, 4
        .comm   loadedcr3, 4
 
index 3c9a0f36a4716f9c60ec44dfb24a1bcaabf61cdd..cbfb2625476790e0e643a7172e023d740e31ac4e 100644 (file)
@@ -52,11 +52,13 @@ _PROTOTYPE( void vir_outsw, (u16_t port, struct proc *proc, u32_t vir, size_t co
 _PROTOTYPE( void i386_updatepde, (int pde, u32_t val));
 _PROTOTYPE( void i386_freepde, (int pde));
 _PROTOTYPE( void getcr3val, (void));
+_PROTOTYPE( void switchedcr3, (void));
 
 
 /* exception.c */
 _PROTOTYPE( void exception, (unsigned vec_nr, u32_t trap_errno,
-       u32_t old_eip, U16_t old_cs, u32_t old_eflags)                  );
+       u32_t old_eip, U16_t old_cs, u32_t old_eflags,
+       u32_t *old_eip_ptr, u32_t *old_eax_ptr, u32_t pagefaultcr2)     );
 
 /* klib386.s */
 _PROTOTYPE( void level0, (void (*func)(void))                           );
index a04cdd6fbebf61a72e2aaf14db508c579d1c95cb..1a6bc80305ace52aa4d2e284bbd468d4caab03ef 100644 (file)
 
 #include "proto.h"
 #include "../../proc.h"
+#include "../../debug.h"
 
 #define CR0_EM 0x0004          /* set to enable trap on any FP instruction */
 
 FORWARD _PROTOTYPE( void ser_debug, (int c));
-FORWARD _PROTOTYPE( void ser_dump_stats, (void));
 
 PUBLIC void arch_shutdown(int how)
 {
@@ -139,39 +139,65 @@ PUBLIC void do_ser_debug()
 
 PRIVATE void ser_debug(int c)
 {
+       int u = 0;
+
        do_serial_debug++;
-       kprintf("ser_debug: %d\n", c);
+       /* Disable interrupts so that we get a consistent state. */
+       if(!intr_disabled()) { lock; u = 1; };
+
        switch(c)
        {
        case '1':
                ser_dump_proc();
                break;
        case '2':
-               ser_dump_stats();
+               ser_dump_queues();
                break;
+#define TOGGLECASE(ch, flag)                           \
+       case ch: {                                      \
+               if(verboseflags & flag) {               \
+                       verboseflags &= ~flag;          \
+                       printf("%s disabled\n", #flag); \
+               } else {                                \
+                       verboseflags |= flag;           \
+                       printf("%s enabled\n", #flag);  \
+               }                                       \
+               break;                                  \
+               }
+       TOGGLECASE('8', VF_SCHEDULING)
+       TOGGLECASE('9', VF_PICKPROC)
        }
        do_serial_debug--;
+       if(u) { unlock; }
 }
 
-PRIVATE void printslot(struct proc *pp)
+PRIVATE void printslot(struct proc *pp, int level)
 {
-       static int level = 0;
        struct proc *depproc = NULL;
        int dep = NONE;
+#define COL { int i; for(i = 0; i < level; i++) printf("> "); }
 
        if(level >= NR_PROCS) {
                kprintf("loop??\n");
                return;
        }
 
-       level++;
+       if(pp->p_ready && pp->p_rts_flags) {
+               printf("HUH? p_ready but rts flags!\n");
+       }
+
+       if(!pp->p_ready && !pp->p_rts_flags) {
+               printf("HUH? not p_ready but no rts flags!\n");
+       }
+
+       COL
 
-       kprintf("%*s %d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s misc %s ",
-               level, "",
+       kprintf("%d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s misc %s ready %d",
                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), miscflagstr(pp->p_misc_flags));
+               rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
+               pp->p_ready);
 
        if(pp->p_rts_flags & SENDING) {
                dep = pp->p_sendto_e;
@@ -201,65 +227,46 @@ PRIVATE void printslot(struct proc *pp)
        } else {
                kprintf("\n");
        }
-       kprintf("%*s ", level, "");
+
+       COL
        proc_stacktrace(pp);
+
+       if(pp->p_rts_flags & VMREQUEST) {
+               COL
+               printf("vmrequest set with: %s\n", pp->p_vmrequest.stacktrace);
+       }
+
        if(depproc)
-               printslot(depproc);
-       level--;
+               printslot(depproc, level+1);
+}
+
+PUBLIC void ser_dump_queues()
+{
+       int q;
+       for(q = 0; q < NR_SCHED_QUEUES; q++) {
+               struct proc *p;
+               if(rdy_head[q]) 
+                       printf("%2d: ", q);
+               for(p = rdy_head[q]; p; p = p->p_nextready) {
+                       printf("%s / %d  ", p->p_name, p->p_endpoint);
+               }
+               printf("\n");
+       }
+
 }
 
 PUBLIC void ser_dump_proc()
 {
        struct proc *pp;
-       int u = 0;
 
-       /* Disable interrupts so that we get a consistent state. */
-       if(!intr_disabled()) { lock; u = 1; };
+       CHECK_RUNQUEUES;
 
        for (pp= BEG_PROC_ADDR; pp < END_PROC_ADDR; pp++)
        {
                if (pp->p_rts_flags & SLOT_FREE)
                        continue;
-               printslot(pp);
-       }
-
-       if(u) { unlock; }
-}
-
-PRIVATE void ser_dump_stats()
-{
-       kprintf("ipc_stats:\n");
-       kprintf("deadproc: %d\n", ipc_stats.deadproc);
-       kprintf("bad_endpoint: %d\n", ipc_stats.bad_endpoint);
-       kprintf("dst_not_allowed: %d\n", ipc_stats.dst_not_allowed);
-       kprintf("bad_call: %d\n", ipc_stats.bad_call);
-       kprintf("call_not_allowed: %d\n", ipc_stats.call_not_allowed);
-       kprintf("bad_buffer: %d\n", ipc_stats.bad_buffer);
-       kprintf("deadlock: %d\n", ipc_stats.deadlock);
-       kprintf("not_ready: %d\n", ipc_stats.not_ready);
-       kprintf("src_died: %d\n", ipc_stats.src_died);
-       kprintf("dst_died: %d\n", ipc_stats.dst_died);
-       kprintf("no_priv: %d\n", ipc_stats.no_priv);
-       kprintf("bad_size: %d\n", ipc_stats.bad_size);
-       kprintf("bad_senda: %d\n", ipc_stats.bad_senda);
-       if (ex64hi(ipc_stats.total))
-       {
-               kprintf("total: %x:%08x\n", ex64hi(ipc_stats.total),
-                       ex64lo(ipc_stats.total));
+               printslot(pp, 0);
        }
-       else
-               kprintf("total: %u\n", ex64lo(ipc_stats.total));
-
-       kprintf("sys_stats:\n");
-       kprintf("bad_req: %d\n", sys_stats.bad_req);
-       kprintf("not_allowed: %d\n", sys_stats.not_allowed);
-       if (ex64hi(sys_stats.total))
-       {
-               kprintf("total: %x:%08x\n", ex64hi(sys_stats.total),
-                       ex64lo(sys_stats.total));
-       }
-       else
-               kprintf("total: %u\n", ex64lo(sys_stats.total));
 }
 
 #if SPROFILE
diff --git a/kernel/arch/i386/vm.h b/kernel/arch/i386/vm.h
deleted file mode 100644 (file)
index 21e551d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-.define _last_cr3
-
-#define LOADCR3WITHEAX(type, newcr3, ptproc)   ;\
-sseg   inc     (_cr3switch)            ;\
-sseg   mov     eax,    newcr3          ;\
-sseg   cmp     (_last_cr3), eax        ;\
-       jz      8f                      ;\
-       mov     cr3, eax                ;\
-sseg   inc     (_cr3reload)            ;\
-sseg   mov     (_last_cr3), eax        ;\
-sseg   mov     eax, (ptproc)           ;\
-sseg   mov     (_ptproc), eax          ;\
-8:
-
index 9e4c78d46e4b29069c2f269837425cbf99906baa..7324d4857aaa95438677a7e1b970fb0baaf53ced 100644 (file)
@@ -96,7 +96,9 @@ check_runqueues_f(char *file, int line)
   for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
        if(xp->p_magic != PMAGIC) 
                MYPANIC("p_magic wrong in proc table");
-       if (! isemptyp(xp) && xp->p_ready && ! xp->p_found) {
+       if (isemptyp(xp))
+               continue;
+       if(xp->p_ready && ! xp->p_found) {
                kprintf("sched error: ready proc %d not on queue\n", xp->p_nr);
                MYPANIC("ready proc not on scheduling queue");
                if (l++ > MAX_LOOP) { MYPANIC("loop in debug.c?"); }
@@ -126,6 +128,7 @@ rtsflagstr(int flags)
        FLAG(VMINHIBIT);
        FLAG(PAGEFAULT);
        FLAG(VMREQUEST);
+       FLAG(VMREQTARGET);
 
        return str;
 }
index 67adacb2609a56527dbada4781fe5968f64f5ec9..8ad26332fd33531cdc9e8c6b6582191197eabc38 100644 (file)
 #define DEBUG_TIME_LOCKS               1
 
 /* Runtime sanity checking. */
-#define DEBUG_VMASSERT                 0
-#define DEBUG_SCHED_CHECK              0
+#define DEBUG_VMASSERT                 1
+#define DEBUG_SCHED_CHECK              1
+#define DEBUG_STACK_CHECK              1
+#define DEBUG_TRACE                    1
+
+#if DEBUG_TRACE
+
+#define VF_SCHEDULING          (1L << 1)
+#define VF_PICKPROC            (1L << 2)
+
+#define TRACE(code, statement) if(verboseflags & code) { printf("%s:%d: ", __FILE__, __LINE__); statement }
+
+#else
+#define TRACE(code, statement)
+#endif
 
 #define NOREC_ENTER(varname) \
        static int varname = 0; \
@@ -50,7 +63,6 @@
 
 #if DEBUG_VMASSERT
 #define vmassert(t) { \
-       FIXME("vmassert on"); \
        if(!(t)) { minix_panic("vm: assert " #t " failed\n", __LINE__); } }
 #else
 #define vmassert(t) { }
index db67062195971b6e5d73859b6cf38ab940501ef6..7790c7d32df970c9dbaa95ea6a545814149428d2 100755 (executable)
@@ -16,6 +16,7 @@
 #include <minix/config.h>
 #include <archtypes.h>
 #include "config.h"
+#include "debug.h"
 
 /* Variables relating to shutting down MINIX. */
 EXTERN char kernel_exception;          /* TRUE after system exceptions */
@@ -29,9 +30,9 @@ EXTERN struct k_randomness krandom;   /* gather kernel random information */
 EXTERN struct loadinfo kloadinfo;      /* status of load average */
 
 /* Process scheduling information and the kernel reentry count. */
-EXTERN struct proc *prev_ptr;  /* previously running process */
 EXTERN struct proc *proc_ptr;  /* pointer to currently running process */
 EXTERN struct proc *next_ptr;  /* next process to run after restart() */
+EXTERN struct proc *prev_ptr;  
 EXTERN struct proc *bill_ptr;  /* process to bill for clock ticks */
 EXTERN struct proc *vmrestart;  /* first process on vmrestart queue */
 EXTERN struct proc *vmrequest;  /* first process on vmrequest queue */
@@ -46,32 +47,6 @@ EXTERN int irq_actids[NR_IRQ_VECTORS];               /* IRQ ID bits active */
 EXTERN int irq_use;                            /* map of all in-use irq's */
 EXTERN u32_t system_hz;                                /* HZ value */
 
-EXTERN struct ipc_stats
-{
-       unsigned long deadproc;
-       unsigned long bad_endpoint;
-       unsigned long dst_not_allowed;
-       unsigned long bad_call;
-       unsigned long call_not_allowed;
-       unsigned long bad_buffer;
-       unsigned long deadlock;
-       unsigned long not_ready;
-       unsigned long src_died;
-       unsigned long dst_died;
-       unsigned long no_priv;
-       unsigned long bad_size;
-       unsigned long bad_senda;
-       u64_t total;
-} ipc_stats;
-extern endpoint_t ipc_stats_target;
-
-EXTERN struct system_stats
-{
-       unsigned long bad_req;
-       unsigned long not_allowed;
-       u64_t total;
-} sys_stats;
-
 /* Miscellaneous. */
 EXTERN reg_t mon_ss, mon_sp;           /* boot monitor stack */
 EXTERN int mon_return;                 /* true if we can return to monitor */
@@ -84,17 +59,14 @@ EXTERN char params_buffer[512];             /* boot monitor parameters */
 EXTERN int minix_panicing;
 EXTERN int locklevel;
 
-EXTERN unsigned long cr3switch;
-EXTERN unsigned long cr3reload;
+#if DEBUG_TRACE
+EXTERN int verboseflags;
+#endif
 
 /* VM */
 EXTERN int vm_running;
-EXTERN int must_notify_vm;
 EXTERN struct proc *ptproc;
 
-/* Verbose flags (debugging). */
-EXTERN int verbose_vm;
-
 /* Timing */
 EXTERN util_timingdata_t timingdata[TIMING_CATEGORIES];
 
index 8ff9e1f70723c6a1e078da68bd77e2a258496adc..e8ca56f321168517057a457a15046db0214d5d89 100755 (executable)
@@ -159,6 +159,9 @@ PUBLIC void main()
                rp->p_reg.sp -= sizeof(reg_t);
        }
 
+       /* scheduling functions depend on proc_ptr pointing somewhere. */
+       if(!proc_ptr) proc_ptr = rp;
+
        /* If this process has its own page table, VM will set the
         * PT up and manage it. VM will signal the kernel when it has
         * done this; until then, don't let it run.
@@ -184,7 +187,7 @@ PUBLIC void main()
   /* MINIX is now ready. All boot image processes are on the ready queue.
    * Return to the assembly code to start running the current process. 
    */
-  bill_ptr = proc_addr(IDLE);          /* it has to point somewhere */
+  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
index 8009b5be649facced88806b4e6d4cc9112ce9389..b17ea091ea8f3225852e026fb0a817f2dd002b8a 100755 (executable)
@@ -67,6 +67,9 @@ FORWARD _PROTOTYPE( int try_one, (struct proc *src_ptr, struct proc *dst_ptr));
 FORWARD _PROTOTYPE( void sched, (struct proc *rp, int *queue, int *front));
 FORWARD _PROTOTYPE( void pick_proc, (void));
 
+#define PICK_ANY       1
+#define PICK_HIGHERONLY        2
+
 #define BuildNotifyMessage(m_ptr, src, dst_ptr) \
        (m_ptr)->m_type = NOTIFY_FROM(src);                             \
        (m_ptr)->NOTIFY_TIMESTAMP = get_uptime();                       \
@@ -81,40 +84,76 @@ FORWARD _PROTOTYPE( void pick_proc, (void));
                break;                                                  \
        }
 
-#define Deliver(rp)    do {    \
-               vmassert(rp->p_misc_flags & MF_DELIVERMSG);     \
-               vmassert(rp->p_delivermsg_lin); \
-               if(arch_switch_copymsg(rp, &rp->p_delivermsg,   \
-                       rp->p_delivermsg_lin)) {        \
-                       minix_panic("MF_DELIVERMSG copy failed", NO_NUM); \
-               }       \
-               rp->p_delivermsg.m_source = NONE;       \
-               rp->p_delivermsg_lin = 0;       \
-               rp->p_misc_flags &= ~MF_DELIVERMSG;     \
-       } while(0)
-
 /*===========================================================================*
  *                             QueueMess                                    * 
  *===========================================================================*/
 PRIVATE int QueueMess(endpoint_t ep, vir_bytes msg_lin, struct proc *dst)
 {
+       int k;
+       NOREC_ENTER(queuemess);
        /* Queue a message from the src process (in memory) to the dst
-        * process (using dst process table entry). Do actual copy here;
-        * it's an error if the copy fails.
+        * process (using dst process table entry). Do actual copy to
+        * kernel here; it's an error if the copy fails into kernel.
         */
        vmassert(!(dst->p_misc_flags & MF_DELIVERMSG)); 
        vmassert(dst->p_delivermsg_lin);
+       vmassert(isokendpt(ep, &k));
+
        if(phys_copy(msg_lin, vir2phys(&dst->p_delivermsg),
                sizeof(message))) {
-               return EFAULT;
+               NOREC_RETURN(queuemess, EFAULT);
        }
+
        dst->p_delivermsg.m_source = ep;
        dst->p_misc_flags |= MF_DELIVERMSG;
+
+#if 0
        if(iskernelp(dst) || ptproc == dst) {
-               Deliver(dst);
+               printf("instant delivery to %d\n", dst->p_endpoint);
+               delivermsg(dst);
+       } else {
+               printf("queued delivery to %d\n", dst->p_endpoint);
        }
+#endif
 
-       return OK;
+       NOREC_RETURN(queuemess, OK);
+}
+
+/*===========================================================================*
+ *                             schedcheck                                   * 
+ *===========================================================================*/
+PUBLIC void schedcheck(void)
+{
+       /* This function is called an instant before proc_ptr is
+        * to be scheduled again.
+        */
+       NOREC_ENTER(schedch);
+       vmassert(intr_disabled());
+       if(next_ptr) {
+               proc_ptr = next_ptr;
+               next_ptr = NULL;
+       }
+       vmassert(proc_ptr);
+       vmassert(!proc_ptr->p_rts_flags);
+       while(proc_ptr->p_misc_flags & MF_DELIVERMSG) {
+               vmassert(!next_ptr);
+               vmassert(!proc_ptr->p_rts_flags);
+               TRACE(VF_SCHEDULING, printf("delivering to %s / %d\n",
+                       proc_ptr->p_name, proc_ptr->p_endpoint););
+               if(delivermsg(proc_ptr) == VMSUSPEND) {
+                       vmassert(next_ptr);
+                       TRACE(VF_SCHEDULING, printf("suspending %s / %d\n",
+                               proc_ptr->p_name, proc_ptr->p_endpoint););
+                       vmassert(proc_ptr->p_rts_flags);
+                       vmassert(next_ptr != proc_ptr);
+                       proc_ptr = next_ptr;
+                       vmassert(!proc_ptr->p_rts_flags);
+                       next_ptr = NULL;
+               } 
+       }
+       TRACE(VF_SCHEDULING, printf("starting %s / %d\n",
+               proc_ptr->p_name, proc_ptr->p_endpoint););
+       NOREC_RETURN(schedch, );
 }
 
 /*===========================================================================*
@@ -146,9 +185,6 @@ long bit_map;                       /* notification event set or flags */
   }
 #endif
 
-  if (caller_ptr->p_endpoint == ipc_stats_target)
-       ipc_stats.total= add64u(ipc_stats.total, 1);
-
 #if 0
   if(src_dst_e != 4 && src_dst_e != 5 &&
        caller_ptr->p_endpoint != 4 && caller_ptr->p_endpoint != 5) {
@@ -167,8 +203,6 @@ long bit_map;                       /* notification event set or flags */
   if (RTS_ISSET(caller_ptr, SLOT_FREE))
   {
        kprintf("called by the dead?!?\n");
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               ipc_stats.deadproc++;
        return EINVAL;
   }
 #endif
@@ -193,8 +227,6 @@ long bit_map;                       /* notification event set or flags */
                kprintf("sys_call: trap %d by %d with bad endpoint %d\n", 
                        call_nr, proc_nr(caller_ptr), src_dst_e);
 #endif
-               if (caller_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.bad_endpoint++;
                return EINVAL;
        }
        src_dst_p = src_dst_e;
@@ -214,8 +246,6 @@ long bit_map;                       /* notification event set or flags */
                kprintf("sys_call: trap %d by %d with bad endpoint %d\n", 
                        call_nr, proc_nr(caller_ptr), src_dst_e);
 #endif
-               if (caller_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.bad_endpoint++;
                return EDEADSRCDST;
        }
 
@@ -233,8 +263,6 @@ long bit_map;                       /* notification event set or flags */
                                call_nr, proc_nr(caller_ptr),
                                caller_ptr->p_name, src_dst_p);
 #endif
-                       if (caller_ptr->p_endpoint == ipc_stats_target)
-                               ipc_stats.dst_not_allowed++;
                        return(ECALLDENIED);    /* call denied by ipc mask */
                }
        }
@@ -247,8 +275,6 @@ long bit_map;                       /* notification event set or flags */
                        "sys_call: ipc mask denied trap %d from %d to %d\n",
                                call_nr, caller_ptr->p_endpoint, src_dst_e);
 #endif
-                       if (caller_ptr->p_endpoint == ipc_stats_target)
-                               ipc_stats.dst_not_allowed++;
                        return(ECALLDENIED);    /* call denied by ipc mask */
                }
        }
@@ -261,8 +287,6 @@ long bit_map;                       /* notification event set or flags */
       kprintf("sys_call: trap %d not allowed, caller %d, src_dst %d\n", 
           call_nr, proc_nr(caller_ptr), src_dst_p);
 #endif
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               ipc_stats.bad_call++;
        return(ETRAPDENIED);            /* trap denied by mask or kernel */
   }
 
@@ -275,8 +299,6 @@ long bit_map;                       /* notification event set or flags */
       kprintf("sys_call: trap %d not allowed, caller %d, src_dst %d\n", 
           call_nr, proc_nr(caller_ptr), src_dst_p);
 #endif
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               ipc_stats.call_not_allowed++;
        return(ETRAPDENIED);            /* trap denied by mask or kernel */
   }
 
@@ -285,8 +307,6 @@ long bit_map;                       /* notification event set or flags */
       kprintf("sys_call: trap %d not allowed, caller %d, src_dst %d\n", 
           call_nr, proc_nr(caller_ptr), src_dst_e);
 #endif
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               ipc_stats.call_not_allowed++;
        return(ETRAPDENIED);            /* trap denied by mask or kernel */
   }
 
@@ -314,8 +334,6 @@ long bit_map;                       /* notification event set or flags */
           kprintf("sys_call: trap %d from %d to %d deadlocked, group size %d\n",
               call_nr, proc_nr(caller_ptr), src_dst_p, group_size);
 #endif
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               ipc_stats.deadlock++;
         return(ELOCKED);
       }
   }
@@ -457,8 +475,6 @@ int flags;
 
   if (RTS_ISSET(dst_ptr, NO_ENDPOINT))
   {
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               ipc_stats.dst_died++;
        return EDSTDIED;
   }
 
@@ -473,8 +489,6 @@ int flags;
        RTS_UNSET(dst_ptr, RECEIVING);
   } else {
        if(flags & NON_BLOCKING) {
-               if (caller_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.not_ready++;
                return(ENOTREADY);
        }
 
@@ -525,6 +539,7 @@ int flags;
 
   /* This is where we want our message. */
   caller_ptr->p_delivermsg_lin = linaddr;
+  caller_ptr->p_delivermsg_vir = m_ptr;
 
   if(src_e == ANY) src_p = ANY;
   else
@@ -532,8 +547,6 @@ int flags;
        okendpt(src_e, &src_p);
        if (RTS_ISSET(proc_addr(src_p), NO_ENDPOINT))
        {
-               if (caller_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.src_died++;
                return ESRCDIED;
        }
   }
@@ -550,6 +563,7 @@ int flags;
 
         map = &priv(caller_ptr)->s_notify_pending;
         for (chunk=&map->chunk[0]; chunk<&map->chunk[NR_SYS_CHUNKS]; chunk++) {
+               endpoint_t hisep;
 
             /* Find a pending notification from the requested source. */ 
             if (! *chunk) continue;                    /* no bits in chunk */
@@ -567,8 +581,10 @@ int flags;
 
             /* Found a suitable source, deliver the notification message. */
            BuildNotifyMessage(&m, src_proc_nr, caller_ptr);    /* assemble message */
+           hisep = proc_addr(src_proc_nr)->p_endpoint;
            vmassert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG));      
-           if((r=QueueMess(src_proc_nr, vir2phys(&m), caller_ptr)) != OK)  {
+           vmassert(src_e == ANY || hisep == src_e);
+           if((r=QueueMess(hisep, vir2phys(&m), caller_ptr)) != OK)  {
                minix_panic("mini_receive: local QueueMess failed", NO_NUM);
            }
             return(OK);                                        /* report success */
@@ -585,8 +601,6 @@ int flags;
                kprintf("%d: receive from %d; found dead %d (%s)?\n",
                        caller_ptr->p_endpoint, src_e, (*xpp)->p_endpoint,
                        (*xpp)->p_name);
-               if (caller_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.deadproc++;
                return EINVAL;
            }
 #endif
@@ -629,8 +643,6 @@ int flags;
       RTS_SET(caller_ptr, RECEIVING);
       return(OK);
   } else {
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               ipc_stats.not_ready++;
        return(ENOTREADY);
   }
 }
@@ -724,8 +736,6 @@ size_t size;
        {
                kprintf(
                "mini_senda: warning caller has no privilege structure\n");
-               if (caller_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.no_priv++;
                return EPERM;
        }
 
@@ -747,8 +757,6 @@ size_t size;
         */
        if (size > 16*(NR_TASKS + NR_PROCS))
        {
-               if (caller_ptr->p_endpoint == ipc_stats_target)
-                       ipc_stats.bad_size++;
                return EDOM;
        }
        
@@ -770,8 +778,6 @@ size_t size;
                if (flags & ~(AMF_VALID|AMF_DONE|AMF_NOTIFY) ||
                        !(flags & AMF_VALID))
                {
-                       if (caller_ptr->p_endpoint == ipc_stats_target)
-                               ipc_stats.bad_senda++;
                        return EINVAL;
                }
 
@@ -935,8 +941,6 @@ struct proc *dst_ptr;
                {
                        kprintf("try_one: bad bits in table\n");
                        privp->s_asynsize= 0;
-                       if (src_ptr->p_endpoint == ipc_stats_target)
-                               ipc_stats.bad_senda++;
                        return EINVAL;
                }
 
@@ -1030,15 +1034,19 @@ register struct proc *rp;       /* this process is now runnable */
   int q;                                       /* scheduling queue to use */
   int front;                                   /* add to front or back */
 
+  NOREC_ENTER(enqueuefunc);
+
 #if DEBUG_SCHED_CHECK
   if(!intr_disabled()) { minix_panic("enqueue with interrupts enabled", NO_NUM); }
-  CHECK_RUNQUEUES;
   if (rp->p_ready) minix_panic("enqueue already ready process", NO_NUM);
 #endif
 
   /* Determine where to insert to process. */
   sched(rp, &q, &front);
 
+  vmassert(q >= 0);
+  vmassert(q < IDLE_Q || rp->p_endpoint == IDLE);
+
   /* Now add the process to the queue. */
   if (rdy_head[q] == NIL_PROC) {               /* add to empty queue */
       rdy_head[q] = rdy_tail[q] = rp;          /* create a new queue */
@@ -1054,19 +1062,30 @@ register struct proc *rp;       /* this process is now runnable */
       rp->p_nextready = NIL_PROC;              /* mark new end */
   }
 
+#if DEBUG_SCHED_CHECK
+  rp->p_ready = 1;
+  CHECK_RUNQUEUES;
+#endif
+
   /* Now select the next process to run, if there isn't a current
    * process yet or current process isn't ready any more, or
    * it's PREEMPTIBLE.
    */
-  if(!proc_ptr || proc_ptr->p_rts_flags ||
-    (priv(proc_ptr)->s_flags & PREEMPTIBLE)) {
+     FIXME("PREEMPTIBLE test?");
+       vmassert(proc_ptr);
+#if 0
+  if(!proc_ptr || proc_ptr->p_rts_flags) 
+#else
+  if((proc_ptr->p_priority > rp->p_priority) &&
+   (priv(proc_ptr)->s_flags & PREEMPTIBLE)) 
+#endif
      pick_proc();
-  }
 
 #if DEBUG_SCHED_CHECK
-  rp->p_ready = 1;
   CHECK_RUNQUEUES;
 #endif
+
+  NOREC_RETURN(enqueuefunc, );
 }
 
 /*===========================================================================*
@@ -1083,14 +1102,17 @@ register struct proc *rp;       /* this process is no longer runnable */
   register struct proc **xpp;                  /* iterate over queue */
   register struct proc *prev_xp;
 
+  NOREC_ENTER(dequeuefunc);
+
+#if DEBUG_STACK_CHECK
   /* Side-effect for kernel: check if the task's stack still is ok? */
   if (iskernelp(rp)) {                                 
        if (*priv(rp)->s_stack_guard != STACK_GUARD)
                minix_panic("stack overrun by task", proc_nr(rp));
   }
+#endif
 
 #if DEBUG_SCHED_CHECK
-  CHECK_RUNQUEUES;
   if(!intr_disabled()) { minix_panic("dequeue with interrupts enabled", NO_NUM); }
   if (! rp->p_ready) minix_panic("dequeue() already unready process", NO_NUM);
 #endif
@@ -1106,17 +1128,23 @@ register struct proc *rp;       /* this process is no longer runnable */
           *xpp = (*xpp)->p_nextready;          /* replace with next chain */
           if (rp == rdy_tail[q])               /* queue tail removed */
               rdy_tail[q] = prev_xp;           /* set new tail */
+
+#if DEBUG_SCHED_CHECK
+               rp->p_ready = 0;
+                 CHECK_RUNQUEUES;
+#endif
           if (rp == proc_ptr || rp == next_ptr)        /* active process removed */
-              pick_proc();                     /* pick new process to run */
+              pick_proc();             /* pick new process to run */
           break;
       }
       prev_xp = *xpp;                          /* save previous in chain */
   }
 
 #if DEBUG_SCHED_CHECK
-  rp->p_ready = 0;
   CHECK_RUNQUEUES;
 #endif
+
+  NOREC_RETURN(dequeuefunc, );
 }
 
 /*===========================================================================*
@@ -1162,32 +1190,28 @@ PRIVATE void pick_proc()
  * clock task can tell who to bill for system time.
  */
   register struct proc *rp;                    /* process to run */
-  int q;                                       /* iterate over queues */
+  int q;                               /* iterate over queues */
+
+  NOREC_ENTER(pick);
 
   /* Check each of the scheduling queues for ready processes. The number of
    * queues is defined in proc.h, and priorities are set in the task table.
    * The lowest queue contains IDLE, which is always ready.
    */
   for (q=0; q < NR_SCHED_QUEUES; q++) {        
-      if ( (rp = rdy_head[q]) != NIL_PROC) {
-         if(rp->p_misc_flags & MF_DELIVERMSG) {
-               /* Want to schedule process, but have to copy a message
-                * first.
-                */
-               FIXME("MF_DELIVERMSG no callback");
-               Deliver(rp);
-         }
-          next_ptr = rp;                       /* run process 'rp' next */
-#if 0
-       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 */
-          return;                               
-      }
+       int found = 0;
+       if(!(rp = rdy_head[q])) {
+               TRACE(VF_PICKPROC, printf("queue %d empty\n", q););
+               continue;
+       }
+       TRACE(VF_PICKPROC, printf("found %s / %d on queue %d\n", 
+               rp->p_name, rp->p_endpoint, q););
+       next_ptr = rp;                  /* run process 'rp' next */
+       vmassert(!next_ptr->p_rts_flags);
+       if (priv(rp)->s_flags & BILLABLE)               
+               bill_ptr = rp;          /* bill for system time */
+       NOREC_RETURN(pick, );
   }
-  minix_panic("no ready process", NO_NUM);
 }
 
 /*===========================================================================*
index f8956eb833a2ad17856e7ab99d4dc660e0395e50..48de9cf3f1ece971ab4d75b5d367f5e68435393e 100755 (executable)
@@ -47,6 +47,7 @@ struct proc {
 
   message p_sendmsg;           /* Message from this process if SENDING */
   message p_delivermsg;                /* Message for this process if MF_DELIVERMSG */
+  vir_bytes p_delivermsg_vir;  /* Virtual addr this proc wants message at */
   vir_bytes p_delivermsg_lin;  /* Linear addr this proc wants message at */
 
   /* If handler functions detect a process wants to do something with
@@ -60,7 +61,8 @@ struct proc {
        struct proc     *nextrestart;   /* next in vmrestart chain */
        struct proc     *nextrequestor; /* next in vmrequest chain */
 #define VMSTYPE_SYS_NONE       0
-#define VMSTYPE_SYS_MESSAGE    1
+#define VMSTYPE_KERNELCALL     1
+#define VMSTYPE_DELIVERMSG     2
        int             type;           /* suspended operation */
        union {
                /* VMSTYPE_SYS_MESSAGE */
@@ -75,10 +77,9 @@ struct proc {
        /* VM result when available */
        int             vmresult;
 
-       /* Target gets this set. (But caller and target can be
-        * the same, so we can't put this in the 'saved' union.)
-       */
-       struct proc     *requestor;
+#if DEBUG_VMASSERT
+       char stacktrace[200];
+#endif
 
        /* If the suspended operation is a sys_call, its details are
         * stored here.
@@ -96,18 +97,19 @@ struct proc {
 };
 
 /* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */
-#define SLOT_FREE      0x01    /* process slot is free */
-#define NO_PRIORITY     0x02   /* process has been stopped */
-#define SENDING                0x04    /* process blocked trying to send */
-#define RECEIVING      0x08    /* process blocked trying to receive */
-#define SIGNALED       0x10    /* set when new kernel signal arrives */
-#define SIG_PENDING    0x20    /* unready while signal being processed */
-#define P_STOP         0x40    /* set when process is being traced */
-#define NO_PRIV                0x80    /* keep forked system process from running */
-#define NO_ENDPOINT    0x100   /* process cannot send or receive messages */
-#define VMINHIBIT      0x200   /* not scheduled until pagetable set by VM */
-#define PAGEFAULT      0x400   /* process has unhandled pagefault */
-#define VMREQUEST      0x800   /* originator of vm memory request */
+#define SLOT_FREE       0x01   /* process slot is free */
+#define NO_PRIORITY      0x02  /* process has been stopped */
+#define SENDING                 0x04   /* process blocked trying to send */
+#define RECEIVING       0x08   /* process blocked trying to receive */
+#define SIGNALED        0x10   /* set when new kernel signal arrives */
+#define SIG_PENDING     0x20   /* unready while signal being processed */
+#define P_STOP          0x40   /* set when process is being traced */
+#define NO_PRIV                 0x80   /* keep forked system process from running */
+#define NO_ENDPOINT     0x100  /* process cannot send or receive messages */
+#define VMINHIBIT       0x200  /* not scheduled until pagetable set by VM */
+#define PAGEFAULT       0x400  /* process has unhandled pagefault */
+#define VMREQUEST       0x800  /* originator of vm memory request */
+#define VMREQTARGET    0x1000  /* target of vm memory request */
 
 /* These runtime flags can be tested and manipulated by these macros. */
 
@@ -117,33 +119,43 @@ struct proc {
 /* Set flag and dequeue if the process was runnable. */
 #define RTS_SET(rp, f)                                                 \
        do {                                                            \
+               vmassert(intr_disabled());                              \
                if(!(rp)->p_rts_flags) { dequeue(rp); }                 \
                (rp)->p_rts_flags |=  (f);                              \
+               vmassert(intr_disabled());                              \
        } while(0)
 
 /* Clear flag and enqueue if the process was not runnable but is now. */
 #define RTS_UNSET(rp, f)                                               \
        do {                                                            \
                int rts;                                                \
-               rts = (rp)->p_rts_flags;                                        \
+               vmassert(intr_disabled());                              \
+               rts = (rp)->p_rts_flags;                                \
                (rp)->p_rts_flags &= ~(f);                              \
                if(rts && !(rp)->p_rts_flags) { enqueue(rp); }          \
+               vmassert(intr_disabled());                              \
        } while(0)
 
 /* Set flag and dequeue if the process was runnable. */
 #define RTS_LOCK_SET(rp, f)                                            \
        do {                                                            \
-               if(!(rp)->p_rts_flags) { lock_dequeue(rp); }            \
+               int u = 0;                                              \
+               if(!intr_disabled()) { u = 1; lock; }                   \
+               if(!(rp)->p_rts_flags) { dequeue(rp); }                 \
                (rp)->p_rts_flags |=  (f);                              \
+               if(u) { unlock; }                                       \
        } while(0)
 
 /* Clear flag and enqueue if the process was not runnable but is now. */
 #define RTS_LOCK_UNSET(rp, f)                                          \
        do {                                                            \
                int rts;                                                \
-               rts = (rp)->p_rts_flags;                                        \
+               int u = 0;                                              \
+               if(!intr_disabled()) { u = 1; lock; }                   \
+               rts = (rp)->p_rts_flags;                                \
                (rp)->p_rts_flags &= ~(f);                              \
-               if(rts && !(rp)->p_rts_flags) { lock_enqueue(rp); }     \
+               if(rts && !(rp)->p_rts_flags) { enqueue(rp); }          \
+               if(u) { unlock; }                                       \
        } while(0)
 
 /* Set flags to this value. */
index 44bbbfefeaacf1e346c2897a0ee8522b422b26e6..65f8675b2fd7662a2972a4c66d6ae3359b582683 100755 (executable)
@@ -39,6 +39,7 @@ _PROTOTYPE( void lock_dequeue, (struct proc *rp)                      );
 _PROTOTYPE( void enqueue, (struct proc *rp)                            );
 _PROTOTYPE( void dequeue, (struct proc *rp)                            );
 _PROTOTYPE( void balance_queues, (struct timer *tp)                    );
+_PROTOTYPE( void schedcheck, (void)                                    );
 _PROTOTYPE( struct proc *endpoint_lookup, (endpoint_t ep)              );
 #if DEBUG_ENABLE_IPC_WARNINGS
 _PROTOTYPE( int isokendpt_f, (char *file, int line, endpoint_t e, int *p, int f));
@@ -162,7 +163,9 @@ _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));
+_PROTOTYPE( int vm_suspend, (struct proc *caller, struct proc *target,
+       phys_bytes lin, phys_bytes size, int wrflag, int type));
+_PROTOTYPE( int delivermsg, (struct proc *target));
 _PROTOTYPE( phys_bytes arch_switch_copymsg, (struct proc *rp, message *m,
        phys_bytes lin));
 
index 8e27606de71bb85299424acd25713468f266b56f..ac36fbaee11c8bfa6535c29539da19090a67e496 100755 (executable)
@@ -58,7 +58,8 @@ char *callnames[NR_SYS_CALLS];
 FORWARD _PROTOTYPE( void initialize, (void));
 FORWARD _PROTOTYPE( struct proc *vmrestart_check, (message *));
 
-u32_t cr3_test, cr3_reload, createpde, linlincopies, physzero;
+u32_t cr3_test, cr3_reload, newpde, overwritepde,
+       linlincopies, physzero, invlpgs, npagefaults, vmreqs, vmcheckranges, straightpdes;
 
 /*===========================================================================*
  *                             sys_task                                     *
@@ -87,21 +88,32 @@ PUBLIC void sys_task()
        /* Get work. Block and wait until a request message arrives. */
        if((r=receive(ANY, &m)) != OK)
                minix_panic("receive() failed", r);
-      }
+      } 
 
 #if 1
       {
        static int prevu;
-       int u;
+       int u, dt;
        u = get_uptime();
-       if(u/system_hz != prevu/system_hz) {
-               printf("cr3 tests: %5lu reloads: %5lu createpde: %5lu linlincopies: %5lu physzero: %5lu\n",
-                       cr3_test, cr3_reload, createpde, linlincopies, physzero);
-               cr3_test = 1;
+       dt = u - prevu;
+       if(dt >= 5*system_hz) {
+#define PERSEC(n) ((n)*system_hz/dt)
+               printf("%6d cr3 tests: %5lu cr3: %5lu straightpdes: %5lu newpde: %5lu overwritepde %5lu linlincopies: %5lu physzero: %5lu invlpgs: %5lu pagefaults: %5lu vmreq: %5lu vmcheckranges: %5lu\n",
+                       u/system_hz,
+                       PERSEC(cr3_test), PERSEC(cr3_reload),
+                       PERSEC(straightpdes), PERSEC(newpde),
+                       PERSEC(overwritepde),
+                       PERSEC(linlincopies), PERSEC(physzero),
+                       PERSEC(invlpgs), PERSEC(npagefaults),
+                       PERSEC(vmreqs), PERSEC(vmcheckranges));
                cr3_reload = 0;
-               createpde = linlincopies = physzero = 0;
+               cr3_test = 0;
+               newpde = overwritepde = linlincopies =
+                       physzero = invlpgs =  straightpdes = 0;
+               npagefaults = 0;
+               vmreqs = vmcheckranges = 0;
+               prevu = u;
        }
-       prevu = u;
       }
 #endif
 
@@ -111,41 +123,13 @@ PUBLIC void sys_task()
       okendpt(who_e, &who_p);
       caller_ptr = proc_addr(who_p);
 
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               sys_stats.total= add64u(sys_stats.total, 1);
-
       /* See if the caller made a valid request and try to handle it. */
       if (call_nr < 0 || call_nr >= NR_SYS_CALLS) {    /* check call number */
-#if DEBUG_ENABLE_IPC_WARNINGS
          kprintf("SYSTEM: illegal request %d from %d.\n",
                call_nr,m.m_source);
-#endif
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               sys_stats.bad_req++;
          result = EBADREQUEST;                 /* illegal message type */
       } 
       else if (!GET_BIT(priv(caller_ptr)->s_k_call_mask, call_nr)) {
-#if DEBUG_ENABLE_IPC_WARNINGS
-       static int curr= 0, limit= 100, extra= 20;
-
-       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");
-       }
-       else if (curr == 2*limit-1)
-               limit *= 2;
-       curr++;
-#endif
-       if (caller_ptr->p_endpoint == ipc_stats_target)
-               sys_stats.not_allowed++;
          result = ECALLDENIED;                 /* illegal message type */
       }
       else {
@@ -157,15 +141,18 @@ PUBLIC void sys_task()
         * until VM tells us it's allowed. VM has been notified
         * and we must wait for its reply to restart the call.
         */
+        vmassert(RTS_ISSET(caller_ptr, VMREQUEST));
+       vmassert(caller_ptr->p_vmrequest.type == VMSTYPE_KERNELCALL);
        memcpy(&caller_ptr->p_vmrequest.saved.reqmsg, &m, sizeof(m));
-       caller_ptr->p_vmrequest.type = VMSTYPE_SYS_MESSAGE;
       } else if (result != EDONTREPLY) {
        /* Send a reply, unless inhibited by a handler function.
         * Use the kernel function lock_send() to prevent a system
         * call trap.
         */
-               if(restarting)
-                       RTS_LOCK_UNSET(restarting, VMREQUEST);
+               if(restarting) {
+                       vmassert(!RTS_ISSET(restarting, VMREQUEST));
+                       vmassert(!RTS_ISSET(restarting, VMREQTARGET));
+               }
                m.m_type = result;              /* report status of call */
                if(WILLRECEIVE(caller_ptr, SYSTEM)) {
                  if (OK != (s=lock_send(m.m_source, &m))) {
@@ -561,23 +548,18 @@ PRIVATE struct proc *vmrestart_check(message *m)
        if(!(restarting = vmrestart))
                return NULL;
 
-       if(restarting->p_rts_flags & SLOT_FREE)
-          minix_panic("SYSTEM: VMREQUEST set for empty process", NO_NUM);
+       vmassert(!RTS_ISSET(restarting, SLOT_FREE));
+       vmassert(RTS_ISSET(restarting, VMREQUEST));
 
        type = restarting->p_vmrequest.type;
        restarting->p_vmrequest.type = VMSTYPE_SYS_NONE;
        vmrestart = restarting->p_vmrequest.nextrestart;
 
-       if(!RTS_ISSET(restarting, VMREQUEST))
-          minix_panic("SYSTEM: VMREQUEST not set for process on vmrestart queue",
-               restarting->p_endpoint);
-
        switch(type) {
-               case VMSTYPE_SYS_MESSAGE:
+               case VMSTYPE_KERNELCALL:
                        memcpy(m, &restarting->p_vmrequest.saved.reqmsg, sizeof(*m));
-                       if(m->m_source != restarting->p_endpoint)
-                          minix_panic("SYSTEM: vmrestart source doesn't match",
-                               NO_NUM);
+                       restarting->p_vmrequest.saved.reqmsg.m_source = NONE;
+                       vmassert(m->m_source == restarting->p_endpoint);
                        /* Original caller could've disappeared in the meantime. */
                        if(!isokendpt(m->m_source, &who_p)) {
                                kprintf("SYSTEM: ignoring call %d from dead %d\n",
index ee7e0a912ed444b5fe0567685ad2385cba9e8742..65834be388e9c472848e4fc09f0618790fd7e079 100644 (file)
@@ -63,19 +63,8 @@ register message *m_ptr;     /* pointer to request message */
        }
        if (i >= nr_io_range)
        {
-               static int curr= 0, limit= 100, extra= 20;
-
-               if (curr < limit+extra)
-               {
                        kprintf("do_devio: port 0x%x (size %d) not allowed\n",
                                m_ptr->DIO_PORT, size);
-               } else if (curr == limit+extra)
-               {
-                       kprintf("do_devio: no debug output for a while\n");
-               }
-               else if (curr == 2*limit-1)
-                       limit *= 2;
-               curr++;
                return EPERM;
        }
     }
@@ -83,19 +72,8 @@ register message *m_ptr;     /* pointer to request message */
 doit:
     if (m_ptr->DIO_PORT & (size-1))
     {
-       static int curr= 0, limit= 100, extra= 20;
-
-       if (curr < limit+extra)
-       {
                kprintf("do_devio: unaligned port 0x%x (size %d)\n",
                        m_ptr->DIO_PORT, size);
-       } else if (curr == limit+extra)
-       {
-               kprintf("do_devio: no debug output for a while\n");
-       }
-       else if (curr == 2*limit-1)
-               limit *= 2;
-       curr++;
        return EPERM;
     }
 
index 3df76da50e19956f3aaa6f81dda863d7db504314..e27ef6adea6a254fd02b6897eb8501cef370c1be 100644 (file)
@@ -90,7 +90,7 @@ register message *m_ptr;      /* pointer to request message */
 
   /* Calculate endpoint identifier, so caller knows what it is. */
   m_ptr->PR_ENDPT = rpc->p_endpoint;
-  m_ptr->PR_FORK_MSGADDR = (char *) rpp->p_delivermsg_lin;
+  m_ptr->PR_FORK_MSGADDR = (char *) rpp->p_delivermsg_vir;
 
   /* Install new map */
   r = newmap(rpc, map_ptr);
index 4c1ecc1c4ceb0f9bc2d9892a0750a9a57adc2304..f6e58e99c8a6d672829d039fc717b4eadcced0e6 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "../system.h"
+#include "../vm.h"
 
 #if USE_MEMSET
 
index 55744b7144543ecd710ac37a4e815942f6fc4e7d..2e7d7f8ee35400af66f9540913520e5138fcfa93 100644 (file)
@@ -61,22 +61,11 @@ endpoint_t *e_granter;              /* new granter (magic grants) */
        if(!HASGRANTTABLE(granter_proc)) return EPERM;
 
        if(priv(granter_proc)->s_grant_entries <= grant) {
-               static int curr= 0, limit= 100, extra= 20;
-
-               if (curr < limit+extra)
-               {
                        kprintf(
                        "verify_grant: grant verify failed in ep %d proc %d: "
                        "grant %d out of range for table size %d\n",
                                granter, proc_nr, grant,
                                priv(granter_proc)->s_grant_entries);
-               } else if (curr == limit+extra)
-               {
-                       kprintf("verify_grant: no debug output for a while\n");
-               }
-               else if (curr == 2*limit-1)
-                       limit *= 2;
-               curr++;
                return(EPERM);
        }
 
@@ -219,23 +208,9 @@ int access;                        /* CPF_READ for a copy from granter to grantee, CPF_WRITE
        /* Verify permission exists. */
        if((r=verify_grant(granter, grantee, grantid, bytes, access,
            g_offset, &v_offset, &new_granter)) != OK) {
-               static int curr= 0, limit= 100, extra= 20;
-
-               if (curr < limit+extra)
-               {
-#if 0
                        kprintf(
                "grant %d verify to copy %d->%d by %d failed: err %d\n",
                                grantid, *src, *dst, grantee, r);
-#endif
-               } else if (curr == limit+extra)
-               {
-                       kprintf(
-                       "do_safecopy`safecopy: no debug output for a while\n");
-               }
-               else if (curr == 2*limit-1)
-                       limit *= 2;
-               curr++;
                return r;
        }
 
index f766ba853174844fa6a26fe80ec6cde9ac9cb184..e33c24b7320782c117f61225c2d79c5432fd1cbb 100644 (file)
@@ -13,6 +13,8 @@
 #include <minix/type.h>
 #include <minix/config.h>
 
+extern int verifyrange;
+
 /*===========================================================================*
  *                             do_vmctl                                     *
  *===========================================================================*/
@@ -21,7 +23,7 @@ register message *m_ptr;      /* pointer to request message */
 {
   int proc_nr, i;
   endpoint_t ep = m_ptr->SVMCTL_WHO;
-  struct proc *p, *rp;
+  struct proc *p, *rp, *target;
 
   if(ep == SELF) { ep = m_ptr->m_source; }
 
@@ -40,15 +42,25 @@ register message *m_ptr;    /* pointer to request message */
                /* Send VM the information about the memory request.  */
                if(!(rp = vmrequest))
                        return ESRCH;
-               if(!RTS_ISSET(rp, VMREQUEST))
-                       minix_panic("do_vmctl: no VMREQUEST set", NO_NUM);
+               vmassert(RTS_ISSET(rp, VMREQUEST));
 
 #if 0
-               printf("kernel: vm request sent by: %s / %d about %d; 0x%lx-0x%lx, wr %d\n",
+               printf("kernel: vm request sent by: %s / %d about %d; 0x%lx-0x%lx, wr %d, stack: %s ",
                        rp->p_name, rp->p_endpoint, rp->p_vmrequest.who,
                        rp->p_vmrequest.start,
                        rp->p_vmrequest.start + rp->p_vmrequest.length,
-                       rp->p_vmrequest.writeflag);
+                       rp->p_vmrequest.writeflag, rp->p_vmrequest.stacktrace);
+               printf("type %d\n", rp->p_vmrequest.type);
+#endif
+
+#if DEBUG_VMASSERT
+               okendpt(rp->p_vmrequest.who, &proc_nr);
+               target = proc_addr(proc_nr);
+               if(!RTS_ISSET(target, VMREQTARGET)) {
+                       printf("set stack: %s\n", rp->p_vmrequest.stacktrace);
+                       minix_panic("VMREQTARGET not set for target",
+                               NO_NUM);
+               }
 #endif
 
                /* Reply with request fields. */
@@ -56,6 +68,7 @@ register message *m_ptr;      /* pointer to request message */
                m_ptr->SVMCTL_MRG_LEN = rp->p_vmrequest.length;
                m_ptr->SVMCTL_MRG_WRITE = rp->p_vmrequest.writeflag;
                m_ptr->SVMCTL_MRG_EP = rp->p_vmrequest.who;
+               m_ptr->SVMCTL_MRG_REQUESTOR = (void *) rp->p_endpoint;
                rp->p_vmrequest.vmresult = VMSUSPEND;
 
                /* Remove from request chain. */
@@ -63,41 +76,84 @@ register message *m_ptr;    /* pointer to request message */
 
                return OK;
        case VMCTL_MEMREQ_REPLY:
-               if(!(rp = p->p_vmrequest.requestor))
-                       minix_panic("do_vmctl: no requestor set", ep);
-               p->p_vmrequest.requestor = NULL;
-               if(!RTS_ISSET(rp, VMREQUEST))
-                       minix_panic("do_vmctl: no VMREQUEST set", ep);
-               if(rp->p_vmrequest.vmresult != VMSUSPEND)
-                       minix_panic("do_vmctl: result not VMSUSPEND set",
-                               rp->p_vmrequest.vmresult);
-               rp->p_vmrequest.vmresult = m_ptr->SVMCTL_VALUE;
-               if(rp->p_vmrequest.vmresult == VMSUSPEND)
-                       minix_panic("VM returned VMSUSPEND?", NO_NUM);
-               if(rp->p_vmrequest.vmresult != OK)
+               vmassert(RTS_ISSET(p, VMREQUEST));
+               vmassert(p->p_vmrequest.vmresult == VMSUSPEND);
+               okendpt(p->p_vmrequest.who, &proc_nr);
+               target = proc_addr(proc_nr);
+               p->p_vmrequest.vmresult = m_ptr->SVMCTL_VALUE;
+               vmassert(p->p_vmrequest.vmresult != VMSUSPEND);
+               if(p->p_vmrequest.vmresult != OK)
                        kprintf("SYSTEM: VM replied %d to mem request\n",
-                               rp->p_vmrequest.vmresult);
+                               p->p_vmrequest.vmresult);
 
-               /* Put on restart chain. */
-               rp->p_vmrequest.nextrestart = vmrestart;
-               vmrestart = rp;
+
+#if 0
+               printf("memreq reply: vm request sent by: %s / %d about %d; 0x%lx-0x%lx, wr %d, stack: %s ",
+                       p->p_name, p->p_endpoint, p->p_vmrequest.who,
+                       p->p_vmrequest.start,
+                       p->p_vmrequest.start + p->p_vmrequest.length,
+                       p->p_vmrequest.writeflag, p->p_vmrequest.stacktrace);
+               printf("type %d\n", p->p_vmrequest.type);
+#endif
 
 #if DEBUG_VMASSERT
+       {
+               vmassert(target->p_rts_flags);
+
                /* Sanity check. */
-               if(rp->p_vmrequest.vmresult == OK) {
-                       if(CHECKRANGE(p,
-                               rp->p_vmrequest.start,
-                               rp->p_vmrequest.length,
-                               rp->p_vmrequest.writeflag) != OK) {
-kprintf("SYSTEM: request %d:0x%lx-0x%lx, wrflag %d, failed\n",
-       rp->p_endpoint,
-       rp->p_vmrequest.start,  rp->p_vmrequest.start + rp->p_vmrequest.length,
-       rp->p_vmrequest.writeflag); 
+               if(p->p_vmrequest.vmresult == OK) {
+                       int r;
+                       vmassert(!verifyrange);
+                       verifyrange = 1;
+                       r = CHECKRANGE(target,
+                               p->p_vmrequest.start,
+                               p->p_vmrequest.length,
+                               p->p_vmrequest.writeflag);
+                       vmassert(verifyrange);
+                       verifyrange = 0;
+
+                       if(r != OK) {
+
+kprintf("SYSTEM: request by %d: on ep %d: 0x%lx-0x%lx, wrflag %d, stack %s, failed\n",
+       p->p_endpoint, target->p_endpoint,
+       p->p_vmrequest.start,  p->p_vmrequest.start + p->p_vmrequest.length,
+       p->p_vmrequest.writeflag,
+       p->p_vmrequest.stacktrace); 
        
+                               printf("printing pt of %d (0x%lx)\n",
+                                       vm_print(target->p_endpoint),
+                                       target->p_seg.p_cr3
+                                       );
+                               vm_print(target->p_seg.p_cr3);
                                minix_panic("SYSTEM: fail but VM said OK", NO_NUM);
-                       } 
-               }
+                        }
+               }  
+       }
 #endif
+
+               vmassert(RTS_ISSET(target, VMREQTARGET));
+               RTS_LOCK_UNSET(target, VMREQTARGET);
+
+               if(p->p_vmrequest.type == VMSTYPE_KERNELCALL) {
+                       /* Put on restart chain. */
+                       p->p_vmrequest.nextrestart = vmrestart;
+                       vmrestart = p;
+               } else if(p->p_vmrequest.type == VMSTYPE_DELIVERMSG) {
+                       vmassert(p->p_misc_flags & MF_DELIVERMSG);
+                       vmassert(p == target);
+                       vmassert(RTS_ISSET(p, VMREQUEST));
+                       vmassert(RTS_ISSET(p, VMREQTARGET));
+                       RTS_LOCK_UNSET(p, VMREQUEST);
+                       RTS_LOCK_UNSET(target, VMREQTARGET);
+               } else {
+#if DEBUG_VMASSERT
+                       printf("suspended with stack: %s\n",
+                               p->p_vmrequest.stacktrace);
+#endif
+                       minix_panic("strange request type",
+                               p->p_vmrequest.type);
+               }
+
                return OK;
        case VMCTL_ENABLE_PAGING:
                if(vm_running) 
@@ -105,8 +161,13 @@ kprintf("SYSTEM: request %d:0x%lx-0x%lx, wrflag %d, failed\n",
                vm_init(p);
                if(!vm_running)
                        minix_panic("do_vmctl: paging enabling failed", NO_NUM);
+               vmassert(p->p_delivermsg_lin ==
+                 umap_local(p, D, p->p_delivermsg_vir, sizeof(message)));
                if(newmap(p, m_ptr->SVMCTL_VALUE) != OK)
                        minix_panic("do_vmctl: newmap failed", NO_NUM);
+               p->p_delivermsg_lin =
+                       umap_local(p, D, p->p_delivermsg_vir, sizeof(message));
+               vmassert(p->p_delivermsg_lin);
                return OK;
   }
 
index 4a09ced0212bc7dce1fe61029a00568c4133f49b..d9df204cc20c20dd16489b7b794c3c82e3ee7c6f 100755 (executable)
@@ -35,7 +35,7 @@
 
 /* Define stack sizes for the kernel tasks included in the system image. */
 #define NO_STACK       0
-#define SMALL_STACK    (256 * sizeof(char *))
+#define SMALL_STACK    (1024 * sizeof(char *))
 #define IDL_S  SMALL_STACK     /* 3 intr, 3 temps, 4 db for Intel */
 #define        HRD_S   NO_STACK        /* dummy task, uses kernel stack */
 #define        TSK_S   SMALL_STACK     /* system and clock task */
index a98d765743f092b488a66d8f9f8a403d093442d5..29f27e2438f5b6c0f313505dca946292ef52004e 100755 (executable)
@@ -43,7 +43,7 @@ PUBLIC int sys_vmctl_get_cr3_i386(endpoint_t who, u32_t *cr3)
 }
 
 PUBLIC int sys_vmctl_get_memreq(endpoint_t *who, vir_bytes *mem,
-       vir_bytes *len, int *wrflag)
+       vir_bytes *len, int *wrflag, endpoint_t *requestor)
 {
   message m;
   int r;
@@ -56,7 +56,16 @@ PUBLIC int sys_vmctl_get_memreq(endpoint_t *who, vir_bytes *mem,
        *mem = (vir_bytes) m.SVMCTL_MRG_ADDR;
        *len = m.SVMCTL_MRG_LEN;
        *wrflag = m.SVMCTL_MRG_WRITE;
+       *requestor = (endpoint_t) m.SVMCTL_MRG_REQUESTOR;
   }
   return r;
 }
 
+PUBLIC int sys_vmctl_enable_paging(struct mem_map *map)
+{
+       message m;
+       m.SVMCTL_WHO = SELF;
+       m.SVMCTL_PARAM = VMCTL_ENABLE_PAGING;
+       m.SVMCTL_VALUE = (int) map;
+       return _taskcall(SYSTASK, SYS_VMCTL, &m);
+}
index e1e5ed21744c6472b28aed036b7c582a2a820394..30c02baac8f90e7704d9ed60b315db1c98a31d9d 100644 (file)
@@ -290,8 +290,11 @@ PRIVATE void get_work()
        continue;
     }
     if(who_p >= 0 && fproc[who_p].fp_endpoint != who_e) {
-       printf("FS: receive endpoint inconsistent (%d, %d, %d).\n",
-               who_e, fproc[who_p].fp_endpoint, who_e);
+       if(fproc[who_p].fp_endpoint == NONE) { 
+               printf("slot unknown even\n");
+       }
+       printf("FS: receive endpoint inconsistent (source %d, who_p %d, stored ep %d, who_e %d).\n",
+               m_in.m_source, who_p, fproc[who_p].fp_endpoint, who_e);
 #if 0
        panic(__FILE__, "FS: inconsistent endpoint ", NO_NUM);
 #endif
index a0af18811ecf1d2e252c17d526476cbce15a55ef..bf4255794f33ae0277be4c46a268c17795851e31 100644 (file)
@@ -145,9 +145,12 @@ PUBLIC int do_fork(message *msg)
   }
 
   if(fullvm) {
-       if(handle_memory(vmc, msgaddr, sizeof(message), 1) != OK)
+       vir_bytes vir;
+       vir = arch_vir2map(vmc, msgaddr);
+       if(handle_memory(vmc, vir, sizeof(message), 1) != OK)
                vm_panic("can't make message writable (child)", NO_NUM);
-       if(handle_memory(vmp, msgaddr, sizeof(message), 1) != OK)
+       vir = arch_vir2map(vmp, msgaddr);
+       if(handle_memory(vmp, vir, sizeof(message), 1) != OK)
                vm_panic("can't make message writable (parent)", NO_NUM);
        if((r=pt_bind(&vmc->vm_pt, vmc)) != OK)
                vm_panic("fork can't pt_bind", r);
index 947ff51414f16c458d44a75a516a1fce494f4986..1f0cf011f22c4a05047b8cc7bda1742d094c0c07 100644 (file)
@@ -719,10 +719,8 @@ PUBLIC void pt_init(void)
         pt_bind(newpt, vmp);
        
        /* 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);
-       }
+       if(sys_vmctl_enable_paging(vmp->vm_arch.vm_seg) != OK)
+               vm_panic("pt_init: enable paging failed", NO_NUM);
 
         /* Back to reality - this is where the stack actually is. */
         vmp->vm_arch.vm_seg[S].mem_len -= extra_clicks;
index 8cfff5c2c31b9220680d38b1c801c970bca2cd6d..a3eaa7661750378cd4c6598f04c6973c99e76140 100644 (file)
@@ -118,6 +118,8 @@ PUBLIC int main(void)
                                 * verified, and/or pagefaults handled.
                                 */
                                do_memory();
+                               break;
+                       case HARDWARE:
                                do_pagefaults();
                                break;
                        case PM_PROC_NR:
index 60987118bf235806bd8eea647d7392445b3bce38..7716c7bae6d7b746e2c0cef36b6bf4353a8377af 100644 (file)
@@ -61,6 +61,11 @@ PUBLIC void do_pagefaults(void)
                vir_bytes offset;
                int p, wr = PFERR_WRITE(err);
 
+#if 0
+               printf("VM: pagefault: ep %d 0x%lx %s\n", 
+                       ep, arch_map2vir(vmp, addr), pf_errstr(err));
+#endif
+
                if(vm_isokendpt(ep, &p) != OK)
                        vm_panic("do_pagefaults: endpoint wrong", ep);
 
@@ -104,9 +109,11 @@ PUBLIC void do_pagefaults(void)
                                vm_panic("sys_kill failed", s);
                        continue;
                }
+#if 0
+               printf("VM: map_pf done; ep %d 0x%lx %s\n", 
+                       ep, arch_map2vir(vmp, addr), pf_errstr(err));
 
 
-#if 0
                printf("VM: handling pagefault OK: %d addr 0x%lx %s\n", 
                        ep, arch_map2vir(vmp, addr), pf_errstr(err));
 #endif
@@ -126,12 +133,13 @@ PUBLIC void do_pagefaults(void)
 PUBLIC void do_memory(void)
 {
        int r, s;
-       endpoint_t who;
+       endpoint_t who, requestor;
        vir_bytes mem;
        vir_bytes len;
        int wrflag;
 
-       while((r=sys_vmctl_get_memreq(&who, &mem, &len, &wrflag)) == OK) {
+       while((r=sys_vmctl_get_memreq(&who, &mem, &len, &wrflag, &requestor))
+         == OK) {
                int p, r = OK;
                struct vmproc *vmp;
 
@@ -141,7 +149,7 @@ PUBLIC void do_memory(void)
 
                r = handle_memory(vmp, mem, len, wrflag);
 
-               if(sys_vmctl(who, VMCTL_MEMREQ_REPLY, r) != OK)
+               if(sys_vmctl(requestor, VMCTL_MEMREQ_REPLY, r) != OK)
                        vm_panic("do_memory: sys_vmctl failed", r);
 
 #if 0
@@ -170,6 +178,7 @@ int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag)
        if(o > 0) len += VM_PAGE_SIZE - o;
 
        if(!(region = map_lookup(vmp, mem))) {
+               map_printmap(vmp);
                printf("VM: do_memory: memory doesn't exist\n");
                r = EFAULT;
        } else if(mem + len > region->vaddr + region->length) {