Page MenuHomeFreeBSD
Authored By
dougm
Aug 2 2022, 9:14 PM
Size
3 KB
Referenced Files
None
Subscribers
None

kib.diff

diff --git a/sys/dev/iommu/iommu_gas.c b/sys/dev/iommu/iommu_gas.c
index bad56ab9140e..6cffd62d5b8c 100644
--- a/sys/dev/iommu/iommu_gas.c
+++ b/sys/dev/iommu/iommu_gas.c
@@ -600,6 +600,100 @@ iommu_gas_free_region(struct iommu_map_entry *entry)
IOMMU_DOMAIN_UNLOCK(domain);
}
+static void
+iommu_gas_remove_entry_locked(struct iommu_domain *domain,
+ struct iommu_map_entry *entry)
+{
+ if ((entry->flags & IOMMU_MAP_ENTRY_RMRR) != 0)
+ return;
+ iommu_gas_free_space(entry);
+ domain->ops->unmap(domain, entry->start, entry->end - entry->start,
+ IOMMU_PGF_WAITOK);
+ if ((entry->flags & IOMMU_MAP_ENTRY_PLACE) == 0)
+ iommu_gas_free_entry(entry);
+}
+
+static void
+iommu_gas_remove_locked(struct iommu_domain *domain, iommu_gaddr_t start,
+ iommu_gaddr_t end, struct iommu_map_entry **r)
+{
+ struct iommu_map_entry *entry, fentry;
+
+ IOMMU_DOMAIN_ASSERT_LOCKED(domain);
+ MPASS(start <= end);
+ MPASS(end <= domain->last_place->end);
+
+ /*
+ * Find an entry which contains the supplied guest's address
+ * start, or the first entry after the start. Since we
+ * asserted that start is below domain end, entry should
+ * exist. Then clip it if needed.
+ */
+ fentry.start = start + 1;
+ fentry.end = start + 1;
+ entry = RB_NFIND(iommu_gas_entries_tree, &domain->rb_root, &fentry);
+ MPASS(start <= entry->start || (entry->start <= start &&
+ start <= entry->end));
+
+ if (entry->start < start) {
+ if (end < entry->end)
+ **r = *entry;
+ entry->end = start;
+ RB_UPDATE_AUGMENT(entry, rb_entry);
+ if (end < entry->end) {
+ (*r)->start = end;
+ iommu_gas_rb_insert(domain, *r);
+ *r = NULL;
+ return;
+ }
+ entry = iommu_gas_entries_tree_RB_NEXT(entry);
+ }
+
+ RB_FOREACH_FROM(entry, iommu_gas_entries_tree, entry) {
+ if (entry->end >= end)
+ break;
+ KASSERT(start <= entry->start,
+ ("iommu_gas_remove entry (%#jx, %#jx) start %#jx",
+ entry->start, entry->end, start));
+ KASSERT(entry->end <= end,
+ ("iommu_gas_remove entry (%#jx, %#jx) end %#jx",
+ entry->start, entry->end, end));
+ iommu_gas_remove_entry_locked(domain, entry);
+ }
+
+ if (entry->start < end) {
+ entry->start = end;
+ RB_UPDATE_AUGMENT(entry, rb_entry);
+ }
+
+#ifdef INVARIANTS
+ RB_FOREACH(entry, iommu_gas_entries_tree, &domain->rb_root) {
+ if ((entry->flags & IOMMU_MAP_ENTRY_RMRR) != 0)
+ continue;
+ KASSERT(entry->end <= start || entry->start >= end,
+ ("iommu_gas_remove leftover entry (%#jx, %#jx) range "
+ "(%#jx, %#jx)",
+ entry->start, entry->end, start, end));
+ }
+#endif
+}
+
+void
+iommu_gas_remove(struct iommu_domain *domain, iommu_gaddr_t start,
+ iommu_gaddr_t size)
+{
+ struct iommu_map_entry *r;
+ iommu_gaddr_t end;
+
+ end = start + size;
+ r = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK);
+ IOMMU_DOMAIN_LOCK(domain);
+ iommu_gas_remove_locked(domain, start, end, &r);
+ IOMMU_DOMAIN_UNLOCK(domain);
+ if (r != NULL)
+ iommu_gas_free_entry(r);
+}
+
int
iommu_gas_map(struct iommu_domain *domain,
const struct bus_dma_tag_common *common, iommu_gaddr_t size, int offset,

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5026269
Default Alt Text
kib.diff (3 KB)

Event Timeline