Generalize interface of some VM functions

This commit is contained in:
Cristiano Giuffrida 2010-07-20 02:08:28 +00:00
parent af424b4e43
commit 1b7d95df29
3 changed files with 74 additions and 33 deletions

View 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. */

View 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));

View 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;
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;