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 * $FreeBSD: src/sys/i386/i386/mem.c,v 1.79.2.9 2003/01/04 22:58:01 njl Exp $ 42 * $DragonFly: src/sys/kern/kern_memio.c,v 1.14 2006/06/27 16:38:41 dillon Exp $ 43 */ 44 45 /* 46 * Memory special file 47 */ 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/buf.h> 52 #include <sys/conf.h> 53 #include <sys/fcntl.h> 54 #include <sys/filio.h> 55 #include <sys/ioccom.h> 56 #include <sys/kernel.h> 57 #include <sys/malloc.h> 58 #include <sys/memrange.h> 59 #include <sys/proc.h> 60 #include <sys/random.h> 61 #include <sys/signalvar.h> 62 #include <sys/uio.h> 63 #include <sys/vnode.h> 64 65 #include <machine/frame.h> 66 #include <machine/psl.h> 67 #include <machine/specialreg.h> 68 #include <i386/isa/intr_machdep.h> 69 70 #include <vm/vm.h> 71 #include <vm/pmap.h> 72 #include <vm/vm_extern.h> 73 74 75 static d_open_t mmopen; 76 static d_close_t mmclose; 77 static d_read_t mmrw; 78 static d_ioctl_t mmioctl; 79 static d_mmap_t memmmap; 80 static d_poll_t mmpoll; 81 82 #define CDEV_MAJOR 2 83 static struct cdevsw mem_cdevsw = { 84 /* name */ "mem", 85 /* maj */ CDEV_MAJOR, 86 /* flags */ D_MEM, 87 /* port */ NULL, 88 /* clone */ NULL, 89 90 /* open */ mmopen, 91 /* close */ mmclose, 92 /* read */ mmrw, 93 /* write */ mmrw, 94 /* ioctl */ mmioctl, 95 /* poll */ mmpoll, 96 /* mmap */ memmmap, 97 /* strategy */ nostrategy, 98 /* dump */ nodump, 99 /* psize */ nopsize 100 }; 101 102 static int rand_bolt; 103 static caddr_t zbuf; 104 105 MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors"); 106 static int mem_ioctl (dev_t, u_long, caddr_t, int, struct thread *); 107 static int random_ioctl (dev_t, u_long, caddr_t, int, struct thread *); 108 109 struct mem_range_softc mem_range_softc; 110 111 112 static int 113 mmclose(dev_t dev, int flags, int fmt, struct thread *td) 114 { 115 struct proc *p = td->td_proc; 116 117 switch (minor(dev)) { 118 case 14: 119 p->p_md.md_regs->tf_eflags &= ~PSL_IOPL; 120 break; 121 default: 122 break; 123 } 124 return (0); 125 } 126 127 static int 128 mmopen(dev_t dev, int flags, int fmt, struct thread *td) 129 { 130 int error; 131 struct proc *p = td->td_proc; 132 133 switch (minor(dev)) { 134 case 0: 135 case 1: 136 if ((flags & FWRITE) && securelevel > 0) 137 return (EPERM); 138 break; 139 case 14: 140 error = suser(td); 141 if (error != 0) 142 return (error); 143 if (securelevel > 0) 144 return (EPERM); 145 p->p_md.md_regs->tf_eflags |= PSL_IOPL; 146 break; 147 default: 148 break; 149 } 150 return (0); 151 } 152 153 static int 154 mmrw(dev, uio, flags) 155 dev_t dev; 156 struct uio *uio; 157 int flags; 158 { 159 int o; 160 u_int c, v; 161 u_int poolsize; 162 struct iovec *iov; 163 int error = 0; 164 caddr_t buf = NULL; 165 166 while (uio->uio_resid > 0 && error == 0) { 167 iov = uio->uio_iov; 168 if (iov->iov_len == 0) { 169 uio->uio_iov++; 170 uio->uio_iovcnt--; 171 if (uio->uio_iovcnt < 0) 172 panic("mmrw"); 173 continue; 174 } 175 switch (minor(dev)) { 176 177 /* minor device 0 is physical memory, /dev/mem */ 178 case 0: 179 v = uio->uio_offset; 180 v &= ~PAGE_MASK; 181 pmap_kenter((vm_offset_t)ptvmmap, v); 182 o = (int)uio->uio_offset & PAGE_MASK; 183 c = (u_int)(PAGE_SIZE - ((int)iov->iov_base & PAGE_MASK)); 184 c = min(c, (u_int)(PAGE_SIZE - o)); 185 c = min(c, (u_int)iov->iov_len); 186 error = uiomove((caddr_t)&ptvmmap[o], (int)c, uio); 187 pmap_kremove((vm_offset_t)ptvmmap); 188 continue; 189 190 /* minor device 1 is kernel memory, /dev/kmem */ 191 case 1: { 192 vm_offset_t addr, eaddr; 193 c = iov->iov_len; 194 195 /* 196 * Make sure that all of the pages are currently 197 * resident so that we don't create any zero-fill 198 * pages. 199 */ 200 addr = trunc_page(uio->uio_offset); 201 eaddr = round_page(uio->uio_offset + c); 202 203 if (addr < (vm_offset_t)VADDR(PTDPTDI, 0)) 204 return EFAULT; 205 if (eaddr >= (vm_offset_t)VADDR(APTDPTDI, 0)) 206 return EFAULT; 207 for (; addr < eaddr; addr += PAGE_SIZE) 208 if (pmap_extract(kernel_pmap, addr) == 0) 209 return EFAULT; 210 211 if (!kernacc((caddr_t)(int)uio->uio_offset, c, 212 uio->uio_rw == UIO_READ ? 213 VM_PROT_READ : VM_PROT_WRITE)) 214 return (EFAULT); 215 error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio); 216 continue; 217 } 218 219 /* minor device 2 is EOF/RATHOLE */ 220 case 2: 221 if (uio->uio_rw == UIO_READ) 222 return (0); 223 c = iov->iov_len; 224 break; 225 226 /* minor device 3 (/dev/random) is source of filth on read, rathole on write */ 227 case 3: 228 if (uio->uio_rw == UIO_WRITE) { 229 c = iov->iov_len; 230 break; 231 } 232 if (buf == NULL) 233 buf = (caddr_t) 234 malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 235 c = min(iov->iov_len, PAGE_SIZE); 236 poolsize = read_random(buf, c); 237 if (poolsize == 0) { 238 if (buf) 239 free(buf, M_TEMP); 240 if ((flags & IO_NDELAY) != 0) 241 return (EWOULDBLOCK); 242 return (0); 243 } 244 c = min(c, poolsize); 245 error = uiomove(buf, (int)c, uio); 246 continue; 247 248 /* minor device 4 (/dev/urandom) is source of muck on read, rathole on write */ 249 case 4: 250 if (uio->uio_rw == UIO_WRITE) { 251 c = iov->iov_len; 252 break; 253 } 254 if (CURSIG(curproc) != 0) { 255 /* 256 * Use tsleep() to get the error code right. 257 * It should return immediately. 258 */ 259 error = tsleep(&rand_bolt, PCATCH, "urand", 1); 260 if (error != 0 && error != EWOULDBLOCK) 261 continue; 262 } 263 if (buf == NULL) 264 buf = (caddr_t) 265 malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 266 c = min(iov->iov_len, PAGE_SIZE); 267 poolsize = read_random_unlimited(buf, c); 268 c = min(c, poolsize); 269 error = uiomove(buf, (int)c, uio); 270 continue; 271 272 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ 273 case 12: 274 if (uio->uio_rw == UIO_WRITE) { 275 c = iov->iov_len; 276 break; 277 } 278 if (zbuf == NULL) { 279 zbuf = (caddr_t) 280 malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 281 bzero(zbuf, PAGE_SIZE); 282 } 283 c = min(iov->iov_len, PAGE_SIZE); 284 error = uiomove(zbuf, (int)c, uio); 285 continue; 286 287 default: 288 return (ENODEV); 289 } 290 if (error) 291 break; 292 iov->iov_base += c; 293 iov->iov_len -= c; 294 uio->uio_offset += c; 295 uio->uio_resid -= c; 296 } 297 if (buf) 298 free(buf, M_TEMP); 299 return (error); 300 } 301 302 303 304 305 /*******************************************************\ 306 * allow user processes to MMAP some memory sections * 307 * instead of going through read/write * 308 \*******************************************************/ 309 static int 310 memmmap(dev_t dev, vm_offset_t offset, int nprot) 311 { 312 switch (minor(dev)) 313 { 314 315 /* minor device 0 is physical memory */ 316 case 0: 317 return i386_btop(offset); 318 319 /* minor device 1 is kernel memory */ 320 case 1: 321 return i386_btop(vtophys(offset)); 322 323 default: 324 return -1; 325 } 326 } 327 328 static int 329 mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) 330 { 331 332 switch (minor(dev)) { 333 case 0: 334 return mem_ioctl(dev, cmd, data, flags, td); 335 case 3: 336 case 4: 337 return random_ioctl(dev, cmd, data, flags, td); 338 } 339 return (ENODEV); 340 } 341 342 /* 343 * Operations for changing memory attributes. 344 * 345 * This is basically just an ioctl shim for mem_range_attr_get 346 * and mem_range_attr_set. 347 */ 348 static int 349 mem_ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) 350 { 351 int nd, error = 0; 352 struct mem_range_op *mo = (struct mem_range_op *)data; 353 struct mem_range_desc *md; 354 355 /* is this for us? */ 356 if ((cmd != MEMRANGE_GET) && 357 (cmd != MEMRANGE_SET)) 358 return (ENOTTY); 359 360 /* any chance we can handle this? */ 361 if (mem_range_softc.mr_op == NULL) 362 return (EOPNOTSUPP); 363 364 /* do we have any descriptors? */ 365 if (mem_range_softc.mr_ndesc == 0) 366 return (ENXIO); 367 368 switch (cmd) { 369 case MEMRANGE_GET: 370 nd = imin(mo->mo_arg[0], mem_range_softc.mr_ndesc); 371 if (nd > 0) { 372 md = (struct mem_range_desc *) 373 malloc(nd * sizeof(struct mem_range_desc), 374 M_MEMDESC, M_WAITOK); 375 error = mem_range_attr_get(md, &nd); 376 if (!error) 377 error = copyout(md, mo->mo_desc, 378 nd * sizeof(struct mem_range_desc)); 379 free(md, M_MEMDESC); 380 } else { 381 nd = mem_range_softc.mr_ndesc; 382 } 383 mo->mo_arg[0] = nd; 384 break; 385 386 case MEMRANGE_SET: 387 md = (struct mem_range_desc *)malloc(sizeof(struct mem_range_desc), 388 M_MEMDESC, M_WAITOK); 389 error = copyin(mo->mo_desc, md, sizeof(struct mem_range_desc)); 390 /* clamp description string */ 391 md->mr_owner[sizeof(md->mr_owner) - 1] = 0; 392 if (error == 0) 393 error = mem_range_attr_set(md, &mo->mo_arg[0]); 394 free(md, M_MEMDESC); 395 break; 396 } 397 return (error); 398 } 399 400 /* 401 * Implementation-neutral, kernel-callable functions for manipulating 402 * memory range attributes. 403 */ 404 int 405 mem_range_attr_get(mrd, arg) 406 struct mem_range_desc *mrd; 407 int *arg; 408 { 409 /* can we handle this? */ 410 if (mem_range_softc.mr_op == NULL) 411 return (EOPNOTSUPP); 412 413 if (*arg == 0) { 414 *arg = mem_range_softc.mr_ndesc; 415 } else { 416 bcopy(mem_range_softc.mr_desc, mrd, (*arg) * sizeof(struct mem_range_desc)); 417 } 418 return (0); 419 } 420 421 int 422 mem_range_attr_set(mrd, arg) 423 struct mem_range_desc *mrd; 424 int *arg; 425 { 426 /* can we handle this? */ 427 if (mem_range_softc.mr_op == NULL) 428 return (EOPNOTSUPP); 429 430 return (mem_range_softc.mr_op->set(&mem_range_softc, mrd, arg)); 431 } 432 433 #ifdef SMP 434 void 435 mem_range_AP_init(void) 436 { 437 if (mem_range_softc.mr_op && mem_range_softc.mr_op->initAP) 438 return (mem_range_softc.mr_op->initAP(&mem_range_softc)); 439 } 440 #endif 441 442 static int 443 random_ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) 444 { 445 int error; 446 int intr; 447 448 /* 449 * Even inspecting the state is privileged, since it gives a hint 450 * about how easily the randomness might be guessed. 451 */ 452 error = 0; 453 454 switch (cmd) { 455 /* Really handled in upper layer */ 456 case FIOASYNC: 457 break; 458 case MEM_SETIRQ: 459 intr = *(int16_t *)data; 460 if ((error = suser(td)) != 0) 461 break; 462 if (intr < 0 || intr >= MAX_INTS) 463 return (EINVAL); 464 register_randintr(intr); 465 break; 466 case MEM_CLEARIRQ: 467 intr = *(int16_t *)data; 468 if ((error = suser(td)) != 0) 469 break; 470 if (intr < 0 || intr >= MAX_INTS) 471 return (EINVAL); 472 unregister_randintr(intr); 473 break; 474 case MEM_RETURNIRQ: 475 error = ENOTSUP; 476 break; 477 case MEM_FINDIRQ: 478 intr = *(int16_t *)data; 479 if ((error = suser(td)) != 0) 480 break; 481 if (intr < 0 || intr >= MAX_INTS) 482 return (EINVAL); 483 intr = next_registered_randintr(intr); 484 if (intr == MAX_INTS) 485 return (ENOENT); 486 *(u_int16_t *)data = intr; 487 break; 488 default: 489 error = ENOTSUP; 490 break; 491 } 492 return (error); 493 } 494 495 int 496 mmpoll(dev_t dev, int events, struct thread *td) 497 { 498 switch (minor(dev)) { 499 case 3: /* /dev/random */ 500 return random_poll(dev, events, td); 501 case 4: /* /dev/urandom */ 502 default: 503 return seltrue(dev, events, td); 504 } 505 } 506 507 int 508 iszerodev(dev) 509 dev_t dev; 510 { 511 return ((major(dev) == mem_cdevsw.d_maj) 512 && minor(dev) == 12); 513 } 514 515 static void 516 mem_drvinit(void *unused) 517 { 518 519 /* Initialise memory range handling */ 520 if (mem_range_softc.mr_op != NULL) 521 mem_range_softc.mr_op->init(&mem_range_softc); 522 523 cdevsw_add(&mem_cdevsw, 0xf0, 0); 524 make_dev(&mem_cdevsw, 0, UID_ROOT, GID_KMEM, 0640, "mem"); 525 make_dev(&mem_cdevsw, 1, UID_ROOT, GID_KMEM, 0640, "kmem"); 526 make_dev(&mem_cdevsw, 2, UID_ROOT, GID_WHEEL, 0666, "null"); 527 make_dev(&mem_cdevsw, 3, UID_ROOT, GID_WHEEL, 0644, "random"); 528 make_dev(&mem_cdevsw, 4, UID_ROOT, GID_WHEEL, 0644, "urandom"); 529 make_dev(&mem_cdevsw, 12, UID_ROOT, GID_WHEEL, 0666, "zero"); 530 make_dev(&mem_cdevsw, 14, UID_ROOT, GID_WHEEL, 0600, "io"); 531 } 532 533 SYSINIT(memdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mem_drvinit,NULL) 534 535