[PowerPC] fix panic reading /dev/kmem on !DMAP machines
This fixes /dev/kmem causing panic on machines not using DMAP. Found when running libkvm Kyua test case on QEMU VM with no Huge Pages support. Reviewed by: jhibbits, luporl Approved by: jhibbits (mentor) Sponsored by: Eldorado Research Institute (eldorado.org.br) Differential Revision: https://reviews.freebsd.org/D23776
This commit is contained in:
parent
aa301e5ffe
commit
d2d06767b5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=359160
@ -98,9 +98,11 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
|
||||
struct vm_page m;
|
||||
vm_page_t marr;
|
||||
vm_size_t cnt;
|
||||
ssize_t orig_resid;
|
||||
|
||||
cnt = 0;
|
||||
error = 0;
|
||||
orig_resid = uio->uio_resid;
|
||||
|
||||
while (uio->uio_resid > 0 && !error) {
|
||||
iov = uio->uio_iov;
|
||||
@ -137,7 +139,8 @@ kmem_direct_mapped: off = v & PAGE_MASK;
|
||||
else if (dev2unit(dev) == CDEV_MINOR_KMEM) {
|
||||
va = uio->uio_offset;
|
||||
|
||||
if ((va < VM_MIN_KERNEL_ADDRESS) || (va > virtual_end)) {
|
||||
if (hw_direct_map &&
|
||||
((va < VM_MIN_KERNEL_ADDRESS) || (va > virtual_end))) {
|
||||
v = DMAP_TO_PHYS(va);
|
||||
goto kmem_direct_mapped;
|
||||
}
|
||||
@ -151,24 +154,34 @@ kmem_direct_mapped: off = v & PAGE_MASK;
|
||||
* so that we don't create any zero-fill pages.
|
||||
*/
|
||||
|
||||
for (; va < eva; va += PAGE_SIZE)
|
||||
if (pmap_extract(kernel_pmap, va) == 0)
|
||||
return (EFAULT);
|
||||
for (; va < eva; va += PAGE_SIZE) {
|
||||
if (pmap_extract(kernel_pmap, va) == 0) {
|
||||
error = EFAULT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (error != 0)
|
||||
break;
|
||||
|
||||
prot = (uio->uio_rw == UIO_READ)
|
||||
? VM_PROT_READ : VM_PROT_WRITE;
|
||||
|
||||
va = uio->uio_offset;
|
||||
if (kernacc((void *) va, iov->iov_len, prot)
|
||||
== FALSE)
|
||||
return (EFAULT);
|
||||
if (((va >= VM_MIN_KERNEL_ADDRESS) && (va <= virtual_end)) &&
|
||||
!kernacc((void *) va, iov->iov_len, prot)) {
|
||||
error = EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
error = uiomove((void *)va, iov->iov_len, uio);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't return error if any byte was written. Read and write
|
||||
* can return error only if no i/o was performed.
|
||||
*/
|
||||
if (uio->uio_resid != orig_resid)
|
||||
error = 0;
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user