1 /* $OpenBSD: mem.c,v 1.38 2024/12/30 02:46:00 guenther Exp $ */ 2 /* $NetBSD: mem.c,v 1.26 2000/03/29 03:48:20 simonb 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/proc.h> 49 #include <sys/uio.h> 50 #include <sys/malloc.h> 51 #include <sys/msgbuf.h> 52 #include <sys/mman.h> 53 #include <sys/conf.h> 54 #include <sys/atomic.h> 55 56 #include <machine/cpu.h> 57 58 #include <uvm/uvm_extern.h> 59 60 #define mmread mmrw 61 #define mmwrite mmrw 62 cdev_decl(mm); 63 64 caddr_t zeropage; 65 66 /* open counter for aperture */ 67 #ifdef APERTURE 68 static int ap_open_count = 0; 69 extern int allowaperture; 70 #endif 71 72 int 73 mmopen(dev_t dev, int flag, int mode, struct proc *p) 74 { 75 extern int allowkmem; 76 77 switch (minor(dev)) { 78 case 0: 79 case 1: 80 if ((int)atomic_load_int(&securelevel) <= 0 || 81 atomic_load_int(&allowkmem)) 82 break; 83 return (EPERM); 84 case 2: 85 case 12: 86 break; 87 #ifdef APERTURE 88 case 4: 89 if (suser(p) != 0 || !allowaperture) 90 return (EPERM); 91 92 /* authorize only one simultaneous open() unless 93 * allowaperture=3 */ 94 if (ap_open_count > 0 && allowaperture < 3) 95 return (EPERM); 96 ap_open_count++; 97 break; 98 #endif 99 default: 100 return (ENXIO); 101 } 102 return (0); 103 } 104 105 int 106 mmclose(dev_t dev, int flag, int mode, struct proc *p) 107 { 108 109 #ifdef APERTURE 110 if (minor(dev) == 4) 111 ap_open_count = 0; 112 #endif 113 return (0); 114 } 115 116 int 117 mmrw(dev_t dev, struct uio *uio, int flags) 118 { 119 vaddr_t o, v; 120 size_t c; 121 struct iovec *iov; 122 int error = 0, rw; 123 extern int msgbufmapped; 124 125 while (uio->uio_resid > 0 && !error) { 126 iov = uio->uio_iov; 127 if (iov->iov_len == 0) { 128 uio->uio_iov++; 129 uio->uio_iovcnt--; 130 if (uio->uio_iovcnt < 0) 131 panic("mmrw"); 132 continue; 133 } 134 switch (minor(dev)) { 135 136 /* minor device 0 is physical memory */ 137 case 0: 138 v = uio->uio_offset; 139 kmemphys: 140 if (v >= ALPHA_K0SEG_TO_PHYS((vaddr_t)msgbufp)) { 141 if (msgbufmapped == 0) { 142 printf("Message Buf not Mapped\n"); 143 error = EFAULT; 144 break; 145 } 146 } 147 148 /* Allow reads only in RAM. */ 149 rw = (uio->uio_rw == UIO_READ) ? PROT_READ : PROT_WRITE; 150 if ((alpha_pa_access(v) & rw) != rw) { 151 error = EFAULT; 152 break; 153 } 154 155 o = uio->uio_offset & PGOFSET; 156 c = ulmin(uio->uio_resid, PAGE_SIZE - o); 157 error = 158 uiomove((caddr_t)ALPHA_PHYS_TO_K0SEG(v), c, uio); 159 break; 160 161 /* minor device 1 is kernel memory */ 162 case 1: 163 v = uio->uio_offset; 164 165 if (v >= ALPHA_K0SEG_BASE && v <= ALPHA_K0SEG_END) { 166 v = ALPHA_K0SEG_TO_PHYS(v); 167 goto kmemphys; 168 } 169 170 c = ulmin(iov->iov_len, MAXPHYS); 171 if (!uvm_kernacc((caddr_t)v, c, 172 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 173 return (EFAULT); 174 error = uiomove((caddr_t)v, c, uio); 175 break; 176 177 /* minor device 2 is /dev/null */ 178 case 2: 179 if (uio->uio_rw == UIO_WRITE) 180 uio->uio_resid = 0; 181 return (0); 182 183 /* minor device 12 is /dev/zero */ 184 case 12: 185 if (uio->uio_rw == UIO_WRITE) { 186 uio->uio_resid = 0; 187 return (0); 188 } 189 /* 190 * On the first call, allocate and zero a page 191 * of memory for use with /dev/zero. 192 */ 193 if (zeropage == NULL) 194 zeropage = malloc(PAGE_SIZE, M_TEMP, 195 M_WAITOK | M_ZERO); 196 c = ulmin(iov->iov_len, PAGE_SIZE); 197 error = uiomove(zeropage, c, uio); 198 break; 199 200 default: 201 return (ENXIO); 202 } 203 } 204 return (error); 205 } 206 207 paddr_t 208 mmmmap(dev_t dev, off_t off, int prot) 209 { 210 switch (minor(dev)) { 211 case 0: 212 /* 213 * /dev/mem is the only one that makes sense through this 214 * interface. For /dev/kmem any physaddr we return here 215 * could be transient and hence incorrect or invalid at 216 * a later time. /dev/null just doesn't make any sense 217 * and /dev/zero is a hack that is handled via the default 218 * pager in mmap(). 219 */ 220 221 /* 222 * Allow access only in RAM. 223 */ 224 if ((prot & alpha_pa_access(atop(off))) != prot) 225 return (-1); 226 return off; 227 228 #ifdef APERTURE 229 case 4: 230 /* minor device 4 is aperture driver */ 231 switch (allowaperture) { 232 case 1: 233 if ((prot & alpha_pa_access(atop(off))) != prot) 234 return (-1); 235 return off; 236 default: 237 return -1; 238 } 239 #endif 240 default: 241 return -1; 242 } 243 } 244 245 int 246 mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 247 { 248 switch (cmd) { 249 case FIOASYNC: 250 /* handled by fd layer */ 251 return 0; 252 } 253 254 return (ENOTTY); 255 } 256