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

fbdev: vfb: simplify memory management

Substitute home-brewed memory management for framebuffer memory with what
core mm provide us: vmalloc_32_user() and remap_vmalloc_range()

The former is designed to allocate virtually contiguous area which is
32bit addressable and zeroed so it can be mapped to userspace without
leaking data. The latter does the similar job to remap_pfn_range() but
additionally validate vmalloc'ed area and it's size.

Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

authored by

Vladimir Murzin and committed by
Tomi Valkeinen
220be8d0 95cc44a0

+5 -81
+5 -81
drivers/video/fbdev/vfb.c
··· 41 41 module_param(mode_option, charp, 0); 42 42 MODULE_PARM_DESC(mode_option, "Preferred video mode (e.g. 640x480-8@60)"); 43 43 44 - /********************************************************************** 45 - * 46 - * Memory management 47 - * 48 - **********************************************************************/ 49 - static void *rvmalloc(unsigned long size) 50 - { 51 - void *mem; 52 - unsigned long adr; 53 - 54 - size = PAGE_ALIGN(size); 55 - mem = vmalloc_32(size); 56 - if (!mem) 57 - return NULL; 58 - 59 - /* 60 - * VFB must clear memory to prevent kernel info 61 - * leakage into userspace 62 - * VGA-based drivers MUST NOT clear memory if 63 - * they want to be able to take over vgacon 64 - */ 65 - 66 - memset(mem, 0, size); 67 - adr = (unsigned long) mem; 68 - while (size > 0) { 69 - SetPageReserved(vmalloc_to_page((void *)adr)); 70 - adr += PAGE_SIZE; 71 - size -= PAGE_SIZE; 72 - } 73 - 74 - return mem; 75 - } 76 - 77 - static void rvfree(void *mem, unsigned long size) 78 - { 79 - unsigned long adr; 80 - 81 - if (!mem) 82 - return; 83 - 84 - adr = (unsigned long) mem; 85 - while ((long) size > 0) { 86 - ClearPageReserved(vmalloc_to_page((void *)adr)); 87 - adr += PAGE_SIZE; 88 - size -= PAGE_SIZE; 89 - } 90 - vfree(mem); 91 - } 92 - 93 44 static const struct fb_videomode vfb_default = { 94 45 .xres = 640, 95 46 .yres = 480, ··· 369 418 static int vfb_mmap(struct fb_info *info, 370 419 struct vm_area_struct *vma) 371 420 { 372 - unsigned long start = vma->vm_start; 373 - unsigned long size = vma->vm_end - vma->vm_start; 374 - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; 375 - unsigned long page, pos; 376 - 377 - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 378 - return -EINVAL; 379 - if (size > info->fix.smem_len) 380 - return -EINVAL; 381 - if (offset > info->fix.smem_len - size) 382 - return -EINVAL; 383 - 384 - pos = (unsigned long)info->fix.smem_start + offset; 385 - 386 - while (size > 0) { 387 - page = vmalloc_to_pfn((void *)pos); 388 - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { 389 - return -EAGAIN; 390 - } 391 - start += PAGE_SIZE; 392 - pos += PAGE_SIZE; 393 - if (size > PAGE_SIZE) 394 - size -= PAGE_SIZE; 395 - else 396 - size = 0; 397 - } 398 - 399 - return 0; 400 - 421 + return remap_vmalloc_range(vma, (void *)info->fix.smem_start, vma->vm_pgoff); 401 422 } 402 423 403 424 #ifndef MODULE ··· 411 488 static int vfb_probe(struct platform_device *dev) 412 489 { 413 490 struct fb_info *info; 491 + unsigned int size = PAGE_ALIGN(videomemorysize); 414 492 int retval = -ENOMEM; 415 493 416 494 /* 417 495 * For real video cards we use ioremap. 418 496 */ 419 - if (!(videomemory = rvmalloc(videomemorysize))) 497 + if (!(videomemory = vmalloc_32_user(size))) 420 498 return retval; 421 499 422 500 info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev); ··· 458 534 err1: 459 535 framebuffer_release(info); 460 536 err: 461 - rvfree(videomemory, videomemorysize); 537 + vfree(videomemory); 462 538 return retval; 463 539 } 464 540 ··· 468 544 469 545 if (info) { 470 546 unregister_framebuffer(info); 471 - rvfree(videomemory, videomemorysize); 547 + vfree(videomemory); 472 548 fb_dealloc_cmap(&info->cmap); 473 549 framebuffer_release(info); 474 550 }