New routine "pmap_kenter", designed to take advantage of the special
[unix-history] / sys / kern / kern_physio.c
CommitLineData
dd403947
DG
1/*
2 * Copyright (c) 1989, 1990, 1991, 1992 William F. Jolitz, TeleMuse
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This software is a component of "386BSD" developed by
16 William F. Jolitz, TeleMuse.
17 * 4. Neither the name of the developer nor the name "386BSD"
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
22 * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
23 * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
24 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
25 * NOT MAKE USE THIS WORK.
26 *
27 * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
28 * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
29 * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
30 * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
31 * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
32 * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
33 * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
34 * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
37 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
42 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 *
7ffbd0e4 48 * $Id: kern_physio.c,v 1.3 1994/03/19 22:13:37 davidg Exp $
dd403947
DG
49 */
50
51#include "param.h"
52#include "systm.h"
53#include "buf.h"
54#include "conf.h"
55#include "proc.h"
56#include "malloc.h"
57#include "vnode.h"
58#include "vm/vm.h"
41aefbec 59#include "vm/vm_page.h"
dd403947
DG
60#include "specdev.h"
61
62/*
63 * Driver interface to do "raw" I/O in the address space of a
64 * user process directly for read and write operations..
65 */
66
67int
68rawread(dev, uio)
69 dev_t dev; struct uio *uio;
70{
71 return (uioapply(physio, (caddr_t) cdevsw[major(dev)].d_strategy,
72 (caddr_t) (u_long) dev, uio));
73}
74
75int
76rawwrite(dev, uio)
77 dev_t dev; struct uio *uio;
78{
79 return (uioapply(physio, (caddr_t) cdevsw[major(dev)].d_strategy,
80 (caddr_t) (u_long) dev, uio));
81}
82
83
84int physio(strat, dev, bp, off, rw, base, len, p)
85 d_strategy_t strat;
86 dev_t dev;
87 struct buf *bp;
88 int rw, off;
89 caddr_t base;
90 int *len;
91 struct proc *p;
92{
93 int amttodo = *len;
94 int error, amtdone;
95 vm_prot_t ftype;
41aefbec 96 vm_offset_t v, lastv, pa;
dd403947
DG
97 caddr_t adr;
98 int oldflags;
99 int s;
100
101 int bp_alloc = (bp == 0);
102
103/*
104 * keep the process from being swapped
105 */
106 oldflags = p->p_flag;
107 p->p_flag |= SPHYSIO;
108
109 rw = rw == UIO_READ ? B_READ : 0;
110
111 /* create and build a buffer header for a transfer */
112
113 if (bp_alloc) {
114 bp = (struct buf *)getpbuf();
115 bzero((char *)bp, sizeof(*bp)); /* 09 Sep 92*/
116 } else {
117 s = splbio();
118 while (bp->b_flags & B_BUSY) {
119 bp->b_flags |= B_WANTED;
120 tsleep((caddr_t)bp, PRIBIO, "physbw", 0);
121 }
122 bp->b_flags |= B_BUSY;
123 splx(s);
124 }
125
126 bp->b_flags = B_BUSY | B_PHYS | rw;
127 bp->b_proc = p;
128 bp->b_dev = dev;
129 bp->b_error = 0;
130 bp->b_blkno = off/DEV_BSIZE;
131 amtdone = 0;
132
133 /* iteratively do I/O on as large a chunk as possible */
134 do {
135 bp->b_flags &= ~B_DONE;
136 bp->b_un.b_addr = base;
137 /* XXX limit */
138 bp->b_bcount = min (256*1024, amttodo);
139
140 /* first, check if accessible */
141 if (rw == B_READ && !useracc(base, bp->b_bcount, B_WRITE)) {
142 error = EFAULT;
143 goto errrtn;
144 }
145 if (rw == B_WRITE && !useracc(base, bp->b_bcount, B_READ)) {
146 error = EFAULT;
147 goto errrtn;
148 }
149
150 /* update referenced and dirty bits, handle copy objects */
151 if (rw == B_READ)
152 ftype = VM_PROT_READ | VM_PROT_WRITE;
153 else
154 ftype = VM_PROT_READ;
155
156 lastv = 0;
157 for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bcount;
158 adr += NBPG) {
159
160/*
41aefbec 161 * make sure that the pde is valid and held
dd403947
DG
162 */
163 v = trunc_page(((vm_offset_t)vtopte(adr)));
164 if (v != lastv) {
41aefbec
DG
165
166 *(volatile int *)v += 0;
167 pa = pmap_extract(&p->p_vmspace->vm_pmap, v);
168 vm_page_hold(PHYS_TO_VM_PAGE(pa));
dd403947
DG
169 lastv = v;
170 }
171
172/*
173 * do the vm_fault if needed, do the copy-on-write thing when
174 * reading stuff off device into memory.
175 */
176 if (ftype & VM_PROT_WRITE) {
177 /*
178 * properly handle copy-on-write
179 */
180 *(volatile int *) adr += 0;
6232f830
DG
181 }
182#if defined(HOLD_WORKS_FOR_SHARING)
183 else {
dd403947
DG
184 *(volatile int *) adr;
185 }
41aefbec 186 pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t) adr);
dd403947 187/*
41aefbec 188 * hold the data page
dd403947 189 */
41aefbec 190 vm_page_hold(PHYS_TO_VM_PAGE(pa));
6232f830 191#endif
41aefbec 192 }
dd403947 193
6232f830
DG
194#if !defined(HOLD_WORKS_FOR_SHARING)
195 vslock(base, bp->b_bcount);
196#endif
dd403947
DG
197 /* perform transfer */
198 physstrat(bp, strat, PRIBIO);
6232f830
DG
199#if !defined(HOLD_WORKS_FOR_SHARING)
200 vsunlock(base, bp->b_bcount);
201#endif
dd403947 202
dd403947 203/*
41aefbec 204 * unhold the pde, and data pages
dd403947 205 */
41aefbec 206 lastv = 0;
dd403947
DG
207 for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bcount;
208 adr += NBPG) {
209 v = trunc_page(((vm_offset_t)vtopte(adr)));
210 if (v != lastv) {
41aefbec
DG
211 pa = pmap_extract(&p->p_vmspace->vm_pmap, v);
212 vm_page_unhold(PHYS_TO_VM_PAGE(pa));
dd403947
DG
213 lastv = v;
214 }
6232f830 215#if defined(HOLD_WORKS_FOR_SHARING)
41aefbec
DG
216 pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t) adr);
217 vm_page_unhold(PHYS_TO_VM_PAGE(pa));
6232f830 218#endif
dd403947
DG
219 }
220
221
222 amtdone = bp->b_bcount - bp->b_resid;
223 amttodo -= amtdone;
224 base += amtdone;
225 bp->b_blkno += amtdone/DEV_BSIZE;
226 } while (amttodo && (bp->b_flags & B_ERROR) == 0 && amtdone > 0);
227
228 error = bp->b_error;
229errrtn:
230 if (bp_alloc) {
231 relpbuf(bp);
232 } else {
233 bp->b_flags &= ~B_BUSY;
234 wakeup((caddr_t)bp);
235 }
236 *len = amttodo;
237
238/*
239 * allow the process to be swapped
240 */
241 p->p_flag &= ~SPHYSIO;
242 p->p_flag |= (oldflags & SPHYSIO);
243
244 return (error);
245}