Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/iommu/intel_qi.c
Show First 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | |||||
taskqueue_enqueue(unit->qi_taskqueue, &unit->qi_task); | taskqueue_enqueue(unit->qi_taskqueue, &unit->qi_task); | ||||
return (FILTER_HANDLED); | return (FILTER_HANDLED); | ||||
} | } | ||||
static void | static void | ||||
dmar_qi_task(void *arg, int pending __unused) | dmar_qi_task(void *arg, int pending __unused) | ||||
{ | { | ||||
struct dmar_unit *unit; | struct dmar_unit *unit; | ||||
struct iommu_domain *domain; | |||||
struct iommu_map_entry *entry, *head; | struct iommu_map_entry *entry, *head; | ||||
uint32_t ics; | uint32_t ics; | ||||
unit = arg; | unit = arg; | ||||
/* | /* | ||||
* Request an interrupt on the completion of the next invalidation | * Request an interrupt on the completion of the next invalidation | ||||
* wait descriptor with the IF field set. | * wait descriptor with the IF field set. | ||||
*/ | */ | ||||
ics = dmar_read4(unit, DMAR_ICS_REG); | ics = dmar_read4(unit, DMAR_ICS_REG); | ||||
if ((ics & DMAR_ICS_IWC) != 0) { | if ((ics & DMAR_ICS_IWC) != 0) { | ||||
ics = DMAR_ICS_IWC; | ics = DMAR_ICS_IWC; | ||||
dmar_write4(unit, DMAR_ICS_REG, ics); | dmar_write4(unit, DMAR_ICS_REG, ics); | ||||
} | } | ||||
for (;;) { | for (;;) { | ||||
head = unit->tlb_flush_head; | head = unit->tlb_flush_head; | ||||
entry = (struct iommu_map_entry *) | entry = (struct iommu_map_entry *) | ||||
atomic_load_acq_ptr((uintptr_t *)&head->tlb_flush_next); | atomic_load_acq_ptr((uintptr_t *)&head->tlb_flush_next); | ||||
if (entry == NULL) | if (entry == NULL) | ||||
break; | break; | ||||
if (!dmar_qi_seq_processed(unit, &entry->gseq)) | if (!dmar_qi_seq_processed(unit, &entry->gseq)) | ||||
break; | break; | ||||
unit->tlb_flush_head = entry; | unit->tlb_flush_head = entry; | ||||
iommu_gas_free_entry(head->domain, head); | iommu_gas_free_entry(head); | ||||
domain = entry->domain; | |||||
IOMMU_DOMAIN_LOCK(domain); | |||||
if ((entry->flags & IOMMU_MAP_ENTRY_RMRR) != 0) | if ((entry->flags & IOMMU_MAP_ENTRY_RMRR) != 0) | ||||
iommu_gas_free_region(domain, entry); | iommu_gas_free_region(entry); | ||||
else | else | ||||
iommu_gas_free_space(domain, entry); | iommu_gas_free_space(entry); | ||||
IOMMU_DOMAIN_UNLOCK(domain); | |||||
} | } | ||||
if (unit->inv_seq_waiters > 0) { | if (unit->inv_seq_waiters > 0) { | ||||
/* | /* | ||||
* Acquire the DMAR lock so that wakeup() is called only after | * Acquire the DMAR lock so that wakeup() is called only after | ||||
* the waiter is sleeping. | * the waiter is sleeping. | ||||
*/ | */ | ||||
DMAR_LOCK(unit); | DMAR_LOCK(unit); | ||||
wakeup(&unit->inv_seq_waiters); | wakeup(&unit->inv_seq_waiters); | ||||
▲ Show 20 Lines • Show All 91 Lines • Show Last 20 Lines |