From: Cristiano Giuffrida Date: Tue, 20 Jul 2010 02:08:28 +0000 (+0000) Subject: Generalize interface of some VM functions X-Git-Tag: v3.1.8~186 X-Git-Url: http://zhaoyanbai.com/repos/man.genrandom.html?a=commitdiff_plain;h=1b7d95df29536643a25c51cd3813fd1c88c80209;p=minix.git Generalize interface of some VM functions --- diff --git a/servers/vm/arch/i386/pagetable.c b/servers/vm/arch/i386/pagetable.c index 8b8a4c426..9c836e279 100644 --- a/servers/vm/arch/i386/pagetable.c +++ b/servers/vm/arch/i386/pagetable.c @@ -456,6 +456,48 @@ PRIVATE int pt_ptalloc(pt_t *pt, int pde, u32_t flags) return OK; } +/*===========================================================================* + * pt_ptalloc_in_range * + *===========================================================================*/ +PUBLIC int pt_ptalloc_in_range(pt_t *pt, vir_bytes start, vir_bytes end, + u32_t flags, int verify) +{ +/* Allocate all the page tables in the range specified. */ + int pde, first_pde, last_pde; + + first_pde = start ? I386_VM_PDE(start) : proc_pde; + last_pde = end ? I386_VM_PDE(end) : I386_VM_DIR_ENTRIES - 1; + assert(first_pde >= proc_pde && first_pde <= last_pde); + assert(last_pde < I386_VM_DIR_ENTRIES); + + /* Scan all page-directory entries in the range. */ + for(pde = first_pde; pde <= last_pde; pde++) { + assert(!(pt->pt_dir[pde] & I386_VM_BIGPAGE)); + if(!(pt->pt_dir[pde] & I386_VM_PRESENT)) { + int r; + if(verify) { + printf("pt_ptalloc_in_range: no pde %d\n", pde); + return EFAULT; + } + assert(!pt->pt_dir[pde]); + if((r=pt_ptalloc(pt, pde, flags)) != OK) { + /* Couldn't do (complete) mapping. + * Don't bother freeing any previously + * allocated page tables, they're + * still writable, don't point to nonsense, + * and pt_ptalloc leaves the directory + * and other data in a consistent state. + */ + printf("pt_ptalloc_in_range: pt_ptalloc failed\n"); + return r; + } + } + assert(pt->pt_dir[pde] & I386_VM_PRESENT); + } + + return OK; +} + PRIVATE char *ptestr(u32_t pte) { #define FLAG(constant, name) { \ @@ -490,8 +532,7 @@ PUBLIC int pt_writemap(pt_t *pt, vir_bytes v, phys_bytes physaddr, { /* Write mapping into page table. Allocate a new page table if necessary. */ /* Page directory and table entries for this virtual address. */ - int p, pages, pdecheck; - int finalpde; + int p, r, pages; int verify = 0; if(writemapflags & WMF_VERIFY) @@ -509,36 +550,13 @@ PUBLIC int pt_writemap(pt_t *pt, vir_bytes v, phys_bytes physaddr, assert(physaddr == MAP_NONE || (flags & I386_VM_PRESENT)); assert(physaddr != MAP_NONE || !flags); - finalpde = I386_VM_PDE(v + I386_PAGE_SIZE * pages); - /* First make sure all the necessary page tables are allocated, * before we start writing in any of them, because it's a pain - * to undo our work properly. Walk the range in page-directory-entry - * sized leaps. + * to undo our work properly. */ - for(pdecheck = I386_VM_PDE(v); pdecheck <= finalpde; pdecheck++) { - assert(pdecheck >= 0 && pdecheck < I386_VM_DIR_ENTRIES); - assert(!(pt->pt_dir[pdecheck] & I386_VM_BIGPAGE)); - if(!(pt->pt_dir[pdecheck] & I386_VM_PRESENT)) { - int r; - if(verify) { - printf("pt_writemap verify: no pde %d\n", pdecheck); - return EFAULT; - } - assert(!pt->pt_dir[pdecheck]); - if((r=pt_ptalloc(pt, pdecheck, flags)) != OK) { - /* Couldn't do (complete) mapping. - * Don't bother freeing any previously - * allocated page tables, they're - * still writable, don't point to nonsense, - * and pt_ptalloc leaves the directory - * and other data in a consistent state. - */ - printf("pt_writemap: pt_ptalloc failed\n"); - return r; - } - } - assert(pt->pt_dir[pdecheck] & I386_VM_PRESENT); + r = pt_ptalloc_in_range(pt, v, v + I386_PAGE_SIZE*pages, flags, verify); + if(r != OK) { + return r; } /* Now write in them. */ diff --git a/servers/vm/proto.h b/servers/vm/proto.h index 0c52d3510..e19b202ce 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -100,6 +100,8 @@ _PROTOTYPE( void pt_init, (phys_bytes limit) ); _PROTOTYPE( void pt_check, (struct vmproc *vmp) ); _PROTOTYPE( int pt_new, (pt_t *pt) ); _PROTOTYPE( void pt_free, (pt_t *pt) ); +_PROTOTYPE( int pt_ptalloc_in_range, (pt_t *pt, vir_bytes start, vir_bytes end, + u32_t flags, int verify)); _PROTOTYPE( int pt_writemap, (pt_t *pt, vir_bytes v, phys_bytes physaddr, size_t bytes, u32_t flags, u32_t writemapflags)); _PROTOTYPE( int pt_checkrange, (pt_t *pt, vir_bytes v, size_t bytes, int write)); @@ -138,6 +140,8 @@ _PROTOTYPE(int map_region_shrink,(struct vir_region *vr, vir_bytes delta)); _PROTOTYPE(int map_unmap_region,(struct vmproc *vmp, struct vir_region *vr, vir_bytes len)); _PROTOTYPE(int map_free_proc,(struct vmproc *vmp)); _PROTOTYPE(int map_proc_copy,(struct vmproc *dst, struct vmproc *src)); +_PROTOTYPE(int map_proc_copy_from,(struct vmproc *dst, struct vmproc *src, + struct vir_region *start_src_vr)); _PROTOTYPE(struct vir_region *map_lookup,(struct vmproc *vmp, vir_bytes addr)); _PROTOTYPE(int map_pf,(struct vmproc *vmp, struct vir_region *region, vir_bytes offset, int write)); diff --git a/servers/vm/region.c b/servers/vm/region.c index 54d704908..2b6c67d9d 100644 --- a/servers/vm/region.c +++ b/servers/vm/region.c @@ -1421,19 +1421,38 @@ PUBLIC int map_writept(struct vmproc *vmp) } /*========================================================================* - * map_proc_copy * + * map_proc_copy * *========================================================================*/ PUBLIC int map_proc_copy(dst, src) struct vmproc *dst; struct vmproc *src; { - struct vir_region *vr, *prevvr = NULL; +/* Copy all the memory regions from the src process to the dst process. */ dst->vm_regions = NULL; - SANITYCHECK(SCL_FUNCTIONS); + return map_proc_copy_from(dst, src, src->vm_regions); +} + +/*========================================================================* + * map_proc_copy_from * + *========================================================================*/ +PUBLIC int map_proc_copy_from(dst, src, start_src_vr) +struct vmproc *dst; +struct vmproc *src; +struct vir_region *start_src_vr; +{ + struct vir_region *vr, *prevvr = NULL; + + assert(start_src_vr->parent == src); + /* Copy source regions after the destination's last region (if any). */ + for(vr = dst->vm_regions; vr; vr = vr->next) { + prevvr = vr; + } + + SANITYCHECK(SCL_FUNCTIONS); - for(vr = src->vm_regions; vr; vr = vr->next) { + for(vr = start_src_vr; vr; vr = vr->next) { physr_iter iter_orig, iter_new; struct vir_region *newvr; struct phys_region *orig_ph, *new_ph;