Index: sys/arm64/arm64/mem.c =================================================================== --- sys/arm64/arm64/mem.c +++ sys/arm64/arm64/mem.c @@ -49,11 +49,10 @@ memrw(struct cdev *dev, struct uio *uio, int flags) { struct iovec *iov; - struct vm_page m; - vm_page_t marr; - vm_offset_t off, v; + vm_offset_t off, v, p; u_int cnt; int error; + void *ptr; error = 0; @@ -67,7 +66,7 @@ continue; } - v = uio->uio_offset; + p = v = uio->uio_offset; off = v & PAGE_MASK; cnt = ulmin(iov->iov_len, PAGE_SIZE - (u_int)off); if (cnt == 0) @@ -88,8 +87,8 @@ } /* Get the physical address to read */ - v = pmap_extract(kernel_pmap, v); - if (v == 0) { + p = pmap_extract(kernel_pmap, v); + if (p == 0) { error = EFAULT; break; } @@ -97,16 +96,15 @@ /* FALLTHROUGH */ case CDEV_MINOR_MEM: /* If within the DMAP use this to copy from */ - if (PHYS_IN_DMAP(v)) { - v = PHYS_TO_DMAP(v); + if (PHYS_IN_DMAP_STRICT(p)) { + v = PHYS_TO_DMAP(p); error = uiomove((void *)v, cnt, uio); break; } - /* Have uiomove_fromphys handle the data */ - m.phys_addr = trunc_page(v); - marr = &m; - uiomove_fromphys(&marr, off, cnt, uio); + ptr = pmap_mapdev(p, PAGE_SIZE); + error = uiomove((void*)ptr, cnt, uio); + pmap_unmapdev((vm_offset_t)ptr, PAGE_SIZE); break; } } Index: sys/arm64/arm64/pmap.c =================================================================== --- sys/arm64/arm64/pmap.c +++ sys/arm64/arm64/pmap.c @@ -6963,6 +6963,19 @@ return (mode >= VM_MEMATTR_DEVICE && mode <= VM_MEMATTR_WRITE_THROUGH); } +bool +pmap_phys_in_dmap_strict(vm_paddr_t pa) +{ + int i; + + for (i = 0; i < physmap_idx * 2; i += 2) { + if ((physmap[i] <= pa) && (pa <= physmap[i+1])) + return true; + } + + return false; +} + /* * Track a range of the kernel's virtual address space that is contiguous * in various mapping attributes. Index: sys/arm64/include/pmap.h =================================================================== --- sys/arm64/include/pmap.h +++ sys/arm64/include/pmap.h @@ -56,6 +56,8 @@ #define pmap_page_is_write_mapped(m) (((m)->a.flags & PGA_WRITEABLE) != 0) void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); +bool pmap_phys_in_dmap_strict(vm_paddr_t pa); + /* * Pmap stuff */ Index: sys/arm64/include/vmparam.h =================================================================== --- sys/arm64/include/vmparam.h +++ sys/arm64/include/vmparam.h @@ -163,12 +163,14 @@ #define DMAP_MIN_PHYSADDR (dmap_phys_base) #define DMAP_MAX_PHYSADDR (dmap_phys_max) -/* True if pa is in the dmap range */ +/* True if pa is in the dmap range, between min and max addresses */ #define PHYS_IN_DMAP(pa) ((pa) >= DMAP_MIN_PHYSADDR && \ (pa) < DMAP_MAX_PHYSADDR) /* True if va is in the dmap range */ #define VIRT_IN_DMAP(va) ((va) >= DMAP_MIN_ADDRESS && \ (va) < (dmap_max_addr)) +/* True if pa is strictly in dmap range, taking into account sparseness */ +#define PHYS_IN_DMAP_STRICT(pa) pmap_phys_in_dmap_strict((pa)) #define PMAP_HAS_DMAP 1 #define PHYS_TO_DMAP(pa) \