]> Zhao Yanbai Git Server - minix.git/commitdiff
Generalize interface of some VM functions
authorCristiano Giuffrida <cristiano@minix3.org>
Tue, 20 Jul 2010 02:08:28 +0000 (02:08 +0000)
committerCristiano Giuffrida <cristiano@minix3.org>
Tue, 20 Jul 2010 02:08:28 +0000 (02:08 +0000)
servers/vm/arch/i386/pagetable.c
servers/vm/proto.h
servers/vm/region.c

index 8b8a4c42647e17032c46140fabb5124e23d06a96..9c836e279fcc478f1fc0ae7e543df3e2a0ab3c5f 100644 (file)
@@ -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. */
index 0c52d35103a5e9452777bce3edcc77a0592c1b2e..e19b202ced1ae96712cfe508f94485132dfed076 100644 (file)
@@ -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));
index 54d70490858d767602f625b834531b09d7e69772..2b6c67d9dfbc386d63e5c40c08c3ab309ca6be85 100644 (file)
@@ -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;