1 /*- 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department, and code derived from software contributed to 9 * Berkeley by William Jolitz. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * from: Utah $Hdr: mem.c 1.13 89/10/08$ 40 * from: @(#)mem.c 7.2 (Berkeley) 5/9/91 41 * $Id: mem.c,v 1.13 1995/09/15 23:49:23 davidg Exp $ 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/systm.h> 52 #include <sys/uio.h> 53 #include <sys/malloc.h> 54 #include <sys/proc.h> 55 56 #include <machine/cpu.h> 57 #include <machine/psl.h> 58 59 #include <vm/vm.h> 60 #include <vm/vm_param.h> 61 #include <vm/lock.h> 62 #include <vm/vm_prot.h> 63 #include <vm/pmap.h> 64 65 #ifdef DEVFS 66 #include <sys/devfsext.h> 67 #include "sys/kernel.h" 68 int mmopen(); 69 70 void memdev_init(void *data) /* data not used */ 71 { 72 void * x; 73 /* path name devsw minor type uid gid perm*/ 74 x=dev_add("/misc", "mem", mmopen, 0, DV_CHR, 0, 2, 0640); 75 x=dev_add("/misc", "kmem", mmopen, 1, DV_CHR, 0, 2, 0640); 76 x=dev_add("/misc", "null", mmopen, 2, DV_CHR, 0, 0, 0666); 77 x=dev_add("/misc", "zero", mmopen, 12, DV_CHR, 0, 0, 0666); 78 x=dev_add("/misc", "io", mmopen, 14, DV_CHR, 0, 2, 0640); 79 } 80 SYSINIT(memdev,SI_SUB_DEVFS, SI_ORDER_ANY, memdev_init, NULL) 81 #endif /*DEVFS*/ 82 83 84 85 extern char *ptvmmap; /* poor name! */ 86 /*ARGSUSED*/ 87 int 88 mmclose(dev, flags, fmt, p) 89 dev_t dev; 90 int flags; 91 int fmt; 92 struct proc *p; 93 { 94 struct trapframe *fp; 95 96 switch (minor(dev)) { 97 case 14: 98 fp = (struct trapframe *)curproc->p_md.md_regs; 99 fp->tf_eflags &= ~PSL_IOPL; 100 break; 101 default: 102 break; 103 } 104 return(0); 105 } 106 /*ARGSUSED*/ 107 int 108 mmopen(dev, flags, fmt, p) 109 dev_t dev; 110 int flags; 111 int fmt; 112 struct proc *p; 113 { 114 struct trapframe *fp; 115 116 switch (minor(dev)) { 117 case 14: 118 fp = (struct trapframe *)curproc->p_md.md_regs; 119 fp->tf_eflags |= PSL_IOPL; 120 break; 121 default: 122 break; 123 } 124 return(0); 125 } 126 /*ARGSUSED*/ 127 int 128 mmrw(dev, uio, flags) 129 dev_t dev; 130 struct uio *uio; 131 int flags; 132 { 133 register int o; 134 register u_int c, v; 135 register struct iovec *iov; 136 int error = 0; 137 caddr_t zbuf = NULL; 138 139 while (uio->uio_resid > 0 && error == 0) { 140 iov = uio->uio_iov; 141 if (iov->iov_len == 0) { 142 uio->uio_iov++; 143 uio->uio_iovcnt--; 144 if (uio->uio_iovcnt < 0) 145 panic("mmrw"); 146 continue; 147 } 148 switch (minor(dev)) { 149 150 /* minor device 0 is physical memory */ 151 case 0: 152 v = uio->uio_offset; 153 pmap_enter(kernel_pmap, (vm_offset_t)ptvmmap, v, 154 uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE, 155 TRUE); 156 o = (int)uio->uio_offset & PGOFSET; 157 c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET)); 158 c = min(c, (u_int)(NBPG - o)); 159 c = min(c, (u_int)iov->iov_len); 160 error = uiomove((caddr_t)&ptvmmap[o], (int)c, uio); 161 pmap_remove(kernel_pmap, (vm_offset_t)ptvmmap, 162 (vm_offset_t)&ptvmmap[NBPG]); 163 continue; 164 165 /* minor device 1 is kernel memory */ 166 case 1: { 167 vm_offset_t addr, eaddr; 168 c = iov->iov_len; 169 170 /* 171 * Make sure that all of the pages are currently resident so 172 * that we don't create any zero-fill pages. 173 */ 174 addr = trunc_page(uio->uio_offset); 175 eaddr = round_page(uio->uio_offset + c); 176 for (; addr < eaddr; addr += PAGE_SIZE) 177 if (pmap_extract(kernel_pmap, addr) == 0) 178 return EFAULT; 179 180 if (!kernacc((caddr_t)(int)uio->uio_offset, c, 181 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 182 return(EFAULT); 183 error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio); 184 continue; 185 } 186 187 /* minor device 2 is EOF/RATHOLE */ 188 case 2: 189 if (uio->uio_rw == UIO_READ) 190 return (0); 191 c = iov->iov_len; 192 break; 193 194 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ 195 case 12: 196 if (uio->uio_rw == UIO_WRITE) { 197 c = iov->iov_len; 198 break; 199 } 200 if (zbuf == NULL) { 201 zbuf = (caddr_t) 202 malloc(CLBYTES, M_TEMP, M_WAITOK); 203 bzero(zbuf, CLBYTES); 204 } 205 c = min(iov->iov_len, CLBYTES); 206 error = uiomove(zbuf, (int)c, uio); 207 continue; 208 209 #ifdef notyet 210 /* 386 I/O address space (/dev/ioport[bwl]) is a read/write access to seperate 211 i/o device address bus, different than memory bus. Semantics here are 212 very different than ordinary read/write, as if iov_len is a multiple 213 an implied string move from a single port will be done. Note that lseek 214 must be used to set the port number reliably. */ 215 case 14: 216 if (iov->iov_len == 1) { 217 u_char tmp; 218 tmp = inb(uio->uio_offset); 219 error = uiomove (&tmp, iov->iov_len, uio); 220 } else { 221 if (!useracc((caddr_t)iov->iov_base, 222 iov->iov_len, uio->uio_rw)) 223 return (EFAULT); 224 insb(uio->uio_offset, iov->iov_base, 225 iov->iov_len); 226 } 227 break; 228 case 15: 229 if (iov->iov_len == sizeof (short)) { 230 u_short tmp; 231 tmp = inw(uio->uio_offset); 232 error = uiomove (&tmp, iov->iov_len, uio); 233 } else { 234 if (!useracc((caddr_t)iov->iov_base, 235 iov->iov_len, uio->uio_rw)) 236 return (EFAULT); 237 insw(uio->uio_offset, iov->iov_base, 238 iov->iov_len/ sizeof (short)); 239 } 240 break; 241 case 16: 242 if (iov->iov_len == sizeof (long)) { 243 u_long tmp; 244 tmp = inl(uio->uio_offset); 245 error = uiomove (&tmp, iov->iov_len, uio); 246 } else { 247 if (!useracc((caddr_t)iov->iov_base, 248 iov->iov_len, uio->uio_rw)) 249 return (EFAULT); 250 insl(uio->uio_offset, iov->iov_base, 251 iov->iov_len/ sizeof (long)); 252 } 253 break; 254 #endif 255 256 default: 257 return (ENXIO); 258 } 259 if (error) 260 break; 261 iov->iov_base += c; 262 iov->iov_len -= c; 263 uio->uio_offset += c; 264 uio->uio_resid -= c; 265 } 266 if (zbuf) 267 free(zbuf, M_TEMP); 268 return (error); 269 } 270 271 272 273 274 /*******************************************************\ 275 * allow user processes to MMAP some memory sections * 276 * instead of going through read/write * 277 \*******************************************************/ 278 int memmmap(dev_t dev, int offset, int nprot) 279 { 280 switch (minor(dev)) 281 { 282 283 /* minor device 0 is physical memory */ 284 case 0: 285 return i386_btop(offset); 286 287 /* minor device 1 is kernel memory */ 288 case 1: 289 return i386_btop(vtophys(offset)); 290 291 default: 292 return -1; 293 } 294 } 295 296