Page MenuHomeFreeBSD

D36624.id112120.diff
No OneTemporary

D36624.id112120.diff

Index: sys/dev/iommu/iommu.h
===================================================================
--- sys/dev/iommu/iommu.h
+++ sys/dev/iommu/iommu.h
@@ -109,6 +109,7 @@
struct iommu_map_entries_tailq unload_entries; /* (d) Entries to
unload */
struct iommu_gas_entries_tree rb_root; /* (d) */
+ struct iommu_map_entry *start_gap; /* (d) */
iommu_gaddr_t end; /* (c) Highest address + 1 in
the guest AS */
struct iommu_map_entry *first_place, *last_place; /* (d) */
Index: sys/dev/iommu/iommu_gas.c
===================================================================
--- sys/dev/iommu/iommu_gas.c
+++ sys/dev/iommu/iommu_gas.c
@@ -209,7 +209,18 @@
static void
iommu_gas_rb_remove(struct iommu_domain *domain, struct iommu_map_entry *entry)
{
-
+ struct iommu_map_entry *nbr;
+
+ /* The removed entry may open a start gap before the current one. */
+ if (entry->end <= domain->start_gap->end) {
+ if (RB_RIGHT(entry, rb_entry) != NULL)
+ nbr = iommu_gas_entries_tree_RB_NEXT(entry);
+ else if (RB_LEFT(entry, rb_entry) != NULL)
+ nbr = RB_LEFT(entry, rb_entry);
+ else
+ nbr = RB_PARENT(entry, rb_entry);
+ domain->start_gap = nbr;
+ }
RB_REMOVE(iommu_gas_entries_tree, &domain->rb_root, entry);
}
@@ -253,6 +264,7 @@
begin->flags = IOMMU_MAP_ENTRY_PLACE | IOMMU_MAP_ENTRY_UNMAPPED;
RB_INSERT_PREV(iommu_gas_entries_tree, &domain->rb_root, end, begin);
+ domain->start_gap = end;
domain->first_place = begin;
domain->last_place = end;
domain->flags |= IOMMU_DOMAIN_GAS_INITED;
@@ -405,6 +417,27 @@
IOMMU_DOMAIN_ASSERT_LOCKED(a->domain);
KASSERT(a->entry->flags == 0,
("dirty entry %p %p", a->domain, a->entry));
+ domain = a->domain;
+
+ /*
+ * start_gap may point to an entry adjacent to gaps too small for any
+ * new allocation. In that case, advance start_gap to the first free
+ * space big enough for a minimum allocation plus two guard pages.
+ */
+ min_free = 3 * IOMMU_PAGE_SIZE;
+ first = domain->start_gap;
+ while (first != NULL && first->free_down < min_free)
+ first = RB_PARENT(first, rb_entry);
+ for (curr = first; curr != NULL;
+ curr = iommu_gas_next(curr, min_free)) {
+ if ((first = RB_LEFT(curr, rb_entry)) != NULL &&
+ first->last + min_free <= curr->start)
+ break;
+ if ((first = RB_RIGHT(curr, rb_entry)) != NULL &&
+ curr->end + min_free <= first->first)
+ break;
+ }
+ domain->start_gap = curr;
/*
* If the subtree doesn't have free space for the requested allocation
@@ -413,20 +446,13 @@
min_free = 2 * IOMMU_PAGE_SIZE +
roundup2(a->size + a->offset, IOMMU_PAGE_SIZE);
- /*
- * Find the first entry in the lower region that could abut a big-enough
- * range.
- */
- domain = a->domain;
- curr = RB_ROOT(&domain->rb_root);
- first = NULL;
- while (curr != NULL && curr->free_down >= min_free) {
- first = curr;
- curr = RB_LEFT(curr, rb_entry);
- }
+ /* Climb to find a node in the subtree of big-enough ranges. */
+ first = curr;
+ while (first != NULL && first->free_down < min_free)
+ first = RB_PARENT(first, rb_entry);
/*
- * Walk the big-enough ranges until one satisfies alignment
+ * Walk the big-enough ranges tree until one satisfies alignment
* requirements, or violates lowaddr address requirement.
*/
addr = a->common->lowaddr + 1;

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 22, 6:24 PM (11 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16034407
Default Alt Text
D36624.id112120.diff (3 KB)

Event Timeline