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