Skip to content

Commit 0ecc08e

Browse files
johnhubbardGnurou
authored andcommitted
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@nvidia.com> Cc: Danilo Krummrich <dakr@kernel.org> Cc: Timur Tabi <ttabi@nvidia.com> Reviewed-by: Joel Fernandes <joelagnelf@nvidia.com> Signed-off-by: John Hubbard <jhubbard@nvidia.com> [acourbot@nvidia.com: remove unneeded `From<BOOT_0> for Revision` implementation.] Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Message-ID: <20251115010923.1192144-4-jhubbard@nvidia.com>
1 parent 4d98033 commit 0ecc08e

2 files changed

Lines changed: 45 additions & 12 deletions

File tree

drivers/gpu/nova-core/gpu.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ pub(crate) struct Revision {
160160
minor: u8,
161161
}
162162

163-
impl From<regs::NV_PMC_BOOT_0> for Revision {
164-
fn from(boot0: regs::NV_PMC_BOOT_0) -> Self {
163+
impl From<regs::NV_PMC_BOOT_42> for Revision {
164+
fn from(boot0: regs::NV_PMC_BOOT_42) -> Self {
165165
Self {
166166
major: boot0.major_revision(),
167167
minor: boot0.minor_revision(),
@@ -183,19 +183,41 @@ pub(crate) struct Spec {
183183

184184
impl Spec {
185185
fn new(bar: &Bar0) -> Result<Spec> {
186+
// Some brief notes about boot0 and boot42, in chronological order:
187+
//
188+
// NV04 through NV50:
189+
//
190+
// Not supported by Nova. boot0 is necessary and sufficient to identify these GPUs.
191+
// boot42 may not even exist on some of these GPUs.
192+
//
193+
// Fermi through Volta:
194+
//
195+
// Not supported by Nova. boot0 is still sufficient to identify these GPUs, but boot42
196+
// is also guaranteed to be both present and accurate.
197+
//
198+
// Turing and later:
199+
//
200+
// Supported by Nova. Identified by first checking boot0 to ensure that the GPU is not
201+
// from an earlier (pre-Fermi) era, and then using boot42 to precisely identify the GPU.
202+
// Somewhere in the Rubin timeframe, boot0 will no longer have space to add new GPU IDs.
203+
186204
let boot0 = regs::NV_PMC_BOOT_0::read(bar);
187205

188-
Spec::try_from(boot0)
206+
if boot0.is_older_than_fermi() {
207+
return Err(ENODEV);
208+
}
209+
210+
Spec::try_from(regs::NV_PMC_BOOT_42::read(bar))
189211
}
190212
}
191213

192-
impl TryFrom<regs::NV_PMC_BOOT_0> for Spec {
214+
impl TryFrom<regs::NV_PMC_BOOT_42> for Spec {
193215
type Error = Error;
194216

195-
fn try_from(boot0: regs::NV_PMC_BOOT_0) -> Result<Self> {
217+
fn try_from(boot42: regs::NV_PMC_BOOT_42) -> Result<Self> {
196218
Ok(Self {
197-
chipset: boot0.chipset()?,
198-
revision: boot0.into(),
219+
chipset: boot42.chipset()?,
220+
revision: boot42.into(),
199221
})
200222
}
201223
}

drivers/gpu/nova-core/regs.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,24 @@ register!(NV_PMC_BOOT_0 @ 0x00000000, "Basic revision information about the GPU"
4040
});
4141

4242
impl NV_PMC_BOOT_0 {
43-
/// Combines `architecture_0` and `architecture_1` to obtain the architecture of the chip.
44-
pub(crate) fn architecture(self) -> Result<Architecture> {
45-
Architecture::try_from(
46-
self.architecture_0() | (self.architecture_1() << Self::ARCHITECTURE_0_RANGE.len()),
47-
)
43+
pub(crate) fn is_older_than_fermi(self) -> bool {
44+
// From https://github.com/NVIDIA/open-gpu-doc/tree/master/manuals :
45+
const NV_PMC_BOOT_0_ARCHITECTURE_GF100: u8 = 0xc;
46+
47+
// Older chips left arch1 zeroed out. That, combined with an arch0 value that is less than
48+
// GF100, means "older than Fermi".
49+
self.architecture_1() == 0 && self.architecture_0() < NV_PMC_BOOT_0_ARCHITECTURE_GF100
4850
}
51+
}
52+
53+
register!(NV_PMC_BOOT_42 @ 0x00000a00, "Extended architecture information" {
54+
15:12 minor_revision as u8, "Minor revision of the chip";
55+
19:16 major_revision as u8, "Major revision of the chip";
56+
23:20 implementation as u8, "Implementation version of the architecture";
57+
29:24 architecture as u8 ?=> Architecture, "Architecture value";
58+
});
4959

60+
impl NV_PMC_BOOT_42 {
5061
/// Combines `architecture` and `implementation` to obtain a code unique to the chipset.
5162
pub(crate) fn chipset(self) -> Result<Chipset> {
5263
self.architecture()

0 commit comments

Comments
 (0)