]> Zhao Yanbai Git Server - minix.git/commitdiff
Make VM fix up memory for kernel that crosses region boundaries
authorBen Gras <ben@minix3.org>
Tue, 8 Dec 2009 13:35:52 +0000 (13:35 +0000)
committerBen Gras <ben@minix3.org>
Tue, 8 Dec 2009 13:35:52 +0000 (13:35 +0000)
too.

Add a test to make this happen (triggers a vm panic before this commit).

servers/vm/i386/pagetable.c
servers/vm/mmap.c
servers/vm/pagefaults.c
servers/vm/region.c
test/Makefile
test/run

index 7dbf6891ac2e329d588c877bc5cbafcbccc82283..7479948d3617bf7150adc32200b02379bec81c70 100644 (file)
@@ -711,9 +711,6 @@ PUBLIC void pt_init(phys_bytes usedlimit)
        /* We have to make mappings up till here. */
        free_pde = id_map_high_pde+1;
 
-       printf("map high pde: %d for limit: 0x%lx\n",
-               id_map_high_pde, usedlimit);
-
         /* Initial (current) range of our virtual address space. */
         lo = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys);
         hi = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_phys +
index 74f3f4f9ff8072e1f127101fab20a01a6a799ba1..5abc459b6887b817db0b8c1b761c107b63df671a 100644 (file)
@@ -72,7 +72,8 @@ PUBLIC int do_mmap(message *m)
                        len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);
 
                if(!(vr = map_page_region(vmp,
-                       arch_vir2map(vmp, vmp->vm_stacktop),
+                       arch_vir2map(vmp,
+                               m->VMM_ADDR ? m->VMM_ADDR : vmp->vm_stacktop),
                        VM_DATATOP, len, MAP_NONE, vrflags, mfflags))) {
                        return ENOMEM;
                }
index 208e5f63e836e3e18a9c0b05ed73c9692fe60059..c6ce4dd7275ad42da4814b1e419c28e28141e261 100644 (file)
@@ -62,21 +62,12 @@ 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);
 
                vmp = &vmproc[p];
                vm_assert(vmp->vm_flags & VMF_INUSE);
 
-#if 0
-               map_printmap(vmp);
-#endif
-
                /* See if address is valid at all. */
                if(!(region = map_lookup(vmp, addr))) {
                        vm_assert(PFERR_NOPAGE(err));
@@ -125,14 +116,6 @@ PUBLIC void do_pagefaults(void)
                                vm_panic("do_pagefaults: sys_vmctl failed", ep);
                        continue;
                }
-#if 0
-               printf("VM: map_pf done; ep %d 0x%lx %s\n", 
-                       ep, arch_map2vir(vmp, addr), pf_errstr(err));
-
-
-               printf("VM: handling pagefault OK: %d addr 0x%lx %s\n", 
-                       ep, arch_map2vir(vmp, addr), pf_errstr(err));
-#endif
 
                /* Pagefault is handled, so now reactivate the process. */
                if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
@@ -167,11 +150,6 @@ PUBLIC void do_memory(void)
 
                if(sys_vmctl(requestor, VMCTL_MEMREQ_REPLY, r) != OK)
                        vm_panic("do_memory: sys_vmctl failed", r);
-
-#if 0
-               printf("VM: handling memory request %d done OK\n",
-                       who);
-#endif
        }
 }
 
