Files
linux/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gb100.c
Timur Tabi 31d3354f42 drm/nouveau: verify that hardware supports the flush page address
Ensure that the DMA address of the framebuffer flush page is not larger
than its hardware register.

On GPUs older than Hopper, the register for the address can hold up to a
40-bit address (right-shifted by 8 so that it fits in the 32-bit
register), and on Hopper and later it can be 52 bits (64-bit register
where bits 52-63 must be zero).

Recently it was discovered that under certain conditions, the flush page
could be allocated outside this range.  Although this bug was fixed, we
can ensure that any future changes to this code don't accidentally
generate an invalid page address.

Signed-off-by: Timur Tabi <ttabi@nvidia.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patch.msgid.link/20251113230323.1271726-2-ttabi@nvidia.com
2025-11-24 17:53:22 -05:00

38 lines
1.2 KiB
C

/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "priv.h"
#include <nvhw/drf.h>
#include <nvhw/ref/gb100/dev_hshub_base.h>
static void
gb100_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
{
const u32 addr_hi = upper_32_bits(fb->sysmem.flush_page_addr);
const u32 addr_lo = lower_32_bits(fb->sysmem.flush_page_addr);
const u32 hshub = DRF_LO(NV_PFB_HSHUB0);
struct nvkm_device *device = fb->subdev.device;
// Ensure that the address is within hardware limits
WARN_ON(fb->sysmem.flush_page_addr > DMA_BIT_MASK(52));
nvkm_wr32(device, hshub + NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI, addr_hi);
nvkm_wr32(device, hshub + NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO, addr_lo);
nvkm_wr32(device, hshub + NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI, addr_hi);
nvkm_wr32(device, hshub + NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO, addr_lo);
}
static const struct nvkm_fb_func
gb100_fb = {
.sysmem.flush_page_init = gb100_fb_sysmem_flush_page_init,
.vidmem.size = ga102_fb_vidmem_size,
};
int
gb100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)
{
return r535_fb_new(&gb100_fb, device, type, inst, pfb);
}