From patchwork Tue Apr 8 10:50:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042821 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D4CEFC3600C for ; Tue, 8 Apr 2025 11:18:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=o15CI+vxxZcLoEcn2vbhrpaY247kAhk2S/bYBOyfbsk=; b=eLh4lEQIYofPGHVURAEswCAobQ 7Lpo0FV+tZkk/HwMH39laLDnUNDSiPAPmJX8sDWFIXM7EfChcvDT52nhMYH9HQMl4uGWFadL9zJbn wcWpj5+ivkQFZ2HpSbn//oE6y+GzXfqaURCJo7gf6Vbd5IMM547S3/isqABgQs4wpm5lzkTUHtYt7 9t7oj8SmAQTBhTepKIx3rc8UffdN23AkZ6kBMDp3pHdlskhHHCo3O1YakvO8Cp9J0/nHEfxFnhea2 GWaFegq5c5w7cIFtjFSA9oVJYL00S4ojp5j8fL+S2p4yKvsIXPTIpWtWQJhRTPCvc5pUC/rkVKAUn 0QrSeuCQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26xt-00000003p9p-2wam; Tue, 08 Apr 2025 11:18:01 +0000 Received: from tor.source.kernel.org ([2600:3c04:e001:324:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Xf-00000003k7Z-1JcY for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:50:55 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id B4D3B6115B; Tue, 8 Apr 2025 10:50:45 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3A611C4CEE7; Tue, 8 Apr 2025 10:50:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109454; bh=Vrm1y9HqogqdHdZx/otTpwpDwGxKKMfsXeVRsPHkIPM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tzLcawWQATZ8Pi02Ek0c2w0JiKTdVzqmJ54DWu0iKI0Gl5Brf3ZBf3fX11s+6QPTd OGJwxrcYaz+q92XkrM/e8SeVbHC9J0/65GJoXDYDoZfuUWUA+kkj6lAQosjUgHNoef OsfH114c8EbIXYH5wSyqemtTcPK5i48qBTQauMsw6SO/rLDao6U1obS29zNl1uY2Tn unxasP/FOsML1WcMa0R6+QvvhntPOc5zL6jib6GS5pEolEXEMTB8tJPHYeJy906PGt qOmq89+/xT9P0JBU7s+dMPTfowqpQp47v1vMM1Br1srI7DCkbEpO5QEPl46qfWhN8i +qGogvLi8gDcA== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:00 +0200 Subject: [PATCH 01/24] Documentation: devicetree: bindings: Add GICv5 DT bindings MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-1-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The GICv5 interrupt controller architecture is composed of: - one or more Interrupt Routing Service (IRS) - zero or more Interrupt Translation Service (ITS) - zero or more Interrupt Wire Bridge (IWB) Describe a GICv5 implementation by specifying a top level node corresponding to the GICv5 system component. IRS nodes are added as GICv5 system component children. An ITS is associated with an IRS so ITS nodes are described as IRS children - use the hierarchy explicitly in the device tree to define the association. IWB nodes are described as GICv5 system component children - to make it explicit that are part of the GICv5 system component; an IWB is connected to a single ITS but the connection is made explicit through the msi-parent property and therefore is not required to be explicit through a parent-child relationship in the device tree. Signed-off-by: Lorenzo Pieralisi Cc: Conor Dooley Cc: Rob Herring Cc: Krzysztof Kozlowski Cc: Marc Zyngier --- .../bindings/interrupt-controller/arm,gic-v5.yaml | 268 +++++++++++++++++++++ MAINTAINERS | 7 + 2 files changed, 275 insertions(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v5.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v5.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5c78375c298a0115c55872f439eb04d4171c4381 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v5.yaml @@ -0,0 +1,268 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/arm,gic-v5.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ARM Generic Interrupt Controller, version 5 + +maintainers: + - Lorenzo Pieralisi + - Marc Zyngier + +description: | + The GICv5 architecture defines the guidelines to implement GICv5 + compliant interrupt controllers for AArch64 systems. + + The GICv5 specification can be found at + https://developer.arm.com/documentation/aes0070 + + The GICv5 architecture is composed of multiple components: + - one or more IRS (Interrupt Routing Service) + - zero or more ITS (Interrupt Translation Service) + - zero or more IWB (Interrupt Wire Bridge) + + The architecture defines: + - PE-Private Peripheral Interrupts (PPI) + - Shared Peripheral Interrupts (SPI) + - Logical Peripheral Interrupts (LPI) + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +properties: + compatible: + const: arm,gic-v5 + + interrupt-controller: true + + "#address-cells": + enum: [ 1, 2 ] + "#size-cells": + enum: [ 1, 2 ] + + ranges: true + + "#interrupt-cells": + description: | + Specifies the number of cells needed to encode an interrupt source. + Must be a single cell with a value 3. + + The 1st cell corresponds to the INTID.Type field in the INTID; 1 for PPI, + 3 for SPI. LPI interrupts must not be described in the bindings since + they are allocated dynamically by the software component managing them. + + The 2nd cell contains the interrupt INTID.ID field. + + The 3rd cell is the flags, encoded as follows: + bits[3:0] trigger type and level flags. + + 1 = low-to-high edge triggered + 2 = high-to-low edge triggered + 4 = active high level-sensitive + 8 = active low level-sensitive + + Cells 4 and beyond are reserved for future use and must have a value + of 0 if present. + const: 3 + + interrupts: + description: + Interrupt source of the VGIC maintenance interrupt. + maxItems: 1 + +required: + - compatible + +patternProperties: + "^irs@[0-9a-f]+$": + type: object + description: + GICv5 has one or more Interrupt Routing Services (IRS) that are + responsible for handling IRQ state and routing. + + additionalProperties: false + properties: + compatible: + const: arm,gic-v5-irs + + "#address-cells": + enum: [ 1, 2 ] + "#size-cells": + enum: [ 1, 2 ] + + ranges: true + + dma-noncoherent: + description: + Present if the GIC IRS permits programming shareability and + cacheability attributes but is connected to a non-coherent + downstream interconnect. + + reg: + minItems: 1 + items: + - description: IRS control frame + - description: IRS setlpi frame + + cpus: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Should be a list of phandles to CPU nodes (as described in + Documentation/devicetree/bindings/arm/cpus.yaml) corresponding to + CPUs managed by the IRS. + + arm,iaffids: + $ref: /schemas/types.yaml#/definitions/uint16-array + description: + Should be a list of u16 values representing IAFFID IDs associated + with the CPU whose CPU node phandle is at the same index in the + cpus array. + + patternProperties: + "^msi-controller@[0-9a-f]+$": + type: object + description: + GICv5 has zero or more Interrupt Translation Services (ITS) that are + used to route Message Signalled Interrupts (MSI) to the CPUs. Each + ITS is connected to an IRS. + additionalProperties: false + properties: + compatible: + const: arm,gic-v5-its + + dma-noncoherent: + description: + Present if the GIC ITS permits programming shareability and + cacheability attributes but is connected to a non-coherent + downstream interconnect. + + msi-controller: true + + "#msi-cells": + description: + The single msi-cell is the DeviceID of the device which will + generate the MSI. + const: 1 + + reg: + items: + - description: ITS control frame + - description: ITS translate frame + + required: + - compatible + - msi-controller + - "#msi-cells" + - reg + + required: + - compatible + - reg + - cpus + - arm,iaffids + + "^interrupt-controller@[0-9a-f]+$": + type: object + description: + GICv5 has zero or more Interrupt Wire Bridges (IWB) that are responsible + for translating wire signals into interrupt messages to the ITS. + + additionalProperties: false + properties: + compatible: + const: arm,gic-v5-iwb + + interrupt-controller: true + + "#address-cells": + const: 0 + + "#interrupt-cells": + description: | + Specifies the number of cells needed to encode an interrupt source. + Must be a single cell with a value 2. + + The 1st cell corresponds to the IWB wire. + + The 2nd cell is the flags, encoded as follows: + bits[3:0] trigger type and level flags. + + 1 = low-to-high edge triggered + 2 = high-to-low edge triggered + 4 = active high level-sensitive + 8 = active low level-sensitive + + Cells 3 and beyond are reserved for future use and must have a value + of 0 if present. + const: 2 + + reg: + items: + - description: IWB control frame + + msi-parent: true + + required: + - compatible + - reg + - msi-parent + +additionalProperties: false + +examples: + - | + interrupt-controller { + compatible = "arm,gic-v5"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + interrupt-controller; + + interrupts = <1 25 4>; + + irs@2f1a0000 { + compatible = "arm,gic-v5-irs"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + reg = <0x0 0x2f1a0000 0x0 0x10000>; // IRS_CONFIG_FRAME for NS + + arm,iaffids = /bits 16 <0 1 2 3 4 5 6 7>; + cpus = <&{/cpus/cpu@0}>, <&{/cpus/cpu@100}>, <&{/cpus/cpu@200}>, + <&{/cpus/cpu@300}>, <&{/cpus/cpu@10000}>, <&{/cpus/cpu@10100}>, + <&{/cpus/cpu@10200}>, <&{/cpus/cpu@10300}>; + + msi-controller@2f120000 { + compatible = "arm,gic-v5-its"; + + msi-controller; + #msi-cells = <1>; + + reg = <0x0 0x2f120000 0x0 0x10000 // ITS_CONFIG_FRAME for NS + 0x0 0x2f130000 0x0 0x10000>; // ITS_TRANSLATE_FRAME + }; + }; + + interrupt-controller@2f000000 { + compatible = "arm,gic-v5-iwb"; + #address-cells = <0>; + + interrupt-controller; + #interrupt-cells = <2>; + + reg = <0x0 0x2f000000 0x0 0x10000>; + + msi-parent = <&its0 64>; + }; + }; + + device@0 { + reg = <0 4>; + interrupts = <3 115 4>; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 96b82704950184bd71623ff41fc4df31e4c7fe87..f3ed84466da19906953b5396a5f4b50e878c376e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1901,6 +1901,13 @@ F: drivers/irqchip/irq-gic*.[ch] F: include/linux/irqchip/arm-gic*.h F: include/linux/irqchip/arm-vgic-info.h +ARM GENERIC INTERRUPT CONTROLLER V5 DRIVERS +M: Lorenzo Pieralisi +M: Marc Zyngier +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: Documentation/devicetree/bindings/interrupt-controller/arm,gic-v5.yaml + ARM HDLCD DRM DRIVER M: Liviu Dudau S: Supported From patchwork Tue Apr 8 10:50:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042835 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 476B8C369A1 for ; Tue, 8 Apr 2025 11:21:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=/Naj+/c+DmeWzjH0iSWv3H6bTHR9+JTgYDr3R1wUOTo=; b=aOYTs5ndQaeZtsLx1onSOT04vm FWLlMOVUkcUGyyxM/fEppIWElkuJmuTSQCjlbtQTyrwbN+FNattCd0TSM55Ka9Zn5DYDS3ZGpYrlD FgDCyFf2xhjxTHheNVlFzL8dV/t3MRBjN0RiffXqoRedPN9E9z4l1E63j1hyIjoDXQqUA27kOK6is kej2aXySsAr5/6UZ7recLvOClDX19I3tHeHakG5699TH4Xysjlc8k9aVlAMdk9YbMtNqYeLBP0+6/ C7wNoX93Crhn5p/KoE0VD28wtSMly/+jKC+l4hH1PVE9cxr4zDbRkyrvordWBrL1YBhlXumkvM022 CfbhtZdg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u271O-00000003pZE-0XLd; Tue, 08 Apr 2025 11:21:38 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Xo-00000003k9S-0avH for linux-arm-kernel@bombadil.infradead.org; Tue, 08 Apr 2025 10:51:04 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Sender:Reply-To:Content-ID:Content-Description; bh=/Naj+/c+DmeWzjH0iSWv3H6bTHR9+JTgYDr3R1wUOTo=; b=Sjt/qk41tHv6SXCN4sJulI7uOe XMQaHEQjEU88J2kanq85M9NKyIKlA2ng6+5eO3Axu0Fktqve+GO2wfiA9+r6iMl8kt967SE/BNrkx mlDtGhnHfDbor6AreN+ESTJraPuDBm5XTjVp8FFCR5v9kvAvlm0O04enX38R37RROd+GGsYKp3jhN lxHBBioYOGR4vbrS6igWoeBSKEJE46B3FKijjBN+sa0RudhQCI/YqwolyHBRkhC6prT5bo3bowiYG 9Zo31ipvWEpSAnm9ZdFw73vHsXABFr0ieJa8qCyHeHTO3DxFJ7eWjw5s/dsKIbYdNaw8Bl2fKZCSy tht6wvkQ==; Received: from nyc.source.kernel.org ([2604:1380:45d1:ec00::3]) by desiato.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Xl-00000008GJa-0tdh for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:02 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 7BBB5A43547; Tue, 8 Apr 2025 10:45:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C37D9C4AF0B; Tue, 8 Apr 2025 10:50:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109457; bh=gXuthZuxBZQLsvBkFkEhlBn3G2hxd3VqLQiwIZeC8vM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=O1VClrhvhQoqFAFwsmzaVjNoCvYwDOPdZwMnSbTggAQSi/aW+TxG/QoKs6WEX4Bev YTkwlBuffY5b28eDs22T+ie4e+0Qbsd+dWG5cxMyxaFhCzKLoPjLsMPzDpRuSm77yy /WmJFKJw0i8u6RU9qk8jJSIbg3Pi+8Dr9p27uih9u3MZCtWgkjK092frtfRIK4hRZE 6YwFUNmfqMLb0ucYt/Irs1mIejy8TCabNv6a5NalQXq5K67Os58h8MkylNWDQNuT1S FwrAgSvjOYWO7MQH8WPxq/JqeD4X3BGz69EvchSzjvUuGnhN2UJstFnaf2SsX5CcX6 AVVN5hZPFWkjg== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:01 +0200 Subject: [PATCH 02/24] arm64/sysreg: Add GCIE field to ID_AA64PFR2_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-2-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_115101_422573_7AD8D0A1 X-CRM114-Status: UNSURE ( 9.81 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add field reporting the GCIE feature to ID_AA64PFR2_EL1 sysreg. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index f9476848a2edfad53bb4af7f68bc05cb2a4af9ce..06e1fb5e126b41b7e41fffa0a00553d73197ac3c 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -1023,7 +1023,10 @@ UnsignedEnum 19:16 UINJ 0b0000 NI 0b0001 IMP EndEnum -Res0 15:12 +UnsignedEnum 15:12 GCIE + 0b0000 NI + 0b0001 IMP +EndEnum UnsignedEnum 11:8 MTEFAR 0b0000 NI 0b0001 IMP From patchwork Tue Apr 8 10:50:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042834 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id ADA2CC369A1 for ; Tue, 8 Apr 2025 11:19:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=fOEpHYzEysW5kxRY9j3WHILnDlJSRYlZLuzyoNWGI+c=; b=JC1XMB+0WSgCvZY4yZIRtavbd2 3LNpB8sNCFS1mhaKBy22xnYlqCqRtX+of8m3JI/lLki4PtX27J2gRzNR54glzribuC5alGh0suaxT cZd/LJetGXnrPMYicmrkGejlIL5cPqypBZUjGCfqwRQ+hbwqjhsn0OSvo5Uu04mkgRcXe7kvzuyoQ d9RWNTOkrCMqBDr4A1LrubrC31KHMMNiuSaiaT4axDXtmWGtQpW7DZyY7kJlmb46WsiMVHnJqZ7qp zAXlXmC1jX2riq/FKPvl0at9I0yTkWB8c1kiJUvfFBrZPypqANotQkTbgcCJt6lNWITkk9dcO3Ehy u1cE+S4Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26ze-00000003pLM-1d5e; Tue, 08 Apr 2025 11:19:50 +0000 Received: from tor.source.kernel.org ([2600:3c04:e001:324:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Xm-00000003k95-1Bjr for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:02 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id CC3FD6115B; Tue, 8 Apr 2025 10:50:52 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5DE57C4CEE5; Tue, 8 Apr 2025 10:50:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109461; bh=TEy69hatB9WvAQZk1Qj5SRXNdR02N3m6osQeJAFrqRk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=YUCkX0ulvIxZ4N51xRAyWmVK7w0m0lvL2hCAQJaaQcN+Y4TXiug/Sw+Hhn6p5wCfK jT1lYHerOEPk+LPgEqRevmpsOq7aPBvLc76gH9Z1abKqSOJLtMQieQeZtFbl0VNhQb TgVYAT8x4jHasXDH8l33BJQW5Q/z/7E69bGHqO981KMv/wslZmQCLOJFsOIEZVDomc gFP2/sgRrg+viz5wx60caX1rXZokKMH2MzsXb2gooSViFvIEStGyl9VJxoueX0lrT9 qSttCm6VKP5rWV2yhLkjGDPKnYYa4Zljt/AQfUuSBTzVg9Rl2o5mqVh7GObxW20H9S cx2x2lJqaAv+Q== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:02 +0200 Subject: [PATCH 03/24] arm64/sysreg: Add ICC_PPI_PRIORITY_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-3-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICC_PPI_PRIORITY_EL1 sysreg description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 06e1fb5e126b41b7e41fffa0a00553d73197ac3c..0cc1268c0bfad8266da47b441e80c603e46c00ae 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -2310,6 +2310,89 @@ Field 31 C Field 30:0 P EndSysreg +SysregFields ICC_PPI_PRIORITYRx_EL1 +Res0 63:61 +Field 60:56 Priority7 +Res0 55:53 +Field 52:48 Priority6 +Res0 47:45 +Field 44:40 Priority5 +Res0 39:37 +Field 36:32 Priority4 +Res0 31:29 +Field 28:24 Priority3 +Res0 23:21 +Field 20:16 Priority2 +Res0 15:13 +Field 12:8 Priority1 +Res0 7:5 +Field 4:0 Priority0 +EndSysregFields + +Sysreg ICC_PPI_PRIORITYR0_EL1 3 0 12 14 0 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR1_EL1 3 0 12 14 1 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR2_EL1 3 0 12 14 2 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR3_EL1 3 0 12 14 3 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR4_EL1 3 0 12 14 4 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR5_EL1 3 0 12 14 5 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR6_EL1 3 0 12 14 6 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR7_EL1 3 0 12 14 7 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR8_EL1 3 0 12 15 0 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR9_EL1 3 0 12 15 1 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR10_EL1 3 0 12 15 2 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR11_EL1 3 0 12 15 3 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR12_EL1 3 0 12 15 4 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR13_EL1 3 0 12 15 5 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR14_EL1 3 0 12 15 6 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + +Sysreg ICC_PPI_PRIORITYR15_EL1 3 0 12 15 7 +Fields ICC_PPI_PRIORITYRx_EL1 +EndSysreg + Sysreg PMSELR_EL0 3 3 9 12 5 Res0 63:5 Field 4:0 SEL From patchwork Tue Apr 8 10:50:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042836 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4C582C3600C for ; Tue, 8 Apr 2025 11:23:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=pUpu6+nXInPhG0brd/ajbIFScuDOf75tvKhvQ+EDI+A=; b=eJEE63sLbHMIER8XH6A9SjS3rY LpZw3lLQicHi/8YMa29rItCjR5S3g+KeBjEutyj6ZeVFgZ+7+OFHepDD3Hywy/hEQk/0mlRM0OgR/ wp1LuRK+GbK3xvDJDPHCu65I1Yursec5qICupk0r2XiST1Wcf81/TC/8mu6dimyn4dPShEV1fBbAV CK7JQxa+szIlzTcKkBf0/XSOgWyibz3sTo044mS0oAxPubbYofuHLbSnZdllKOZXROZJc/XtGzMM7 Q9keTFCMGOzt/4rPeydLON5JYvEVxor1HhScBna7mTYkppt/YNGxUycO4Rti1Hxazb63SJqmcblgB 0A3LKmog==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u2737-00000003pkz-3Tcj; Tue, 08 Apr 2025 11:23:25 +0000 Received: from tor.source.kernel.org ([2600:3c04:e001:324:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Xp-00000003kAe-3Qhq for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:05 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 5F2AA614B5; Tue, 8 Apr 2025 10:50:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E1F63C4CEE7; Tue, 8 Apr 2025 10:51:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109464; bh=Tv02OqEETUJL5RhGfHRLiUOkxm6hkdgtGZBz124yXQU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tQXMHk9fNNskMb5ZIzN4/MHk7noFhLHI/ogsrVPQqc6BboroIWnQ0P9VkObRnoHlC puBUSqgUYDOTvahy7fEZrgOhv1YzNp0oAKzxuNHVjEoQpcp7TRwW4fu6OguAy7a+U3 lskhmbazxBjqUUCC2PP49TsRzlYP6mV3fzjmsOqZiVsAGWUA8UywX9h2EvXI7Jb3Eh ABdHls/ciZCClLmms/SMw/e4lD/amzS/ifqmSxa/jXV9r6Qt9Wdi6O0nCxwweuOjI3 KcqQGtK13cGvbZl2i7kXTL8UI5jJeSkG2wwAYYVT6DttjmZvN36xGY9NnFyDfFtVQU t6eoKBUimZtcw== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:03 +0200 Subject: [PATCH 04/24] arm64/sysreg: Add ICC_ICSR_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-4-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICC_ICSR_EL1 register sysreg description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 0cc1268c0bfad8266da47b441e80c603e46c00ae..985f2cdb67cfec6df335a3951ecb63f128f6da55 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -2310,6 +2310,20 @@ Field 31 C Field 30:0 P EndSysreg +Sysreg ICC_ICSR_EL1 3 0 12 10 4 +Res0 63:48 +Field 47:32 IAFFID +Res0 31:16 +Field 15:11 Priority +Res0 10:6 +Field 5 HM +Field 4 Active +Field 3 IRM +Field 2 Pending +Field 1 Enabled +Field 0 F +EndSysreg + SysregFields ICC_PPI_PRIORITYRx_EL1 Res0 63:61 Field 60:56 Priority7 From patchwork Tue Apr 8 10:50:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042881 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EEB07C3600C for ; Tue, 8 Apr 2025 11:25:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=5VpPTyMpob64bmtSPLdeOS323Vzlu6TUyDVXKvCV4Ks=; b=rA0m6QPaZEsqXYc3dJwV97g9Eq SOOC+yLsArifeMokC+1nrtGAeyMfCZif6Uwzmtc6xRO+vGdrUmbNNCELi38dqKdaNuQseokzubMwC fKn031t9EyAoHN6sc35YONDtatMkc1Foq92UYi1fprnRYe/dCv+xDSNu6olrfbMy6eGbRxyfagriN ghaP+QnaUXqZZ1uY29dmuVRosR5dPZHIQaMiygHPS56FVTzaeHZ4pacgIRyIThmpYZJbrMGvQC0Lp I20QXd3lUNwD/yuSQTGHD17HTifz5Wfk0YjHTZkCH8k9rgA/EG0GCd1I/rcmxn++4TklJJ3Ar5pz5 5WCxm+qw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u274r-00000003py3-21Jw; Tue, 08 Apr 2025 11:25:13 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Xw-00000003kC4-2Pzp for linux-arm-kernel@bombadil.infradead.org; Tue, 08 Apr 2025 10:51:12 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Sender:Reply-To:Content-ID:Content-Description; bh=5VpPTyMpob64bmtSPLdeOS323Vzlu6TUyDVXKvCV4Ks=; b=mqeE8O4wI8/pBhq+26lU+uzwy5 kN9ACiz4d88TWUPyG0vdv0K3pIlkfKro82TtIvFoxoCqSU7HO2S6rKXUFAcIeFOzmHSOyqf+0xl1s 7f1+v3L0x+2zZ1c8IgYWf1WPB5bGbzQw5gSb3oKdyCbKqwF2GpJ51rzjGBj5fpKlLDMnxOSWT13jB ZtCfI+Pnoc2t+ffD0o7DG7kTH5kfq20b40vuV+Ou7/toxEuifR12ET4hJ2rW/oqV2JKpvyk6VMCfo 8aKBOYGL6dKwbgBpGsvsDtwh34vtTwbm3vS0x22DJ66WEuH40mRnS56g2FaM/K62dByDCDwldNcLO xChZ/ADQ==; Received: from nyc.source.kernel.org ([2604:1380:45d1:ec00::3]) by desiato.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Xt-00000008GKu-3cMr for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:11 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 24756A43FAA; Tue, 8 Apr 2025 10:45:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 73267C4CEE7; Tue, 8 Apr 2025 10:51:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109468; bh=OznnXe4nZQZT5vM8HP2AP0cBLVxiMADjBCE9cYkRzRc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=mLVfkvzJ2DMGQmfGN6IE3+UNqU0hXa2ZtoXJjYp9hs7CfIYOw/zMNtryebjBkt0pe fH9dTJxPR1aV2lP48Ldw+MsTLjqy3rILIwr9mY1tkSBxt0uybRzIUMVtIypgYceEky cwRXlMAiQhfQCspSJzcRNZwxWH1TcXgEwCOviDwF0M/wE1yawZXMD0ccXtiz8WKMEP 4oJw72rlUFBQsiUjHfWIjv47US+ciUytYeZapY6RA/HCvlLKcKjC/5LxBu9M1Eh8ek n64KTb9py/uo9AcU8shsOqoyp1HGrKkMxR1zNmbWoliVgXz7WDZl7zf0YKnu71qMpk tl+PpFtNYYwWg== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:04 +0200 Subject: [PATCH 05/24] arm64/sysreg: Add ICC_PPI_HMR_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-5-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_115110_090722_2B321A23 X-CRM114-Status: UNSURE ( 7.81 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICC_PPI_HMR_EL1 registers sysreg description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 985f2cdb67cfec6df335a3951ecb63f128f6da55..d046d719d4f69801aeef51b5b9437a0eaa04134e 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -2324,6 +2324,81 @@ Field 1 Enabled Field 0 F EndSysreg +SysregFields ICC_PPI_HMRx_EL1 +Field 63 HM63 +Field 62 HM62 +Field 61 HM61 +Field 60 HM60 +Field 59 HM59 +Field 58 HM58 +Field 57 HM57 +Field 56 HM56 +Field 55 HM55 +Field 54 HM54 +Field 53 HM53 +Field 52 HM52 +Field 51 HM51 +Field 50 HM50 +Field 49 HM49 +Field 48 HM48 +Field 47 HM47 +Field 46 HM46 +Field 45 HM45 +Field 44 HM44 +Field 43 HM43 +Field 42 HM42 +Field 41 HM41 +Field 40 HM40 +Field 39 HM39 +Field 38 HM38 +Field 37 HM37 +Field 36 HM36 +Field 35 HM35 +Field 34 HM34 +Field 33 HM33 +Field 32 HM32 +Field 31 HM31 +Field 30 HM30 +Field 29 HM29 +Field 28 HM28 +Field 27 HM27 +Field 26 HM26 +Field 25 HM25 +Field 24 HM24 +Field 23 HM23 +Field 22 HM22 +Field 21 HM21 +Field 20 HM20 +Field 19 HM19 +Field 18 HM18 +Field 17 HM17 +Field 16 HM16 +Field 15 HM15 +Field 14 HM14 +Field 13 HM13 +Field 12 HM12 +Field 11 HM11 +Field 10 HM10 +Field 9 HM9 +Field 8 HM8 +Field 7 HM7 +Field 6 HM6 +Field 5 HM5 +Field 4 HM4 +Field 3 HM3 +Field 2 HM2 +Field 1 HM1 +Field 0 HM0 +EndSysregFields + +Sysreg ICC_PPI_HMR0_EL1 3 0 12 10 0 +Fields ICC_PPI_HMRx_EL1 +EndSysreg + +Sysreg ICC_PPI_HMR1_EL1 3 0 12 10 1 +Fields ICC_PPI_HMRx_EL1 +EndSysreg + SysregFields ICC_PPI_PRIORITYRx_EL1 Res0 63:61 Field 60:56 Priority7 From patchwork Tue Apr 8 10:50:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042882 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 31657C369A1 for ; Tue, 8 Apr 2025 11:27:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=m2H8dMlHh2+wVbsUUu4lSOiJjv87gmwxE9PRNcKVErM=; b=EaI9zrtiAj7rqbb7mZ8ecsG/41 63PwSju1+Tl2rtEAtoJ9eMLRgSa0ZdX/ThxefNUnPZnQNXnw0ntWw/UfYhT7q4LXu6jhV3D2M9Oo9 ZEn6tTM/yxHK/IeqHvsoLDVwP7jJ6Er3PjYuHONXWWsoki6NNuaAygOw19z0xyHPbhqejALygxYmb xqw7ib8723o1+WUWSdUoZTURQ7iE2wBipsyM1zPPCZ2WLEeP41a9mSl2sIheDLj/VKAM2FUl7sdt3 4xpYAhqvZq5XIybi4y4N8NxQVBugD2MtX/oQJ82p1CO6yxm0485c71sfa5trEMBKiwdkruZCeqBUj uC6lsfdg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u276c-00000003qEQ-1BaW; Tue, 08 Apr 2025 11:27:02 +0000 Received: from tor.source.kernel.org ([172.105.4.254]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Xx-00000003kCA-0IvE for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:13 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 788BA6115B; Tue, 8 Apr 2025 10:51:03 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 07815C4CEE5; Tue, 8 Apr 2025 10:51:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109472; bh=eUBcCIH4szhTdWT4b2dVdh8O8kcTuP+XkEb7/cO8FcI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CP/eyDuna76WIQOXURkeSNYeN1WASmyCiQ/h0aniWChKSgMyN0r5PRcwhBT4hl35j PH934lfjaxT2bE1ylVsJ+yUforc1DTm8m/oGfwYwm/Zlq6VcJYSYjpQ0GadQxmEb7o TYsgA2mY0vVJ4T5jsQrRxgKJmKItULt3EZ7jLcC5WO7yJlAtpTcqRXcprZs+M0/pCm L+QhH7XmB8RasXs99BAQQYsYtSre3E2l1kjnCj3AnP9oplxp6DScw/w5odb0fUUEV0 Vt9WV0qlLrysObTtqfCIfNthDv2fNOJUWrrZ3QgRelAs3z5z17AYqmjmNyDHCla2OK wN6hhFOh9UE8Q== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:05 +0200 Subject: [PATCH 06/24] arm64/sysreg: Add ICC_PPI_ENABLER_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-6-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICC_PPI_ENABLER_EL1 registers sysreg description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index d046d719d4f69801aeef51b5b9437a0eaa04134e..6c5552707ad88c145adc8b7ceb3f63da401191ea 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -2399,6 +2399,81 @@ Sysreg ICC_PPI_HMR1_EL1 3 0 12 10 1 Fields ICC_PPI_HMRx_EL1 EndSysreg +SysregFields ICC_PPI_ENABLERx_EL1 +Field 63 EN63 +Field 62 EN62 +Field 61 EN61 +Field 60 EN60 +Field 59 EN59 +Field 58 EN58 +Field 57 EN57 +Field 56 EN56 +Field 55 EN55 +Field 54 EN54 +Field 53 EN53 +Field 52 EN52 +Field 51 EN51 +Field 50 EN50 +Field 49 EN49 +Field 48 EN48 +Field 47 EN47 +Field 46 EN46 +Field 45 EN45 +Field 44 EN44 +Field 43 EN43 +Field 42 EN42 +Field 41 EN41 +Field 40 EN40 +Field 39 EN39 +Field 38 EN38 +Field 37 EN37 +Field 36 EN36 +Field 35 EN35 +Field 34 EN34 +Field 33 EN33 +Field 32 EN32 +Field 31 EN31 +Field 30 EN30 +Field 29 EN29 +Field 28 EN28 +Field 27 EN27 +Field 26 EN26 +Field 25 EN25 +Field 24 EN24 +Field 23 EN23 +Field 22 EN22 +Field 21 EN21 +Field 20 EN20 +Field 19 EN19 +Field 18 EN18 +Field 17 EN17 +Field 16 EN16 +Field 15 EN15 +Field 14 EN14 +Field 13 EN13 +Field 12 EN12 +Field 11 EN11 +Field 10 EN10 +Field 9 EN9 +Field 8 EN8 +Field 7 EN7 +Field 6 EN6 +Field 5 EN5 +Field 4 EN4 +Field 3 EN3 +Field 2 EN2 +Field 1 EN1 +Field 0 EN0 +EndSysregFields + +Sysreg ICC_PPI_ENABLER0_EL1 3 0 12 10 6 +Fields ICC_PPI_ENABLERx_EL1 +EndSysreg + +Sysreg ICC_PPI_ENABLER1_EL1 3 0 12 10 7 +Fields ICC_PPI_ENABLERx_EL1 +EndSysreg + SysregFields ICC_PPI_PRIORITYRx_EL1 Res0 63:61 Field 60:56 Priority7 From patchwork Tue Apr 8 10:50:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042883 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 17FDBC3600C for ; Tue, 8 Apr 2025 11:29:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=1CL2CJUXDs5eV5qDJgIRkt8UMtUJFRuthcCNkGtLP1I=; b=vJc44/RwlD592ESUqLgagRIkMq 0BHonZQ85Lmyfh1c5erZdpvDe27nGHyvK+7wc3eeIh1WNwfgJgBbBOUQmxtyKcy1iEqEV6TC5Htkh X3o9h2rJEmL43owL2z0aHER691veil/P6r4wYxuMO2hQrICiZ0sYvIm6h4RLQexBAERRg4uDg1cLY xvjq+NXcR4U+DNG8f4AaxNuoPF44tPjCEXkGNY39e4bpC2VtM8E0pTkreCX9PfdTnGqvQl4yuYqYf vbZKLjmVY6wVj83frs9mK3G9wwPHJdARN0QLP/zyJieQVmVbj1Y+wze+OdUvksg4vTBx/rXX8OsUe K1jaXWkA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u278L-00000003qXQ-3x2q; Tue, 08 Apr 2025 11:28:49 +0000 Received: from sea.source.kernel.org ([172.234.252.31]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Y0-00000003kD5-0jUC for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:17 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 06ABF4A113; Tue, 8 Apr 2025 10:51:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8C272C4CEE7; Tue, 8 Apr 2025 10:51:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109475; bh=kr4FIsYzSG8vhPEwCV+efvFDb0h/Nmo/+nvgPyW4hHA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=V2k16FIKh3L0qk7mXkvtvYwDc4/1TV10uaJm4yIQthxTL2zOuLjIxeb7eA5e8E3YR NSnepy9Jmq4ZIcPR0tyNALaph50n4itF3VLjyHzVscSf/8Z8ZGGbcRFQM2aYg2hi6Z rcngSrv3xLfiZLJdDkbe5d9qnsGqTiJrHNkoiScJqvziZSk8lJC1usBoNW82pRILrc yKL9t5COa1XQqb1P17IAIeJUGtH0DMHY8xYIodIH6PPYeubRD9m2fL5GaL2mMs3DpF nnua16A9mkQgVkEjz7KI5eGhTbXvU3fTYTMsjL8suCwpAN3w9OviksFb+PzoySmhwq qwY4VapIWJYdw== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:06 +0200 Subject: [PATCH 07/24] arm64/sysreg: Add ICC_PPI_{C/S}ACTIVER_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-7-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035116_259003_E84AF774 X-CRM114-Status: UNSURE ( 8.12 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICC_PPI_{C/S}ACTIVER_EL1 registers description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 6c5552707ad88c145adc8b7ceb3f63da401191ea..0485721e1575c9ed158210c6f02fb9af2828f2d5 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -2474,6 +2474,89 @@ Sysreg ICC_PPI_ENABLER1_EL1 3 0 12 10 7 Fields ICC_PPI_ENABLERx_EL1 EndSysreg +SysregFields ICC_PPI_ACTIVERx_EL1 +Field 63 Active63 +Field 62 Active62 +Field 61 Active61 +Field 60 Active60 +Field 59 Active59 +Field 58 Active58 +Field 57 Active57 +Field 56 Active56 +Field 55 Active55 +Field 54 Active54 +Field 53 Active53 +Field 52 Active52 +Field 51 Active51 +Field 50 Active50 +Field 49 Active49 +Field 48 Active48 +Field 47 Active47 +Field 46 Active46 +Field 45 Active45 +Field 44 Active44 +Field 43 Active43 +Field 42 Active42 +Field 41 Active41 +Field 40 Active40 +Field 39 Active39 +Field 38 Active38 +Field 37 Active37 +Field 36 Active36 +Field 35 Active35 +Field 34 Active34 +Field 33 Active33 +Field 32 Active32 +Field 31 Active31 +Field 30 Active30 +Field 29 Active29 +Field 28 Active28 +Field 27 Active27 +Field 26 Active26 +Field 25 Active25 +Field 24 Active24 +Field 23 Active23 +Field 22 Active22 +Field 21 Active21 +Field 20 Active20 +Field 19 Active19 +Field 18 Active18 +Field 17 Active17 +Field 16 Active16 +Field 15 Active15 +Field 14 Active14 +Field 13 Active13 +Field 12 Active12 +Field 11 Active11 +Field 10 Active10 +Field 9 Active9 +Field 8 Active8 +Field 7 Active7 +Field 6 Active6 +Field 5 Active5 +Field 4 Active4 +Field 3 Active3 +Field 2 Active2 +Field 1 Active1 +Field 0 Active0 +EndSysregFields + +Sysreg ICC_PPI_CACTIVER0_EL1 3 0 12 13 0 +Fields ICC_PPI_ACTIVERx_EL1 +EndSysreg + +Sysreg ICC_PPI_CACTIVER1_EL1 3 0 12 13 1 +Fields ICC_PPI_ACTIVERx_EL1 +EndSysreg + +Sysreg ICC_PPI_SACTIVER0_EL1 3 0 12 13 2 +Fields ICC_PPI_ACTIVERx_EL1 +EndSysreg + +Sysreg ICC_PPI_SACTIVER1_EL1 3 0 12 13 3 +Fields ICC_PPI_ACTIVERx_EL1 +EndSysreg + SysregFields ICC_PPI_PRIORITYRx_EL1 Res0 63:61 Field 60:56 Priority7 From patchwork Tue Apr 8 10:50:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042893 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9803EC36010 for ; Tue, 8 Apr 2025 11:30:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=U8JJ/3CV5wjhXkg+7uT/2bDGhAR4ZPkse9+QsO0gUnA=; b=iRDt1kr4hr61hrQvvjitt5DkWB D9jkE48n6bgq8VT1VL7Sl/dlWb8M0SRYWeg48xulvD8nsSVpiE+SZiTb9LYBxTjjPFXWE/C5RoPK9 MUSDZ4gJ6OcN2nM6DnXM/IHOjJzlxwGgH2OLS+Il70WivVWcqZgf6JhRyv/a105sK5bPczDzo+XIR eiiN8NgCUjWVePwjom+d1wDOTNqAlBReoSHGk5+2XkuchEVgw4pBqdUSbbRQI112IQsRkqBwE82aT cU6UlIIGg9SNPc4UjU3lRYgJYIaZp1yav1jHh+0pEs+yDc1gB4x6H1y1K37vlS+LXcNHwQ0iXHvDU Q+7JvdtQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u27A5-00000003qop-2dZk; Tue, 08 Apr 2025 11:30:37 +0000 Received: from tor.source.kernel.org ([2600:3c04:e001:324:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Y4-00000003kE2-0Cc6 for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:20 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 9957A6115B; Tue, 8 Apr 2025 10:51:10 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1E02BC4CEE5; Tue, 8 Apr 2025 10:51:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109479; bh=sQqjxedBfR/x/zpD52PYNFW1off5a3wsTQ0MTvz8038=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=bWe3vA10IDTa6iJ5S9wV+IZKFTI9SEENovJyMJQhVbWGNQazRxS+0jkpuEgIWHuns mUa0xkyOssVH6XqLpWRbsmhBplloFTPbCKX7dKxY0EO/wiC4BRI58F+XIPGoI98qXp w57IMrGFd+rmhZr8YE4I/wzctReAVkLksFPWCvuNLDAIiXL9vI3M3B3Dk8X8EmOyHc 6dFIspIbtTnUNr1LP+eOCxKPFFN5c+iCIL5b32fxhiSIXbSUMF118zTLleKgeF2gri nvnBSwoVACXbh2dE5P7l3IP0z88RQ+jFnQnY5kmUrM1siu10zlNw02vT7qUCAgqT2K S/x+CbDIoNgVw== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:07 +0200 Subject: [PATCH 08/24] arm64/sysreg: Add ICC_PPI_{C/S}PENDR_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-8-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICC_PPI_{C/S}PENDR_EL1 registers description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 0485721e1575c9ed158210c6f02fb9af2828f2d5..7acad93718c56729ce2a333ed007243ec554dbc9 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -2557,6 +2557,89 @@ Sysreg ICC_PPI_SACTIVER1_EL1 3 0 12 13 3 Fields ICC_PPI_ACTIVERx_EL1 EndSysreg +SysregFields ICC_PPI_PENDRx_EL1 +Field 63 Pend63 +Field 62 Pend62 +Field 61 Pend61 +Field 60 Pend60 +Field 59 Pend59 +Field 58 Pend58 +Field 57 Pend57 +Field 56 Pend56 +Field 55 Pend55 +Field 54 Pend54 +Field 53 Pend53 +Field 52 Pend52 +Field 51 Pend51 +Field 50 Pend50 +Field 49 Pend49 +Field 48 Pend48 +Field 47 Pend47 +Field 46 Pend46 +Field 45 Pend45 +Field 44 Pend44 +Field 43 Pend43 +Field 42 Pend42 +Field 41 Pend41 +Field 40 Pend40 +Field 39 Pend39 +Field 38 Pend38 +Field 37 Pend37 +Field 36 Pend36 +Field 35 Pend35 +Field 34 Pend34 +Field 33 Pend33 +Field 32 Pend32 +Field 31 Pend31 +Field 30 Pend30 +Field 29 Pend29 +Field 28 Pend28 +Field 27 Pend27 +Field 26 Pend26 +Field 25 Pend25 +Field 24 Pend24 +Field 23 Pend23 +Field 22 Pend22 +Field 21 Pend21 +Field 20 Pend20 +Field 19 Pend19 +Field 18 Pend18 +Field 17 Pend17 +Field 16 Pend16 +Field 15 Pend15 +Field 14 Pend14 +Field 13 Pend13 +Field 12 Pend12 +Field 11 Pend11 +Field 10 Pend10 +Field 9 Pend9 +Field 8 Pend8 +Field 7 Pend7 +Field 6 Pend6 +Field 5 Pend5 +Field 4 Pend4 +Field 3 Pend3 +Field 2 Pend2 +Field 1 Pend1 +Field 0 Pend0 +EndSysregFields + +Sysreg ICC_PPI_CPENDR0_EL1 3 0 12 13 4 +Fields ICC_PPI_PENDRx_EL1 +EndSysreg + +Sysreg ICC_PPI_CPENDR1_EL1 3 0 12 13 5 +Fields ICC_PPI_PENDRx_EL1 +EndSysreg + +Sysreg ICC_PPI_SPENDR0_EL1 3 0 12 13 6 +Fields ICC_PPI_PENDRx_EL1 +EndSysreg + +Sysreg ICC_PPI_SPENDR1_EL1 3 0 12 13 7 +Fields ICC_PPI_PENDRx_EL1 +EndSysreg + SysregFields ICC_PPI_PRIORITYRx_EL1 Res0 63:61 Field 60:56 Priority7 From patchwork Tue Apr 8 10:50:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042894 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 90BF3C3600C for ; Tue, 8 Apr 2025 11:32:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=8JFavAtgsloXzh/GLkUVm+0T2OM9EjBVwK5Uur8DR5U=; b=C7AZNLL/L0lcNxZpZXpTgBOMLj AKqtpQRZL7rHxYkazY29Wd7R4JyvG4WKIU8w9imLatdhClP1I+w7w+ZQA6Oh1XMznDw+wyDMy4txt 3pFVzo9jIZSKI6vzp7+HJTMjoovvTi14fPJriyNOFVLBznl0UhSjjxosPfGKWqvfuklEz/1lW9oe6 EGRnBEIIXsYyjcOtIqmUr5uIRHsyH4Rc7m2iHyhQie/DzpYsiYJ3wFmi8m4QuWqd3+i2eL7VYDL39 By3nU6Td9ygQwnu5VsTzHn1rAetNPxHrLtfoEZllUi4GSxXk1F6GuGuFTEzXuvvmTeHrOSZltESjE QWroWS1Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u27Bp-00000003r5y-1Yt4; Tue, 08 Apr 2025 11:32:25 +0000 Received: from nyc.source.kernel.org ([2604:1380:45d1:ec00::3]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Y7-00000003kEb-32hN for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:24 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 5ED16A4391D; Tue, 8 Apr 2025 10:45:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id ABACAC4CEEC; Tue, 8 Apr 2025 10:51:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109482; bh=aABGEIrWEsGcFFHRxubhJftIId76X0k2qcZSdwnplek=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=RvsNNxRYx8hl2H8vVr6dYtg/DVIBjG4wppMV7ADcrrQU2V0F5PAW2DVEUBP0WZYFW fvauJoAxLLj94F6myogejoqESUqFI/qHbRUfVxwkk3SvppKejErXGmVS/LvUILm1PK 73MC0pTsyLYaAlc4ED23L7JW8McYqv8TnM0wpDPo3hOmYMOKPWbFl5nzalFc7wzxGj d2WN92oTkpFzGjzKhTgtuXZhQv2X2/Z0halB0D1amvs3bqho9nAV90YEFefEkf4FfA HlKZkydDIEfHnSPXgYb1BWecy2nFA0viHXopm6M6SmwYZ0dXxmY7rDlo81wCA6X4Xd bgaIDOelYJcwA== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:08 +0200 Subject: [PATCH 09/24] arm64/sysreg: Add ICC_CR0_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-9-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035123_830750_FDCE5505 X-CRM114-Status: UNSURE ( 8.04 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICC_CR0_EL1 register description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 7acad93718c56729ce2a333ed007243ec554dbc9..c96243505031ea680c04a693fee2c96ad19e30ea 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -2798,6 +2798,14 @@ Res0 14:12 Field 11:0 AFFINITY EndSysreg +Sysreg ICC_CR0_EL1 3 1 12 0 1 +Res0 63:39 +Field 38 PID +Field 37:32 IPPT +Res0 31:1 +Field 0 EN +EndSysreg + Sysreg CSSELR_EL1 3 2 0 0 0 Res0 63:5 Field 4 TnD From patchwork Tue Apr 8 10:50:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042896 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 264D7C3600C for ; Tue, 8 Apr 2025 11:34:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=CPgGiBFAX70unZaYouOMrE/S/CJ8oTuGZe8qicAjMCE=; b=b7aWz+jjrJ+ANbeRQzfIu/88Xb szR0tkkOfqcJAjnC5zaWYY8z74yjtC+/PzgJpqYutpYCTxt1SQX9oCfL7o4vfdYJtyfz3DfBJrNrS NVzs402vKOVCeimIRHmQtg/ldK8rJoWxq+nrvC2hdVz7s/ydWPYdDZ/QC0/UC+poWGfbwXtuI8fiz 7yRlsqDYNzXulmYIGVYxJoTQzblNMhl4dAYiR1H56bJ4BrSSmbrGlROL1hNGRqvD/mRJPKfXbHM5x 2evMF8qoSO/XdyMVSJIhCC03DEWYTE3NwtbmWfj2l1ucB/PnIh+/qbQDtCVrryWV2xeByCBH7PZsp HDPy9uAA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u27DY-00000003rPd-0NZt; Tue, 08 Apr 2025 11:34:12 +0000 Received: from tor.source.kernel.org ([2600:3c04:e001:324:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26YB-00000003kFM-0rmp for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:27 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id C0C9D614AB; Tue, 8 Apr 2025 10:51:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 403E1C4CEE5; Tue, 8 Apr 2025 10:51:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109486; bh=IR60XZsATfdTuIxQzwSdrYf53KWRtcmnuEgRG5+wtmQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=XfGxKLEYSTFLNm/CA7KfzyvK/2GTBl7eTIjUsfsLnCTE7IRLm0uc1JLHyqW0111Ib nDZ5aGuYRrlZ/tDFPObh11a2EBWSJnIgTnIN6oi+5XcqntkJDHRikD1pt8e9DCsUS7 XAyEhvjlVO9kNHHTg3eO5MTyXUfboQK3myXNF8adm1elJBtH/MvuEFEuhIwK/Elz4u YWMpGLZ9GQLP8lSWArA7QVjYkrqaY2TO6xOJK6EGwtJDztjuKhuET3IipBUR+BE2uB mMulOxb1+pnnu3k8Rwn8h4zXXibl35utBr+j8XEP6TkJnRocOWfZflvXMmWQkM15kM w5G3F4w6l96MA== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:09 +0200 Subject: [PATCH 10/24] arm64/sysreg: Add ICC_PCR_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-10-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICC_PCR_EL1 register description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index c96243505031ea680c04a693fee2c96ad19e30ea..9a2ddab8661c85586b0e91f7eaabd5a6b3409c67 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -2806,6 +2806,11 @@ Res0 31:1 Field 0 EN EndSysreg +Sysreg ICC_PCR_EL1 3 1 12 0 2 +Res0 63:5 +Field 4:0 PRIORITY +EndSysreg + Sysreg CSSELR_EL1 3 2 0 0 0 Res0 63:5 Field 4 TnD From patchwork Tue Apr 8 10:50:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042897 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0653CC3600C for ; Tue, 8 Apr 2025 11:36:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=KgFGM4UrAHc8l5P7MSQ6zM9EO/qM9t/Uhdc7+dyiwLQ=; b=XxiUE7SfH/vJ5N5sspU7ubQ8it h+c9WaPdcX1WC55DWsk8MNCpqd7WDhyVrOaonZmQ49VOGRwIsJmr4sIkdUuvzNhDY+INwHH9JwDUQ qxzw2qlhd0C9p3+kO75VceiFmqbMLwQrKQgUYnPYkM3TwPlQ9rxjYdR8waAiMjx6BXmR6FVIwKIMo QrKnfSVAfH9oCUUDoEGdEQ3Uj9jdpjou/2GGJ5UZ0Wkq2X5MpgXwCZkHKX0UTASfIGUejww70fugd R9L1fPCrxAK9m75fWDOEtZI0ceidSZIx99u92cQliUuo8T0Pz73pJ1ENnGrMi/5a7cnHJkmQkn7BM N3qDEQVw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u27FH-00000003riw-3GUd; Tue, 08 Apr 2025 11:35:59 +0000 Received: from sea.source.kernel.org ([2600:3c0a:e001:78e:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26YE-00000003kFu-1oEA for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:31 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 5A60549D41; Tue, 8 Apr 2025 10:51:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3250C4CEE7; Tue, 8 Apr 2025 10:51:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109489; bh=Dk78WkgkowYSPPndroB+3TTj6jQAcxwQp1XS8EQ5gtg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Z8JOL97PD3zlgguwVdPmHQrUGhcV92w6q/9eDzQEu1K6ldhM2x8pICfBH2Jiva+fH z8Yd1Fbeu0KlmxO29wzPQTkB1YEIqLs+2TbzYONJpKLRQXnI+E67a8b5CI7ZqLrweQ BUg5ZDMdn03ICM34rzt2jPZFU+BB1FyFrtdszLulcqWPMz/Y3Xn8VrHbYgv5NDpYc/ 9b10i4Mfw//PVkk+07tpQJLRstpt+EhHlkB49F5ilr4w3ZTNec+pkYtePkJFza86pY tiCqefJxhsYWq1DfHb8dP1dRze2qbjfHjasr3On99wOo867aCnKOuEuVKY9jFEO5Cy YQi/aA9p2uxTQ== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:10 +0200 Subject: [PATCH 11/24] arm64/sysreg: Add ICC_IDR0_EL1 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-11-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035130_492005_2FE102B2 X-CRM114-Status: UNSURE ( 8.02 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICC_IDR0_EL1 register description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 9a2ddab8661c85586b0e91f7eaabd5a6b3409c67..1ec8113df713dfea6d38e39c42eba1e3dca5eea5 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -2399,6 +2399,22 @@ Sysreg ICC_PPI_HMR1_EL1 3 0 12 10 1 Fields ICC_PPI_HMRx_EL1 EndSysreg +Sysreg ICC_IDR0_EL1 3 0 12 10 2 +Res0 63:12 +UnsignedEnum 11:8 GCIE_LEGACY + 0b0000 NI + 0b0001 IMP +EndEnum +UnsignedEnum 7:4 PRI_BITS + 0b0011 4BITS + 0b0100 5BITS +EndEnum +UnsignedEnum 3:0 ID_BITS + 0b0000 16BITS + 0b0001 24BITS +EndEnum +EndSysreg + SysregFields ICC_PPI_ENABLERx_EL1 Field 63 EN63 Field 62 EN62 From patchwork Tue Apr 8 10:50:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042898 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 02D89C36010 for ; Tue, 8 Apr 2025 11:37:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=kWjdOX2b6nCEvV6otLRk9XBMfiJdwuZ3izATbMjcg00=; b=IT+U0fITrT+pIQNoZK1OYQ7QXo eq7jxt/h9ibVp4fgpqX+V85VcOOM9FO9/ghIy7/T7zQDrGaZVUxG5O3LjFcEythILmKlu//CVWTTs R2LBGrl6hMgaq0oBoKQAf80oS9ULFvIUcDjG9PZ8jrAleDc1tVvrkxWMyew+OxQtuWTeFZHltHrFH pmV5zevmclxUxeis/XRB+xaxbpOBUqFaS0AHlF1F4hvNrvaVZ6g4X5pufZ8dcs4pcpMPUQ9gS5ugd wB4dS/uUXFJUwFRgXHuW1He7t64i9Gp6uXbWp5cIyjNDwLdOkvP8QOwFBiNtpw7t7W2A2tfjb6ctB MK9+Kz/w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u27H1-00000003s0y-29UF; Tue, 08 Apr 2025 11:37:47 +0000 Received: from nyc.source.kernel.org ([147.75.193.91]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26YI-00000003kGc-2VAj for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:35 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 22396A4914A; Tue, 8 Apr 2025 10:46:05 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 71841C4CEE5; Tue, 8 Apr 2025 10:51:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109493; bh=jtBNyXLItJhfIxTK4Pp6vzdTvnQztzIAhQqNSaBxo3Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=gcHqfVKgcYLuBTU7Og2f0WEJNqp2cezz1sPjSWcx3UmMF78B2KB9vzySIEjnh7VDr 4csyHcatdloWToED15Ve0fmNnzc/GNVle91dhOyXR5p2E8KD2gIRCq5SyfUWw+fop/ QpRBWbicqARu5AyUE18/EnD5etROcE91/mwr2pmzEwXK+L9CbzE7wLRfBT243NIAiT Mz3BxcPM6/FlooovDmqVvoHGnOnJUWutivaVHYl4nCF5sGPOzou7FxddLIBQbljKb6 e8+sF71ud1+JFjSVMBoxQDEsKuyGt0B8UG8oTs/nBj/peNURNYGPMxEIU/kC9tUiUJ CJ4YjTIsz7RkA== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:11 +0200 Subject: [PATCH 12/24] arm64/sysreg: Add ICH_HFGRTR_EL2 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-12-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035134_709566_13E7D0E9 X-CRM114-Status: UNSURE ( 7.87 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICH_HFGRTR_EL2 register description. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 1ec8113df713dfea6d38e39c42eba1e3dca5eea5..0c0e805481c84a14ae62d199466171d97d54ef90 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -3583,6 +3583,24 @@ Field 31:16 PhyPARTID29 Field 15:0 PhyPARTID28 EndSysreg +Sysreg ICH_HFGRTR_EL2 3 4 12 9 4 +Res0 63:21 +Field 20 ICC_PPI_ACTIVERn_EL1 +Field 19 ICC_PPI_PRIORITYRn_EL1 +Field 18 ICC_PPI_PENDRn_EL1 +Field 17 ICC_PPI_ENABLERn_EL1 +Field 16 ICC_PPI_HMRn_EL1 +Res0 15:8 +Field 7 ICC_IAFFIDR_EL1 +Field 6 ICC_ICSR_EL1 +Field 5 ICC_PCR_EL1 +Field 4 ICC_HPPIR_EL1 +Field 3 ICC_HAPR_EL1 +Field 2 ICC_CR0_EL1 +Field 1 ICC_IDRn_EL1 +Field 0 ICC_APR_EL1 +EndSysreg + Sysreg ICH_HCR_EL2 3 4 12 11 0 Res0 63:32 Field 31:27 EOIcount From patchwork Tue Apr 8 10:50:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042903 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8B5FAC3600C for ; Tue, 8 Apr 2025 11:39:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=qzMtod2qUfHlBjzjIZwoDbgEUXezRfAtnB0HYm2QZYE=; b=Ft/jmpWCEMpKShGB0yX05VX3CE 8cUjzOPpcTWoOaQrAHnNYpiDZq33/kfZ2aTQpqhK6e5YxBkt7eHtyQ4UU62AvyL73WWbI4ZEX9udW 4C5XlPZ1S5JwJxkOG2ZTqBguxZMjkyBnFOc+U1rlgkhVz2SJugaYV4vUv1gPi5fmfX5OMtXK7OJmT 3s6WzscdjSM5ptx3ITi8rw8ezft+X5GyvL9KtFdT0Kio0i/vDf/S7gy9B3bw9HTBgAI2G1MvXkSbE chwfBXoze7BCUJ1ZHE5X+WmwwD+GKIJbZ/elPVf8thiD+b+pbERYzUKwhuh51VNEYJI7C5YRIq8v6 DYTM1qqg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u27Il-00000003sJU-0mV8; Tue, 08 Apr 2025 11:39:35 +0000 Received: from tor.source.kernel.org ([172.105.4.254]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26YL-00000003kHX-3xwa for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:38 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 80B666115B; Tue, 8 Apr 2025 10:51:28 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 068CDC4CEE7; Tue, 8 Apr 2025 10:51:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109497; bh=3IG/dkyf3kNeiDq8iUpch8Bd+BjlFKQ3NbAf5IVjrxM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=FHKQq4twrK7xTKWdKlPXPZsuvBDkicu1IY7gUhelIlyw8F51yyGrSCxthPOZJueZz UECF4Uv/3UOFpXdj3bUFCyMDdOJyXV0dq0WdwHJoBP/sZ2sc2E2Jw7OJADD0R1U1J8 EeujiAHNfwx6qnvxU4n3QuS/8rFs6eZ07/9MrREzuXHL95/PJJxHQJbWlZNBhsyjGS AY2y4tZCKQbarq4+0/3ypqStJiqiL7FhabuHNgVrRZFsdqTxl+QARXIK7suQ3NtZRT 1skYiLsUC3nRr1fwg4uXfQ/ZqgOKRZDSwtJR3O3sWhErD9GQ3FS6mL6ptSTlv8XoTi L4u6wHsLrBxoA== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:12 +0200 Subject: [PATCH 13/24] arm64/sysreg: Add ICH_HFGWTR_EL2 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-13-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICH_HFGWTR_EL2 register description to sysreg. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 0c0e805481c84a14ae62d199466171d97d54ef90..1b519e35000be328acfe26d51e098059f9cf9ef2 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -3601,6 +3601,21 @@ Field 1 ICC_IDRn_EL1 Field 0 ICC_APR_EL1 EndSysreg +Sysreg ICH_HFGWTR_EL2 3 4 12 9 6 +Res0 63:21 +Field 20 ICC_PPI_ACTIVERn_EL1 +Field 19 ICC_PPI_PRIORITYRn_EL1 +Field 18 ICC_PPI_PENDRn_EL1 +Field 17 ICC_PPI_ENABLERn_EL1 +Res0 16:7 +Field 6 ICC_ICSR_EL1 +Field 5 ICC_PCR_EL1 +Res0 4:3 +Field 2 ICC_CR0_EL1 +Res0 1 +Field 0 ICC_APR_EL1 +EndSysreg + Sysreg ICH_HCR_EL2 3 4 12 11 0 Res0 63:32 Field 31:27 EOIcount From patchwork Tue Apr 8 10:50:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14043017 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 158EDC369A4 for ; Tue, 8 Apr 2025 13:14:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=9zxld5MK5nl7RVPnOXXCg5A1OmUF2muw/uPgyMfoYRo=; b=sQMh1nJN5IWNWVkewzCm1j5rZL eZ8U52KxrH0KMZ9JLltU3NdNprNx8v6zIzNDqF2ziIwBsrQQrMNpVIuScEX5TUpQXfoagt0xk6Nt1 cvO4HCaV3J9sEMJThcPkeoaghcbtAFkTBQDKBEYaAntlXhjEBLnMJ6AMMQ00HBJkVgnHOF5b4u4Pt EPPpvixkj919qjF3S+wy9GMoA372yzGlgkjOt5SrVBlnnqtL9OJPDABsFyRpowH/9bQ29SEYbbv8k b1VAd58xUptKwQgWsfHkMjCRG5C4DeSWSeqtn66tZumPHGnl5FOSIDFbim7XGmBCS18U8jeGVjw9f eFjCDdkw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u28lk-000000045yg-1ary; Tue, 08 Apr 2025 13:13:36 +0000 Received: from nyc.source.kernel.org ([2604:1380:45d1:ec00::3]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26YP-00000003kIh-2Urx for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:43 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 454CCA4391D; Tue, 8 Apr 2025 10:46:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 96949C4CEE5; Tue, 8 Apr 2025 10:51:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109500; bh=9zWp7WGj091+ZG2FSlP0T7J3sn+1tw+UEtNEfbmUjxQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=nqlpQpc1SEMWis8VXKD3OnJH1X5KYSi+9N9gfPHksaZ6ekQ2RN6rNygsuiZpMx5Bb SX/sGi0Os0mb8ZDQC3ickjOESKwD4P5gzt98oAbOovsDGLK11Z4WnlS/l4Z9Aa8dTU vqK7cx686WtbvVdn4cEjU36P44gVnD8ThbKS7w63kBc7qUcqUDbA/SwbKliM79DsWQ bHHMFgS2HeNh1hi1FH1fR8Oa4Q+ZyGYQQgOI9oO2aIWGaHWP/IdPMe814VFjMcnfj4 Aw+P09xsa3MKaZw9yq1sQoLh8aHPjC4KTo/GPWaB2j+g/ZIBXY3ZANsmfrjbEo+Ph0 /QnSwZbk7PuwA== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:13 +0200 Subject: [PATCH 14/24] arm64/sysreg: Add ICH_HFGITR_EL2 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-14-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035141_701165_9FF382AD X-CRM114-Status: UNSURE ( 8.06 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add ICH_HFGITR_EL2 register description to sysreg. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/tools/sysreg | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 1b519e35000be328acfe26d51e098059f9cf9ef2..5af0dea6e775ea680686dbe4bc836b5f5b69fbc7 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -3616,6 +3616,21 @@ Res0 1 Field 0 ICC_APR_EL1 EndSysreg +Sysreg ICH_HFGITR_EL2 3 4 12 9 7 +Res0 63:11 +Field 10 GICRCDNMIA +Field 9 GICRCDIA +Field 8 GICCDDI +Field 7 GICCDEOI +Field 6 GICCDHM +Field 5 GICCRDRCFG +Field 4 GICCDPEND +Field 3 GICCDAFF +Field 2 GICCDPRI +Field 1 GICCDDIS +Field 0 GICCDEN +EndSysreg + Sysreg ICH_HCR_EL2 3 4 12 11 0 Res0 63:32 Field 31:27 EOIcount From patchwork Tue Apr 8 10:50:14 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14043011 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B5053C369A2 for ; Tue, 8 Apr 2025 13:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=f10M61XlxnvNY0rHLLPIa1FiknWC/lQAzy6gpUVvXHg=; b=ojDHttStRoMG+r3xkdX1vAwMaK Q4ZA7MS/b+TS7dEHMVn1w1BLQxcsW3FzGq73in794tziQ3Tt5yqpZrM0dIKZCVb4e8G1XD953q76X f7Tqd5qSlRBQhS21hAPGEvFObh097uls+iZMSvFYjHOTVrXcMCv+i+92yVwyDr3EALO81piZ1yCSK 6mj9ZQCzkqGm+AT7z6Js5NZm6rvblRoCuWIRSoE2Xo6/c22bD0EPEFgYks9Y1hhIMh7YvMvqYgrUe hFHP/qErAN3sNI+GrOOygN36cT6ad9k1E9vLh1ckei9kx6IkvNNfJLP3eZCv106JRap8tf0udTNHX X/0OwCrw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u28lk-000000045zA-49Oe; Tue, 08 Apr 2025 13:13:36 +0000 Received: from sea.source.kernel.org ([2600:3c0a:e001:78e:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26YS-00000003kJZ-2b91 for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:45 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id A259A4A10C; Tue, 8 Apr 2025 10:51:43 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2A539C4CEE7; Tue, 8 Apr 2025 10:51:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109504; bh=sVDAwu7zYs5UYmhKsIqu4Xi0KrfAlQzxvPf603/w1qs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=NzskJDRL+zvRKPmHm6Vr3yQh8MiYkr9C4dyMFNcvNScc2hA6FgtNTx+Iazh1kF0c4 7Upk9Af0gbZMoWsQob/NhM0PfYF4vyKmim0tkl7n8oJ1THltSbnQI/+05Tk9q+M+mR Njm3htHhK9jxgyY8F+WjZ02ADseeD+T/5xC2BvNCXhthtwzswS7Ljucg5loDwQ6vzX 0haifBTxZilEj170vSA85KjlYfSM5dFR+FjLRE3fR3j9YdyR015DTEQ+nVVRduVey8 TfkU6E/O8jhpke/H88GxKn7Zik1QJzMxud4zN+DIYHRkHvE40+x02NAxUr5nvfUn3J 4X+bt+5GCO2Bg== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:14 +0200 Subject: [PATCH 15/24] arm64: Disable GICv5 read/write/instruction traps MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-15-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035144_705295_EC5AFBC4 X-CRM114-Status: UNSURE ( 8.64 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org GICv5 trap configuration registers value is UNKNOWN at reset. Initialize GICv5 EL2 trap configuration registers to prevent trapping GICv5 instruction/register access upon entering the kernel. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/include/asm/el2_setup.h | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h index ebceaae3c749b84395c9c5eccf0caf874697ad11..1e362bb3b042d51fff15a7c2abc73842930b275a 100644 --- a/arch/arm64/include/asm/el2_setup.h +++ b/arch/arm64/include/asm/el2_setup.h @@ -165,6 +165,50 @@ .Lskip_gicv3_\@: .endm +/* GICv5 system register access */ +.macro __init_el2_gicv5 + mrs_s x0, SYS_ID_AA64PFR2_EL1 + ubfx x0, x0, #ID_AA64PFR2_EL1_GCIE_SHIFT, #4 + cbz x0, .Lskip_gicv5_\@ + + mov x0, #(1 << ICH_HFGITR_EL2_GICRCDNMIA_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICRCDIA_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICCDDI_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICCDEOI_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICCDHM_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICCRDRCFG_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICCDPEND_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICCDAFF_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICCDPRI_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICCDDIS_SHIFT | \ + 1 << ICH_HFGITR_EL2_GICCDEN_SHIFT) + msr_s SYS_ICH_HFGITR_EL2, x0 // Disable instruction traps + mov_q x0, (1 << ICH_HFGRTR_EL2_ICC_PPI_ACTIVERn_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_PPI_PRIORITYRn_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_PPI_PENDRn_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_PPI_ENABLERn_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_PPI_HMRn_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_IAFFIDR_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_ICSR_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_PCR_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_HPPIR_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_HAPR_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_CR0_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_IDRn_EL1_SHIFT | \ + 1 << ICH_HFGRTR_EL2_ICC_APR_EL1_SHIFT) + msr_s SYS_ICH_HFGRTR_EL2, x0 // Disable reg read traps + mov_q x0, (1 << ICH_HFGWTR_EL2_ICC_PPI_ACTIVERn_EL1_SHIFT | \ + 1 << ICH_HFGWTR_EL2_ICC_PPI_PRIORITYRn_EL1_SHIFT | \ + 1 << ICH_HFGWTR_EL2_ICC_PPI_PENDRn_EL1_SHIFT | \ + 1 << ICH_HFGWTR_EL2_ICC_PPI_ENABLERn_EL1_SHIFT | \ + 1 << ICH_HFGWTR_EL2_ICC_ICSR_EL1_SHIFT | \ + 1 << ICH_HFGWTR_EL2_ICC_PCR_EL1_SHIFT | \ + 1 << ICH_HFGWTR_EL2_ICC_CR0_EL1_SHIFT | \ + 1 << ICH_HFGWTR_EL2_ICC_APR_EL1_SHIFT) + msr_s SYS_ICH_HFGWTR_EL2, x0 // Disable reg write traps +.Lskip_gicv5_\@: +.endm + .macro __init_el2_hstr msr hstr_el2, xzr // Disable CP15 traps to EL2 .endm @@ -323,6 +367,7 @@ __init_el2_lor __init_el2_stage2 __init_el2_gicv3 + __init_el2_gicv5 __init_el2_hstr __init_el2_mpam __init_el2_nvhe_idregs From patchwork Tue Apr 8 10:50:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14043030 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8B659C3600C for ; Tue, 8 Apr 2025 13:14:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=XWlQGKvS5S/DIKdngVLDDvHLv5rD+FZpfPi8nDiTNK0=; b=yaA9cLrooUCKOzV3rlfSa/yVjq qIhRf4nGkGVEMYbAIXks0n1OGDYzFVbjP7jIbQbH42oUMn97sr+OfXOGJqgXfIlRE1o+xUj+otlnw oiw7fnNY8rUgmCdt+14VkL6X5Pwbg5AzirWVF2WVSk+2KAbad9/f0xN5zmGah8NzVM508zYng1I31 +0CTvGh7wJMOHpXeNAeFYUGcp4Q40gQvvvXn+1YzO4zjIz38UYTMTIvdnk5ARP3RwmRYG7cK0340k vG+5xp56TUck+ac0xMzR8Br/JQYcUP4bhBl7bNJQy4Z3p3UT915JqhsXmi4Lr428poVd4teFyHalp /EX3sUkQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u28ll-000000045zf-2KCP; Tue, 08 Apr 2025 13:13:37 +0000 Received: from nyc.source.kernel.org ([147.75.193.91]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26YW-00000003kKC-3DVS for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:49 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 6481CA4914A; Tue, 8 Apr 2025 10:46:19 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B6190C4CEEB; Tue, 8 Apr 2025 10:51:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109507; bh=1VFamCW1T2hwFfR2ldmMdvGBnFem7jd3W15avtomy2U=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lgJttQ21RqeRYvVhAbo24CKebPI5FCVfbMYp9EbD9S+MI+0FUXTp0a0oeKcj+HME8 Kzbfjmn3j+Uy6zK50WSb/JzseS9GhkPGN1Qbgbn+0ZmamCI766tI4gvDtiPc9TaMBy d6SfBaFlBCNSTNeZD0HsvJvRvbTSbbx9iyFBBU61jjqEhnNKIxFhHIj3+B0OoD7UvB LMdJcwHvdBPceX2HYypOaoI3b9GhrmJaWgtWllLFQSic8J7Pdb+LUOck1CrBlXFv05 y3mj2N0kMk7cBaev6wi//xxB4pP8Znu/CtQB3RF37EM2m+eP5S9SIYVZZI71oWNVsc F0rhD8OoMj4gQ== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:15 +0200 Subject: [PATCH 16/24] arm64: cpucaps: Add GCIE capability MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-16-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035148_886007_E97474CB X-CRM114-Status: GOOD ( 10.23 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Implement the GCIE capability as a strict boot cpu capability to detect whether architectural GICv5 support is available in HW. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/kernel/cpufeature.c | 7 +++++++ arch/arm64/tools/cpucaps | 1 + 2 files changed, 8 insertions(+) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 9c4d6d552b25cb3a31d1fb267bd73d3f82513e69..8c60591633f3d435ad9b80a10e484f26af328964 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -3041,6 +3041,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .matches = has_pmuv3, }, #endif + { + .desc = "GCIE", + .type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE, + .capability = ARM64_HAS_GCIE, + .matches = has_cpuid_feature, + ARM64_CPUID_FIELDS(ID_AA64PFR2_EL1, GCIE, IMP) + }, {}, }; diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps index 772c1b008e437ed34cedb1c0f663c4dcea8f6759..e87e4bc2501f6b86352c03bd35adf33c160a577c 100644 --- a/arch/arm64/tools/cpucaps +++ b/arch/arm64/tools/cpucaps @@ -29,6 +29,7 @@ HAS_EVT HAS_FPMR HAS_FGT HAS_FPSIMD +HAS_GCIE HAS_GCS HAS_GENERIC_AUTH HAS_GENERIC_AUTH_ARCH_QARMA3 From patchwork Tue Apr 8 10:50:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14043013 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D6CBFC369A5 for ; Tue, 8 Apr 2025 13:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=bBjWbCc3PNzivVeotmgDC+x5gUF1jJVu8dVVjZoOgLI=; b=zxFF9qwBXW8ajli8sgS2Qktw2E xzD7u6iB+PXcKmNsT9XEep3oiuwxi7uqFA5bHrVsYh0UXklRWkyxQI79Cij9/EZuNkESxjxFaDz/y m6brGcq948g70snvKyeH2T1U2Js4/zR78lFwDyLHBNjAw/e/4qQXysnEYxCoEKaJ+CF1GgmwNj1AU 32u/atV5hiUyBAfLwIrwWWkHWEcbY8S8Ky0teR2WzBcPDdGBxg3WGqtCDehUJg3K9oRd4Lc+p8uI+ d90Gu7wzJ+4Tu+wF5FilPNriEML/+y6e4hsliwRYP6MHoa+CTHFBuJxlRnvkBF0RHSDiBhkAVQDT7 yTdPGmmQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u28lm-000000045zp-0dzm; Tue, 08 Apr 2025 13:13:38 +0000 Received: from sea.source.kernel.org ([172.234.252.31]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26YZ-00000003kKy-2y7K for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:52 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id B3F2543B61; Tue, 8 Apr 2025 10:51:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 48794C4CEE5; Tue, 8 Apr 2025 10:51:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109511; bh=WxlJpUqowBsQvYZOUMs8IGUAxzbj1n5Ter/RIBHuc/M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=BibSWXtaJKEo1CvnXPoF6Tkzjzru09cSXP70AY72DWEuPIN8CcynJBn68yzf7TqSA kffXvLlNT771qRUeE/Ukegf45ppT5Iz65XwfRojT+ccXpmbyJ3NChDyXZsNWEFHBoF fjIZ17ZhbjvoCmrJGQBlxXCpoXAWNhey8clL8/BWoDUX1I5dhyt60qLTwrzqFDIo5T otbUOaw8J2INx4sqWPHsDViZOBpYSBrKDkDI6Jgr08yF/zzd6eoV3ocxjcb7IRPe2q D6c8jHrVe4ypMZ48G1lyqeKCUuxE0bna3jBPvNS81FCtP4LFooCVu2dl+6So3DXZPs 1wD3Q7KiFm5eg== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:16 +0200 Subject: [PATCH 17/24] arm64: smp: Support non-SGIs for IPIs MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-17-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035151_798673_DEBE0343 X-CRM114-Status: GOOD ( 20.82 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Marc Zyngier The arm64 arch has relied so far on GIC architectural software generated interrupt (SGIs) to handle IPIs. Those are per-cpu software generated interrupts. arm64 architecture code that allocates the IPIs virtual IRQs and IRQ descriptors was written accordingly. On GICv5 systems, IPIs are implemented using LPIs that are not per-cpu interrupts - they are just normal routable IRQs. Add arch code to set-up IPIs on systems where they are handled using normal routable IRQs. For those systems, force the IRQ affinity (and make it immutable) to the cpu a given IRQ was assigned to. Signed-off-by: Marc Zyngier [timothy.hayes@arm.com: fixed ipi/irq conversion, irq flags] Signed-off-by: Timothy Hayes [lpieralisi: changed affinity set-up, log] Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas --- arch/arm64/include/asm/smp.h | 7 ++- arch/arm64/kernel/smp.c | 139 ++++++++++++++++++++++++++++++++----------- 2 files changed, 111 insertions(+), 35 deletions(-) diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index 2510eec026f7e3d6f0ecf1197c3a81b183ddd216..d6fd6efb66a673ae33825971e4aa07e791c02ee5 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h @@ -53,7 +53,12 @@ extern void smp_init_cpus(void); /* * Register IPI interrupts with the arch SMP code */ -extern void set_smp_ipi_range(int ipi_base, int nr_ipi); +extern void set_smp_ipi_range_percpu(int ipi_base, int nr_ipi, int ncpus); + +static inline void set_smp_ipi_range(int ipi_base, int n) +{ + set_smp_ipi_range_percpu(ipi_base, n, 0); +} /* * Called from the secondary holding pen, this is the secondary CPU entry point. diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 3b3f6b56e733039cad7ff5b8995db16a68f3c762..3f3712e47c94c62836fb89cd4bfb3595fbb41557 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -83,7 +83,26 @@ enum ipi_msg_type { static int ipi_irq_base __ro_after_init; static int nr_ipi __ro_after_init = NR_IPI; -static struct irq_desc *ipi_desc[MAX_IPI] __ro_after_init; + +struct ipi_descs { + struct irq_desc *descs[MAX_IPI]; +}; + +static DEFINE_PER_CPU(struct ipi_descs, pcpu_ipi_desc); + +#define get_ipi_desc(__cpu, __ipi) (per_cpu_ptr(&pcpu_ipi_desc, __cpu)->descs[__ipi]) + +static bool percpu_ipi_descs __ro_after_init; + +static int ipi_to_irq(int ipi, int cpu) +{ + return ipi_irq_base + (cpu * nr_ipi) + ipi; +} + +static int irq_to_ipi(int irq) +{ + return (irq - ipi_irq_base) % nr_ipi; +} static bool crash_stop; @@ -844,7 +863,7 @@ int arch_show_interrupts(struct seq_file *p, int prec) seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i, prec >= 4 ? " " : ""); for_each_online_cpu(cpu) - seq_printf(p, "%10u ", irq_desc_kstat_cpu(ipi_desc[i], cpu)); + seq_printf(p, "%10u ", irq_desc_kstat_cpu(get_ipi_desc(cpu, i), cpu)); seq_printf(p, " %s\n", ipi_types[i]); } @@ -919,7 +938,13 @@ static void __noreturn ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs static void arm64_backtrace_ipi(cpumask_t *mask) { - __ipi_send_mask(ipi_desc[IPI_CPU_BACKTRACE], mask); + unsigned int cpu; + + if (!percpu_ipi_descs) + __ipi_send_mask(get_ipi_desc(0, IPI_CPU_BACKTRACE), mask); + else + for_each_cpu(cpu, mask) + __ipi_send_single(get_ipi_desc(cpu, IPI_CPU_BACKTRACE), cpu); } void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu) @@ -944,7 +969,7 @@ void kgdb_roundup_cpus(void) if (cpu == this_cpu) continue; - __ipi_send_single(ipi_desc[IPI_KGDB_ROUNDUP], cpu); + __ipi_send_single(get_ipi_desc(cpu, IPI_KGDB_ROUNDUP), cpu); } } #endif @@ -1013,14 +1038,21 @@ static void do_handle_IPI(int ipinr) static irqreturn_t ipi_handler(int irq, void *data) { - do_handle_IPI(irq - ipi_irq_base); + do_handle_IPI(irq_to_ipi(irq)); return IRQ_HANDLED; } static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) { + unsigned int cpu; + trace_ipi_raise(target, ipi_types[ipinr]); - __ipi_send_mask(ipi_desc[ipinr], target); + + if (!percpu_ipi_descs) + __ipi_send_mask(get_ipi_desc(0, ipinr), target); + else + for_each_cpu(cpu, target) + __ipi_send_single(get_ipi_desc(cpu, ipinr), cpu); } static bool ipi_should_be_nmi(enum ipi_msg_type ipi) @@ -1046,11 +1078,15 @@ static void ipi_setup(int cpu) return; for (i = 0; i < nr_ipi; i++) { - if (ipi_should_be_nmi(i)) { - prepare_percpu_nmi(ipi_irq_base + i); - enable_percpu_nmi(ipi_irq_base + i, 0); + if (!percpu_ipi_descs) { + if (ipi_should_be_nmi(i)) { + prepare_percpu_nmi(ipi_irq_base + i); + enable_percpu_nmi(ipi_irq_base + i, 0); + } else { + enable_percpu_irq(ipi_irq_base + i, 0); + } } else { - enable_percpu_irq(ipi_irq_base + i, 0); + enable_irq(irq_desc_get_irq(get_ipi_desc(cpu, i))); } } } @@ -1064,44 +1100,79 @@ static void ipi_teardown(int cpu) return; for (i = 0; i < nr_ipi; i++) { - if (ipi_should_be_nmi(i)) { - disable_percpu_nmi(ipi_irq_base + i); - teardown_percpu_nmi(ipi_irq_base + i); + if (!percpu_ipi_descs) { + if (ipi_should_be_nmi(i)) { + disable_percpu_nmi(ipi_irq_base + i); + teardown_percpu_nmi(ipi_irq_base + i); + } else { + disable_percpu_irq(ipi_irq_base + i); + } } else { - disable_percpu_irq(ipi_irq_base + i); + disable_irq(irq_desc_get_irq(get_ipi_desc(cpu, i))); } } } #endif -void __init set_smp_ipi_range(int ipi_base, int n) +static void ipi_setup_ppi(int ipi) +{ + int err, irq, cpu; + + irq = ipi_irq_base + ipi; + + if (ipi_should_be_nmi(irq)) { + err = request_percpu_nmi(irq, ipi_handler, "IPI", &irq_stat); + WARN(err, "Could not request IRQ %d as NMI, err=%d\n", irq, err); + } else { + err = request_percpu_irq(irq, ipi_handler, "IPI", &irq_stat); + WARN(err, "Could not request IRQ %d as IRQ, err=%d\n", irq, err); + } + + for_each_possible_cpu(cpu) + get_ipi_desc(cpu, ipi) = irq_to_desc(irq); + + irq_set_status_flags(irq, IRQ_HIDDEN); +} + +static void ipi_setup_lpi(int ipi, int ncpus) +{ + for (int cpu = 0; cpu < ncpus; cpu++) { + int err, irq; + + irq = ipi_to_irq(ipi, cpu); + + err = irq_force_affinity(irq, cpumask_of(cpu)); + + WARN(err, "Could not force affinity IRQ %d, err=%d\n", irq, err); + + err = request_irq(irq, ipi_handler, IRQF_NO_AUTOEN, "IPI", + &irq_stat); + + WARN(err, "Could not request IRQ %d, err=%d\n", irq, err); + + irq_set_status_flags(irq, (IRQ_HIDDEN | IRQ_NO_BALANCING_MASK)); + + get_ipi_desc(cpu, ipi) = irq_to_desc(irq); + } +} + +void __init set_smp_ipi_range_percpu(int ipi_base, int n, int ncpus) { int i; WARN_ON(n < MAX_IPI); nr_ipi = min(n, MAX_IPI); - for (i = 0; i < nr_ipi; i++) { - int err; - - if (ipi_should_be_nmi(i)) { - err = request_percpu_nmi(ipi_base + i, ipi_handler, - "IPI", &irq_stat); - WARN(err, "Could not request IPI %d as NMI, err=%d\n", - i, err); - } else { - err = request_percpu_irq(ipi_base + i, ipi_handler, - "IPI", &irq_stat); - WARN(err, "Could not request IPI %d as IRQ, err=%d\n", - i, err); - } - - ipi_desc[i] = irq_to_desc(ipi_base + i); - irq_set_status_flags(ipi_base + i, IRQ_HIDDEN); - } - + percpu_ipi_descs = !!ncpus; ipi_irq_base = ipi_base; + for (i = 0; i < nr_ipi; i++) { + if (!percpu_ipi_descs) + ipi_setup_ppi(i); + else + ipi_setup_lpi(i, ncpus); + } + /* Setup the boot CPU immediately */ ipi_setup(smp_processor_id()); } From patchwork Tue Apr 8 10:50:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14043014 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 07F03C3600C for ; Tue, 8 Apr 2025 13:13:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=+rW1nft2KeiSORoydTAn0hLCw79lVCSFTkWZQ86orPg=; b=3oMC2EgmIYRG13eqDPTSsR5dD1 Ne5H05L7TslK7fPdrcE9rIA+f0KotVFwgQ9ZEr1RO8dER6VVolI72gUSXAwHteL3uEFtU+N8EVzph 49GC6X2F1gUviFFglovzHfSp3FtgbMXyrEr+ba645o4dzLeCCioJoWINTJnXHJh/RlCGa8KI+qDu+ bKvUCyIQkJUpP6eYX7TKpc+VQja+/bieyClv2vS3GDQ6pssmsJwJa1UoqM93Qj18etu6RPJxSUM/T ZeQsTiY4xKZ/glumCxHOA7iMZNRk9RrHxHFsynkdeGABtSJ/qdaNmo57SvfQQUm2Fo0wjZ0Bs7Ec/ ktXNodkA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u28lm-00000004600-30Jc; Tue, 08 Apr 2025 13:13:38 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Yi-00000003kNB-0lu5 for linux-arm-kernel@bombadil.infradead.org; Tue, 08 Apr 2025 10:52:00 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Sender:Reply-To:Content-ID:Content-Description; bh=+rW1nft2KeiSORoydTAn0hLCw79lVCSFTkWZQ86orPg=; b=eevJL878Jhu1mFYNe1KNne9Hc0 Fv/n4YRKniUtDWo5vGbFoez6JLFvGiECWuenYOHcGRSNsoL5hp9pxzbU+o4jlb34j6rZoHYn9w3/C 1eNM6PVn8fwQU5+Gx3IrxzURXh0+A/vpizk9Fj22+Frfp2SylJsguYEKB6Rzx5PohiZvQMNQ0qbZ6 Mevr9VSRvw0ZA8EWz7yxcY2PvqldCBkUJFWVI/n0G+35Tk0unRhBajAFxoZNuK7WKVWXfCB6ocTGG Esm3CgiPMKF3hBV2y7RPlXJgqDmM1bIvE7nIf3J/TYJ6P9te3hWbSP/cyytlSxes2hoQn2YMvZq0M dPoz8iig==; Received: from sea.source.kernel.org ([2600:3c0a:e001:78e:0:1991:8:25]) by desiato.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Yf-00000008GNw-03S1 for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:51:59 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 5056349D41; Tue, 8 Apr 2025 10:51:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D12BDC4CEE7; Tue, 8 Apr 2025 10:51:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109514; bh=nJ8ExirTmfRpxgLbitQ00fQuZneCF/UWvT0+5dUuNfw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ec8YIM7uRax3tcIOQg7yxBAd1I377q0V4FSE+Iz6kfPqYhJw+vIG1lmjqNZqtvcMQ vkbKWLApMguARbdzTlawwtdhTweTw0w9dAE0lt80Fw7D+yuFZ249OkXhnR5lqS962N G6bJk9W+M9aUgpzlCZL15LPDrBMOGwSC+GtU7dPEvfQXFVVeFH2QIjsZctseebYR+3 IWp0Fzno5d3UrIm2kak4O4UznXxzJmvfXAPTTtVjZEaLIQDhd8ZTI0vqPSR+haipQ5 KLBJuefZF5IIutkO8RCFeAgFkEWz1xVuNJEw8UdxX4CDtCjWMCElHSDJeFNWsIUdxT reTkt+fyrslNw== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:17 +0200 Subject: [PATCH 18/24] irqchip/gic-v5: Add GICv5 PPI support MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-18-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_115157_566377_ADA00B02 X-CRM114-Status: GOOD ( 24.88 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The GICv5 CPU interface implements support for PE-Private Peripheral Interrupts (PPI), that are handled (enabled/prioritized/delivered) entirely within the CPU interface hardware. To enable PPI interrupts, implement the baseline GICv5 host kernel driver infrastructure required to handle interrupts on a GICv5 system. Add the exception handling code path and definitions for GICv5 instructions. Add GICv5 PPI handling code as a specific IRQ domain to: - Set-up PPI priority - Manage PPI configuration and state - Manage IRQ flow handler - IRQs allocation/free - Hook-up a PPI specific IRQchip to provide the relevant methods PPI IRQ priority is chosen as the minimum allowed priority by the system design (after probing the number of priority bits implemented by the CPU interface). Co-developed-by: Sascha Bischoff Signed-off-by: Sascha Bischoff Co-developed-by: Timothy Hayes Signed-off-by: Timothy Hayes Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Thomas Gleixner Cc: Catalin Marinas Cc: Marc Zyngier --- MAINTAINERS | 2 + arch/arm64/include/asm/arch_gicv5.h | 38 +++ drivers/irqchip/Kconfig | 5 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-gic-v5.c | 497 ++++++++++++++++++++++++++++++++++++ drivers/irqchip/irq-gic-v5.h | 19 ++ 6 files changed, 562 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f3ed84466da19906953b5396a5f4b50e878c376e..cdeceb6782355a4a18609135bf7f03249d8b0bb5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1907,6 +1907,8 @@ M: Marc Zyngier L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/interrupt-controller/arm,gic-v5.yaml +F: arch/arm64/include/asm/arch_gicv5.h +F: drivers/irqchip/irq-gic-v5*.[ch] ARM HDLCD DRM DRIVER M: Liviu Dudau diff --git a/arch/arm64/include/asm/arch_gicv5.h b/arch/arm64/include/asm/arch_gicv5.h new file mode 100644 index 0000000000000000000000000000000000000000..e86cda5e5b3295c4f9c784d92adad1c6df6dbc34 --- /dev/null +++ b/arch/arm64/include/asm/arch_gicv5.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2025 ARM Ltd. + */ +#ifndef __ASM_ARCH_GICV5_H +#define __ASM_ARCH_GICV5_H + +#include + +#ifndef __ASSEMBLY__ + +#define GICV5_OP_GIC_CDDI sys_insn(1, 0, 12, 2, 0) +#define GICV5_OP_GIC_CDEOI sys_insn(1, 0, 12, 1, 7) +#define GICV5_OP_GICR_CDIA sys_insn(1, 0, 12, 3, 0) + +#define gicr_insn(insn) read_sysreg_s(insn) +#define gic_insn(v, insn) write_sysreg_s(v, insn) + +#define GSB_ACK __emit_inst(0xd5000000 | sys_insn(1, 0, 12, 0, 1) | 31) + +#define gsb_ack() asm volatile(GSB_ACK : : : "memory") + +/* Shift and mask definitions for GIC CDDI */ +#define GICV5_GIC_CDDI_TYPE_MASK GENMASK_ULL(31, 29) +#define GICV5_GIC_CDDI_TYPE(r) FIELD_GET(GICV5_GIC_CDDI_TYPE_MASK, r) +#define GICV5_GIC_CDDI_ID_MASK GENMASK_ULL(23, 0) +#define GICV5_GIC_CDDI_ID(r) FIELD_GET(GICV5_GIC_CDDI_ID_MASK, r) + +/* Shift and mask definitions for GICR CDIA */ +#define GICV5_GIC_CDIA_VALID_MASK BIT_ULL(32) +#define GICV5_GIC_CDIA_VALID(r) FIELD_GET(GICV5_GIC_CDIA_VALID_MASK, r) +#define GICV5_GIC_CDIA_TYPE_MASK GENMASK_ULL(31, 29) +#define GICV5_GIC_CDIA_TYPE(r) FIELD_GET(GICV5_GIC_CDIA_TYPE_MASK, r) +#define GICV5_GIC_CDIA_ID_MASK GENMASK_ULL(23, 0) +#define GICV5_GIC_CDIA_ID(r) FIELD_GET(GICV5_GIC_CDIA_ID_MASK, r) + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_ARCH_GICV5_H */ diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index cec05e443083b8982b3e72f4212d808a22883914..160a4761d5d85f6dbf36f3142fd619c114733e36 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -54,6 +54,11 @@ config ARM_GIC_V3_ITS_FSL_MC depends on FSL_MC_BUS default ARM_GIC_V3_ITS +config ARM_GIC_V5 + bool + select IRQ_DOMAIN_HIERARCHY + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP + config ARM_NVIC bool select IRQ_DOMAIN_HIERARCHY diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 365bcea9a61ff89e2cb41034125b3fc8cd494d81..3f8225bba5f0f9ce5dbb629b6d4782eacf85da44 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v4.o irq-gic-v3-its-msi-parent.o obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o +obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o obj-$(CONFIG_ARM_NVIC) += irq-nvic.o obj-$(CONFIG_ARM_VIC) += irq-vic.o diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c new file mode 100644 index 0000000000000000000000000000000000000000..996e2c992ef33e5ec8d2680ad4026b725ca39b04 --- /dev/null +++ b/drivers/irqchip/irq-gic-v5.c @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024-2025 ARM Limited, All Rights Reserved. + */ + +#define pr_fmt(fmt) "GICv5: " fmt + +#include +#include +#include + +#include +#include + +#include "irq-gic-v5.h" + +static u8 pri_bits = 5; +#define GICV5_IRQ_PRIORITY_MASK 0x1f +#define GICV5_IRQ_PRIORITY_MI \ + (GICV5_IRQ_PRIORITY_MASK & GENMASK(4, 5 - pri_bits)) + +static bool gicv5_cpuif_has_gcie(void) +{ + return this_cpu_has_cap(ARM64_HAS_GCIE); +} + +struct gicv5_chip_data { + struct fwnode_handle *fwnode; + struct irq_domain *ppi_domain; +}; + +static struct gicv5_chip_data gicv5_global_data __read_mostly; + +static void gicv5_ppi_priority_init(void) +{ + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR0_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR1_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR2_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR3_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR4_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR5_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR6_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR7_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR8_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR9_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR10_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR11_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR12_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR13_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR14_EL1); + write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), + SYS_ICC_PPI_PRIORITYR15_EL1); + + /* + * Context syncronization required to make sure system + * register writes effects are synchronized + */ + isb(); +} + +static void gicv5_ppi_irq_mask(struct irq_data *d) +{ + u64 hwirq_id_bit = BIT_ULL(d->hwirq % 64); + + if (d->hwirq < 64) + sysreg_clear_set_s(SYS_ICC_PPI_ENABLER0_EL1, hwirq_id_bit, 0); + else + sysreg_clear_set_s(SYS_ICC_PPI_ENABLER1_EL1, hwirq_id_bit, 0); + + /* + * Ensure that the disable takes effect + */ + isb(); +} + +static void gicv5_ppi_irq_unmask(struct irq_data *d) +{ + u64 hwirq_id_bit = BIT_ULL(d->hwirq % 64); + + if (d->hwirq < 64) + sysreg_clear_set_s(SYS_ICC_PPI_ENABLER0_EL1, 0, hwirq_id_bit); + else + sysreg_clear_set_s(SYS_ICC_PPI_ENABLER1_EL1, 0, hwirq_id_bit); +} + +static void gicv5_hwirq_eoi(u32 hwirq_id, u32 hwirq_type) +{ + u64 cddi = hwirq_id | FIELD_PREP(GICV5_GIC_CDDI_TYPE_MASK, hwirq_type); + + gic_insn(cddi, GICV5_OP_GIC_CDDI); + + gic_insn(0, GICV5_OP_GIC_CDEOI); +} + +static void gicv5_ppi_irq_eoi(struct irq_data *d) +{ + gicv5_hwirq_eoi(d->hwirq, GICV5_HWIRQ_TYPE_PPI); +} + +static int gicv5_ppi_set_type(struct irq_data *d, unsigned int type) +{ + /* + * The PPI trigger mode is not configurable at runtime, + * therefore this function simply confirms that the `type` + * parameter matches what is present. + */ + u64 hmr; + + if (d->hwirq < 64) + hmr = read_sysreg_s(SYS_ICC_PPI_HMR0_EL1); + else + hmr = read_sysreg_s(SYS_ICC_PPI_HMR1_EL1); + + switch (type) { + case IRQ_TYPE_LEVEL_HIGH: + case IRQ_TYPE_LEVEL_LOW: + if (((hmr >> (d->hwirq % 64)) & 0x1) != GICV5_PPI_HM_LEVEL) + return -EINVAL; + break; + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_EDGE_FALLING: + if (((hmr >> (d->hwirq % 64)) & 0x1) != GICV5_PPI_HM_EDGE) + return -EINVAL; + break; + default: + pr_debug("Unexpected PPI trigger mode"); + return -EINVAL; + } + + return 0; +} + +static int gicv5_ppi_irq_get_irqchip_state(struct irq_data *d, + enum irqchip_irq_state which, + bool *val) +{ + u64 pendr, activer, enabler, hwirq_id_bit = BIT_ULL(d->hwirq % 64); + + switch (which) { + case IRQCHIP_STATE_PENDING: + if (d->hwirq < 64) + pendr = read_sysreg_s(SYS_ICC_PPI_SPENDR0_EL1); + else + pendr = read_sysreg_s(SYS_ICC_PPI_SPENDR1_EL1); + + *val = !!(pendr & hwirq_id_bit); + + return 0; + case IRQCHIP_STATE_ACTIVE: + if (d->hwirq < 64) + activer = read_sysreg_s(SYS_ICC_PPI_SACTIVER0_EL1); + else + activer = read_sysreg_s(SYS_ICC_PPI_SACTIVER1_EL1); + + *val = !!(activer & hwirq_id_bit); + + return 0; + case IRQCHIP_STATE_MASKED: + if (d->hwirq < 64) + enabler = read_sysreg_s(SYS_ICC_PPI_ENABLER0_EL1); + else + enabler = read_sysreg_s(SYS_ICC_PPI_ENABLER1_EL1); + + *val = !(enabler & hwirq_id_bit); + + return 0; + default: + pr_debug("Unexpected PPI irqchip state\n"); + return -EINVAL; + } + + return -EINVAL; +} + +static int gicv5_ppi_irq_set_irqchip_state(struct irq_data *d, + enum irqchip_irq_state which, + bool val) +{ + u64 hwirq_id_bit = BIT_ULL(d->hwirq % 64); + + switch (which) { + case IRQCHIP_STATE_PENDING: + if (val) { + if (d->hwirq < 64) + write_sysreg_s(hwirq_id_bit, + SYS_ICC_PPI_SPENDR0_EL1); + else + write_sysreg_s(hwirq_id_bit, + SYS_ICC_PPI_SPENDR1_EL1); + + } else { + if (d->hwirq < 64) + write_sysreg_s(hwirq_id_bit, + SYS_ICC_PPI_CPENDR0_EL1); + else + write_sysreg_s(hwirq_id_bit, + SYS_ICC_PPI_CPENDR1_EL1); + } + + return 0; + case IRQCHIP_STATE_ACTIVE: + if (val) { + if (d->hwirq < 64) + write_sysreg_s(hwirq_id_bit, + SYS_ICC_PPI_SACTIVER0_EL1); + else + write_sysreg_s(hwirq_id_bit, + SYS_ICC_PPI_SACTIVER1_EL1); + } else { + if (d->hwirq < 64) + write_sysreg_s(hwirq_id_bit, + SYS_ICC_PPI_CACTIVER0_EL1); + else + write_sysreg_s(hwirq_id_bit, + SYS_ICC_PPI_CACTIVER1_EL1); + } + + return 0; + case IRQCHIP_STATE_MASKED: + if (val) + gicv5_ppi_irq_mask(d); + else + gicv5_ppi_irq_unmask(d); + return 0; + default: + pr_debug("Unexpected PPI irqchip state\n"); + return -EINVAL; + } + + return -EINVAL; +} + +static const struct irq_chip gicv5_ppi_irq_chip = { + .name = "GICv5-PPI", + .irq_mask = gicv5_ppi_irq_mask, + .irq_unmask = gicv5_ppi_irq_unmask, + .irq_eoi = gicv5_ppi_irq_eoi, + .irq_set_type = gicv5_ppi_set_type, + .irq_get_irqchip_state = gicv5_ppi_irq_get_irqchip_state, + .irq_set_irqchip_state = gicv5_ppi_irq_set_irqchip_state, + .flags = IRQCHIP_SET_TYPE_MASKED | + IRQCHIP_SKIP_SET_WAKE | + IRQCHIP_MASK_ON_SUSPEND +}; + +static int gicv5_irq_ppi_domain_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + irq_hw_number_t *hwirq, + unsigned int *type) +{ + if (is_of_node(fwspec->fwnode)) { + if (fwspec->param_count < 3) + return -EINVAL; + + if (fwspec->param[0] != GICV5_HWIRQ_TYPE_PPI) + return -EINVAL; + + *hwirq = fwspec->param[1]; + *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; + + return 0; + } + + return -EINVAL; +} + +static int gicv5_irq_ppi_domain_alloc(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs, + void *arg) +{ + unsigned int type = IRQ_TYPE_NONE; + struct irq_fwspec *fwspec = arg; + irq_hw_number_t hwirq; + int ret; + + if (WARN_ON(nr_irqs != 1)) + return -EINVAL; + + ret = gicv5_irq_ppi_domain_translate(domain, fwspec, &hwirq, &type); + if (ret) + return ret; + + irq_set_percpu_devid(virq); + irq_domain_set_info(domain, virq, hwirq, &gicv5_ppi_irq_chip, NULL, + handle_percpu_devid_irq, NULL, NULL); + + return 0; +} + +static void gicv5_irq_ppi_domain_free(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs) +{ + struct irq_data *d; + + if (WARN_ON(nr_irqs != 1)) + return; + + d = irq_domain_get_irq_data(domain, virq); + + irq_set_handler(virq, NULL); + irq_domain_reset_irq_data(d); +} + +static int gicv5_irq_ppi_domain_select(struct irq_domain *d, + struct irq_fwspec *fwspec, + enum irq_domain_bus_token bus_token) +{ + /* Not for us */ + if (fwspec->fwnode != d->fwnode) + return 0; + + if (fwspec->param[0] != GICV5_HWIRQ_TYPE_PPI) { + // only handle PPIs + return 0; + } + + return (d == gicv5_global_data.ppi_domain); +} + +static const struct irq_domain_ops gicv5_irq_ppi_domain_ops = { + .translate = gicv5_irq_ppi_domain_translate, + .alloc = gicv5_irq_ppi_domain_alloc, + .free = gicv5_irq_ppi_domain_free, + .select = gicv5_irq_ppi_domain_select +}; + +static inline void handle_irq_per_domain(u32 hwirq) +{ + u32 hwirq_id; + struct irq_domain *domain = NULL; + u8 hwirq_type = FIELD_GET(GICV5_HWIRQ_TYPE, hwirq); + + hwirq_id = FIELD_GET(GICV5_HWIRQ_ID, hwirq); + + if (hwirq_type == GICV5_HWIRQ_TYPE_PPI) + domain = gicv5_global_data.ppi_domain; + + if (generic_handle_domain_irq(domain, hwirq_id)) { + pr_err("Could not handle, hwirq = 0x%x", hwirq_id); + gicv5_hwirq_eoi(hwirq_id, hwirq_type); + } +} + +static asmlinkage void __exception_irq_entry +gicv5_handle_irq(struct pt_regs *regs) +{ + u64 ia; + bool valid; + u32 hwirq; + + ia = gicr_insn(GICV5_OP_GICR_CDIA); + valid = GICV5_GIC_CDIA_VALID(ia); + + if (!valid) + return; + + /* + * Ensure that the CDIA instruction effects (ie IRQ activation) are + * completed before handling the interrupt. + */ + gsb_ack(); + + /* + * Ensure instruction ordering between an acknowledgment and subsequent + * instructions in the IRQ handler using an ISB. + */ + isb(); + + hwirq = FIELD_GET(GICV5_HWIRQ_INTID, ia); + + handle_irq_per_domain(hwirq); +} + +/* + * Disable IRQs for the executing CPU + */ +static void gicv5_cpu_disable_interrupts(void) +{ + u64 cr0; + + // Disable interrupts for the Interrupt Domain + cr0 = FIELD_PREP(ICC_CR0_EL1_EN, 0); + write_sysreg_s(cr0, SYS_ICC_CR0_EL1); +} + +/* + * Enable IRQs for the executing CPU + */ +static void gicv5_cpu_enable_interrupts(void) +{ + u64 cr0, pcr; + + write_sysreg_s(0, SYS_ICC_PPI_ENABLER0_EL1); + write_sysreg_s(0, SYS_ICC_PPI_ENABLER1_EL1); + + gicv5_ppi_priority_init(); + + // Explicitly set the physical interrupt priority of the CPU + pcr = FIELD_PREP(ICC_PCR_EL1_PRIORITY, GICV5_IRQ_PRIORITY_MI); + write_sysreg_s(pcr, SYS_ICC_PCR_EL1); + + // Enable interrupts for the Interrupt Domain + cr0 = FIELD_PREP(ICC_CR0_EL1_EN, 1); + write_sysreg_s(cr0, SYS_ICC_CR0_EL1); +} + +static int gicv5_starting_cpu(unsigned int cpu) +{ + if (WARN(!gicv5_cpuif_has_gcie(), + "GICv5 system components present but CPU does not have FEAT_GCIE")) + return -ENODEV; + + gicv5_cpu_enable_interrupts(); + + return 0; +} + +static void __init gicv5_free_domains(void) +{ + if (gicv5_global_data.ppi_domain) + irq_domain_remove(gicv5_global_data.ppi_domain); +} + +static int __init gicv5_init_domains(struct fwnode_handle *handle) +{ + gicv5_global_data.fwnode = handle; + gicv5_global_data.ppi_domain = irq_domain_create_linear( + handle, 128, &gicv5_irq_ppi_domain_ops, NULL); + + if (WARN_ON(!gicv5_global_data.ppi_domain)) + return -ENOMEM; + irq_domain_update_bus_token(gicv5_global_data.ppi_domain, + DOMAIN_BUS_WIRED); + + return 0; +} + +static void gicv5_set_cpuif_pribits(void) +{ + u64 icc_idr0 = read_sysreg_s(SYS_ICC_IDR0_EL1); + + switch (FIELD_GET(ICC_IDR0_EL1_PRI_BITS, icc_idr0)) { + case ICC_IDR0_EL1_PRI_BITS_4BITS: + pri_bits = 4; + break; + case ICC_IDR0_EL1_PRI_BITS_5BITS: + pri_bits = 5; + break; + default: + pr_err("Unexpected ICC_IDR0_EL1_PRI_BITS value, default to 4"); + pri_bits = 4; + break; + } +} + +static int __init gicv5_of_init(struct device_node *node, + struct device_node *parent) +{ + int ret; + + ret = gicv5_init_domains(&node->fwnode); + if (ret) + return ret; + + gicv5_set_cpuif_pribits(); + + ret = gicv5_starting_cpu(smp_processor_id()); + if (ret) { + gicv5_free_domains(); + return ret; + } + + ret = set_handle_irq(gicv5_handle_irq); + if (ret) { + gicv5_free_domains(); + gicv5_cpu_disable_interrupts(); + return ret; + } + + return 0; +} +IRQCHIP_DECLARE(gic_v5, "arm,gic-v5", gicv5_of_init); diff --git a/drivers/irqchip/irq-gic-v5.h b/drivers/irqchip/irq-gic-v5.h new file mode 100644 index 0000000000000000000000000000000000000000..d8b797cdea2f786646fd88d9c8f60d483380991c --- /dev/null +++ b/drivers/irqchip/irq-gic-v5.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2025 ARM Limited, All Rights Reserved. + */ +#ifndef __LINUX_IRQCHIP_GIC_V5_H +#define __LINUX_IRQCHIP_GIC_V5_H + +#include + +#define GICV5_HWIRQ_ID GENMASK(23, 0) +#define GICV5_HWIRQ_TYPE GENMASK(31, 29) +#define GICV5_HWIRQ_INTID GENMASK_ULL(31, 0) + +#define GICV5_HWIRQ_TYPE_PPI UL(0x1) + +#define GICV5_PPI_HM_EDGE UL(0x0) +#define GICV5_PPI_HM_LEVEL UL(0x1) + +#endif From patchwork Tue Apr 8 10:50:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14043028 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 80D32C369A6 for ; Tue, 8 Apr 2025 13:14:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=pnl4XcgU48Ex8habiStORk1zKGF0bJ0DtM73L9wH5GE=; b=PhfOeGw016QVH6xBtf3IEEN3K1 fUDmY+LbNDAd6D3gcoplaZR1CumM0Uc8Fqe9FqySsyUpJ8SiCNsODiD6EvkWRi79ZejWLVp2KniWK 5lYt/xkLvifWp8pvLtHUOI1QfJmYsHBC+mP+MjvJg1VEWZSLiVxKCaI4/PBf0P8aAHrHqViqLOIA1 f+I5dJrfT5rapHc2sqUcGpaLJMRc82m4aGyz+tZdoahM4hXNTH8J68zf4yDJOJsnF/bWrqM/xSIZ9 iXt2009UED6TbskLa1Hdv+8+7ka+zdX59/PnXpRKfNoxnQqCIqizA0zdy0r0zwpLxV9Cj+2FY1Zdf 4FS2adzA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u28ln-00000004619-19V1; Tue, 08 Apr 2025 13:13:39 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Yl-00000003kNO-08O5 for linux-arm-kernel@bombadil.infradead.org; Tue, 08 Apr 2025 10:52:03 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Sender:Reply-To:Content-ID:Content-Description; bh=pnl4XcgU48Ex8habiStORk1zKGF0bJ0DtM73L9wH5GE=; b=ecTjUPWK7On7Ua3PUeANaKSYPO XEyzfl6EA7LGGQCCMUNC77LZdgqggmfmqupjR/75ExWGrTjw5/V654fNWibJRvpzhBQ8Qcx68pFUn ZR/ri5+TeubWniMtVNMp3xIAWrvhhoGgwWuHGGthkKPw6LxuQ7Icd2kG7T3nYPusYIOIv/p+B0vpj +vwE2wo2Zud3usqt4+Nf55648lKqoxWf6rG0buGM4A7ckvRK/z6wgdRmGeKU3G38az/fvMEXdql8c x3Xf5IeA1OMuk6Ej1REr0ovH1erLyvS6ebmXvBu1kXY0ZGNB6e0fF+CRU7R0QoKskqR/coOg6rcbb vqm3VC2A==; Received: from sea.source.kernel.org ([2600:3c0a:e001:78e:0:1991:8:25]) by desiato.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Yh-00000008GOg-3YR1 for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:52:01 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id D52144A115; Tue, 8 Apr 2025 10:51:57 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67B53C4CEE5; Tue, 8 Apr 2025 10:51:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109518; bh=pik6u9BwGeLrLXHngnJh2R85kRRqDVN3sWtOgzyrus8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JmgbLMxmN+IbqtTD6Q3dyg6Sj7WZaip7nKXdHEryeloaYJCF4GJj8B1wH93e4gEye 1jt8lTzr1gebV8Ib7IZ+1JgOPNcOzzwbw9rvonhL/O0It27AcZpz+deBHKTrHa2OOQ oI3oQv3YUtq5nqhOH0LS110FXQF/MixTWszlmWkhjI4JOYPBoM9Ijt7pRF3HiRvD/H 1OAg+1tjKecOSspfQdzYaolHvk+LwZ/esDYyNVY2STdafh6m0BQRI2rARjfBYcKqCD FwgAml7rx4siabkmT9L9wn7OYtDtXlJWlGMx+FOF5z5vaghCa6JAlq5Gs/OBGsBEp7 Le//f4WFBmQpg== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:18 +0200 Subject: [PATCH 19/24] irqchip/gic-v5: Add GICv5 IRS/SPI support MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-19-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_115200_346845_ABD3E4CD X-CRM114-Status: GOOD ( 25.71 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The GICv5 Interrupt Routing Service (IRS) component implements interrupt management and routing in the GICv5 architecture. A GICv5 system comprises one or more IRSes, that together handle the interrupt routing and state for the system. An IRS supports Shared Peripheral Interrupts (SPIs), that are interrupt sources directly connected to the IRS; they do not rely on memory for storage. The number of supported SPIs is fixed for a given implementation and can be probed through IRS IDR registers. SPI interrupt state and routing are managed through GICv5 instructions. Each core (PE in GICv5 terms) in a GICv5 system is identified with an Interrupt AFFinity ID (IAFFID). An IRS manages a set of cores that are connected to it. Firmware provides a topology description that the driver uses to detect to which IRS a CPU (ie an IAFFID) is associated with. Use probeable information and firmware description to initialize the IRSes and implement GICv5 IRS SPIs support through an SPI-specific IRQ domain. The GICv5 IRS driver: - Probes IRSes in the system to detect SPI ranges - Associates an IRS with a set of cores connected to it - Adds an IRQchip structure for SPI handling SPIs priority is set to a value corresponding to the lowest permissible priority in the system (taking into account the implemented priority bits of the IRS and CPU interface). Since all IRQs are set to the same priority value, the value itself does not matter as long as it is a valid one. Co-developed-by: Sascha Bischoff Signed-off-by: Sascha Bischoff Co-developed-by: Timothy Hayes Signed-off-by: Timothy Hayes Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Thomas Gleixner Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/include/asm/arch_gicv5.h | 52 +++++ drivers/irqchip/Makefile | 2 +- drivers/irqchip/irq-gic-v5-irs.c | 452 ++++++++++++++++++++++++++++++++++++ drivers/irqchip/irq-gic-v5.c | 326 ++++++++++++++++++++++++-- drivers/irqchip/irq-gic-v5.h | 101 ++++++++ 5 files changed, 917 insertions(+), 16 deletions(-) diff --git a/arch/arm64/include/asm/arch_gicv5.h b/arch/arm64/include/asm/arch_gicv5.h index e86cda5e5b3295c4f9c784d92adad1c6df6dbc34..00c6b7903094ca5d6e496890d029d21d82b7af66 100644 --- a/arch/arm64/include/asm/arch_gicv5.h +++ b/arch/arm64/include/asm/arch_gicv5.h @@ -9,16 +9,34 @@ #ifndef __ASSEMBLY__ +#define GICV5_OP_GIC_CDAFF sys_insn(1, 0, 12, 1, 3) #define GICV5_OP_GIC_CDDI sys_insn(1, 0, 12, 2, 0) +#define GICV5_OP_GIC_CDDIS sys_insn(1, 0, 12, 1, 0) +#define GICV5_OP_GIC_CDEN sys_insn(1, 0, 12, 1, 1) #define GICV5_OP_GIC_CDEOI sys_insn(1, 0, 12, 1, 7) +#define GICV5_OP_GIC_CDPEND sys_insn(1, 0, 12, 1, 4) +#define GICV5_OP_GIC_CDPRI sys_insn(1, 0, 12, 1, 2) +#define GICV5_OP_GIC_CDRCFG sys_insn(1, 0, 12, 1, 5) #define GICV5_OP_GICR_CDIA sys_insn(1, 0, 12, 3, 0) #define gicr_insn(insn) read_sysreg_s(insn) #define gic_insn(v, insn) write_sysreg_s(v, insn) #define GSB_ACK __emit_inst(0xd5000000 | sys_insn(1, 0, 12, 0, 1) | 31) +#define GSB_SYS __emit_inst(0xd5000000 | sys_insn(1, 0, 12, 0, 0) | 31) #define gsb_ack() asm volatile(GSB_ACK : : : "memory") +#define gsb_sys() asm volatile(GSB_SYS : : : "memory") + +/* Shift and mask definitions for GIC CDAFF */ +#define GICV5_GIC_CDAFF_IAFFID_MASK GENMASK_ULL(47, 32) +#define GICV5_GIC_CDAFF_IAFFID(r) FIELD_GET(GICV5_GIC_CDAFF_IAFFID_MASK, r) +#define GICV5_GIC_CDAFF_TYPE_MASK GENMASK_ULL(31, 29) +#define GICV5_GIC_CDAFF_TYPE(r) FIELD_GET(GICV5_GIC_CDAFF_TYPE_MASK, r) +#define GICV5_GIC_CDAFF_IRM_MASK BIT_ULL(28) +#define GICV5_GIC_CDAFF_IRM(r) FIELD_GET(GICV5_GIC_CDAFF_IRM_MASK, r) +#define GICV5_GIC_CDAFF_ID_MASK GENMASK_ULL(23, 0) +#define GICV5_GIC_CDAFF_ID(r) FIELD_GET(GICV5_GIC_CDAFF_ID_MASK, r) /* Shift and mask definitions for GIC CDDI */ #define GICV5_GIC_CDDI_TYPE_MASK GENMASK_ULL(31, 29) @@ -26,6 +44,40 @@ #define GICV5_GIC_CDDI_ID_MASK GENMASK_ULL(23, 0) #define GICV5_GIC_CDDI_ID(r) FIELD_GET(GICV5_GIC_CDDI_ID_MASK, r) +/* Shift and mask definitions for GIC CDDIS */ +#define GICV5_GIC_CDDIS_TYPE_MASK GENMASK_ULL(31, 29) +#define GICV5_GIC_CDDIS_TYPE(r) FIELD_GET(GICV5_GIC_CDDIS_TYPE_MASK, r) +#define GICV5_GIC_CDDIS_ID_MASK GENMASK_ULL(23, 0) +#define GICV5_GIC_CDDIS_ID(r) FIELD_GET(GICV5_GIC_CDDIS_ID_MASK, r) + +/* Shift and mask definitions for GIC CDEN */ +#define GICV5_GIC_CDEN_TYPE_MASK GENMASK_ULL(31, 29) +#define GICV5_GIC_CDEN_TYPE(r) FIELD_GET(GICV5_GIC_CDEN_TYPE_MASK, r) +#define GICV5_GIC_CDEN_ID_MASK GENMASK_ULL(23, 0) +#define GICV5_GIC_CDEN_ID(r) FIELD_GET(GICV5_GIC_CDEN_ID_MASK, r) + +/* Shift and mask definitions for GIC CDPEND */ +#define GICV5_GIC_CDPEND_PENDING_MASK BIT_ULL(32) +#define GICV5_GIC_CDPEND_PENDING(r) FIELD_GET(GICV5_GIC_CDPEND_PENDING_MASK, r) +#define GICV5_GIC_CDPEND_TYPE_MASK GENMASK_ULL(31, 29) +#define GICV5_GIC_CDPEND_TYPE(r) FIELD_GET(GICV5_GIC_CDPEND_TYPE_MASK, r) +#define GICV5_GIC_CDPEND_ID_MASK GENMASK_ULL(23, 0) +#define GICV5_GIC_CDPEND_ID(r) FIELD_GET(GICV5_GIC_CDPEND_ID_MASK, r) + +/* Shift and mask definitions for GIC CDPRI */ +#define GICV5_GIC_CDPRI_PRIORITY_MASK GENMASK_ULL(39, 35) +#define GICV5_GIC_CDPRI_PRIORITY(r) FIELD_GET(GICV5_GIC_CDPRI_PRIORITY_MASK, r) +#define GICV5_GIC_CDPRI_TYPE_MASK GENMASK_ULL(31, 29) +#define GICV5_GIC_CDPRI_TYPE(r) FIELD_GET(GICV5_GIC_CDPRI_TYPE_MASK, r) +#define GICV5_GIC_CDPRI_ID_MASK GENMASK_ULL(23, 0) +#define GICV5_GIC_CDPRI_ID(r) FIELD_GET(GICV5_GIC_CDPRI_ID_MASK, r) + +/* Shift and mask definitions for GIC CDRCFG */ +#define GICV5_GIC_CDRCFG_TYPE_MASK GENMASK_ULL(31, 29) +#define GICV5_GIC_CDRCFG_TYPE(r) FIELD_GET(GICV5_GIC_CDRCFG_TYPE_MASK, r) +#define GICV5_GIC_CDRCFG_ID_MASK GENMASK_ULL(23, 0) +#define GICV5_GIC_CDRCFG_ID(r) FIELD_GET(GICV5_GIC_CDRCFG_ID_MASK, r) + /* Shift and mask definitions for GICR CDIA */ #define GICV5_GIC_CDIA_VALID_MASK BIT_ULL(32) #define GICV5_GIC_CDIA_VALID(r) FIELD_GET(GICV5_GIC_CDIA_VALID_MASK, r) diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 3f8225bba5f0f9ce5dbb629b6d4782eacf85da44..3d9c47fa3fdf40b7452c059d84fe8ac24c91bc0f 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -35,7 +35,7 @@ obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v4.o irq-gic-v3-its-msi-parent.o obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o -obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o +obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o irq-gic-v5-irs.o obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o obj-$(CONFIG_ARM_NVIC) += irq-nvic.o obj-$(CONFIG_ARM_VIC) += irq-vic.o diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c new file mode 100644 index 0000000000000000000000000000000000000000..5999f2a2c8dac0ea01ab0aa5df65bf12e1f59f63 --- /dev/null +++ b/drivers/irqchip/irq-gic-v5-irs.c @@ -0,0 +1,452 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024-2025 ARM Limited, All Rights Reserved. + */ + +#define pr_fmt(fmt) "GICv5 IRS: " fmt + +#include +#include +#include +#include + +#include "irq-gic-v5.h" + +#define IRS_FLAGS_NON_COHERENT BIT(0) + +static DEFINE_PER_CPU(struct gicv5_irs_chip_data *, per_cpu_irs_data); +static LIST_HEAD(irs_nodes); + +static u32 irs_readl(struct gicv5_irs_chip_data *irs_data, const u64 reg_offset) +{ + return readl_relaxed(irs_data->irs_base + reg_offset); +} + +static void irs_writel(struct gicv5_irs_chip_data *irs_data, const u32 val, + const u64 reg_offset) +{ + writel_relaxed(val, irs_data->irs_base + reg_offset); +} + +struct iaffid_entry { + u16 iaffid; + bool valid; +}; + +static DEFINE_PER_CPU(struct iaffid_entry, cpu_iaffid); + +int gicv5_irs_cpu_to_iaffid(int cpuid, u16 *iaffid) +{ + if (!per_cpu(cpu_iaffid, cpuid).valid) { + pr_err("IAFFID for CPU %d has not been initialised\n", cpuid); + return -ENODEV; + } + + *iaffid = per_cpu(cpu_iaffid, cpuid).iaffid; + + return 0; +} + +struct gicv5_irs_chip_data *gicv5_irs_lookup_by_spi_id(u32 spi_id) +{ + struct gicv5_irs_chip_data *irs_data; + u32 min, max; + + list_for_each_entry(irs_data, &irs_nodes, entry) { + if (!irs_data->spi_range) + continue; + + min = irs_data->spi_min; + max = irs_data->spi_min + irs_data->spi_range - 1; + if (spi_id >= min && spi_id <= max) + return irs_data; + } + + return NULL; +} + +static int gicv5_irs_wait_for_spi_op(struct gicv5_irs_chip_data *irs_data) +{ + int ret; + u32 statusr; + + ret = readl_relaxed_poll_timeout_atomic( + irs_data->irs_base + GICV5_IRS_SPI_STATUSR, statusr, + FIELD_GET(GICV5_IRS_SPI_STATUSR_IDLE, statusr), 1, + USEC_PER_SEC); + + if (ret == -ETIMEDOUT) { + pr_err_ratelimited("Time out waiting for IRS SPI to be configured\n"); + return ret; + } + + return !!FIELD_GET(GICV5_IRS_SPI_STATUSR_V, statusr) ? 0 : -ENXIO; +} + +static int gicv5_irs_wait_for_irs_pe(struct gicv5_irs_chip_data *irs_data, + bool selr) +{ + u32 statusr; + int ret; + bool valid; + + ret = readl_relaxed_poll_timeout_atomic( + irs_data->irs_base + GICV5_IRS_PE_STATUSR, statusr, + FIELD_GET(GICV5_IRS_PE_STATUSR_IDLE, statusr), 1, + USEC_PER_SEC); + + if (ret == -ETIMEDOUT) { + pr_err_ratelimited("Time out waiting for PE_STATUSR after %s\n", + selr ? "IRS_PE_SELR" : "IRS_PE_CR0"); + return ret; + } + + if (selr) { + valid = !!FIELD_GET(GICV5_IRS_PE_STATUSR_V, statusr); + return valid ? 0 : -ENXIO; + } + + return 0; +} + +static int gicv5_irs_wait_for_pe_selr(struct gicv5_irs_chip_data *irs_data) +{ + return gicv5_irs_wait_for_irs_pe(irs_data, true); +} + +static int gicv5_irs_wait_for_pe_cr0(struct gicv5_irs_chip_data *irs_data) +{ + return gicv5_irs_wait_for_irs_pe(irs_data, false); +} + +int gicv5_spi_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct gicv5_irs_chip_data *irs_data = d->chip_data; + u32 selr, cfgr; + bool level; + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_EDGE_FALLING: + level = false; + break; + case IRQ_TYPE_LEVEL_HIGH: + case IRQ_TYPE_LEVEL_LOW: + level = true; + break; + default: + return -EINVAL; + } + + guard(raw_spinlock)(&irs_data->spi_config_lock); + + selr = FIELD_PREP(GICV5_IRS_SPI_SELR_ID, d->hwirq); + irs_writel(irs_data, selr, GICV5_IRS_SPI_SELR); + if (gicv5_irs_wait_for_spi_op(irs_data)) + return -EIO; + + cfgr = FIELD_PREP(GICV5_IRS_SPI_CFGR_TM, level); + + irs_writel(irs_data, cfgr, GICV5_IRS_SPI_CFGR); + if (gicv5_irs_wait_for_spi_op(irs_data)) + return -EPERM; + + return 0; +} + +static int gicv5_irs_wait_for_idle(struct gicv5_irs_chip_data *irs_data) +{ + u32 cr0; + int ret; + + ret = readl_relaxed_poll_timeout_atomic( + irs_data->irs_base + GICV5_IRS_CR0, cr0, + FIELD_GET(GICV5_IRS_CR0_IDLE, cr0), 1, + USEC_PER_SEC); + + if (ret == -ETIMEDOUT) + pr_err_ratelimited("CR0 timeout...\n"); + + return ret; +} + +int gicv5_irs_register_cpu(int cpuid) +{ + struct gicv5_irs_chip_data *irs_data; + u32 selr, cr0; + u16 iaffid; + int ret; + + ret = gicv5_irs_cpu_to_iaffid(cpuid, &iaffid); + if (ret) { + pr_err("IAFFID for CPU %d has not been initialised\n", cpuid); + return ret; + } + + irs_data = per_cpu(per_cpu_irs_data, cpuid); + if (!irs_data) { + pr_err("No IRS associated with CPU %u\n", cpuid); + return -ENXIO; + } + + selr = FIELD_PREP(GICV5_IRS_PE_SELR_IAFFID, iaffid); + irs_writel(irs_data, selr, GICV5_IRS_PE_SELR); + + ret = gicv5_irs_wait_for_pe_selr(irs_data); + if (ret) { + pr_err("IAFFID 0x%x used in IRS_PE_SELR is invalid\n", iaffid); + return -ENXIO; + } + + cr0 = FIELD_PREP(GICV5_IRS_PE_CR0_DPS, 0x1); + irs_writel(irs_data, cr0, GICV5_IRS_PE_CR0); + + ret = gicv5_irs_wait_for_pe_cr0(irs_data); + if (ret) + return ret; + + pr_debug("CPU%d enabled PE IAFFID 0x%x\n", cpuid, iaffid); + + return 0; +} + +static int __init gicv5_irs_init_bases(struct gicv5_irs_chip_data *irs_data, + void __iomem *irs_base, + struct fwnode_handle *handle) +{ + u32 cr0, cr1; + struct device_node *np = to_of_node(handle); + + irs_data->fwnode = handle; + irs_data->irs_base = irs_base; + + if (of_property_read_bool(np, "dma-noncoherent")) { + /* + * A non-coherent IRS implies that some cache levels cannot be + * used coherently by the cores and GIC. Our only option is to mark + * memory attributes for the GIC as non-cacheable; by default, + * non-cacheable memory attributes imply outer-shareable + * shareability, the value written into IRS_CR1_SH is ignored. + */ + cr1 = FIELD_PREP(GICV5_IRS_CR1_VPED_WA, GICV5_NO_WRITE_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VPED_RA, GICV5_NO_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VMD_WA, GICV5_NO_WRITE_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VMD_RA, GICV5_NO_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VPET_RA, GICV5_NO_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VMT_RA, GICV5_NO_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_IST_WA, GICV5_NO_WRITE_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_IST_RA, GICV5_NO_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_IC, GICV5_NON_CACHE) | + FIELD_PREP(GICV5_IRS_CR1_OC, GICV5_NON_CACHE); + irs_data->flags |= IRS_FLAGS_NON_COHERENT; + } else { + cr1 = FIELD_PREP(GICV5_IRS_CR1_VPED_WA, GICV5_WRITE_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VPED_RA, GICV5_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VMD_WA, GICV5_WRITE_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VMD_RA, GICV5_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VPET_RA, GICV5_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_VMT_RA, GICV5_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_IST_WA, GICV5_WRITE_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_IST_RA, GICV5_READ_ALLOC) | + FIELD_PREP(GICV5_IRS_CR1_IC, GICV5_WB_CACHE) | + FIELD_PREP(GICV5_IRS_CR1_OC, GICV5_WB_CACHE) | + FIELD_PREP(GICV5_IRS_CR1_SH, GICV5_INNER_SHARE); + } + + irs_writel(irs_data, cr1, GICV5_IRS_CR1); + + cr0 = FIELD_PREP(GICV5_IRS_CR0_IRSEN, 0x1); + irs_writel(irs_data, cr0, GICV5_IRS_CR0); + gicv5_irs_wait_for_idle(irs_data); + + return 0; +} + +static int __init gicv5_irs_of_init_affinity(struct device_node *node, + struct gicv5_irs_chip_data *irs_data, + u8 iaffid_bits) +{ + /* + * Detect IAFFID<->CPU mappings from the device tree and + * record IRS<->CPU topology information. + */ + int ret, i, ncpus, niaffids; + u16 *iaffids; + u16 iaffid_mask = GENMASK(iaffid_bits - 1, 0); + + ncpus = of_property_count_elems_of_size(node, "cpus", sizeof(u32)); + if (WARN_ON(ncpus < 0)) + return -EINVAL; + + niaffids = of_property_count_elems_of_size(node, "arm,iaffids", + sizeof(u16)); + if (WARN_ON(niaffids != ncpus)) + return -EINVAL; + + iaffids = kcalloc(niaffids, sizeof(*iaffids), GFP_KERNEL); + if (!iaffids) + return -ENOMEM; + + ret = of_property_read_u16_array(node, "arm,iaffids", iaffids, niaffids); + if (ret) + return ret; + + for (i = 0; i < ncpus; i++) { + struct device_node *cpu_node; + u32 cpu_phandle; + int cpu; + + if (of_property_read_u32_index(node, "cpus", i, &cpu_phandle)) + continue; + + cpu_node = of_find_node_by_phandle(cpu_phandle); + if (WARN_ON(!cpu_node)) + continue; + + cpu = of_cpu_node_to_id(cpu_node); + of_node_put(cpu_node); + if (WARN_ON(cpu < 0)) + continue; + + if (iaffids[i] & ~iaffid_mask) { + pr_warn("CPU %d iaffid 0x%x exceeds IRS iaffid bits\n", + cpu, iaffids[i]); + continue; + } + + per_cpu(cpu_iaffid, cpu).iaffid = iaffids[i]; + per_cpu(cpu_iaffid, cpu).valid = true; + + // We also know that the CPU is connected to this IRS + per_cpu(per_cpu_irs_data, cpu) = irs_data; + } + + kfree(iaffids); + + return ret; +} + +static void irs_setup_pri_bits(u32 idr1) +{ + switch (FIELD_GET(GICV5_IRS_IDR1_PRIORITY_BITS, idr1)) { + case GICV5_IRS_IDR1_PRIORITY_BITS_1BITS: + gicv5_global_data.irs_pri_bits = 1; + break; + case GICV5_IRS_IDR1_PRIORITY_BITS_2BITS: + gicv5_global_data.irs_pri_bits = 2; + break; + case GICV5_IRS_IDR1_PRIORITY_BITS_3BITS: + gicv5_global_data.irs_pri_bits = 3; + break; + case GICV5_IRS_IDR1_PRIORITY_BITS_4BITS: + gicv5_global_data.irs_pri_bits = 4; + break; + case GICV5_IRS_IDR1_PRIORITY_BITS_5BITS: + gicv5_global_data.irs_pri_bits = 5; + break; + default: + pr_warn("Detected wrong IDR priority bits value 0x%lx\n", + FIELD_GET(GICV5_IRS_IDR1_PRIORITY_BITS, idr1)); + break; + } +} + +static int __init gicv5_irs_init(struct device_node *node) +{ + void __iomem *irs_base; + struct gicv5_irs_chip_data *irs_data; + int ret; + u32 idr; + u8 iaffid_bits; + + irs_data = kzalloc(sizeof(*irs_data), GFP_KERNEL); + if (!irs_data) + return -ENOMEM; + + raw_spin_lock_init(&irs_data->spi_config_lock); + + irs_base = of_io_request_and_map(node, 0, "IRS"); + if (IS_ERR(irs_base)) { + pr_err("%pOF: unable to map GICv5 IRS registers\n", node); + ret = PTR_ERR(irs_base); + goto out_err; + } + + gicv5_irs_init_bases(irs_data, irs_base, &node->fwnode); + + idr = irs_readl(irs_data, GICV5_IRS_IDR1); + iaffid_bits = FIELD_GET(GICV5_IRS_IDR1_IAFFID_BITS, idr) + 1; + + ret = gicv5_irs_of_init_affinity(node, irs_data, iaffid_bits); + if (ret) { + pr_err("Failed to parse CPU IAFFIDs from the device tree!\n"); + goto out_iomem; + } + + idr = irs_readl(irs_data, GICV5_IRS_IDR7); + irs_data->spi_min = FIELD_GET(GICV5_IRS_IDR7_SPI_BASE, idr); + idr = irs_readl(irs_data, GICV5_IRS_IDR6); + irs_data->spi_range = FIELD_GET(GICV5_IRS_IDR6_SPI_IRS_RANGE, idr); + + if (irs_data->spi_range) + pr_info("%s detected SPI range [%u-%u]\n", + of_node_full_name(node), + irs_data->spi_min, + irs_data->spi_min + + irs_data->spi_range - 1); + + /* + * Do the global setting only on the first IRS. + * Global properties (iaffid_bits, global spi count) are guaranteed to + * be consistent across IRSes by the architecture. + */ + if (list_empty(&irs_nodes)) { + + idr = irs_readl(irs_data, GICV5_IRS_IDR1); + irs_setup_pri_bits(idr); + + idr = irs_readl(irs_data, GICV5_IRS_IDR5); + gicv5_global_data.global_spi_count = + FIELD_GET(GICV5_IRS_IDR5_SPI_RANGE, idr); + + pr_debug("Detected %u SPIs globally\n", + gicv5_global_data.global_spi_count); + } + + list_add_tail(&irs_data->entry, &irs_nodes); + + return 0; +out_iomem: + iounmap(irs_base); +out_err: + kfree(irs_data); + return ret; +} + +void __init gicv5_irs_remove(void) +{ + struct gicv5_irs_chip_data *irs_data, *tmp_data; + + list_for_each_entry_safe(irs_data, tmp_data, &irs_nodes, entry) { + iounmap(irs_data->irs_base); + list_del(&irs_data->entry); + kfree(irs_data); + } +} + +int __init gicv5_irs_of_probe(struct device_node *parent) +{ + int ret; + struct device_node *np; + + for_each_available_child_of_node(parent, np) { + if (!of_device_is_compatible(np, "arm,gic-v5-irs")) + continue; + + ret = gicv5_irs_init(np); + if (ret) + pr_err("Failed to init IRS %s\n", np->full_name); + } + + return list_empty(&irs_nodes) ? -ENODEV : 0; +} diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c index 996e2c992ef33e5ec8d2680ad4026b725ca39b04..5c7a9263e0cea36515dbdadd067b8eb5f65e8da4 100644 --- a/drivers/irqchip/irq-gic-v5.c +++ b/drivers/irqchip/irq-gic-v5.c @@ -24,12 +24,7 @@ static bool gicv5_cpuif_has_gcie(void) return this_cpu_has_cap(ARM64_HAS_GCIE); } -struct gicv5_chip_data { - struct fwnode_handle *fwnode; - struct irq_domain *ppi_domain; -}; - -static struct gicv5_chip_data gicv5_global_data __read_mostly; +struct gicv5_chip_data gicv5_global_data __read_mostly; static void gicv5_ppi_priority_init(void) { @@ -73,6 +68,30 @@ static void gicv5_ppi_priority_init(void) isb(); } +static void gicv5_hwirq_init(irq_hw_number_t hwirq, u8 priority, u8 hwirq_type) +{ + u64 cdpri, cdaff; + u16 iaffid; + int ret; + + if (hwirq_type == GICV5_HWIRQ_TYPE_SPI) { + cdpri = FIELD_PREP(GICV5_GIC_CDPRI_PRIORITY_MASK, priority) | + FIELD_PREP(GICV5_GIC_CDPRI_TYPE_MASK, hwirq_type) | + FIELD_PREP(GICV5_GIC_CDPRI_ID_MASK, hwirq); + gic_insn(cdpri, GICV5_OP_GIC_CDPRI); + + ret = gicv5_irs_cpu_to_iaffid(smp_processor_id(), &iaffid); + + if (WARN_ON(ret)) + return; + + cdaff = FIELD_PREP(GICV5_GIC_CDAFF_IAFFID_MASK, iaffid) | + FIELD_PREP(GICV5_GIC_CDAFF_TYPE_MASK, hwirq_type) | + FIELD_PREP(GICV5_GIC_CDAFF_ID_MASK, hwirq); + gic_insn(cdaff, GICV5_OP_GIC_CDAFF); + } +} + static void gicv5_ppi_irq_mask(struct irq_data *d) { u64 hwirq_id_bit = BIT_ULL(d->hwirq % 64); @@ -88,6 +107,22 @@ static void gicv5_ppi_irq_mask(struct irq_data *d) isb(); } +static void gicv5_iri_irq_mask(struct irq_data *d, u8 hwirq_type) +{ + u64 cddis = d->hwirq | FIELD_PREP(GICV5_GIC_CDDIS_TYPE_MASK, hwirq_type); + + gic_insn(cddis, GICV5_OP_GIC_CDDIS); + /* + * We must make sure that GIC CDDIS write effects are propagated + */ + gsb_sys(); +} + +static void gicv5_spi_irq_mask(struct irq_data *d) +{ + gicv5_iri_irq_mask(d, GICV5_HWIRQ_TYPE_SPI); +} + static void gicv5_ppi_irq_unmask(struct irq_data *d) { u64 hwirq_id_bit = BIT_ULL(d->hwirq % 64); @@ -98,7 +133,19 @@ static void gicv5_ppi_irq_unmask(struct irq_data *d) sysreg_clear_set_s(SYS_ICC_PPI_ENABLER1_EL1, 0, hwirq_id_bit); } -static void gicv5_hwirq_eoi(u32 hwirq_id, u32 hwirq_type) +static void gicv5_iri_irq_unmask(struct irq_data *d, u8 hwirq_type) +{ + u64 cden = d->hwirq | FIELD_PREP(GICV5_GIC_CDEN_TYPE_MASK, hwirq_type); + + gic_insn(cden, GICV5_OP_GIC_CDEN); +} + +static void gicv5_spi_irq_unmask(struct irq_data *d) +{ + gicv5_iri_irq_unmask(d, GICV5_HWIRQ_TYPE_SPI); +} + +static void gicv5_hwirq_eoi(u32 hwirq_id, u8 hwirq_type) { u64 cddi = hwirq_id | FIELD_PREP(GICV5_GIC_CDDI_TYPE_MASK, hwirq_type); @@ -112,6 +159,11 @@ static void gicv5_ppi_irq_eoi(struct irq_data *d) gicv5_hwirq_eoi(d->hwirq, GICV5_HWIRQ_TYPE_PPI); } +static void gicv5_spi_irq_eoi(struct irq_data *d) +{ + gicv5_hwirq_eoi(d->hwirq, GICV5_HWIRQ_TYPE_SPI); +} + static int gicv5_ppi_set_type(struct irq_data *d, unsigned int type) { /* @@ -145,6 +197,41 @@ static int gicv5_ppi_set_type(struct irq_data *d, unsigned int type) return 0; } +static int gicv5_iri_irq_set_affinity(struct irq_data *d, + const struct cpumask *mask_val, + bool force, u8 hwirq_type) +{ + u16 iaffid; + u64 cdaff; + int ret, cpuid; + + if (force) + cpuid = cpumask_first(mask_val); + else + cpuid = cpumask_any_and(mask_val, cpu_online_mask); + + ret = gicv5_irs_cpu_to_iaffid(cpuid, &iaffid); + if (ret) + return ret; + + cdaff = FIELD_PREP(GICV5_GIC_CDAFF_IAFFID_MASK, iaffid) | + FIELD_PREP(GICV5_GIC_CDAFF_TYPE_MASK, hwirq_type) | + FIELD_PREP(GICV5_GIC_CDAFF_ID_MASK, d->hwirq); + gic_insn(cdaff, GICV5_OP_GIC_CDAFF); + + irq_data_update_effective_affinity(d, cpumask_of(cpuid)); + + return IRQ_SET_MASK_OK_DONE; +} + +static int gicv5_spi_irq_set_affinity(struct irq_data *d, + const struct cpumask *mask_val, + bool force) +{ + return gicv5_iri_irq_set_affinity(d, mask_val, force, + GICV5_HWIRQ_TYPE_SPI); +} + static int gicv5_ppi_irq_get_irqchip_state(struct irq_data *d, enum irqchip_irq_state which, bool *val) @@ -187,6 +274,53 @@ static int gicv5_ppi_irq_get_irqchip_state(struct irq_data *d, return -EINVAL; } +static int gicv5_iri_irq_get_irqchip_state(struct irq_data *d, + enum irqchip_irq_state which, + bool *val, u8 hwirq_type) +{ + u64 icsr, cdrcfg = d->hwirq | FIELD_PREP(GICV5_GIC_CDRCFG_TYPE_MASK, + hwirq_type); + + preempt_disable(); + gic_insn(cdrcfg, GICV5_OP_GIC_CDRCFG); + isb(); + icsr = read_sysreg_s(SYS_ICC_ICSR_EL1); + preempt_enable(); + + if (FIELD_GET(ICC_ICSR_EL1_F, icsr)) { + pr_err("ICSR_EL1 is invalid\n"); + return -EINVAL; + } + + switch (which) { + case IRQCHIP_STATE_PENDING: + *val = !!(FIELD_GET(ICC_ICSR_EL1_Pending, icsr)); + return 0; + + case IRQCHIP_STATE_ACTIVE: + *val = !!(FIELD_GET(ICC_ICSR_EL1_Active, icsr)); + return 0; + + case IRQCHIP_STATE_MASKED: + *val = !(FIELD_GET(ICC_ICSR_EL1_Enabled, icsr)); + return 0; + + default: + pr_debug("Unexpected irqchip_irq_state\n"); + return -EINVAL; + } + + return -EINVAL; +} + +static int gicv5_spi_irq_get_irqchip_state(struct irq_data *d, + enum irqchip_irq_state which, + bool *val) +{ + return gicv5_iri_irq_get_irqchip_state(d, which, val, + GICV5_HWIRQ_TYPE_SPI); +} + static int gicv5_ppi_irq_set_irqchip_state(struct irq_data *d, enum irqchip_irq_state which, bool val) @@ -245,6 +379,51 @@ static int gicv5_ppi_irq_set_irqchip_state(struct irq_data *d, return -EINVAL; } +static void gicv5_iri_irq_write_pending_state(struct irq_data *d, bool val, + u8 hwirq_type) +{ + u64 cdpend; + + cdpend = FIELD_PREP(GICV5_GIC_CDPEND_TYPE_MASK, hwirq_type) | + FIELD_PREP(GICV5_GIC_CDPEND_ID_MASK, d->hwirq) | + FIELD_PREP(GICV5_GIC_CDPEND_PENDING_MASK, val); + + gic_insn(cdpend, GICV5_OP_GIC_CDPEND); +} + +static void gicv5_spi_irq_write_pending_state(struct irq_data *d, bool val) +{ + gicv5_iri_irq_write_pending_state(d, val, GICV5_HWIRQ_TYPE_SPI); +} + +static int gicv5_spi_irq_set_irqchip_state(struct irq_data *d, + enum irqchip_irq_state which, + bool val) +{ + switch (which) { + case IRQCHIP_STATE_PENDING: + gicv5_spi_irq_write_pending_state(d, val); + break; + case IRQCHIP_STATE_MASKED: + if (val) + gicv5_spi_irq_mask(d); + else + gicv5_spi_irq_unmask(d); + break; + default: + pr_debug("Unexpected irqchip_irq_state\n"); + return -EINVAL; + } + + return 0; +} + +static int gicv5_spi_irq_retrigger(struct irq_data *data) +{ + return !gicv5_spi_irq_set_irqchip_state(data, IRQCHIP_STATE_PENDING, + true); +} + static const struct irq_chip gicv5_ppi_irq_chip = { .name = "GICv5-PPI", .irq_mask = gicv5_ppi_irq_mask, @@ -258,6 +437,21 @@ static const struct irq_chip gicv5_ppi_irq_chip = { IRQCHIP_MASK_ON_SUSPEND }; +static const struct irq_chip gicv5_spi_irq_chip = { + .name = "GICv5-SPI", + .irq_mask = gicv5_spi_irq_mask, + .irq_unmask = gicv5_spi_irq_unmask, + .irq_eoi = gicv5_spi_irq_eoi, + .irq_set_type = gicv5_spi_irq_set_type, + .irq_set_affinity = gicv5_spi_irq_set_affinity, + .irq_retrigger = gicv5_spi_irq_retrigger, + .irq_get_irqchip_state = gicv5_spi_irq_get_irqchip_state, + .irq_set_irqchip_state = gicv5_spi_irq_set_irqchip_state, + .flags = IRQCHIP_SET_TYPE_MASKED | + IRQCHIP_SKIP_SET_WAKE | + IRQCHIP_MASK_ON_SUSPEND +}; + static int gicv5_irq_ppi_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec, irq_hw_number_t *hwirq, @@ -302,8 +496,8 @@ static int gicv5_irq_ppi_domain_alloc(struct irq_domain *domain, return 0; } -static void gicv5_irq_ppi_domain_free(struct irq_domain *domain, - unsigned int virq, unsigned int nr_irqs) +static void gicv5_irq_domain_free(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs) { struct irq_data *d; @@ -335,10 +529,84 @@ static int gicv5_irq_ppi_domain_select(struct irq_domain *d, static const struct irq_domain_ops gicv5_irq_ppi_domain_ops = { .translate = gicv5_irq_ppi_domain_translate, .alloc = gicv5_irq_ppi_domain_alloc, - .free = gicv5_irq_ppi_domain_free, + .free = gicv5_irq_domain_free, .select = gicv5_irq_ppi_domain_select }; +static int gicv5_irq_spi_domain_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + irq_hw_number_t *hwirq, + unsigned int *type) +{ + if (is_of_node(fwspec->fwnode)) { + if (fwspec->param_count < 3) + return -EINVAL; + + if (fwspec->param[0] != GICV5_HWIRQ_TYPE_SPI) + return -EINVAL; + + *hwirq = fwspec->param[1]; + *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; + + return 0; + } + + return -EINVAL; +} + +static int gicv5_irq_spi_domain_alloc(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs, + void *arg) +{ + struct gicv5_irs_chip_data *chip_data; + struct irq_data *irqd; + unsigned int type = IRQ_TYPE_NONE; + struct irq_fwspec *fwspec = arg; + irq_hw_number_t hwirq; + int ret; + + if (WARN_ON(nr_irqs != 1)) + return -EINVAL; + + ret = gicv5_irq_spi_domain_translate(domain, fwspec, &hwirq, &type); + if (ret) + return ret; + + irqd = irq_desc_get_irq_data(irq_to_desc(virq)); + chip_data = gicv5_irs_lookup_by_spi_id(hwirq); + + irq_domain_set_info(domain, virq, hwirq, &gicv5_spi_irq_chip, chip_data, + handle_fasteoi_irq, NULL, NULL); + irq_set_probe(virq); + irqd_set_single_target(irqd); + + gicv5_hwirq_init(hwirq, GICV5_IRQ_PRIORITY_MI, GICV5_HWIRQ_TYPE_SPI); + + return 0; +} + +static int gicv5_irq_spi_domain_select(struct irq_domain *d, + struct irq_fwspec *fwspec, + enum irq_domain_bus_token bus_token) +{ + if (fwspec->fwnode != d->fwnode) + return 0; + + if (fwspec->param[0] != GICV5_HWIRQ_TYPE_SPI) { + // only handle SPIs + return 0; + } + + return (d == gicv5_global_data.spi_domain); +} + +static const struct irq_domain_ops gicv5_irq_spi_domain_ops = { + .translate = gicv5_irq_spi_domain_translate, + .alloc = gicv5_irq_spi_domain_alloc, + .free = gicv5_irq_domain_free, + .select = gicv5_irq_spi_domain_select +}; + static inline void handle_irq_per_domain(u32 hwirq) { u32 hwirq_id; @@ -349,6 +617,8 @@ static inline void handle_irq_per_domain(u32 hwirq) if (hwirq_type == GICV5_HWIRQ_TYPE_PPI) domain = gicv5_global_data.ppi_domain; + else if (hwirq_type == GICV5_HWIRQ_TYPE_SPI) + domain = gicv5_global_data.spi_domain; if (generic_handle_domain_irq(domain, hwirq_id)) { pr_err("Could not handle, hwirq = 0x%x", hwirq_id); @@ -427,13 +697,15 @@ static int gicv5_starting_cpu(unsigned int cpu) gicv5_cpu_enable_interrupts(); - return 0; + return gicv5_irs_register_cpu(cpu); } static void __init gicv5_free_domains(void) { if (gicv5_global_data.ppi_domain) irq_domain_remove(gicv5_global_data.ppi_domain); + if (gicv5_global_data.spi_domain) + irq_domain_remove(gicv5_global_data.spi_domain); } static int __init gicv5_init_domains(struct fwnode_handle *handle) @@ -447,6 +719,19 @@ static int __init gicv5_init_domains(struct fwnode_handle *handle) irq_domain_update_bus_token(gicv5_global_data.ppi_domain, DOMAIN_BUS_WIRED); + if (gicv5_global_data.global_spi_count) { + gicv5_global_data.spi_domain = irq_domain_create_linear( + handle, gicv5_global_data.global_spi_count, + &gicv5_irq_spi_domain_ops, NULL); + + if (WARN_ON(!gicv5_global_data.spi_domain)) { + gicv5_free_domains(); + return -ENOMEM; + } + irq_domain_update_bus_token(gicv5_global_data.spi_domain, + DOMAIN_BUS_WIRED); + } + return 0; } @@ -456,14 +741,14 @@ static void gicv5_set_cpuif_pribits(void) switch (FIELD_GET(ICC_IDR0_EL1_PRI_BITS, icc_idr0)) { case ICC_IDR0_EL1_PRI_BITS_4BITS: - pri_bits = 4; + gicv5_global_data.cpuif_pri_bits = 4; break; case ICC_IDR0_EL1_PRI_BITS_5BITS: - pri_bits = 5; + gicv5_global_data.cpuif_pri_bits = 5; break; default: pr_err("Unexpected ICC_IDR0_EL1_PRI_BITS value, default to 4"); - pri_bits = 4; + gicv5_global_data.cpuif_pri_bits = 4; break; } } @@ -473,20 +758,31 @@ static int __init gicv5_of_init(struct device_node *node, { int ret; - ret = gicv5_init_domains(&node->fwnode); + ret = gicv5_irs_of_probe(node); if (ret) return ret; + ret = gicv5_init_domains(&node->fwnode); + if (ret) { + gicv5_irs_remove(); + return ret; + } + gicv5_set_cpuif_pribits(); + pri_bits = min_not_zero(gicv5_global_data.cpuif_pri_bits, + gicv5_global_data.irs_pri_bits); + ret = gicv5_starting_cpu(smp_processor_id()); if (ret) { + gicv5_irs_remove(); gicv5_free_domains(); return ret; } ret = set_handle_irq(gicv5_handle_irq); if (ret) { + gicv5_irs_remove(); gicv5_free_domains(); gicv5_cpu_disable_interrupts(); return ret; diff --git a/drivers/irqchip/irq-gic-v5.h b/drivers/irqchip/irq-gic-v5.h index d8b797cdea2f786646fd88d9c8f60d483380991c..57e2472f1f2a9984f399d2a8633c824bc208da26 100644 --- a/drivers/irqchip/irq-gic-v5.h +++ b/drivers/irqchip/irq-gic-v5.h @@ -12,8 +12,109 @@ #define GICV5_HWIRQ_INTID GENMASK_ULL(31, 0) #define GICV5_HWIRQ_TYPE_PPI UL(0x1) +#define GICV5_HWIRQ_TYPE_SPI UL(0x3) #define GICV5_PPI_HM_EDGE UL(0x0) #define GICV5_PPI_HM_LEVEL UL(0x1) +#define GICV5_NO_READ_ALLOC 0b0 +#define GICV5_READ_ALLOC 0b1 +#define GICV5_NO_WRITE_ALLOC 0b0 +#define GICV5_WRITE_ALLOC 0b1 + +#define GICV5_NON_CACHE 0b00 +#define GICV5_WB_CACHE 0b01 +#define GICV5_WT_CACHE 0b10 + +#define GICV5_NON_SHARE 0b00 +#define GICV5_OUTER_SHARE 0b10 +#define GICV5_INNER_SHARE 0b11 + +#define GICV5_IRS_IDR1 0x0004 +#define GICV5_IRS_IDR2 0x0008 +#define GICV5_IRS_IDR5 0x0014 +#define GICV5_IRS_IDR6 0x0018 +#define GICV5_IRS_IDR7 0x001c +#define GICV5_IRS_CR0 0x0080 +#define GICV5_IRS_CR1 0x0084 +#define GICV5_IRS_SPI_SELR 0x0108 +#define GICV5_IRS_SPI_CFGR 0x0114 +#define GICV5_IRS_SPI_STATUSR 0x0118 +#define GICV5_IRS_PE_SELR 0x0140 +#define GICV5_IRS_PE_STATUSR 0x0144 +#define GICV5_IRS_PE_CR0 0x0148 + +#define GICV5_IRS_IDR1_PRIORITY_BITS GENMASK(22, 20) +#define GICV5_IRS_IDR1_IAFFID_BITS GENMASK(19, 16) + +#define GICV5_IRS_IDR1_PRIORITY_BITS_1BITS 0b000 +#define GICV5_IRS_IDR1_PRIORITY_BITS_2BITS 0b001 +#define GICV5_IRS_IDR1_PRIORITY_BITS_3BITS 0b010 +#define GICV5_IRS_IDR1_PRIORITY_BITS_4BITS 0b011 +#define GICV5_IRS_IDR1_PRIORITY_BITS_5BITS 0b100 + +#define GICV5_IRS_IDR5_SPI_RANGE GENMASK(24, 0) +#define GICV5_IRS_IDR6_SPI_IRS_RANGE GENMASK(24, 0) +#define GICV5_IRS_IDR7_SPI_BASE GENMASK(23, 0) + +#define GICV5_IRS_CR0_IDLE BIT(1) +#define GICV5_IRS_CR0_IRSEN BIT(0) + +#define GICV5_IRS_CR1_VPED_WA BIT(15) +#define GICV5_IRS_CR1_VPED_RA BIT(14) +#define GICV5_IRS_CR1_VMD_WA BIT(13) +#define GICV5_IRS_CR1_VMD_RA BIT(12) +#define GICV5_IRS_CR1_VPET_WA BIT(11) +#define GICV5_IRS_CR1_VPET_RA BIT(10) +#define GICV5_IRS_CR1_VMT_WA BIT(9) +#define GICV5_IRS_CR1_VMT_RA BIT(8) +#define GICV5_IRS_CR1_IST_WA BIT(7) +#define GICV5_IRS_CR1_IST_RA BIT(6) +#define GICV5_IRS_CR1_IC GENMASK(5, 4) +#define GICV5_IRS_CR1_OC GENMASK(3, 2) +#define GICV5_IRS_CR1_SH GENMASK(1, 0) + +#define GICV5_IRS_SPI_STATUSR_V BIT(1) +#define GICV5_IRS_SPI_STATUSR_IDLE BIT(0) + +#define GICV5_IRS_SPI_SELR_ID GENMASK(23, 0) + +#define GICV5_IRS_SPI_CFGR_TM BIT(0) + +#define GICV5_IRS_PE_SELR_IAFFID GENMASK(15, 0) + +#define GICV5_IRS_PE_STATUSR_V BIT(1) +#define GICV5_IRS_PE_STATUSR_IDLE BIT(0) + +#define GICV5_IRS_PE_CR0_DPS BIT(0) + +struct gicv5_chip_data { + struct fwnode_handle *fwnode; + struct irq_domain *ppi_domain; + struct irq_domain *spi_domain; + u32 global_spi_count; + u8 cpuif_pri_bits; + u8 irs_pri_bits; + u8 irs_iaffid_bits; +}; + +extern struct gicv5_chip_data gicv5_global_data __read_mostly; + +struct gicv5_irs_chip_data { + struct list_head entry; + struct fwnode_handle *fwnode; + void __iomem *irs_base; + u32 flags; + u32 spi_min; + u32 spi_range; + raw_spinlock_t spi_config_lock; +}; + +int gicv5_irs_of_probe(struct device_node *parent); +void gicv5_irs_remove(void); +int gicv5_irs_register_cpu(int cpuid); +int gicv5_irs_cpu_to_iaffid(int cpu_id, u16 *iaffid); +struct gicv5_irs_chip_data *gicv5_irs_lookup_by_spi_id(u32 spi_id); +int gicv5_spi_irq_set_type(struct irq_data *d, unsigned int type); + #endif From patchwork Tue Apr 8 10:50:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14043023 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0C859C369A7 for ; Tue, 8 Apr 2025 13:14:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=GVC5aGgAs9LopoyaByToyuTpik5Wwk3QDblayCtWxQ4=; b=tDSEyWuKzIz5zVb7VJUBLGwO4r oLcyGx7bJ4Z2KQVKBbvsQ7aHO5Yg7wv2mJhmC2oHErWlO28t+ZKFV8YBntTp5YM45hpqAXvQD6teO 9hPjGWzuIyLh2V+o33XSKexDYmwuEIJUH4KsrGM77wvxP54YzjugAmPeeaAtRBMEu+SBpUKA4CR8u 8RzA96Tb+Acz3bf8r7fdI1bCv2Un4NvmQ8/yTihjWJkOBNttIoIw1DV9FwyhfiezrMnyDdhfdqC0t yymWO1XgyaPnXfDEw0FzOvoFfxKL/macR8pstW5AhzkioFYSE3evIx1ZYHVxuOvXRiy6iyFI5Af9b uPSn6wqQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u28ln-0000000461d-3hyj; Tue, 08 Apr 2025 13:13:39 +0000 Received: from tor.source.kernel.org ([2600:3c04:e001:324:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Yl-00000003kNU-1IFi for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:52:03 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 9843E614B8; Tue, 8 Apr 2025 10:51:53 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id F260BC4CEEB; Tue, 8 Apr 2025 10:51:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109522; bh=I4CJMV1W3CjDmDnFQpck8HW5RiufP8Jfd8CGS/MAO7E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qmhw3C2fYCa4e3SfuKrBTW0DL3tQdeDdKusG1PeTa4nieLYqy3mvJJLNDllpqtrLw xm+Lt+UYg3rnJjHJVTbPx3knzNlrRlt15yxOn5/aUMTNl4fh2d9fn3j/i6h33gnJZH dDX5w/NaTWx/JKJklBGxg2mmusMlD6Jznt7SN/7muxWLMzfELleIzY6RGSXzAECWhS xBHv2vrrM/pUaEeiDM9+v0UMEs9iK7Pz5vAlGKz++gE9GoVm2YL5zRsavgzHcyG5uM Tk8xg1YaJu+WU1fTUh/SX8H8lGTrtwx7ogR6N49MyhFGjmi3+Kv8XaSCZKWHwpE21q crbl8ZUjFMpTg== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:19 +0200 Subject: [PATCH 20/24] irqchip/gic-v5: Add GICv5 LPI/IPI support MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-20-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org An IRS supports Logical Peripheral Interrupts (LPIs) and implement Linux IPIs on top of it. LPIs are used for interrupt signals that are translated by a GICv5 ITS (Interrupt Translation Service) but also for software generated IRQs - namely interrupts that are not driven by a HW signal, ie IPIs. LPIs rely on memory storage for interrupt routing and state. Memory storage is handled by the IRS - that is configured at probe time by the driver with the required memory. LPIs state and routing information is kept in the Interrupt State Table (IST). IRSes provide support for 1- or 2-level IST tables configured to support a maximum number of interrupts that depend on the OS configuration and the HW capabilities. On systems that provide 2-level IST support, always allow the maximum number of LPIs; On systems with only 1-level support, limit the number of LPIs to 2^12 to prevent wasting memory (presumably a system that supports a 1-level only IST is not expecting a large number of interrupts). On a 2-level IST system, L2 entries are allocated on demand. The IST table memory is allocated using the kmalloc() interface; the allocation required may be smaller than a page and must be made up of contiguous physical pages if larger than a page. On systems where the IRS is not cache-coherent with the CPUs, cache mainteinance operations are executed to clean and invalidate the allocated memory to the point of coherency making it visible to the IRS components. Add an LPI IRQ domain to: - Manage LPI state and routing - Add LPI IRQchip structure and callbacks - LPI domain allocation/de-allocation On GICv5 systems, IPIs are implemented using LPIs. Implement an IPI-specific IRQ domain created as a child/subdomain of the LPI domain to allocate the required number of LPIs needed to implement the IPIs. Move the arm64 IPI enum declaration to a header file so that the GICv5 driver code can detect how many IPIs are required by arch code. IPIs are backed by LPIs, add LPIs allocation/de-allocation functions. The LPI INTID namespace is managed using a maple tree which encodes ranges, add code to alloc/free LPI INTIDs. Maple tree entries are not used by the driver, only the range tracking is required - therefore the driver first finds an empty area large enough to contain the required number of LPIs then checks the adjacent (and possibly occupied) LPI ranges and try to merge them together, reducing maple tree slots usage. Associate an IPI irqchip with IPI IRQ descriptors to provide core code with the irqchip.ipi_send_single() method required to raise an IPI. Co-developed-by: Sascha Bischoff Signed-off-by: Sascha Bischoff Co-developed-by: Timothy Hayes Signed-off-by: Timothy Hayes Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Thomas Gleixner Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/include/asm/arch_gicv5.h | 1 + arch/arm64/include/asm/smp.h | 17 ++ arch/arm64/kernel/smp.c | 17 -- drivers/irqchip/irq-gic-v5-irs.c | 369 ++++++++++++++++++++++++++++++++++++ drivers/irqchip/irq-gic-v5.c | 347 ++++++++++++++++++++++++++++++++- drivers/irqchip/irq-gic-v5.h | 64 +++++++ 6 files changed, 797 insertions(+), 18 deletions(-) diff --git a/arch/arm64/include/asm/arch_gicv5.h b/arch/arm64/include/asm/arch_gicv5.h index 00c6b7903094ca5d6e496890d029d21d82b7af66..75557fdad611fa51d7136126eb80cb861be98a8d 100644 --- a/arch/arm64/include/asm/arch_gicv5.h +++ b/arch/arm64/include/asm/arch_gicv5.h @@ -5,6 +5,7 @@ #ifndef __ASM_ARCH_GICV5_H #define __ASM_ARCH_GICV5_H +#include #include #ifndef __ASSEMBLY__ diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index d6fd6efb66a673ae33825971e4aa07e791c02ee5..d48ef6d5abcc77d1c06ad8e91e72006acf662078 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h @@ -50,6 +50,23 @@ struct seq_file; */ extern void smp_init_cpus(void); +enum ipi_msg_type { + IPI_RESCHEDULE, + IPI_CALL_FUNC, + IPI_CPU_STOP, + IPI_CPU_STOP_NMI, + IPI_TIMER, + IPI_IRQ_WORK, + NR_IPI, + /* + * Any enum >= NR_IPI and < MAX_IPI is special and not tracable + * with trace_ipi_* + */ + IPI_CPU_BACKTRACE = NR_IPI, + IPI_KGDB_ROUNDUP, + MAX_IPI +}; + /* * Register IPI interrupts with the arch SMP code */ diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 3f3712e47c94c62836fb89cd4bfb3595fbb41557..148145979d83f67469075df1c8b5e366ffe9d907 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -64,23 +64,6 @@ struct secondary_data secondary_data; /* Number of CPUs which aren't online, but looping in kernel text. */ static int cpus_stuck_in_kernel; -enum ipi_msg_type { - IPI_RESCHEDULE, - IPI_CALL_FUNC, - IPI_CPU_STOP, - IPI_CPU_STOP_NMI, - IPI_TIMER, - IPI_IRQ_WORK, - NR_IPI, - /* - * Any enum >= NR_IPI and < MAX_IPI is special and not tracable - * with trace_ipi_* - */ - IPI_CPU_BACKTRACE = NR_IPI, - IPI_KGDB_ROUNDUP, - MAX_IPI -}; - static int ipi_irq_base __ro_after_init; static int nr_ipi __ro_after_init = NR_IPI; diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c index 5999f2a2c8dac0ea01ab0aa5df65bf12e1f59f63..909ccf07879a1feb5abb65fa265706f2c276d927 100644 --- a/drivers/irqchip/irq-gic-v5-irs.c +++ b/drivers/irqchip/irq-gic-v5-irs.c @@ -7,11 +7,14 @@ #include #include +#include #include #include #include "irq-gic-v5.h" +#define LPI_ID_BITS_LINEAR 12 + #define IRS_FLAGS_NON_COHERENT BIT(0) static DEFINE_PER_CPU(struct gicv5_irs_chip_data *, per_cpu_irs_data); @@ -22,12 +25,346 @@ static u32 irs_readl(struct gicv5_irs_chip_data *irs_data, const u64 reg_offset) return readl_relaxed(irs_data->irs_base + reg_offset); } +static u64 irs_readq(struct gicv5_irs_chip_data *irs_data, const u64 reg_offset) +{ + return readq_relaxed(irs_data->irs_base + reg_offset); +} + static void irs_writel(struct gicv5_irs_chip_data *irs_data, const u32 val, const u64 reg_offset) { writel_relaxed(val, irs_data->irs_base + reg_offset); } +static void irs_writeq(struct gicv5_irs_chip_data *irs_data, const u64 val, + const u64 reg_offset) +{ + writeq_relaxed(val, irs_data->irs_base + reg_offset); +} + +/* Wait for completion of an IST change */ +static int gicv5_irs_ist_wait_for_idle(struct gicv5_irs_chip_data *irs_data) +{ + int ret; + u32 val; + + ret = readl_relaxed_poll_timeout_atomic( + irs_data->irs_base + GICV5_IRS_IST_STATUSR, val, + FIELD_GET(GICV5_IRS_IST_STATUSR_IDLE, val), 1, + USEC_PER_SEC); + + if (ret == -ETIMEDOUT) + pr_err_ratelimited("IST_STATUSR.IDLE timeout...\n"); + + return ret; +} + +static int __init gicv5_irs_init_ist_linear(struct gicv5_irs_chip_data *irs_data, + unsigned int lpi_id_bits, + unsigned int istsz) +{ + void *ist; + u32 n, cfgr; + u64 baser; + size_t l2istsz; + int ret; + + /* Taken from GICv5 specifications 10.2.1.13 IRS_IST_BASER */ + n = max(5, lpi_id_bits + 1 + istsz); + + l2istsz = BIT(n + 1); + if (l2istsz > KMALLOC_MAX_SIZE) { + u8 lpi_id_cap = ilog2(KMALLOC_MAX_SIZE) - 2 + istsz; + + pr_warn("Limiting LPI ID bits from %u to %u\n", + lpi_id_bits, lpi_id_cap); + lpi_id_bits = lpi_id_cap; + l2istsz = KMALLOC_MAX_SIZE; + } + + ist = kzalloc(l2istsz, GFP_KERNEL); + if (!ist) + return -ENOMEM; + + if (irs_data->flags & IRS_FLAGS_NON_COHERENT) + dcache_clean_inval_poc((unsigned long)ist, + (unsigned long)ist + l2istsz); + else + dsb(ishst); + + cfgr = FIELD_PREP(GICV5_IRS_IST_CFGR_STRUCTURE, + GICV5_IRS_IST_CFGR_STRUCTURE_LINEAR) | + FIELD_PREP(GICV5_IRS_IST_CFGR_ISTSZ, istsz) | + FIELD_PREP(GICV5_IRS_IST_CFGR_L2SZ, + GICV5_IRS_IST_CFGR_L2SZ_4K) | + FIELD_PREP(GICV5_IRS_IST_CFGR_LPI_ID_BITS, lpi_id_bits); + irs_writel(irs_data, cfgr, GICV5_IRS_IST_CFGR); + + gicv5_global_data.ist.l2 = false; + + baser = (virt_to_phys(ist) & GICV5_IRS_IST_BASER_ADDR_MASK) | + FIELD_PREP(GICV5_IRS_IST_BASER_VALID, 0x1); + irs_writeq(irs_data, baser, GICV5_IRS_IST_BASER); + + ret = gicv5_irs_ist_wait_for_idle(irs_data); + if (ret) { + kfree(ist); + return ret; + } + + return 0; +} + +static int __init gicv5_irs_init_ist_two_level( + struct gicv5_irs_chip_data *irs_data, + unsigned int lpi_id_bits, + unsigned int istsz, + unsigned int l2sz) +{ + u32 cfgr, n; + u64 baser; + size_t l1sz; + __le64 *l1ist; + int ret; + + /* Taken from GICv5 specifications 10.2.1.13 IRS_IST_BASER */ + n = max(5, lpi_id_bits - ((10 - istsz) + (2 * l2sz)) + 2); + + l1sz = BIT(n + 1); + + l1ist = kzalloc(l1sz, GFP_KERNEL); + if (!l1ist) + return -ENOMEM; + + if (irs_data->flags & IRS_FLAGS_NON_COHERENT) + dcache_clean_inval_poc((unsigned long)l1ist, + (unsigned long)l1ist + l1sz); + else + dsb(ishst); + + cfgr = FIELD_PREP(GICV5_IRS_IST_CFGR_STRUCTURE, + GICV5_IRS_IST_CFGR_STRUCTURE_TWO_LEVEL) | + FIELD_PREP(GICV5_IRS_IST_CFGR_ISTSZ, istsz) | + FIELD_PREP(GICV5_IRS_IST_CFGR_L2SZ, l2sz) | + FIELD_PREP(GICV5_IRS_IST_CFGR_LPI_ID_BITS, lpi_id_bits); + irs_writel(irs_data, cfgr, GICV5_IRS_IST_CFGR); + + /* + * The L2SZ determine bits required at L2 level. Number of bytes + * required by metadata is reported through istsz - the number of bits + * covered by L2 entries scales accordingly. + */ + gicv5_global_data.ist.l2_size = BIT(11 + (2 * l2sz) + 1); + gicv5_global_data.ist.l2_bits = (10 - istsz) + (2 * l2sz); + gicv5_global_data.ist.l1ist_addr = l1ist; + gicv5_global_data.ist.l2 = true; + + baser = (virt_to_phys(l1ist) & GICV5_IRS_IST_BASER_ADDR_MASK) | + FIELD_PREP(GICV5_IRS_IST_BASER_VALID, 0x1); + irs_writeq(irs_data, baser, GICV5_IRS_IST_BASER); + + ret = gicv5_irs_ist_wait_for_idle(irs_data); + if (ret) { + kfree(l1ist); + return ret; + } + + return 0; +} + +/* + * Alloc L2 IST entries on demand. + * Locking/serialization is guaranteed by irqdomain core code by + * taking the hierarchical domain struct irq_domain.root->mutex. + */ +int gicv5_irs_iste_alloc(const u32 lpi) +{ + struct gicv5_irs_chip_data *irs_data; + u32 l2istr, l2bits; + size_t l2size; + unsigned int index; + __le64 *l1ist; + void *l2ist; + int ret; + + if (!gicv5_global_data.ist.l2) + return 0; + + irs_data = per_cpu(per_cpu_irs_data, smp_processor_id()); + if (!irs_data) + return -ENOENT; + + l2size = gicv5_global_data.ist.l2_size; + l2bits = gicv5_global_data.ist.l2_bits; + + l1ist = gicv5_global_data.ist.l1ist_addr; + + index = lpi >> l2bits; + + if (FIELD_GET(GICV5_ISTL1E_VALID, le64_to_cpu(l1ist[index]))) + return 0; + + l2ist = kzalloc(l2size, GFP_KERNEL); + if (!l2ist) + return -ENOMEM; + + l1ist[index] = cpu_to_le64( + virt_to_phys(l2ist) & GICV5_ISTL1E_L2_ADDR_MASK); + + if (irs_data->flags & IRS_FLAGS_NON_COHERENT) { + dcache_clean_inval_poc((unsigned long)l2ist, + (unsigned long)l2ist + l2size); + dcache_clean_poc((unsigned long)(l1ist + index), + (unsigned long)(l1ist + index) + sizeof(*l1ist)); + } else { + dsb(ishst); + } + + l2istr = FIELD_PREP(GICV5_IRS_MAP_L2_ISTR_ID, lpi); + irs_writel(irs_data, l2istr, GICV5_IRS_MAP_L2_ISTR); + + ret = gicv5_irs_ist_wait_for_idle(irs_data); + if (ret) { + l1ist[index] = 0; + kfree(l2ist); + return ret; + } + + /* + * Make sure we invalidate the cache line pulled before the IRS + * had a chance to update the L1 entry and mark it valid. + */ + if (irs_data->flags & IRS_FLAGS_NON_COHERENT) { + /* + * Order the MMIO IRS wait for idle with cache + * invalidation + */ + dma_rmb(); + dcache_inval_poc((unsigned long)(l1ist + index), + (unsigned long)(l1ist + index) + sizeof(*l1ist)); + } + + return 0; +} + +/* + * Try to match the L2 IST size to the pagesize, and if this is not possible + * pick the smallest supported L2 size in order to minimise the requirement for + * physically contiguous blocks of memory as page-sized allocations are + * guaranteed to be physically contiguous, and are by definition the easiest to + * find. + * + * Fall back to the smallest supported size (in the event that the pagesize + * itself is not supported) again serves to make it easier to find physically + * contiguous blocks of memory. + */ +static int gicv5_irs_l2_sz(u32 idr2) +{ + switch (PAGE_SIZE) { + case SZ_64K: + if (GICV5_IRS_IST_L2SZ_SUPPORT_64KB(idr2)) + return GICV5_IRS_IST_CFGR_L2SZ_64K; + fallthrough; + case SZ_16K: + if (GICV5_IRS_IST_L2SZ_SUPPORT_16KB(idr2)) + return GICV5_IRS_IST_CFGR_L2SZ_16K; + fallthrough; + case SZ_4K: + if (GICV5_IRS_IST_L2SZ_SUPPORT_4KB(idr2)) + return GICV5_IRS_IST_CFGR_L2SZ_4K; + if (GICV5_IRS_IST_L2SZ_SUPPORT_16KB(idr2)) + return GICV5_IRS_IST_CFGR_L2SZ_16K; + if (GICV5_IRS_IST_L2SZ_SUPPORT_64KB(idr2)) + return GICV5_IRS_IST_CFGR_L2SZ_64K; + break; + } + + return -ENODEV; +} + +static int __init gicv5_irs_init_ist(struct gicv5_irs_chip_data *irs_data) +{ + u32 lpi_id_bits, idr2_id_bits, idr2_min_lpi_id_bits, + l2_iste_sz, l2sz, l2_iste_sz_split, idr2; + bool two_levels, istmd; + u64 baser; + int ret; + + baser = irs_readq(irs_data, GICV5_IRS_IST_BASER); + if (FIELD_GET(GICV5_IRS_IST_BASER_VALID, baser)) { + pr_err("IST is marked as valid already; cannot allocate\n"); + return -EPERM; + } + + idr2 = irs_readl(irs_data, GICV5_IRS_IDR2); + + two_levels = !!FIELD_GET(GICV5_IRS_IDR2_IST_LEVELS, idr2); + + idr2_id_bits = FIELD_GET(GICV5_IRS_IDR2_ID_BITS, idr2); + idr2_min_lpi_id_bits = FIELD_GET(GICV5_IRS_IDR2_MIN_LPI_ID_BITS, idr2); + + /* + * For two level tables we are always allocating the maximum allowed + * number of IDs. + * + * For 1-level tables, we should allocate a number of bits that + * is >= min_lpi_id_bits but cap it to LPI_ID_BITS_LINEAR lest + * the level 1-table gets too large and its memory allocation + * may fail. + */ + if (two_levels) { + lpi_id_bits = idr2_id_bits; + } else { + lpi_id_bits = max(LPI_ID_BITS_LINEAR, idr2_min_lpi_id_bits); + lpi_id_bits = min(lpi_id_bits, idr2_id_bits); + } + + /* + * Cap the ID bits according to the CPUIF supported ID bits + */ + lpi_id_bits = min(lpi_id_bits, gicv5_global_data.cpuif_id_bits); + + if (two_levels) { + l2sz = gicv5_irs_l2_sz(idr2); + if (l2sz < 0) + return l2sz; + } + + istmd = !!FIELD_GET(GICV5_IRS_IDR2_ISTMD, idr2); + + l2_iste_sz = GICV5_IRS_IST_CFGR_ISTSZ_4; + + // Only supported if IRS_IDR2.ISTMD is 1 + if (istmd) { + l2_iste_sz_split = FIELD_GET(GICV5_IRS_IDR2_ISTMD_SZ, idr2); + + if (lpi_id_bits < l2_iste_sz_split) + l2_iste_sz = GICV5_IRS_IST_CFGR_ISTSZ_8; + else + l2_iste_sz = GICV5_IRS_IST_CFGR_ISTSZ_16; + } + + /* + * Follow GICv5 specification recommendation to opt in for two + * level tables + */ + two_levels = two_levels && (lpi_id_bits > ((10 - l2_iste_sz) + + (2 * l2sz))); + + if (two_levels) + ret = gicv5_irs_init_ist_two_level(irs_data, lpi_id_bits, + l2_iste_sz, l2sz); + else + ret = gicv5_irs_init_ist_linear(irs_data, lpi_id_bits, + l2_iste_sz); + if (ret) + return ret; + + gicv5_init_lpi(BIT(lpi_id_bits)); + + return 0; +} + struct iaffid_entry { u16 iaffid; bool valid; @@ -383,8 +720,16 @@ static int __init gicv5_irs_init(struct device_node *node) goto out_iomem; } + idr = irs_readl(irs_data, GICV5_IRS_IDR2); + if (WARN(!FIELD_GET(GICV5_IRS_IDR2_LPI, idr), + "LPI support not available - no IPIs, can't proceed\n")) { + ret = -ENODEV; + goto out_iomem; + } + idr = irs_readl(irs_data, GICV5_IRS_IDR7); irs_data->spi_min = FIELD_GET(GICV5_IRS_IDR7_SPI_BASE, idr); + idr = irs_readl(irs_data, GICV5_IRS_IDR6); irs_data->spi_range = FIELD_GET(GICV5_IRS_IDR6_SPI_IRS_RANGE, idr); @@ -409,6 +754,8 @@ static int __init gicv5_irs_init(struct device_node *node) gicv5_global_data.global_spi_count = FIELD_GET(GICV5_IRS_IDR5_SPI_RANGE, idr); + gicv5_init_lpi_domain(); + pr_debug("Detected %u SPIs globally\n", gicv5_global_data.global_spi_count); } @@ -427,6 +774,9 @@ void __init gicv5_irs_remove(void) { struct gicv5_irs_chip_data *irs_data, *tmp_data; + gicv5_free_lpi_domain(); + gicv5_free_lpi(); + list_for_each_entry_safe(irs_data, tmp_data, &irs_nodes, entry) { iounmap(irs_data->irs_base); list_del(&irs_data->entry); @@ -434,6 +784,25 @@ void __init gicv5_irs_remove(void) } } +int __init gicv5_irs_enable(void) +{ + int ret; + struct gicv5_irs_chip_data *irs_data; + + irs_data = list_first_entry_or_null(&irs_nodes, + struct gicv5_irs_chip_data, entry); + if (!irs_data) + return -ENODEV; + + ret = gicv5_irs_init_ist(irs_data); + if (ret) { + pr_err("Failed to init IST\n"); + return ret; + } + + return 0; +} + int __init gicv5_irs_of_probe(struct device_node *parent) { int ret; diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c index 5c7a9263e0cea36515dbdadd067b8eb5f65e8da4..85d951bfd807fc1b67b616dbadeebc150848293f 100644 --- a/drivers/irqchip/irq-gic-v5.c +++ b/drivers/irqchip/irq-gic-v5.c @@ -7,6 +7,8 @@ #include #include +#include +#include #include #include @@ -26,6 +28,90 @@ static bool gicv5_cpuif_has_gcie(void) struct gicv5_chip_data gicv5_global_data __read_mostly; +static struct maple_tree lpi_mt; +static u32 num_lpis; + +void __init gicv5_init_lpi(u32 lpis) +{ + mt_init_flags(&lpi_mt, MT_FLAGS_ALLOC_RANGE); + num_lpis = lpis; +} + +void __init gicv5_free_lpi(void) +{ + mtree_destroy(&lpi_mt); + num_lpis = 0; +} + +#define MT_ENTRY ((void *)&lpi_mt) /* Unused - just a valid pointer */ + +static int alloc_lpi_range(u32 lpis, u32 *base) +{ + int ret; + void *entry; + unsigned long lpi_base, startp, lastp; + + MA_STATE(mas, &lpi_mt, 0, 0); + + if (!num_lpis) + return -ENODEV; + + mtree_lock(&lpi_mt); + ret = mas_empty_area(&mas, 0, num_lpis - 1, lpis); + if (ret) { + pr_err("Failed to perform a dynamic alloc in the LPI MT!\n"); + return ret; + } + + lpi_base = mas.index; + + /* + * We don't really care about the entry itself, only about + * allocation of a maple tree ranges describing in use LPIs. + * That's why, upon allocation, we try to merge slots adjacent + * with the empty one we are allocating to minimize the number + * of slots we take from maple tree nodes for nothing, all + * we need to keep track of is in use ranges. + */ + startp = mas.index; + lastp = mas.last; + + entry = mas_next(&mas, num_lpis - 1); + if (entry && mas.index == lastp + 1) + lastp = mas.last; + + entry = mas_prev(&mas, 0); + if (entry) + startp = mas.index; + mas_set_range(&mas, startp, lastp); + mas_store_gfp(&mas, MT_ENTRY, GFP_KERNEL); + mtree_unlock(&lpi_mt); + + // startp is the index at which we allocated, i.e. the base LPI. + *base = lpi_base; + + return 0; +} + +// Drop entries between min and max (inclusive) +static int release_lpi_range(u32 min, u32 max) +{ + return mtree_store_range(&lpi_mt, min, max, NULL, GFP_KERNEL); +} + +static int gicv5_alloc_lpi_range(u32 nr_lpis, u32 *base) +{ + return alloc_lpi_range(nr_lpis, base); +} + +static int gicv5_free_lpi_range(u32 base, u32 nr_lpis) +{ + if (nr_lpis < 1) + return -EINVAL; + + return release_lpi_range(base, base + nr_lpis - 1); +} + static void gicv5_ppi_priority_init(void) { write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRIORITY_MI), @@ -74,7 +160,8 @@ static void gicv5_hwirq_init(irq_hw_number_t hwirq, u8 priority, u8 hwirq_type) u16 iaffid; int ret; - if (hwirq_type == GICV5_HWIRQ_TYPE_SPI) { + if (hwirq_type == GICV5_HWIRQ_TYPE_LPI || + hwirq_type == GICV5_HWIRQ_TYPE_SPI) { cdpri = FIELD_PREP(GICV5_GIC_CDPRI_PRIORITY_MASK, priority) | FIELD_PREP(GICV5_GIC_CDPRI_TYPE_MASK, hwirq_type) | FIELD_PREP(GICV5_GIC_CDPRI_ID_MASK, hwirq); @@ -123,6 +210,11 @@ static void gicv5_spi_irq_mask(struct irq_data *d) gicv5_iri_irq_mask(d, GICV5_HWIRQ_TYPE_SPI); } +static void gicv5_lpi_irq_mask(struct irq_data *d) +{ + gicv5_iri_irq_mask(d, GICV5_HWIRQ_TYPE_LPI); +} + static void gicv5_ppi_irq_unmask(struct irq_data *d) { u64 hwirq_id_bit = BIT_ULL(d->hwirq % 64); @@ -145,6 +237,11 @@ static void gicv5_spi_irq_unmask(struct irq_data *d) gicv5_iri_irq_unmask(d, GICV5_HWIRQ_TYPE_SPI); } +static void gicv5_lpi_irq_unmask(struct irq_data *d) +{ + gicv5_iri_irq_unmask(d, GICV5_HWIRQ_TYPE_LPI); +} + static void gicv5_hwirq_eoi(u32 hwirq_id, u8 hwirq_type) { u64 cddi = hwirq_id | FIELD_PREP(GICV5_GIC_CDDI_TYPE_MASK, hwirq_type); @@ -164,6 +261,11 @@ static void gicv5_spi_irq_eoi(struct irq_data *d) gicv5_hwirq_eoi(d->hwirq, GICV5_HWIRQ_TYPE_SPI); } +static void gicv5_lpi_irq_eoi(struct irq_data *d) +{ + gicv5_hwirq_eoi(d->hwirq, GICV5_HWIRQ_TYPE_LPI); +} + static int gicv5_ppi_set_type(struct irq_data *d, unsigned int type) { /* @@ -232,6 +334,14 @@ static int gicv5_spi_irq_set_affinity(struct irq_data *d, GICV5_HWIRQ_TYPE_SPI); } +static int gicv5_lpi_irq_set_affinity(struct irq_data *d, + const struct cpumask *mask_val, + bool force) +{ + return gicv5_iri_irq_set_affinity(d, mask_val, force, + GICV5_HWIRQ_TYPE_LPI); +} + static int gicv5_ppi_irq_get_irqchip_state(struct irq_data *d, enum irqchip_irq_state which, bool *val) @@ -321,6 +431,14 @@ static int gicv5_spi_irq_get_irqchip_state(struct irq_data *d, GICV5_HWIRQ_TYPE_SPI); } +static int gicv5_lpi_irq_get_irqchip_state(struct irq_data *d, + enum irqchip_irq_state which, + bool *val) +{ + return gicv5_iri_irq_get_irqchip_state(d, which, val, + GICV5_HWIRQ_TYPE_LPI); +} + static int gicv5_ppi_irq_set_irqchip_state(struct irq_data *d, enum irqchip_irq_state which, bool val) @@ -396,6 +514,11 @@ static void gicv5_spi_irq_write_pending_state(struct irq_data *d, bool val) gicv5_iri_irq_write_pending_state(d, val, GICV5_HWIRQ_TYPE_SPI); } +static void gicv5_lpi_irq_write_pending_state(struct irq_data *d, bool val) +{ + gicv5_iri_irq_write_pending_state(d, val, GICV5_HWIRQ_TYPE_LPI); +} + static int gicv5_spi_irq_set_irqchip_state(struct irq_data *d, enum irqchip_irq_state which, bool val) @@ -418,12 +541,47 @@ static int gicv5_spi_irq_set_irqchip_state(struct irq_data *d, return 0; } +static int gicv5_lpi_irq_set_irqchip_state(struct irq_data *d, + enum irqchip_irq_state which, + bool val) +{ + switch (which) { + case IRQCHIP_STATE_PENDING: + gicv5_lpi_irq_write_pending_state(d, val); + break; + case IRQCHIP_STATE_MASKED: + if (val) + gicv5_lpi_irq_mask(d); + else + gicv5_lpi_irq_unmask(d); + break; + + default: + pr_debug("Unexpected irqchip_irq_state\n"); + return -EINVAL; + } + + return 0; +} + static int gicv5_spi_irq_retrigger(struct irq_data *data) { return !gicv5_spi_irq_set_irqchip_state(data, IRQCHIP_STATE_PENDING, true); } +static int gicv5_lpi_irq_retrigger(struct irq_data *data) +{ + return !gicv5_lpi_irq_set_irqchip_state(data, IRQCHIP_STATE_PENDING, + true); +} + +static void gicv5_ipi_send_single(struct irq_data *d, unsigned int cpu) +{ + /* Mark the LPI pending */ + irq_chip_retrigger_hierarchy(d); +} + static const struct irq_chip gicv5_ppi_irq_chip = { .name = "GICv5-PPI", .irq_mask = gicv5_ppi_irq_mask, @@ -452,6 +610,35 @@ static const struct irq_chip gicv5_spi_irq_chip = { IRQCHIP_MASK_ON_SUSPEND }; +static const struct irq_chip gicv5_lpi_irq_chip = { + .name = "GICv5-LPI", + .irq_mask = gicv5_lpi_irq_mask, + .irq_unmask = gicv5_lpi_irq_unmask, + .irq_eoi = gicv5_lpi_irq_eoi, + .irq_set_affinity = gicv5_lpi_irq_set_affinity, + .irq_retrigger = gicv5_lpi_irq_retrigger, + .irq_get_irqchip_state = gicv5_lpi_irq_get_irqchip_state, + .irq_set_irqchip_state = gicv5_lpi_irq_set_irqchip_state, + .flags = IRQCHIP_SET_TYPE_MASKED | + IRQCHIP_SKIP_SET_WAKE | + IRQCHIP_MASK_ON_SUSPEND +}; + +static const struct irq_chip gicv5_ipi_irq_chip = { + .name = "GICv5-IPI", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, + .irq_get_irqchip_state = irq_chip_get_parent_state, + .irq_set_irqchip_state = irq_chip_set_parent_state, + // We only handle this one in the IPI domain - the rest go to parent + .ipi_send_single = gicv5_ipi_send_single, + .flags = IRQCHIP_SET_TYPE_MASKED | + IRQCHIP_SKIP_SET_WAKE | + IRQCHIP_MASK_ON_SUSPEND +}; + static int gicv5_irq_ppi_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec, irq_hw_number_t *hwirq, @@ -607,6 +794,120 @@ static const struct irq_domain_ops gicv5_irq_spi_domain_ops = { .select = gicv5_irq_spi_domain_select }; +static int gicv5_irq_lpi_domain_alloc(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs, + void *arg) +{ + irq_hw_number_t hwirq; + struct irq_data *irqd; + u32 *base_lpi = arg; + int i, ret; + + hwirq = *base_lpi; + + for (i = 0; i < nr_irqs; i++) { + irqd = irq_desc_get_irq_data(irq_to_desc(virq + i)); + + irq_domain_set_info(domain, virq + i, hwirq + i, + &gicv5_lpi_irq_chip, NULL, + handle_fasteoi_irq, NULL, NULL); + irqd_set_single_target(irqd); + + ret = gicv5_irs_iste_alloc(hwirq + i); + if (ret < 0) + return ret; + + gicv5_hwirq_init((hwirq + i), GICV5_IRQ_PRIORITY_MI, + GICV5_HWIRQ_TYPE_LPI); + } + + return 0; +} + +static void gicv5_irq_lpi_domain_free(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs) +{ + int i; + + for (i = 0; i < nr_irqs; i++) { + struct irq_data *d = irq_domain_get_irq_data(domain, virq + i); + + irq_set_handler(virq + i, NULL); + irq_domain_reset_irq_data(d); + } +} + +static const struct irq_domain_ops gicv5_irq_lpi_domain_ops = { + .alloc = gicv5_irq_lpi_domain_alloc, + .free = gicv5_irq_lpi_domain_free, +}; + +void __init gicv5_init_lpi_domain(void) +{ + gicv5_global_data.lpi_domain = irq_domain_create_tree(NULL, + &gicv5_irq_lpi_domain_ops, NULL); +} + +void __init gicv5_free_lpi_domain(void) +{ + irq_domain_remove(gicv5_global_data.lpi_domain); +} + +static int gicv5_irq_ipi_domain_alloc(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs, + void *arg) +{ + int ret, i; + u32 lpi; + struct irq_data *irqd = irq_desc_get_irq_data(irq_to_desc(virq)); + + // Get LPIs for the IPIs + ret = gicv5_alloc_lpi_range(nr_irqs, &lpi); + if (ret) + return ret; + + ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &lpi); + if (ret) { + gicv5_free_lpi_range(lpi, nr_irqs); + return ret; + } + + for (i = 0; i < nr_irqs; i++) { + irqd = irq_desc_get_irq_data(irq_to_desc(virq + i)); + + irq_domain_set_hwirq_and_chip(domain, virq + i, i, + &gicv5_ipi_irq_chip, NULL); + + irqd_set_single_target(irqd); + + irq_set_handler(virq + i, handle_percpu_irq); + } + + return 0; +} + +static void gicv5_irq_ipi_domain_free(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs) +{ + for (unsigned int i = 0; i < nr_irqs; i++) { + struct irq_data *d = irq_domain_get_irq_data(domain, virq + i); + + if (WARN_ON(!d)) + return; + + gicv5_free_lpi_range(d->parent_data->hwirq, 1); + + irq_set_handler(virq + i, NULL); + irq_domain_reset_irq_data(d); + } + irq_domain_free_irqs_parent(domain, virq, nr_irqs); +} + +static const struct irq_domain_ops gicv5_irq_ipi_domain_ops = { + .alloc = gicv5_irq_ipi_domain_alloc, + .free = gicv5_irq_ipi_domain_free, +}; + static inline void handle_irq_per_domain(u32 hwirq) { u32 hwirq_id; @@ -619,6 +920,8 @@ static inline void handle_irq_per_domain(u32 hwirq) domain = gicv5_global_data.ppi_domain; else if (hwirq_type == GICV5_HWIRQ_TYPE_SPI) domain = gicv5_global_data.spi_domain; + else if (hwirq_type == GICV5_HWIRQ_TYPE_LPI) + domain = gicv5_global_data.lpi_domain; if (generic_handle_domain_irq(domain, hwirq_id)) { pr_err("Could not handle, hwirq = 0x%x", hwirq_id); @@ -706,6 +1009,8 @@ static void __init gicv5_free_domains(void) irq_domain_remove(gicv5_global_data.ppi_domain); if (gicv5_global_data.spi_domain) irq_domain_remove(gicv5_global_data.spi_domain); + if (gicv5_global_data.ipi_domain) + irq_domain_remove(gicv5_global_data.ipi_domain); } static int __init gicv5_init_domains(struct fwnode_handle *handle) @@ -732,6 +1037,19 @@ static int __init gicv5_init_domains(struct fwnode_handle *handle) DOMAIN_BUS_WIRED); } + if (!WARN(!gicv5_global_data.lpi_domain, + "LPI domain uninitialized, can't set up IPIs")) { + gicv5_global_data.ipi_domain = irq_domain_create_hierarchy( + gicv5_global_data.lpi_domain, 0, + GICV5_IPIS_PER_CPU * nr_cpu_ids, + NULL, &gicv5_irq_ipi_domain_ops, NULL); + + if (WARN_ON(!gicv5_global_data.ipi_domain)) { + gicv5_free_domains(); + return -ENOMEM; + } + } + return 0; } @@ -753,6 +1071,25 @@ static void gicv5_set_cpuif_pribits(void) } } +static void gicv5_set_cpuif_idbits(void) +{ + u32 icc_idr0 = read_sysreg_s(SYS_ICC_IDR0_EL1); + + switch (FIELD_GET(ICC_IDR0_EL1_ID_BITS, icc_idr0)) { + case ICC_IDR0_EL1_ID_BITS_16BITS: + gicv5_global_data.cpuif_id_bits = 16; + break; + case ICC_IDR0_EL1_ID_BITS_24BITS: + gicv5_global_data.cpuif_id_bits = 24; + break; + default: + pr_err("Unexpected ICC_IDR0_EL1_ID_BITS value, default to 16"); + gicv5_global_data.cpuif_id_bits = 16; + break; + } +} + + static int __init gicv5_of_init(struct device_node *node, struct device_node *parent) { @@ -769,6 +1106,7 @@ static int __init gicv5_of_init(struct device_node *node, } gicv5_set_cpuif_pribits(); + gicv5_set_cpuif_idbits(); pri_bits = min_not_zero(gicv5_global_data.cpuif_pri_bits, gicv5_global_data.irs_pri_bits); @@ -781,6 +1119,13 @@ static int __init gicv5_of_init(struct device_node *node, } ret = set_handle_irq(gicv5_handle_irq); + if (ret) { + gicv5_irs_remove(); + gicv5_free_domains(); + gicv5_cpu_disable_interrupts(); + } + + ret = gicv5_irs_enable(); if (ret) { gicv5_irs_remove(); gicv5_free_domains(); diff --git a/drivers/irqchip/irq-gic-v5.h b/drivers/irqchip/irq-gic-v5.h index 57e2472f1f2a9984f399d2a8633c824bc208da26..8376da2a342d14568a71c0bc85b79c4e7b83a66c 100644 --- a/drivers/irqchip/irq-gic-v5.h +++ b/drivers/irqchip/irq-gic-v5.h @@ -6,12 +6,16 @@ #define __LINUX_IRQCHIP_GIC_V5_H #include +#include + +#define GICV5_IPIS_PER_CPU MAX_IPI #define GICV5_HWIRQ_ID GENMASK(23, 0) #define GICV5_HWIRQ_TYPE GENMASK(31, 29) #define GICV5_HWIRQ_INTID GENMASK_ULL(31, 0) #define GICV5_HWIRQ_TYPE_PPI UL(0x1) +#define GICV5_HWIRQ_TYPE_LPI UL(0x2) #define GICV5_HWIRQ_TYPE_SPI UL(0x3) #define GICV5_PPI_HM_EDGE UL(0x0) @@ -43,6 +47,10 @@ #define GICV5_IRS_PE_SELR 0x0140 #define GICV5_IRS_PE_STATUSR 0x0144 #define GICV5_IRS_PE_CR0 0x0148 +#define GICV5_IRS_IST_BASER 0x0180 +#define GICV5_IRS_IST_CFGR 0x0190 +#define GICV5_IRS_IST_STATUSR 0x0194 +#define GICV5_IRS_MAP_L2_ISTR 0x01c0 #define GICV5_IRS_IDR1_PRIORITY_BITS GENMASK(22, 20) #define GICV5_IRS_IDR1_IAFFID_BITS GENMASK(19, 16) @@ -53,10 +61,22 @@ #define GICV5_IRS_IDR1_PRIORITY_BITS_4BITS 0b011 #define GICV5_IRS_IDR1_PRIORITY_BITS_5BITS 0b100 +#define GICV5_IRS_IDR2_ISTMD_SZ GENMASK(19, 15) +#define GICV5_IRS_IDR2_ISTMD BIT(14) +#define GICV5_IRS_IDR2_IST_L2SZ GENMASK(13, 11) +#define GICV5_IRS_IDR2_IST_LEVELS BIT(10) +#define GICV5_IRS_IDR2_MIN_LPI_ID_BITS GENMASK(9, 6) +#define GICV5_IRS_IDR2_LPI BIT(5) +#define GICV5_IRS_IDR2_ID_BITS GENMASK(4, 0) + #define GICV5_IRS_IDR5_SPI_RANGE GENMASK(24, 0) #define GICV5_IRS_IDR6_SPI_IRS_RANGE GENMASK(24, 0) #define GICV5_IRS_IDR7_SPI_BASE GENMASK(23, 0) +#define GICV5_IRS_IST_L2SZ_SUPPORT_4KB(r) FIELD_GET(BIT(11), (r)) +#define GICV5_IRS_IST_L2SZ_SUPPORT_16KB(r) FIELD_GET(BIT(12), (r)) +#define GICV5_IRS_IST_L2SZ_SUPPORT_64KB(r) FIELD_GET(BIT(13), (r)) + #define GICV5_IRS_CR0_IDLE BIT(1) #define GICV5_IRS_CR0_IRSEN BIT(0) @@ -88,14 +108,50 @@ #define GICV5_IRS_PE_CR0_DPS BIT(0) +#define GICV5_IRS_IST_STATUSR_IDLE BIT(0) + +#define GICV5_IRS_IST_CFGR_STRUCTURE BIT(16) +#define GICV5_IRS_IST_CFGR_ISTSZ GENMASK(8, 7) +#define GICV5_IRS_IST_CFGR_L2SZ GENMASK(6, 5) +#define GICV5_IRS_IST_CFGR_LPI_ID_BITS GENMASK(4, 0) + +#define GICV5_IRS_IST_CFGR_STRUCTURE_LINEAR 0b0 +#define GICV5_IRS_IST_CFGR_STRUCTURE_TWO_LEVEL 0b1 + +#define GICV5_IRS_IST_CFGR_ISTSZ_4 0b00 +#define GICV5_IRS_IST_CFGR_ISTSZ_8 0b01 +#define GICV5_IRS_IST_CFGR_ISTSZ_16 0b10 + +#define GICV5_IRS_IST_CFGR_L2SZ_4K 0b00 +#define GICV5_IRS_IST_CFGR_L2SZ_16K 0b01 +#define GICV5_IRS_IST_CFGR_L2SZ_64K 0b10 + +#define GICV5_IRS_IST_BASER_ADDR_MASK GENMASK_ULL(55, 6) +#define GICV5_IRS_IST_BASER_VALID BIT_ULL(0) + +#define GICV5_IRS_MAP_L2_ISTR_ID GENMASK(23, 0) + +#define GICV5_ISTL1E_VALID BIT_ULL(0) + +#define GICV5_ISTL1E_L2_ADDR_MASK GENMASK_ULL(55, 12) + struct gicv5_chip_data { struct fwnode_handle *fwnode; struct irq_domain *ppi_domain; struct irq_domain *spi_domain; + struct irq_domain *lpi_domain; + struct irq_domain *ipi_domain; u32 global_spi_count; u8 cpuif_pri_bits; + u8 cpuif_id_bits; u8 irs_pri_bits; u8 irs_iaffid_bits; + struct { + __le64 *l1ist_addr; + u32 l2_size; + u8 l2_bits; + bool l2; + } ist; }; extern struct gicv5_chip_data gicv5_global_data __read_mostly; @@ -110,11 +166,19 @@ struct gicv5_irs_chip_data { raw_spinlock_t spi_config_lock; }; +void __init gicv5_init_lpi_domain(void); +void __init gicv5_free_lpi_domain(void); + int gicv5_irs_of_probe(struct device_node *parent); void gicv5_irs_remove(void); +int gicv5_irs_enable(void); int gicv5_irs_register_cpu(int cpuid); int gicv5_irs_cpu_to_iaffid(int cpu_id, u16 *iaffid); struct gicv5_irs_chip_data *gicv5_irs_lookup_by_spi_id(u32 spi_id); int gicv5_spi_irq_set_type(struct irq_data *d, unsigned int type); +int gicv5_spi_set_type(struct irq_data *d, unsigned int type); +int gicv5_irs_iste_alloc(u32 lpi); +void gicv5_init_lpi(u32 max); +void gicv5_free_lpi(void); #endif From patchwork Tue Apr 8 10:50:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14043012 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3498FC369A6 for ; Tue, 8 Apr 2025 13:13:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=6LHQSalCmVlCgPfIU7QuXxuQm5lxLd81InbukbDQhVc=; b=sgRyOrhtc0TewpZBA/FFDcGK9g DZVbC7wuXlh9FGn5cAOYJpLLxuvv0/ksvR5z5Lws5ZwDiir0GMcx1rVkWFxmlEJYqJYgUSPf2eMvl cn/7r2TLxDruEL9pKKMGpWrgL/gxJr5C4ARCtaekcz6rhK8BXHecoofhU4pjB6n7b9xq+ZEN0dywB 7+KVxnc/Sfk5vG4HYp3mrrUlNyMx0/sTJWRTX/YYYkSfYDJbbHVNWmQOYCcnEZKZRuUYmYY73yPVj 55oNVvKbtqyBdeL/3idB2gbxXtMG6sz+rd8olTmjaak6eIURjbk3Qsgas6jriXlucuvQWExEEQhIO d9wYQ7Hw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u28lo-0000000461v-2IpZ; Tue, 08 Apr 2025 13:13:40 +0000 Received: from tor.source.kernel.org ([2600:3c04:e001:324:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Yo-00000003kOj-20S7 for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:52:06 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 0C901614BA; Tue, 8 Apr 2025 10:51:57 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8C6FAC4CEEC; Tue, 8 Apr 2025 10:52:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109525; bh=D/+rC6w5Q4F5lWg5Dnv7jXrhOy3R2o7m8ettK5W6kbo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JwsJN+JIUpF4no0YRkWLBYsTjWq/YvmA9FgsFGAtB3SyzR7dfvtH+0YPU0CvTRsTD m0qlfqyYwVfgD1hu/TwVbkB6LAFkr0/ZT1W6DErcM1IR1o7rl0vln6YPBGACW4rljK jvUZpvjmS6wJknzfhzrQZydfElElk/3lZ/+A8pCQBaVg7AoCFdxJm9ltYIDsUZOvav 8+kG62nigGokhXoNoFKd0P80gj4/O8tpdxEQDohAGrKCtqAQjQMUOZIYsldZEmChdI 1jYZxJzLaye/6ntNPRsx2cBIgeLbihhBPAu9jAbEtHtxPt42YTyXEHpKtxnNA6brgg YyFoDwPuF4Img== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:20 +0200 Subject: [PATCH 21/24] irqchip/gic-v5: Enable GICv5 SMP booting MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-21-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Set up IPIs by allocating IPI IRQs for all cpus and call into arm64 core code to initialise IPIs IRQ descriptors and request the related IRQ. Implement hotplug callback to enable interrupts on a cpu and register the cpu with an IRS. Implement hotplug callback to check the IRS affinity setup for IPIs on each CPU in order to ensure that each CPU's IPIs affinity is what it is expected to be. Co-developed-by: Sascha Bischoff Signed-off-by: Sascha Bischoff Co-developed-by: Timothy Hayes Signed-off-by: Timothy Hayes Signed-off-by: Lorenzo Pieralisi Cc: Thomas Gleixner Cc: Marc Zyngier --- drivers/irqchip/irq-gic-v5.c | 84 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c index 85d951bfd807fc1b67b616dbadeebc150848293f..24789e9590115e6de7007cd4a74376ae34702ed6 100644 --- a/drivers/irqchip/irq-gic-v5.c +++ b/drivers/irqchip/irq-gic-v5.c @@ -5,6 +5,7 @@ #define pr_fmt(fmt) "GICv5: " fmt +#include #include #include #include @@ -992,6 +993,68 @@ static void gicv5_cpu_enable_interrupts(void) write_sysreg_s(cr0, SYS_ICC_CR0_EL1); } +static int base_ipi_virq; + +static int gicv5_check_ipi_affinity(unsigned int cpu) +{ + int ret; + u64 cdrcfg, icsr; + u16 programmed_iaffid, requested_iaffid; + struct irq_data *d; + unsigned int i, virq_base = base_ipi_virq + cpu * GICV5_IPIS_PER_CPU; + + for (i = 0; i < GICV5_IPIS_PER_CPU; i++) { + d = irq_get_irq_data(virq_base + i); + + if (WARN_ON(!d)) + return -ENODEV; + + /* + * We need to know the actual LPI that is being used, rather + * than the IPI domain hwirq. + * + * Hence, use the hwirq from the parent (LPI domain) here. + */ + cdrcfg = d->parent_data->hwirq | + FIELD_PREP(GICV5_HWIRQ_TYPE, GICV5_HWIRQ_TYPE_LPI); + preempt_disable(); + gic_insn(cdrcfg, GICV5_OP_GIC_CDRCFG); + isb(); + icsr = read_sysreg_s(SYS_ICC_ICSR_EL1); + preempt_enable(); + + if (FIELD_GET(ICC_ICSR_EL1_F, icsr)) { + pr_err("SYS_ID_ICC_ICSR_EL1 is not valid"); + return -ENXIO; + } + + if (!FIELD_GET(ICC_ICSR_EL1_Enabled, icsr)) { + pr_err("interrupt is disabled"); + return -ENXIO; + } + + if (FIELD_GET(ICC_ICSR_EL1_IRM, icsr)) { + pr_debug("Interrupt not using targeted routing"); + return -ENXIO; + } + + programmed_iaffid = (u16)FIELD_GET(ICC_ICSR_EL1_IAFFID, icsr); + + ret = gicv5_irs_cpu_to_iaffid(cpu, &requested_iaffid); + if (ret) + return ret; + + if (programmed_iaffid != requested_iaffid) { + pr_err("Mismatch between programmed_iaffid (%u) and requested_iaffid (%u)", + programmed_iaffid, requested_iaffid); + + return -EIO; + } + } + + return 0; +} + static int gicv5_starting_cpu(unsigned int cpu) { if (WARN(!gicv5_cpuif_has_gcie(), @@ -1003,6 +1066,25 @@ static int gicv5_starting_cpu(unsigned int cpu) return gicv5_irs_register_cpu(cpu); } +static void __init gicv5_smp_init(void) +{ + unsigned int num_ipis = GICV5_IPIS_PER_CPU * nr_cpu_ids; + + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING, + "irqchip/arm/gicv5:starting", + gicv5_starting_cpu, NULL); + + base_ipi_virq = irq_domain_alloc_irqs(gicv5_global_data.ipi_domain, + num_ipis, NUMA_NO_NODE, NULL); + if (WARN(base_ipi_virq <= 0, "IPI IRQ allocation was not successful")) + return; + + set_smp_ipi_range_percpu(base_ipi_virq, GICV5_IPIS_PER_CPU, nr_cpu_ids); + + cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "irqchip/arm/gicv5:online", + gicv5_check_ipi_affinity, NULL); +} + static void __init gicv5_free_domains(void) { if (gicv5_global_data.ppi_domain) @@ -1133,6 +1215,8 @@ static int __init gicv5_of_init(struct device_node *node, return ret; } + gicv5_smp_init(); + return 0; } IRQCHIP_DECLARE(gic_v5, "arm,gic-v5", gicv5_of_init); From patchwork Tue Apr 8 10:50:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042905 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A51D3C3600C for ; Tue, 8 Apr 2025 11:43:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=ZXwuSuw1dAmZBaEDQ4oIayXWRYqiemn1Lz1a2lcHDr0=; b=Uvk8RTeyaNKJ1Vm1svyzIJHb2z m8EGlZVkNZV1NpPJXg74KW0xu4xZS6Z1sZ8u+3GnH/sF5s2E+/PX4AXjvYpq8BDxng6C+bwlbaIiZ ZQpL6Bk2J1/NlT+jQuueQoij6N6KuRW7DK3a0mPHJdtS+h41RACE7Ls0l3bgsnXuhfINGNFp9DvLI 85KOuGek50uSqpfN+H39CSMA2GGPKf3RBTCD9QAa+A7Ni1LQQWOfbFpDYPuFzg7X+FoVXsXiLgDdt 0ngnGV+0bMsVoZy7PkuRfIT+81M51J1jhlhJhs4c0yUDC65B56imggVVaOzlN0GU6w1dNV7u6ZZPz 8KqMQedQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u27Lv-00000003spl-1dUZ; Tue, 08 Apr 2025 11:42:51 +0000 Received: from nyc.source.kernel.org ([2604:1380:45d1:ec00::3]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Ys-00000003kQ6-26P3 for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:52:12 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id DE5B0A4914A; Tue, 8 Apr 2025 10:46:40 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2C1CDC4CEE5; Tue, 8 Apr 2025 10:52:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109529; bh=rY5dPb1vf6Wy5cyG08JALybtE0XAkX7MA6hHC2Rf47U=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EwjoydndXqy1+uaaxrMcLntH0KdJgil3Va4X10lHhMKa9uJwGPUCsw49dY76XZrjC +OvfA2niJMrK3vKVxdZIg5ydbARuol/wVUsj7PkB/JbLVrecMWzwbKguErkprr73an QhowwwhJp8m69A8IazgFh8ZpT772OAbu3dVDGiIG6O37Hlmjpm3Gt83Gb0U68XMLEn UeYfPoBGlpVD8l/XHGC0dzmcr5RwQjUhI0QYbw4RInGMxmSaGPv4fHpZbJrURQDS0k FvTy208B3l2qWVRYlS4HRvHLTy5JAhd1Pj2GReWNGTufipH8nzh18sXP6kKV6ewhHj CA66/xqR4uo8w== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:21 +0200 Subject: [PATCH 22/24] irqchip/gic-v5: Add GICv5 ITS support MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-22-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035210_765364_FEDB4ED9 X-CRM114-Status: GOOD ( 28.70 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The GICv5 architecture implements Interrupt Translation Service (ITS) components in order to translate events coming from peripherals into interrupt events delivered to the connected IRSes. Events (ie MSI memory writes to ITS translate frame), are translated by the ITS using tables kept in memory. ITS translation tables for peripherals is kept in memory storage (device table [DT] and Interrupt Translation Table [ITT]) that is allocated by the driver on boot. Both tables can be 1- or 2-level; the structure is chosen by the driver after probing the ITS HW parameters and checking the allowed table splits and supported {device/event}_IDbits. DT table entries are allocated on demand (ie when a device is probed); the DT table is sized using the number of supported deviceID bits in that that's a system design decision (ie the number of deviceID bits implemented should reflect the number of devices expected in a system) therefore it makes sense to allocate a DT table that can cater for the maximum number of devices. DT and ITT tables are allocated using the kmalloc interface; the allocation size may be smaller than a page or larger, and must provide contiguous memory pages. LPIs INTIDs backing the device events are allocated one-by-one and only upon Linux IRQ allocation; this to avoid preallocating a large number of LPIs to cover the HW device MSI vector size whereas few MSI entries are actually enabled by a device. ITS cacheability/shareability attributes are programmed according to the provided firmware ITS description. The GICv5 ITS reuses the GICv3 MSI parent infrastructure, there is no need to duplicate it, make it common. Co-developed-by: Sascha Bischoff Signed-off-by: Sascha Bischoff Co-developed-by: Timothy Hayes Signed-off-by: Timothy Hayes Signed-off-by: Lorenzo Pieralisi Cc: Thomas Gleixner Cc: Marc Zyngier --- MAINTAINERS | 1 + drivers/irqchip/Kconfig | 11 + drivers/irqchip/Makefile | 4 +- drivers/irqchip/irq-gic-common.h | 2 - ...3-its-msi-parent.c => irq-gic-its-msi-parent.c} | 3 +- drivers/irqchip/irq-gic-its-msi-parent.h | 13 + drivers/irqchip/irq-gic-v3-its.c | 3 +- drivers/irqchip/irq-gic-v5-irs.c | 32 + drivers/irqchip/irq-gic-v5-its.c | 1294 ++++++++++++++++++++ drivers/irqchip/irq-gic-v5.c | 6 +- drivers/irqchip/irq-gic-v5.h | 160 +++ 11 files changed, 1521 insertions(+), 8 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index cdeceb6782355a4a18609135bf7f03249d8b0bb5..d231077c024deba42153663ac66b6c05f7673f03 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1908,6 +1908,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/interrupt-controller/arm,gic-v5.yaml F: arch/arm64/include/asm/arch_gicv5.h +F: drivers/irqchip/irq-gic-its-msi-parent.[ch] F: drivers/irqchip/irq-gic-v5*.[ch] ARM HDLCD DRM DRIVER diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 160a4761d5d85f6dbf36f3142fd619c114733e36..6c348d421b05af0e4f4909877e02ac8ef19178ff 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -41,10 +41,14 @@ config ARM_GIC_V3 select HAVE_ARM_SMCCC_DISCOVERY select IRQ_MSI_IOMMU +config ARM_GIC_ITS_PARENT + bool + config ARM_GIC_V3_ITS bool select GENERIC_MSI_IRQ select IRQ_MSI_LIB + select ARM_GIC_ITS_PARENT default ARM_GIC_V3 select IRQ_MSI_IOMMU @@ -59,6 +63,13 @@ config ARM_GIC_V5 select IRQ_DOMAIN_HIERARCHY select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP +config ARM_GIC_V5_ITS + bool + select GENERIC_MSI_IRQ + select IRQ_MSI_LIB + select ARM_GIC_ITS_PARENT + default ARM_GIC_V5 + config ARM_NVIC bool select IRQ_DOMAIN_HIERARCHY diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 3d9c47fa3fdf40b7452c059d84fe8ac24c91bc0f..4280395e3bdff7858102f0b4eaaea1121cace52f 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -32,10 +32,12 @@ obj-$(CONFIG_ARCH_REALVIEW) += irq-gic-realview.o obj-$(CONFIG_IRQ_MSI_LIB) += irq-msi-lib.o obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o -obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v4.o irq-gic-v3-its-msi-parent.o +obj-$(CONFIG_ARM_GIC_ITS_PARENT) += irq-gic-its-msi-parent.o +obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v4.o obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o irq-gic-v5-irs.o +obj-$(CONFIG_ARM_GIC_V5_ITS) += irq-gic-v5-its.o obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o obj-$(CONFIG_ARM_NVIC) += irq-nvic.o obj-$(CONFIG_ARM_VIC) += irq-vic.o diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h index 020ecdf16901c9720e5746aec4d0b5b39d3625ed..710cab61d9195a0bd64d57e03c60852c4cd6ff8e 100644 --- a/drivers/irqchip/irq-gic-common.h +++ b/drivers/irqchip/irq-gic-common.h @@ -29,8 +29,6 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, void gic_enable_of_quirks(const struct device_node *np, const struct gic_quirk *quirks, void *data); -extern const struct msi_parent_ops gic_v3_its_msi_parent_ops; - #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) #define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1) #define RDIST_FLAGS_FORCE_NON_SHAREABLE (1 << 2) diff --git a/drivers/irqchip/irq-gic-v3-its-msi-parent.c b/drivers/irqchip/irq-gic-its-msi-parent.c similarity index 98% rename from drivers/irqchip/irq-gic-v3-its-msi-parent.c rename to drivers/irqchip/irq-gic-its-msi-parent.c index bdb04c8081480de468fb217b68c6933a8e1e2bd7..71edcdb2defdfd5b892d86354039d2e46b832ea5 100644 --- a/drivers/irqchip/irq-gic-v3-its-msi-parent.c +++ b/drivers/irqchip/irq-gic-its-msi-parent.c @@ -7,7 +7,6 @@ #include #include -#include "irq-gic-common.h" #include "irq-msi-lib.h" #define ITS_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ @@ -200,7 +199,7 @@ static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain, return true; } -const struct msi_parent_ops gic_v3_its_msi_parent_ops = { +const struct msi_parent_ops gic_its_msi_parent_ops = { .supported_flags = ITS_MSI_FLAGS_SUPPORTED, .required_flags = ITS_MSI_FLAGS_REQUIRED, .chip_flags = MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK, diff --git a/drivers/irqchip/irq-gic-its-msi-parent.h b/drivers/irqchip/irq-gic-its-msi-parent.h new file mode 100644 index 0000000000000000000000000000000000000000..e7bb7f3862eef379e5b85fe7bd5eb72f3586d3b7 --- /dev/null +++ b/drivers/irqchip/irq-gic-its-msi-parent.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 ARM Limited, All Rights Reserved. + */ + +#ifndef _IRQ_GIC_ITS_MSI_PARENT_H +#define _IRQ_GIC_ITS_MSI_PARENT_H + +#include + +extern const struct msi_parent_ops gic_its_msi_parent_ops; + +#endif /* _IRQ_GIC_ITS_MSI_PARENT_H */ diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 0115ad6c82593de511c285d99437996919bfa308..6c51bf4e34a38103d612c74476d640cd4126e8b6 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -41,6 +41,7 @@ #include #include "irq-gic-common.h" +#include "irq-gic-its-msi-parent.h" #include "irq-msi-lib.h" #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) @@ -5139,7 +5140,7 @@ static int its_init_domain(struct its_node *its) irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS); - inner_domain->msi_parent_ops = &gic_v3_its_msi_parent_ops; + inner_domain->msi_parent_ops = &gic_its_msi_parent_ops; inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; return 0; diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c index 909ccf07879a1feb5abb65fa265706f2c276d927..3078baa57ec669db962796efe72f881342217a52 100644 --- a/drivers/irqchip/irq-gic-v5-irs.c +++ b/drivers/irqchip/irq-gic-v5-irs.c @@ -507,6 +507,30 @@ static int gicv5_irs_wait_for_idle(struct gicv5_irs_chip_data *irs_data) return ret; } +void gicv5_irs_syncr(void) +{ + u32 syncr; + u32 statusr; + int ret; + struct gicv5_irs_chip_data *irs_data; + + irs_data = list_first_entry_or_null(&irs_nodes, + struct gicv5_irs_chip_data, entry); + if (WARN_ON(!irs_data)) + return; + + syncr = FIELD_PREP(GICV5_IRS_SYNCR_SYNC, 1); + irs_writel(irs_data, syncr, GICV5_IRS_SYNCR); + + ret = readl_relaxed_poll_timeout_atomic( + irs_data->irs_base + GICV5_IRS_SYNC_STATUSR, statusr, + FIELD_GET(GICV5_IRS_SYNC_STATUSR_IDLE, statusr), 1, + USEC_PER_SEC); + + if (ret == -ETIMEDOUT) + pr_err_ratelimited("SYNCR timeout...\n"); +} + int gicv5_irs_register_cpu(int cpuid) { struct gicv5_irs_chip_data *irs_data; @@ -803,6 +827,14 @@ int __init gicv5_irs_enable(void) return 0; } +void __init gicv5_irs_its_probe(void) +{ + struct gicv5_irs_chip_data *irs_data; + + list_for_each_entry(irs_data, &irs_nodes, entry) + gicv5_its_of_probe(to_of_node(irs_data->fwnode)); +} + int __init gicv5_irs_of_probe(struct device_node *parent) { int ret; diff --git a/drivers/irqchip/irq-gic-v5-its.c b/drivers/irqchip/irq-gic-v5-its.c new file mode 100644 index 0000000000000000000000000000000000000000..f4f381e6c3af896f354e7e03bc2452b8a65cf093 --- /dev/null +++ b/drivers/irqchip/irq-gic-v5-its.c @@ -0,0 +1,1294 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024-2025 ARM Limited, All Rights Reserved. + */ + +#define pr_fmt(fmt) "GICv5 ITS: " fmt + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include "irq-gic-v5.h" +#include "irq-gic-its-msi-parent.h" +#include "irq-msi-lib.h" + +#define ITS_FLAGS_NON_COHERENT BIT(0) + +static LIST_HEAD(its_nodes); + +static u32 its_readl(struct gicv5_its_chip_data *its_node, const u64 reg_offset) +{ + return readl_relaxed(its_node->its_base + reg_offset); +} + +static void its_writel(struct gicv5_its_chip_data *its_node, const u32 val, + const u64 reg_offset) +{ + writel_relaxed(val, its_node->its_base + reg_offset); +} + +static void its_writeq(struct gicv5_its_chip_data *its_node, const u64 val, + const u64 reg_offset) +{ + writeq_relaxed(val, its_node->its_base + reg_offset); +} + +static void its_write_table_entry(struct gicv5_its_chip_data *its, + __le64 *entry, u64 val) +{ + WRITE_ONCE(*entry, val); + if (its->flags & ITS_FLAGS_NON_COHERENT) + dcache_clean_inval_poc((unsigned long)entry, + (unsigned long)entry + sizeof(*entry)); + else + dsb(ishst); +} + +static int gicv5_its_wait_for_invalidation(struct gicv5_its_chip_data *its) +{ + int ret; + u32 statusr; + + ret = readl_relaxed_poll_timeout_atomic( + its->its_base + GICV5_ITS_STATUSR, statusr, + FIELD_GET(GICV5_ITS_STATUSR_IDLE, statusr), 1, + USEC_PER_SEC); + + if (ret == -ETIMEDOUT) + pr_err_ratelimited("STATUSR timeout...\n"); + + return ret; +} + +static void gicv5_its_syncr(struct gicv5_its_chip_data *its, + struct gicv5_its_dev *its_dev) +{ + int ret; + u64 syncr; + u32 statusr; + + syncr = FIELD_PREP(GICV5_ITS_SYNCR_SYNC, 1) | + FIELD_PREP(GICV5_ITS_SYNCR_DEVICEID, its_dev->device_id); + + its_writeq(its, syncr, GICV5_ITS_SYNCR); + + ret = readl_relaxed_poll_timeout_atomic( + its->its_base + GICV5_ITS_SYNC_STATUSR, statusr, + FIELD_GET(GICV5_ITS_SYNC_STATUSR_IDLE, statusr), 1, + USEC_PER_SEC); + + if (ret == -ETIMEDOUT) + pr_err_ratelimited("SYNCR timeout...\n"); +} + +static int gicv5_its_l2sz_to_l2_bits(unsigned int sz) +{ + switch (sz) { + case GICV5_ITS_DT_ITT_CFGR_L2SZ_4k: + return 9; + case GICV5_ITS_DT_ITT_CFGR_L2SZ_16k: + return 11; + case GICV5_ITS_DT_ITT_CFGR_L2SZ_64k: + return 13; + default: + return -EINVAL; + } +} + +static int gicv5_its_itt_cache_inv(struct gicv5_its_chip_data *its, + u32 device_id, u16 event_id) +{ + u64 didr; + u32 eventr, eidr; + + didr = FIELD_PREP(GICV5_ITS_DIDR_DEVICEID, device_id); + eidr = FIELD_PREP(GICV5_ITS_EIDR_EVENTID, event_id); + eventr = FIELD_PREP(GICV5_ITS_INV_EVENTR_I, 0x1); + + its_writeq(its, didr, GICV5_ITS_DIDR); + its_writel(its, eidr, GICV5_ITS_EIDR); + its_writel(its, eventr, GICV5_ITS_INV_EVENTR); + + return gicv5_its_wait_for_invalidation(its); +} + +static void gicv5_its_free_itt_linear(struct gicv5_its_dev *its_dev) +{ + kfree(its_dev->itt_cfg.linear.itt); +} + +static void gicv5_its_free_itt_two_level(struct gicv5_its_dev *its_dev) +{ + unsigned int i, num_ents = its_dev->itt_cfg.l2.num_l1_ents; + + for (i = 0; i < num_ents; i++) + kfree(its_dev->itt_cfg.l2.l2ptrs[i]); + + kfree(its_dev->itt_cfg.l2.l2ptrs); + kfree(its_dev->itt_cfg.l2.l1itt); +} + +static void gicv5_its_free_itt(struct gicv5_its_dev *its_dev) +{ + if (!its_dev->itt_cfg.l2itt) + gicv5_its_free_itt_linear(its_dev); + else + gicv5_its_free_itt_two_level(its_dev); +} + +static int gicv5_its_create_itt_linear(struct gicv5_its_chip_data *its, + struct gicv5_its_dev *its_dev, + unsigned int event_id_bits) +{ + __le64 *itt; + unsigned int num_ents = BIT(event_id_bits); + + itt = kcalloc(num_ents, sizeof(*itt), GFP_KERNEL); + if (!itt) + return -ENOMEM; + + its_dev->itt_cfg.linear.itt = itt; + its_dev->itt_cfg.linear.num_ents = num_ents; + its_dev->itt_cfg.l2itt = false; + its_dev->itt_cfg.event_id_bits = event_id_bits; + + if (its->flags & ITS_FLAGS_NON_COHERENT) + dcache_clean_inval_poc((unsigned long)itt, + (unsigned long)itt + num_ents * sizeof(*itt)); + else + dsb(ishst); + + return 0; +} + +/* + * Allocate a two-level ITT. All ITT entries are allocated in one go, unlike + * with the device table. Span may be used to limit the second level table + * size, where possible. + */ +static int gicv5_its_create_itt_two_level(struct gicv5_its_chip_data *its, + struct gicv5_its_dev *its_dev, + unsigned int event_id_bits, + unsigned int itt_l2sz, + unsigned int num_events) +{ + u64 val; + int ret, i; + __le64 *itt_l1, *itt_l2, **l2ptrs; + unsigned int l1_bits, l2_bits, span, events_per_l2_table, + complete_tables, final_span, num_ents; + + ret = gicv5_its_l2sz_to_l2_bits(itt_l2sz); + if (ret < 0 || ret >= event_id_bits) { + pr_debug("Incorrect l2sz (0x%x) for %u EventID bits. Cannot allocate ITT\n", + itt_l2sz, event_id_bits); + return -EINVAL; + } + + l2_bits = ret; + + l1_bits = event_id_bits - l2_bits; + + num_ents = BIT(l1_bits); + + itt_l1 = kcalloc(num_ents, sizeof(*itt_l1), GFP_KERNEL); + if (!itt_l1) + return -ENOMEM; + + l2ptrs = kcalloc(num_ents, sizeof(*l2ptrs), GFP_KERNEL); + if (!l2ptrs) { + kfree(itt_l1); + return -ENOMEM; + } + + its_dev->itt_cfg.l2.l2ptrs = l2ptrs; + + its_dev->itt_cfg.l2.l2sz = itt_l2sz; + its_dev->itt_cfg.l2.l1itt = itt_l1; + its_dev->itt_cfg.l2.num_l1_ents = num_ents; + its_dev->itt_cfg.l2itt = true; + its_dev->itt_cfg.event_id_bits = event_id_bits; + + /* + * Need to determine how many entries there are per L2 - this is based + * on the number of bits in the table. + */ + events_per_l2_table = BIT(l2_bits); + complete_tables = num_events / events_per_l2_table; + final_span = order_base_2(num_events % events_per_l2_table); + + for (i = 0; i < num_ents; i++) { + size_t l2sz; + + span = i == complete_tables ? final_span : l2_bits; + + itt_l2 = kcalloc(BIT(span), sizeof(*itt_l2), GFP_KERNEL); + if (!itt_l2) { + ret = -ENOMEM; + goto out_free; + } + + its_dev->itt_cfg.l2.l2ptrs[i] = itt_l2; + + l2sz = BIT(span) * sizeof(*itt_l2); + + if (its->flags & ITS_FLAGS_NON_COHERENT) + dcache_clean_inval_poc((unsigned long)itt_l2, + (unsigned long)itt_l2 + l2sz); + + val = (virt_to_phys(itt_l2) & GICV5_ITTL1E_L2_ADDR_MASK) | + FIELD_PREP(GICV5_ITTL1E_SPAN, span) | + FIELD_PREP(GICV5_ITTL1E_VALID, 0x1); + + WRITE_ONCE(itt_l1[i], cpu_to_le64(val)); + } + + if (its->flags & ITS_FLAGS_NON_COHERENT) + dcache_clean_inval_poc((unsigned long)itt_l1, + (unsigned long)itt_l1 + num_ents * sizeof(*itt_l1)); + else + dsb(ishst); + + return 0; +out_free: + for (i = i - 1; i >= 0; i--) + kfree(its_dev->itt_cfg.l2.l2ptrs[i]); + + kfree(its_dev->itt_cfg.l2.l2ptrs); + kfree(itt_l1); + return ret; +} + +/* + * Function to check whether the device table or ITT table support + * a two-level table and if so depending on the number of id_bits + * requested, determine whether a two-level table is required. + * + * Return the 2-level size value if a two level table is deemed + * necessary. + */ +static bool gicv5_its_l2sz_two_level(bool devtab, u32 its_idr1, u8 id_bits, + u8 *sz) +{ + int l2_bits, l2_sz = -EINVAL; + + if (devtab && !FIELD_GET(GICV5_ITS_IDR1_DT_LEVELS, its_idr1)) + return false; + + if (!devtab && !FIELD_GET(GICV5_ITS_IDR1_ITT_LEVELS, its_idr1)) + return false; + + /* + * Pick an L2 size that matches the pagesize; if a match + * is not found, go for the smallest supported l2 size granule. + * + * This ensures that we will always be able to allocate + * contiguous memory at L2. + */ + switch (PAGE_SIZE) { + case SZ_64K: + if (GICV5_ITS_IDR1_L2SZ_SUPPORT_64KB(its_idr1)) { + l2_sz = GICV5_ITS_DT_ITT_CFGR_L2SZ_64k; + break; + } + fallthrough; + case SZ_16K: + if (GICV5_ITS_IDR1_L2SZ_SUPPORT_16KB(its_idr1)) { + l2_sz = GICV5_ITS_DT_ITT_CFGR_L2SZ_16k; + break; + } + fallthrough; + case SZ_4K: + if (GICV5_ITS_IDR1_L2SZ_SUPPORT_4KB(its_idr1)) { + l2_sz = GICV5_ITS_DT_ITT_CFGR_L2SZ_4k; + break; + } + if (GICV5_ITS_IDR1_L2SZ_SUPPORT_16KB(its_idr1)) { + l2_sz = GICV5_ITS_DT_ITT_CFGR_L2SZ_16k; + break; + } + if (GICV5_ITS_IDR1_L2SZ_SUPPORT_64KB(its_idr1)) { + l2_sz = GICV5_ITS_DT_ITT_CFGR_L2SZ_64k; + break; + } + break; + } + + l2_bits = gicv5_its_l2sz_to_l2_bits(l2_sz); + + if (l2_bits < 0 || l2_bits > id_bits) + return false; + + *sz = l2_sz; + + return true; +} + +static int gicv5_its_device_get_itte_ref(struct gicv5_its_dev *its_dev, + __le64 **itte, u16 event_id) +{ + if (!its_dev->itt_cfg.l2itt) { + __le64 *itt = its_dev->itt_cfg.linear.itt; + *itte = &itt[event_id]; + } else { + unsigned int l1_idx, l2_idx, l2_size, l2_bits; + __le64 *l2_itt, *l1_itt = its_dev->itt_cfg.l2.l1itt; + int ret; + + ret = gicv5_its_l2sz_to_l2_bits(its_dev->itt_cfg.l2.l2sz); + if (ret < 0) + return ret; + l2_bits = ret; + + l1_idx = event_id >> l2_bits; + + if (!FIELD_GET(GICV5_ITTL1E_VALID, + le64_to_cpu(l1_itt[l1_idx]))) { + pr_debug("L1 ITT entry is not valid.\n"); + return -EINVAL; + } + + l2_idx = event_id & GENMASK(l2_bits - 1, 0); + + l2_size = BIT(FIELD_GET(GICV5_ITTL1E_SPAN, + le64_to_cpu(l1_itt[l1_idx]))); + + // Sanity check our indexing + if (l2_idx >= l2_size) { + pr_debug("L2 ITT index (%u) exceeds L2 table size (%u)!\n", + l2_idx, l2_size); + return -EINVAL; + } + l2_itt = its_dev->itt_cfg.l2.l2ptrs[l1_idx]; + *itte = &l2_itt[l2_idx]; + } + + return 0; +} + +static int gicv5_its_device_cache_inv(struct gicv5_its_chip_data *its, + struct gicv5_its_dev *its_dev) +{ + u32 devicer; + u64 didr; + + didr = FIELD_PREP(GICV5_ITS_DIDR_DEVICEID, its_dev->device_id); + devicer = FIELD_PREP(GICV5_ITS_INV_DEVICER_I, 0x1) | + FIELD_PREP(GICV5_ITS_INV_DEVICER_EVENTID_BITS, + its_dev->itt_cfg.event_id_bits) | + FIELD_PREP(GICV5_ITS_INV_DEVICER_L1, 0x0); + its_writeq(its, didr, GICV5_ITS_DIDR); + its_writel(its, devicer, GICV5_ITS_INV_DEVICER); + + return gicv5_its_wait_for_invalidation(its); +} + +/* + * Allocate a level 2 device table entry, update L1 parent to reference it. + * Only used for 2-level device tables, and it is called on demand. + */ +static int gicv5_its_alloc_l2_devtab(struct gicv5_its_chip_data *its, + unsigned int l1_index) +{ + int ret; + u64 l1dte; + u8 span, l2sz, l2_bits; + __le64 *l2devtab, *l1devtab = its->devtab_cfgr.l2.l1devtab; + + if (FIELD_GET(GICV5_DTL1E_VALID, le64_to_cpu(l1devtab[l1_index]))) + return 0; + + span = FIELD_GET(GICV5_DTL1E_SPAN, le64_to_cpu(l1devtab[l1_index])); + l2sz = FIELD_GET(GICV5_ITS_DT_CFGR_L2SZ, its->devtab_cfgr.cfgr); + + ret = gicv5_its_l2sz_to_l2_bits(l2sz); + if (ret < 0) + return ret; + + l2_bits = ret; + + /* + * Span allows us to create a smaller L2 device table. + * If it is too large, use the number of allowed L2 bits. + */ + if (span > l2_bits) + span = l2_bits; + + l2devtab = kcalloc(BIT(span), sizeof(*l2devtab), GFP_KERNEL); + if (!l2devtab) + return -ENOMEM; + + its->devtab_cfgr.l2.l2ptrs[l1_index] = l2devtab; + + l1dte = FIELD_PREP(GICV5_DTL1E_SPAN, span) | + (virt_to_phys(l2devtab) & GICV5_DTL1E_L2_ADDR_MASK) | + FIELD_PREP(GICV5_DTL1E_VALID, 0x1); + its_write_table_entry(its, &l1devtab[l1_index], cpu_to_le64(l1dte)); + + return 0; +} + +static int gicv5_its_devtab_get_dte_ref(struct gicv5_its_chip_data *its, + __le64 **dte, u32 device_id, + bool alloc) +{ + int ret; + __le64 *l1devtab, *l2devtab; + unsigned int l2sz, l2_bits, l1_idx, l2_idx; + u8 str = FIELD_GET(GICV5_ITS_DT_CFGR_STRUCTURE, its->devtab_cfgr.cfgr); + + if (str == GICV5_ITS_DT_ITT_CFGR_STRUCTURE_LINEAR) { + l2devtab = its->devtab_cfgr.linear.devtab; + *dte = &l2devtab[device_id]; + } else { + l2sz = FIELD_GET(GICV5_ITS_DT_CFGR_L2SZ, its->devtab_cfgr.cfgr); + l1devtab = its->devtab_cfgr.l2.l1devtab; + + ret = gicv5_its_l2sz_to_l2_bits(l2sz); + if (ret < 0) + return -EINVAL; + + l2_bits = ret; + l1_idx = device_id >> l2_bits; + l2_idx = device_id & GENMASK(l2_bits - 1, 0); + + if (alloc) { + /* + * Allocate a new L2 device table here before + * continuing. We make the assumption that the span in + * the L1 table has been set correctly, and blindly use + * that value. + */ + ret = gicv5_its_alloc_l2_devtab(its, l1_idx); + if (ret) + return ret; + } else { + if (!FIELD_GET(GICV5_DTL1E_VALID, + le64_to_cpu(l1devtab[l1_idx]))) + return -EINVAL; + } + + + l2devtab = its->devtab_cfgr.l2.l2ptrs[l1_idx]; + *dte = &l2devtab[l2_idx]; + } + + return 0; +} + +/* + * Register a new device in the device table. Allocate an ITT and + * program the L2DTE entry according to the ITT structure that + * was chosen. + */ +static int gicv5_its_device_register(struct gicv5_its_chip_data *its, + struct gicv5_its_dev *its_dev) +{ + u8 event_id_bits, device_id_bits, itt_struct, itt_l2sz; + phys_addr_t itt_phys_base; + u32 idr1, idr2; + bool two_level_itt; + __le64 *dte; + int ret; + u64 val; + + device_id_bits = FIELD_GET(GICV5_ITS_DT_CFGR_DEVICEID_BITS, + its->devtab_cfgr.cfgr); + + if (its_dev->device_id >= BIT(device_id_bits)) { + pr_err("Supplied DeviceID (%u) outside of Device Table range (%u)!", + its_dev->device_id, (u32)GENMASK(device_id_bits - 1, 0)); + return -EINVAL; + } + + ret = gicv5_its_devtab_get_dte_ref(its, &dte, its_dev->device_id, true); + if (ret) + return ret; + + if (FIELD_GET(GICV5_DTL2E_VALID, le64_to_cpu(*dte))) + return -EBUSY; + + /* + * Determine how many bits we need, validate those against the max. + * Based on these, determine if we should go for a 1- or 2-level ITT. + */ + event_id_bits = order_base_2(its_dev->num_events); + + idr2 = its_readl(its, GICV5_ITS_IDR2); + + if (event_id_bits > FIELD_GET(GICV5_ITS_IDR2_EVENTID_BITS, idr2)) { + pr_err("Required EventID bits (%u) larger than supported bits (%u)!", + event_id_bits, + (u8)FIELD_GET(GICV5_ITS_IDR2_EVENTID_BITS, idr2)); + return -EINVAL; + } + + idr1 = its_readl(its, GICV5_ITS_IDR1); + + /* + * L2 ITT size is programmed into the L2DTE regardless of + * whether a two-level or linear ITT is built, init it. + */ + itt_l2sz = 0; + + two_level_itt = gicv5_its_l2sz_two_level(false, idr1, event_id_bits, + &itt_l2sz); + if (two_level_itt) + ret = gicv5_its_create_itt_two_level(its, its_dev, event_id_bits, + itt_l2sz, + its_dev->num_events); + else + ret = gicv5_its_create_itt_linear(its, its_dev, event_id_bits); + if (ret) + return ret; + + itt_phys_base = two_level_itt ? + virt_to_phys(its_dev->itt_cfg.l2.l1itt) : + virt_to_phys(its_dev->itt_cfg.linear.itt); + + itt_struct = two_level_itt ? GICV5_ITS_DT_ITT_CFGR_STRUCTURE_TWO_LEVEL : + GICV5_ITS_DT_ITT_CFGR_STRUCTURE_LINEAR; + + val = FIELD_PREP(GICV5_DTL2E_EVENT_ID_BITS, event_id_bits) | + FIELD_PREP(GICV5_DTL2E_ITT_STRUCTURE, itt_struct) | + (itt_phys_base & GICV5_DTL2E_ITT_ADDR_MASK) | + FIELD_PREP(GICV5_DTL2E_ITT_L2SZ, itt_l2sz) | + FIELD_PREP(GICV5_DTL2E_VALID, 0x1); + + its_write_table_entry(its, dte, cpu_to_le64(val)); + + ret = gicv5_its_device_cache_inv(its, its_dev); + if (ret) { + gicv5_its_free_itt(its_dev); + its_write_table_entry(its, dte, 0); + return ret; + } + + return 0; +} + +/* + * Unregister a device in the device table. Lookup the device by ID, free the + * corresponding ITT, mark the device as invalid in the device table. + */ +static int gicv5_its_device_unregister(struct gicv5_its_chip_data *its, + struct gicv5_its_dev *its_dev) +{ + int ret; + __le64 *dte; + + ret = gicv5_its_devtab_get_dte_ref(its, &dte, its_dev->device_id, false); + if (ret) { + pr_debug("Failed to find DTE for DeviceID 0x%x\n", its_dev->device_id); + return -EINVAL; + } + + if (!FIELD_GET(GICV5_DTL2E_VALID, le64_to_cpu(*dte))) { + pr_debug("Device table entry for DeviceID 0x%x is not valid. Nothing to clean up!", + its_dev->device_id); + return -EINVAL; + } + + gicv5_its_free_itt(its_dev); + + /* Zero everything - make it clear that this is an invalid entry */ + its_write_table_entry(its, dte, 0); + + return gicv5_its_device_cache_inv(its, its_dev); +} + +/* + * Allocate a 1-level device table. All entries are allocated, but marked + * invalid. + */ +static int gicv5_its_alloc_devtab_linear(struct gicv5_its_chip_data *its, + u8 device_id_bits) +{ + u32 cfgr; + u64 baser; + size_t sz; + __le64 *devtab; + + sz = BIT_ULL(device_id_bits) * sizeof(*devtab); + if (sz > KMALLOC_MAX_SIZE) { + u8 device_id_cap = ilog2(KMALLOC_MAX_SIZE/sizeof(*devtab)); + + pr_warn("Limiting device ID bits from %u to %u\n", + device_id_bits, device_id_cap); + device_id_bits = device_id_cap; + } + + devtab = kcalloc(BIT(device_id_bits), sizeof(*devtab), GFP_KERNEL); + if (!devtab) + return -ENOMEM; + + if (its->flags & ITS_FLAGS_NON_COHERENT) + dcache_clean_inval_poc((unsigned long)devtab, + (unsigned long)devtab + sz); + else + dsb(ishst); + + cfgr = FIELD_PREP(GICV5_ITS_DT_CFGR_STRUCTURE, + GICV5_ITS_DT_ITT_CFGR_STRUCTURE_LINEAR) | + FIELD_PREP(GICV5_ITS_DT_CFGR_L2SZ, 0) | + FIELD_PREP(GICV5_ITS_DT_CFGR_DEVICEID_BITS, device_id_bits); + its_writel(its, cfgr, GICV5_ITS_DT_CFGR); + + baser = virt_to_phys(devtab) & GICV5_ITS_DT_BASER_ADDR_MASK; + its_writeq(its, baser, GICV5_ITS_DT_BASER); + + its->devtab_cfgr.cfgr = cfgr; + its->devtab_cfgr.linear.devtab = devtab; + + return 0; +} + +/* + * Allocate a 2-level device table. L2 entries are not allocated, + * they are allocated on-demand. + */ +static int gicv5_its_alloc_devtab_two_level(struct gicv5_its_chip_data *its, + u8 device_id_bits, + u8 devtab_l2sz) +{ + int ret; + u64 baser; + u32 cfgr; + size_t l1_sz; + __le64 *l1devtab, **l2ptrs; + unsigned int l1_bits, l2_bits, i; + + ret = gicv5_its_l2sz_to_l2_bits(devtab_l2sz); + if (ret < 0) + return ret; + + l2_bits = ret; + + l1_bits = device_id_bits - l2_bits; + l1_sz = BIT(l1_bits) * sizeof(*l1devtab); + if (l1_sz > KMALLOC_MAX_SIZE) { + l1_bits = ilog2(KMALLOC_MAX_SIZE/sizeof(*l1devtab)); + + pr_warn("Limiting device ID bits from %u to %u\n", + device_id_bits, l1_bits + l2_bits); + device_id_bits = l1_bits + l2_bits; + l1_sz = KMALLOC_MAX_SIZE; + } + + l1devtab = kcalloc(BIT(l1_bits), sizeof(*l1devtab), GFP_KERNEL); + if (!l1devtab) + return -ENOMEM; + + l2ptrs = kcalloc(BIT(l1_bits), sizeof(*l2ptrs), GFP_KERNEL); + if (!l2ptrs) { + kfree(l1devtab); + return -ENOMEM; + } + + for (i = 0; i < BIT(l1_bits); i++) + l1devtab[i] = cpu_to_le64(FIELD_PREP(GICV5_DTL1E_SPAN, l2_bits)); + + if (its->flags & ITS_FLAGS_NON_COHERENT) + dcache_clean_inval_poc((unsigned long)l1devtab, + (unsigned long)l1devtab + l1_sz); + else + dsb(ishst); + + cfgr = FIELD_PREP(GICV5_ITS_DT_CFGR_STRUCTURE, + GICV5_ITS_DT_ITT_CFGR_STRUCTURE_TWO_LEVEL) | + FIELD_PREP(GICV5_ITS_DT_CFGR_L2SZ, devtab_l2sz) | + FIELD_PREP(GICV5_ITS_DT_CFGR_DEVICEID_BITS, device_id_bits); + its_writel(its, cfgr, GICV5_ITS_DT_CFGR); + + baser = virt_to_phys(l1devtab) & GICV5_ITS_DT_BASER_ADDR_MASK; + its_writeq(its, baser, GICV5_ITS_DT_BASER); + + its->devtab_cfgr.cfgr = cfgr; + its->devtab_cfgr.l2.l1devtab = l1devtab; + its->devtab_cfgr.l2.l2ptrs = l2ptrs; + + return 0; +} + +/* + * Initialise the device table as either 1- or 2-level depending on what is + * supported by the hardware. + */ +static int gicv5_its_init_devtab(struct gicv5_its_chip_data *its) +{ + u32 idr1; + bool two_level_devtab; + u8 device_id_bits, devtab_l2sz; + + idr1 = its_readl(its, GICV5_ITS_IDR1); + + device_id_bits = FIELD_GET(GICV5_ITS_IDR1_DEVICEID_BITS, idr1); + two_level_devtab = gicv5_its_l2sz_two_level(true, idr1, device_id_bits, + &devtab_l2sz); + if (two_level_devtab) + return gicv5_its_alloc_devtab_two_level(its, device_id_bits, + devtab_l2sz); + else + return gicv5_its_alloc_devtab_linear(its, device_id_bits); +} + +static void gicv5_its_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) +{ + u64 addr; + struct gicv5_its_dev *its_dev = irq_data_get_irq_chip_data(d); + struct gicv5_its_chip_data *its = its_dev->its_node; + + addr = its->its_trans_phys_base; + + msg->data = FIELD_GET(GICV5_ITS_HWIRQ_EVENT_ID, d->hwirq); + msi_msg_set_addr(irq_data_get_msi_desc(d), msg, addr); +} + +static const struct irq_chip gicv5_its_irq_chip = { + .name = "GICv5-ITS-MSI", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, + .irq_get_irqchip_state = irq_chip_get_parent_state, + .irq_set_irqchip_state = irq_chip_set_parent_state, + .irq_compose_msi_msg = gicv5_its_compose_msi_msg, + .flags = IRQCHIP_SET_TYPE_MASKED | + IRQCHIP_SKIP_SET_WAKE | + IRQCHIP_MASK_ON_SUSPEND +}; + +static struct gicv5_its_dev *gicv5_its_find_device( + struct gicv5_its_chip_data *its, u32 device_id) +{ + struct gicv5_its_dev *dev = xa_load(&its->its_devices, device_id); + + return dev ? dev : ERR_PTR(-ENODEV); +} + +static struct gicv5_its_dev *gicv5_its_alloc_device( + struct gicv5_its_chip_data *its, int nvec, + u32 dev_id) +{ + int ret; + struct gicv5_its_dev *its_dev; + + its_dev = gicv5_its_find_device(its, dev_id); + if (!IS_ERR(its_dev)) { + pr_debug("A device with this DeviceID (0x%x) has already been registered.\n", + dev_id); + + if (nvec > its_dev->num_events) { + pr_debug("Requesting more ITT entries than allocated\n"); + return ERR_PTR(-ENXIO); + } + + its_dev->shared = true; + + return its_dev; + } + + its_dev = kzalloc(sizeof(*its_dev), GFP_KERNEL); + if (!its_dev) + return ERR_PTR(-ENOMEM); + + its_dev->device_id = dev_id; + its_dev->num_events = nvec; + its_dev->num_mapped_events = 0; + + ret = gicv5_its_device_register(its, its_dev); + if (ret) { + pr_debug("Failed to register the device\n"); + kfree(its_dev); + return ERR_PTR(ret); + } + + gicv5_its_device_cache_inv(its, its_dev); + + /* + * This is the first time we have seen this device. Hence, it is not + * shared. + */ + its_dev->shared = false; + + its_dev->its_node = its; + + its_dev->event_map = + (unsigned long *)bitmap_zalloc(its_dev->num_events, GFP_KERNEL); + if (!its_dev->event_map) { + gicv5_its_device_unregister(its, its_dev); + kfree(its_dev); + return ERR_PTR(-ENOMEM); + } + + xa_store(&its->its_devices, dev_id, its_dev, GFP_KERNEL); + + return its_dev; +} + +static int gicv5_its_msi_prepare(struct irq_domain *domain, struct device *dev, + int nvec, msi_alloc_info_t *info) +{ + struct msi_domain_info *msi_info; + struct gicv5_its_chip_data *its; + struct gicv5_its_dev *its_dev; + u32 dev_id = info->scratchpad[0].ul; + + msi_info = msi_get_domain_info(domain); + its = msi_info->data; + + guard(mutex)(&its->dev_alloc_lock); + + its_dev = gicv5_its_alloc_device(its, nvec, dev_id); + if (IS_ERR(its_dev)) + return PTR_ERR(its_dev); + + if (info->flags & MSI_ALLOC_FLAGS_PROXY_DEVICE) + its_dev->shared = true; + + return 0; +} + +static struct msi_domain_ops its_msi_domain_ops = { + .msi_prepare = gicv5_its_msi_prepare, +}; + +static int gicv5_its_alloc_event(struct gicv5_its_dev *its_dev, u16 event_id, + u32 lpi) +{ + int ret; + __le64 *itte; + u64 itt_entry; + struct gicv5_its_chip_data *its = its_dev->its_node; + + if (event_id >= its_dev->num_events) { + pr_debug("EventID 0x%x outside of ITT range (0x%x)\n", event_id, + its_dev->num_events); + return -EINVAL; + } + + if (WARN(its_dev->num_mapped_events == its_dev->num_events, + "Reached maximum number of events\n")) + return -EINVAL; + + ret = gicv5_its_device_get_itte_ref(its_dev, &itte, event_id); + if (ret) + return ret; + + if (FIELD_GET(GICV5_ITTL2E_VALID, *itte)) + return -EEXIST; + + itt_entry = FIELD_PREP(GICV5_ITTL2E_LPI_ID, lpi) | + FIELD_PREP(GICV5_ITTL2E_VALID, 0x1); + + its_write_table_entry(its, itte, cpu_to_le64(itt_entry)); + + gicv5_its_itt_cache_inv(its, its_dev->device_id, event_id); + + its_dev->num_mapped_events += 1; + + return 0; +} + +static void gicv5_its_free_event(struct gicv5_its_dev *its_dev, u16 event_id) +{ + int ret; + __le64 *itte; + u64 itte_val; + struct gicv5_its_chip_data *its = its_dev->its_node; + + if (WARN(!its_dev->num_mapped_events, "No mapped events\n")) + return; + + ret = gicv5_its_device_get_itte_ref(its_dev, &itte, event_id); + if (ret) { + pr_debug("Failed to get the ITTE!\n"); + return; + } + + itte_val = le64_to_cpu(*itte); + itte_val &= ~GICV5_ITTL2E_VALID; + + its_write_table_entry(its, itte, cpu_to_le64(itte_val)); + + gicv5_its_itt_cache_inv(its, its_dev->device_id, event_id); + + its_dev->num_mapped_events -= 1; +} + +static int gicv5_its_alloc_eventid(struct gicv5_its_dev *its_dev, + unsigned int nr_irqs, u32 *eventid) +{ + int ret; + + ret = bitmap_find_free_region(its_dev->event_map, + its_dev->num_events, + get_count_order(nr_irqs)); + + if (ret < 0) + return ret; + + *eventid = ret; + + return 0; +} + +static void gicv5_its_free_eventid(struct gicv5_its_dev *its_dev, + u32 event_id_base, + unsigned int nr_irqs) +{ + bitmap_release_region(its_dev->event_map, event_id_base, + get_count_order(nr_irqs)); +} + +static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs, + void *arg) +{ + int ret, i; + irq_hw_number_t hwirq; + struct irq_data *irqd; + struct gicv5_its_dev *its_dev; + struct gicv5_its_chip_data *its; + u32 event_id_base, lpi_base, lpi; + struct msi_domain_info *msi_info; + msi_alloc_info_t *info = arg; + unsigned long device_id = info->scratchpad[0].ul; + + msi_info = msi_get_domain_info(domain); + its = msi_info->data; + + guard(mutex)(&its->dev_alloc_lock); + + its_dev = gicv5_its_find_device(its, device_id); + if (IS_ERR(its_dev)) + return PTR_ERR(its_dev); + + ret = gicv5_its_alloc_eventid(its_dev, nr_irqs, &event_id_base); + if (ret) + return ret; + + ret = iommu_dma_prepare_msi(info->desc, + its->its_trans_phys_base); + if (ret) + goto out_eventid; + + ret = gicv5_alloc_lpi_range(nr_irqs, &lpi_base); + if (ret) { + pr_debug("Failed to find free LPIs!\n"); + goto out_eventid; + } + + for (i = 0; i < nr_irqs; i++) { + lpi = lpi_base + i; + + ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, &lpi); + if (ret) + goto out_free_lpi; + + /* + * Store eventid and deviceid into the hwirq for later use. + * + * hwirq = event_id << 32 | device_id + */ + hwirq = FIELD_PREP(GICV5_ITS_HWIRQ_DEVICE_ID, device_id) | + FIELD_PREP(GICV5_ITS_HWIRQ_EVENT_ID, + (u64)event_id_base + i); + irq_domain_set_info(domain, virq + i, hwirq, + &gicv5_its_irq_chip, its_dev, + handle_fasteoi_irq, NULL, NULL); + + irqd = irq_get_irq_data(virq + i); + irqd_set_single_target(irqd); + irqd_set_affinity_on_activate(irqd); + irqd_set_resend_when_in_progress(irqd); + } + + return 0; + +out_free_lpi: + gicv5_free_lpi_range(lpi_base, nr_irqs); +out_eventid: + gicv5_its_free_eventid(its_dev, event_id_base, nr_irqs); + + return ret; +} + +static void gicv5_its_irq_domain_free(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs) +{ + int i; + u16 event_id_base; + u32 device_id; + bool free_device; + struct irq_data *d; + struct gicv5_its_dev *its_dev; + struct msi_domain_info *msi_info; + struct gicv5_its_chip_data *its; + + msi_info = msi_get_domain_info(domain); + its = msi_info->data; + + d = irq_domain_get_irq_data(domain, virq); + device_id = FIELD_GET(GICV5_ITS_HWIRQ_DEVICE_ID, d->hwirq); + event_id_base = FIELD_GET(GICV5_ITS_HWIRQ_EVENT_ID, d->hwirq); + + guard(mutex)(&its->dev_alloc_lock); + + its_dev = gicv5_its_find_device(its, device_id); + if (IS_ERR(its_dev)) { + pr_debug("Couldn't find the ITS device!\n"); + return; + } + + bitmap_release_region(its_dev->event_map, event_id_base, + get_count_order(nr_irqs)); + + free_device = !its_dev->shared && bitmap_empty(its_dev->event_map, + its_dev->num_events); + + /* Hierarchically free irq data */ + for (i = 0; i < nr_irqs; i++) { + d = irq_domain_get_irq_data(domain, virq + i); + + WARN_ON(gicv5_free_lpi_range(d->parent_data->hwirq, 1)); + irq_domain_reset_irq_data(d); + } + irq_domain_free_irqs_parent(domain, virq, nr_irqs); + + gicv5_its_syncr(its, its_dev); + gicv5_irs_syncr(); + + if (free_device) { + gicv5_its_device_unregister(its, its_dev); + bitmap_free(its_dev->event_map); + xa_erase(&its->its_devices, device_id); + kfree(its_dev); + } +} + +static int gicv5_its_irq_domain_activate(struct irq_domain *domain, + struct irq_data *d, bool reserve) +{ + u16 event_id; + u32 lpi; + struct gicv5_its_dev *its_dev = irq_data_get_irq_chip_data(d); + + event_id = FIELD_GET(GICV5_ITS_HWIRQ_EVENT_ID, d->hwirq); + lpi = d->parent_data->hwirq; + + return gicv5_its_alloc_event(its_dev, event_id, lpi); +} + +static void gicv5_its_irq_domain_deactivate(struct irq_domain *domain, + struct irq_data *d) +{ + u16 event_id; + struct gicv5_its_dev *its_dev = irq_data_get_irq_chip_data(d); + + event_id = FIELD_GET(GICV5_ITS_HWIRQ_EVENT_ID, d->hwirq); + + gicv5_its_free_event(its_dev, event_id); +} +static const struct irq_domain_ops gicv5_its_irq_domain_ops = { + .alloc = gicv5_its_irq_domain_alloc, + .free = gicv5_its_irq_domain_free, + .activate = gicv5_its_irq_domain_activate, + .deactivate = gicv5_its_irq_domain_deactivate, + .select = msi_lib_irq_domain_select, +}; + +static int gicv5_its_wait_for_idle(struct gicv5_its_chip_data *its) +{ + int ret; + u32 cr0; + + ret = readl_relaxed_poll_timeout_atomic( + its->its_base + GICV5_ITS_CR0, cr0, + FIELD_GET(GICV5_ITS_CR0_IDLE, cr0), 1, + USEC_PER_SEC); + + if (ret == -ETIMEDOUT) + pr_err_ratelimited("GICv5 ITS CR0 timeout...\n"); + + return ret; +} + +static void gicv5_its_print_info(struct gicv5_its_chip_data *its_node) +{ + u8 str; + bool devtab_linear; + u8 device_id_bits = FIELD_GET(GICV5_ITS_DT_CFGR_DEVICEID_BITS, + its_node->devtab_cfgr.cfgr); + + str = FIELD_GET(GICV5_ITS_DT_CFGR_STRUCTURE, its_node->devtab_cfgr.cfgr); + devtab_linear = (str == GICV5_ITS_DT_ITT_CFGR_STRUCTURE_LINEAR); + + pr_info("ITS %s enabled using %s device table device_id_bits %u\n", + fwnode_get_name(its_node->fwnode), + devtab_linear ? "linear" : "2-level", + device_id_bits); +} + +static int __init gicv5_its_init_bases(phys_addr_t its_trans_base, + void __iomem *its_base, + struct fwnode_handle *handle, + struct irq_domain *parent_domain) + +{ + int ret; + bool enabled; + u32 cr0, cr1; + struct gicv5_its_chip_data *its_node; + struct msi_domain_info *info; + struct device_node *np = to_of_node(handle); + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + its_node = kzalloc(sizeof(*its_node), GFP_KERNEL); + if (!its_node) { + kfree(info); + return -ENOMEM; + } + + info->ops = &its_msi_domain_ops; + info->data = its_node; + + mutex_init(&its_node->dev_alloc_lock); + xa_init(&its_node->its_devices); + its_node->fwnode = handle; + its_node->its_base = its_base; + its_node->its_trans_phys_base = its_trans_base; + + its_node->domain = irq_domain_create_hierarchy( + parent_domain, IRQ_DOMAIN_FLAG_ISOLATED_MSI, 0, handle, + &gicv5_its_irq_domain_ops, info); + irq_domain_update_bus_token(its_node->domain, + DOMAIN_BUS_NEXUS); + + its_node->domain->msi_parent_ops = &gic_its_msi_parent_ops; + its_node->domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; + + cr0 = its_readl(its_node, GICV5_ITS_CR0); + enabled = FIELD_GET(GICV5_ITS_CR0_ITSEN, cr0); + if (WARN(enabled, "ITS %s enabled, disabling it before proceeding\n", + np->full_name)) { + cr0 = FIELD_PREP(GICV5_ITS_CR0_ITSEN, 0x0); + its_writel(its_node, cr0, GICV5_ITS_CR0); + ret = gicv5_its_wait_for_idle(its_node); + if (ret) { + irq_domain_remove(its_node->domain); + kfree(info); + kfree(its_node); + return ret; + } + } + + if (of_property_read_bool(np, "dma-noncoherent")) { + /* + * A non-coherent ITS implies that some cache levels cannot be + * used coherently by the cores and GIC. Our only option is to mark + * memory attributes for the GIC as non-cacheable; by default, + * non-cacheable memory attributes imply outer-shareable + * shareability, the value written into ITS_CR1_SH is ignored. + */ + cr1 = FIELD_PREP(GICV5_ITS_CR1_ITT_RA, GICV5_NO_READ_ALLOC) | + FIELD_PREP(GICV5_ITS_CR1_DT_RA, GICV5_NO_READ_ALLOC) | + FIELD_PREP(GICV5_ITS_CR1_IC, GICV5_NON_CACHE) | + FIELD_PREP(GICV5_ITS_CR1_OC, GICV5_NON_CACHE); + its_node->flags |= ITS_FLAGS_NON_COHERENT; + } else { + cr1 = FIELD_PREP(GICV5_ITS_CR1_ITT_RA, GICV5_READ_ALLOC) | + FIELD_PREP(GICV5_ITS_CR1_DT_RA, GICV5_READ_ALLOC) | + FIELD_PREP(GICV5_ITS_CR1_IC, GICV5_WB_CACHE) | + FIELD_PREP(GICV5_ITS_CR1_OC, GICV5_WB_CACHE) | + FIELD_PREP(GICV5_ITS_CR1_SH, GICV5_INNER_SHARE); + } + + its_writel(its_node, cr1, GICV5_ITS_CR1); + + ret = gicv5_its_init_devtab(its_node); + if (ret) { + irq_domain_remove(its_node->domain); + kfree(info); + kfree(its_node); + return ret; + } + + cr0 = FIELD_PREP(GICV5_ITS_CR0_ITSEN, 0x1); + its_writel(its_node, cr0, GICV5_ITS_CR0); + + ret = gicv5_its_wait_for_idle(its_node); + if (ret) { + irq_domain_remove(its_node->domain); + kfree(info); + kfree(its_node); + return ret; + } + + list_add(&its_node->entry, &its_nodes); + + gicv5_its_print_info(its_node); + + return 0; +} + +static int __init gicv5_its_init(struct device_node *node) +{ + int ret = 0; + void __iomem *its_base; + struct resource res; + + its_base = of_io_request_and_map(node, 0, "ITS"); + if (IS_ERR(its_base)) { + pr_err("%pOF: unable to map GICv5 ITS_CONFIG_FRAME\n", node); + return PTR_ERR(its_base); + } + + /* + * The ITS_TRANSLATE_FRAME is the second reg entry, (first is the + * ITS_CONFIG_FRAME) - extract it and use it to init ITS data + * structures. + */ + ret = of_address_to_resource(node, 1, &res); + if (ret) + goto out_unmap; + + ret = gicv5_its_init_bases(res.start, its_base, &node->fwnode, + gicv5_global_data.lpi_domain); + if (ret) + goto out_unmap; + + return 0; +out_unmap: + iounmap(its_base); + return ret; +} + +void __init gicv5_its_of_probe(struct device_node *parent) +{ + struct device_node *np; + + for_each_available_child_of_node(parent, np) { + if (!of_device_is_compatible(np, "arm,gic-v5-its")) + continue; + + if (gicv5_its_init(np)) + pr_err("Failed to init ITS %s\n", np->full_name); + } +} diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c index 24789e9590115e6de7007cd4a74376ae34702ed6..13145d8b0a038b7c13fee32a3b1bc235029e38f1 100644 --- a/drivers/irqchip/irq-gic-v5.c +++ b/drivers/irqchip/irq-gic-v5.c @@ -100,12 +100,12 @@ static int release_lpi_range(u32 min, u32 max) return mtree_store_range(&lpi_mt, min, max, NULL, GFP_KERNEL); } -static int gicv5_alloc_lpi_range(u32 nr_lpis, u32 *base) +int gicv5_alloc_lpi_range(u32 nr_lpis, u32 *base) { return alloc_lpi_range(nr_lpis, base); } -static int gicv5_free_lpi_range(u32 base, u32 nr_lpis) +int gicv5_free_lpi_range(u32 base, u32 nr_lpis) { if (nr_lpis < 1) return -EINVAL; @@ -1217,6 +1217,8 @@ static int __init gicv5_of_init(struct device_node *node, gicv5_smp_init(); + gicv5_irs_its_probe(); + return 0; } IRQCHIP_DECLARE(gic_v5, "arm,gic-v5", gicv5_of_init); diff --git a/drivers/irqchip/irq-gic-v5.h b/drivers/irqchip/irq-gic-v5.h index 8376da2a342d14568a71c0bc85b79c4e7b83a66c..b5c3f69305f30dfa6332fd50c0b98300e3484a05 100644 --- a/drivers/irqchip/irq-gic-v5.h +++ b/drivers/irqchip/irq-gic-v5.h @@ -41,6 +41,8 @@ #define GICV5_IRS_IDR7 0x001c #define GICV5_IRS_CR0 0x0080 #define GICV5_IRS_CR1 0x0084 +#define GICV5_IRS_SYNCR 0x00c0 +#define GICV5_IRS_SYNC_STATUSR 0x00c4 #define GICV5_IRS_SPI_SELR 0x0108 #define GICV5_IRS_SPI_CFGR 0x0114 #define GICV5_IRS_SPI_STATUSR 0x0118 @@ -94,6 +96,10 @@ #define GICV5_IRS_CR1_OC GENMASK(3, 2) #define GICV5_IRS_CR1_SH GENMASK(1, 0) +#define GICV5_IRS_SYNCR_SYNC BIT(31) + +#define GICV5_IRS_SYNC_STATUSR_IDLE BIT(0) + #define GICV5_IRS_SPI_STATUSR_V BIT(1) #define GICV5_IRS_SPI_STATUSR_IDLE BIT(0) @@ -135,6 +141,101 @@ #define GICV5_ISTL1E_L2_ADDR_MASK GENMASK_ULL(55, 12) +#define GICV5_ITS_IDR1 0x0004 +#define GICV5_ITS_IDR2 0x0008 +#define GICV5_ITS_CR0 0x0080 +#define GICV5_ITS_CR1 0x0084 +#define GICV5_ITS_DT_BASER 0x00c0 +#define GICV5_ITS_DT_CFGR 0x00d0 +#define GICV5_ITS_DIDR 0x0100 +#define GICV5_ITS_EIDR 0x0108 +#define GICV5_ITS_INV_EVENTR 0x010c +#define GICV5_ITS_INV_DEVICER 0x0110 +#define GICV5_ITS_STATUSR 0x0120 +#define GICV5_ITS_SYNCR 0x0140 +#define GICV5_ITS_SYNC_STATUSR 0x0148 + +#define GICV5_ITS_IDR1_L2SZ GENMASK(10, 8) +#define GICV5_ITS_IDR1_ITT_LEVELS BIT(7) +#define GICV5_ITS_IDR1_DT_LEVELS BIT(6) +#define GICV5_ITS_IDR1_DEVICEID_BITS GENMASK(5, 0) + +#define GICV5_ITS_IDR1_L2SZ_SUPPORT_4KB(r) FIELD_GET(BIT(8), (r)) +#define GICV5_ITS_IDR1_L2SZ_SUPPORT_16KB(r) FIELD_GET(BIT(9), (r)) +#define GICV5_ITS_IDR1_L2SZ_SUPPORT_64KB(r) FIELD_GET(BIT(10), (r)) + +#define GICV5_ITS_IDR2_XDMN_EVENTs GENMASK(6, 5) +#define GICV5_ITS_IDR2_EVENTID_BITS GENMASK(4, 0) + +#define GICV5_ITS_CR0_IDLE BIT(1) +#define GICV5_ITS_CR0_ITSEN BIT(0) + +#define GICV5_ITS_CR1_ITT_RA BIT(7) +#define GICV5_ITS_CR1_DT_RA BIT(6) +#define GICV5_ITS_CR1_IC GENMASK(5, 4) +#define GICV5_ITS_CR1_OC GENMASK(3, 2) +#define GICV5_ITS_CR1_SH GENMASK(1, 0) + +#define GICV5_ITS_DT_CFGR_STRUCTURE BIT(16) +#define GICV5_ITS_DT_CFGR_L2SZ GENMASK(7, 6) +#define GICV5_ITS_DT_CFGR_DEVICEID_BITS GENMASK(5, 0) + +#define GICV5_ITS_DT_BASER_ADDR_MASK GENMASK_ULL(55, 3) + +#define GICV5_ITS_INV_DEVICER_I BIT(31) +#define GICV5_ITS_INV_DEVICER_EVENTID_BITS GENMASK(5, 1) +#define GICV5_ITS_INV_DEVICER_L1 BIT(0) + +#define GICV5_ITS_DIDR_DEVICEID GENMASK_ULL(31, 0) + +#define GICV5_ITS_EIDR_EVENTID GENMASK(15, 0) + +#define GICV5_ITS_INV_EVENTR_I BIT(31) +#define GICV5_ITS_INV_EVENTR_ITT_L2SZ GENMASK(2, 1) +#define GICV5_ITS_INV_EVENTR_L1 BIT(0) + +#define GICV5_ITS_STATUSR_IDLE BIT(0) + +#define GICV5_ITS_SYNCR_SYNC BIT_ULL(63) +#define GICV5_ITS_SYNCR_SYNCALL BIT_ULL(32) +#define GICV5_ITS_SYNCR_DEVICEID GENMASK_ULL(31, 0) + +#define GICV5_ITS_SYNC_STATUSR_IDLE BIT(0) + +#define GICV5_DTL1E_VALID BIT_ULL(0) +// Note that there is no shift for the address by design +#define GICV5_DTL1E_L2_ADDR_MASK GENMASK_ULL(55, 3) +#define GICV5_DTL1E_SPAN GENMASK_ULL(63, 60) + +#define GICV5_DTL2E_VALID BIT_ULL(0) +#define GICV5_DTL2E_ITT_L2SZ GENMASK_ULL(2, 1) +// Note that there is no shift for the address by design +#define GICV5_DTL2E_ITT_ADDR_MASK GENMASK_ULL(55, 3) +#define GICV5_DTL2E_ITT_DSWE BIT_ULL(57) +#define GICV5_DTL2E_ITT_STRUCTURE BIT_ULL(58) +#define GICV5_DTL2E_EVENT_ID_BITS GENMASK_ULL(63, 59) + +#define GICV5_ITTL1E_VALID BIT_ULL(0) +// Note that there is no shift for the address by design +#define GICV5_ITTL1E_L2_ADDR_MASK GENMASK_ULL(55, 3) +#define GICV5_ITTL1E_SPAN GENMASK_ULL(63, 60) + +#define GICV5_ITTL2E_LPI_ID GENMASK_ULL(23, 0) +#define GICV5_ITTL2E_DAC GENMASK_ULL(29, 28) +#define GICV5_ITTL2E_VIRTUAL BIT_ULL(30) +#define GICV5_ITTL2E_VALID BIT_ULL(31) +#define GICV5_ITTL2E_VM_ID GENMASK_ULL(47, 32) + +#define GICV5_ITS_DT_ITT_CFGR_L2SZ_4k 0b00 +#define GICV5_ITS_DT_ITT_CFGR_L2SZ_16k 0b01 +#define GICV5_ITS_DT_ITT_CFGR_L2SZ_64k 0b10 + +#define GICV5_ITS_DT_ITT_CFGR_STRUCTURE_LINEAR 0 +#define GICV5_ITS_DT_ITT_CFGR_STRUCTURE_TWO_LEVEL 1 + +#define GICV5_ITS_HWIRQ_DEVICE_ID GENMASK_ULL(31, 0) +#define GICV5_ITS_HWIRQ_EVENT_ID GENMASK_ULL(63, 32) + struct gicv5_chip_data { struct fwnode_handle *fwnode; struct irq_domain *ppi_domain; @@ -172,13 +273,72 @@ void __init gicv5_free_lpi_domain(void); int gicv5_irs_of_probe(struct device_node *parent); void gicv5_irs_remove(void); int gicv5_irs_enable(void); +void gicv5_irs_its_probe(void); int gicv5_irs_register_cpu(int cpuid); int gicv5_irs_cpu_to_iaffid(int cpu_id, u16 *iaffid); struct gicv5_irs_chip_data *gicv5_irs_lookup_by_spi_id(u32 spi_id); int gicv5_spi_irq_set_type(struct irq_data *d, unsigned int type); int gicv5_spi_set_type(struct irq_data *d, unsigned int type); int gicv5_irs_iste_alloc(u32 lpi); +void gicv5_irs_syncr(void); + +struct gicv5_its_devtab_cfg { + union { + struct { + __le64 *devtab; + } linear; + struct { + __le64 *l1devtab; + __le64 **l2ptrs; + } l2; + }; + u32 cfgr; +}; + +struct gicv5_its_itt_cfg { + union { + struct { + __le64 *itt; + unsigned int num_ents; + } linear; + struct { + __le64 *l1itt; + __le64 **l2ptrs; + unsigned int num_l1_ents; + u8 l2sz; + } l2; + }; + u8 event_id_bits; + bool l2itt; +}; + +struct gicv5_its_chip_data { + struct list_head entry; + struct xarray its_devices; + struct mutex dev_alloc_lock; + struct fwnode_handle *fwnode; + struct gicv5_its_devtab_cfg devtab_cfgr; + struct irq_domain *domain; + void __iomem *its_base; + phys_addr_t its_trans_phys_base; + u32 flags; +}; + +struct gicv5_its_dev { + struct gicv5_its_chip_data *its_node; + struct gicv5_its_itt_cfg itt_cfg; + unsigned long *event_map; + u32 device_id; + u32 num_events; + u32 num_mapped_events; + bool shared; +}; void gicv5_init_lpi(u32 max); void gicv5_free_lpi(void); + +int gicv5_alloc_lpi_range(u32 nr_lpis, u32 *base); +int gicv5_free_lpi_range(u32 base, u32 nr_lpis); + +void __init gicv5_its_of_probe(struct device_node *parent); #endif From patchwork Tue Apr 8 10:50:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14042910 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C52A8C3600C for ; Tue, 8 Apr 2025 11:44:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=4unmQL9/iS8XoGlV+bGfmkFwaFeXSzCwcuZcElLPDlk=; b=EeppUJgzT1GYoSd5FP7y32m8/z JBU3irw+RV7nuQIRZuu/JMdQK/eyko41kyzdwD1PGY18dA4+LYuNYI/LlNvP3dfH3Sd9/G+Zj+SQT TTqqGvJu1T1K5FmsVkx4mte16qoWY293eZ5NIgthdWb+jXVf461PIcPYzXZvDsTFz/Ie4l1C/tVM4 2DKBHkBlGv9AgRyiGqxmVfccikNFLDxg0k+HAKIVQm9+u5qJzKYTz9zwtXcN0FeA2XYJV6Q9U7Kvp Bu7OGhDM1tEH8CRswl5A2t6usMe10kJ5eMeWgOWCvzhv63upib0E7NAVjH4Qxu302UAuxfHR1w3wY T8z6XriQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u27Nf-00000003tD8-0dcS; Tue, 08 Apr 2025 11:44:39 +0000 Received: from dfw.source.kernel.org ([2604:1380:4641:c500::1]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Yv-00000003kRC-3abD for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:52:15 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 1A7CB5C5C5C; Tue, 8 Apr 2025 10:49:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C10EDC4CEE7; Tue, 8 Apr 2025 10:52:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109532; bh=VWbKskICjszzODfmcIHRFNDwR7rzLsL1xOAkLUxLHSo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=mUL4j67xgNQ+lX3F73gG1z+ao2XpcNrIrqMFOh5zT0QvTpI954vhx3kiBBCjQE1J5 q1Zn4orWvyzHAu4xCjAc3cQS3RC7/3LRmwvI0BRcesRB0S68Ic2+pEYjNkVV1fiSDX bbWnV8BJi8RDJt/RkbksVIgrm81GRVFfdHSpBkzosWHg85u+BxRyASW2U9OcKZjXqN nbGqpXSYw9u7uFfXE5JeEk5MSYTcVTCtomFbOrgfJubhK2jT8HBVpOcUZVSHZXmDp1 wLiDiu1G3m2yij+O58jCLTwjPNZDEiXT9qID+zV+El11ncWn21oV4rHdC58Y9lkocX Tduj3Ig9P1aHA== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:22 +0200 Subject: [PATCH 23/24] irqchip/gic-v5: Add GICv5 IWB support MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-23-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035214_027067_6633E093 X-CRM114-Status: GOOD ( 34.37 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The GICv5 architecture implements the Interrupt Wire Bridge (IWB) in order to support wired interrupts that cannot be connected directly to an IRS and instead uses the ITS to translate a wire event into an IRQ signal. An IWB is a special ITS device with its own deviceID; upon probe, an IWB calls into the ITS driver to allocate DT/ITT tables for its events (ie wires). An IWB is always associated with a single ITS in the system. An IWB is connected to an ITS and it has its own deviceID for all interrupt wires that it manages; the IWB input wire number is exposed to the ITS as an eventID. This eventID is not programmable and therefore requires special handling in the ITS driver. Add an IWB driver in order to: - Probe IWBs in the system and allocate ITS tables - Manage IWB IRQ domains - Handle IWB input wires state (enable/disable) - Add the required IWB IRQchip representation - Handle firmware representation to Linux IRQ translation Co-developed-by: Sascha Bischoff Signed-off-by: Sascha Bischoff Co-developed-by: Timothy Hayes Signed-off-by: Timothy Hayes Signed-off-by: Lorenzo Pieralisi Cc: Thomas Gleixner Cc: Marc Zyngier --- drivers/irqchip/Makefile | 2 +- drivers/irqchip/irq-gic-v5-its.c | 70 ++++++-- drivers/irqchip/irq-gic-v5-iwb.c | 377 +++++++++++++++++++++++++++++++++++++++ drivers/irqchip/irq-gic-v5.c | 2 + drivers/irqchip/irq-gic-v5.h | 28 +++ 5 files changed, 459 insertions(+), 20 deletions(-) diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 4280395e3bdff7858102f0b4eaaea1121cace52f..7bfb2369fbe494a64b72308d95ae33de93c6b8c6 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -37,7 +37,7 @@ obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v4.o obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o irq-gic-v5-irs.o -obj-$(CONFIG_ARM_GIC_V5_ITS) += irq-gic-v5-its.o +obj-$(CONFIG_ARM_GIC_V5_ITS) += irq-gic-v5-its.o irq-gic-v5-iwb.o obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o obj-$(CONFIG_ARM_NVIC) += irq-nvic.o obj-$(CONFIG_ARM_VIC) += irq-vic.o diff --git a/drivers/irqchip/irq-gic-v5-its.c b/drivers/irqchip/irq-gic-v5-its.c index f4f381e6c3af896f354e7e03bc2452b8a65cf093..84ce6032f36724e4f17d6169a7d1933ed11f9110 100644 --- a/drivers/irqchip/irq-gic-v5-its.c +++ b/drivers/irqchip/irq-gic-v5-its.c @@ -779,9 +779,8 @@ static struct gicv5_its_dev *gicv5_its_find_device( return dev ? dev : ERR_PTR(-ENODEV); } -static struct gicv5_its_dev *gicv5_its_alloc_device( - struct gicv5_its_chip_data *its, int nvec, - u32 dev_id) +struct gicv5_its_dev *gicv5_its_alloc_device(struct gicv5_its_chip_data *its, + int nvec, u32 dev_id, bool is_iwb) { int ret; struct gicv5_its_dev *its_dev; @@ -808,6 +807,7 @@ static struct gicv5_its_dev *gicv5_its_alloc_device( its_dev->device_id = dev_id; its_dev->num_events = nvec; its_dev->num_mapped_events = 0; + its_dev->is_iwb = is_iwb; ret = gicv5_its_device_register(its, its_dev); if (ret) { @@ -820,9 +820,11 @@ static struct gicv5_its_dev *gicv5_its_alloc_device( /* * This is the first time we have seen this device. Hence, it is not - * shared. + * shared, unless it is an IWB that is a shared ITS device by + * definition, its eventids are hardcoded and never change - we allocate + * it once for all and never free it. */ - its_dev->shared = false; + its_dev->shared = is_iwb; its_dev->its_node = its; @@ -852,7 +854,7 @@ static int gicv5_its_msi_prepare(struct irq_domain *domain, struct device *dev, guard(mutex)(&its->dev_alloc_lock); - its_dev = gicv5_its_alloc_device(its, nvec, dev_id); + its_dev = gicv5_its_alloc_device(its, nvec, dev_id, false); if (IS_ERR(its_dev)) return PTR_ERR(its_dev); @@ -930,28 +932,55 @@ static void gicv5_its_free_event(struct gicv5_its_dev *its_dev, u16 event_id) } static int gicv5_its_alloc_eventid(struct gicv5_its_dev *its_dev, + msi_alloc_info_t *info, unsigned int nr_irqs, u32 *eventid) { - int ret; + int event_id_base; - ret = bitmap_find_free_region(its_dev->event_map, - its_dev->num_events, - get_count_order(nr_irqs)); + if (!its_dev->is_iwb) { - if (ret < 0) - return ret; + event_id_base = bitmap_find_free_region( + its_dev->event_map, its_dev->num_events, + get_count_order(nr_irqs)); + if (event_id_base < 0) + return event_id_base; + } else { + /* + * We want to have a fixed EventID mapped for the IWB. + */ + if (WARN(nr_irqs != 1, "IWB requesting nr_irqs != 1\n")) + return -EINVAL; - *eventid = ret; + event_id_base = info->scratchpad[1].ul; + + if (event_id_base >= its_dev->num_events) { + pr_err("EventID ouside of ITT range; cannot allocate an ITT entry!\n"); + + return -EINVAL; + } + + if (test_and_set_bit(event_id_base, its_dev->event_map)) { + pr_warn("Can't reserve event_id bitmap\n"); + return -EINVAL; + + } + } + + *eventid = event_id_base; return 0; + } static void gicv5_its_free_eventid(struct gicv5_its_dev *its_dev, u32 event_id_base, unsigned int nr_irqs) { - bitmap_release_region(its_dev->event_map, event_id_base, + if (!its_dev->is_iwb) + bitmap_release_region(its_dev->event_map, event_id_base, get_count_order(nr_irqs)); + else + clear_bit(event_id_base, its_dev->event_map); } static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, @@ -977,14 +1006,17 @@ static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, if (IS_ERR(its_dev)) return PTR_ERR(its_dev); - ret = gicv5_its_alloc_eventid(its_dev, nr_irqs, &event_id_base); + ret = gicv5_its_alloc_eventid(its_dev, info, nr_irqs, &event_id_base); if (ret) return ret; - ret = iommu_dma_prepare_msi(info->desc, - its->its_trans_phys_base); - if (ret) - goto out_eventid; + /* IWB are never upstream an IOMMU */ + if (!its_dev->is_iwb) { + ret = iommu_dma_prepare_msi(info->desc, + its->its_trans_phys_base); + if (ret) + goto out_eventid; + } ret = gicv5_alloc_lpi_range(nr_irqs, &lpi_base); if (ret) { diff --git a/drivers/irqchip/irq-gic-v5-iwb.c b/drivers/irqchip/irq-gic-v5-iwb.c new file mode 100644 index 0000000000000000000000000000000000000000..5938d271f5bcf2c926dc58d1664e30ee75139479 --- /dev/null +++ b/drivers/irqchip/irq-gic-v5-iwb.c @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024-2025 ARM Limited, All Rights Reserved. + */ +#define pr_fmt(fmt) "GICv5 IWB: " fmt + +#include +#include +#include +#include +#include +#include +#include + +#include "irq-gic-v5.h" + +static u32 iwb_readl(struct gicv5_iwb_chip_data *iwb_node, const u64 reg_offset) +{ + return readl_relaxed(iwb_node->iwb_base + reg_offset); +} + +static void iwb_writel(struct gicv5_iwb_chip_data *iwb_node, const u32 val, + const u64 reg_offset) +{ + writel_relaxed(val, iwb_node->iwb_base + reg_offset); +} + +static int gicv5_iwb_wait_for_wenabler(struct gicv5_iwb_chip_data *iwb_node) +{ + int ret; + u32 val; + + ret = readl_relaxed_poll_timeout_atomic( + iwb_node->iwb_base + GICV5_IWB_WENABLE_STATUSR, val, + FIELD_GET(GICV5_IWB_WENABLE_STATUSR_IDLE, val), 1, + USEC_PER_SEC); + + if (ret == -ETIMEDOUT) + pr_err_ratelimited("GICv5 IWB_WENABLE_STATUSR timeout\n"); + + return ret; +} + +static int __gicv5_iwb_set_wire_enable(struct gicv5_iwb_chip_data *iwb_node, + u32 iwb_wire, bool enable) +{ + u32 val; + u32 n = iwb_wire / 32; + u8 i = iwb_wire % 32; + + if (n >= iwb_node->nr_regs) { + pr_err("IWB_WENABLER is invalid for n=%u\n", n); + return -EINVAL; + } + + /* + * Enable IWB wire/pin at this point + * Note: This is not the same as enabling the interrupt + */ + val = iwb_readl(iwb_node, GICV5_IWB_WENABLER + (4 * n)); + if (enable) + val |= BIT(i); + else + val &= ~BIT(i); + iwb_writel(iwb_node, val, GICV5_IWB_WENABLER + (4 * n)); + + return gicv5_iwb_wait_for_wenabler(iwb_node); +} + +static int gicv5_iwb_enable_wire(struct gicv5_iwb_chip_data *iwb_node, + u32 iwb_wire) +{ + return __gicv5_iwb_set_wire_enable(iwb_node, iwb_wire, true); +} + +static int gicv5_iwb_disable_wire(struct gicv5_iwb_chip_data *iwb_node, + u32 iwb_wire) +{ + return __gicv5_iwb_set_wire_enable(iwb_node, iwb_wire, false); +} + +static int gicv5_iwb_set_type(struct irq_data *d, unsigned int type) +{ + struct gicv5_iwb_chip_data *iwb_node = irq_data_get_irq_chip_data(d); + u32 iwb_wire, n, wtmr; + u8 i; + + iwb_wire = d->hwirq; + + i = iwb_wire % 32; + n = iwb_wire / 32; + + WARN_ON(n >= iwb_node->nr_regs); + + wtmr = iwb_readl(iwb_node, GICV5_IWB_WTMR + (4 * n)); + + switch (type) { + case IRQ_TYPE_LEVEL_HIGH: + case IRQ_TYPE_LEVEL_LOW: + wtmr |= BIT(i); + break; + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_EDGE_FALLING: + wtmr &= ~BIT(i); + break; + default: + pr_debug("unexpected wire trigger mode"); + return -EINVAL; + } + + iwb_writel(iwb_node, wtmr, GICV5_IWB_WTMR + (4 * n)); + + return 0; +} + +static const struct irq_chip gicv5_iwb_chip = { + .name = "GICv5-IWB", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_type = gicv5_iwb_set_type, + .irq_set_affinity = irq_chip_set_affinity_parent, + .irq_get_irqchip_state = irq_chip_get_parent_state, + .irq_set_irqchip_state = irq_chip_set_parent_state, + .flags = IRQCHIP_SET_TYPE_MASKED | + IRQCHIP_SKIP_SET_WAKE | + IRQCHIP_MASK_ON_SUSPEND +}; + +static int gicv5_iwb_irq_domain_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + irq_hw_number_t *hwirq, + unsigned int *type) +{ + if (is_of_node(fwspec->fwnode)) { + if (fwspec->param_count < 2) + return -EINVAL; + + /* + * param[0] is be the wire + * param[1] is the interrupt type + */ + *hwirq = fwspec->param[0]; + + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; + + return 0; + } + + return -EINVAL; +} + +static void gicv5_iwb_irq_domain_free(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs) +{ + /* Free the local data, and then go up the hierarchy doing the same */ + struct gicv5_iwb_chip_data *iwb_node = domain->host_data; + struct irq_data *data; + + if (WARN_ON(nr_irqs != 1)) + return; + + data = irq_domain_get_irq_data(domain, virq); + gicv5_iwb_disable_wire(iwb_node, data->hwirq); + + irq_domain_reset_irq_data(data); + + irq_domain_free_irqs_parent(domain, virq, nr_irqs); +} + +/* + * Our parent is the ITS, which expects MSI devices with programmable + * event IDs. IWB event IDs are hardcoded. + * + * Use the msi_alloc_info_t structure to convey both our DeviceID + * (scratchpad[0]), and the wire that we are attempting to map to an LPI in + * the ITT (scratchpad[1]). + */ +static int iwb_alloc_lpi_irq_parent(struct irq_domain *domain, + unsigned int virq, irq_hw_number_t hwirq) +{ + msi_alloc_info_t info; + struct gicv5_iwb_chip_data *iwb_node = domain->host_data; + + info.scratchpad[0].ul = iwb_node->device_id; + info.scratchpad[1].ul = hwirq; + info.hwirq = hwirq; + + return irq_domain_alloc_irqs_parent(domain, virq, 1, &info); +} + +static int gicv5_iwb_irq_domain_alloc(struct irq_domain *domain, + unsigned int virq, unsigned int nr_irqs, + void *arg) +{ + int ret; + irq_hw_number_t hwirq; + unsigned int type = IRQ_TYPE_NONE; + struct irq_fwspec *fwspec = arg; + struct irq_data *irqd; + struct gicv5_iwb_chip_data *iwb_node; + + if (WARN_ON(nr_irqs != 1)) + return -EINVAL; + + ret = gicv5_iwb_irq_domain_translate(domain, fwspec, &hwirq, &type); + if (ret) + return ret; + + irqd = irq_desc_get_irq_data(irq_to_desc(virq)); + iwb_node = domain->host_data; + + if (iwb_alloc_lpi_irq_parent(domain, virq, hwirq)) + return -EINVAL; + + gicv5_iwb_enable_wire(iwb_node, hwirq); + + irq_domain_set_info(domain, virq, hwirq, &gicv5_iwb_chip, iwb_node, + handle_fasteoi_irq, NULL, NULL); + irq_set_probe(virq); + irqd_set_single_target(irqd); + + return 0; +} + +static int gicv5_iwb_irq_domain_select(struct irq_domain *d, + struct irq_fwspec *fwspec, + enum irq_domain_bus_token bus_token) +{ + struct gicv5_iwb_chip_data *iwb_node; + + /* Not for us */ + if (fwspec->fwnode != d->fwnode) + return 0; + + iwb_node = d->host_data; + + return (d == iwb_node->domain); +} + +static const struct irq_domain_ops gicv5_iwb_irq_domain_ops = { + .translate = gicv5_iwb_irq_domain_translate, + .alloc = gicv5_iwb_irq_domain_alloc, + .free = gicv5_iwb_irq_domain_free, + .select = gicv5_iwb_irq_domain_select +}; + +static struct gicv5_iwb_chip_data * +__init gicv5_iwb_init_bases(void __iomem *iwb_base, + struct fwnode_handle *handle, + struct irq_domain *parent_domain, u32 device_id) +{ + u32 nr_wires, idr0, cr0; + struct gicv5_iwb_chip_data *iwb_node; + struct msi_domain_info *msi_info; + struct gicv5_its_chip_data *its; + struct gicv5_its_dev *its_dev; + int ret; + + msi_info = msi_get_domain_info(parent_domain); + its = msi_info->data; + if (!its) { + pr_warn("IWB %pOF can't find parent ITS, bailing\n", + to_of_node(handle)); + return ERR_PTR(-ENODEV); + } + + iwb_node = kzalloc(sizeof(*iwb_node), GFP_KERNEL); + if (!iwb_node) + return ERR_PTR(-ENOMEM); + + iwb_node->iwb_base = iwb_base; + iwb_node->device_id = device_id; + + idr0 = iwb_readl(iwb_node, GICV5_IWB_IDR0); + nr_wires = (FIELD_GET(GICV5_IWB_IDR0_IW_RANGE, idr0) + 1) * 32; + + iwb_node->domain = irq_domain_create_hierarchy(parent_domain, 0, + nr_wires, handle, &gicv5_iwb_irq_domain_ops, + iwb_node); + irq_domain_update_bus_token(iwb_node->domain, DOMAIN_BUS_WIRED); + + cr0 = iwb_readl(iwb_node, GICV5_IWB_CR0); + if (!FIELD_GET(GICV5_IWB_CR0_IWBEN, cr0)) { + pr_err("IWB %s must be enabled in firmware\n", + fwnode_get_name(handle)); + ret = -EINVAL; + goto out_free; + } + + iwb_node->nr_regs = FIELD_GET(GICV5_IWB_IDR0_IW_RANGE, idr0) + 1; + + for (unsigned int n = 0; n < iwb_node->nr_regs; n++) + iwb_writel(iwb_node, 0, GICV5_IWB_WENABLER + (sizeof(u32) * n)); + + ret = gicv5_iwb_wait_for_wenabler(iwb_node); + if (ret) + goto out_free; + + guard(mutex)(&its->dev_alloc_lock); + + its_dev = gicv5_its_alloc_device(its, roundup_pow_of_two(nr_wires), + device_id, true); + if (IS_ERR(its_dev)) { + ret = -ENODEV; + goto out_free; + } + + return iwb_node; +out_free: + irq_domain_remove(iwb_node->domain); + kfree(iwb_node); + + return ERR_PTR(ret); +} + +static int __init gicv5_iwb_of_init(struct device_node *node) +{ + struct gicv5_iwb_chip_data *iwb_node; + void __iomem *iwb_base; + u32 device_id; + struct irq_domain *parent_domain; + struct device_node *parent_its __free(device_node) = NULL; + struct of_phandle_args args; + int ret; + + iwb_base = of_io_request_and_map(node, 0, "IWB"); + if (IS_ERR(iwb_base)) { + pr_err("%pOF: unable to map GICv5 IWB registers\n", node); + return PTR_ERR(iwb_base); + } + + ret = of_parse_phandle_with_args(node, "msi-parent", "#msi-cells", 0, + &args); + if (ret) { + pr_err("%pOF: Can't retrieve deviceID\n", node); + goto out_unmap; + } + + parent_its = args.np; + parent_domain = irq_find_matching_host(parent_its, DOMAIN_BUS_NEXUS); + if (!parent_domain) { + pr_err("Unable to find the parent ITS domain for %pOF!\n", node); + ret = -ENXIO; + goto out_unmap; + } + + device_id = args.args[0]; + pr_debug("IWB deviceID: 0x%x\n", device_id); + + iwb_node = gicv5_iwb_init_bases(iwb_base, &node->fwnode, parent_domain, + device_id); + if (IS_ERR(iwb_node)) { + ret = PTR_ERR(iwb_node); + goto out_unmap; + } + + return 0; +out_unmap: + iounmap(iwb_base); + return ret; +} + +void __init gicv5_iwb_of_probe(struct device_node *parent) +{ + int ret; + struct device_node *np; + + for_each_available_child_of_node(parent, np) { + if (!of_device_is_compatible(np, "arm,gic-v5-iwb")) + continue; + + ret = gicv5_iwb_of_init(np); + if (ret) + pr_err("Failed to init IWB %s\n", np->full_name); + } +} diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c index 13145d8b0a038b7c13fee32a3b1bc235029e38f1..798c9772c2963f4dc08520673b90d43b88ae3fa2 100644 --- a/drivers/irqchip/irq-gic-v5.c +++ b/drivers/irqchip/irq-gic-v5.c @@ -1219,6 +1219,8 @@ static int __init gicv5_of_init(struct device_node *node, gicv5_irs_its_probe(); + gicv5_iwb_of_probe(node); + return 0; } IRQCHIP_DECLARE(gic_v5, "arm,gic-v5", gicv5_of_init); diff --git a/drivers/irqchip/irq-gic-v5.h b/drivers/irqchip/irq-gic-v5.h index b5c3f69305f30dfa6332fd50c0b98300e3484a05..9cd4fa98a6640de7c30ef46120a65c0f7c73c789 100644 --- a/drivers/irqchip/irq-gic-v5.h +++ b/drivers/irqchip/irq-gic-v5.h @@ -236,6 +236,20 @@ #define GICV5_ITS_HWIRQ_DEVICE_ID GENMASK_ULL(31, 0) #define GICV5_ITS_HWIRQ_EVENT_ID GENMASK_ULL(63, 32) +#define GICV5_IWB_IDR0 0x0000 +#define GICV5_IWB_CR0 0x0080 +#define GICV5_IWB_WENABLE_STATUSR 0x00c0 +#define GICV5_IWB_WENABLER 0x2000 +#define GICV5_IWB_WTMR 0x4000 + +#define GICV5_IWB_IDR0_INT_DOMS GENMASK(14, 11) +#define GICV5_IWB_IDR0_IW_RANGE GENMASK(10, 0) + +#define GICV5_IWB_CR0_IDLE BIT(1) +#define GICV5_IWB_CR0_IWBEN BIT(0) + +#define GICV5_IWB_WENABLE_STATUSR_IDLE BIT(0) + struct gicv5_chip_data { struct fwnode_handle *fwnode; struct irq_domain *ppi_domain; @@ -332,6 +346,7 @@ struct gicv5_its_dev { u32 num_events; u32 num_mapped_events; bool shared; + bool is_iwb; }; void gicv5_init_lpi(u32 max); @@ -341,4 +356,17 @@ int gicv5_alloc_lpi_range(u32 nr_lpis, u32 *base); int gicv5_free_lpi_range(u32 base, u32 nr_lpis); void __init gicv5_its_of_probe(struct device_node *parent); +struct gicv5_its_dev *gicv5_its_alloc_device(struct gicv5_its_chip_data *its, + int nvec, u32 dev_id, bool is_iwb); + +struct gicv5_iwb_chip_data { + void __iomem *iwb_base; + struct irq_domain *domain; + u64 flags; + u32 device_id; + u16 nr_regs; +}; + +void gicv5_iwb_of_probe(struct device_node *parent); + #endif From patchwork Tue Apr 8 10:50:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 14043010 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 285A9C3600C for ; Tue, 8 Apr 2025 13:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=CHuBxSVI3miYGq7VQcz5Dk/EGYJMTC0E0UPB/7Z89ow=; b=1u9kEGxL9rubZAmfRPxN4KnNNc ZSdJFG3986AdP0MSDgh1j0UUOnw2wtRseMgMiBe0r11dBfhdqmTB0HjbOrXymqTNKWzdjOx/wM03+ ptLBdTPEWYdmMfrBH/bPo38IUmsDX3yvszeDlkJt9Nj7MMHa81IwLIR1kUhaaT/1zzi+TNHf1FKeH qlXgZ8EmSE4LW0iK+g2whuJd5O7kvN49wbZq0QzBiprCTqZXS/QZztYEFpiXt9mlFjoRc6cGNblMp Sa65H9ZSptg8A41wWFW1mOsQzSYBIywEK+QJkGgMR0Ndzs3z9beBHGGydW7T40nFQFpjcgI0UPmEd ALmPLVIA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.1 #2 (Red Hat Linux)) id 1u28lp-0000000462V-0wLN; Tue, 08 Apr 2025 13:13:41 +0000 Received: from sea.source.kernel.org ([2600:3c0a:e001:78e:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.1 #2 (Red Hat Linux)) id 1u26Yy-00000003kSG-3LBf for linux-arm-kernel@lists.infradead.org; Tue, 08 Apr 2025 10:52:17 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id CCE854A04B; Tue, 8 Apr 2025 10:52:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 56A5FC4CEE5; Tue, 8 Apr 2025 10:52:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744109536; bh=Dhr0rsx9WpeMa8aspdbgl7YO+d4d6KcEE2+waQCoYbI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=QPcFfMueH+YR1V9Q9Qfq/RUp1p9rSenNC/vFt0XOexIUUc52d6+g0KpfC394f8kWm qfS9mWg7ucUq5IN0ivu4QqeoYH0zs7Eszb/pRZqrkiI/RAfMHWTYLsuoz/OkFy/Cc9 iovtDoVhcauoezTvoHsIMbwcXj7P2XwzeRxbMOWOcp0IaaVLzoKBdEsuwiioxbpLAg /pqeKQy3CJNqSWcVvfJfQFpy+Vgs5IMSmKO+TTap2xNm0KIrhydnhOFTbAD40L+E7p PGxIRLbdhLvsMZxQdEMoYqgR7rfnYZ7z/b5toiliF0n2Vvfm5E97Dpqjxv2rjnKZPB fPJmVDmxoDmDg== From: Lorenzo Pieralisi Date: Tue, 08 Apr 2025 12:50:23 +0200 Subject: [PATCH 24/24] arm64: Kconfig: Enable GICv5 MIME-Version: 1.0 Message-Id: <20250408-gicv5-host-v1-24-1f26db465f8d@kernel.org> References: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> In-Reply-To: <20250408-gicv5-host-v1-0-1f26db465f8d@kernel.org> To: Marc Zyngier , Thomas Gleixner , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Catalin Marinas , Will Deacon Cc: Sascha Bischoff , Timothy Hayes , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Lorenzo Pieralisi X-Mailer: b4 0.14.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250408_035216_859446_20E854CC X-CRM114-Status: UNSURE ( 8.62 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Enable GICv5 driver code for the ARM64 architecture. Signed-off-by: Lorenzo Pieralisi Cc: Will Deacon Cc: Catalin Marinas Cc: Marc Zyngier --- arch/arm64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a182295e6f08bfa0f3e6f630dc4adfe797a4d273..f1b3c695b376717979ae864865238ae12ad65ca2 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -128,6 +128,7 @@ config ARM64 select ARM_GIC_V2M if PCI select ARM_GIC_V3 select ARM_GIC_V3_ITS if PCI + select ARM_GIC_V5 select ARM_PSCI_FW select BUILDTIME_TABLE_SORT select CLONE_BACKWARDS