Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Nov 2019 19:57:17 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r355138 - in head/sys/x86: include iommu x86
Message-ID:  <201911271957.xARJvHCk090046@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Nov 27 19:57:17 2019
New Revision: 355138
URL: https://svnweb.freebsd.org/changeset/base/355138

Log:
  bus_dma_dmar_load_ident(9): load identity mapping into the map.
  
  Requested, reviewed and tested by:	mav
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week
  Differential revision:	https://reviews.freebsd.org/D22559

Modified:
  head/sys/x86/include/bus_dma.h
  head/sys/x86/iommu/busdma_dmar.c
  head/sys/x86/iommu/intel_ctx.c
  head/sys/x86/iommu/intel_dmar.h
  head/sys/x86/iommu/intel_gas.c
  head/sys/x86/x86/busdma_machdep.c

Modified: head/sys/x86/include/bus_dma.h
==============================================================================
--- head/sys/x86/include/bus_dma.h	Wed Nov 27 19:49:55 2019	(r355137)
+++ head/sys/x86/include/bus_dma.h	Wed Nov 27 19:57:17 2019	(r355138)
@@ -193,6 +193,8 @@ _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t 
 
 #ifdef _KERNEL
 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
 
 #endif /* !_X86_BUS_DMA_H_ */

Modified: head/sys/x86/iommu/busdma_dmar.c
==============================================================================
--- head/sys/x86/iommu/busdma_dmar.c	Wed Nov 27 19:49:55 2019	(r355137)
+++ head/sys/x86/iommu/busdma_dmar.c	Wed Nov 27 19:57:17 2019	(r355138)
@@ -973,3 +973,66 @@ dmar_fini_busdma(struct dmar_unit *unit)
 	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);
+}

Modified: head/sys/x86/iommu/intel_ctx.c
==============================================================================
--- head/sys/x86/iommu/intel_ctx.c	Wed Nov 27 19:49:55 2019	(r355137)
+++ head/sys/x86/iommu/intel_ctx.c	Wed Nov 27 19:57:17 2019	(r355138)
@@ -279,7 +279,7 @@ domain_init_rmrr(struct dmar_domain *domain, device_t 
 		}
 		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

Modified: head/sys/x86/iommu/intel_dmar.h
==============================================================================
--- head/sys/x86/iommu/intel_dmar.h	Wed Nov 27 19:49:55 2019	(r355137)
+++ head/sys/x86/iommu/intel_dmar.h	Wed Nov 27 19:57:17 2019	(r355138)
@@ -391,6 +391,7 @@ bool dmar_is_buswide_ctx(struct dmar_unit *unit, u_int
 
 #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

Modified: head/sys/x86/iommu/intel_gas.c
==============================================================================
--- head/sys/x86/iommu/intel_gas.c	Wed Nov 27 19:49:55 2019	(r355137)
+++ head/sys/x86/iommu/intel_gas.c	Wed Nov 27 19:57:17 2019	(r355138)
@@ -543,13 +543,15 @@ dmar_gas_alloc_region(struct dmar_domain *domain, stru
 	 */
 	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 @@ dmar_gas_alloc_region(struct dmar_domain *domain, stru
 	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 @@ dmar_gas_map_region(struct dmar_domain *domain, struct
 
 	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;

Modified: head/sys/x86/x86/busdma_machdep.c
==============================================================================
--- head/sys/x86/x86/busdma_machdep.c	Wed Nov 27 19:49:55 2019	(r355137)
+++ head/sys/x86/x86/busdma_machdep.c	Wed Nov 27 19:57:17 2019	(r355138)
@@ -253,4 +253,11 @@ bus_dma_dmar_set_buswide(device_t dev)
 {
 	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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911271957.xARJvHCk090046>