Index: sys/x86/include/bus_dma.h =================================================================== --- sys/x86/include/bus_dma.h +++ sys/x86/include/bus_dma.h @@ -192,6 +192,8 @@ } bool bus_dma_dmar_set_buswide(device_t dev); +int bus_dma_dmar_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t start, vm_size_t length, int flags); #endif /* !_X86_BUS_DMA_H_ */ Index: sys/x86/iommu/busdma_dmar.c =================================================================== --- sys/x86/iommu/busdma_dmar.c +++ sys/x86/iommu/busdma_dmar.c @@ -973,3 +973,66 @@ taskqueue_free(unit->delayed_taskqueue); unit->delayed_taskqueue = NULL; } + +int +bus_dma_dmar_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map1, + vm_paddr_t start, vm_size_t length, int flags) +{ + struct bus_dma_tag_common *tc; + struct bus_dma_tag_dmar *tag; + struct bus_dmamap_dmar *map; + struct dmar_ctx *ctx; + struct dmar_domain *domain; + struct dmar_map_entry *entry; + vm_page_t *ma; + vm_size_t i; + int error; + bool waitok; + + MPASS((start & PAGE_MASK) == 0); + MPASS((length & PAGE_MASK) == 0); + MPASS(length > 0); + MPASS(start + length >= start); + MPASS((flags & ~(BUS_DMA_NOWAIT | BUS_DMA_NOWRITE)) == 0); + + tc = (struct bus_dma_tag_common *)dmat; + if (tc->impl != &bus_dma_dmar_impl) + return (0); + + tag = (struct bus_dma_tag_dmar *)dmat; + ctx = tag->ctx; + domain = ctx->domain; + map = (struct bus_dmamap_dmar *)map1; + waitok = (flags & BUS_DMA_NOWAIT) != 0; + + entry = dmar_gas_alloc_entry(domain, waitok ? 0 : DMAR_PGF_WAITOK); + if (entry == NULL) + return (ENOMEM); + entry->start = start; + entry->end = start + length; + ma = malloc(sizeof(vm_page_t) * atop(length), M_TEMP, waitok ? + M_WAITOK : M_NOWAIT); + if (ma == NULL) { + dmar_gas_free_entry(domain, entry); + return (ENOMEM); + } + for (i = 0; i < atop(length); i++) { + ma[i] = vm_page_getfake(entry->start + PAGE_SIZE * i, + VM_MEMATTR_DEFAULT); + } + error = dmar_gas_map_region(domain, entry, DMAR_MAP_ENTRY_READ | + ((flags & BUS_DMA_NOWRITE) ? 0 : DMAR_MAP_ENTRY_WRITE), + waitok ? DMAR_GM_CANWAIT : 0, ma); + if (error == 0) { + DMAR_DOMAIN_LOCK(domain); + TAILQ_INSERT_TAIL(&map->map_entries, entry, dmamap_link); + entry->flags |= DMAR_MAP_ENTRY_MAP; + DMAR_DOMAIN_UNLOCK(domain); + } else { + dmar_domain_unload_entry(entry, true); + } + for (i = 0; i < atop(length); i++) + vm_page_putfake(ma[i]); + free(ma, M_TEMP); + return (error); +} Index: sys/x86/iommu/intel_ctx.c =================================================================== --- sys/x86/iommu/intel_ctx.c +++ sys/x86/iommu/intel_ctx.c @@ -279,7 +279,7 @@ } error1 = dmar_gas_map_region(domain, entry, DMAR_MAP_ENTRY_READ | DMAR_MAP_ENTRY_WRITE, - DMAR_GM_CANWAIT, ma); + DMAR_GM_CANWAIT | DMAR_GM_RMRR, ma); /* * Non-failed RMRR entries are owned by context rb * tree. Get rid of the failed entry, but do not stop Index: sys/x86/iommu/intel_dmar.h =================================================================== --- sys/x86/iommu/intel_dmar.h +++ sys/x86/iommu/intel_dmar.h @@ -391,6 +391,7 @@ #define DMAR_GM_CANWAIT 0x0001 #define DMAR_GM_CANSPLIT 0x0002 +#define DMAR_GM_RMRR 0x0004 #define DMAR_PGF_WAITOK 0x0001 #define DMAR_PGF_ZERO 0x0002 Index: sys/x86/iommu/intel_gas.c =================================================================== --- sys/x86/iommu/intel_gas.c +++ sys/x86/iommu/intel_gas.c @@ -543,13 +543,15 @@ */ if (prev != NULL && prev->end > entry->start && (prev->flags & DMAR_MAP_ENTRY_PLACE) == 0) { - if ((prev->flags & DMAR_MAP_ENTRY_RMRR) == 0) + if ((flags & DMAR_GM_RMRR) == 0 || + (prev->flags & DMAR_MAP_ENTRY_RMRR) == 0) return (EBUSY); entry->start = prev->end; } if (next->start < entry->end && (next->flags & DMAR_MAP_ENTRY_PLACE) == 0) { - if ((next->flags & DMAR_MAP_ENTRY_RMRR) == 0) + if ((flags & DMAR_GM_RMRR) == 0 || + (next->flags & DMAR_MAP_ENTRY_RMRR) == 0) return (EBUSY); entry->end = next->start; } @@ -569,7 +571,8 @@ found = dmar_gas_rb_insert(domain, entry); KASSERT(found, ("found RMRR dup %p start %jx end %jx", domain, (uintmax_t)entry->start, (uintmax_t)entry->end)); - entry->flags = DMAR_MAP_ENTRY_RMRR; + if ((flags & DMAR_GM_RMRR) != 0) + entry->flags = DMAR_MAP_ENTRY_RMRR; #ifdef INVARIANTS struct dmar_map_entry *ip, *in; @@ -689,7 +692,7 @@ KASSERT(entry->flags == 0, ("used RMRR entry %p %p %x", domain, entry, entry->flags)); - KASSERT((flags & ~(DMAR_GM_CANWAIT)) == 0, + KASSERT((flags & ~(DMAR_GM_CANWAIT | DMAR_GM_RMRR)) == 0, ("invalid flags 0x%x", flags)); start = entry->start; Index: sys/x86/x86/busdma_machdep.c =================================================================== --- sys/x86/x86/busdma_machdep.c +++ sys/x86/x86/busdma_machdep.c @@ -253,4 +253,11 @@ { return (false); } + +int +bus_dma_dmar_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t start, vm_size_t length, int flags) +{ + return (0); +} #endif