Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/iommu/iommu_gas.c
Show First 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | iommu_gas_check_free(struct iommu_domain *domain) | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
static void | static void | ||||
iommu_gas_rb_remove(struct iommu_domain *domain, struct iommu_map_entry *entry) | iommu_gas_rb_remove(struct iommu_domain *domain, struct iommu_map_entry *entry) | ||||
{ | { | ||||
/* The removed entry may open a new, smaller start gap. */ | |||||
if (entry->end <= domain->start_gap->end) { | |||||
domain->start_gap = RB_RIGHT(entry, rb_entry) != NULL ? | |||||
iommu_gas_entries_tree_RB_NEXT(entry) : | |||||
RB_LEFT(entry, rb_entry) != NULL ? | |||||
RB_LEFT(entry, rb_entry) : RB_PARENT(entry, rb_entry); | |||||
kib: This expression is in style, but IMO it is too confusing for a reader. Could you please add… | |||||
} | |||||
RB_REMOVE(iommu_gas_entries_tree, &domain->rb_root, entry); | RB_REMOVE(iommu_gas_entries_tree, &domain->rb_root, entry); | ||||
} | } | ||||
struct iommu_domain * | struct iommu_domain * | ||||
iommu_get_ctx_domain(struct iommu_ctx *ctx) | iommu_get_ctx_domain(struct iommu_ctx *ctx) | ||||
{ | { | ||||
return (ctx->domain); | return (ctx->domain); | ||||
Show All 27 Lines | iommu_gas_init_domain(struct iommu_domain *domain) | ||||
end->flags = IOMMU_MAP_ENTRY_PLACE | IOMMU_MAP_ENTRY_UNMAPPED; | end->flags = IOMMU_MAP_ENTRY_PLACE | IOMMU_MAP_ENTRY_UNMAPPED; | ||||
RB_INSERT(iommu_gas_entries_tree, &domain->rb_root, end); | RB_INSERT(iommu_gas_entries_tree, &domain->rb_root, end); | ||||
begin->start = 0; | begin->start = 0; | ||||
begin->end = IOMMU_PAGE_SIZE; | begin->end = IOMMU_PAGE_SIZE; | ||||
begin->flags = IOMMU_MAP_ENTRY_PLACE | IOMMU_MAP_ENTRY_UNMAPPED; | begin->flags = IOMMU_MAP_ENTRY_PLACE | IOMMU_MAP_ENTRY_UNMAPPED; | ||||
RB_INSERT_PREV(iommu_gas_entries_tree, &domain->rb_root, end, begin); | RB_INSERT_PREV(iommu_gas_entries_tree, &domain->rb_root, end, begin); | ||||
domain->start_gap = end; | |||||
domain->first_place = begin; | domain->first_place = begin; | ||||
domain->last_place = end; | domain->last_place = end; | ||||
domain->flags |= IOMMU_DOMAIN_GAS_INITED; | domain->flags |= IOMMU_DOMAIN_GAS_INITED; | ||||
IOMMU_DOMAIN_UNLOCK(domain); | IOMMU_DOMAIN_UNLOCK(domain); | ||||
} | } | ||||
void | void | ||||
iommu_gas_fini_domain(struct iommu_domain *domain) | iommu_gas_fini_domain(struct iommu_domain *domain) | ||||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | if ((next = RB_RIGHT(curr, rb_entry)) != NULL && | ||||
while ((next = RB_PARENT(curr, rb_entry)) != NULL && | while ((next = RB_PARENT(curr, rb_entry)) != NULL && | ||||
curr == RB_RIGHT(next, rb_entry)) | curr == RB_RIGHT(next, rb_entry)) | ||||
curr = next; | curr = next; | ||||
curr = next; | curr = next; | ||||
} | } | ||||
return (curr); | return (curr); | ||||
} | } | ||||
static int | static int | ||||
iommu_gas_find_space(struct iommu_gas_match_args *a) | iommu_gas_find_space(struct iommu_gas_match_args *a) | ||||
Not Done Inline ActionsThis function has gotten so complicated that I'd suggest adding a comment at the top that says that it implements an address ordered first fit. alc: This function has gotten so complicated that I'd suggest adding a comment at the top that says… | |||||
{ | { | ||||
struct iommu_domain *domain; | struct iommu_domain *domain; | ||||
struct iommu_map_entry *curr, *first; | struct iommu_map_entry *curr, *first; | ||||
iommu_gaddr_t addr, min_free; | iommu_gaddr_t addr, min_free; | ||||
IOMMU_DOMAIN_ASSERT_LOCKED(a->domain); | IOMMU_DOMAIN_ASSERT_LOCKED(a->domain); | ||||
KASSERT(a->entry->flags == 0, | KASSERT(a->entry->flags == 0, | ||||
("dirty entry %p %p", a->domain, a->entry)); | ("dirty entry %p %p", a->domain, a->entry)); | ||||
domain = a->domain; | |||||
Not Done Inline ActionsMight as well move this up so the above asserts can use it. alc: Might as well move this up so the above asserts can use it. | |||||
/* | /* | ||||
* Advance start_gap to the first free space big enough for a | |||||
* minimum allocation plus two guard pages. | |||||
*/ | |||||
min_free = 3 * IOMMU_PAGE_SIZE; | |||||
kibUnsubmitted Done Inline ActionsShould a->size somehow participate in the expression for min_free? kib: Should a->size somehow participate in the expression for min_free? | |||||
dougmAuthorUnsubmitted Done Inline ActionsThe value of start_gap is adjusted for the smallest possible allocation, not for this particular (possibly larger) allocation. dougm: The value of start_gap is adjusted for the smallest possible allocation, not for this… | |||||
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 | * If the subtree doesn't have free space for the requested allocation | ||||
* plus two guard pages, skip it. | * plus two guard pages, skip it. | ||||
*/ | */ | ||||
min_free = 2 * IOMMU_PAGE_SIZE + | min_free = 2 * IOMMU_PAGE_SIZE + | ||||
roundup2(a->size + a->offset, IOMMU_PAGE_SIZE); | roundup2(a->size + a->offset, IOMMU_PAGE_SIZE); | ||||
/* | /* Climb to find a node in the subtree of big-enough ranges. */ | ||||
* 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; | first = curr; | ||||
curr = RB_LEFT(curr, rb_entry); | 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. | * requirements, or violates lowaddr address requirement. | ||||
*/ | */ | ||||
addr = a->common->lowaddr + 1; | addr = a->common->lowaddr + 1; | ||||
for (curr = first; curr != NULL; | for (curr = first; curr != NULL; | ||||
curr = iommu_gas_next(curr, min_free)) { | curr = iommu_gas_next(curr, min_free)) { | ||||
if ((first = RB_LEFT(curr, rb_entry)) != NULL && | if ((first = RB_LEFT(curr, rb_entry)) != NULL && | ||||
iommu_gas_match_one(a, first->last, curr->start, | iommu_gas_match_one(a, first->last, curr->start, | ||||
0, addr)) { | 0, addr)) { | ||||
▲ Show 20 Lines • Show All 574 Lines • Show Last 20 Lines |
This expression is in style, but IMO it is too confusing for a reader. Could you please add braces for the inner '?:' expression?