1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * %sccs.include.redist.c% 15 * 16 * @(#)mem.c 8.1 (Berkeley) 06/11/93 17 * 18 * from: $Header: mem.c,v 1.9 92/11/26 03:05:03 torek Exp $ 19 */ 20 21 /* 22 * Memory special file 23 */ 24 25 #include <sys/param.h> 26 #include <sys/proc.h> 27 #include <sys/conf.h> 28 #include <sys/buf.h> 29 #include <sys/systm.h> 30 #include <sys/malloc.h> 31 32 #include <vm/vm.h> 33 34 /*ARGSUSED*/ 35 mmrw(dev, uio, flags) 36 dev_t dev; 37 struct uio *uio; 38 int flags; 39 { 40 register struct iovec *iov; 41 register caddr_t va; 42 register int o; 43 register u_int c; 44 int error = 0; 45 caddr_t zbuf = NULL; 46 extern caddr_t vmempage; 47 static struct { 48 int locked; 49 int wanted; 50 } physlock; 51 52 if (minor(dev) == 0) { 53 /* lock against other uses of shared vmempage */ 54 while (physlock.locked) { 55 physlock.wanted = 1; 56 (void)tsleep((caddr_t)&physlock, PZERO, "mmrw", 0); 57 } 58 physlock.locked = 1; 59 } 60 while (uio->uio_resid > 0 && error == 0) { 61 iov = uio->uio_iov; 62 if (iov->iov_len == 0) { 63 uio->uio_iov++; 64 uio->uio_iovcnt--; 65 if (uio->uio_iovcnt < 0) 66 panic("mmrw"); 67 continue; 68 } 69 switch (minor(dev)) { 70 71 /* minor device 0 is physical memory */ 72 case 0: 73 o = uio->uio_offset; 74 va = vmempage; 75 if (pmap_enter_hw(kernel_pmap, (vm_offset_t)va, 76 (vm_offset_t)trunc_page(o), 77 uio->uio_rw == UIO_READ ? 78 VM_PROT_READ : VM_PROT_WRITE, 1)) { 79 error = EFAULT; 80 goto unlock; 81 } 82 o = (int)uio->uio_offset & PGOFSET; 83 c = min(uio->uio_resid, (u_int)(NBPG - o)); 84 error = uiomove(&va[o], (int)c, uio); 85 pmap_remove(kernel_pmap, 86 (vm_offset_t)va, (vm_offset_t)va + PAGE_SIZE); 87 continue; 88 89 /* minor device 1 is kernel memory */ 90 case 1: 91 va = (caddr_t)uio->uio_offset; 92 c = min(iov->iov_len, MAXPHYS); 93 if (!kernacc(va, c, 94 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 95 return (EFAULT); 96 error = uiomove(va, (int)c, uio); 97 continue; 98 99 /* minor device 2 is EOF/RATHOLE */ 100 case 2: 101 if (uio->uio_rw == UIO_WRITE) 102 uio->uio_resid = 0; 103 return (0); 104 105 /* XXX should add sbus, `prom', etc */ 106 107 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ 108 case 12: 109 if (uio->uio_rw == UIO_WRITE) { 110 uio->uio_resid = 0; 111 return (0); 112 } 113 if (zbuf == NULL) { /* XXX grot */ 114 zbuf = (caddr_t)malloc(CLBYTES, 115 M_TEMP, M_WAITOK); 116 bzero(zbuf, CLBYTES); 117 } 118 c = min(iov->iov_len, CLBYTES); 119 error = uiomove(zbuf, (int)c, uio); 120 continue; 121 122 default: 123 return (ENXIO); 124 } 125 if (error) 126 break; 127 iov->iov_base += c; 128 iov->iov_len -= c; 129 uio->uio_offset += c; 130 uio->uio_resid -= c; 131 } 132 if (zbuf) 133 free(zbuf, M_TEMP); 134 if (minor(dev) == 0) { 135 unlock: 136 physlock.locked = 0; 137 if (physlock.wanted) 138 wakeup((caddr_t)&physlock); 139 } 140 return (error); 141 } 142