Do not use pmap_kextract() to find out the physical address of a user

belong to a user virtual address; while this happens to work on some
architectures, it can't on sparc64, since user and kernel virtual
address spaces overlap there (the distinction between them is done via
separate address space identifiers).

Instead, look up the page in the vm_map of the process in question.

Reviewed by:	jake
This commit is contained in:
tmm 2002-04-12 19:38:41 +00:00
parent 389e1779ff
commit 1720bac84c

View File

@ -599,9 +599,16 @@ pipe_build_write_buffer(wpipe, uio)
struct pipe *wpipe;
struct uio *uio;
{
vm_map_t map;
vm_map_entry_t me;
vm_object_t obj;
vm_pindex_t pidx;
vm_prot_t prot;
vm_page_t m;
boolean_t wired;
u_int size;
int i;
vm_offset_t addr, endaddr, paddr;
int i, rv;
vm_offset_t addr, endaddr;
GIANT_REQUIRED;
PIPE_LOCK_ASSERT(wpipe, MA_NOTOWNED);
@ -613,19 +620,23 @@ pipe_build_write_buffer(wpipe, uio)
endaddr = round_page((vm_offset_t)uio->uio_iov->iov_base + size);
addr = trunc_page((vm_offset_t)uio->uio_iov->iov_base);
for (i = 0; addr < endaddr; addr += PAGE_SIZE, i++) {
vm_page_t m;
map = &curproc->p_vmspace->vm_map;
rv = KERN_FAILURE;
if (vm_fault_quick((caddr_t)addr, VM_PROT_READ) < 0 ||
(paddr = pmap_kextract(addr)) == 0) {
(rv = vm_map_lookup(&map, addr, VM_PROT_READ, &me, &obj,
&pidx, &prot, &wired)) != KERN_SUCCESS ||
(m = vm_page_lookup(obj, pidx)) == NULL) {
int j;
if (rv == KERN_SUCCESS)
vm_map_lookup_done(map, me);
for (j = 0; j < i; j++)
vm_page_unwire(wpipe->pipe_map.ms[j], 1);
return (EFAULT);
}
m = PHYS_TO_VM_PAGE(paddr);
vm_page_wire(m);
vm_map_lookup_done(map, me);
wpipe->pipe_map.ms[i] = m;
}