Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_uio.c
Show First 20 Lines • Show All 273 Lines • ▼ Show 20 Lines | while (n > 0 && uio->uio_resid) { | ||||
n -= cnt; | n -= cnt; | ||||
} | } | ||||
out: | out: | ||||
if (save) | if (save) | ||||
curthread_pflags_restore(save); | curthread_pflags_restore(save); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | |||||
uiobiomove(void *cp, int n, struct uio_bio *uio) | |||||
{ | |||||
vm_paddr_t paddr; | |||||
int rc; | |||||
struct iovec iov[1]; | |||||
struct uio auio; | |||||
ssize_t resid, size; | |||||
int pageoff, pageidx; | |||||
KASSERT(uio->uio_ma_offset + n <= (uio->uio_ma_cnt << PAGE_SHIFT), | |||||
("byte count too large offset: %ju count: %d size: %d", | |||||
uio->uio_ma_offset, n, uio->uio_ma_cnt << PAGE_SHIFT)); | |||||
pageoff = uio->uio_ma_offset & PAGE_MASK; | |||||
pageidx = uio->uio_ma_offset >> PAGE_SHIFT; | |||||
if (pageoff) { | |||||
size = min(PAGE_SIZE - pageoff, n); | |||||
paddr = VM_PAGE_TO_PHYS(uio->uio_ma[pageidx]) + pageoff; | |||||
/* | |||||
* This is confusing because the user addresses are physical | |||||
* and the kernel addresses are virtual, so the naming is | |||||
* reversed. | |||||
*/ | |||||
if (uio->uio_cmd == UIO_BIO_READ) | |||||
rc = physcopyin(cp, paddr, size); | |||||
else if (uio->uio_cmd == UIO_BIO_WRITE) | |||||
rc = physcopyout(paddr, cp, size); | |||||
else | |||||
panic("invalid command to uiobiomove: %d", uio->uio_cmd); | |||||
n -= size; | |||||
if (rc != 0) | |||||
return (rc); | |||||
pageidx++; | |||||
uio->uio_ma_offset += size; | |||||
uio->uio_offset += size; | |||||
uio->uio_resid -= size; | |||||
cp = ((char *)cp) + size; | |||||
} | |||||
iov[0].iov_base = cp; | |||||
iov[0].iov_len = n; | |||||
auio.uio_iov = iov; | |||||
auio.uio_iovcnt = 1; | |||||
auio.uio_offset = 0; | |||||
resid = auio.uio_resid = uio->uio_resid; | |||||
auio.uio_segflg = UIO_SYSSPACE; | |||||
/* | |||||
* Again reversed because user is physical | |||||
*/ | |||||
if (uio->uio_cmd == UIO_BIO_READ) | |||||
auio.uio_rw = UIO_WRITE; | |||||
else if (uio->uio_cmd == UIO_BIO_WRITE) | |||||
auio.uio_rw = UIO_READ; | |||||
else | |||||
panic("invalid command to uiobiomove: %d", uio->uio_cmd); | |||||
rc = uiomove_fromphys(uio->uio_ma + pageidx, 0, n, &auio); | |||||
if (rc == 0) { | |||||
size = (resid - auio.uio_resid); | |||||
uio->uio_resid -= size; | |||||
uio->uio_offset += size; | |||||
uio->uio_ma_offset += size; | |||||
} | |||||
return (rc); | |||||
} | |||||
/* | /* | ||||
* Wrapper for uiomove() that validates the arguments against a known-good | * Wrapper for uiomove() that validates the arguments against a known-good | ||||
* kernel buffer. Currently, uiomove accepts a signed (n) argument, which | * kernel buffer. Currently, uiomove accepts a signed (n) argument, which | ||||
* is almost definitely a bad thing, so we catch that here as well. We | * is almost definitely a bad thing, so we catch that here as well. We | ||||
* return a runtime failure, but it might be desirable to generate a runtime | * return a runtime failure, but it might be desirable to generate a runtime | ||||
* assertion failure instead. | * assertion failure instead. | ||||
*/ | */ | ||||
int | int | ||||
▲ Show 20 Lines • Show All 225 Lines • Show Last 20 Lines |