1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1992 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 Ralph Campbell. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: mem.c 1.14 90/10/12$ 13 * 14 * @(#)mem.c 7.6 (Berkeley) 10/11/92 15 */ 16 17 /* 18 * Memory special file 19 */ 20 21 #include <sys/param.h> 22 #include <sys/conf.h> 23 #include <sys/buf.h> 24 #include <sys/systm.h> 25 #include <sys/malloc.h> 26 27 #include <machine/cpu.h> 28 29 #include <vm/vm_param.h> 30 #include <vm/lock.h> 31 #include <vm/vm_prot.h> 32 #include <vm/pmap.h> 33 34 /*ARGSUSED*/ 35 mmrw(dev, uio, flags) 36 dev_t dev; 37 struct uio *uio; 38 int flags; 39 { 40 register u_long v; 41 register u_int c; 42 register struct iovec *iov; 43 int error = 0; 44 caddr_t zbuf = NULL; 45 extern vm_offset_t avail_end; 46 47 while (uio->uio_resid > 0 && error == 0) { 48 iov = uio->uio_iov; 49 if (iov->iov_len == 0) { 50 uio->uio_iov++; 51 uio->uio_iovcnt--; 52 if (uio->uio_iovcnt < 0) 53 panic("mmrw"); 54 continue; 55 } 56 switch (minor(dev)) { 57 58 /* minor device 0 is physical memory */ 59 case 0: 60 v = (u_long)uio->uio_offset; 61 c = iov->iov_len; 62 if (v + c >= physmem) 63 return (EFAULT); 64 error = uiomove((caddr_t)(MACH_CACHED_MEMORY_ADDR + v), 65 (int)c, uio); 66 continue; 67 68 /* minor device 1 is kernel memory */ 69 case 1: 70 v = (u_long)uio->uio_offset; 71 if (v < MACH_CACHED_MEMORY_ADDR) 72 return (EFAULT); 73 c = iov->iov_len; 74 if (v + c <= MACH_PHYS_TO_CACHED(avail_end) || 75 v >= MACH_KSEG2_ADDR && kernacc((caddr_t)v, c, 76 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) { 77 error = uiomove((caddr_t)v, (int)c, uio); 78 continue; 79 } 80 return (EFAULT); 81 82 /* minor device 2 is EOF/RATHOLE */ 83 case 2: 84 if (uio->uio_rw == UIO_WRITE) 85 uio->uio_resid = 0; 86 return (0); 87 88 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ 89 case 12: 90 if (uio->uio_rw == UIO_WRITE) { 91 c = iov->iov_len; 92 break; 93 } 94 if (zbuf == NULL) { 95 zbuf = (caddr_t) 96 malloc(CLBYTES, M_TEMP, M_WAITOK); 97 bzero(zbuf, CLBYTES); 98 } 99 c = min(iov->iov_len, CLBYTES); 100 error = uiomove(zbuf, (int)c, uio); 101 continue; 102 103 default: 104 return (ENXIO); 105 } 106 if (error) 107 break; 108 iov->iov_base += c; 109 iov->iov_len -= c; 110 uio->uio_offset += c; 111 uio->uio_resid -= c; 112 } 113 if (zbuf) 114 free(zbuf, M_TEMP); 115 return (error); 116 } 117