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.51 1998/06/07 17:10:02 dfr Exp $ 42 */ 43 44 /* 45 * Memory special file 46 */ 47 48 #include "opt_devfs.h" 49 #include "opt_perfmon.h" 50 51 #include <sys/param.h> 52 #include <sys/conf.h> 53 #include <sys/buf.h> 54 #ifdef DEVFS 55 #include <sys/devfsext.h> 56 #endif /* DEVFS */ 57 #include <sys/kernel.h> 58 #include <sys/systm.h> 59 #include <sys/uio.h> 60 #include <sys/malloc.h> 61 #include <sys/proc.h> 62 63 #include <machine/frame.h> 64 #include <machine/random.h> 65 #include <machine/psl.h> 66 #ifdef PERFMON 67 #include <machine/perfmon.h> 68 #endif 69 #include <i386/isa/intr_machdep.h> 70 71 #include <vm/vm.h> 72 #include <vm/vm_prot.h> 73 #include <vm/pmap.h> 74 #include <vm/vm_extern.h> 75 76 77 78 static d_open_t mmopen; 79 static d_close_t mmclose; 80 static d_read_t mmrw; 81 static d_ioctl_t mmioctl; 82 static d_mmap_t memmmap; 83 static d_poll_t mmpoll; 84 85 #define CDEV_MAJOR 2 86 static struct cdevsw mem_cdevsw = 87 { mmopen, mmclose, mmrw, mmrw, /*2*/ 88 mmioctl, nullstop, nullreset, nodevtotty,/* memory */ 89 mmpoll, memmmap, NULL, "mem", NULL, -1 }; 90 91 static struct random_softc random_softc[16]; 92 static caddr_t zbuf; 93 94 #ifdef DEVFS 95 static void *mem_devfs_token; 96 static void *kmem_devfs_token; 97 static void *null_devfs_token; 98 static void *random_devfs_token; 99 static void *urandom_devfs_token; 100 static void *zero_devfs_token; 101 static void *io_devfs_token; 102 #ifdef PERFMON 103 static void *perfmon_devfs_token; 104 #endif 105 106 static void memdevfs_init __P((void)); 107 108 static void 109 memdevfs_init() 110 { 111 mem_devfs_token = 112 devfs_add_devswf(&mem_cdevsw, 0, DV_CHR, 113 UID_ROOT, GID_KMEM, 0640, "mem"); 114 kmem_devfs_token = 115 devfs_add_devswf(&mem_cdevsw, 1, DV_CHR, 116 UID_ROOT, GID_KMEM, 0640, "kmem"); 117 null_devfs_token = 118 devfs_add_devswf(&mem_cdevsw, 2, DV_CHR, 119 UID_ROOT, GID_WHEEL, 0666, "null"); 120 random_devfs_token = 121 devfs_add_devswf(&mem_cdevsw, 3, DV_CHR, 122 UID_ROOT, GID_WHEEL, 0644, "random"); 123 urandom_devfs_token = 124 devfs_add_devswf(&mem_cdevsw, 4, DV_CHR, 125 UID_ROOT, GID_WHEEL, 0644, "urandom"); 126 zero_devfs_token = 127 devfs_add_devswf(&mem_cdevsw, 12, DV_CHR, 128 UID_ROOT, GID_WHEEL, 0666, "zero"); 129 io_devfs_token = 130 devfs_add_devswf(&mem_cdevsw, 14, DV_CHR, 131 UID_ROOT, GID_WHEEL, 0600, "io"); 132 #ifdef PERFMON 133 perfmon_devfs_token = 134 devfs_add_devswf(&mem_cdevsw, 32, DV_CHR, 135 UID_ROOT, GID_KMEM, 0640, "perfmon"); 136 #endif /* PERFMON */ 137 } 138 #endif /* DEVFS */ 139 140 static int 141 mmclose(dev, flags, fmt, p) 142 dev_t dev; 143 int flags; 144 int fmt; 145 struct proc *p; 146 { 147 switch (minor(dev)) { 148 #ifdef PERFMON 149 case 32: 150 return perfmon_close(dev, flags, fmt, p); 151 #endif 152 case 14: 153 curproc->p_md.md_regs->tf_eflags &= ~PSL_IOPL; 154 break; 155 default: 156 break; 157 } 158 return(0); 159 } 160 161 static int 162 mmopen(dev, flags, fmt, p) 163 dev_t dev; 164 int flags; 165 int fmt; 166 struct proc *p; 167 { 168 int error; 169 170 switch (minor(dev)) { 171 case 32: 172 #ifdef PERFMON 173 return perfmon_open(dev, flags, fmt, p); 174 #else 175 return ENODEV; 176 #endif 177 case 14: 178 error = suser(p->p_ucred, &p->p_acflag); 179 if (error != 0) 180 return (error); 181 if (securelevel > 0) 182 return (EPERM); 183 curproc->p_md.md_regs->tf_eflags |= PSL_IOPL; 184 break; 185 default: 186 break; 187 } 188 return(0); 189 } 190 191 static int 192 mmrw(dev, uio, flags) 193 dev_t dev; 194 struct uio *uio; 195 int flags; 196 { 197 register int o; 198 register u_int c, v; 199 u_int poolsize; 200 register struct iovec *iov; 201 int error = 0; 202 caddr_t buf = NULL; 203 204 while (uio->uio_resid > 0 && error == 0) { 205 iov = uio->uio_iov; 206 if (iov->iov_len == 0) { 207 uio->uio_iov++; 208 uio->uio_iovcnt--; 209 if (uio->uio_iovcnt < 0) 210 panic("mmrw"); 211 continue; 212 } 213 switch (minor(dev)) { 214 215 /* minor device 0 is physical memory */ 216 case 0: 217 v = uio->uio_offset; 218 pmap_enter(kernel_pmap, (vm_offset_t)ptvmmap, v, 219 uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE, 220 TRUE); 221 o = (int)uio->uio_offset & PAGE_MASK; 222 c = (u_int)(PAGE_SIZE - ((int)iov->iov_base & PAGE_MASK)); 223 c = min(c, (u_int)(PAGE_SIZE - o)); 224 c = min(c, (u_int)iov->iov_len); 225 error = uiomove((caddr_t)&ptvmmap[o], (int)c, uio); 226 pmap_remove(kernel_pmap, (vm_offset_t)ptvmmap, 227 (vm_offset_t)&ptvmmap[PAGE_SIZE]); 228 continue; 229 230 /* minor device 1 is kernel memory */ 231 case 1: { 232 vm_offset_t addr, eaddr; 233 c = iov->iov_len; 234 235 /* 236 * Make sure that all of the pages are currently resident so 237 * that we don't create any zero-fill pages. 238 */ 239 addr = trunc_page(uio->uio_offset); 240 eaddr = round_page(uio->uio_offset + c); 241 242 if (addr < (vm_offset_t)VADDR(PTDPTDI, 0)) 243 return EFAULT; 244 if (eaddr >= (vm_offset_t)VADDR(APTDPTDI, 0)) 245 return EFAULT; 246 for (; addr < eaddr; addr += PAGE_SIZE) 247 if (pmap_extract(kernel_pmap, addr) == 0) 248 return EFAULT; 249 250 if (!kernacc((caddr_t)(int)uio->uio_offset, c, 251 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 252 return(EFAULT); 253 error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio); 254 continue; 255 } 256 257 /* minor device 2 is EOF/RATHOLE */ 258 case 2: 259 if (uio->uio_rw == UIO_READ) 260 return (0); 261 c = iov->iov_len; 262 break; 263 264 /* minor device 3 (/dev/random) is source of filth on read, rathole on write */ 265 case 3: 266 if (uio->uio_rw == UIO_WRITE) { 267 c = iov->iov_len; 268 break; 269 } 270 if (buf == NULL) 271 buf = (caddr_t) 272 malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 273 c = min(iov->iov_len, PAGE_SIZE); 274 poolsize = read_random(buf, c); 275 if (poolsize == 0) { 276 if (buf) 277 free(buf, M_TEMP); 278 return (0); 279 } 280 c = min(c, poolsize); 281 error = uiomove(buf, (int)c, uio); 282 continue; 283 284 /* minor device 4 (/dev/urandom) is source of muck on read, rathole on write */ 285 case 4: 286 if (uio->uio_rw == UIO_WRITE) { 287 c = iov->iov_len; 288 break; 289 } 290 if (buf == NULL) 291 buf = (caddr_t) 292 malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 293 c = min(iov->iov_len, PAGE_SIZE); 294 poolsize = read_random_unlimited(buf, c); 295 c = min(c, poolsize); 296 error = uiomove(buf, (int)c, uio); 297 continue; 298 299 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ 300 case 12: 301 if (uio->uio_rw == UIO_WRITE) { 302 c = iov->iov_len; 303 break; 304 } 305 if (zbuf == NULL) { 306 zbuf = (caddr_t) 307 malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 308 bzero(zbuf, PAGE_SIZE); 309 } 310 c = min(iov->iov_len, PAGE_SIZE); 311 error = uiomove(zbuf, (int)c, uio); 312 continue; 313 314 #ifdef notyet 315 /* 386 I/O address space (/dev/ioport[bwl]) is a read/write access to seperate 316 i/o device address bus, different than memory bus. Semantics here are 317 very different than ordinary read/write, as if iov_len is a multiple 318 an implied string move from a single port will be done. Note that lseek 319 must be used to set the port number reliably. */ 320 case 14: 321 if (iov->iov_len == 1) { 322 u_char tmp; 323 tmp = inb(uio->uio_offset); 324 error = uiomove (&tmp, iov->iov_len, uio); 325 } else { 326 if (!useracc((caddr_t)iov->iov_base, 327 iov->iov_len, uio->uio_rw)) 328 return (EFAULT); 329 insb(uio->uio_offset, iov->iov_base, 330 iov->iov_len); 331 } 332 break; 333 case 15: 334 if (iov->iov_len == sizeof (short)) { 335 u_short tmp; 336 tmp = inw(uio->uio_offset); 337 error = uiomove (&tmp, iov->iov_len, uio); 338 } else { 339 if (!useracc((caddr_t)iov->iov_base, 340 iov->iov_len, uio->uio_rw)) 341 return (EFAULT); 342 insw(uio->uio_offset, iov->iov_base, 343 iov->iov_len/ sizeof (short)); 344 } 345 break; 346 case 16: 347 if (iov->iov_len == sizeof (long)) { 348 u_long tmp; 349 tmp = inl(uio->uio_offset); 350 error = uiomove (&tmp, iov->iov_len, uio); 351 } else { 352 if (!useracc((caddr_t)iov->iov_base, 353 iov->iov_len, uio->uio_rw)) 354 return (EFAULT); 355 insl(uio->uio_offset, iov->iov_base, 356 iov->iov_len/ sizeof (long)); 357 } 358 break; 359 #endif 360 361 default: 362 return (ENXIO); 363 } 364 if (error) 365 break; 366 iov->iov_base += c; 367 iov->iov_len -= c; 368 uio->uio_offset += c; 369 uio->uio_resid -= c; 370 } 371 if (buf) 372 free(buf, M_TEMP); 373 return (error); 374 } 375 376 377 378 379 /*******************************************************\ 380 * allow user processes to MMAP some memory sections * 381 * instead of going through read/write * 382 \*******************************************************/ 383 static int 384 memmmap(dev_t dev, int offset, int nprot) 385 { 386 switch (minor(dev)) 387 { 388 389 /* minor device 0 is physical memory */ 390 case 0: 391 return i386_btop(offset); 392 393 /* minor device 1 is kernel memory */ 394 case 1: 395 return i386_btop(vtophys(offset)); 396 397 default: 398 return -1; 399 } 400 } 401 402 static int 403 mmioctl(dev, cmd, data, flags, p) 404 dev_t dev; 405 u_long cmd; 406 caddr_t data; 407 int flags; 408 struct proc *p; 409 { 410 static intrmask_t interrupt_allowed; 411 intrmask_t interrupt_mask; 412 int error, intr; 413 struct random_softc *sc; 414 415 switch (minor(dev)) { 416 case 3: 417 case 4: 418 break; 419 #ifdef PERFMON 420 case 32: 421 return perfmon_ioctl(dev, cmd, data, flags, p); 422 #endif 423 default: 424 return (ENODEV); 425 } 426 427 /* 428 * We're the random or urandom device. The only ioctls are for 429 * selecting and inspecting which interrupts are used in the muck 430 * gathering business. 431 */ 432 if (cmd != MEM_SETIRQ && cmd != MEM_CLEARIRQ && cmd != MEM_RETURNIRQ) 433 return (ENOTTY); 434 435 /* 436 * Even inspecting the state is privileged, since it gives a hint 437 * about how easily the randomness might be guessed. 438 */ 439 error = suser(p->p_ucred, &p->p_acflag); 440 if (error != 0) 441 return (error); 442 443 /* 444 * XXX the data is 16-bit due to a historical botch, so we use 445 * magic 16's instead of ICU_LEN and can't support 24 interrupts 446 * under SMP. 447 */ 448 intr = *(int16_t *)data; 449 if (cmd != MEM_RETURNIRQ && (intr < 0 || intr >= 16)) 450 return (EINVAL); 451 452 interrupt_mask = 1 << intr; 453 sc = &random_softc[intr]; 454 switch (cmd) { 455 case MEM_SETIRQ: 456 if (interrupt_allowed & interrupt_mask) 457 break; 458 interrupt_allowed |= interrupt_mask; 459 sc->sc_intr = intr; 460 disable_intr(); 461 sc->sc_handler = intr_handler[intr]; 462 intr_handler[intr] = add_interrupt_randomness; 463 sc->sc_arg = intr_unit[intr]; 464 intr_unit[intr] = sc; 465 enable_intr(); 466 break; 467 case MEM_CLEARIRQ: 468 if (!(interrupt_allowed & interrupt_mask)) 469 break; 470 interrupt_allowed &= ~interrupt_mask; 471 disable_intr(); 472 intr_handler[intr] = sc->sc_handler; 473 intr_unit[intr] = sc->sc_arg; 474 enable_intr(); 475 break; 476 case MEM_RETURNIRQ: 477 *(u_int16_t *)data = interrupt_allowed; 478 break; 479 default: 480 return (ENOTTY); 481 } 482 return (0); 483 } 484 485 int 486 mmpoll(dev, events, p) 487 dev_t dev; 488 int events; 489 struct proc *p; 490 { 491 switch (minor(dev)) { 492 case 3: /* /dev/random */ 493 return random_poll(dev, events, p); 494 case 4: /* /dev/urandom */ 495 default: 496 return seltrue(dev, events, p); 497 } 498 } 499 500 /* 501 * Routine that identifies /dev/mem and /dev/kmem. 502 * 503 * A minimal stub routine can always return 0. 504 */ 505 int 506 iskmemdev(dev) 507 dev_t dev; 508 { 509 510 return ((major(dev) == mem_cdevsw.d_maj) 511 && (minor(dev) == 0 || minor(dev) == 1)); 512 } 513 514 int 515 iszerodev(dev) 516 dev_t dev; 517 { 518 return ((major(dev) == mem_cdevsw.d_maj) 519 && minor(dev) == 12); 520 } 521 522 523 524 static int mem_devsw_installed; 525 526 static void 527 mem_drvinit(void *unused) 528 { 529 dev_t dev; 530 531 if( ! mem_devsw_installed ) { 532 dev = makedev(CDEV_MAJOR, 0); 533 cdevsw_add(&dev,&mem_cdevsw, NULL); 534 mem_devsw_installed = 1; 535 #ifdef DEVFS 536 memdevfs_init(); 537 #endif 538 } 539 } 540 541 SYSINIT(memdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mem_drvinit,NULL) 542 543