1: /*
2: * Copyright (c) 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)vm_swp.c 2.3 (2.11BSD) 11/30/94
7: */
8:
9: #include "param.h"
10: #include "../machine/seg.h"
11:
12: #include "user.h"
13: #include "proc.h"
14: #include "buf.h"
15: #include "conf.h"
16: #include "systm.h"
17: #include "vm.h"
18: #include "trace.h"
19: #include "uio.h"
20:
21: /*
22: * swap I/O
23: */
24: swap(blkno, coreaddr, count, rdflg)
25: memaddr blkno, coreaddr;
26: register int count;
27: int rdflg;
28: {
29: register struct buf *bp;
30: register int tcount;
31: int s;
32:
33: #ifdef UCB_METER
34: if (rdflg) {
35: cnt.v_pswpin += count;
36: cnt.v_pgin++;
37: }
38: else {
39: cnt.v_pswpout += count;
40: cnt.v_pgout++;
41: }
42: #endif
43: bp = geteblk(); /* allocate a buffer header */
44:
45: while (count) {
46: bp->b_flags = B_BUSY | B_PHYS | B_INVAL | rdflg;
47: bp->b_dev = swapdev;
48: tcount = count;
49: if (tcount >= 01700) /* prevent byte-count wrap */
50: tcount = 01700;
51: bp->b_bcount = ctob(tcount);
52: bp->b_blkno = blkno;
53: bp->b_un.b_addr = (caddr_t)(coreaddr<<6);
54: bp->b_xmem = (coreaddr>>10) & 077;
55: trace(TR_SWAPIO);
56: (*bdevsw[major(swapdev)].d_strategy)(bp);
57: s = splbio();
58: while ((bp->b_flags & B_DONE) == 0)
59: sleep((caddr_t)bp, PSWP);
60: splx(s);
61: if ((bp->b_flags & B_ERROR) || bp->b_resid)
62: panic("hard err: swap");
63: count -= tcount;
64: coreaddr += tcount;
65: blkno += ctod(tcount);
66: }
67: brelse(bp);
68: }
69:
70: /*
71: * rout is the name of the routine where we ran out of swap space.
72: */
73: swkill(p, rout)
74: register struct proc *p;
75: char *rout;
76: {
77:
78: tprintf(u.u_ttyp, "sorry, pid %d killed in %s: no swap space\n",
79: p->p_pid, rout);
80: /*
81: * To be sure no looping (e.g. in vmsched trying to
82: * swap out) mark process locked in core (as though
83: * done by user) after killing it so noone will try
84: * to swap it out.
85: */
86: psignal(p, SIGKILL);
87: p->p_flag |= SULOCK;
88: }
89:
90: /*
91: * Raw I/O. The arguments are
92: * The strategy routine for the device
93: * A buffer, which may be a special buffer header
94: * owned exclusively by the device for this purpose or
95: * NULL if one is to be allocated.
96: * The device number
97: * Read/write flag
98: * Essentially all the work is computing physical addresses and
99: * validating them.
100: *
101: * rewritten to use the iov/uio mechanism from 4.3bsd. the physbuf routine
102: * was inlined. essentially the chkphys routine performs the same task
103: * as the useracc routine on a 4.3 system. 3/90 sms
104: *
105: * If the buffer pointer is NULL then one is allocated "dynamically" from
106: * the system cache. the 'invalid' flag is turned on so that the brelse()
107: * done later doesn't place the buffer back in the cache. the 'phys' flag
108: * is left on so that the address of the buffer is recalcuated in getnewbuf().
109: * The BYTE/WORD stuff began to be removed after testing proved that either
110: * 1) the underlying hardware gives an error or 2) nothing bad happens.
111: * besides, 4.3BSD doesn't do the byte/word check and noone could remember
112: * why the byte/word check was added in the first place - likely historical
113: * paranoia. chkphys() inlined. 5/91 sms
114: *
115: * Refined (and streamlined) the flow by using a 'for' construct
116: * (a la 4.3Reno). Avoid allocating/freeing the buffer for each iovec
117: * element (i must have been confused at the time). 6/91-sms
118: *
119: * Finished removing the BYTE/WORD code as part of implementing the common
120: * raw read&write routines , systems had been running fine for several
121: * months with it ifdef'd out. 9/91-sms
122: */
123: physio(strat, bp, dev, rw, uio)
124: int (*strat)();
125: register struct buf *bp;
126: dev_t dev;
127: int rw;
128: register struct uio *uio;
129: {
130: int error = 0, s, nb, ts, c, allocbuf = 0;
131: register struct iovec *iov;
132:
133: if (!bp) {
134: allocbuf++;
135: bp = geteblk();
136: }
137: u.u_procp->p_flag |= SLOCK;
138: for ( ; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) {
139: iov = uio->uio_iov;
140: if (iov->iov_base >= iov->iov_base + iov->iov_len) {
141: error = EFAULT;
142: break;
143: }
144: if (u.u_sep)
145: ts = 0;
146: else
147: ts = (u.u_tsize + 127) & ~0177;
148: nb = ((int)iov->iov_base >> 6) & 01777;
149: /*
150: * Check overlap with text. (ts and nb now
151: * in 64-byte clicks)
152: */
153: if (nb < ts) {
154: error = EFAULT;
155: break;
156: }
157: /*
158: * Check that transfer is either entirely in the
159: * data or in the stack: that is, either
160: * the end is in the data or the start is in the stack
161: * (remember wraparound was already checked).
162: */
163: if (((((int)iov->iov_base + iov->iov_len) >> 6) & 01777) >=
164: ts + u.u_dsize && nb < 1024 - u.u_ssize) {
165: error = EFAULT;
166: break;
167: }
168: if (!allocbuf) {
169: s = splbio();
170: while (bp->b_flags & B_BUSY) {
171: bp->b_flags |= B_WANTED;
172: sleep((caddr_t)bp, PRIBIO+1);
173: }
174: splx(s);
175: }
176: bp->b_error = 0;
177: while (iov->iov_len) {
178: bp->b_flags = B_BUSY|B_PHYS|B_INVAL|rw;
179: bp->b_dev = dev;
180: nb = ((int)iov->iov_base >> 6) & 01777;
181: ts = (u.u_sep ? UDSA : UISA)[nb >> 7] + (nb & 0177);
182: bp->b_un.b_addr = (caddr_t)((ts << 6) + ((int)iov->iov_base & 077));
183: bp->b_xmem = (ts >> 10) & 077;
184: bp->b_blkno = uio->uio_offset >> PGSHIFT;
185: bp->b_bcount = iov->iov_len;
186: c = bp->b_bcount;
187: (*strat)(bp);
188: s = splbio();
189: while ((bp->b_flags & B_DONE) == 0)
190: sleep((caddr_t)bp, PRIBIO);
191: if (bp->b_flags & B_WANTED) /* rare */
192: wakeup((caddr_t)bp);
193: splx(s);
194: c -= bp->b_resid;
195: iov->iov_base += c;
196: iov->iov_len -= c;
197: uio->uio_resid -= c;
198: uio->uio_offset += c;
199: /* temp kludge for tape drives */
200: if (bp->b_resid || (bp->b_flags & B_ERROR))
201: break;
202: }
203: bp->b_flags &= ~(B_BUSY|B_WANTED);
204: error = geterror(bp);
205: /* temp kludge for tape drives */
206: if (bp->b_resid || error)
207: break;
208: }
209: if (allocbuf)
210: brelse(bp);
211: u.u_procp->p_flag &= ~SLOCK;
212: return(error);
213: }
214:
215: rawrw(dev, uio, flag)
216: dev_t dev;
217: register struct uio *uio;
218: int flag;
219: {
220: return(physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, dev,
221: uio->uio_rw == UIO_READ ? B_READ : B_WRITE, uio));
222: }
Defined functions
rawrw
defined in line
215; used 27 times
swap
defined in line
24; used 10 times