Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/iommu/iommu_gas.c
Show First 20 Lines • Show All 529 Lines • ▼ Show 20 Lines | if (next->start < entry->end) { | ||||
iommu_gas_rb_remove(domain, next); | iommu_gas_rb_remove(domain, next); | ||||
next = NULL; | next = NULL; | ||||
} | } | ||||
found = iommu_gas_rb_insert(domain, entry); | found = iommu_gas_rb_insert(domain, entry); | ||||
KASSERT(found, ("found RMRR dup %p start %jx end %jx", | KASSERT(found, ("found RMRR dup %p start %jx end %jx", | ||||
domain, (uintmax_t)entry->start, (uintmax_t)entry->end)); | domain, (uintmax_t)entry->start, (uintmax_t)entry->end)); | ||||
if ((flags & IOMMU_MF_RMRR) != 0) | if ((flags & IOMMU_MF_RMRR) != 0) | ||||
entry->flags = IOMMU_MAP_ENTRY_RMRR; | entry->flags |= IOMMU_MAP_ENTRY_RMRR; | ||||
if ((flags & IOMMU_MF_VMM) != 0) | |||||
entry->flags |= IOMMU_MAP_ENTRY_VMM; | |||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
struct iommu_map_entry *ip, *in; | struct iommu_map_entry *ip, *in; | ||||
ip = RB_PREV(iommu_gas_entries_tree, &domain->rb_root, entry); | ip = RB_PREV(iommu_gas_entries_tree, &domain->rb_root, entry); | ||||
in = RB_NEXT(iommu_gas_entries_tree, &domain->rb_root, entry); | in = RB_NEXT(iommu_gas_entries_tree, &domain->rb_root, entry); | ||||
KASSERT(prev == NULL || ip == prev, | KASSERT(prev == NULL || ip == prev, | ||||
("RMRR %p (%jx %jx) prev %p (%jx %jx) ins prev %p (%jx %jx)", | ("RMRR %p (%jx %jx) prev %p (%jx %jx) ins prev %p (%jx %jx)", | ||||
entry, entry->start, entry->end, prev, | entry, entry->start, entry->end, prev, | ||||
Show All 10 Lines | |||||
} | } | ||||
void | void | ||||
iommu_gas_free_space(struct iommu_map_entry *entry) | iommu_gas_free_space(struct iommu_map_entry *entry) | ||||
{ | { | ||||
struct iommu_domain *domain; | struct iommu_domain *domain; | ||||
domain = entry->domain; | domain = entry->domain; | ||||
KASSERT((entry->flags & (IOMMU_MAP_ENTRY_PLACE | IOMMU_MAP_ENTRY_RMRR | | KASSERT((entry->flags & IOMMU_MAP_ENTRY_RMRR) == 0, | ||||
IOMMU_MAP_ENTRY_MAP)) == IOMMU_MAP_ENTRY_MAP, | ("removing RMRR entry dom %p e %p (%#jx, %#jx) fl %#x", domain, | ||||
("permanent entry %p %p", domain, entry)); | entry, | ||||
(uintmax_t)entry->start, (uintmax_t)entry->end, entry->flags)); | |||||
IOMMU_DOMAIN_LOCK(domain); | IOMMU_DOMAIN_LOCK(domain); | ||||
iommu_gas_rb_remove(domain, entry); | iommu_gas_rb_remove(domain, entry); | ||||
entry->flags &= ~IOMMU_MAP_ENTRY_MAP; | entry->flags &= ~IOMMU_MAP_ENTRY_MAP; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
if (iommu_check_free) | if (iommu_check_free) | ||||
iommu_gas_check_free(domain); | iommu_gas_check_free(domain); | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 196 Lines • ▼ Show 20 Lines | #endif | ||||
*res = entry; | *res = entry; | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
iommu_gas_map_region(struct iommu_domain *domain, struct iommu_map_entry *entry, | iommu_gas_map_region(struct iommu_domain *domain, struct iommu_map_entry *entry, | ||||
u_int eflags, u_int flags, vm_page_t *ma) | u_int eflags, u_int flags, vm_page_t *ma) | ||||
{ | { | ||||
iommu_gaddr_t start; | struct iommu_map_entry *r1, *r2; | ||||
int error; | int error; | ||||
KASSERT(entry->domain == domain, | KASSERT(entry->domain == domain, | ||||
("mismatched domain %p entry %p entry->domain %p", domain, | ("mismatched domain %p entry %p entry->domain %p", domain, | ||||
entry, entry->domain)); | entry, entry->domain)); | ||||
KASSERT(entry->flags == 0, ("used RMRR entry %p %p %x", domain, | KASSERT(entry->flags == 0, ("used RMRR entry %p %p %x", domain, | ||||
entry, entry->flags)); | entry, entry->flags)); | ||||
KASSERT((flags & ~(IOMMU_MF_CANWAIT | IOMMU_MF_RMRR)) == 0, | KASSERT((flags & ~(IOMMU_MF_CANWAIT | IOMMU_MF_CANTRIM | | ||||
IOMMU_MF_CANSPLIT | IOMMU_MF_RMRR | IOMMU_MF_VMM)) == 0, | |||||
("invalid flags 0x%x", flags)); | ("invalid flags 0x%x", flags)); | ||||
start = entry->start; | if ((flags & IOMMU_MF_VMM) != 0) { | ||||
r1 = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK); | |||||
r2 = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK); | |||||
} | |||||
IOMMU_DOMAIN_LOCK(domain); | IOMMU_DOMAIN_LOCK(domain); | ||||
if ((flags & IOMMU_MF_VMM) != 0) { | |||||
iommu_gas_remove_locked(domain, entry->start, entry->end, | |||||
&r1, &r2); | |||||
} | |||||
error = iommu_gas_alloc_region(domain, entry, flags); | error = iommu_gas_alloc_region(domain, entry, flags); | ||||
if (error != 0) { | if (error != 0) { | ||||
IOMMU_DOMAIN_UNLOCK(domain); | IOMMU_DOMAIN_UNLOCK(domain); | ||||
return (error); | goto done; | ||||
} | } | ||||
entry->flags |= eflags; | entry->flags |= eflags; | ||||
IOMMU_DOMAIN_UNLOCK(domain); | IOMMU_DOMAIN_UNLOCK(domain); | ||||
if (entry->end == entry->start) | if (entry->end == entry->start) | ||||
return (0); | goto done; | ||||
error = domain->ops->map(domain, entry->start, | error = domain->ops->map(domain, entry->start, | ||||
entry->end - entry->start, ma + OFF_TO_IDX(start - entry->start), | entry->end - entry->start, ma, eflags, | ||||
eflags, ((flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0)); | (flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0); | ||||
if (error == ENOMEM) { | if (error == ENOMEM) { | ||||
iommu_domain_unload_entry(entry, false, | iommu_domain_unload_entry(entry, false, | ||||
(flags & IOMMU_MF_CANWAIT) != 0); | (flags & IOMMU_MF_CANWAIT) != 0); | ||||
return (error); | goto done; | ||||
} | } | ||||
KASSERT(error == 0, | KASSERT(error == 0, | ||||
("unexpected error %d from domain_map_buf", error)); | ("unexpected error %d from domain_map_buf", error)); | ||||
done: | |||||
return (0); | if ((flags & IOMMU_MF_VMM) != 0) { | ||||
if (r1 != NULL) | |||||
iommu_gas_free_entry(r1); | |||||
if (r2 != NULL) | |||||
iommu_gas_free_entry(r2); | |||||
} | |||||
return (error); | |||||
} | } | ||||
static int | static int | ||||
iommu_gas_reserve_region_locked(struct iommu_domain *domain, | iommu_gas_reserve_region_locked(struct iommu_domain *domain, | ||||
iommu_gaddr_t start, iommu_gaddr_t end, struct iommu_map_entry *entry) | iommu_gaddr_t start, iommu_gaddr_t end, struct iommu_map_entry *entry) | ||||
{ | { | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 173 Lines • Show Last 20 Lines |