int modify_irte(int irq, struct irte *irte_modified) { int rc; int index; struct irte *irte; struct intel_iommu *iommu; struct irq_2_iommu *irq_iommu; unsigned long flags; spin_lock_irqsave(&irq_2_ir_lock, flags); irq_iommu = valid_irq_2_iommu(irq); if (!irq_iommu) { spin_unlock_irqrestore(&irq_2_ir_lock, flags); return -1; } iommu = irq_iommu->iommu; index = irq_iommu->irte_index + irq_iommu->sub_handle; irte = &iommu->ir_table->base[index]; set_64bit((unsigned long *)&irte->low, irte_modified->low); set_64bit((unsigned long *)&irte->high, irte_modified->high); __iommu_flush_cache(iommu, irte, sizeof(*irte)); rc = qi_flush_iec(iommu, index, 0); spin_unlock_irqrestore(&irq_2_ir_lock, flags); return rc; }
int modify_irte(int irq, struct irte *irte_modified) { int index; struct irte *irte; struct intel_iommu *iommu; struct irq_2_iommu *irq_iommu; spin_lock(&irq_2_ir_lock); irq_iommu = valid_irq_2_iommu(irq); if (!irq_iommu) { spin_unlock(&irq_2_ir_lock); return -1; } iommu = irq_iommu->iommu; index = irq_iommu->irte_index + irq_iommu->sub_handle; irte = &iommu->ir_table->base[index]; set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1)); __iommu_flush_cache(iommu, irte, sizeof(*irte)); qi_flush_iec(iommu, index, 0); spin_unlock(&irq_2_ir_lock); return 0; }
static int modify_irte(struct irq_2_iommu *irq_iommu, struct irte *irte_modified) { struct intel_iommu *iommu; unsigned long flags; struct irte *irte; int rc, index; if (!irq_iommu) return -1; raw_spin_lock_irqsave(&irq_2_ir_lock, flags); iommu = irq_iommu->iommu; index = irq_iommu->irte_index + irq_iommu->sub_handle; irte = &iommu->ir_table->base[index]; #if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) if ((irte->pst == 1) || (irte_modified->pst == 1)) { bool ret; ret = cmpxchg_double(&irte->low, &irte->high, irte->low, irte->high, irte_modified->low, irte_modified->high); /* * We use cmpxchg16 to atomically update the 128-bit IRTE, * and it cannot be updated by the hardware or other processors * behind us, so the return value of cmpxchg16 should be the * same as the old value. */ WARN_ON(!ret); } else #endif { set_64bit(&irte->low, irte_modified->low); set_64bit(&irte->high, irte_modified->high); } __iommu_flush_cache(iommu, irte, sizeof(*irte)); rc = qi_flush_iec(iommu, index, 0); /* Update iommu mode according to the IRTE mode */ irq_iommu->mode = irte->pst ? IRQ_POSTING : IRQ_REMAPPING; raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags); return rc; }
static int iommu_load_old_irte(struct intel_iommu *iommu) { struct irte *old_ir_table; phys_addr_t irt_phys; unsigned int i; size_t size; u64 irta; if (!is_kdump_kernel()) { pr_warn("IRQ remapping was enabled on %s but we are not in kdump mode\n", iommu->name); clear_ir_pre_enabled(iommu); iommu_disable_irq_remapping(iommu); return -EINVAL; } /* Check whether the old ir-table has the same size as ours */ irta = dmar_readq(iommu->reg + DMAR_IRTA_REG); if ((irta & INTR_REMAP_TABLE_REG_SIZE_MASK) != INTR_REMAP_TABLE_REG_SIZE) return -EINVAL; irt_phys = irta & VTD_PAGE_MASK; size = INTR_REMAP_TABLE_ENTRIES*sizeof(struct irte); /* Map the old IR table */ old_ir_table = memremap(irt_phys, size, MEMREMAP_WB); if (!old_ir_table) return -ENOMEM; /* Copy data over */ memcpy(iommu->ir_table->base, old_ir_table, size); __iommu_flush_cache(iommu, iommu->ir_table->base, size); /* * Now check the table for used entries and mark those as * allocated in the bitmap */ for (i = 0; i < INTR_REMAP_TABLE_ENTRIES; i++) { if (iommu->ir_table->base[i].present) bitmap_set(iommu->ir_table->bitmap, i, 1); } memunmap(old_ir_table); return 0; }