From nobody Sat Feb 7 07:11:40 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1769449832; cv=none; d=zohomail.com; s=zohoarc; b=XVwcZj4vWF2rbwCLQq87HRCDDqIneU6QEoL5JgsG07Ep6SGlNDvF3pPjLEiRF2xr0DIYFmj1rGLC9srkv5kxjSiRc+wCduocHgmTqUXvsMzi2Q3msB/I0ieANWouqlqJQ8DGvqB7l6B/r4Kf7QBwo1u5ChtaD66Ji1yUN3/R1Ss= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769449832; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=8v1gA33hjaYhV55XhXrq0Gi+pAkxwSl9Pre/BV0Vh8U=; b=H4ESlcaRRL2WMO+5uxX7NZh6S1gRRz69PETABu/gC68+nY09hlCvATIpP712kHLOltv8CStZQhJwi9a00SJdRqf3r01G+39qAI3Lj61lKG9RPCslhjEY7VvwjR1tAeqdBxSgmPHD09Hnp3f8cqNv2asMB6nvQfCzjLfmTrJeqVg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1769449832472253.35360796331008; Mon, 26 Jan 2026 09:50:32 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vkQd5-0001Zw-FR; Mon, 26 Jan 2026 12:43:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vkQcp-0001Pu-HD for qemu-devel@nongnu.org; Mon, 26 Jan 2026 12:43:44 -0500 Received: from mail-wr1-x42a.google.com ([2a00:1450:4864:20::42a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vkQcm-00007d-Mh for qemu-devel@nongnu.org; Mon, 26 Jan 2026 12:43:43 -0500 Received: by mail-wr1-x42a.google.com with SMTP id ffacd0b85a97d-43596062728so3569223f8f.1 for ; Mon, 26 Jan 2026 09:43:40 -0800 (PST) Received: from thinkpad-t470s.. (93-143-71-105.adsl.net.t-com.hr. [93.143.71.105]) by smtp.googlemail.com with ESMTPSA id ffacd0b85a97d-435b1e71730sm34199603f8f.26.2026.01.26.09.43.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Jan 2026 09:43:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769449419; x=1770054219; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8v1gA33hjaYhV55XhXrq0Gi+pAkxwSl9Pre/BV0Vh8U=; b=ePM+xd18oRM+DGALVxRekZwfc8qIWuzwXEDLyLP/SEclSPvNztKgwaiJPxmnpCsqp7 Jp9ujVzgwIF2X4+ryuYoFGl3QSmM4au4ahGuVQ1cpyOUQCKvL87z8eB9Pb+upfeNzcm9 6SAEzsc41eILZbd9LL0Yspzh9yDpOjonbMcQd7Z1x+b5J4IUGAolY/oKXAGsMfdTRbQt oIhkBE0UVNVOTPi77HZULsnN4q6ENf7sjuKpqztQPHPyHNzcOQAp9QkYKJOB6vGqx4pp eqrprh8sz6+8Vrd7G5zvMwEmPCeyXblB2umUeMn5pGEidqSeEs4xtXZMg6UqppRXHOCL KZuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769449419; x=1770054219; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=8v1gA33hjaYhV55XhXrq0Gi+pAkxwSl9Pre/BV0Vh8U=; b=jgrm48HcqnN71g73wfLiA/A3Z/cA4G/xEyOM6YH0mt8BhvPu3RTq8PUHTgQ6io4V5u XrfoLvjRpzC3CwcXfkf1cx1UfmwmdIgwZZb7pc7xk19Jr1vaRZ375aZKOd6xbgaPcY0q adeqLSMMjzyd/vfc0k3GcJrdKnyvDuv8FiiUrz9JW9MVtekYuLxd/KS+lWCPDvbFlxic t9IYkqtv2KHfgS7q40LPMqjOl7wVIUWIp7utwZDzEqbExr+ySYI+OSbDePeZ4HylJY7e j5DsyUjjnbkGgTa6Yyc550eJaV9VrZVTZBuQbq4R7+jhfMMtf1WGEYABsFhp75dxz/9T xonw== X-Gm-Message-State: AOJu0YyAFcHz5qxpiOQ8GXSqF4oaXMBu/jo45X/i/3GYXIltOxknRCrT UXEeNKChn3LoXTguIMTLvvaIgAY4ql4co5u99qL5z08/rX4fIPnNbUzech+MAjYS X-Gm-Gg: AZuq6aI1WT16CSQnaYfDnqoIIB2waC3UU8uj+ZlzIMqVcbhvaI0THdnpNiq98f1RiKu 1qQXNGKcm36U7YpDyCiXhBvO8mBOdLd0um09fSLgAVQ97Odmu1g7RIUEUvUySq6M4kAWkQutaU3 yaDLgEd9LS2WRiTxZmRVchYvMhUH9lWr52pLtJLck7JKZkyFQRO9ZAR222Wl6JYJzIoNyFmSoFE jFm0OqJRs1Cj55Avuyec0pp67Ucmoiqb7QyilRQC9WOk+ZDWIuG40w8i9jsLypSDt96XN21CdH9 H7A9aWZN1xzDSj9HmoGgKNbm0w/fjqeFGf9zhoOfKbqQVXcFl9uuu0v3xcVPf2QbTecMF7oHVMA wDhVY6aTOkt5WM9YaNGweB9espbWycvacPH1Uf0QBC3HMTdKHSVTy/1HIsdjAziwDCtMHgbWGnk 7gclJAooh05bvA8PxroUp16NkYJEWxOMZFnaz8DbdTW4VPtvhm+pMO5w== X-Received: by 2002:a05:6000:3110:b0:432:59d4:f54a with SMTP id ffacd0b85a97d-435c9d289c5mr10406397f8f.30.1769449418770; Mon, 26 Jan 2026 09:43:38 -0800 (PST) From: Ruslan Ruslichenko To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, peter.maydell@linaro.org, artem_mygaiev@epam.com, volodymyr_babchuk@epam.com, takahiro.nakata.wr@renesas.com, "Edgar E . Iglesias" , Ruslan_Ruslichenko@epam.com Subject: [PATCH 15/27] hw/core/fdt_generic_util: Connect device irqs Date: Mon, 26 Jan 2026 18:43:01 +0100 Message-ID: <20260126174313.1418150-16-ruslichenko.r@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260126174313.1418150-1-ruslichenko.r@gmail.com> References: <20260126174313.1418150-1-ruslichenko.r@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::42a; envelope-from=ruslichenko.r@gmail.com; helo=mail-wr1-x42a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1769449834594154100 Content-Type: text/plain; charset="utf-8" From: Ruslan Ruslichenko The patch implements IRQ wiring logic for fdt created devices. The wiring performed in two stages. As devices are created, their IRQs saved in the list. After all devices processed, fdt_init_all_irqs() goes through all IRQs and does actual wiring. For IRQs which have multiple source, shared IRQ handler allocated. For interrupt controllers with auto_parent callback implemented and their fdt node has 'interrupt and 'interrupts-extended' properties empty, the auto_parent() will be called to connect them to their interrupt-parent, for example to CPUs. Signed-off-by: Ruslan Ruslichenko --- hw/core/fdt_generic_util.c | 146 +++++++++++++++++++++++++++++++++- include/hw/core/fdt_generic.h | 12 +++ 2 files changed, 157 insertions(+), 1 deletion(-) diff --git a/hw/core/fdt_generic_util.c b/hw/core/fdt_generic_util.c index af20ffd9db..2f49909a50 100644 --- a/hw/core/fdt_generic_util.c +++ b/hw/core/fdt_generic_util.c @@ -76,6 +76,88 @@ static void fdt_get_irq_info_from_intc(FDTMachineInfo *f= dti, qemu_irq *ret, uint32_t *cells, uint32_t num_cells, uint32_t max, Error **errp); =20 +typedef struct QEMUIRQSharedState { + qemu_irq sink; + int num; + bool (*merge_fn)(bool *, int); +/* FIXME: remove artificial limit */ +#define MAX_IRQ_SHARED_INPUTS 256 + bool inputs[MAX_IRQ_SHARED_INPUTS]; +} QEMUIRQSharedState; + +static bool qemu_irq_shared_or_handler(bool *inputs, int n) +{ + int i; + + assert(n < MAX_IRQ_SHARED_INPUTS); + + for (i =3D 0; i < n; ++i) { + if (inputs[i]) { + return true; + } + } + return false; +} + +static void qemu_irq_shared_handler(void *opaque, int n, int level) +{ + QEMUIRQSharedState *s =3D opaque; + + assert(n < MAX_IRQ_SHARED_INPUTS); + s->inputs[n] =3D level; + qemu_set_irq(s->sink, s->merge_fn(s->inputs, s->num)); +} + +static void fdt_init_all_irqs(FDTMachineInfo *fdti) +{ + while (fdti->irqs) { + FDTIRQConnection *first =3D fdti->irqs; + qemu_irq sink =3D first->irq; + bool (*merge_fn)(bool *, int) =3D first->merge_fn; + int num_sources =3D 0; + FDTIRQConnection *irq; + + for (irq =3D first; irq; irq =3D irq->next) { + if (irq->irq =3D=3D sink) { /* Same sink */ + num_sources++; + } + } + if (num_sources > 1) { + QEMUIRQSharedState *s =3D g_malloc0(sizeof *s); + s->sink =3D sink; + s->merge_fn =3D merge_fn; + qemu_irq *sources =3D qemu_allocate_irqs(qemu_irq_shared_handl= er, s, + num_sources); + for (irq =3D first; irq; irq =3D irq->next) { + if (irq->irq =3D=3D sink) { + char *shared_irq_name =3D g_strdup_printf("shared-irq-= %p", + *sources); + + if (irq->merge_fn !=3D merge_fn) { + fprintf(stderr, "ERROR: inconsistent IRQ merge fns= \n"); + exit(1); + } + + object_property_add_child(OBJECT(irq->dev), shared_irq= _name, + OBJECT(*sources)); + g_free(shared_irq_name); + irq->irq =3D *(sources++); + s->num++; + } + } + } + DB_PRINT(0, "%s: connected to %s irq line %d (%s)\n", + first->sink_info ? first->sink_info : "", + object_get_canonical_path(OBJECT(first->dev)), + first->i, first->name ? first->name : ""); + + qdev_connect_gpio_out_named(DEVICE(first->dev), first->name, first= ->i, + first->irq); + fdti->irqs =3D first->next; + g_free(first); + } +} + FDTMachineInfo *fdt_generic_create_machine(void *fdt, qemu_irq *cpu_irq) { char node_path[DT_PATH_LENGTH]; @@ -91,6 +173,7 @@ FDTMachineInfo *fdt_generic_create_machine(void *fdt, qe= mu_irq *cpu_irq) while (qemu_co_enter_next(fdti->cq, NULL)) { ; } + fdt_init_all_irqs(fdti); memory_region_transaction_commit(); } else { fprintf(stderr, "FDT: ERROR: cannot get root node from device tree= %s\n" @@ -908,8 +991,9 @@ static int fdt_init_qdev(char *node_path, FDTMachineInf= o *fdti, char *compat) { Object *dev, *parent; char *dev_type =3D NULL; + int is_intc; Error *errp =3D NULL; - int i; + int i, j; QEMUDevtreeProp *prop, *props; char parent_node_path[DT_PATH_LENGTH]; =20 @@ -1125,6 +1209,66 @@ exit_reg_parse: } } =20 + if (object_dynamic_cast(dev, TYPE_SYS_BUS_DEVICE)) { + { + int len; + fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_pa= th), + "interrupt-controller", &len); + is_intc =3D len >=3D 0; + DB_PRINT_NP(is_intc ? 0 : 1, "is interrupt controller: %c\n", + is_intc ? 'y' : 'n'); + } + /* connect irq */ + j =3D 0; + for (i =3D 0;; i++) { + char irq_info[6 * 1024]; + char *irq_info_p =3D irq_info; + bool map_mode; + int len =3D -1; + qemu_irq *irqs =3D fdt_get_irq_info(fdti, node_path, i, irq_in= fo, + &map_mode); + /* INTCs inferr their top level, if no IRQ connection specifie= d */ + fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_pa= th), + "interrupts-extended", &len); + if (!irqs && is_intc && i =3D=3D 0 && len <=3D 0) { + FDTGenericIntc *id =3D (FDTGenericIntc *)object_dynamic_ca= st( + dev, TYPE_FDT_GENERIC_INTC); + FDTGenericIntcClass *idc =3D FDT_GENERIC_INTC_GET_CLASS(id= ); + if (id && idc->auto_parent) { + Error *err =3D NULL; + idc->auto_parent(id, &err); + } else { + irqs =3D fdti->irq_base; + } + } + if (!irqs) { + break; + } + while (*irqs) { + FDTIRQConnection *irq =3D g_new0(FDTIRQConnection, 1); + *irq =3D (FDTIRQConnection) { + .dev =3D DEVICE(dev), + .name =3D SYSBUS_DEVICE_GPIO_IRQ, + .merge_fn =3D qemu_irq_shared_or_handler, + .i =3D j, + .irq =3D *irqs, + .sink_info =3D g_strdup(irq_info_p), + .next =3D fdti->irqs + }; + if (!map_mode) { + j++; + } else { + irq_info_p +=3D strlen(irq_info_p) + 1; + } + fdti->irqs =3D irq; + irqs++; + } + if (map_mode) { + j++; + } + } + } + g_free(dev_type); =20 return 0; diff --git a/include/hw/core/fdt_generic.h b/include/hw/core/fdt_generic.h index 46b7dc084b..ad9e249156 100644 --- a/include/hw/core/fdt_generic.h +++ b/include/hw/core/fdt_generic.h @@ -24,6 +24,16 @@ typedef struct FDTCPUCluster { bool user; } FDTCPUCluster; =20 +typedef struct FDTIRQConnection { + DeviceState *dev; + const char *name; + int i; + bool (*merge_fn)(bool *, int); + qemu_irq irq; + char *sink_info; /* Debug only */ + void *next; +} FDTIRQConnection; + typedef struct FDTMachineInfo { /* the fdt blob */ void *fdt; @@ -33,6 +43,8 @@ typedef struct FDTMachineInfo { FDTDevOpaque *dev_opaques; /* recheck coroutine queue */ CoQueue *cq; + /* list of all IRQ connections */ + FDTIRQConnection *irqs; /* list of all CPU clusters */ FDTCPUCluster *clusters; } FDTMachineInfo; --=20 2.43.0