Skip to content

Commit a5bf742

Browse files
johnhubbardGnurou
authored andcommitted
gpu: nova-core: Blackwell: use correct sysmem flush registers
Blackwell GPUs moved the sysmem flush page registers away from the Ampere/Ada location. GB10x routes the flush through a pair of HSHUB0 register sets (primary and egress) that must both be programmed to the same address. GB20x routes it through FBHUB0. Define these registers relative to their HSHUB0 and FBHUB0 bases, as Open RM does, and implement the flush paths in the GB10x and GB20x framebuffer HALs. Signed-off-by: John Hubbard <jhubbard@nvidia.com> Reviewed-by: Eliot Courtney <ecourtney@nvidia.com> Link: https://patch.msgid.link/20260602032111.224790-7-jhubbard@nvidia.com Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
1 parent f66287c commit a5bf742

3 files changed

Lines changed: 154 additions & 6 deletions

File tree

drivers/gpu/nova-core/fb/hal/gb100.rs

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
//! Blackwell GB10x framebuffer HAL.
55
66
use kernel::{
7+
io::{
8+
register::{
9+
RegisterBase,
10+
WithBase, //
11+
},
12+
Io, //
13+
},
14+
num::Bounded,
715
prelude::*,
816
ptr::{
917
const_align_up,
@@ -15,23 +23,75 @@ use kernel::{
1523
use crate::{
1624
driver::Bar0,
1725
fb::hal::FbHal,
18-
num::usize_into_u32, //
26+
num::usize_into_u32,
27+
regs, //
1928
};
2029

2130
struct Gb100;
2231

32+
impl RegisterBase<regs::Hshub0Base> for Gb100 {
33+
const BASE: usize = 0x0087_0000;
34+
}
35+
36+
fn read_sysmem_flush_page_gb100(bar: &Bar0) -> u64 {
37+
let lo = u64::from(
38+
bar.read(regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::of::<Gb100>())
39+
.adr(),
40+
);
41+
let hi = u64::from(
42+
bar.read(regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::of::<Gb100>())
43+
.adr(),
44+
);
45+
46+
lo | (hi << 32)
47+
}
48+
49+
/// Write the sysmem flush page address through the GB10x HSHUB0 registers.
50+
///
51+
/// Both the primary and EG (egress) register pairs must be programmed to the same address,
52+
/// as required by hardware.
53+
fn write_sysmem_flush_page_gb100(bar: &Bar0, addr: Bounded<u64, 52>) {
54+
// CAST: lower 32 bits. Hardware ignores bits 7:0.
55+
let addr_lo = *addr as u32;
56+
let addr_hi = addr.shr::<32, 20>().cast::<u32>();
57+
58+
// Write HI first. The hardware will trigger the flush on the LO write.
59+
60+
// Primary HSHUB pair.
61+
bar.write(
62+
regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::of::<Gb100>(),
63+
regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::zeroed().with_adr(addr_hi),
64+
);
65+
bar.write(
66+
regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::of::<Gb100>(),
67+
regs::NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::zeroed().with_adr(addr_lo),
68+
);
69+
70+
// EG (egress) pair -- must match the primary pair.
71+
bar.write(
72+
regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI::of::<Gb100>(),
73+
regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI::zeroed().with_adr(addr_hi),
74+
);
75+
bar.write(
76+
regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO::of::<Gb100>(),
77+
regs::NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO::zeroed().with_adr(addr_lo),
78+
);
79+
}
80+
2381
pub(super) const fn pmu_reserved_size_gb100() -> u32 {
2482
usize_into_u32::<{ const_align_up(SZ_8M + SZ_16M + SZ_4K, Alignment::new::<SZ_128K>()).unwrap() }>(
2583
)
2684
}
2785

2886
impl FbHal for Gb100 {
2987
fn read_sysmem_flush_page(&self, bar: &Bar0) -> u64 {
30-
super::ga100::read_sysmem_flush_page_ga100(bar)
88+
read_sysmem_flush_page_gb100(bar)
3189
}
3290

3391
fn write_sysmem_flush_page(&self, bar: &Bar0, addr: u64) -> Result {
34-
super::ga100::write_sysmem_flush_page_ga100(bar, addr);
92+
let addr = Bounded::<u64, 52>::try_new(addr).ok_or(EINVAL)?;
93+
94+
write_sysmem_flush_page_gb100(bar, addr);
3595

3696
Ok(())
3797
}

drivers/gpu/nova-core/fb/hal/gb202.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,67 @@
44
//! Blackwell GB20x framebuffer HAL.
55
66
use kernel::{
7+
io::{
8+
register::{
9+
RegisterBase,
10+
WithBase, //
11+
},
12+
Io, //
13+
},
14+
num::Bounded,
715
prelude::*,
816
sizes::SizeConstants, //
917
};
1018

1119
use crate::{
1220
driver::Bar0,
13-
fb::hal::FbHal, //
21+
fb::hal::FbHal,
22+
regs, //
1423
};
1524

1625
struct Gb202;
1726

27+
impl RegisterBase<regs::Fbhub0Base> for Gb202 {
28+
const BASE: usize = 0x008a_0000;
29+
}
30+
31+
fn read_sysmem_flush_page_gb202(bar: &Bar0) -> u64 {
32+
let lo = u64::from(
33+
bar.read(regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::of::<Gb202>())
34+
.adr(),
35+
);
36+
let hi = u64::from(
37+
bar.read(regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::of::<Gb202>())
38+
.adr(),
39+
);
40+
41+
lo | (hi << 32)
42+
}
43+
44+
/// Write the sysmem flush page address through the GB20x FBHUB0 registers.
45+
fn write_sysmem_flush_page_gb202(bar: &Bar0, addr: Bounded<u64, 52>) {
46+
// Write HI first. The hardware will trigger the flush on the LO write.
47+
bar.write(
48+
regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::of::<Gb202>(),
49+
regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::zeroed()
50+
.with_adr(addr.shr::<32, 20>().cast::<u32>()),
51+
);
52+
bar.write(
53+
regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::of::<Gb202>(),
54+
// CAST: lower 32 bits. Hardware ignores bits 7:0.
55+
regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::zeroed().with_adr(*addr as u32),
56+
);
57+
}
58+
1859
impl FbHal for Gb202 {
1960
fn read_sysmem_flush_page(&self, bar: &Bar0) -> u64 {
20-
super::ga100::read_sysmem_flush_page_ga100(bar)
61+
read_sysmem_flush_page_gb202(bar)
2162
}
2263

2364
fn write_sysmem_flush_page(&self, bar: &Bar0, addr: u64) -> Result {
24-
super::ga100::write_sysmem_flush_page_ga100(bar, addr);
65+
let addr = Bounded::<u64, 52>::try_new(addr).ok_or(EINVAL)?;
66+
67+
write_sysmem_flush_page_gb202(bar, addr);
2568

2669
Ok(())
2770
}

drivers/gpu/nova-core/regs.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// SPDX-License-Identifier: GPL-2.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
23

34
use kernel::{
45
io::{
@@ -147,6 +148,50 @@ register! {
147148
}
148149
}
149150

151+
/// Base of the GB10x HSHUB0 register window (`NV_HSHUB0_PRIV_BASE` in Open RM).
152+
///
153+
/// The base is provided by the GB10x framebuffer HAL.
154+
pub(crate) struct Hshub0Base(());
155+
156+
/// Base of the GB20x FBHUB0 register window (`NV_FBHUB0_PRI_BASE` in Open RM).
157+
///
158+
/// The base is provided by the GB20x framebuffer HAL.
159+
pub(crate) struct Fbhub0Base(());
160+
161+
register! {
162+
// GB10x sysmem flush registers, relative to the HSHUB0 base. GB10x routes sysmembar
163+
// through a primary and an EG (egress) pair that must both be programmed to the same
164+
// address. Hardware ignores bits 7:0 of each LO register. The boot path uses a fixed
165+
// HSHUB0 base, so the multiple runtime-discovered HSHUB bases are not needed here.
166+
pub(crate) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base + 0x00000e50 {
167+
31:0 adr => u32;
168+
}
169+
170+
pub(crate) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base + 0x00000e54 {
171+
19:0 adr;
172+
}
173+
174+
pub(crate) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base + 0x000006c0 {
175+
31:0 adr => u32;
176+
}
177+
178+
pub(crate) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base + 0x000006c4 {
179+
19:0 adr;
180+
}
181+
182+
// GB20x sysmem flush registers, relative to the FBHUB0 base. Unlike the older
183+
// NV_PFB_NISO_FLUSH_SYSMEM_ADDR registers which encode the address with an 8-bit
184+
// right-shift, these take the raw address split into lower and upper halves. Hardware
185+
// ignores bits 7:0 of the LO register.
186+
pub(crate) NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Fbhub0Base + 0x00001d58 {
187+
31:0 adr => u32;
188+
}
189+
190+
pub(crate) NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Fbhub0Base + 0x00001d5c {
191+
19:0 adr;
192+
}
193+
}
194+
150195
impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE {
151196
/// Returns the usable framebuffer size, in bytes.
152197
pub(crate) fn usable_fb_size(self) -> u64 {

0 commit comments

Comments
 (0)