Commit 23437509 authored by Jocelyn Falempe's avatar Jocelyn Falempe
Browse files

drm/panic: Fix 24bit pixel crossing page boundaries



When using page list framebuffer, and using RGB888 format, some
pixels can cross the page boundaries, and this case was not handled,
leading to writing 1 or 2 bytes on the next virtual address.

Add a check and a specific function to handle this case.

Fixes: c9ff2808 ("drm/panic: Add support to scanout buffer as array of pages")
Reviewed-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Link: https://lore.kernel.org/r/20251009122955.562888-7-jfalempe@redhat.com


Signed-off-by: default avatarJocelyn Falempe <jfalempe@redhat.com>
parent 2e337dd2
Loading
Loading
Loading
Loading
+44 −2
Original line number Diff line number Diff line
@@ -174,6 +174,33 @@ static void drm_panic_write_pixel24(void *vaddr, unsigned int offset, u32 color)
	*p = color & 0xff;
}

/*
 * Special case if the pixel crosses page boundaries
 */
static void drm_panic_write_pixel24_xpage(void *vaddr, struct page *next_page,
					  unsigned int offset, u32 color)
{
	u8 *vaddr2;
	u8 *p = vaddr + offset;

	vaddr2 = kmap_local_page_try_from_panic(next_page);

	*p++ = color & 0xff;
	color >>= 8;

	if (offset == PAGE_SIZE - 1)
		p = vaddr2;

	*p++ = color & 0xff;
	color >>= 8;

	if (offset == PAGE_SIZE - 2)
		p = vaddr2;

	*p = color & 0xff;
	kunmap_local(vaddr2);
}

static void drm_panic_write_pixel32(void *vaddr, unsigned int offset, u32 color)
{
	u32 *p = vaddr + offset;
@@ -231,7 +258,14 @@ static void drm_panic_blit_page(struct page **pages, unsigned int dpitch,
					page = new_page;
					vaddr = kmap_local_page_try_from_panic(pages[page]);
				}
				if (vaddr)
				if (!vaddr)
					continue;

				// Special case for 24bit, as a pixel might cross page boundaries
				if (cpp == 3 && offset + 3 > PAGE_SIZE)
					drm_panic_write_pixel24_xpage(vaddr, pages[page + 1],
								      offset, fg32);
				else
					drm_panic_write_pixel(vaddr, offset, fg32, cpp);
			}
		}
@@ -321,6 +355,14 @@ static void drm_panic_fill_page(struct page **pages, unsigned int dpitch,
				page = new_page;
				vaddr = kmap_local_page_try_from_panic(pages[page]);
			}
			if (!vaddr)
				continue;

			// Special case for 24bit, as a pixel might cross page boundaries
			if (cpp == 3 && offset + 3 > PAGE_SIZE)
				drm_panic_write_pixel24_xpage(vaddr, pages[page + 1],
							      offset, color);
			else
				drm_panic_write_pixel(vaddr, offset, color, cpp);
		}
	}