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; }