From bcaacec1ca714224807728a63eccb37e3d685cd6 Mon Sep 17 00:00:00 2001 From: Glenn Elliott Date: Fri, 8 Mar 2013 00:43:41 -0500 Subject: uncachedev: mmap memory that is not cached by CPUs This patch creates a new character device, uncachedev. Pages of RAM allocated by this device are not cached by CPUs. Uses for such pages: 1) Determining *very* pessimistic emperical worst- case execution times. 2) Compare against performance with caches (quantify the avg. case benefit). 3) Deterministic memory accesses (access cannot cause a cache eviction.) 4) Theoretically, increased performance can be achieved by storing infrequently accessed data in uncache pages. uncachedev allocates pages with the pgprot_noncached() page attribute for user applications. Since pages allocated by uncachedev are not locked in memory by default, applications with any access level may mmap pages with uncachedev. Limitations: 1) Uncache pages must be MAP_PRIVATE. 2) Remapping not supported. Usage (user level): int size = NR_PAGES*PAGE_SIZE; int fd = open("/dev/litmus/uncache", O_RDWR); char *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); <...do stuff...> munmap(data, size); --- litmus/Makefile | 1 + litmus/uncachedev.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 litmus/uncachedev.c diff --git a/litmus/Makefile b/litmus/Makefile index d26ca7076b62..2bddc94a399f 100644 --- a/litmus/Makefile +++ b/litmus/Makefile @@ -18,6 +18,7 @@ obj-y = sched_plugin.o litmus.o \ bheap.o \ binheap.o \ ctrldev.o \ + uncachedev.o \ sched_gsn_edf.o \ sched_psn_edf.o \ sched_pfp.o diff --git a/litmus/uncachedev.c b/litmus/uncachedev.c new file mode 100644 index 000000000000..06a6a7c17983 --- /dev/null +++ b/litmus/uncachedev.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* device for allocating pages not cached by the CPU */ + +#define UNCACHE_NAME "litmus/uncache" + +void litmus_uncache_vm_open(struct vm_area_struct *vma) +{ +} + +void litmus_uncache_vm_close(struct vm_area_struct *vma) +{ +} + +int litmus_uncache_vm_fault(struct vm_area_struct* vma, + struct vm_fault* vmf) +{ + /* modeled after SG DMA video4linux, but without DMA. */ + /* (see drivers/media/video/videobuf-dma-sg.c) */ + struct page *page; + + page = alloc_page(GFP_USER); + if (!page) + return VM_FAULT_OOM; + + clear_user_highpage(page, (unsigned long)vmf->virtual_address); + vmf->page = page; + + return 0; +} + +static struct vm_operations_struct litmus_uncache_vm_ops = { + .open = litmus_uncache_vm_open, + .close = litmus_uncache_vm_close, + .fault = litmus_uncache_vm_fault, +}; + +static int litmus_uncache_mmap(struct file* filp, struct vm_area_struct* vma) +{ + /* first make sure mapper knows what he's doing */ + + /* you can only map the "first" page */ + if (vma->vm_pgoff != 0) + return -EINVAL; + + /* you can't share it with anyone */ + if (vma->vm_flags & (VM_MAYSHARE | VM_SHARED)) + return -EINVAL; + + /* cannot be expanded, and is not a "normal" page. */ + vma->vm_flags |= VM_DONTEXPAND; + + /* noncached pages are not explicitly locked in memory (for now). */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + vma->vm_ops = &litmus_uncache_vm_ops; + + return 0; +} + +static struct file_operations litmus_uncache_fops = { + .owner = THIS_MODULE, + .mmap = litmus_uncache_mmap, +}; + +static struct miscdevice litmus_uncache_dev = { + .name = UNCACHE_NAME, + .minor = MISC_DYNAMIC_MINOR, + .fops = &litmus_uncache_fops, + /* pages are not locked, so there is no reason why + anyone cannot allocate an uncache pages */ + .mode = (S_IRUGO | S_IWUGO), +}; + +static int __init init_litmus_uncache_dev(void) +{ + int err; + + printk("Initializing LITMUS^RT uncache device.\n"); + err = misc_register(&litmus_uncache_dev); + if (err) + printk("Could not allocate %s device (%d).\n", UNCACHE_NAME, err); + return err; +} + +static void __exit exit_litmus_uncache_dev(void) +{ + misc_deregister(&litmus_uncache_dev); +} + +module_init(init_litmus_uncache_dev); +module_exit(exit_litmus_uncache_dev); -- cgit v1.2.2