1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1982, 1986, 1990, 1993 4 * The Regents of the University of California. 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. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: mem.c 1.14 90/10/12$ 13 * 14 * @(#)mem.c 8.3 (Berkeley) 01/12/94 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 extern u_int lowram; 35 caddr_t zeropage; 36 37 /*ARGSUSED*/ 38 mmrw(dev, uio, flags) 39 dev_t dev; 40 struct uio *uio; 41 int flags; 42 { 43 register int o; 44 register u_int c, v; 45 register struct iovec *iov; 46 int error = 0; 47 int kernloc; 48 49 while (uio->uio_resid > 0 && error == 0) { 50 iov = uio->uio_iov; 51 if (iov->iov_len == 0) { 52 uio->uio_iov++; 53 uio->uio_iovcnt--; 54 if (uio->uio_iovcnt < 0) 55 panic("mmrw"); 56 continue; 57 } 58 switch (minor(dev)) { 59 60 /* minor device 0 is physical memory */ 61 case 0: 62 v = uio->uio_offset; 63 #ifndef DEBUG 64 /* allow reads only in RAM (except for DEBUG) */ 65 if (v >= 0xFFFFFFFC || v < lowram) 66 return (EFAULT); 67 #endif 68 pmap_enter(kernel_pmap, (vm_offset_t)vmmap, 69 trunc_page(v), uio->uio_rw == UIO_READ ? 70 VM_PROT_READ : VM_PROT_WRITE, TRUE); 71 o = (int)uio->uio_offset & PGOFSET; 72 c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET)); 73 c = min(c, (u_int)(NBPG - o)); 74 c = min(c, (u_int)iov->iov_len); 75 error = uiomove((caddr_t)&vmmap[o], (int)c, uio); 76 pmap_remove(kernel_pmap, (vm_offset_t)vmmap, 77 (vm_offset_t)&vmmap[NBPG]); 78 continue; 79 80 /* minor device 1 is kernel memory */ 81 case 1: 82 kernloc = uio->uio_offset; 83 c = min(iov->iov_len, MAXPHYS); 84 if (!kernacc((caddr_t)kernloc, c, 85 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 86 return (EFAULT); 87 error = uiomove((caddr_t)kernloc, (int)c, uio); 88 continue; 89 90 /* minor device 2 is EOF/RATHOLE */ 91 case 2: 92 if (uio->uio_rw == UIO_WRITE) 93 uio->uio_resid = 0; 94 return (0); 95 96 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ 97 case 12: 98 if (uio->uio_rw == UIO_WRITE) { 99 c = iov->iov_len; 100 break; 101 } 102 /* 103 * On the first call, allocate and zero a page 104 * of memory for use with /dev/zero. 105 * 106 * XXX on the hp300 we already know where there 107 * is a global zeroed page, the null segment table. 108 */ 109 if (zeropage == NULL) { 110 #if CLBYTES == NBPG 111 extern caddr_t Segtabzero; 112 zeropage = Segtabzero; 113 #else 114 zeropage = (caddr_t) 115 malloc(CLBYTES, M_TEMP, M_WAITOK); 116 bzero(zeropage, CLBYTES); 117 #endif 118 } 119 c = min(iov->iov_len, CLBYTES); 120 error = uiomove(zeropage, (int)c, uio); 121 continue; 122 123 default: 124 return (ENXIO); 125 } 126 if (error) 127 break; 128 iov->iov_base += c; 129 iov->iov_len -= c; 130 uio->uio_offset += c; 131 uio->uio_resid -= c; 132 } 133 return (error); 134 } 135 136 mmmap(dev, off, prot) 137 dev_t dev; 138 int off, prot; 139 { 140 /* 141 * /dev/mem is the only one that makes sense through this 142 * interface. For /dev/kmem any physaddr we return here 143 * could be transient and hence incorrect or invalid at 144 * a later time. /dev/null just doesn't make any sense 145 * and /dev/zero is a hack that is handled via the default 146 * pager in mmap(). 147 */ 148 if (minor(dev) != 0) 149 return (-1); 150 /* 151 * Allow access only in RAM. 152 * 153 * XXX could be extended to allow access to IO space but must 154 * be very careful. 155 */ 156 if ((unsigned)off < lowram || (unsigned)off >= 0xFFFFFFFC) 157 return (-1); 158 return (hp300_btop(off)); 159 } 160