Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/iommu/iommu_gas.c
Context not available. | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/counter.h> | |||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/interrupt.h> | #include <sys/interrupt.h> | ||||
Context not available. | |||||
return (false); | return (false); | ||||
} | } | ||||
static COUNTER_U64_DEFINE_EARLY(gas_total); | |||||
SYSCTL_COUNTER_U64(_hw_iommu, OID_AUTO, gas_total, CTLFLAG_RD, | |||||
&gas_total, | |||||
"Sum of gas tree sizes"); | |||||
static void | static void | ||||
iommu_gas_match_insert(struct iommu_gas_match_args *a) | iommu_gas_match_insert(struct iommu_gas_match_args *a) | ||||
{ | { | ||||
Context not available. | |||||
*/ | */ | ||||
a->entry->end = a->entry->start + a->size; | a->entry->end = a->entry->start + a->size; | ||||
counter_u64_add(gas_total, a->domain->entries_cnt); | |||||
found = iommu_gas_rb_insert(a->domain, a->entry); | found = iommu_gas_rb_insert(a->domain, a->entry); | ||||
KASSERT(found, ("found dup %p start %jx size %jx", | KASSERT(found, ("found dup %p start %jx size %jx", | ||||
a->domain, (uintmax_t)a->entry->start, (uintmax_t)a->size)); | a->domain, (uintmax_t)a->entry->start, (uintmax_t)a->size)); | ||||
a->entry->flags = IOMMU_MAP_ENTRY_MAP; | a->entry->flags = IOMMU_MAP_ENTRY_MAP; | ||||
} | } | ||||
static COUNTER_U64_DEFINE_EARLY(gas_lookup); | |||||
SYSCTL_COUNTER_U64(_hw_iommu, OID_AUTO, gas_lookup, CTLFLAG_RD, | |||||
&gas_lookup, | |||||
"Number of gas node accesses"); | |||||
static int | static int | ||||
iommu_gas_lowermatch(struct iommu_gas_match_args *a, struct iommu_map_entry *entry) | iommu_gas_lowermatch(struct iommu_gas_match_args *a, struct iommu_map_entry *entry) | ||||
{ | { | ||||
Context not available. | |||||
if (entry->first >= a->common->lowaddr) | if (entry->first >= a->common->lowaddr) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
child = RB_RIGHT(entry, rb_entry); | child = RB_RIGHT(entry, rb_entry); | ||||
if (child != NULL) | |||||
counter_u64_add(gas_lookup, 1); | |||||
if (child != NULL && 0 == iommu_gas_lowermatch(a, child)) | if (child != NULL && 0 == iommu_gas_lowermatch(a, child)) | ||||
return (0); | return (0); | ||||
if (child != NULL && entry->end < a->common->lowaddr && | if (child != NULL && entry->end < a->common->lowaddr && | ||||
Context not available. | |||||
return (0); | return (0); | ||||
} | } | ||||
child = RB_LEFT(entry, rb_entry); | child = RB_LEFT(entry, rb_entry); | ||||
if (child != NULL) | |||||
counter_u64_add(gas_lookup, 1); | |||||
if (child != NULL && child->last < a->common->lowaddr && | if (child != NULL && child->last < a->common->lowaddr && | ||||
iommu_gas_match_one(a, child->last, entry->start, | iommu_gas_match_one(a, child->last, entry->start, | ||||
a->common->lowaddr)) { | a->common->lowaddr)) { | ||||
Context not available. | |||||
if (entry->last < a->common->highaddr) | if (entry->last < a->common->highaddr) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
child = RB_LEFT(entry, rb_entry); | child = RB_LEFT(entry, rb_entry); | ||||
if (child != NULL) | |||||
counter_u64_add(gas_lookup, 1); | |||||
if (child != NULL && 0 == iommu_gas_uppermatch(a, child)) | if (child != NULL && 0 == iommu_gas_uppermatch(a, child)) | ||||
return (0); | return (0); | ||||
if (child != NULL && child->last >= a->common->highaddr && | if (child != NULL && child->last >= a->common->highaddr && | ||||
Context not available. | |||||
return (0); | return (0); | ||||
} | } | ||||
child = RB_RIGHT(entry, rb_entry); | child = RB_RIGHT(entry, rb_entry); | ||||
if (child != NULL) | |||||
counter_u64_add(gas_lookup, 1); | |||||
if (child != NULL && entry->end >= a->common->highaddr && | if (child != NULL && entry->end >= a->common->highaddr && | ||||
iommu_gas_match_one(a, entry->end, child->first, | iommu_gas_match_one(a, entry->end, child->first, | ||||
a->domain->end)) { | a->domain->end)) { | ||||
Context not available. | |||||
a.entry = entry; | a.entry = entry; | ||||
/* Handle lower region. */ | /* Handle lower region. */ | ||||
if (common->lowaddr > 0 ||common->highaddr < domain->end) | |||||
counter_u64_add(gas_lookup, 1); | |||||
if (common->lowaddr > 0) { | if (common->lowaddr > 0) { | ||||
error = iommu_gas_lowermatch(&a, | error = iommu_gas_lowermatch(&a, | ||||
RB_ROOT(&domain->rb_root)); | RB_ROOT(&domain->rb_root)); | ||||
Context not available. | |||||
{ | { | ||||
int error; | int error; | ||||
CTR4(KTR_SPARE5, | |||||
"iommu_map: domain %p, entries %u, size %jd, offset %d", | |||||
domain, domain->entries_cnt, (uintmax_t)size, offset); | |||||
error = iommu_gas_map(domain, common, size, offset, eflags, flags, | error = iommu_gas_map(domain, common, size, offset, eflags, flags, | ||||
ma, res); | ma, res); | ||||
Context not available. |