Skip to content

Commit 31d3354

Browse files
ttabiLyude
authored andcommitted
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
1 parent 04d98b3 commit 31d3354

5 files changed

Lines changed: 15 additions & 0 deletions

File tree

drivers/gpu/drm/nouveau/nvkm/subdev/fb/gb100.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ gb100_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
1515
const u32 hshub = DRF_LO(NV_PFB_HSHUB0);
1616
struct nvkm_device *device = fb->subdev.device;
1717

18+
// Ensure that the address is within hardware limits
19+
WARN_ON(fb->sysmem.flush_page_addr > DMA_BIT_MASK(52));
20+
1821
nvkm_wr32(device, hshub + NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI, addr_hi);
1922
nvkm_wr32(device, hshub + NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO, addr_lo);
2023
nvkm_wr32(device, hshub + NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI, addr_hi);

drivers/gpu/drm/nouveau/nvkm/subdev/fb/gb202.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ gb202_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
1313
struct nvkm_device *device = fb->subdev.device;
1414
const u64 addr = fb->sysmem.flush_page_addr;
1515

16+
// Ensure that the address is within hardware limits
17+
WARN_ON(fb->sysmem.flush_page_addr > DMA_BIT_MASK(52));
18+
1619
nvkm_wr32(device, NV_PFB_FBHUB0_PCIE_FLUSH_SYSMEM_ADDR_HI, upper_32_bits(addr));
1720
nvkm_wr32(device, NV_PFB_FBHUB0_PCIE_FLUSH_SYSMEM_ADDR_LO, lower_32_bits(addr));
1821
}

drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ gf100_fb_init_page(struct nvkm_fb *fb)
8080
void
8181
gf100_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
8282
{
83+
// Ensure that the address can actually fit in the register
84+
WARN_ON(fb->sysmem.flush_page_addr > DMA_BIT_MASK(40));
85+
8386
nvkm_wr32(fb->subdev.device, 0x100c10, fb->sysmem.flush_page_addr >> 8);
8487
}
8588

drivers/gpu/drm/nouveau/nvkm/subdev/fb/gh100.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ gh100_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
1313
const u64 addr = fb->sysmem.flush_page_addr >> NV_PFB_NISO_FLUSH_SYSMEM_ADDR_SHIFT;
1414
struct nvkm_device *device = fb->subdev.device;
1515

16+
// Ensure that the address is within hardware limits
17+
WARN_ON(fb->sysmem.flush_page_addr > DMA_BIT_MASK(52));
18+
1619
nvkm_wr32(device, NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI, upper_32_bits(addr));
1720
nvkm_wr32(device, NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO, lower_32_bits(addr));
1821
}

drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ nv50_fb_tags(struct nvkm_fb *base)
214214
static void
215215
nv50_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
216216
{
217+
// Ensure that the address can actually fit in the register
218+
WARN_ON(fb->sysmem.flush_page_addr > DMA_BIT_MASK(40));
219+
217220
nvkm_wr32(fb->subdev.device, 0x100c08, fb->sysmem.flush_page_addr >> 8);
218221
}
219222

0 commit comments

Comments
 (0)