Files
retrobsd/sys/kernel/vm_swp.c
Serge Vakulenko 585773955b Fix include paths in the kernel sources.
Max32 kernel successfully compiled with kconfig utility.
2015-08-31 00:21:41 -07:00

176 lines
5.4 KiB
C

/*
* Copyright (c) 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <sys/param.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/systm.h>
#include <sys/vm.h>
#include <sys/uio.h>
/*
* swap I/O
*/
void
swap (blkno, coreaddr, count, rdflg)
size_t blkno, coreaddr;
register int count;
int rdflg;
{
register struct buf *bp;
int s;
//printf ("swap (%u, %08x, %d, %s)\n", blkno, coreaddr, count, rdflg ? "R" : "W");
#ifdef UCB_METER
if (rdflg) {
cnt.v_kbin += (count + 1023) / 1024;
} else {
cnt.v_kbout += (count + 1023) / 1024;
}
#endif
bp = geteblk(); /* allocate a buffer header */
while (count) {
bp->b_flags = B_BUSY | B_PHYS | B_INVAL | rdflg;
bp->b_dev = swapdev;
bp->b_bcount = count;
bp->b_blkno = blkno;
bp->b_addr = (caddr_t) coreaddr;
(*bdevsw[major(swapdev)].d_strategy) (bp);
s = splbio();
while ((bp->b_flags & B_DONE) == 0)
sleep ((caddr_t)bp, PSWP);
splx (s);
if ((bp->b_flags & B_ERROR) || bp->b_resid)
panic ("hard err: swap");
count -= count;
coreaddr += count;
blkno += btod (count);
}
brelse(bp);
}
/*
* Raw I/O. The arguments are
* The strategy routine for the device
* A buffer, which may be a special buffer header
* owned exclusively by the device for this purpose or
* NULL if one is to be allocated.
* The device number
* Read/write flag
* Essentially all the work is computing physical addresses and
* validating them.
*
* rewritten to use the iov/uio mechanism from 4.3bsd. the physbuf routine
* was inlined. essentially the chkphys routine performs the same task
* as the useracc routine on a 4.3 system. 3/90 sms
*
* If the buffer pointer is NULL then one is allocated "dynamically" from
* the system cache. the 'invalid' flag is turned on so that the brelse()
* done later doesn't place the buffer back in the cache. the 'phys' flag
* is left on so that the address of the buffer is recalcuated in getnewbuf().
* The BYTE/WORD stuff began to be removed after testing proved that either
* 1) the underlying hardware gives an error or 2) nothing bad happens.
* besides, 4.3BSD doesn't do the byte/word check and noone could remember
* why the byte/word check was added in the first place - likely historical
* paranoia. chkphys() inlined. 5/91 sms
*
* Refined (and streamlined) the flow by using a 'for' construct
* (a la 4.3Reno). Avoid allocating/freeing the buffer for each iovec
* element (i must have been confused at the time). 6/91-sms
*
* Finished removing the BYTE/WORD code as part of implementing the common
* raw read&write routines , systems had been running fine for several
* months with it ifdef'd out. 9/91-sms
*/
int
physio(strat, bp, dev, rw, uio)
void (*strat) (struct buf*);
register struct buf *bp;
dev_t dev;
int rw;
register struct uio *uio;
{
int error = 0, s, c, allocbuf = 0;
register struct iovec *iov;
if (! bp) {
allocbuf++;
bp = geteblk();
}
u.u_procp->p_flag |= SLOCK;
for ( ; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) {
iov = uio->uio_iov;
if (iov->iov_base >= iov->iov_base + iov->iov_len) {
error = EFAULT;
break;
}
/*
* Check that transfer is either entirely in the
* data or in the stack: that is, either
* the end is in the data or the start is in the stack
* (remember wraparound was already checked).
*/
if (baduaddr (iov->iov_base) ||
baduaddr (iov->iov_base + iov->iov_len - 1)) {
error = EFAULT;
break;
}
if (! allocbuf) {
s = splbio();
while (bp->b_flags & B_BUSY) {
bp->b_flags |= B_WANTED;
sleep((caddr_t)bp, PRIBIO+1);
}
splx(s);
}
bp->b_error = 0;
while (iov->iov_len) {
bp->b_flags = B_BUSY | B_PHYS | B_INVAL | rw;
bp->b_dev = dev;
bp->b_addr = iov->iov_base;
bp->b_blkno = (unsigned) uio->uio_offset >> DEV_BSHIFT;
bp->b_bcount = iov->iov_len;
c = bp->b_bcount;
(*strat)(bp);
s = splbio();
while ((bp->b_flags & B_DONE) == 0)
sleep((caddr_t)bp, PRIBIO);
if (bp->b_flags & B_WANTED) /* rare */
wakeup((caddr_t)bp);
splx(s);
c -= bp->b_resid;
iov->iov_base += c;
iov->iov_len -= c;
uio->uio_resid -= c;
uio->uio_offset += c;
/* temp kludge for tape drives */
if (bp->b_resid || (bp->b_flags & B_ERROR))
break;
}
bp->b_flags &= ~(B_BUSY | B_WANTED);
error = geterror(bp);
/* temp kludge for tape drives */
if (bp->b_resid || error)
break;
}
if (allocbuf)
brelse(bp);
u.u_procp->p_flag &= ~SLOCK;
return(error);
}
int
rawrw (dev, uio, flag)
dev_t dev;
register struct uio *uio;
int flag;
{
return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, dev,
uio->uio_rw == UIO_READ ? B_READ : B_WRITE, uio));
}