1 /* $OpenBSD: mem.c,v 1.24 2024/12/30 02:46:00 guenther Exp $ */ 2 /* $NetBSD: mem.c,v 1.18 2001/04/24 04:31:12 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1988 University of Utah. 6 * Copyright (c) 1982, 1986, 1990, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * the Systems Programming Group of the University of Utah Computer 11 * Science Department. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)mem.c 8.3 (Berkeley) 1/12/94 38 */ 39 40 /* 41 * Memory special file 42 */ 43 44 #include <sys/param.h> 45 #include <sys/buf.h> 46 #include <sys/filio.h> 47 #include <sys/systm.h> 48 #include <sys/uio.h> 49 #include <sys/malloc.h> 50 #include <sys/proc.h> 51 #include <sys/rwlock.h> 52 #include <sys/conf.h> 53 #include <sys/atomic.h> 54 55 #include <machine/conf.h> 56 #include <machine/ctlreg.h> 57 58 #include <uvm/uvm_extern.h> 59 60 vaddr_t prom_vstart = 0xf000000; 61 vaddr_t prom_vend = 0xf0100000; 62 caddr_t zeropage; 63 64 int 65 mmopen(dev_t dev, int flag, int mode, struct proc *p) 66 { 67 extern int allowkmem; 68 69 switch (minor(dev)) { 70 case 0: 71 case 1: 72 if ((int)atomic_load_int(&securelevel) <= 0 || 73 atomic_load_int(&allowkmem)) 74 break; 75 return (EPERM); 76 case 2: 77 case 12: 78 break; 79 default: 80 return (ENXIO); 81 } 82 return (0); 83 } 84 85 int 86 mmclose(dev_t dev, int flag, int mode, struct proc *p) 87 { 88 89 return (0); 90 } 91 92 static struct rwlock physlock = RWLOCK_INITIALIZER("mmrw"); 93 94 int 95 mmrw(dev_t dev, struct uio *uio, int flags) 96 { 97 vaddr_t o, v; 98 size_t c; 99 struct iovec *iov; 100 int error = 0; 101 vm_prot_t prot; 102 extern caddr_t vmmap; 103 104 if (minor(dev) == 0) { 105 /* lock against other uses of shared vmmap */ 106 error = rw_enter(&physlock, RW_WRITE | RW_INTR); 107 if (error) 108 return (error); 109 } 110 while (uio->uio_resid > 0 && error == 0) { 111 int n; 112 iov = uio->uio_iov; 113 if (iov->iov_len == 0) { 114 uio->uio_iov++; 115 uio->uio_iovcnt--; 116 if (uio->uio_iovcnt < 0) 117 panic("mmrw"); 118 continue; 119 } 120 121 /* Note how much is still to go */ 122 n = uio->uio_resid; 123 124 switch (minor(dev)) { 125 126 /* minor device 0 is physical memory */ 127 case 0: 128 v = uio->uio_offset; 129 if (!pmap_pa_exists(v)) { 130 error = EFAULT; 131 goto unlock; 132 } 133 prot = uio->uio_rw == UIO_READ ? PROT_READ : 134 PROT_WRITE; 135 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, 136 trunc_page(v), prot, prot|PMAP_WIRED); 137 pmap_update(pmap_kernel()); 138 o = uio->uio_offset & PGOFSET; 139 c = ulmin(uio->uio_resid, NBPG - o); 140 error = uiomove((caddr_t)vmmap + o, c, uio); 141 pmap_remove(pmap_kernel(), (vaddr_t)vmmap, 142 (vaddr_t)vmmap + NBPG); 143 pmap_update(pmap_kernel()); 144 break; 145 146 /* minor device 1 is kernel memory */ 147 case 1: 148 v = uio->uio_offset; 149 c = ulmin(iov->iov_len, MAXPHYS); 150 if (!uvm_kernacc((caddr_t)v, c, 151 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 152 return (EFAULT); 153 error = uiomove((caddr_t)v, c, uio); 154 break; 155 156 /* minor device 2 is /dev/null */ 157 case 2: 158 if (uio->uio_rw == UIO_WRITE) 159 uio->uio_resid = 0; 160 return (0); 161 162 /* minor device 12 is /dev/zero */ 163 case 12: 164 if (uio->uio_rw == UIO_WRITE) { 165 uio->uio_resid = 0; 166 return(0); 167 } 168 if (zeropage == NULL) 169 zeropage = malloc(NBPG, M_TEMP, 170 M_WAITOK | M_ZERO); 171 c = ulmin(iov->iov_len, NBPG); 172 error = uiomove(zeropage, c, uio); 173 break; 174 175 default: 176 return (ENXIO); 177 } 178 179 /* If we didn't make any progress (i.e. EOF), we're done here */ 180 if (n == uio->uio_resid) 181 break; 182 } 183 if (minor(dev) == 0) { 184 unlock: 185 rw_exit(&physlock); 186 } 187 return (error); 188 } 189 190 paddr_t 191 mmmmap(dev_t dev, off_t off, int prot) 192 { 193 194 return (-1); 195 } 196 197 int 198 mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 199 { 200 switch (cmd) { 201 case FIOASYNC: 202 /* handled by fd layer */ 203 return 0; 204 } 205 206 return (ENOTTY); 207 } 208