Home | History | Annotate | Line # | Download | only in usermode
      1 /* $NetBSD: vm_machdep.c,v 1.5 2018/01/24 09:04:45 skrll Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2007 Jared D. McNeill <jmcneill (at) invisible.ca>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.5 2018/01/24 09:04:45 skrll Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/buf.h>
     34 #include <sys/proc.h>
     35 
     36 #include <uvm/uvm_extern.h>
     37 
     38 
     39 /*
     40  * Map a user I/O request into kernel virtual address space.
     41  * Note: the pages are already locked by uvm_vslock(), so we
     42  * do not need to pass an access_type to pmap_enter().
     43  */
     44 /* This code was originally stolen from the alpha port. */
     45 
     46 int
     47 vmapbuf(struct buf *bp, vsize_t len)
     48 {
     49 	vaddr_t faddr, taddr, off;
     50 	paddr_t pa;
     51 	struct proc *p;
     52 	vm_prot_t prot;
     53 
     54 	if ((bp->b_flags & B_PHYS) == 0)
     55 		panic("vmapbuf");
     56 	p = bp->b_proc;
     57 	bp->b_saveaddr = bp->b_data;
     58 	faddr = trunc_page((vaddr_t)bp->b_data);
     59 	off = (vaddr_t)bp->b_data - faddr;
     60 	len = round_page(off + len);
     61 	taddr = uvm_km_alloc(phys_map, len, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA);
     62 	bp->b_data = (void *)(taddr + off);
     63 	len = atop(len);
     64 	prot = bp->b_flags & B_READ ? VM_PROT_READ | VM_PROT_WRITE :
     65 				      VM_PROT_READ;
     66 	while (len--) {
     67 		if (pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map), faddr,
     68 		    &pa) == false)
     69 			panic("vmapbuf: null page frame");
     70 		pmap_enter(vm_map_pmap(phys_map), taddr, trunc_page(pa),
     71 		    prot, prot | PMAP_WIRED);
     72 		faddr += PAGE_SIZE;
     73 		taddr += PAGE_SIZE;
     74 	}
     75 	pmap_update(vm_map_pmap(phys_map));
     76 
     77 	return 0;
     78 }
     79 
     80 /*
     81  * Unmap a previously-mapped user I/O request.
     82  */
     83 void
     84 vunmapbuf(struct buf *bp, vsize_t len)
     85 {
     86 	vaddr_t addr, off;
     87 
     88 	if ((bp->b_flags & B_PHYS) == 0)
     89 		panic("vunmapbuf");
     90 	addr = trunc_page((vaddr_t)bp->b_data);
     91 	off = (vaddr_t)bp->b_data - addr;
     92 	len = round_page(off + len);
     93 	pmap_remove(vm_map_pmap(phys_map), addr, addr + len);
     94 	pmap_update(vm_map_pmap(phys_map));
     95 	uvm_km_free(phys_map, addr, len, UVM_KMF_VAONLY);
     96 	bp->b_data = bp->b_saveaddr;
     97 	bp->b_saveaddr = NULL;
     98 }
     99 
    100