Index: head/sys/x86/iommu/busdma_dmar.c =================================================================== --- head/sys/x86/iommu/busdma_dmar.c +++ head/sys/x86/iommu/busdma_dmar.c @@ -665,9 +665,9 @@ { struct bus_dma_tag_dmar *tag; struct bus_dmamap_dmar *map; - vm_page_t *ma; - vm_paddr_t pstart, pend; - int error, i, ma_cnt, offset; + vm_page_t *ma, fma; + vm_paddr_t pstart, pend, paddr; + int error, i, ma_cnt, mflags, offset; tag = (struct bus_dma_tag_dmar *)dmat; map = (struct bus_dmamap_dmar *)map1; @@ -675,14 +675,36 @@ pend = round_page(buf + buflen); offset = buf & PAGE_MASK; ma_cnt = OFF_TO_IDX(pend - pstart); - ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, map->cansleep ? - M_WAITOK : M_NOWAIT); + mflags = map->cansleep ? M_WAITOK : M_NOWAIT; + ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, mflags); if (ma == NULL) return (ENOMEM); - for (i = 0; i < ma_cnt; i++) - ma[i] = PHYS_TO_VM_PAGE(pstart + i * PAGE_SIZE); + fma = NULL; + for (i = 0; i < ma_cnt; i++) { + paddr = pstart + i * PAGE_SIZE; + ma[i] = PHYS_TO_VM_PAGE(paddr); + if (ma[i] == NULL || VM_PAGE_TO_PHYS(ma[i]) != paddr) { + /* + * If PHYS_TO_VM_PAGE() returned NULL or the + * vm_page was not initialized we'll use a + * fake page. + */ + if (fma == NULL) { + fma = malloc(sizeof(struct vm_page) * ma_cnt, + M_DEVBUF, mflags); + if (fma == NULL) { + free(ma, M_DEVBUF); + return (ENOMEM); + } + } + vm_page_initfake(&fma[i], pstart + i * PAGE_SIZE, + VM_MEMATTR_DEFAULT); + ma[i] = &fma[i]; + } + } error = dmar_bus_dmamap_load_something(tag, map, ma, offset, buflen, flags, segs, segp); + free(fma, M_DEVBUF); free(ma, M_DEVBUF); return (error); } @@ -696,7 +718,7 @@ struct bus_dmamap_dmar *map; vm_page_t *ma, fma; vm_paddr_t pstart, pend, paddr; - int error, i, ma_cnt, offset; + int error, i, ma_cnt, mflags, offset; tag = (struct bus_dma_tag_dmar *)dmat; map = (struct bus_dmamap_dmar *)map1; @@ -704,41 +726,33 @@ pend = round_page((vm_offset_t)buf + buflen); offset = (vm_offset_t)buf & PAGE_MASK; ma_cnt = OFF_TO_IDX(pend - pstart); - ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, map->cansleep ? - M_WAITOK : M_NOWAIT); + mflags = map->cansleep ? M_WAITOK : M_NOWAIT; + ma = malloc(sizeof(vm_page_t) * ma_cnt, M_DEVBUF, mflags); if (ma == NULL) return (ENOMEM); - if (dumping) { - /* - * If dumping, do not attempt to call - * PHYS_TO_VM_PAGE() at all. It may return non-NULL - * but the vm_page returned might be not initialized, - * e.g. for the kernel itself. - */ - KASSERT(pmap == kernel_pmap, ("non-kernel address write")); - fma = malloc(sizeof(struct vm_page) * ma_cnt, M_DEVBUF, - M_ZERO | (map->cansleep ? M_WAITOK : M_NOWAIT)); - if (fma == NULL) { - free(ma, M_DEVBUF); - return (ENOMEM); - } - for (i = 0; i < ma_cnt; i++, pstart += PAGE_SIZE) { + fma = NULL; + for (i = 0; i < ma_cnt; i++, pstart += PAGE_SIZE) { + if (pmap == kernel_pmap) paddr = pmap_kextract(pstart); + else + paddr = pmap_extract(pmap, pstart); + ma[i] = PHYS_TO_VM_PAGE(paddr); + if (ma[i] == NULL || VM_PAGE_TO_PHYS(ma[i]) != paddr) { + /* + * If PHYS_TO_VM_PAGE() returned NULL or the + * vm_page was not initialized we'll use a + * fake page. + */ + if (fma == NULL) { + fma = malloc(sizeof(struct vm_page) * ma_cnt, + M_DEVBUF, mflags); + if (fma == NULL) { + free(ma, M_DEVBUF); + return (ENOMEM); + } + } vm_page_initfake(&fma[i], paddr, VM_MEMATTR_DEFAULT); ma[i] = &fma[i]; - } - } else { - fma = NULL; - for (i = 0; i < ma_cnt; i++, pstart += PAGE_SIZE) { - if (pmap == kernel_pmap) - paddr = pmap_kextract(pstart); - else - paddr = pmap_extract(pmap, pstart); - ma[i] = PHYS_TO_VM_PAGE(paddr); - KASSERT(VM_PAGE_TO_PHYS(ma[i]) == paddr, - ("PHYS_TO_VM_PAGE failed %jx %jx m %p", - (uintmax_t)paddr, (uintmax_t)VM_PAGE_TO_PHYS(ma[i]), - ma[i])); } } error = dmar_bus_dmamap_load_something(tag, map, ma, offset, buflen,