1 /* $OpenBSD: mem.c,v 1.27 2024/12/30 02:46:00 guenther Exp $ */ 2 /* $NetBSD: mem.c,v 1.11 2003/10/16 12:02:58 jdolecek Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 /* 37 * Copyright (c) 1988 University of Utah. 38 * 39 * This code is derived from software contributed to Berkeley by 40 * the Systems Programming Group of the University of Utah Computer 41 * Science Department. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by the University of 54 * California, Berkeley and its contributors. 55 * 4. Neither the name of the University nor the names of its contributors 56 * may be used to endorse or promote products derived from this software 57 * without specific prior written permission. 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 */ 71 72 /* 73 * Memory special file 74 */ 75 76 #include <sys/param.h> 77 #include <sys/buf.h> 78 #include <sys/filio.h> 79 #include <sys/systm.h> 80 #include <sys/uio.h> 81 #include <sys/malloc.h> 82 #include <sys/rwlock.h> 83 #include <sys/atomic.h> 84 85 #include <arm/conf.h> 86 87 #include <uvm/uvm_extern.h> 88 89 extern char *memhook; /* poor name! */ 90 caddr_t zeropage; 91 92 /* open counter for aperture */ 93 #ifdef APERTURE 94 static int ap_open_count = 0; 95 extern int allowaperture; 96 #endif 97 98 99 int 100 mmopen(dev_t dev, int flag, int mode, struct proc *p) 101 { 102 extern int allowkmem; 103 104 switch (minor(dev)) { 105 case 0: 106 case 1: 107 if ((int)atomic_load_int(&securelevel) <= 0 || 108 atomic_load_int(&allowkmem)) 109 break; 110 return (EPERM); 111 case 2: 112 case 12: 113 break; 114 #ifdef APERTURE 115 case 4: 116 if (suser(p) != 0 || !allowaperture) 117 return (EPERM); 118 119 /* authorize only one simultaneous open() unless 120 * allowaperture=3 */ 121 if (ap_open_count > 0 && allowaperture < 3) 122 return (EPERM); 123 ap_open_count++; 124 break; 125 #endif 126 default: 127 return (ENXIO); 128 } 129 return (0); 130 } 131 132 int 133 mmclose(dev_t dev, int flag, int mode, struct proc *p) 134 { 135 #ifdef APERTURE 136 if (minor(dev) == 4) 137 ap_open_count = 0; 138 #endif 139 return (0); 140 } 141 142 static struct rwlock physlock = RWLOCK_INITIALIZER("mmrw"); 143 144 int 145 mmrw(dev_t dev, struct uio *uio, int flags) 146 { 147 vaddr_t o, v; 148 size_t c; 149 struct iovec *iov; 150 int error = 0; 151 vm_prot_t prot; 152 153 if (minor(dev) == 0) { 154 /* lock against other uses of shared vmmap */ 155 error = rw_enter(&physlock, RW_WRITE | RW_INTR); 156 if (error) 157 return (error); 158 159 } 160 while (uio->uio_resid > 0 && error == 0) { 161 iov = uio->uio_iov; 162 if (iov->iov_len == 0) { 163 uio->uio_iov++; 164 uio->uio_iovcnt--; 165 if (uio->uio_iovcnt < 0) 166 panic("mmrw"); 167 continue; 168 } 169 switch (minor(dev)) { 170 171 case 0: 172 v = uio->uio_offset; 173 prot = uio->uio_rw == UIO_READ ? PROT_READ : 174 PROT_WRITE; 175 pmap_enter(pmap_kernel(), (vaddr_t)memhook, 176 trunc_page(v), prot, prot|PMAP_WIRED); 177 pmap_update(pmap_kernel()); 178 o = uio->uio_offset & PGOFSET; 179 c = ulmin(uio->uio_resid, PAGE_SIZE - o); 180 error = uiomove((caddr_t)memhook + o, c, uio); 181 pmap_remove(pmap_kernel(), (vaddr_t)memhook, 182 (vaddr_t)memhook + PAGE_SIZE); 183 pmap_update(pmap_kernel()); 184 break; 185 186 case 1: 187 v = uio->uio_offset; 188 c = ulmin(iov->iov_len, MAXPHYS); 189 if (!uvm_kernacc((caddr_t)v, c, 190 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 191 return (EFAULT); 192 error = uiomove((caddr_t)v, c, uio); 193 break; 194 195 case 2: 196 if (uio->uio_rw == UIO_WRITE) 197 uio->uio_resid = 0; 198 return (0); 199 200 case 12: 201 if (uio->uio_rw == UIO_WRITE) { 202 uio->uio_resid = 0; 203 return (0); 204 } 205 if (zeropage == NULL) 206 zeropage = malloc(PAGE_SIZE, M_TEMP, 207 M_WAITOK | M_ZERO); 208 c = ulmin(iov->iov_len, PAGE_SIZE); 209 error = uiomove(zeropage, c, uio); 210 break; 211 212 default: 213 return (ENXIO); 214 } 215 } 216 if (minor(dev) == 0) { 217 rw_exit(&physlock); 218 } 219 return (error); 220 } 221 222 paddr_t 223 mmmmap(dev_t dev, off_t off, int prot) 224 { 225 struct proc *p = curproc; /* XXX */ 226 227 /* 228 * /dev/mem is the only one that makes sense through this 229 * interface. For /dev/kmem any physaddr we return here 230 * could be transient and hence incorrect or invalid at 231 * a later time. /dev/null just doesn't make any sense 232 * and /dev/zero is a hack that is handled via the default 233 * pager in mmap(). 234 */ 235 if (minor(dev) != 0) 236 return (-1); 237 238 /* minor device 0 is physical memory */ 239 240 if ((paddr_t)off >= ptoa((paddr_t)physmem) && 241 suser(p) != 0) 242 return -1; 243 return off; 244 } 245 246 int 247 mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 248 { 249 switch (cmd) { 250 case FIOASYNC: 251 /* handled by fd layer */ 252 return 0; 253 } 254 255 return (ENOTTY); 256 } 257