svn commit: r363747 - in head/sys: dev/iommu x86/iommu
Ruslan Bukin
br at FreeBSD.org
Fri Jul 31 23:02:19 UTC 2020
Author: br
Date: Fri Jul 31 23:02:17 2020
New Revision: 363747
URL: https://svnweb.freebsd.org/changeset/base/363747
Log:
Add iommu_domain_map_ops virtual table with map/unmap methods
so x86 can support Intel DMAR and AMD IOMMU simultaneously.
Reviewed by: kib
Sponsored by: DARPA/AFRL
Differential Revision: https://reviews.freebsd.org/D25894
Modified:
head/sys/dev/iommu/iommu.h
head/sys/dev/iommu/iommu_gas.c
head/sys/x86/iommu/intel_ctx.c
head/sys/x86/iommu/intel_dmar.h
head/sys/x86/iommu/intel_idpgtbl.c
Modified: head/sys/dev/iommu/iommu.h
==============================================================================
--- head/sys/dev/iommu/iommu.h Fri Jul 31 22:23:32 2020 (r363746)
+++ head/sys/dev/iommu/iommu.h Fri Jul 31 23:02:17 2020 (r363747)
@@ -100,6 +100,13 @@ struct iommu_unit {
uint32_t buswide_ctxs[(PCI_BUSMAX + 1) / NBBY / sizeof(uint32_t)];
};
+struct iommu_domain_map_ops {
+ int (*map)(struct iommu_domain *domain, iommu_gaddr_t base,
+ iommu_gaddr_t size, vm_page_t *ma, uint64_t pflags, int flags);
+ int (*unmap)(struct iommu_domain *domain, iommu_gaddr_t base,
+ iommu_gaddr_t size, int flags);
+};
+
/*
* Locking annotations:
* (u) - Protected by iommu unit lock
@@ -109,6 +116,7 @@ struct iommu_unit {
struct iommu_domain {
struct iommu_unit *iommu; /* (c) */
+ const struct iommu_domain_map_ops *ops;
struct mtx lock; /* (c) */
struct task unload_task; /* (c) */
u_int entries_cnt; /* (d) */
Modified: head/sys/dev/iommu/iommu_gas.c
==============================================================================
--- head/sys/dev/iommu/iommu_gas.c Fri Jul 31 22:23:32 2020 (r363746)
+++ head/sys/dev/iommu/iommu_gas.c Fri Jul 31 23:02:17 2020 (r363747)
@@ -66,10 +66,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/md_var.h>
#if defined(__amd64__) || defined(__i386__)
-#include <machine/specialreg.h>
-#include <x86/include/busdma_impl.h>
#include <x86/iommu/intel_reg.h>
-#include <x86/iommu/intel_dmar.h>
#endif
#include <dev/iommu/busdma_iommu.h>
@@ -620,9 +617,9 @@ iommu_gas_map(struct iommu_domain *domain,
entry->flags |= eflags;
IOMMU_DOMAIN_UNLOCK(domain);
- error = domain_map_buf(domain, entry->start, entry->end - entry->start,
- ma, eflags,
- ((flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0));
+ error = domain->ops->map(domain, entry->start,
+ entry->end - entry->start, ma, eflags,
+ ((flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0));
if (error == ENOMEM) {
iommu_domain_unload_entry(entry, true);
return (error);
@@ -658,9 +655,9 @@ iommu_gas_map_region(struct iommu_domain *domain, stru
if (entry->end == entry->start)
return (0);
- error = domain_map_buf(domain, entry->start, entry->end - entry->start,
- ma + OFF_TO_IDX(start - entry->start), eflags,
- ((flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0));
+ error = domain->ops->map(domain, entry->start,
+ entry->end - entry->start, ma + OFF_TO_IDX(start - entry->start),
+ eflags, ((flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0));
if (error == ENOMEM) {
iommu_domain_unload_entry(entry, false);
return (error);
Modified: head/sys/x86/iommu/intel_ctx.c
==============================================================================
--- head/sys/x86/iommu/intel_ctx.c Fri Jul 31 22:23:32 2020 (r363746)
+++ head/sys/x86/iommu/intel_ctx.c Fri Jul 31 23:02:17 2020 (r363747)
@@ -341,6 +341,7 @@ dmar_domain_alloc(struct dmar_unit *dmar, bool id_mapp
mtx_init(&domain->iodom.lock, "dmardom", NULL, MTX_DEF);
domain->dmar = dmar;
domain->iodom.iommu = &dmar->iommu;
+ domain_pgtbl_init(domain);
/*
* For now, use the maximal usable physical address of the
@@ -842,15 +843,17 @@ dmar_domain_unload(struct dmar_domain *domain,
struct iommu_map_entries_tailq *entries, bool cansleep)
{
struct dmar_unit *unit;
+ struct iommu_domain *iodom;
struct iommu_map_entry *entry, *entry1;
int error;
+ iodom = (struct iommu_domain *)domain;
unit = (struct dmar_unit *)domain->iodom.iommu;
TAILQ_FOREACH_SAFE(entry, entries, dmamap_link, entry1) {
KASSERT((entry->flags & IOMMU_MAP_ENTRY_MAP) != 0,
("not mapped entry %p %p", domain, entry));
- error = domain_unmap_buf(domain, entry->start, entry->end -
+ error = iodom->ops->unmap(iodom, entry->start, entry->end -
entry->start, cansleep ? IOMMU_PGF_WAITOK : 0);
KASSERT(error == 0, ("unmap %p error %d", domain, error));
if (!unit->qi_enabled) {
Modified: head/sys/x86/iommu/intel_dmar.h
==============================================================================
--- head/sys/x86/iommu/intel_dmar.h Fri Jul 31 22:23:32 2020 (r363746)
+++ head/sys/x86/iommu/intel_dmar.h Fri Jul 31 23:02:17 2020 (r363747)
@@ -244,14 +244,11 @@ void dmar_qi_invalidate_iec(struct dmar_unit *unit, u_
vm_object_t domain_get_idmap_pgtbl(struct dmar_domain *domain,
iommu_gaddr_t maxaddr);
void put_idmap_pgtbl(vm_object_t obj);
-int domain_map_buf(struct iommu_domain *domain, iommu_gaddr_t base,
- iommu_gaddr_t size, vm_page_t *ma, uint64_t pflags, int flags);
-int domain_unmap_buf(struct dmar_domain *domain, iommu_gaddr_t base,
- iommu_gaddr_t size, int flags);
void domain_flush_iotlb_sync(struct dmar_domain *domain, iommu_gaddr_t base,
iommu_gaddr_t size);
int domain_alloc_pgtbl(struct dmar_domain *domain);
void domain_free_pgtbl(struct dmar_domain *domain);
+void domain_pgtbl_init(struct dmar_domain *domain);
int dmar_dev_depth(device_t child);
void dmar_dev_path(device_t child, int *busno, void *path1, int depth);
Modified: head/sys/x86/iommu/intel_idpgtbl.c
==============================================================================
--- head/sys/x86/iommu/intel_idpgtbl.c Fri Jul 31 22:23:32 2020 (r363746)
+++ head/sys/x86/iommu/intel_idpgtbl.c Fri Jul 31 23:02:17 2020 (r363747)
@@ -498,7 +498,7 @@ domain_map_buf_locked(struct dmar_domain *domain, iomm
return (0);
}
-int
+static int
domain_map_buf(struct iommu_domain *iodom, iommu_gaddr_t base,
iommu_gaddr_t size, vm_page_t *ma, uint64_t eflags, int flags)
{
@@ -684,12 +684,15 @@ domain_unmap_buf_locked(struct dmar_domain *domain, io
return (0);
}
-int
-domain_unmap_buf(struct dmar_domain *domain, iommu_gaddr_t base,
+static int
+domain_unmap_buf(struct iommu_domain *iodom, iommu_gaddr_t base,
iommu_gaddr_t size, int flags)
{
+ struct dmar_domain *domain;
int error;
+ domain = (struct dmar_domain *)iodom;
+
DMAR_DOMAIN_PGLOCK(domain);
error = domain_unmap_buf_locked(domain, base, size, flags);
DMAR_DOMAIN_PGUNLOCK(domain);
@@ -808,4 +811,18 @@ domain_flush_iotlb_sync(struct dmar_domain *domain, io
}
}
DMAR_UNLOCK(unit);
+}
+
+static const struct iommu_domain_map_ops dmar_domain_map_ops = {
+ .map = domain_map_buf,
+ .unmap = domain_unmap_buf,
+};
+
+void
+domain_pgtbl_init(struct dmar_domain *domain)
+{
+ struct iommu_domain *iodom;
+
+ iodom = (struct iommu_domain *)domain;
+ iodom->ops = &dmar_domain_map_ops;
}
More information about the svn-src-head
mailing list