From nobody Wed Apr 8 04:27:16 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773163068; cv=none; d=zohomail.com; s=zohoarc; b=RNVzq3A8A1iOoDvSfF9v7P8nNi68aAwQWZxhiKOEvcqQgUnktEj4k/MAgaaledJ2jywW8t11ToR/DRMFSVTlEA/1FT0qMoZMgAXZkdzm5MmsGTy+PsdATDHnU6CQNYBbToNuAXw41YDu1uI4FQnZwFkuy3/cot4G/D9mg/5Wj8Q= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773163068; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=1QzhisNeEOl5GG/axHTaY1VrOGJ87S7KPahT63K4FL0=; b=erPmy/Sn7x5KU/W4eipjsUdvTtIAY5Kzc/AtOrBsHbjJBIDuYDfeAN7NmxBMdSF/CaUCNlZh2+IxGaA7WACj7X614gN2eUbsHSonraV5QDKUJR94/S4yAGfAURVRdJDMeVD55noq2j3LcXG2MfFOfpUFH70GRnjkgvs5qasHV6s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1773163068813936.3589985279546; Tue, 10 Mar 2026 10:17:48 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1250499.1547989 (Exim 4.92) (envelope-from ) id 1w00hz-0001sp-Tj; Tue, 10 Mar 2026 17:17:27 +0000 Received: by outflank-mailman (output) from mailman id 1250499.1547989; Tue, 10 Mar 2026 17:17:27 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1w00hz-0001sf-Qa; Tue, 10 Mar 2026 17:17:27 +0000 Received: by outflank-mailman (input) for mailman id 1250499; Tue, 10 Mar 2026 17:17:26 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1w00aJ-0001QA-9q for xen-devel@lists.xenproject.org; Tue, 10 Mar 2026 17:09:31 +0000 Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [2a00:1450:4864:20::32c]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id e635720d-1ca3-11f1-9ccf-f158ae23cfc8; Tue, 10 Mar 2026 18:09:29 +0100 (CET) Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-48539d21b76so20305135e9.1 for ; Tue, 10 Mar 2026 10:09:29 -0700 (PDT) Received: from fedora (user-109-243-67-101.play-internet.pl. [109.243.67.101]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-485359bf807sm119619845e9.2.2026.03.10.10.09.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 10 Mar 2026 10:09:28 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: e635720d-1ca3-11f1-9ccf-f158ae23cfc8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773162569; x=1773767369; darn=lists.xenproject.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=1QzhisNeEOl5GG/axHTaY1VrOGJ87S7KPahT63K4FL0=; b=QRnE/YbuQxS5aJsCV1+VHm3IC/UsB81S8opwqaYiMnl3i672gr5xq3uwdlCOzBOaHR HzEAe7scP69C2TpkeCRcpAwSZkj2qlea0fdUReJARKMwivOnu1QPubvlHIws9SBO7A6m ll1TAX5d7wHh7VA+ihPtpsJOoO7ud3BQmaBlobhUeC41cKAYhltGByFIqS0kanz0VDTM vW9Dbwg5JO3mhYWWenjb1bbRdCy4euHUot+8tzidopxZ0388Q9GwK0i0Hw6qhcRiKUTN yvp/9CK063/uTOaxKU4+FA550XTu7mHht1eVgRN552Ck+k45H+jx3WNOLEy1CzagNCdr kyTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773162569; x=1773767369; 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=1QzhisNeEOl5GG/axHTaY1VrOGJ87S7KPahT63K4FL0=; b=uHhY1BSJcVMoHtrsi6XEY0VoUuRNenbTaAz593RRwsg+H3Znb8gj8Qlw1uGQJV5yU6 mPvpcA1DWm0OamktGw99yTDsWtx5yyk6HUyfLBJtNlZZONmyAmD29hEktzpXJIBrsERi ARAoxDF24ZvQBVBrhd6ofWQ+NA5Qz087di6RS/QuFJhVg8frSkk9W2F/0Mq0PJo0Sm1f K5BnYBie7IofBFf6BlEliWGhAwfQeujqss7KmgeGr0vye6ebT5Y5d9xSKCFcR7jI54Vh OOOJyCTUaYbEOmSZGsS3dLqnmS3MJrXd59g+gsk+K/BUYqhytwNs+/H5Vh1JNdORSkTc r6kQ== X-Gm-Message-State: AOJu0YwUjtVCh53HhmnBe9NzB1H9p2gVx2NwP+o51D3ElOjTAINqB1c5 IpAInqJZFqLx2WdPOaDTqEgBEXotpNTs81gxm8t1Z3WbgIYXh/atgEVKv2nOOgou X-Gm-Gg: ATEYQzybt1JojwHVHE5NESSNSDv6kr2dKw59Ge+Lq6sbMAIzu4k5URkk1oNlt/TZ+gs D1Bl4RW/qAEs4d+sb1PHA7rnh4NC9rRRhmYafay0oYuUrNZlQ+7pBB9VATgUSM5N5EOkN9Yy9J8 VWwVzH4EnbDexnUj8gvkhlA2GNw0L3kfSgIoZET5VDPnmCIx0EAIpp4JozMClpXdmk6IRK89abc 3FpiJppI5shIkgUpwW+KcJ/SFa1Ci60UJS+lcv9GeWCHtT2LIkD/hdzgKZ752qYUr74xgTrPsaq JLYHVNuF+7PuDoRpaidzhj00mqEyM0o8/KsZZ76+KxnpMVPz9hlzHrPWWNYXRGxs5HzDazY+YbJ 7ZbHdfpGRu7aBJN8zfzPEMKZ05JwmSf3NtVKTiS1cGSvZ79n2o4RRXaPF0zUhRnm4qXiJf+FP6r xg/0E8AmWEBX8oSYH/HeprzQwBKVJsZ+KGCuzz/LcgteOiZIstg6sfEEEsgf5EcSmSPA== X-Received: by 2002:a05:600c:8719:b0:485:39d1:b4ca with SMTP id 5b1f17b1804b1-48539d1bb25mr151543855e9.9.1773162568498; Tue, 10 Mar 2026 10:09:28 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v1 16/27] xen/riscv: implement IRQ mapping for device passthrough Date: Tue, 10 Mar 2026 18:08:49 +0100 Message-ID: <10654a6c38fa929b5fdf6f214badfe4f60fe78d4.1773157782.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773163069526158500 Content-Type: text/plain; charset="utf-8" Add initial support for assigning device interrupts to domains in dom0less configurations. IRQs described in the device tree are retrieved and authorized for the target domain. Interrupts that are not connected to the primary interrupt controller (at the momemnt, I haven't seen the platform with secondary interrupt controller) are ignored, and IRQs already assigned to another domain are rejected to prevent sharing. Signed-off-by: Oleksii Kurochko --- For better undesrstanding how auth_irq_bmp[] is going to be used it is also introduced two extra patches which are going after this. They aren't really needed now as this code will be used when guest will be ran, but it improves understanding and it in general can go with this patch series. --- --- xen/arch/riscv/include/asm/aplic.h | 2 + xen/arch/riscv/include/asm/intc.h | 12 +++ xen/arch/riscv/include/asm/setup.h | 17 ++++ xen/arch/riscv/intc.c | 8 ++ xen/arch/riscv/vaplic.c | 124 ++++++++++++++++++++++++++++- 5 files changed, 162 insertions(+), 1 deletion(-) diff --git a/xen/arch/riscv/include/asm/aplic.h b/xen/arch/riscv/include/as= m/aplic.h index b0724fe6f360..55cd4a128de7 100644 --- a/xen/arch/riscv/include/asm/aplic.h +++ b/xen/arch/riscv/include/asm/aplic.h @@ -15,6 +15,8 @@ =20 #include =20 +#define APLIC_NUM_REGS 32 + #define APLIC_DOMAINCFG_IE BIT(8, U) #define APLIC_DOMAINCFG_DM BIT(2, U) =20 diff --git a/xen/arch/riscv/include/asm/intc.h b/xen/arch/riscv/include/asm= /intc.h index c5a869db8bc5..76d2fd09cb8b 100644 --- a/xen/arch/riscv/include/asm/intc.h +++ b/xen/arch/riscv/include/asm/intc.h @@ -16,6 +16,7 @@ struct cpu_user_regs; struct dt_device_node; struct irq_desc; struct kernel_info; +struct rangeset; struct vcpu; =20 struct intc_info { @@ -54,11 +55,22 @@ struct vintc_ops { =20 /* Check if a register is virtual interrupt controller MMIO */ int (*is_access)(const struct vcpu *vcpu, const unsigned long addr); + + /* + * Retrieves the interrupts configuration from a device tree node and = maps + * those interrupts to the target domain. + */ + int (*map_device_irqs_to_domain)(struct domain *d, + struct dt_device_node *dev, + bool need_mapping, + struct rangeset *irq_ranges); }; =20 struct vintc { const struct intc_info *info; const struct vintc_ops *ops; + + void *private; }; =20 void intc_preinit(void); diff --git a/xen/arch/riscv/include/asm/setup.h b/xen/arch/riscv/include/as= m/setup.h index 2215894cfbb1..1c23043f409f 100644 --- a/xen/arch/riscv/include/asm/setup.h +++ b/xen/arch/riscv/include/asm/setup.h @@ -5,6 +5,10 @@ =20 #include =20 +struct domain; +struct dt_device_node; +struct rangeset; + #define max_init_domid (0) =20 void setup_mm(void); @@ -13,6 +17,19 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned = long len); =20 void init_csr_masks(void); =20 +/* TODO: move somewhere to common header? */ +/* + * Retrieves the interrupts configuration from a device tree node and maps + * those interrupts to the target domain. + * + * Returns: + * < 0 error + * 0 success + */ +int map_device_irqs_to_domain(struct domain *d, struct dt_device_node *dev, + bool need_mapping, + struct rangeset *irq_ranges); + #endif /* ASM__RISCV__SETUP_H */ =20 /* diff --git a/xen/arch/riscv/intc.c b/xen/arch/riscv/intc.c index ff7a76accaca..a91dbc5e997c 100644 --- a/xen/arch/riscv/intc.c +++ b/xen/arch/riscv/intc.c @@ -79,3 +79,11 @@ int __init intc_make_domu_dt_node(const struct kernel_in= fo *kinfo) =20 return -ENOSYS; } + +int map_device_irqs_to_domain(struct domain *d, struct dt_device_node *dev, + bool need_mapping, + struct rangeset *irq_ranges) +{ + return d->arch.vintc->ops->map_device_irqs_to_domain(d, dev, need_mapp= ing, + irq_ranges); +} diff --git a/xen/arch/riscv/vaplic.c b/xen/arch/riscv/vaplic.c index 9b105de7ed7d..0c69f087cf4d 100644 --- a/xen/arch/riscv/vaplic.c +++ b/xen/arch/riscv/vaplic.c @@ -9,6 +9,7 @@ */ =20 #include +#include #include #include =20 @@ -19,6 +20,113 @@ =20 #include "aplic-priv.h" =20 +struct vaplic_priv { + /* Contains a legal interrupts for a domain */ + uint32_t auth_irq_bmp[APLIC_NUM_REGS]; +}; + +static bool is_irq_shared_among_domains(const struct domain *d, + const unsigned int irq_num) +{ + struct domain *tmp; + unsigned int reg_num =3D irq_num / APLIC_NUM_REGS; + unsigned int bit_pos =3D irq_num % APLIC_NUM_REGS; + + for_each_domain ( tmp ) + { + uint32_t *auth_irq_bmp; + + if ( tmp =3D=3D d ) + continue; + + auth_irq_bmp =3D tmp->arch.vintc->private; + + if ( auth_irq_bmp[reg_num] & BIT(bit_pos, U) ) + { + printk("%s: irq%d is shared between %pd and %pd\n", __func__, + irq_num, tmp, d); + + return true; + } + } + + return false; +} + +int vaplic_map_device_irqs_to_domain(struct domain *d, + struct dt_device_node *dev, + bool need_mapping, + struct rangeset *irq_ranges) +{ + unsigned int i, nirq; + int res, irq; + struct dt_raw_irq rirq; + uint32_t *auth_irq_bmp =3D d->arch.vintc->private; + unsigned int reg_num; + + nirq =3D dt_number_of_irq(dev); + + /* Give permission and map IRQs */ + for ( i =3D 0; i < nirq; i++ ) + { + res =3D dt_device_get_raw_irq(dev, i, &rirq); + if ( res ) + { + printk(XENLOG_ERR "Unable to retrieve irq %u for %s\n", + i, dt_node_full_name(dev)); + return res; + } + + /* + * Don't map IRQ that have no physical meaning + * ie: IRQ whose controller is not APLIC/IMSIC/PLIC. + */ + if ( rirq.controller !=3D dt_interrupt_controller ) + { + dt_dprintk("irq %u not connected to primary controller." + "Connected to %s\n", i, + dt_node_full_name(rirq.controller)); + continue; + } + + irq =3D platform_get_irq(dev, i); + if ( irq < 0 ) + { + printk("Unable to get irq %u for %s\n", i, dt_node_full_name(d= ev)); + return irq; + } + + res =3D irq_permit_access(d, irq); + if ( res ) + { + printk(XENLOG_ERR "Unable to permit to %pd access to IRQ %u\n"= , d, + irq); + return res; + } + + reg_num =3D irq / APLIC_NUM_REGS; + + if ( is_irq_shared_among_domains(d, irq) ) + { + printk("%s: Shared IRQ isn't supported\n", __func__); + return -EINVAL; + } + + auth_irq_bmp[reg_num] |=3D BIT(irq % APLIC_NUM_REGS, U); + + dt_dprintk(" - IRQ: %u\n", irq); + + if ( irq_ranges ) + { + res =3D rangeset_add_singleton(irq_ranges, irq); + if ( res ) + return res; + } + } + + return 0; +} + static int __init cf_check vcpu_vaplic_init(struct vcpu *v) { int rc =3D 0; @@ -34,6 +142,7 @@ static int __init cf_check vcpu_vaplic_init(struct vcpu = *v) =20 static const struct vintc_ops vaplic_ops =3D { .vcpu_init =3D vcpu_vaplic_init, + .map_device_irqs_to_domain =3D vaplic_map_device_irqs_to_domain, }; =20 static struct vintc * __init vaplic_alloc(void) @@ -62,13 +171,26 @@ int __init domain_vaplic_init(struct domain *d) to_vaplic(d->arch.vintc)->regs.domaincfg =3D APLIC_DOMAINCFG_IE | APLIC_DOMAINCFG_DM; =20 + d->arch.vintc->private =3D xvzalloc(struct vaplic_priv); + if ( !d->arch.vintc->private ) + { + ret =3D -ENOMEM; + goto fail; + } + + return ret; + fail: + domain_vaplic_deinit(d); + return ret; } =20 void __init domain_vaplic_deinit(struct domain *d) { - struct vaplic *vaplic =3D to_vaplic(d->arch.vintc); + struct vintc *vintc =3D d->arch.vintc; + struct vaplic *vaplic =3D to_vaplic(vintc); =20 + XVFREE(vintc->private); XVFREE(vaplic); } --=20 2.53.0