@@ -179,12 +157,7 @@ int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag)
 {
        struct vir_region *region;
        vir_bytes o;
-       int r;
-
-#if 0
-       printf("VM: handling memory request: %d, 0x%lx-0x%lx, wr %d\n",
-               vmp->vm_endpoint, mem, mem+len, wrflag);
-#endif
+       vir_bytes v;
 
        /* Page-align memory and length. */
        o = mem % VM_PAGE_SIZE;
@@ -193,31 +166,39 @@ int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag)
        o = len % VM_PAGE_SIZE;
        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) {
-               vm_assert(region->vaddr <= mem);
-               vm_panic("do_memory: not contained", NO_NUM);
-       } else if(!(region->flags & VR_WRITABLE) && wrflag) {
-               printf("VM: do_memory: write to unwritable map\n");
-               r = EFAULT;
-       } else {
-               vir_bytes offset;
-               vm_assert(region->vaddr <= mem);
-               vm_assert(!(region->flags & VR_NOPF));
-               vm_assert(!(region->vaddr % VM_PAGE_SIZE));
-               offset = mem - region->vaddr;
-
-               r = map_handle_memory(vmp, region, offset, len, wrflag);
-       }
-
-       if(r != OK) {
-               printf("VM: memory range 0x%lx-0x%lx not available in %d\n",
-                       arch_map2vir(vmp, mem), arch_map2vir(vmp, mem+len),
-                       vmp->vm_endpoint);
+       while(len > 0) {
+               int r;
+               if(!(region = map_lookup(vmp, mem))) {
+                       map_printmap(vmp);
+                       printf("VM: do_memory: memory doesn't exist\n");
+                       r = EFAULT;
+               } else if(!(region->flags & VR_WRITABLE) && wrflag) {
+                       printf("VM: do_memory: write to unwritable map\n");
+                       r = EFAULT;
+               } else {
+                       vir_bytes offset, sublen;
+                       vm_assert(region->vaddr <= mem);
+                       vm_assert(!(region->flags & VR_NOPF));
+                       vm_assert(!(region->vaddr % VM_PAGE_SIZE));
+                       offset = mem - region->vaddr;
+                       sublen = len;
+                       if(offset + sublen > region->length)
+                               sublen = region->length - offset;
+       
+                       r = map_handle_memory(vmp, region, offset,
+                               sublen, wrflag);
+
+                       len -= sublen;
+                       mem += sublen;
+               }
+       
+               if(r != OK) {
+                       printf("VM: memory range 0x%lx-0x%lx not available in %d\n",
+                               arch_map2vir(vmp, mem), arch_map2vir(vmp, mem+len),
+                               vmp->vm_endpoint);
+                       return r;
+               }
        }
 
-       return r;
+       return OK;
 }
index bc3a92e768bf34a35990e4055116cbf71721f290..559f3eecb2fd4b3a01caf7e4240f29270a4ac7a2 100644 (file)
@@ -898,6 +898,7 @@ int write;
        physr_start_iter(region->phys, &it, where, AVL_EQUAL);  \
        what = physr_get_iter(&it); \
        if(!what)  vm_panic("thing missing", NO_NUM); \
+       if(what->offset != where) vm_panic("thing wrong", NO_NUM);      \
 }
 
        FREE_RANGE_HERE(NULL, physr);
@@ -908,8 +909,8 @@ int write;
                        physr_incr_iter(&iter);
                        physr = physr_get_iter(&iter);
 
+                       FREE_RANGE_HERE(NULL, physr);
                        if(physr) {
-                               FREE_RANGE_HERE(NULL, physr);
                                RESET_ITER(iter, physr->offset, physr);
                        }
                }
@@ -957,7 +958,11 @@ int write;
 
        SANITYCHECK(SCL_FUNCTIONS);
 
-       vm_assert(changes > 0);
+       if(changes < 1) {
+               printf("region start at 0x%lx offset 0x%lx len 0x%lx write %d\n", 
+                       region->vaddr, offset, length, write);
+               vm_panic("no changes in map_handle_memory", NO_NUM);
+       }
 
 #if SANITYCHECKS
        if(OK != pt_checkrange(&vmp->vm_pt, region->vaddr+offset, length, write)) {
index 3e006e0a3762034134ffccfddb6b9261b317c49b..845b588831b24604b061e7f7930524a92abbd3b7 100644 (file)
@@ -8,7 +8,7 @@ OBJ=    test1  test2  test3  test4  test5  test6  test7  test8  test9  \
               test21 test22 test23        test25 test26 test27 test28 test29 \
        test30 test31 test32        test34 test35 test36 test37 test38 \
        test39 t10a t11a t11b test40 t40a t40b t40c t40d t40e t40f test41 \
-       test42 
+       test42 test44
 
 BIGOBJ=  test20 test24
 ROOTOBJ= test11 test33 test43
@@ -84,3 +84,4 @@ t40f: t40f.c
 test41: test41.c
 test42: test42.c
 test43: test43.c
+test44: test44.c
index 4e9297df705fc93d2e3188e430248317a57cff81..c6b33d8b52e619fdcc01885cea8e6739e528d96a 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -18,7 +18,7 @@ echo " "
 # Run all the tests, keeping track of who failed.
 for i in  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 \
          21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
-         41 42 43 sh1.sh sh2.sh
+         41 42 43 44 sh1.sh sh2.sh
 do total=`expr $total + 1`
    FAIL=0
    if [ $USER = root -a \( $i = 11 -o $i = 33 \) ]