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