Kernel: replace vm_contiguous with vm_lookup_range
This commit is contained in:
parent
5737b690dc
commit
08af3f672b
|
@ -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) {
|
|
||||||
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. */
|
|
||||||
while(bytes > 0) {
|
|
||||||
phys_bytes phys;
|
|
||||||
|
|
||||||
if((r=vm_lookup(targetproc, vir_buf, &phys, NULL)) != OK) {
|
|
||||||
printf("vm_contiguous: vm_lookup failed, %d\n", r);
|
|
||||||
printf("kernel stack: ");
|
|
||||||
util_stacktrace();
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (phys_addr != NULL)
|
||||||
|
*phys_addr = phys;
|
||||||
|
|
||||||
|
len = I386_PAGE_SIZE - (vir_addr % I386_PAGE_SIZE);
|
||||||
|
vir_addr += len;
|
||||||
|
next_phys = phys + len;
|
||||||
|
|
||||||
|
/* Look up any next pages and test physical contiguity. */
|
||||||
|
while (len < bytes) {
|
||||||
|
if (vm_lookup(proc, vir_addr, &phys, NULL) != OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (next_phys != phys)
|
||||||
|
break;
|
||||||
|
|
||||||
|
len += I386_PAGE_SIZE;
|
||||||
|
vir_addr += I386_PAGE_SIZE;
|
||||||
|
next_phys += I386_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!first) {
|
/* We might now have overshot the requested length somewhat. */
|
||||||
if(prev_phys+I386_PAGE_SIZE != phys) {
|
return MIN(bytes, len);
|
||||||
printf("vm_contiguous: no (0x%lx, 0x%lx)\n",
|
|
||||||
prev_phys, phys);
|
|
||||||
printf("kernel stack: ");
|
|
||||||
util_stacktrace();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
first = 0;
|
|
||||||
|
|
||||||
prev_phys = phys;
|
|
||||||
vir_buf += I386_PAGE_SIZE;
|
|
||||||
bytes -= I386_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue