enum acpi_irq_model_id acpi_irq_model;
 
-static struct fwnode_handle *acpi_gsi_domain_id;
+static struct fwnode_handle *(*acpi_get_gsi_domain_id)(u32 gsi);
 
 /**
  * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI
  */
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-       struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-                                                       DOMAIN_BUS_ANY);
+       struct irq_domain *d;
 
+       d = irq_find_matching_fwnode(acpi_get_gsi_domain_id(gsi),
+                                       DOMAIN_BUS_ANY);
        *irq = irq_find_mapping(d, gsi);
        /*
         * *irq == 0 means no mapping, that should
 {
        struct irq_fwspec fwspec;
 
-       if (WARN_ON(!acpi_gsi_domain_id)) {
+       fwspec.fwnode = acpi_get_gsi_domain_id(gsi);
+       if (WARN_ON(!fwspec.fwnode)) {
                pr_warn("GSI: No registered irqchip, giving up\n");
                return -EINVAL;
        }
 
-       fwspec.fwnode = acpi_gsi_domain_id;
        fwspec.param[0] = gsi;
        fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
        fwspec.param_count = 2;
  */
 void acpi_unregister_gsi(u32 gsi)
 {
-       struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-                                                       DOMAIN_BUS_ANY);
+       struct irq_domain *d;
        int irq;
 
        if (WARN_ON(acpi_irq_model == ACPI_IRQ_MODEL_GIC && gsi < 16))
                return;
 
+       d = irq_find_matching_fwnode(acpi_get_gsi_domain_id(gsi),
+                                    DOMAIN_BUS_ANY);
        irq = irq_find_mapping(d, gsi);
        irq_dispose_mapping(irq);
 }
  * The referenced device fwhandle or NULL on failure
  */
 static struct fwnode_handle *
-acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
+acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source,
+                            u32 gsi)
 {
        struct fwnode_handle *result;
        struct acpi_device *device;
        acpi_status status;
 
        if (!source->string_length)
-               return acpi_gsi_domain_id;
+               return acpi_get_gsi_domain_id(gsi);
 
        status = acpi_get_handle(NULL, source->string_ptr, &handle);
        if (WARN_ON(ACPI_FAILURE(status)))
                        ctx->index -= irq->interrupt_count;
                        return AE_OK;
                }
-               fwnode = acpi_gsi_domain_id;
+               fwnode = acpi_get_gsi_domain_id(irq->interrupts[ctx->index]);
                acpi_irq_parse_one_match(fwnode, irq->interrupts[ctx->index],
                                         irq->triggering, irq->polarity,
                                         irq->shareable, ctx);
                        ctx->index -= eirq->interrupt_count;
                        return AE_OK;
                }
-               fwnode = acpi_get_irq_source_fwhandle(&eirq->resource_source);
+               fwnode = acpi_get_irq_source_fwhandle(&eirq->resource_source,
+                                                     eirq->interrupts[ctx->index]);
                acpi_irq_parse_one_match(fwnode, eirq->interrupts[ctx->index],
                                         eirq->triggering, eirq->polarity,
                                         eirq->shareable, ctx);
  *          GSI interrupts
  */
 void __init acpi_set_irq_model(enum acpi_irq_model_id model,
-                              struct fwnode_handle *fwnode)
+                              struct fwnode_handle *(*fn)(u32))
 {
        acpi_irq_model = model;
-       acpi_gsi_domain_id = fwnode;
+       acpi_get_gsi_domain_id = fn;
 }
 
 /**
                                             const struct irq_domain_ops *ops,
                                             void *host_data)
 {
-       struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-                                                       DOMAIN_BUS_ANY);
+       struct irq_domain *d;
+
+       /* This only works for the GIC model... */
+       if (acpi_irq_model != ACPI_IRQ_MODEL_GIC)
+               return NULL;
+
+       d = irq_find_matching_fwnode(acpi_get_gsi_domain_id(0),
+                                    DOMAIN_BUS_ANY);
 
        if (!d)
                return NULL;
 
        vgic_set_kvm_info(&gic_v3_kvm_info);
 }
 
+static struct fwnode_handle *gsi_domain_handle;
+
+static struct fwnode_handle *gic_v3_get_gsi_domain_id(u32 gsi)
+{
+       return gsi_domain_handle;
+}
+
 static int __init
 gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)
 {
        struct acpi_madt_generic_distributor *dist;
-       struct fwnode_handle *domain_handle;
        size_t size;
        int i, err;
 
        if (err)
                goto out_redist_unmap;
 
-       domain_handle = irq_domain_alloc_fwnode(&dist->base_address);
-       if (!domain_handle) {
+       gsi_domain_handle = irq_domain_alloc_fwnode(&dist->base_address);
+       if (!gsi_domain_handle) {
                err = -ENOMEM;
                goto out_redist_unmap;
        }
 
        err = gic_init_bases(acpi_data.dist_base, acpi_data.redist_regs,
-                            acpi_data.nr_redist_regions, 0, domain_handle);
+                            acpi_data.nr_redist_regions, 0, gsi_domain_handle);
        if (err)
                goto out_fwhandle_free;
 
-       acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
+       acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v3_get_gsi_domain_id);
 
        if (static_branch_likely(&supports_deactivate_key))
                gic_acpi_setup_kvm_info();
        return 0;
 
 out_fwhandle_free:
-       irq_domain_free_fwnode(domain_handle);
+       irq_domain_free_fwnode(gsi_domain_handle);
 out_redist_unmap:
        for (i = 0; i < acpi_data.nr_redist_regions; i++)
                if (acpi_data.redist_regs[i].redist_base)
 
        vgic_set_kvm_info(&gic_v2_kvm_info);
 }
 
+static struct fwnode_handle *gsi_domain_handle;
+
+static struct fwnode_handle *gic_v2_get_gsi_domain_id(u32 gsi)
+{
+       return gsi_domain_handle;
+}
+
 static int __init gic_v2_acpi_init(union acpi_subtable_headers *header,
                                   const unsigned long end)
 {
        struct acpi_madt_generic_distributor *dist;
-       struct fwnode_handle *domain_handle;
        struct gic_chip_data *gic = &gic_data[0];
        int count, ret;
 
        /*
         * Initialize GIC instance zero (no multi-GIC support).
         */
-       domain_handle = irq_domain_alloc_fwnode(&dist->base_address);
-       if (!domain_handle) {
+       gsi_domain_handle = irq_domain_alloc_fwnode(&dist->base_address);
+       if (!gsi_domain_handle) {
                pr_err("Unable to allocate domain handle\n");
                gic_teardown(gic);
                return -ENOMEM;
        }
 
-       ret = __gic_init_bases(gic, domain_handle);
+       ret = __gic_init_bases(gic, gsi_domain_handle);
        if (ret) {
                pr_err("Failed to initialise GIC\n");
-               irq_domain_free_fwnode(domain_handle);
+               irq_domain_free_fwnode(gsi_domain_handle);
                gic_teardown(gic);
                return ret;
        }
 
-       acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
+       acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v2_get_gsi_domain_id);
 
        if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
                gicv2m_init(NULL, gic_data[0].domain);