From: John Hubbard <jhubbard@nvidia.com>
To: Danilo Krummrich <dakr@kernel.org>,
Joel Fernandes <joel@joelfernandes.org>,
Alexandre Courbot <acourbot@nvidia.com>
Cc: "Timur Tabi" <ttabi@nvidia.com>,
"Alistair Popple" <apopple@nvidia.com>,
"Eliot Courtney" <ecourtney@nvidia.com>,
"Shashank Sharma" <shashanks@nvidia.com>,
"Zhi Wang" <zhiw@nvidia.com>, "David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Bjorn Helgaas" <bhelgaas@google.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
nova-gpu@lists.linux.dev, LKML <linux-kernel@vger.kernel.org>,
"John Hubbard" <jhubbard@nvidia.com>,
"Will Pierce" <wpierce@nvidia.com>
Subject: [PATCH 07/17] gpu: nova-core: add the per-architecture GIN CPU interrupt HAL
Date: Fri, 7 Aug 2026 20:11:09 -0700 [thread overview]
Message-ID: <20260808031120.363869-8-jhubbard@nvidia.com> (raw)
In-Reply-To: <20260808031120.363869-1-jhubbard@nvidia.com>
GIN, the GPU Interrupt and Notification unit, is the GPU's interrupt
controller. Each PCIe function has its own tree, whose leaf count
depends on the GPU family.
Message-signaled delivery stops after each edge until the CPU rearms it,
and the rearm write differs by family and interrupt type:
* Pre-Hopper MSI writes an EOI through the BAR0 PCI configuration
space mirror.
* MSI for Hopper and later cycles the TOP enable bits of every
serviced subtree.
* MSI-X on any family cycles the bits of the handler's own subtree.
Provide the leaf count and the rearm method through a per-architecture
interrupt HAL.
Assisted-by: Cursor:claude-opus-5
Reviewed-by: Will Pierce <wpierce@nvidia.com>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
drivers/gpu/nova-core/irq.rs | 12 ++-
drivers/gpu/nova-core/irq/hal.rs | 113 +++++++++++++++++++++++++
drivers/gpu/nova-core/irq/hal/gh100.rs | 30 +++++++
drivers/gpu/nova-core/irq/hal/tu102.rs | 29 +++++++
4 files changed, 182 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/nova-core/irq/hal.rs
create mode 100644 drivers/gpu/nova-core/irq/hal/gh100.rs
create mode 100644 drivers/gpu/nova-core/irq/hal/tu102.rs
diff --git a/drivers/gpu/nova-core/irq.rs b/drivers/gpu/nova-core/irq.rs
index b70efc239334..ef77066e0514 100644
--- a/drivers/gpu/nova-core/irq.rs
+++ b/drivers/gpu/nova-core/irq.rs
@@ -1,6 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+//! GPU interrupt support.
+//!
+//! GIN, the GPU Interrupt and Notification unit, is the GPU's interrupt controller: a two-level
+//! tree of pending and enable registers, one tree per PCIe function.
+//!
+//! See `Documentation/gpu/nova/core/interrupts.rst`.
+
+mod hal;
+mod interrupt_tree;
+
use kernel::{
device::Bound,
pci::{
@@ -11,8 +21,6 @@
prelude::*,
};
-mod interrupt_tree;
-
pub(crate) fn alloc_vector(pdev: &pci::Device<Bound>) -> Result<pci::IrqVector<'_>> {
let msi_types = IrqTypes::default().with(IrqType::Msi).with(IrqType::MsiX);
diff --git a/drivers/gpu/nova-core/irq/hal.rs b/drivers/gpu/nova-core/irq/hal.rs
new file mode 100644
index 000000000000..8de2f6e536c2
--- /dev/null
+++ b/drivers/gpu/nova-core/irq/hal.rs
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+//! Per-architecture properties of the GIN CPU interrupt tree.
+
+mod gh100;
+mod tu102;
+
+use kernel::{
+ io::Io,
+ pci::IrqType, //
+};
+
+use crate::{
+ driver::Bar0,
+ gpu::{
+ Architecture,
+ Chipset, //
+ },
+ regs, //
+};
+
+/// Register write that restores PCI interrupt delivery to the CPU.
+///
+/// A message-signaled interrupt is delivered once per edge, and the PCI side delivers no further
+/// interrupt until the CPU rearms it. A handler that returns without this write receives no more
+/// interrupts.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub(super) enum PciIrqRearmMethod {
+ /// The MSI end-of-interrupt register in the BAR0 PCI configuration-space mirror, used by
+ /// MSI on pre-Hopper GPUs.
+ ConfigMirrorEoi,
+
+ /// A clear then a set of the `TOP` enable bits of every serviced subtree, which produces the
+ /// edge that delivers the next interrupt.
+ ///
+ /// MSI has a single message that every subtree raises, so the rearm covers the whole serviced
+ /// set.
+ TopEnableCycleServiced,
+
+ /// The same enable cycle, restricted to the one subtree the handler serves.
+ ///
+ /// MSI-X gives each subtree its own table entry and its own handler.
+ TopEnableCycleSubtree,
+}
+
+impl PciIrqRearmMethod {
+ /// Performs this method's register write.
+ ///
+ /// `serviced` holds the `TOP` bit of every subtree the driver services, and `subtree` holds
+ /// the bit of the one subtree the calling handler serves. Each method uses whichever of the
+ /// two its interrupt type delivers on, so both are required.
+ #[expect(dead_code)]
+ pub(super) fn rearm(self, bar: Bar0<'_>, serviced: u32, subtree: u32) {
+ let subtrees = match self {
+ // The written value is ignored, so any write rearms delivery.
+ Self::ConfigMirrorEoi => {
+ bar.write(regs::tu102::NV_XVE_CYA_2, 0u32.into());
+ return;
+ }
+ Self::TopEnableCycleServiced => serviced,
+ Self::TopEnableCycleSubtree => subtree,
+ };
+
+ bar.write(
+ regs::NV_VIRTUAL_FUNCTION_PRIV_CPU_INTR_TOP_EN_CLEAR,
+ subtrees.into(),
+ );
+ bar.write(
+ regs::NV_VIRTUAL_FUNCTION_PRIV_CPU_INTR_TOP_EN_SET,
+ subtrees.into(),
+ );
+ }
+}
+
+/// Per-architecture properties of the GIN CPU interrupt tree.
+///
+/// The tree size and the method that rearms PCI interrupt delivery differ by family. The tree
+/// walk, the vector encoding, and the read-and-clear sequence do not, and are in generic code.
+///
+/// See `Documentation/gpu/nova/core/interrupts.rst`.
+pub(super) trait CpuInterruptHal {
+ /// Returns the number of implemented interrupt leaves in the CPU tree.
+ ///
+ /// Each leaf is a 32-bit register, so the tree carries `num_leaves * 32` vectors.
+ fn num_leaves(&self) -> usize;
+
+ /// Returns the subtrees this architecture implements.
+ ///
+ /// Each `TOP` bit covers two adjacent leaves, so the tree has `num_leaves / 2` subtrees and
+ /// the result has one bit set for each. Bits outside the result are not meaningful in
+ /// `TOP_EN_SET` or `TOP_EN_CLEAR`.
+ fn implemented_subtrees(&self) -> u32 {
+ (1u32 << (self.num_leaves() / 2)) - 1
+ }
+
+ /// Returns the method that rearms PCI interrupt delivery for `irq_type`.
+ ///
+ /// `None` means that `irq_type` needs no rearm write. That is the case for `INTx`, which is
+ /// level-triggered, and which nova-core does not allocate.
+ #[expect(dead_code)]
+ fn pci_irq_rearm_method(&self, irq_type: IrqType) -> Option<PciIrqRearmMethod>;
+}
+
+/// Returns the [`CpuInterruptHal`] for `chipset`.
+pub(super) fn cpu_interrupt_hal(chipset: Chipset) -> &'static dyn CpuInterruptHal {
+ match chipset.arch() {
+ Architecture::Turing | Architecture::Ampere | Architecture::Ada => tu102::TU102_HAL,
+ Architecture::Hopper | Architecture::BlackwellGB10x | Architecture::BlackwellGB20x => {
+ gh100::GH100_HAL
+ }
+ }
+}
diff --git a/drivers/gpu/nova-core/irq/hal/gh100.rs b/drivers/gpu/nova-core/irq/hal/gh100.rs
new file mode 100644
index 000000000000..69bd092e38b5
--- /dev/null
+++ b/drivers/gpu/nova-core/irq/hal/gh100.rs
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+use kernel::pci::IrqType;
+
+use super::{
+ CpuInterruptHal,
+ PciIrqRearmMethod, //
+};
+
+/// GIN parameters for Hopper and Blackwell, which implement a 16-leaf CPU tree. Only 12 leaves
+/// carry sources.
+struct Gh100;
+
+impl CpuInterruptHal for Gh100 {
+ fn num_leaves(&self) -> usize {
+ 16
+ }
+
+ fn pci_irq_rearm_method(&self, irq_type: IrqType) -> Option<PciIrqRearmMethod> {
+ match irq_type {
+ IrqType::Intx => None,
+ IrqType::Msi => Some(PciIrqRearmMethod::TopEnableCycleServiced),
+ IrqType::MsiX => Some(PciIrqRearmMethod::TopEnableCycleSubtree),
+ }
+ }
+}
+
+const GH100: Gh100 = Gh100;
+pub(super) const GH100_HAL: &dyn CpuInterruptHal = &GH100;
diff --git a/drivers/gpu/nova-core/irq/hal/tu102.rs b/drivers/gpu/nova-core/irq/hal/tu102.rs
new file mode 100644
index 000000000000..590f0dc9a701
--- /dev/null
+++ b/drivers/gpu/nova-core/irq/hal/tu102.rs
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+use kernel::pci::IrqType;
+
+use super::{
+ CpuInterruptHal,
+ PciIrqRearmMethod, //
+};
+
+/// GIN parameters for Turing, Ampere, and Ada, which implement an 8-leaf CPU tree.
+struct Tu102;
+
+impl CpuInterruptHal for Tu102 {
+ fn num_leaves(&self) -> usize {
+ 8
+ }
+
+ fn pci_irq_rearm_method(&self, irq_type: IrqType) -> Option<PciIrqRearmMethod> {
+ match irq_type {
+ IrqType::Intx => None,
+ IrqType::Msi => Some(PciIrqRearmMethod::ConfigMirrorEoi),
+ IrqType::MsiX => Some(PciIrqRearmMethod::TopEnableCycleSubtree),
+ }
+ }
+}
+
+const TU102: Tu102 = Tu102;
+pub(super) const TU102_HAL: &dyn CpuInterruptHal = &TU102;
--
2.55.0
next prev parent reply other threads:[~2026-08-08 3:11 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-08 3:11 [PATCH 00/17] nova-core: GPU interrupt support and GSP event delivery John Hubbard
2026-08-08 3:11 ` [PATCH 01/17] rust: sync: completion: add wait_for_completion_timeout() John Hubbard
[not found] ` <DKK2DM3VK6TF.3KBBWP7S4A8T1@nvidia.com>
2026-08-09 21:43 ` John Hubbard
2026-08-08 3:11 ` [PATCH 02/17] rust: pci: expose the whole interrupt vector allocation John Hubbard
2026-08-09 13:27 ` Danilo Krummrich
2026-08-08 3:11 ` [PATCH 03/17] rust: pci: expose the allocated interrupt type John Hubbard
2026-08-09 13:24 ` Danilo Krummrich
2026-08-09 21:42 ` John Hubbard
2026-08-08 3:11 ` [PATCH 04/17] gpu: nova-core: allocate PCI MSI vector during probe John Hubbard
2026-08-08 3:11 ` [PATCH 05/17] gpu: nova-core: add the GIN CPU interrupt tree and MSI EOI registers John Hubbard
2026-08-08 3:11 ` [PATCH 06/17] gpu: nova-core: add the GIN interrupt tree API John Hubbard
2026-08-08 3:11 ` John Hubbard [this message]
2026-08-08 3:11 ` [PATCH 08/17] gpu: nova-core: allocate interrupt vectors for the serviced subtrees John Hubbard
2026-08-08 3:11 ` [PATCH 09/17] gpu: nova-core: add an interrupt delivery self-test John Hubbard
2026-08-08 3:11 ` [PATCH 10/17] gpu: nova-core: dispatch GSP events instead of discarding them John Hubbard
2026-08-08 3:11 ` [PATCH 11/17] gpu: nova-core: match GSP RPC replies by sequence, not just function John Hubbard
2026-08-08 3:11 ` [PATCH 12/17] gpu: nova-core: recover the GSP receive path from corrupt framing John Hubbard
2026-08-08 3:11 ` [PATCH 13/17] gpu: nova-core: bound a GSP wait by a single deadline John Hubbard
2026-08-08 3:11 ` [PATCH 14/17] gpu: nova-core: drive GSP events with the SWGEN0 interrupt John Hubbard
2026-08-08 3:11 ` [PATCH 15/17] gpu: nova-core: retrigger the GSP falcon and clear every latched cause John Hubbard
2026-08-08 3:11 ` [PATCH 16/17] gpu: nova-core: add KUnit tests for the interrupt tree and HALs John Hubbard
2026-08-08 3:11 ` [PATCH 17/17] gpu: nova-core: document the GIN interrupt controller and GSP events John Hubbard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260808031120.363869-8-jhubbard@nvidia.com \
--to=jhubbard@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=bhelgaas@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=ecourtney@nvidia.com \
--cc=gary@garyguo.net \
--cc=joel@joelfernandes.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=shashanks@nvidia.com \
--cc=simona@ffwll.ch \
--cc=tmgross@umich.edu \
--cc=ttabi@nvidia.com \
--cc=wpierce@nvidia.com \
--cc=zhiw@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox