1 /* $OpenBSD: mem.c,v 1.28 2024/12/30 02:46:00 guenther Exp $ */ 2 /* $NetBSD: mem.c,v 1.6 1995/04/10 11:55:03 mycroft 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 and Ralph Campbell. 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. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)mem.c 8.3 (Berkeley) 1/12/94 42 */ 43 44 /* 45 * Memory special file 46 */ 47 48 #include <sys/param.h> 49 #include <sys/conf.h> 50 #include <sys/buf.h> 51 #include <sys/filio.h> 52 #include <sys/proc.h> 53 #include <sys/msgbuf.h> 54 #include <sys/systm.h> 55 #include <sys/uio.h> 56 #include <sys/malloc.h> 57 #include <sys/atomic.h> 58 59 #include <machine/autoconf.h> 60 #include <machine/cpu.h> 61 #include <machine/memconf.h> 62 63 #include <uvm/uvm_extern.h> 64 65 int is_memory_range(paddr_t, psize_t, psize_t); 66 67 caddr_t zeropage; 68 69 #define mmread mmrw 70 #define mmwrite mmrw 71 cdev_decl(mm); 72 73 int 74 mmopen(dev_t dev, int flag, int mode, struct proc *p) 75 { 76 extern int allowkmem; 77 78 switch (minor(dev)) { 79 case 0: 80 case 1: 81 if ((int)atomic_load_int(&securelevel) <= 0 || 82 atomic_load_int(&allowkmem)) 83 break; 84 return (EPERM); 85 case 2: 86 case 12: 87 break; 88 default: 89 return (ENXIO); 90 } 91 return (0); 92 } 93 94 int 95 mmclose(dev_t dev, int flag, int mode, struct proc *p) 96 { 97 return (0); 98 } 99 100 int 101 mmrw(dev_t dev, struct uio *uio, int flags) 102 { 103 struct iovec *iov; 104 int allowed; 105 int error = 0; 106 size_t c; 107 vaddr_t v; 108 109 while (uio->uio_resid > 0 && error == 0) { 110 iov = uio->uio_iov; 111 if (iov->iov_len == 0) { 112 uio->uio_iov++; 113 uio->uio_iovcnt--; 114 if (uio->uio_iovcnt < 0) 115 panic("mmrw"); 116 continue; 117 } 118 switch (minor(dev)) { 119 120 /* minor device 0 is physical memory */ 121 case 0: 122 v = uio->uio_offset; 123 c = iov->iov_len; 124 if (v + c < v || v + c > ptoa((psize_t)physmem)) 125 return (EFAULT); 126 v = (vaddr_t)PHYS_TO_XKPHYS(v, CCA_NONCOHERENT); 127 error = uiomove((caddr_t)v, c, uio); 128 continue; 129 130 /* minor device 1 is kernel memory */ 131 case 1: 132 v = uio->uio_offset; 133 c = ulmin(iov->iov_len, MAXPHYS); 134 135 /* Allow access to RAM through XKPHYS... */ 136 if (IS_XKPHYS(v)) 137 allowed = is_memory_range(XKPHYS_TO_PHYS(v), 138 (psize_t)c, 0); 139 /* ...or through CKSEG0... */ 140 else if (v >= CKSEG0_BASE && 141 v < CKSEG0_BASE + CKSEG_SIZE) 142 allowed = is_memory_range(CKSEG0_TO_PHYS(v), 143 (psize_t)c, CKSEG_SIZE); 144 /* ...or through CKSEG1... */ 145 else if (v >= CKSEG1_BASE && 146 v < CKSEG1_BASE + CKSEG_SIZE) 147 allowed = is_memory_range(CKSEG1_TO_PHYS(v), 148 (psize_t)c, CKSEG_SIZE); 149 /* ...otherwise, check it's within kernel kvm limits. */ 150 else 151 allowed = uvm_kernacc((caddr_t)v, c, 152 uio->uio_rw == UIO_READ ? B_READ : B_WRITE); 153 154 if (allowed) { 155 error = uiomove((caddr_t)v, c, uio); 156 continue; 157 } else { 158 return (EFAULT); 159 } 160 161 /* minor device 2 is /dev/null */ 162 case 2: 163 if (uio->uio_rw == UIO_WRITE) 164 uio->uio_resid = 0; 165 return (0); 166 167 /* minor device 12 is /dev/zero */ 168 case 12: 169 if (uio->uio_rw == UIO_WRITE) { 170 c = iov->iov_len; 171 break; 172 } 173 if (zeropage == NULL) 174 zeropage = malloc(PAGE_SIZE, M_TEMP, 175 M_WAITOK | M_ZERO); 176 c = ulmin(iov->iov_len, PAGE_SIZE); 177 error = uiomove(zeropage, c, uio); 178 continue; 179 180 default: 181 return (ENODEV); 182 } 183 if (error) 184 break; 185 iov->iov_base += c; 186 iov->iov_len -= c; 187 uio->uio_offset += c; 188 uio->uio_resid -= c; 189 } 190 return error; 191 } 192 193 paddr_t 194 mmmmap(dev_t dev, off_t off, int prot) 195 { 196 return -1; 197 } 198 199 int 200 mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 201 { 202 switch (cmd) { 203 case FIOASYNC: 204 /* handled by fd layer */ 205 return 0; 206 } 207 208 return (ENOTTY); 209 } 210