int its_alloc_vcpu_irqs(struct its_vm *vm) { int vpe_base_irq, i; vm->fwnode = irq_domain_alloc_named_id_fwnode("GICv4-vpe", task_pid_nr(current)); if (!vm->fwnode) goto err; vm->domain = irq_domain_create_hierarchy(gic_domain, 0, vm->nr_vpes, vm->fwnode, vpe_domain_ops, vm); if (!vm->domain) goto err; for (i = 0; i < vm->nr_vpes; i++) { vm->vpes[i]->its_vm = vm; vm->vpes[i]->idai = true; } vpe_base_irq = __irq_domain_alloc_irqs(vm->domain, -1, vm->nr_vpes, NUMA_NO_NODE, vm, false, NULL); if (vpe_base_irq <= 0) goto err; for (i = 0; i < vm->nr_vpes; i++) vm->vpes[i]->irq = vpe_base_irq + i; return 0; err: if (vm->domain) irq_domain_remove(vm->domain); if (vm->fwnode) irq_domain_free_fwnode(vm->fwnode); return -ENOMEM; }
static struct irq_domain *uv_get_irq_domain(void) { static struct irq_domain *uv_domain; static DEFINE_MUTEX(uv_lock); struct fwnode_handle *fn; mutex_lock(&uv_lock); if (uv_domain) goto out; fn = irq_domain_alloc_named_fwnode("UV-CORE"); if (!fn) goto out; uv_domain = irq_domain_create_tree(fn, &uv_domain_ops, NULL); irq_domain_free_fwnode(fn); if (uv_domain) uv_domain->parent = x86_vector_domain; out: mutex_unlock(&uv_lock); return uv_domain; }
static int __init hyperv_prepare_irq_remapping(void) { struct fwnode_handle *fn; int i; if (!hypervisor_is_type(X86_HYPER_MS_HYPERV) || !x2apic_supported()) return -ENODEV; fn = irq_domain_alloc_named_id_fwnode("HYPERV-IR", 0); if (!fn) return -ENOMEM; ioapic_ir_domain = irq_domain_create_hierarchy(arch_get_ir_parent_domain(), 0, IOAPIC_REMAPPING_ENTRY, fn, &hyperv_ir_domain_ops, NULL); irq_domain_free_fwnode(fn); /* * Hyper-V doesn't provide irq remapping function for * IO-APIC and so IO-APIC only accepts 8-bit APIC ID. * Cpu's APIC ID is read from ACPI MADT table and APIC IDs * in the MADT table on Hyper-v are sorted monotonic increasingly. * APIC ID reflects cpu topology. There maybe some APIC ID * gaps when cpu number in a socket is not power of two. Prepare * max cpu affinity for IOAPIC irqs. Scan cpu 0-255 and set cpu * into ioapic_max_cpumask if its APIC ID is less than 256. */ for (i = min_t(unsigned int, num_possible_cpus() - 1, 255); i >= 0; i--) if (cpu_physical_id(i) < 256) cpumask_set_cpu(i, &ioapic_max_cpumask); return 0; }
static int intel_setup_irq_remapping(struct intel_iommu *iommu) { struct ir_table *ir_table; struct fwnode_handle *fn; unsigned long *bitmap; struct page *pages; if (iommu->ir_table) return 0; ir_table = kzalloc(sizeof(struct ir_table), GFP_KERNEL); if (!ir_table) return -ENOMEM; pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, INTR_REMAP_PAGE_ORDER); if (!pages) { pr_err("IR%d: failed to allocate pages of order %d\n", iommu->seq_id, INTR_REMAP_PAGE_ORDER); goto out_free_table; } bitmap = kcalloc(BITS_TO_LONGS(INTR_REMAP_TABLE_ENTRIES), sizeof(long), GFP_ATOMIC); if (bitmap == NULL) { pr_err("IR%d: failed to allocate bitmap\n", iommu->seq_id); goto out_free_pages; } fn = irq_domain_alloc_named_id_fwnode("INTEL-IR", iommu->seq_id); if (!fn) goto out_free_bitmap; iommu->ir_domain = irq_domain_create_hierarchy(arch_get_ir_parent_domain(), 0, INTR_REMAP_TABLE_ENTRIES, fn, &intel_ir_domain_ops, iommu); irq_domain_free_fwnode(fn); if (!iommu->ir_domain) { pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id); goto out_free_bitmap; } iommu->ir_msi_domain = arch_create_remap_msi_irq_domain(iommu->ir_domain, "INTEL-IR-MSI", iommu->seq_id); ir_table->base = page_address(pages); ir_table->bitmap = bitmap; iommu->ir_table = ir_table; /* * If the queued invalidation is already initialized, * shouldn't disable it. */ if (!iommu->qi) { /* * Clear previous faults. */ dmar_fault(-1, iommu); dmar_disable_qi(iommu); if (dmar_enable_qi(iommu)) { pr_err("Failed to enable queued invalidation\n"); goto out_free_bitmap; } } init_ir_status(iommu); if (ir_pre_enabled(iommu)) { 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); } else if (iommu_load_old_irte(iommu)) pr_err("Failed to copy IR table for %s from previous kernel\n", iommu->name); else pr_info("Copied IR table for %s from previous kernel\n", iommu->name); } iommu_set_irq_remapping(iommu, eim_mode); return 0; out_free_bitmap: kfree(bitmap); out_free_pages: __free_pages(pages, INTR_REMAP_PAGE_ORDER); out_free_table: kfree(ir_table); iommu->ir_table = NULL; return -ENOMEM; }
void its_free_vcpu_irqs(struct its_vm *vm) { irq_domain_free_irqs(vm->vpes[0]->irq, vm->nr_vpes); irq_domain_remove(vm->domain); irq_domain_free_fwnode(vm->fwnode); }