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) { \
{
/* 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)
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. */
_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));
_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));
}
/*========================================================================*
- * 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;