1/* $OpenBSD: mem.c,v 1.24 2019/12/20 13:34:41 visa 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 58#include <machine/autoconf.h> 59#include <machine/cpu.h> 60#include <machine/memconf.h> 61 62#include <uvm/uvm_extern.h> 63 64int is_memory_range(paddr_t, psize_t, psize_t); 65 66caddr_t zeropage; 67 68#define mmread mmrw 69#define mmwrite mmrw 70cdev_decl(mm); 71 72int 73mmopen(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 (securelevel <= 0 || allowkmem) 81 break; 82 return (EPERM); 83 case 2: 84 case 12: 85 break; 86 default: 87 return (ENXIO); 88 } 89 return (0); 90} 91 92int 93mmclose(dev_t dev, int flag, int mode, struct proc *p) 94{ 95 return (0); 96} 97 98int 99mmrw(dev_t dev, struct uio *uio, int flags) 100{ 101 struct iovec *iov; 102 int allowed; 103 int error = 0; 104 size_t c; 105 vaddr_t v; 106 107 while (uio->uio_resid > 0 && error == 0) { 108 iov = uio->uio_iov; 109 if (iov->iov_len == 0) { 110 uio->uio_iov++; 111 uio->uio_iovcnt--; 112 if (uio->uio_iovcnt < 0) 113 panic("mmrw"); 114 continue; 115 } 116 switch (minor(dev)) { 117 118 /* minor device 0 is physical memory */ 119 case 0: 120 v = uio->uio_offset; 121 c = iov->iov_len; 122 if (v + c < v || v + c > ptoa((psize_t)physmem)) 123 return (EFAULT); 124 v = (vaddr_t)PHYS_TO_XKPHYS(v, CCA_NONCOHERENT); 125 error = uiomove((caddr_t)v, c, uio); 126 continue; 127 128 /* minor device 1 is kernel memory */ 129 case 1: 130 v = uio->uio_offset; 131 c = ulmin(iov->iov_len, MAXPHYS); 132 133 /* Allow access to RAM through XKPHYS... */ 134 if (IS_XKPHYS(v)) 135 allowed = is_memory_range(XKPHYS_TO_PHYS(v), 136 (psize_t)c, 0); 137 /* ...or through CKSEG0... */ 138 else if (v >= CKSEG0_BASE && 139 v < CKSEG0_BASE + CKSEG_SIZE) 140 allowed = is_memory_range(CKSEG0_TO_PHYS(v), 141 (psize_t)c, CKSEG_SIZE); 142 /* ...or through CKSEG1... */ 143 else if (v >= CKSEG1_BASE && 144 v < CKSEG1_BASE + CKSEG_SIZE) 145 allowed = is_memory_range(CKSEG1_TO_PHYS(v), 146 (psize_t)c, CKSEG_SIZE); 147 /* ...otherwise, check it's within kernel kvm limits. */ 148 else 149 allowed = uvm_kernacc((caddr_t)v, c, 150 uio->uio_rw == UIO_READ ? B_READ : B_WRITE); 151 152 if (allowed) { 153 error = uiomove((caddr_t)v, c, uio); 154 continue; 155 } else { 156 return (EFAULT); 157 } 158 159 /* minor device 2 is /dev/null */ 160 case 2: 161 if (uio->uio_rw == UIO_WRITE) 162 uio->uio_resid = 0; 163 return (0); 164 165 /* minor device 12 is /dev/zero */ 166 case 12: 167 if (uio->uio_rw == UIO_WRITE) { 168 c = iov->iov_len; 169 break; 170 } 171 if (zeropage == NULL) 172 zeropage = malloc(PAGE_SIZE, M_TEMP, 173 M_WAITOK | M_ZERO); 174 c = ulmin(iov->iov_len, PAGE_SIZE); 175 error = uiomove(zeropage, c, uio); 176 continue; 177 178 default: 179 return (ENODEV); 180 } 181 if (error) 182 break; 183 iov->iov_base += c; 184 iov->iov_len -= c; 185 uio->uio_offset += c; 186 uio->uio_resid -= c; 187 } 188 return error; 189} 190 191paddr_t 192mmmmap(dev_t dev, off_t off, int prot) 193{ 194 return -1; 195} 196 197int 198mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 199{ 200 switch (cmd) { 201 case FIONBIO: 202 case FIOASYNC: 203 /* handled by fd layer */ 204 return 0; 205 } 206 207 return (EOPNOTSUPP); 208} 209