Page MenuHomeFreeBSD

D35424.id106738.diff
No OneTemporary

D35424.id106738.diff

Index: sys/dev/iommu/busdma_iommu.c
===================================================================
--- sys/dev/iommu/busdma_iommu.c
+++ sys/dev/iommu/busdma_iommu.c
@@ -594,8 +594,7 @@
if (seg + 1 < tag->common.nsegments)
gas_flags |= IOMMU_MF_CANSPLIT;
- error = iommu_map(domain, &tag->common,
- round_page(offset + buflen1),
+ error = iommu_map(domain, &tag->common, buflen1,
offset, e_flags, gas_flags, ma + idx, &entry);
if (error != 0)
break;
Index: sys/dev/iommu/iommu_gas.c
===================================================================
--- sys/dev/iommu/iommu_gas.c
+++ sys/dev/iommu/iommu_gas.c
@@ -301,54 +301,50 @@
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_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)
- 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,
- a->common->boundary)) {
- a->entry->start = start;
- return (true);
+ iommu_gaddr_t first, start;
+
+ /* IOMMU_PAGE_SIZE to create gaps before, after new entry. */
+ end -= a->size + a->offset + IOMMU_PAGE_SIZE;
+ maxaddr -= a->size + a->offset;
+ end = ummin(end, maxaddr);
+
+ beg += IOMMU_PAGE_SIZE;
+ start = roundup2(beg, a->common->alignment);
+ first = start;
+
+ /* Boundary crossing. */
+ if (!vm_addr_bound_ok(start + a->offset,
+ a->size, a->common->boundary)) {
+ /*
+ * 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);
+ /* Still a boundary crossing. */
+ if (!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);
+ start = first;
+ a->size = beg - start;
+
}
-
- return (false);
+ if (start > end)
+ return (false);
+ a->entry->start = start;
+ return (true);
}
static void
@@ -364,7 +360,8 @@
* 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->end = a->entry->start +
+ roundup2(a->size + a->offset, IOMMU_PAGE_SIZE);
found = iommu_gas_rb_insert(a->domain, a->entry);
KASSERT(found, ("found dup %p start %jx size %jx",
@@ -389,7 +386,8 @@
* If the subtree doesn't have free space for the requested allocation
* plus two guard pages, give up.
*/
- if (entry->free_down < a->size + a->offset + 2 * IOMMU_PAGE_SIZE)
+ if (entry->free_down < 2 * IOMMU_PAGE_SIZE +
+ roundup2(a->size + a->offset, IOMMU_PAGE_SIZE))
return (ENOMEM);
if (entry->first >= a->common->lowaddr)
return (ENOMEM);
@@ -417,7 +415,8 @@
* If the subtree doesn't have free space for the requested allocation
* plus two guard pages, give up.
*/
- if (entry->free_down < a->size + a->offset + 2 * IOMMU_PAGE_SIZE)
+ if (entry->free_down < 2 * IOMMU_PAGE_SIZE +
+ roundup2(a->size + a->offset, IOMMU_PAGE_SIZE))
return (ENOMEM);
if (entry->last < a->common->highaddr)
return (ENOMEM);
@@ -452,7 +451,6 @@
IOMMU_DOMAIN_ASSERT_LOCKED(domain);
KASSERT(entry->flags == 0, ("dirty entry %p %p", domain, entry));
- KASSERT((size & IOMMU_PAGE_MASK) == 0, ("size %jx", (uintmax_t)size));
a.domain = domain;
a.size = size;

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 23, 2:06 PM (9 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16799726
Default Alt Text
D35424.id106738.diff (5 KB)

Event Timeline