Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fbdev: Warn on incorrect framebuffer access

Test in framebuffer read, write and drawing helpers if FBINFO_VIRTFB
has been set correctly. Framebuffers in I/O memory should only be
accessed with the architecture's respective helpers. Framebuffers
in system memory should be accessed with the regular load and
store operations. Presumably not all drivers get this right, so we
now warn about it.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231127131655.4020-32-tzimmermann@suse.de

+40 -1
+3
drivers/video/fbdev/core/cfbcopyarea.c
··· 391 391 if (p->state != FBINFO_STATE_RUNNING) 392 392 return; 393 393 394 + if (p->flags & FBINFO_VIRTFB) 395 + fb_warn_once(p, "Framebuffer is not in I/O address space."); 396 + 394 397 /* if the beginning of the target area might overlap with the end of 395 398 the source area, be have to copy the area reverse. */ 396 399 if ((dy == sy && dx > sx) || (dy > sy)) {
+3
drivers/video/fbdev/core/cfbfillrect.c
··· 287 287 if (p->state != FBINFO_STATE_RUNNING) 288 288 return; 289 289 290 + if (p->flags & FBINFO_VIRTFB) 291 + fb_warn_once(p, "Framebuffer is not in I/O address space."); 292 + 290 293 if (p->fix.visual == FB_VISUAL_TRUECOLOR || 291 294 p->fix.visual == FB_VISUAL_DIRECTCOLOR ) 292 295 fg = ((u32 *) (p->pseudo_palette))[rect->color];
+3
drivers/video/fbdev/core/cfbimgblt.c
··· 326 326 if (p->state != FBINFO_STATE_RUNNING) 327 327 return; 328 328 329 + if (p->flags & FBINFO_VIRTFB) 330 + fb_warn_once(p, "Framebuffer is not in I/O address space."); 331 + 329 332 bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); 330 333 start_index = bitstart & (32 - 1); 331 334 pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
+9
drivers/video/fbdev/core/fb_io_fops.c
··· 12 12 int c, cnt = 0, err = 0; 13 13 unsigned long total_size, trailing; 14 14 15 + if (info->flags & FBINFO_VIRTFB) 16 + fb_warn_once(info, "Framebuffer is not in I/O address space."); 17 + 15 18 if (!info->screen_base) 16 19 return -ENODEV; 17 20 ··· 75 72 u8 __iomem *dst; 76 73 int c, cnt = 0, err = 0; 77 74 unsigned long total_size, trailing; 75 + 76 + if (info->flags & FBINFO_VIRTFB) 77 + fb_warn_once(info, "Framebuffer is not in I/O address space."); 78 78 79 79 if (!info->screen_base) 80 80 return -ENODEV; ··· 143 137 unsigned long start = info->fix.smem_start; 144 138 u32 len = info->fix.smem_len; 145 139 unsigned long mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT; 140 + 141 + if (info->flags & FBINFO_VIRTFB) 142 + fb_warn_once(info, "Framebuffer is not in I/O address space."); 146 143 147 144 /* 148 145 * This can be either the framebuffer mapping, or if pgoff points
+6
drivers/video/fbdev/core/fb_sys_fops.c
··· 22 22 unsigned long total_size, c; 23 23 ssize_t ret; 24 24 25 + if (!(info->flags & FBINFO_VIRTFB)) 26 + fb_warn_once(info, "Framebuffer is not in virtual address space."); 27 + 25 28 if (!info->screen_buffer) 26 29 return -ENODEV; 27 30 ··· 66 63 int err = 0; 67 64 unsigned long total_size, c; 68 65 size_t ret; 66 + 67 + if (!(info->flags & FBINFO_VIRTFB)) 68 + fb_warn_once(info, "Framebuffer is not in virtual address space."); 69 69 70 70 if (!info->screen_buffer) 71 71 return -ENODEV;
+3
drivers/video/fbdev/core/syscopyarea.c
··· 324 324 if (p->state != FBINFO_STATE_RUNNING) 325 325 return; 326 326 327 + if (!(p->flags & FBINFO_VIRTFB)) 328 + fb_warn_once(p, "Framebuffer is not in virtual address space."); 329 + 327 330 /* if the beginning of the target area might overlap with the end of 328 331 the source area, be have to copy the area reverse. */ 329 332 if ((dy == sy && dx > sx) || (dy > sy)) {
+3
drivers/video/fbdev/core/sysfillrect.c
··· 242 242 if (p->state != FBINFO_STATE_RUNNING) 243 243 return; 244 244 245 + if (!(p->flags & FBINFO_VIRTFB)) 246 + fb_warn_once(p, "Framebuffer is not in virtual address space."); 247 + 245 248 if (p->fix.visual == FB_VISUAL_TRUECOLOR || 246 249 p->fix.visual == FB_VISUAL_DIRECTCOLOR ) 247 250 fg = ((u32 *) (p->pseudo_palette))[rect->color];
+3
drivers/video/fbdev/core/sysimgblt.c
··· 296 296 if (p->state != FBINFO_STATE_RUNNING) 297 297 return; 298 298 299 + if (!(p->flags & FBINFO_VIRTFB)) 300 + fb_warn_once(p, "Framebuffer is not in virtual address space."); 301 + 299 302 bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); 300 303 start_index = bitstart & (32 - 1); 301 304 pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
+7 -1
include/linux/fb.h
··· 849 849 } 850 850 #endif 851 851 852 - /* Convenience logging macros */ 852 + /* 853 + * Convenience logging macros 854 + */ 855 + 853 856 #define fb_err(fb_info, fmt, ...) \ 854 857 pr_err("fb%d: " fmt, (fb_info)->node, ##__VA_ARGS__) 855 858 #define fb_notice(info, fmt, ...) \ ··· 863 860 pr_info("fb%d: " fmt, (fb_info)->node, ##__VA_ARGS__) 864 861 #define fb_dbg(fb_info, fmt, ...) \ 865 862 pr_debug("fb%d: " fmt, (fb_info)->node, ##__VA_ARGS__) 863 + 864 + #define fb_warn_once(fb_info, fmt, ...) \ 865 + pr_warn_once("fb%d: " fmt, (fb_info)->node, ##__VA_ARGS__) 866 866 867 867 #endif /* _LINUX_FB_H */