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).
This commit is contained in:
parent
bd0933a19b
commit
8d800b3df7
@ -711,9 +711,6 @@ PUBLIC void pt_init(phys_bytes usedlimit)
|
|||||||
/* We have to make mappings up till here. */
|
/* We have to make mappings up till here. */
|
||||||
free_pde = id_map_high_pde+1;
|
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. */
|
/* Initial (current) range of our virtual address space. */
|
||||||
lo = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys);
|
lo = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys);
|
||||||
hi = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_phys +
|
hi = CLICK2ABS(vmp->vm_arch.vm_seg[S].mem_phys +
|
||||||
|
@ -72,7 +72,8 @@ PUBLIC int do_mmap(message *m)
|
|||||||
len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);
|
len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);
|
||||||
|
|
||||||
if(!(vr = map_page_region(vmp,
|
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))) {
|
VM_DATATOP, len, MAP_NONE, vrflags, mfflags))) {
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -62,21 +62,12 @@ PUBLIC void do_pagefaults(void)
|
|||||||
vir_bytes offset;
|
vir_bytes offset;
|
||||||
int p, wr = PFERR_WRITE(err);
|
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)
|
if(vm_isokendpt(ep, &p) != OK)
|
||||||
vm_panic("do_pagefaults: endpoint wrong", ep);
|
vm_panic("do_pagefaults: endpoint wrong", ep);
|
||||||
|
|
||||||
vmp = &vmproc[p];
|
vmp = &vmproc[p];
|
||||||
vm_assert(vmp->vm_flags & VMF_INUSE);
|
vm_assert(vmp->vm_flags & VMF_INUSE);
|
||||||
|
|
||||||
#if 0
|
|
||||||
map_printmap(vmp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* See if address is valid at all. */
|
/* See if address is valid at all. */
|
||||||
if(!(region = map_lookup(vmp, addr))) {
|
if(!(region = map_lookup(vmp, addr))) {
|
||||||
vm_assert(PFERR_NOPAGE(err));
|
vm_assert(PFERR_NOPAGE(err));
|
||||||
@ -125,14 +116,6 @@ PUBLIC void do_pagefaults(void)
|
|||||||
vm_panic("do_pagefaults: sys_vmctl failed", ep);
|
vm_panic("do_pagefaults: sys_vmctl failed", ep);
|
||||||
continue;
|
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. */
|
/* Pagefault is handled, so now reactivate the process. */
|
||||||
if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
|
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)
|
if(sys_vmctl(requestor, VMCTL_MEMREQ_REPLY, r) != OK)
|
||||||
vm_panic("do_memory: sys_vmctl failed", r);
|
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;
|
struct vir_region *region;
|
||||||
vir_bytes o;
|
vir_bytes o;
|
||||||
int r;
|
vir_bytes v;
|
||||||
|
|
||||||
#if 0
|
|
||||||
printf("VM: handling memory request: %d, 0x%lx-0x%lx, wr %d\n",
|
|
||||||
vmp->vm_endpoint, mem, mem+len, wrflag);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Page-align memory and length. */
|
/* Page-align memory and length. */
|
||||||
o = mem % VM_PAGE_SIZE;
|
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;
|
o = len % VM_PAGE_SIZE;
|
||||||
if(o > 0) len += VM_PAGE_SIZE - o;
|
if(o > 0) len += VM_PAGE_SIZE - o;
|
||||||
|
|
||||||
if(!(region = map_lookup(vmp, mem))) {
|
while(len > 0) {
|
||||||
map_printmap(vmp);
|
int r;
|
||||||
printf("VM: do_memory: memory doesn't exist\n");
|
if(!(region = map_lookup(vmp, mem))) {
|
||||||
r = EFAULT;
|
map_printmap(vmp);
|
||||||
} else if(mem + len > region->vaddr + region->length) {
|
printf("VM: do_memory: memory doesn't exist\n");
|
||||||
vm_assert(region->vaddr <= mem);
|
r = EFAULT;
|
||||||
vm_panic("do_memory: not contained", NO_NUM);
|
} else if(!(region->flags & VR_WRITABLE) && wrflag) {
|
||||||
} else if(!(region->flags & VR_WRITABLE) && wrflag) {
|
printf("VM: do_memory: write to unwritable map\n");
|
||||||
printf("VM: do_memory: write to unwritable map\n");
|
r = EFAULT;
|
||||||
r = EFAULT;
|
} else {
|
||||||
} else {
|
vir_bytes offset, sublen;
|
||||||
vir_bytes offset;
|
vm_assert(region->vaddr <= mem);
|
||||||
vm_assert(region->vaddr <= mem);
|
vm_assert(!(region->flags & VR_NOPF));
|
||||||
vm_assert(!(region->flags & VR_NOPF));
|
vm_assert(!(region->vaddr % VM_PAGE_SIZE));
|
||||||
vm_assert(!(region->vaddr % VM_PAGE_SIZE));
|
offset = mem - region->vaddr;
|
||||||
offset = mem - region->vaddr;
|
sublen = len;
|
||||||
|
if(offset + sublen > region->length)
|
||||||
|
sublen = region->length - offset;
|
||||||
|
|
||||||
|
r = map_handle_memory(vmp, region, offset,
|
||||||
|
sublen, wrflag);
|
||||||
|
|
||||||
r = map_handle_memory(vmp, region, offset, len, 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(r != OK) {
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
@ -898,6 +898,7 @@ int write;
|
|||||||
physr_start_iter(region->phys, &it, where, AVL_EQUAL); \
|
physr_start_iter(region->phys, &it, where, AVL_EQUAL); \
|
||||||
what = physr_get_iter(&it); \
|
what = physr_get_iter(&it); \
|
||||||
if(!what) vm_panic("thing missing", NO_NUM); \
|
if(!what) vm_panic("thing missing", NO_NUM); \
|
||||||
|
if(what->offset != where) vm_panic("thing wrong", NO_NUM); \
|
||||||
}
|
}
|
||||||
|
|
||||||
FREE_RANGE_HERE(NULL, physr);
|
FREE_RANGE_HERE(NULL, physr);
|
||||||
@ -908,8 +909,8 @@ int write;
|
|||||||
physr_incr_iter(&iter);
|
physr_incr_iter(&iter);
|
||||||
physr = physr_get_iter(&iter);
|
physr = physr_get_iter(&iter);
|
||||||
|
|
||||||
|
FREE_RANGE_HERE(NULL, physr);
|
||||||
if(physr) {
|
if(physr) {
|
||||||
FREE_RANGE_HERE(NULL, physr);
|
|
||||||
RESET_ITER(iter, physr->offset, physr);
|
RESET_ITER(iter, physr->offset, physr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -957,7 +958,11 @@ int write;
|
|||||||
|
|
||||||
SANITYCHECK(SCL_FUNCTIONS);
|
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 SANITYCHECKS
|
||||||
if(OK != pt_checkrange(&vmp->vm_pt, region->vaddr+offset, length, write)) {
|
if(OK != pt_checkrange(&vmp->vm_pt, region->vaddr+offset, length, write)) {
|
||||||
|
@ -8,7 +8,7 @@ OBJ= test1 test2 test3 test4 test5 test6 test7 test8 test9 \
|
|||||||
test21 test22 test23 test25 test26 test27 test28 test29 \
|
test21 test22 test23 test25 test26 test27 test28 test29 \
|
||||||
test30 test31 test32 test34 test35 test36 test37 test38 \
|
test30 test31 test32 test34 test35 test36 test37 test38 \
|
||||||
test39 t10a t11a t11b test40 t40a t40b t40c t40d t40e t40f test41 \
|
test39 t10a t11a t11b test40 t40a t40b t40c t40d t40e t40f test41 \
|
||||||
test42
|
test42 test44
|
||||||
|
|
||||||
BIGOBJ= test20 test24
|
BIGOBJ= test20 test24
|
||||||
ROOTOBJ= test11 test33 test43
|
ROOTOBJ= test11 test33 test43
|
||||||
@ -84,3 +84,4 @@ t40f: t40f.c
|
|||||||
test41: test41.c
|
test41: test41.c
|
||||||
test42: test42.c
|
test42: test42.c
|
||||||
test43: test43.c
|
test43: test43.c
|
||||||
|
test44: test44.c
|
||||||
|
2
test/run
2
test/run
@ -18,7 +18,7 @@ echo " "
|
|||||||
# Run all the tests, keeping track of who failed.
|
# 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 \
|
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 \
|
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`
|
do total=`expr $total + 1`
|
||||||
FAIL=0
|
FAIL=0
|
||||||
if [ $USER = root -a \( $i = 11 -o $i = 33 \) ]
|
if [ $USER = root -a \( $i = 11 -o $i = 33 \) ]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user