Kernel: replace vm_contiguous with vm_lookup_range

This commit is contained in:
David van Moolenbroek 2012-03-21 23:46:51 +01:00
parent 5737b690dc
commit 08af3f672b
3 changed files with 40 additions and 43 deletions

View file

@ -381,7 +381,7 @@ vir_bytes bytes; /* # of bytes to be copied */
/* Now make sure addresses are contiguous in physical memory /* Now make sure addresses are contiguous in physical memory
* so that the umap makes sense. * so that the umap makes sense.
*/ */
if(bytes > 0 && !vm_contiguous(rp, linear, bytes)) { if(bytes > 0 && vm_lookup_range(rp, linear, NULL, bytes) != bytes) {
printf("umap_virtual: %s: %lu at 0x%lx (vir 0x%lx) not contiguous\n", printf("umap_virtual: %s: %lu at 0x%lx (vir 0x%lx) not contiguous\n",
rp->p_name, bytes, linear, vir_addr); rp->p_name, bytes, linear, vir_addr);
return 0; return 0;
@ -453,59 +453,55 @@ PUBLIC int vm_lookup(const struct proc *proc, const vir_bytes virtual,
} }
/*===========================================================================* /*===========================================================================*
* vm_contiguous * * vm_lookup_range *
*===========================================================================*/ *===========================================================================*/
PUBLIC int vm_contiguous(const struct proc *targetproc, vir_bytes vir_buf, size_t bytes) PUBLIC size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr,
phys_bytes *phys_addr, size_t bytes)
{ {
int first = 1, r; /* Look up the physical address corresponding to linear virtual address
phys_bytes prev_phys = 0; /* Keep lints happy. */ * 'vir_addr' for process 'proc'. Return the size of the range covered
u32_t po; * by contiguous physical memory starting from that address; this may
* be anywhere between 0 and 'bytes' inclusive. If the return value is
* nonzero, and 'phys_addr' is non-NULL, 'phys_addr' will be set to the
* base physical address of the range. 'vir_addr' and 'bytes' need not
* be page-aligned, but the caller must have verified that the given
* linear range is valid for the given process at all.
*/
phys_bytes phys, next_phys;
size_t len;
assert(targetproc); assert(proc);
assert(bytes > 0); assert(bytes > 0);
if(!HASPT(targetproc)) if (!HASPT(proc))
return 1; return bytes;
/* Start and end at page boundary to make logic simpler. */ /* Look up the first page. */
po = vir_buf % I386_PAGE_SIZE; if (vm_lookup(proc, vir_addr, &phys, NULL) != OK)
if(po > 0) { return 0;
bytes += po;
vir_buf -= po;
}
po = (vir_buf + bytes) % I386_PAGE_SIZE;
if(po > 0)
bytes += I386_PAGE_SIZE - po;
/* Keep going as long as we cross a page boundary. */ if (phys_addr != NULL)
while(bytes > 0) { *phys_addr = phys;
phys_bytes phys;
if((r=vm_lookup(targetproc, vir_buf, &phys, NULL)) != OK) { len = I386_PAGE_SIZE - (vir_addr % I386_PAGE_SIZE);
printf("vm_contiguous: vm_lookup failed, %d\n", r); vir_addr += len;
printf("kernel stack: "); next_phys = phys + len;
util_stacktrace();
return 0;
}
if(!first) { /* Look up any next pages and test physical contiguity. */
if(prev_phys+I386_PAGE_SIZE != phys) { while (len < bytes) {
printf("vm_contiguous: no (0x%lx, 0x%lx)\n", if (vm_lookup(proc, vir_addr, &phys, NULL) != OK)
prev_phys, phys); break;
printf("kernel stack: ");
util_stacktrace();
return 0;
}
}
first = 0; if (next_phys != phys)
break;
prev_phys = phys; len += I386_PAGE_SIZE;
vir_buf += I386_PAGE_SIZE; vir_addr += I386_PAGE_SIZE;
bytes -= I386_PAGE_SIZE; next_phys += I386_PAGE_SIZE;
} }
return 1; /* We might now have overshot the requested length somewhat. */
return MIN(bytes, len);
} }
/*===========================================================================* /*===========================================================================*

View file

@ -207,9 +207,10 @@ _PROTOTYPE( void arch_pre_exec, (struct proc *pr, u32_t, u32_t));
_PROTOTYPE( int arch_umap, (const struct proc *pr, vir_bytes, vir_bytes, _PROTOTYPE( int arch_umap, (const struct proc *pr, vir_bytes, vir_bytes,
int, phys_bytes *)); int, phys_bytes *));
_PROTOTYPE( int arch_do_vmctl, (message *m_ptr, struct proc *p)); _PROTOTYPE( int arch_do_vmctl, (message *m_ptr, struct proc *p));
_PROTOTYPE( int vm_contiguous, (const struct proc *targetproc, vir_bytes vir_buf, size_t count));
_PROTOTYPE( void proc_stacktrace, (struct proc *proc) ); _PROTOTYPE( void proc_stacktrace, (struct proc *proc) );
_PROTOTYPE( int vm_lookup, (const struct proc *proc, vir_bytes virtual, phys_bytes *result, u32_t *ptent)); _PROTOTYPE( int vm_lookup, (const struct proc *proc, vir_bytes virtual, phys_bytes *result, u32_t *ptent));
_PROTOTYPE( size_t vm_lookup_range, (const struct proc *proc,
vir_bytes vir_addr, phys_bytes *phys_addr, size_t bytes) );
_PROTOTYPE( void delivermsg, (struct proc *target)); _PROTOTYPE( void delivermsg, (struct proc *target));
_PROTOTYPE( void arch_do_syscall, (struct proc *proc) ); _PROTOTYPE( void arch_do_syscall, (struct proc *proc) );
_PROTOTYPE( int arch_phys_map, (int index, phys_bytes *addr, _PROTOTYPE( int arch_phys_map, (int index, phys_bytes *addr,

View file

@ -111,7 +111,7 @@ PUBLIC int do_umap_remote(struct proc * caller, message * m_ptr)
phys_addr = lin_addr; phys_addr = lin_addr;
} }
if(vm_running && !vm_contiguous(targetpr, lin_addr, count)) { if(vm_running && vm_lookup_range(targetpr, lin_addr, NULL, count) != count) {
printf("SYSTEM:do_umap: not contiguous\n"); printf("SYSTEM:do_umap: not contiguous\n");
return EFAULT; return EFAULT;
} }