From 8d800b3df70dab3057517f6ada7b1c67ee8be615 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Tue, 8 Dec 2009 13:35:52 +0000 Subject: [PATCH] Make VM fix up memory for kernel that crosses region boundaries too. Add a test to make this happen (triggers a vm panic before this commit). --- servers/vm/i386/pagetable.c | 3 -- servers/vm/mmap.c | 3 +- servers/vm/pagefaults.c | 87 +++++++++++++++---------------------- servers/vm/region.c | 9 +++- test/Makefile | 3 +- test/run | 2 +- 6 files changed, 46 insertions(+), 61 deletions(-) diff --git a/servers/vm/i386/pagetable.c b/servers/vm/i386/pagetable.c index 7dbf6891a..7479948d3 100644 --- a/servers/vm/i386/pagetable.c +++ b/servers/vm/i386/pagetable.c @@ -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 + diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c index 74f3f4f9f..5abc459b6 100644 --- a/servers/vm/mmap.c +++ b/servers/vm/mmap.c @@ -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; } diff --git a/servers/vm/pagefaults.c b/servers/vm/pagefaults.c index 208e5f63e..c6ce4dd72 100644 --- a/servers/vm/pagefaults.c +++ b/servers/vm/pagefaults.c @@ -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; } diff --git a/servers/vm/region.c b/servers/vm/region.c index bc3a92e76..559f3eecb 100644 --- a/servers/vm/region.c +++ b/servers/vm/region.c @@ -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)) { diff --git a/test/Makefile b/test/Makefile index 3e006e0a3..845b58883 100644 --- a/test/Makefile +++ b/test/Makefile @@ -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 diff --git a/test/run b/test/run index 4e9297df7..c6b33d8b5 100755 --- 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 \) ] -- 2.44.0