* [PATCH] gpu: nova-core: make pramin/buddy optional
@ 2026-10-26 4:24 Dave Airlie via B4 Relay
2026-10-26 6:58 ` sashiko-bot
2026-10-26 18:50 ` Danilo Krummrich
0 siblings, 2 replies; 3+ messages in thread
From: Dave Airlie via B4 Relay @ 2026-10-26 4:24 UTC (permalink / raw)
To: Danilo Krummrich, Alexandre Courbot, David Airlie
Cc: nova-gpu, dri-devel, Dave Airlie
From: Dave Airlie <airlied@redhat.com>
These aren't used on systems with no framebuffer memory.
Signed-off-by: Dave Airlie <airlied@redhat.com>
---
drivers/gpu/nova-core/gpu.rs | 15 +++++++------
drivers/gpu/nova-core/mm.rs | 34 +++++++++++++++---------------
drivers/gpu/nova-core/mm/bar_user.rs | 14 ++++++------
drivers/gpu/nova-core/mm/pagetable/map.rs | 10 ++++-----
drivers/gpu/nova-core/mm/pagetable/walk.rs | 2 +-
5 files changed, 38 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 4e59072cab50..5d53fde2cdc1 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -564,18 +564,19 @@ pub(crate) fn new<'a>(
// Create GPU memory manager owning memory management resources.
mm: {
- let usable_vram = gsp_static_info.usable_fb_regions.first().ok_or(ENODEV)?;
- let buddy_params = GpuBuddyParams {
- base_offset: usable_vram.start,
- size: usable_vram.end - usable_vram.start,
- chunk_size: Alignment::new::<SZ_4K>(),
- };
+ let buddy_params = gsp_static_info.usable_fb_regions.first().map(|usable_vram| {
+ GpuBuddyParams {
+ base_offset: usable_vram.start,
+ size: usable_vram.end - usable_vram.start,
+ chunk_size: Alignment::new::<SZ_4K>(),
+ }
+ });
GpuMm::new(
bar,
gsp_resources.spec.chipset,
buddy_params,
- VramAddress::from_raw(gsp_static_info.total_fb_end),
+ Some(VramAddress::from_raw(gsp_static_info.total_fb_end)),
)?
},
diff --git a/drivers/gpu/nova-core/mm.rs b/drivers/gpu/nova-core/mm.rs
index 8a934c55169f..9a2c73c978be 100644
--- a/drivers/gpu/nova-core/mm.rs
+++ b/drivers/gpu/nova-core/mm.rs
@@ -71,12 +71,12 @@ macro_rules! impl_pfn_bounded {
/// GPU Memory Manager - owns all core MM components.
///
/// Provides centralized ownership of memory management resources:
-/// - [`GpuBuddy`] allocator for VRAM page table allocation.
-/// - [`pramin::Pramin`] for direct VRAM access.
+/// - Optional [`GpuBuddy`] allocator for VRAM page table allocation.
+/// - Optional [`pramin::Pramin`] for direct VRAM access.
/// - [`Tlb`] manager for translation buffer flush operations.
pub(crate) struct GpuMm<'gpu> {
- buddy: GpuBuddy,
- pramin: pramin::Pramin<'gpu>,
+ buddy: Option<GpuBuddy>,
+ pramin: Option<pramin::Pramin<'gpu>>,
tlb: Pin<KBox<Tlb<'gpu>>>,
}
@@ -85,28 +85,28 @@ impl<'gpu> GpuMm<'gpu> {
pub(crate) fn new(
bar: Bar0<'gpu>,
chipset: Chipset,
- buddy_params: GpuBuddyParams,
- total_fb_end: VramAddress,
+ buddy_params: Option<GpuBuddyParams>,
+ total_fb_end: Option<VramAddress>,
) -> Result<Self> {
- // PRAMIN covers all physical VRAM (including GSP-reserved areas
- // above the usable region, e.g. the BAR1 page directory).
- let vram_region = VramAddress::ZERO..total_fb_end;
-
Ok(Self {
- buddy: GpuBuddy::new(buddy_params)?,
- pramin: pramin::Pramin::new(bar, chipset, vram_region)?,
+ buddy: buddy_params.map(GpuBuddy::new).transpose()?,
+ // PRAMIN covers all physical VRAM, including GSP-reserved areas above
+ // the usable region, such as the BAR1 page directory.
+ pramin: total_fb_end
+ .map(|end| pramin::Pramin::new(bar, chipset, VramAddress::ZERO..end))
+ .transpose()?,
tlb: KBox::pin_init(Tlb::new(bar), GFP_KERNEL)?,
})
}
/// Access the [`GpuBuddy`] allocator.
- pub(crate) fn buddy(&self) -> &GpuBuddy {
- &self.buddy
+ pub(crate) fn buddy(&self) -> Result<&GpuBuddy> {
+ self.buddy.as_ref().ok_or(ENODEV)
}
/// Access the [`pramin::Pramin`].
- fn pramin_mut(&mut self) -> &mut pramin::Pramin<'gpu> {
- &mut self.pramin
+ fn pramin_mut(&mut self) -> Result<&mut pramin::Pramin<'gpu>> {
+ self.pramin.as_mut().ok_or(ENODEV)
}
/// Access the [`Tlb`] manager.
@@ -329,7 +329,7 @@ pub(crate) fn run(
return Ok(());
};
- pramin::selftest::run(dev, mm.pramin_mut(), VramAddress::from_raw(base))?;
+ pramin::selftest::run(dev, mm.pramin_mut()?, VramAddress::from_raw(base))?;
bar_user::run_self_test(dev, mm, bar_user, bar1_pdb, chipset)
}
}
diff --git a/drivers/gpu/nova-core/mm/bar_user.rs b/drivers/gpu/nova-core/mm/bar_user.rs
index 6e9384f06f43..baf9450b93a6 100644
--- a/drivers/gpu/nova-core/mm/bar_user.rs
+++ b/drivers/gpu/nova-core/mm/bar_user.rs
@@ -212,14 +212,14 @@ pub(crate) fn run_self_test(
let pdb_addr = VramAddress::from_raw(bar1_pdb);
// Check if initial page tables are in VRAM.
- if crate::mm::pagetable::check_pdb_valid(mm.pramin_mut(), pdb_addr, chipset).is_err() {
+ if crate::mm::pagetable::check_pdb_valid(mm.pramin_mut()?, pdb_addr, chipset).is_err() {
dev_info!(dev, "MM: Self-test SKIPPED - no valid VRAM page tables\n");
return Ok(());
}
// Set up a test page from the buddy allocator.
let test_page_blocks = KBox::pin_init(
- mm.buddy().alloc_blocks(
+ mm.buddy()?.alloc_blocks(
GpuBuddyAllocMode::Simple,
SZ_4K.into_safe_cast(),
Alignment::new::<SZ_4K>(),
@@ -245,7 +245,7 @@ pub(crate) fn run_self_test(
let vram_read_addr = test_vram + 0x100;
// Test 1: Write via PRAMIN, read via BAR1.
- mm.pramin_mut()
+ mm.pramin_mut()?
.window_at::<u32>(vram_read_addr)?
.view()
.write_val(PATTERN_PRAMIN);
@@ -296,7 +296,7 @@ pub(crate) fn run_self_test(
// Punch a 4K hole at base+16K so the subsequent 32K allocation must split.
let _hole = KBox::pin_init(
- mm.buddy().alloc_blocks(
+ mm.buddy()?.alloc_blocks(
GpuBuddyAllocMode::Range(range_base + sz_16k..range_base + sz_16k + sz_4k),
SZ_4K.into_safe_cast(),
Alignment::new::<SZ_4K>(),
@@ -308,7 +308,7 @@ pub(crate) fn run_self_test(
// Allocate 32K within [base, base+36K). The hole forces the allocator to return
// split blocks whose sizes are determined by buddy alignment.
let blocks = KBox::pin_init(
- mm.buddy().alloc_blocks(
+ mm.buddy()?.alloc_blocks(
GpuBuddyAllocMode::Range(range_base..range_base + sz_32k_4k),
SZ_32K.into_safe_cast(),
Alignment::new::<SZ_4K>(),
@@ -353,7 +353,7 @@ pub(crate) fn run_self_test(
bar1.try_write32(PATTERN_BAR1, page_bar1_off)?;
let pramin_val = mm
- .pramin_mut()
+ .pramin_mut()?
.window_at::<u32>(VramAddress::from_raw(page_phys))?
.view()
.read_val();
@@ -391,7 +391,7 @@ pub(crate) fn run_self_test(
let access = bar_user.map(mm, &[test_pfn], true)?;
// Write pattern via PRAMIN, read via BarUserAccess.
- mm.pramin_mut()
+ mm.pramin_mut()?
.window_at::<u32>(test_vram)?
.view()
.write_val(PATTERN_BAR1);
diff --git a/drivers/gpu/nova-core/mm/pagetable/map.rs b/drivers/gpu/nova-core/mm/pagetable/map.rs
index 77431c509a89..fd404b0734bb 100644
--- a/drivers/gpu/nova-core/mm/pagetable/map.rs
+++ b/drivers/gpu/nova-core/mm/pagetable/map.rs
@@ -81,7 +81,7 @@ pub(super) fn new(pdb_addr: VramAddress) -> Self {
/// Allocate and zero a physical page table page.
fn alloc_and_zero_page(mm: &mut GpuMm<'_>, level: PageTableLevel) -> Result<PreparedPtPage> {
let blocks = KBox::pin_init(
- mm.buddy().alloc_blocks(
+ mm.buddy()?.alloc_blocks(
GpuBuddyAllocMode::Simple,
SZ_4K.into_safe_cast(),
Alignment::new::<SZ_4K>(),
@@ -94,7 +94,7 @@ fn alloc_and_zero_page(mm: &mut GpuMm<'_>, level: PageTableLevel) -> Result<Prep
// Zero via PRAMIN.
let window = mm
- .pramin_mut()
+ .pramin_mut()?
.window_at::<[u64; PAGE_SIZE / 8]>(page_vram)?;
for i in 0..PAGE_SIZE / 8 {
io_write!(window.view(), [build: i], 0);
@@ -120,7 +120,7 @@ fn ensure_single_pte_path(
for _ in 0..max_iter {
let result = self
.walker
- .walk_pde_levels(mm.pramin_mut(), vfn, |install_addr| {
+ .walk_pde_levels(mm.pramin_mut()?, vfn, |install_addr| {
pt_pages.get(&install_addr).and_then(|p| {
p.alloc
.iter()
@@ -197,7 +197,7 @@ pub(super) fn install_mappings(
writable: bool,
) -> Result {
{
- let pramin = mm.pramin_mut();
+ let pramin = mm.pramin_mut()?;
// Drain prepared PT pages, install all pending PDEs.
let mut cursor = pt_pages.cursor_front_mut();
@@ -255,7 +255,7 @@ pub(super) fn invalidate_ptes(
let invalid_pte = M::Pte::invalid();
{
- let pramin = mm.pramin_mut();
+ let pramin = mm.pramin_mut()?;
for i in 0..num_pages {
let i_u64: u64 = i.into_safe_cast();
let vfn = Vfn::new(vfn_start.raw() + i_u64);
diff --git a/drivers/gpu/nova-core/mm/pagetable/walk.rs b/drivers/gpu/nova-core/mm/pagetable/walk.rs
index 76c1729971f5..19aae75c2c76 100644
--- a/drivers/gpu/nova-core/mm/pagetable/walk.rs
+++ b/drivers/gpu/nova-core/mm/pagetable/walk.rs
@@ -172,7 +172,7 @@ pub(super) fn walk_pde_levels(
///
/// Returns [`WalkResult::PageTableMissing`] if intermediate tables don't exist.
pub(super) fn walk_to_pte_lookup(&self, mm: &mut GpuMm<'_>, vfn: Vfn) -> Result<WalkResult> {
- self.walk_to_pte_lookup_with_window(mm.pramin_mut(), vfn)
+ self.walk_to_pte_lookup_with_window(mm.pramin_mut()?, vfn)
}
/// Walk to PTE using a caller-provided PRAMIN manager (lookup only).
---
base-commit: 3497a403264b094ebd61b8b755165d56e7d9dc37
change-id: 20261026-nova-pramin-option-50cdf1102281
Best regards,
--
Dave Airlie <airlied@redhat.com>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] gpu: nova-core: make pramin/buddy optional
2026-10-26 4:24 [PATCH] gpu: nova-core: make pramin/buddy optional Dave Airlie via B4 Relay
@ 2026-10-26 6:58 ` sashiko-bot
2026-10-26 18:50 ` Danilo Krummrich
1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-10-26 6:58 UTC (permalink / raw)
To: Dave Airlie, Danilo Krummrich, Alexandre Courbot, David Airlie
Cc: nova-gpu, dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] gpu: nova-core: Gpu::new() always passes Some for total_fb_end to GpuMm::new()
--
commit c48efe432798819fed4e7632bc17f4fc720dd7e4
Author: Dave Airlie <airlied@redhat.com>
gpu: nova-core: make pramin/buddy optional
This commit updates GpuMm so that the GpuBuddy allocator and Pramin manager
are optional to support GPU systems with no framebuffer memory.
> diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
> index 4e59072cab507..5d53fde2cdc1e 100644
> --- a/drivers/gpu/nova-core/gpu.rs
> +++ b/drivers/gpu/nova-core/gpu.rs
> @@ -564,18 +564,19 @@ pub(crate) fn new<'a>(
>
> // Create GPU memory manager owning memory management resources.
> mm: {
> - let usable_vram = gsp_static_info.usable_fb_regions.first().ok_or(ENODEV)?;
> - let buddy_params = GpuBuddyParams {
> - base_offset: usable_vram.start,
> - size: usable_vram.end - usable_vram.start,
> - chunk_size: Alignment::new::<SZ_4K>(),
> - };
> + let buddy_params = gsp_static_info.usable_fb_regions.first().map(|usable_vram| {
> + GpuBuddyParams {
> + base_offset: usable_vram.start,
> + size: usable_vram.end - usable_vram.start,
> + chunk_size: Alignment::new::<SZ_4K>(),
> + }
> + });
>
> GpuMm::new(
> bar,
> gsp_resources.spec.chipset,
> buddy_params,
> - VramAddress::from_raw(gsp_static_info.total_fb_end),
> + Some(VramAddress::from_raw(gsp_static_info.total_fb_end)),
> )?
> },
[Severity: Medium]
In Gpu::new(), the total_fb_end argument to GpuMm::new() is unconditionally
wrapped in Some(...). Since Gpu::new() is the only caller of GpuMm::new(),
won't GpuMm::new() always receive Some(...) for total_fb_end and
unconditionally call pramin::Pramin::new(), which writes the hardware BAR0
PRAMIN window base register via hal.write_pramin_window_base(bar, base) and
leaves GpuMm::pramin populated even on systems without framebuffer memory?
Also, in drivers/gpu/nova-core/gsp/commands.rs, GetGspStaticInfoReply::read()
still requires msg.total_fb_end() to be present when called from
Gpu::new() -> Gsp::get_static_info():
drivers/gpu/nova-core/gsp/commands.rs:GetGspStaticInfoReply::read() {
...
let total_fb_end = msg.total_fb_end().ok_or(EINVAL)?;
...
}
When GSP reports no framebuffer regions, msg.total_fb_end() returns None,
causing GetGspStaticInfoReply::read() to fail probe with EINVAL before
GpuMm::new() is reached.
Should GetGspStaticInfoReply::total_fb_end be changed to Option<u64> (or
Option<VramAddress>) and passed through to GpuMm::new() without wrapping it
unconditionally in Some(...)?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261026-nova-pramin-option-v1-1-d073b3f047fc@redhat.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] gpu: nova-core: make pramin/buddy optional
2026-10-26 4:24 [PATCH] gpu: nova-core: make pramin/buddy optional Dave Airlie via B4 Relay
2026-10-26 6:58 ` sashiko-bot
@ 2026-10-26 18:50 ` Danilo Krummrich
1 sibling, 0 replies; 3+ messages in thread
From: Danilo Krummrich @ 2026-10-26 18:50 UTC (permalink / raw)
To: Dave Airlie via B4 Relay
Cc: airlied, Alexandre Courbot, David Airlie, nova-gpu, dri-devel
On Mon Oct 26, 2026 at 5:24 AM CET, Dave Airlie via B4 Relay wrote:
> These aren't used on systems with no framebuffer memory.
Looks good, but I think it would be nice to have some more context in the commit
message.
Thanks,
Danilo
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-26 18:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-26 4:24 [PATCH] gpu: nova-core: make pramin/buddy optional Dave Airlie via B4 Relay
2026-10-26 6:58 ` sashiko-bot
2026-10-26 18:50 ` Danilo Krummrich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox