Generalize interface of some VM functions
This commit is contained in:
parent
af424b4e43
commit
1b7d95df29
3 changed files with 74 additions and 33 deletions
|
@ -456,6 +456,48 @@ PRIVATE int pt_ptalloc(pt_t *pt, int pde, u32_t flags)
|
||||||
return OK;
|
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)
|
PRIVATE char *ptestr(u32_t pte)
|
||||||
{
|
{
|
||||||
#define FLAG(constant, name) { \
|
#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. */
|
/* Write mapping into page table. Allocate a new page table if necessary. */
|
||||||
/* Page directory and table entries for this virtual address. */
|
/* Page directory and table entries for this virtual address. */
|
||||||
int p, pages, pdecheck;
|
int p, r, pages;
|
||||||
int finalpde;
|
|
||||||
int verify = 0;
|
int verify = 0;
|
||||||
|
|
||||||
if(writemapflags & WMF_VERIFY)
|
if(writemapflags & WMF_VERIFY)
|
||||||
|
@ -509,37 +550,14 @@ 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 & I386_VM_PRESENT));
|
||||||
assert(physaddr != MAP_NONE || !flags);
|
assert(physaddr != MAP_NONE || !flags);
|
||||||
|
|
||||||
finalpde = I386_VM_PDE(v + I386_PAGE_SIZE * pages);
|
|
||||||
|
|
||||||
/* First make sure all the necessary page tables are allocated,
|
/* First make sure all the necessary page tables are allocated,
|
||||||
* before we start writing in any of them, because it's a pain
|
* 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
|
* to undo our work properly.
|
||||||
* sized leaps.
|
|
||||||
*/
|
*/
|
||||||
for(pdecheck = I386_VM_PDE(v); pdecheck <= finalpde; pdecheck++) {
|
r = pt_ptalloc_in_range(pt, v, v + I386_PAGE_SIZE*pages, flags, verify);
|
||||||
assert(pdecheck >= 0 && pdecheck < I386_VM_DIR_ENTRIES);
|
if(r != OK) {
|
||||||
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;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
assert(pt->pt_dir[pdecheck] & I386_VM_PRESENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now write in them. */
|
/* Now write in them. */
|
||||||
for(p = 0; p < pages; p++) {
|
for(p = 0; p < pages; p++) {
|
||||||
|
|
|
@ -100,6 +100,8 @@ _PROTOTYPE( void pt_init, (phys_bytes limit) );
|
||||||
_PROTOTYPE( void pt_check, (struct vmproc *vmp) );
|
_PROTOTYPE( void pt_check, (struct vmproc *vmp) );
|
||||||
_PROTOTYPE( int pt_new, (pt_t *pt) );
|
_PROTOTYPE( int pt_new, (pt_t *pt) );
|
||||||
_PROTOTYPE( void pt_free, (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,
|
_PROTOTYPE( int pt_writemap, (pt_t *pt, vir_bytes v, phys_bytes physaddr,
|
||||||
size_t bytes, u32_t flags, u32_t writemapflags));
|
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 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_unmap_region,(struct vmproc *vmp, struct vir_region *vr, vir_bytes len));
|
||||||
_PROTOTYPE(int map_free_proc,(struct vmproc *vmp));
|
_PROTOTYPE(int map_free_proc,(struct vmproc *vmp));
|
||||||
_PROTOTYPE(int map_proc_copy,(struct vmproc *dst, struct vmproc *src));
|
_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(struct vir_region *map_lookup,(struct vmproc *vmp, vir_bytes addr));
|
||||||
_PROTOTYPE(int map_pf,(struct vmproc *vmp,
|
_PROTOTYPE(int map_pf,(struct vmproc *vmp,
|
||||||
struct vir_region *region, vir_bytes offset, int write));
|
struct vir_region *region, vir_bytes offset, int write));
|
||||||
|
|
|
@ -1427,13 +1427,32 @@ PUBLIC int map_proc_copy(dst, src)
|
||||||
struct vmproc *dst;
|
struct vmproc *dst;
|
||||||
struct vmproc *src;
|
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;
|
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);
|
SANITYCHECK(SCL_FUNCTIONS);
|
||||||
|
|
||||||
|
for(vr = start_src_vr; vr; vr = vr->next) {
|
||||||
for(vr = src->vm_regions; vr; vr = vr->next) {
|
|
||||||
physr_iter iter_orig, iter_new;
|
physr_iter iter_orig, iter_new;
|
||||||
struct vir_region *newvr;
|
struct vir_region *newvr;
|
||||||
struct phys_region *orig_ph, *new_ph;
|
struct phys_region *orig_ph, *new_ph;
|
||||||
|
|
Loading…
Reference in a new issue