--- mmap-orig.c 2020-08-06 10:27:00.844340199 -0700 +++ mmap-mod.c 2020-08-06 10:33:36.733107851 -0700 @@ -11,7 +11,12 @@ static const char *filename = "lkmc_mmap"; -enum { BUFFER_SIZE = 4 }; +#ifndef PAGE_SIZE //should be defined in kernel +#define PAGE_SIZE 4096 +#endif +#define BUFFER_PAGES 64 +#define PAGES_ORDER 6 //2^6 = 64 pages +#define BUFFER_SIZE (PAGE_SIZE * BUFFER_PAGES) struct mmap_info { char *data; @@ -32,7 +37,7 @@ pr_info("vm_fault\n"); info = (struct mmap_info *)vmf->vma->vm_private_data; if (info->data) { - page = virt_to_page(info->data); + page = virt_to_page(info->data + (PAGE_SIZE * vmf->pgoff)); get_page(page); vmf->page = page; } @@ -69,8 +74,14 @@ pr_info("open\n"); info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL); pr_info("virt_to_phys = 0x%llx\n", (unsigned long long)virt_to_phys((void *)info)); - info->data = (char *)get_zeroed_page(GFP_KERNEL); - memcpy(info->data, "asdf", BUFFER_SIZE); + info->data = (char *)__get_free_pages(GFP_KERNEL, PAGES_ORDER); + if(info->data == NULL) + { + pr_err("Unable to allocate framebuffer!\n"); + return -ENOMEM; + } + memset(info->data, 0, PAGE_SIZE << PAGES_ORDER); //zero the buffer + memcpy(info->data, "asdf", 4); filp->private_data = info; return 0; } @@ -105,10 +116,13 @@ static int release(struct inode *inode, struct file *filp) { struct mmap_info *info; + struct page *page; pr_info("release\n"); info = filp->private_data; - free_page((unsigned long)info->data); + page = virt_to_page(info->data); + put_page(page); + free_pages((unsigned long)info->data, PAGES_ORDER); kfree(info); filp->private_data = NULL; return 0;