1*b9ae17a0Sguenther /* $OpenBSD: mem.c,v 1.28 2024/12/30 02:46:00 guenther Exp $ */ 2f58c7388Spefo /* $NetBSD: mem.c,v 1.6 1995/04/10 11:55:03 mycroft Exp $ */ 3f58c7388Spefo 4f58c7388Spefo /* 5f58c7388Spefo * Copyright (c) 1988 University of Utah. 6f58c7388Spefo * Copyright (c) 1982, 1986, 1990, 1993 7f58c7388Spefo * The Regents of the University of California. All rights reserved. 8f58c7388Spefo * 9f58c7388Spefo * This code is derived from software contributed to Berkeley by 10f58c7388Spefo * the Systems Programming Group of the University of Utah Computer 11f58c7388Spefo * Science Department and Ralph Campbell. 12f58c7388Spefo * 13f58c7388Spefo * Redistribution and use in source and binary forms, with or without 14f58c7388Spefo * modification, are permitted provided that the following conditions 15f58c7388Spefo * are met: 16f58c7388Spefo * 1. Redistributions of source code must retain the above copyright 17f58c7388Spefo * notice, this list of conditions and the following disclaimer. 18f58c7388Spefo * 2. Redistributions in binary form must reproduce the above copyright 19f58c7388Spefo * notice, this list of conditions and the following disclaimer in the 20f58c7388Spefo * documentation and/or other materials provided with the distribution. 21f58c7388Spefo * 3. All advertising materials mentioning features or use of this software 22f58c7388Spefo * must display the following acknowledgement: 23f58c7388Spefo * This product includes software developed by the University of 24f58c7388Spefo * California, Berkeley and its contributors. 25f58c7388Spefo * 4. Neither the name of the University nor the names of its contributors 26f58c7388Spefo * may be used to endorse or promote products derived from this software 27f58c7388Spefo * without specific prior written permission. 28f58c7388Spefo * 29f58c7388Spefo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30f58c7388Spefo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31f58c7388Spefo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32f58c7388Spefo * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33f58c7388Spefo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34f58c7388Spefo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35f58c7388Spefo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36f58c7388Spefo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37f58c7388Spefo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38f58c7388Spefo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39f58c7388Spefo * SUCH DAMAGE. 40f58c7388Spefo * 41f58c7388Spefo * @(#)mem.c 8.3 (Berkeley) 1/12/94 42f58c7388Spefo */ 43f58c7388Spefo 44f58c7388Spefo /* 45f58c7388Spefo * Memory special file 46f58c7388Spefo */ 47f58c7388Spefo 48f58c7388Spefo #include <sys/param.h> 49f58c7388Spefo #include <sys/conf.h> 50f58c7388Spefo #include <sys/buf.h> 51c2a35b38Sguenther #include <sys/filio.h> 52f58c7388Spefo #include <sys/proc.h> 53f58c7388Spefo #include <sys/msgbuf.h> 54f58c7388Spefo #include <sys/systm.h> 55f58c7388Spefo #include <sys/uio.h> 56f58c7388Spefo #include <sys/malloc.h> 5764293e57Smvs #include <sys/atomic.h> 58f58c7388Spefo 59f58c7388Spefo #include <machine/autoconf.h> 60f58c7388Spefo #include <machine/cpu.h> 61f8c4d001Smiod #include <machine/memconf.h> 62f58c7388Spefo 63f58c7388Spefo #include <uvm/uvm_extern.h> 64f58c7388Spefo 6594483548Svisa int is_memory_range(paddr_t, psize_t, psize_t); 66f8c4d001Smiod 67f58c7388Spefo caddr_t zeropage; 68f58c7388Spefo 69f58c7388Spefo #define mmread mmrw 70f58c7388Spefo #define mmwrite mmrw 71f58c7388Spefo cdev_decl(mm); 72f58c7388Spefo 73f58c7388Spefo int 741806efc6Sderaadt mmopen(dev_t dev, int flag, int mode, struct proc *p) 75f58c7388Spefo { 7619aedf23Sderaadt extern int allowkmem; 77f58c7388Spefo 78f58c7388Spefo switch (minor(dev)) { 79f58c7388Spefo case 0: 80f58c7388Spefo case 1: 810815c577Smvs if ((int)atomic_load_int(&securelevel) <= 0 || 8264293e57Smvs atomic_load_int(&allowkmem)) 8319aedf23Sderaadt break; 8419aedf23Sderaadt return (EPERM); 85f58c7388Spefo case 2: 86f58c7388Spefo case 12: 8719aedf23Sderaadt break; 88f58c7388Spefo default: 89f58c7388Spefo return (ENXIO); 90f58c7388Spefo } 9119aedf23Sderaadt return (0); 92f58c7388Spefo } 93f58c7388Spefo 94f58c7388Spefo int 951806efc6Sderaadt mmclose(dev_t dev, int flag, int mode, struct proc *p) 96f58c7388Spefo { 97f58c7388Spefo return (0); 98f58c7388Spefo } 99f58c7388Spefo 100f58c7388Spefo int 1011806efc6Sderaadt mmrw(dev_t dev, struct uio *uio, int flags) 102f58c7388Spefo { 103f58c7388Spefo struct iovec *iov; 10494483548Svisa int allowed; 1050a32e46cSmiod int error = 0; 1060a32e46cSmiod size_t c; 1071806efc6Sderaadt vaddr_t v; 108f58c7388Spefo 109f58c7388Spefo while (uio->uio_resid > 0 && error == 0) { 110f58c7388Spefo iov = uio->uio_iov; 111f58c7388Spefo if (iov->iov_len == 0) { 112f58c7388Spefo uio->uio_iov++; 113f58c7388Spefo uio->uio_iovcnt--; 114f58c7388Spefo if (uio->uio_iovcnt < 0) 115f58c7388Spefo panic("mmrw"); 116f58c7388Spefo continue; 117f58c7388Spefo } 118f58c7388Spefo switch (minor(dev)) { 119f58c7388Spefo 120f58c7388Spefo /* minor device 0 is physical memory */ 121f58c7388Spefo case 0: 122f58c7388Spefo v = uio->uio_offset; 123f58c7388Spefo c = iov->iov_len; 1240a32e46cSmiod if (v + c < v || v + c > ptoa((psize_t)physmem)) 125f58c7388Spefo return (EFAULT); 126001861eaSmiod v = (vaddr_t)PHYS_TO_XKPHYS(v, CCA_NONCOHERENT); 1279c829367Smiod error = uiomove((caddr_t)v, c, uio); 128f58c7388Spefo continue; 129f58c7388Spefo 130f58c7388Spefo /* minor device 1 is kernel memory */ 131f58c7388Spefo case 1: 132f58c7388Spefo v = uio->uio_offset; 1330a32e46cSmiod c = ulmin(iov->iov_len, MAXPHYS); 134edb45030Smiod 135edb45030Smiod /* Allow access to RAM through XKPHYS... */ 136f8c4d001Smiod if (IS_XKPHYS(v)) 137f8c4d001Smiod allowed = is_memory_range(XKPHYS_TO_PHYS(v), 138f8c4d001Smiod (psize_t)c, 0); 13971b9f840Smiod /* ...or through CKSEG0... */ 14071b9f840Smiod else if (v >= CKSEG0_BASE && 141f8c4d001Smiod v < CKSEG0_BASE + CKSEG_SIZE) 142f8c4d001Smiod allowed = is_memory_range(CKSEG0_TO_PHYS(v), 143f8c4d001Smiod (psize_t)c, CKSEG_SIZE); 14471b9f840Smiod /* ...or through CKSEG1... */ 14571b9f840Smiod else if (v >= CKSEG1_BASE && 146f8c4d001Smiod v < CKSEG1_BASE + CKSEG_SIZE) 147f8c4d001Smiod allowed = is_memory_range(CKSEG1_TO_PHYS(v), 148f8c4d001Smiod (psize_t)c, CKSEG_SIZE); 149edb45030Smiod /* ...otherwise, check it's within kernel kvm limits. */ 150edb45030Smiod else 151edb45030Smiod allowed = uvm_kernacc((caddr_t)v, c, 152edb45030Smiod uio->uio_rw == UIO_READ ? B_READ : B_WRITE); 153edb45030Smiod 154edb45030Smiod if (allowed) { 1559c829367Smiod error = uiomove((caddr_t)v, c, uio); 156f58c7388Spefo continue; 15721d1227dSpefo } else { 15821d1227dSpefo return (EFAULT); 15921d1227dSpefo } 160f58c7388Spefo 1618aecc570Stedu /* minor device 2 is /dev/null */ 162f58c7388Spefo case 2: 163f58c7388Spefo if (uio->uio_rw == UIO_WRITE) 164f58c7388Spefo uio->uio_resid = 0; 165f58c7388Spefo return (0); 166f58c7388Spefo 1678aecc570Stedu /* minor device 12 is /dev/zero */ 168f58c7388Spefo case 12: 169f58c7388Spefo if (uio->uio_rw == UIO_WRITE) { 170f58c7388Spefo c = iov->iov_len; 171f58c7388Spefo break; 172f58c7388Spefo } 173bb5ecd09Skrw if (zeropage == NULL) 174bb5ecd09Skrw zeropage = malloc(PAGE_SIZE, M_TEMP, 175bb5ecd09Skrw M_WAITOK | M_ZERO); 1760a32e46cSmiod c = ulmin(iov->iov_len, PAGE_SIZE); 1779c829367Smiod error = uiomove(zeropage, c, uio); 178f58c7388Spefo continue; 179f58c7388Spefo 180f58c7388Spefo default: 181f58c7388Spefo return (ENODEV); 182f58c7388Spefo } 183f58c7388Spefo if (error) 184f58c7388Spefo break; 185f58c7388Spefo iov->iov_base += c; 186f58c7388Spefo iov->iov_len -= c; 187f58c7388Spefo uio->uio_offset += c; 188f58c7388Spefo uio->uio_resid -= c; 189f58c7388Spefo } 190f58c7388Spefo return error; 191f58c7388Spefo } 192f58c7388Spefo 193f58c7388Spefo paddr_t 1941806efc6Sderaadt mmmmap(dev_t dev, off_t off, int prot) 195f58c7388Spefo { 196f58c7388Spefo return -1; 197f58c7388Spefo } 198f58c7388Spefo 199f58c7388Spefo int 2001806efc6Sderaadt mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 201f58c7388Spefo { 202c2a35b38Sguenther switch (cmd) { 203c2a35b38Sguenther case FIOASYNC: 204c2a35b38Sguenther /* handled by fd layer */ 205c2a35b38Sguenther return 0; 206c2a35b38Sguenther } 207c2a35b38Sguenther 20887449d88Skettenis return (ENOTTY); 209f58c7388Spefo } 210