John Hubbard
2025-Nov-12 04:29 UTC
[PATCH v7 0/4] gpu: nova: add boot42 support for next-gen GPUs
Changes in v7: 1) Added a TODO to eventually remove the Default trait from Architecture. 2) Further refined the logic and comments for reading boot0, then boot42. Changes in v6: 1) Split out a separate patch for implementing Display for Spec. 2) Moved Spec implementation code to its proper location. 3) Significantly changed the use_boot42_instead() logic, and updated the comments accordingly. 4) Fixed the boot42 register and field values, which were wrong (and had not been exercised before). 5) Imported Revision, to save a few ::'s. 6) Rebased to the very latest drm-rust-next, which now includes the new "one 'use' item per line" updates. Changes in v5: Two fixes, both from Timur's review feedback (thanks!): 1) Updated both the cover letter, and patch 3 commit description, with the correct description of the future contents of NV_PMC_BOOT_0. 2) Removed a trailing "boot42" typo from a comment in the code. Changes in v4: 1) Simplified and improved the decision logic: reads both arch_0 and arch_1 fields in boot0, and skips the unnecessary is_nv04() logic as well. Thanks to Timur Tabi and Danilo for noticing these issues. 2) Added a patch to represent Architecture as a u8. This simplifies a few things. (Thanks to Alex Courbot. I added your Suggested-by to that patch.) 3) Enhanced the Revision type to do more, which simplifies the callers. (Thanks to Danilo.) Changes in v3: 1) Restored the Revision type as recommended by Danilo, but decoupled it from boot0. 2) Applied Alex Courbot's suggestion to use TryFrom<NV_PMC_BOOT_0/42> for Spec. 3) Reflowed the new comment documentation to 100 cols, to avoid wasting a few vertical lines. Changes in v2: 1) Restored the Spec type, and used that to encapsulate the subsequent boot42 enhancements. Thanks to Danilo Krummrich's feedback for that improvement. v1 cover letter (with typos fixed) NVIDIA GPUs are moving away from using NV_PMC_BOOT_0 to contain architecture and revision details, and will instead use NV_PMC_BOOT_42 in the future. NV_PMC_BOOT_0 will contain a specific set of values that will mean "go read NV_PMC_BOOT_42 instead". Change the selection logic in Nova so that it will claim Turing and later GPUs. This will work for the foreseeable future, without any further code changes here, because all NVIDIA GPUs are considered, from the oldest supported on Linux (NV04), through the future GPUs. Add some comment documentation to explain, chronologically, how boot0 and boot42 change with the GPU eras, and how that affects the selection logic. Also, remove the Revision type, because Revision is no longer valuable as a stand-alone type, because we only ever want the full information that Spec provides. This is based on today's drm-rust-next, which in turn is based on Linux 6.18-rc2. John Hubbard (4): gpu: nova-core: implement Display for Spec gpu: nova-core: prepare Spec and Revision types for boot0/boot42 gpu: nova-core: make Architecture behave as a u8 type gpu: nova-core: add boot42 support for next-gen GPUs drivers/gpu/nova-core/gpu.rs | 82 ++++++++++++++++++++++++++--------- drivers/gpu/nova-core/regs.rs | 33 +++++++++++--- 2 files changed, 87 insertions(+), 28 deletions(-) base-commit: e54ad0cd3673c93cdafda58505eaa81610fe3aef -- 2.51.2
John Hubbard
2025-Nov-12 04:29 UTC
[PATCH v7 1/4] gpu: nova-core: implement Display for Spec
Implement Display for Spec. This simplifies the dev_info!() code for
printing banners such as:
NVIDIA (Chipset: GA104, Architecture: Ampere, Revision: a.1)
Cc: Alexandre Courbot <acourbot at nvidia.com>
Cc: Danilo Krummrich <dakr at kernel.org>
Cc: Timur Tabi <ttabi at nvidia.com>
Signed-off-by: John Hubbard <jhubbard at nvidia.com>
---
drivers/gpu/nova-core/gpu.rs | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 802e71e4f97d..7fd9e91771a6 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -180,6 +180,18 @@ fn new(bar: &Bar0) -> Result<Spec> {
}
}
+impl fmt::Display for Spec {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) ->
fmt::Result {
+ write!(
+ f,
+ "Chipset: {}, Architecture: {:?}, Revision: {}",
+ self.chipset,
+ self.chipset.arch(),
+ self.revision
+ )
+ }
+}
+
/// Structure holding the resources required to operate the GPU.
#[pin_data]
pub(crate) struct Gpu {
@@ -206,13 +218,7 @@ pub(crate) fn new<'a>(
) -> impl PinInit<Self, Error> + 'a {
try_pin_init!(Self {
spec: Spec::new(bar).inspect(|spec| {
- dev_info!(
- pdev.as_ref(),
- "NVIDIA (Chipset: {}, Architecture: {:?}, Revision:
{})\n",
- spec.chipset,
- spec.chipset.arch(),
- spec.revision
- );
+ dev_info!(pdev.as_ref(),"NVIDIA ({})\n", spec);
})?,
// We must wait for GFW_BOOT completion before doing any
significant setup on the GPU.
--
2.51.2
John Hubbard
2025-Nov-12 04:29 UTC
[PATCH v7 2/4] gpu: nova-core: prepare Spec and Revision types for boot0/boot42
1) Decouple Revision from boot0.
2) Enhance Revision, which in turn simplifies Spec::new().
3) Also, slightly enhance the comment about Spec, to be more precise.
Cc: Alexandre Courbot <acourbot at nvidia.com>
Cc: Danilo Krummrich <dakr at kernel.org>
Cc: Timur Tabi <ttabi at nvidia.com>
Signed-off-by: John Hubbard <jhubbard at nvidia.com>
---
drivers/gpu/nova-core/gpu.rs | 25 ++++++++++++-------------
drivers/gpu/nova-core/regs.rs | 11 ++++++++++-
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 7fd9e91771a6..acf564fee9c8 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -143,17 +143,8 @@ fn try_from(value: u8) -> Result<Self> {
}
pub(crate) struct Revision {
- major: u8,
- minor: u8,
-}
-
-impl Revision {
- fn from_boot0(boot0: regs::NV_PMC_BOOT_0) -> Self {
- Self {
- major: boot0.major_revision(),
- minor: boot0.minor_revision(),
- }
- }
+ pub(crate) major: u8,
+ pub(crate) minor: u8,
}
impl fmt::Display for Revision {
@@ -162,7 +153,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>)
-> fmt::Result {
}
}
-/// Structure holding the metadata of the GPU.
+/// Structure holding a basic description of the GPU: Architecture, Chipset and
Revision.
pub(crate) struct Spec {
chipset: Chipset,
/// The revision of the chipset.
@@ -173,9 +164,17 @@ impl Spec {
fn new(bar: &Bar0) -> Result<Spec> {
let boot0 = regs::NV_PMC_BOOT_0::read(bar);
+ Spec::try_from(boot0)
+ }
+}
+
+impl TryFrom<regs::NV_PMC_BOOT_0> for Spec {
+ type Error = Error;
+
+ fn try_from(boot0: regs::NV_PMC_BOOT_0) -> Result<Self> {
Ok(Self {
chipset: boot0.chipset()?,
- revision: Revision::from_boot0(boot0),
+ revision: boot0.revision(),
})
}
}
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index 934003cab8a8..8c9af3c59708 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -24,7 +24,8 @@
},
gpu::{
Architecture,
- Chipset, //
+ Chipset,
+ Revision, //
},
num::FromSafeCast,
};
@@ -56,6 +57,14 @@ pub(crate) fn chipset(self) -> Result<Chipset> {
})
.and_then(Chipset::try_from)
}
+
+ /// Returns the revision information of the chip.
+ pub(crate) fn revision(self) -> Revision {
+ Revision {
+ major: self.major_revision(),
+ minor: self.minor_revision(),
+ }
+ }
}
// PBUS
--
2.51.2
John Hubbard
2025-Nov-12 04:29 UTC
[PATCH v7 3/4] gpu: nova-core: make Architecture behave as a u8 type
This allows Architecture to be passed into register!() and bitfield!()
macro calls. That in turn requires a default implementation for
Architecture.
This simplifies transforming BOOT0 (and later, BOOT42) register values
into GPU architectures.
Cc: Danilo Krummrich <dakr at kernel.org>
Cc: Timur Tabi <ttabi at nvidia.com>
Suggested-by: Alexandre Courbot <acourbot at nvidia.com>
Signed-off-by: John Hubbard <jhubbard at nvidia.com>
---
drivers/gpu/nova-core/gpu.rs | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index acf564fee9c8..cd58040b681b 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -122,8 +122,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>)
-> fmt::Result {
}
/// Enum representation of the GPU generation.
-#[derive(fmt::Debug)]
+///
+/// TODO: remove the `Default` trait implementation, and the `#[default]`
+/// attribute, once the register!() macro (which creates Architecture items) no
+/// longer requires it for read-only fields.
+#[derive(fmt::Debug, Default, Copy, Clone)]
+#[repr(u8)]
pub(crate) enum Architecture {
+ #[default]
Turing = 0x16,
Ampere = 0x17,
Ada = 0x19,
@@ -142,6 +148,13 @@ fn try_from(value: u8) -> Result<Self> {
}
}
+impl From<Architecture> for u8 {
+ fn from(value: Architecture) -> Self {
+ // CAST: `Architecture` is `repr(u8)`, so this cast is always lossless.
+ value as u8
+ }
+}
+
pub(crate) struct Revision {
pub(crate) major: u8,
pub(crate) minor: u8,
--
2.51.2
John Hubbard
2025-Nov-12 04:30 UTC
[PATCH v7 4/4] gpu: nova-core: add boot42 support for next-gen GPUs
NVIDIA GPUs are moving away from using NV_PMC_BOOT_0 to contain
architecture and revision details, and will instead use NV_PMC_BOOT_42
in the future. NV_PMC_BOOT_0 will contain a specific set of values
that will mean "go read NV_PMC_BOOT_42 instead".
Change the selection logic in Nova so that it will claim Turing and
later GPUs. This will work for the foreseeable future, without any
further code changes here, because all NVIDIA GPUs are considered, from
the oldest supported on Linux (NV04), through the future GPUs.
Add some comment documentation to explain, chronologically, how boot0
and boot42 change with the GPU eras, and how that affects the selection
logic.
Cc: Alexandre Courbot <acourbot at nvidia.com>
Cc: Danilo Krummrich <dakr at kernel.org>
Cc: Timur Tabi <ttabi at nvidia.com>
Signed-off-by: John Hubbard <jhubbard at nvidia.com>
---
drivers/gpu/nova-core/gpu.rs | 32 +++++++++++++++++++++++++++-----
drivers/gpu/nova-core/regs.rs | 22 ++++++++++++++++------
2 files changed, 43 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index cd58040b681b..8c5f46f6aaac 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -175,19 +175,41 @@ pub(crate) struct Spec {
impl Spec {
fn new(bar: &Bar0) -> Result<Spec> {
+ // Some brief notes about boot0 and boot42, in chronological order:
+ //
+ // NV04 through NV50:
+ //
+ // Not supported by Nova. boot0 is necessary and sufficient to
identify these GPUs.
+ // boot42 may not even exist on some of these GPUs.
+ //
+ // Fermi through Volta:
+ //
+ // Not supported by Nova. boot0 is still sufficient to identify
these GPUs, but boot42
+ // is also guaranteed to be both present and accurate.
+ //
+ // Turing and later:
+ //
+ // Supported by Nova. Identified by first checking boot0 to ensure
that the GPU is not
+ // from an earlier (pre-Fermi) era, and then using boot42 to
precisely identify the GPU.
+ // Somewhere in the Rubin timeframe, boot0 will no longer have
space to add new GPU IDs.
+
let boot0 = regs::NV_PMC_BOOT_0::read(bar);
- Spec::try_from(boot0)
+ if boot0.is_older_than_fermi() {
+ return Err(ENOTSUPP);
+ }
+
+ Spec::try_from(regs::NV_PMC_BOOT_42::read(bar))
}
}
-impl TryFrom<regs::NV_PMC_BOOT_0> for Spec {
+impl TryFrom<regs::NV_PMC_BOOT_42> for Spec {
type Error = Error;
- fn try_from(boot0: regs::NV_PMC_BOOT_0) -> Result<Self> {
+ fn try_from(boot42: regs::NV_PMC_BOOT_42) -> Result<Self> {
Ok(Self {
- chipset: boot0.chipset()?,
- revision: boot0.revision(),
+ chipset: boot42.chipset()?,
+ revision: boot42.revision(),
})
}
}
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index 8c9af3c59708..81097e83c276 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -41,14 +41,24 @@
});
impl NV_PMC_BOOT_0 {
- /// Combines `architecture_0` and `architecture_1` to obtain the
architecture of the chip.
- pub(crate) fn architecture(self) -> Result<Architecture> {
- Architecture::try_from(
- self.architecture_0() | (self.architecture_1() <<
Self::ARCHITECTURE_0_RANGE.len()),
- )
+ pub(crate) fn is_older_than_fermi(self) -> bool {
+ // From https://github.com/NVIDIA/open-gpu-doc/tree/master/manuals :
+ const NV_PMC_BOOT_0_ARCHITECTURE_GF100: u8 = 0xc;
+
+ // Older chips left arch1 zeroed out. That, combined with an arch0
value that is less than
+ // GF100, means "older than Fermi".
+ self.architecture_1() == 0 && self.architecture_0() <
NV_PMC_BOOT_0_ARCHITECTURE_GF100
}
+}
+
+register!(NV_PMC_BOOT_42 @ 0x00000a00, "Extended architecture
information" {
+ 15:12 minor_revision as u8, "Minor revision of the chip";
+ 19:16 major_revision as u8, "Major revision of the chip";
+ 23:20 implementation as u8, "Implementation version of the
architecture";
+ 29:24 architecture as u8 ?=> Architecture, "Architecture
value";
+});
- /// Combines `architecture` and `implementation` to obtain a code unique to
the chipset.
+impl NV_PMC_BOOT_42 {
pub(crate) fn chipset(self) -> Result<Chipset> {
self.architecture()
.map(|arch| {
--
2.51.2
Joel Fernandes
2025-Nov-13 20:02 UTC
[PATCH v7 0/4] gpu: nova: add boot42 support for next-gen GPUs
On 11/11/2025 11:29 PM, John Hubbard wrote:> Changes in v7: > > 1) Added a TODO to eventually remove the Default trait from Architecture. > 2) Further refined the logic and comments for reading boot0, then boot42.Other than the few nits I left, looks really good. Thanks! For all, Reviewed-by: Joel Fernandes <joelagnelf at nvidia.com> - Joel