Page MenuHomeFreeBSD

D35440.id106779.diff
No OneTemporary

D35440.id106779.diff

Index: sys/dev/iommu/iommu_gas.c
===================================================================
--- sys/dev/iommu/iommu_gas.c
+++ sys/dev/iommu/iommu_gas.c
@@ -301,61 +301,45 @@
iommu_gas_match_one(struct iommu_gas_match_args *a, iommu_gaddr_t beg,
iommu_gaddr_t end, iommu_gaddr_t maxaddr)
{
- iommu_gaddr_t bs, start;
-
- a->entry->start = roundup2(beg + IOMMU_PAGE_SIZE,
- a->common->alignment);
- if (a->entry->start + a->offset + a->size > maxaddr)
- return (false);
+ iommu_gaddr_t first, start;
+ bool found __diagused;
- /* IOMMU_PAGE_SIZE to create gap after new entry. */
- if (a->entry->start < beg + IOMMU_PAGE_SIZE ||
- a->entry->start + a->size + a->offset + IOMMU_PAGE_SIZE > end)
+ /* IOMMU_PAGE_SIZE to create gaps before, after new entry. */
+ beg += IOMMU_PAGE_SIZE;
+ first = start = roundup2(beg, a->common->alignment);
+ end = ummin(end - IOMMU_PAGE_SIZE, maxaddr);
+ if (start + a->size + a->offset > end)
return (false);
- /* No boundary crossing. */
- if (vm_addr_bound_ok(a->entry->start + a->offset, a->size,
- a->common->boundary))
- return (true);
-
- /*
- * The start + offset to start + offset + size region crosses
- * the boundary. Check if there is enough space after the
- * next boundary after the beg.
- */
- bs = rounddown2(a->entry->start + a->offset + a->common->boundary,
- a->common->boundary);
- start = roundup2(bs, a->common->alignment);
- /* IOMMU_PAGE_SIZE to create gap after new entry. */
- if (start + a->offset + a->size + IOMMU_PAGE_SIZE <= end &&
- start + a->offset + a->size <= maxaddr &&
- vm_addr_bound_ok(start + a->offset, a->size,
+ /* Check for and try to skip past boundary crossing. */
+ if (!vm_addr_bound_ok(start + a->offset, a->size,
a->common->boundary)) {
- a->entry->start = start;
- return (true);
+ /*
+ * The start + offset to start + offset + size region crosses
+ * the boundary. Check if there is enough space after the next
+ * boundary after the beg.
+ */
+ beg = roundup2(start + a->offset + 1, a->common->boundary);
+ start = roundup2(beg, a->common->alignment);
}
- /*
- * Not enough space to align at the requested boundary, or
- * boundary is smaller than the size, but allowed to split.
- * We already checked that start + size does not overlap maxaddr.
- *
- * XXXKIB. It is possible that bs is exactly at the start of
- * the next entry, then we do not have gap. Ignore for now.
- */
- if ((a->gas_flags & IOMMU_MF_CANSPLIT) != 0) {
- a->size = bs - a->entry->start;
- return (true);
+ if (start + a->offset + a->size > end ||
+ !vm_addr_bound_ok(start + a->offset, a->size,
+ a->common->boundary)) {
+ /*
+ * Not enough space to align at the requested boundary, or
+ * boundary is smaller than the size, but allowed to split. We
+ * already checked that start + size does not overlap maxaddr.
+ *
+ * XXXKIB. It is possible that beg is exactly at the start of
+ * the next entry, then we do not have gap. Ignore for now.
+ */
+ if ((a->gas_flags & IOMMU_MF_CANSPLIT) == 0)
+ return (false);
+ a->size = beg - first;
+ start = first;
}
- return (false);
-}
-
-static void
-iommu_gas_match_insert(struct iommu_gas_match_args *a)
-{
- bool found __diagused;
-
/*
* The prev->end is always aligned on the page size, which
* causes page alignment for the entry->start too. The size
@@ -364,12 +348,14 @@
* The page sized gap is created between consequent
* allocations to ensure that out-of-bounds accesses fault.
*/
- a->entry->end = a->entry->start + a->size;
+ a->entry->start = start;
+ a->entry->end = start + a->size;
found = iommu_gas_rb_insert(a->domain, a->entry);
KASSERT(found, ("found dup %p start %jx size %jx",
- a->domain, (uintmax_t)a->entry->start, (uintmax_t)a->size));
+ a->domain, (uintmax_t)start, (uintmax_t)a->size));
a->entry->flags = IOMMU_MAP_ENTRY_MAP;
+ return (true);
}
static int
@@ -380,10 +366,8 @@
child = RB_RIGHT(entry, rb_entry);
if (child != NULL && entry->end < a->common->lowaddr &&
iommu_gas_match_one(a, entry->end, child->first,
- a->common->lowaddr)) {
- iommu_gas_match_insert(a);
+ a->common->lowaddr))
return (0);
- }
/*
* If the subtree doesn't have free space for the requested allocation
@@ -398,10 +382,8 @@
return (0);
if (child != NULL && child->last < a->common->lowaddr &&
iommu_gas_match_one(a, child->last, entry->start,
- a->common->lowaddr)) {
- iommu_gas_match_insert(a);
+ a->common->lowaddr))
return (0);
- }
child = RB_RIGHT(entry, rb_entry);
if (child != NULL && 0 == iommu_gas_lowermatch(a, child))
return (0);
@@ -426,17 +408,13 @@
return (0);
if (child != NULL && child->last >= a->common->highaddr &&
iommu_gas_match_one(a, child->last, entry->start,
- a->domain->end)) {
- iommu_gas_match_insert(a);
+ a->domain->end))
return (0);
- }
child = RB_RIGHT(entry, rb_entry);
if (child != NULL && entry->end >= a->common->highaddr &&
iommu_gas_match_one(a, entry->end, child->first,
- a->domain->end)) {
- iommu_gas_match_insert(a);
+ a->domain->end))
return (0);
- }
if (child != NULL && 0 == iommu_gas_uppermatch(a, child))
return (0);
return (ENOMEM);

File Metadata

Mime Type
text/plain
Expires
Fri, May 2, 6:38 PM (13 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17910072
Default Alt Text
D35440.id106779.diff (5 KB)

Event Timeline