Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/iommu/iommu_gas.c
Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
SYSINIT(intel_gas, SI_SUB_DRIVERS, SI_ORDER_FIRST, intel_gas_init, NULL); | SYSINIT(intel_gas, SI_SUB_DRIVERS, SI_ORDER_FIRST, intel_gas_init, NULL); | ||||
struct iommu_map_entry * | struct iommu_map_entry * | ||||
iommu_gas_alloc_entry(struct iommu_domain *domain, u_int flags) | iommu_gas_alloc_entry(struct iommu_domain *domain, u_int flags) | ||||
{ | { | ||||
struct iommu_map_entry *res; | struct iommu_map_entry *res; | ||||
KASSERT((flags & ~(DMAR_PGF_WAITOK)) == 0, | KASSERT((flags & ~(IOMMU_PGF_WAITOK)) == 0, | ||||
("unsupported flags %x", flags)); | ("unsupported flags %x", flags)); | ||||
res = uma_zalloc(iommu_map_entry_zone, ((flags & DMAR_PGF_WAITOK) != | res = uma_zalloc(iommu_map_entry_zone, ((flags & IOMMU_PGF_WAITOK) != | ||||
0 ? M_WAITOK : M_NOWAIT) | M_ZERO); | 0 ? M_WAITOK : M_NOWAIT) | M_ZERO); | ||||
if (res != NULL) { | if (res != NULL) { | ||||
res->domain = domain; | res->domain = domain; | ||||
atomic_add_int(&domain->entries_cnt, 1); | atomic_add_int(&domain->entries_cnt, 1); | ||||
} | } | ||||
return (res); | return (res); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | iommu_gas_rb_remove(struct iommu_domain *domain, struct iommu_map_entry *entry) | ||||
RB_REMOVE(iommu_gas_entries_tree, &domain->rb_root, entry); | RB_REMOVE(iommu_gas_entries_tree, &domain->rb_root, entry); | ||||
} | } | ||||
void | void | ||||
iommu_gas_init_domain(struct iommu_domain *domain) | iommu_gas_init_domain(struct iommu_domain *domain) | ||||
{ | { | ||||
struct iommu_map_entry *begin, *end; | struct iommu_map_entry *begin, *end; | ||||
begin = iommu_gas_alloc_entry(domain, DMAR_PGF_WAITOK); | begin = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK); | ||||
end = iommu_gas_alloc_entry(domain, DMAR_PGF_WAITOK); | end = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK); | ||||
IOMMU_DOMAIN_LOCK(domain); | IOMMU_DOMAIN_LOCK(domain); | ||||
KASSERT(domain->entries_cnt == 2, ("dirty domain %p", domain)); | KASSERT(domain->entries_cnt == 2, ("dirty domain %p", domain)); | ||||
KASSERT(RB_EMPTY(&domain->rb_root), | KASSERT(RB_EMPTY(&domain->rb_root), | ||||
("non-empty entries %p", domain)); | ("non-empty entries %p", domain)); | ||||
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; | ||||
iommu_gas_rb_insert(domain, begin); | iommu_gas_rb_insert(domain, begin); | ||||
end->start = domain->end; | end->start = domain->end; | ||||
end->end = domain->end; | end->end = domain->end; | ||||
end->flags = IOMMU_MAP_ENTRY_PLACE | IOMMU_MAP_ENTRY_UNMAPPED; | end->flags = IOMMU_MAP_ENTRY_PLACE | IOMMU_MAP_ENTRY_UNMAPPED; | ||||
iommu_gas_rb_insert(domain, end); | iommu_gas_rb_insert(domain, end); | ||||
domain->first_place = begin; | domain->first_place = begin; | ||||
domain->last_place = end; | domain->last_place = end; | ||||
domain->flags |= DMAR_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) | ||||
{ | { | ||||
struct iommu_map_entry *entry, *entry1; | struct iommu_map_entry *entry, *entry1; | ||||
▲ Show 20 Lines • Show All 343 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct iommu_map_entry *entry; | struct iommu_map_entry *entry; | ||||
int error; | int error; | ||||
KASSERT((flags & ~(IOMMU_MF_CANWAIT | IOMMU_MF_CANSPLIT)) == 0, | KASSERT((flags & ~(IOMMU_MF_CANWAIT | IOMMU_MF_CANSPLIT)) == 0, | ||||
("invalid flags 0x%x", flags)); | ("invalid flags 0x%x", flags)); | ||||
entry = iommu_gas_alloc_entry(domain, | entry = iommu_gas_alloc_entry(domain, | ||||
(flags & IOMMU_MF_CANWAIT) != 0 ? DMAR_PGF_WAITOK : 0); | (flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0); | ||||
if (entry == NULL) | if (entry == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
IOMMU_DOMAIN_LOCK(domain); | IOMMU_DOMAIN_LOCK(domain); | ||||
error = iommu_gas_find_space(domain, common, size, offset, flags, | error = iommu_gas_find_space(domain, common, size, offset, flags, | ||||
entry); | entry); | ||||
if (error == ENOMEM) { | if (error == ENOMEM) { | ||||
IOMMU_DOMAIN_UNLOCK(domain); | IOMMU_DOMAIN_UNLOCK(domain); | ||||
iommu_gas_free_entry(domain, entry); | iommu_gas_free_entry(domain, entry); | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
if (iommu_check_free) | if (iommu_check_free) | ||||
iommu_gas_check_free(domain); | iommu_gas_check_free(domain); | ||||
#endif | #endif | ||||
KASSERT(error == 0, | KASSERT(error == 0, | ||||
("unexpected error %d from iommu_gas_find_entry", error)); | ("unexpected error %d from iommu_gas_find_entry", error)); | ||||
KASSERT(entry->end < domain->end, ("allocated GPA %jx, max GPA %jx", | KASSERT(entry->end < domain->end, ("allocated GPA %jx, max GPA %jx", | ||||
(uintmax_t)entry->end, (uintmax_t)domain->end)); | (uintmax_t)entry->end, (uintmax_t)domain->end)); | ||||
entry->flags |= eflags; | entry->flags |= eflags; | ||||
IOMMU_DOMAIN_UNLOCK(domain); | IOMMU_DOMAIN_UNLOCK(domain); | ||||
error = domain_map_buf(domain, entry->start, entry->end - entry->start, | error = domain_map_buf(domain, entry->start, entry->end - entry->start, | ||||
ma, eflags, | ma, eflags, | ||||
((flags & IOMMU_MF_CANWAIT) != 0 ? DMAR_PGF_WAITOK : 0)); | ((flags & IOMMU_MF_CANWAIT) != 0 ? IOMMU_PGF_WAITOK : 0)); | ||||
if (error == ENOMEM) { | if (error == ENOMEM) { | ||||
iommu_domain_unload_entry(entry, true); | iommu_domain_unload_entry(entry, true); | ||||
return (error); | return (error); | ||||
} | } | ||||
KASSERT(error == 0, | KASSERT(error == 0, | ||||
("unexpected error %d from domain_map_buf", error)); | ("unexpected error %d from domain_map_buf", error)); | ||||
*res = entry; | *res = entry; | ||||
Show All 21 Lines | iommu_gas_map_region(struct iommu_domain *domain, struct iommu_map_entry *entry, | ||||
} | } | ||||
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); | return (0); | ||||
error = domain_map_buf(domain, entry->start, entry->end - entry->start, | error = domain_map_buf(domain, entry->start, entry->end - entry->start, | ||||
ma + OFF_TO_IDX(start - entry->start), eflags, | ma + OFF_TO_IDX(start - entry->start), eflags, | ||||
((flags & IOMMU_MF_CANWAIT) != 0 ? DMAR_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); | ||||
return (error); | return (error); | ||||
} | } | ||||
KASSERT(error == 0, | KASSERT(error == 0, | ||||
("unexpected error %d from domain_map_buf", error)); | ("unexpected error %d from domain_map_buf", error)); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
iommu_gas_reserve_region(struct iommu_domain *domain, iommu_gaddr_t start, | iommu_gas_reserve_region(struct iommu_domain *domain, iommu_gaddr_t start, | ||||
iommu_gaddr_t end) | iommu_gaddr_t end) | ||||
{ | { | ||||
struct iommu_map_entry *entry; | struct iommu_map_entry *entry; | ||||
int error; | int error; | ||||
entry = iommu_gas_alloc_entry(domain, DMAR_PGF_WAITOK); | entry = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK); | ||||
entry->start = start; | entry->start = start; | ||||
entry->end = end; | entry->end = end; | ||||
IOMMU_DOMAIN_LOCK(domain); | IOMMU_DOMAIN_LOCK(domain); | ||||
error = iommu_gas_alloc_region(domain, entry, IOMMU_MF_CANWAIT); | error = iommu_gas_alloc_region(domain, entry, IOMMU_MF_CANWAIT); | ||||
if (error == 0) | if (error == 0) | ||||
entry->flags |= IOMMU_MAP_ENTRY_UNMAPPED; | entry->flags |= IOMMU_MAP_ENTRY_UNMAPPED; | ||||
IOMMU_DOMAIN_UNLOCK(domain); | IOMMU_DOMAIN_UNLOCK(domain); | ||||
if (error != 0) | if (error != 0) | ||||
▲ Show 20 Lines • Show All 52 Lines • Show Last 20 Lines |