From: Peter Dinda Date: Wed, 13 Mar 2013 15:49:36 +0000 (-0500) Subject: Support for optional full /dev/mem access even if host kernel has strict devmem X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=afdee70966b757149da1c1a47c5d0043a37336a1;p=palacios.releases.git Support for optional full /dev/mem access even if host kernel has strict devmem This adds a new option: insmod v3vee.ko allow_devmem=1 This will enable host user space programs to mmap any host physical memory using /dev/mem even if the host kernel has strict /dev/mem limitations. --- diff --git a/linux_module/Makefile b/linux_module/Makefile index 3b8f699..a7eeb53 100644 --- a/linux_module/Makefile +++ b/linux_module/Makefile @@ -17,6 +17,7 @@ v3vee-y := palacios-stubs.o \ main.o \ vm.o \ mm.o \ + allow_devmem.o \ util-queue.o \ util-hashtable.o \ linux-exts.o diff --git a/linux_module/allow_devmem.c b/linux_module/allow_devmem.c new file mode 100644 index 0000000..696f98c --- /dev/null +++ b/linux_module/allow_devmem.c @@ -0,0 +1,119 @@ +#include +#include +#include + +#include "palacios.h" +#include "allow_devmem.h" + +/* + The purpose of this component is to disable and reenable + strict devmem control. + + On kernels compiled with CONFIG_STRICT_DEVMEM, /dev/mem access + from user space is limited to the first 1 MB and to non-memory + regions (ie, devices). For various purposes in Palacios, + for example linux_usr/v3_guest_mem.[ch], we want to allow + host user space access to guest memory via mmap. + + This borrows from Dave Anderson @ Red Hat's implementation +*/ + +#define DEVMEM_CHECK_FUNC "devmem_is_allowed" + +static enum { NOTRUN=0, OPEN, SET, NOTSET } devmem_state = NOTRUN; + + +// this is invoked after return from devmem_is_allowed() +static int devmem_ret_handler(struct kretprobe_instance *ri, + struct pt_regs *regs) +{ + regs->ax = 1; // yes, it's allowed - "ax" now means "rax" + return 0; +} + +static struct kretprobe devmem_kretprobe = { + .handler = devmem_ret_handler, + .maxactive = 20 // up to 20 at a time +}; + + +int palacios_allow_devmem(void) +{ +#ifndef CONFIG_STRICT_DEVMEM + INFO("System already has open /dev/mem - doing nothing\n"); + devmem_state = OPEN; + return 0; +#else + switch (devmem_state) { + case NOTRUN: + case NOTSET: { + int rc; + + devmem_kretprobe.kp.symbol_name = DEVMEM_CHECK_FUNC; + + rc = register_kretprobe(&devmem_kretprobe); + + if (rc<0) { + ERROR("register_kretprobe failed, returned %d\n", rc); + return -1; + } + + devmem_state=SET; + INFO("/dev/mem is now enabled (probe at %p)\n",devmem_kretprobe.kp.addr); + + return 0; + } + + break; + default: + // already set + return 0; + break; + } +#endif +} + + +int palacios_restore_devmem(void) +{ +#ifndef CONFIG_STRICT_DEVMEM + INFO("System already has open /dev/mem - doing nothing\n"); + devmem_state = OPEN; + return 0; +#else + switch (devmem_state) { + case NOTRUN: + ERROR("Ignoring disable of dev mem\n"); + return 0; + case NOTSET: + INFO("/dev/mem not explicitly enabled, ignoring restore request\n"); + return 0; + break; + + case SET: { + + unregister_kretprobe(&devmem_kretprobe); + + if (devmem_kretprobe.nmissed>0) { + ERROR("Note: missed %d instances of %s\n", + devmem_kretprobe.nmissed, DEVMEM_CHECK_FUNC); + } + + devmem_state=NOTSET; + + INFO("Restored strict /dev/mem access\n"); + return 0; + } + + break; + default: + // already set + return 0; + break; + } + + return 0; +#endif +} + + diff --git a/linux_module/allow_devmem.h b/linux_module/allow_devmem.h new file mode 100644 index 0000000..3b7c229 --- /dev/null +++ b/linux_module/allow_devmem.h @@ -0,0 +1,9 @@ +#ifndef _ALLOW_DEVMEM +#define _ALLOW_DEVMEM + + + +int palacios_allow_devmem(void); +int palacios_restore_devmem(void); + +#endif diff --git a/linux_module/main.c b/linux_module/main.c index 296d01b..5c9ffa2 100644 --- a/linux_module/main.c +++ b/linux_module/main.c @@ -26,11 +26,11 @@ #include "palacios.h" #include "mm.h" #include "vm.h" +#include "allow_devmem.h" #include "linux-exts.h" - MODULE_LICENSE("GPL"); // Module parameter @@ -39,11 +39,16 @@ int cpu_list_len = 0; module_param_array(cpu_list, int, &cpu_list_len, 0644); MODULE_PARM_DESC(cpu_list, "Comma-delimited list of CPUs that Palacios will run on"); +static int allow_devmem = 0; +module_param(allow_devmem, int, 0); +MODULE_PARM_DESC(allow_devmem, "Allow general user-space /dev/mem access even if kernel is strict"); + // Palacios options parameter static char *options; module_param(options, charp, 0); MODULE_PARM_DESC(options, "Generic options to internal Palacios modules"); + int mod_allocs = 0; int mod_frees = 0; @@ -332,6 +337,9 @@ static int show_mem(char * buf, char ** start, off_t off, int count, } + + + static int __init v3_init(void) { dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number int ret = 0; @@ -339,6 +347,10 @@ static int __init v3_init(void) { palacios_init_mm(); + if (allow_devmem) { + palacios_allow_devmem(); + } + // Initialize Palacios palacios_vmm_init(options); @@ -460,6 +472,10 @@ static void __exit v3_exit(void) { deinit_lnx_extensions(); + if (allow_devmem) { + palacios_restore_devmem(); + } + palacios_deinit_mm(); remove_proc_entry("v3-guests", dir);