Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Support for optional full /dev/mem access even if host kernel has strict devmem
Peter Dinda [Wed, 13 Mar 2013 15:49:36 +0000 (10:49 -0500)]
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.

linux_module/Makefile
linux_module/allow_devmem.c [new file with mode: 0644]
linux_module/allow_devmem.h [new file with mode: 0644]
linux_module/main.c

index 3b8f699..a7eeb53 100644 (file)
@@ -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 (file)
index 0000000..696f98c
--- /dev/null
@@ -0,0 +1,119 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+
+#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 (file)
index 0000000..3b7c229
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _ALLOW_DEVMEM
+#define _ALLOW_DEVMEM
+
+
+
+int palacios_allow_devmem(void);
+int palacios_restore_devmem(void);
+
+#endif
index 296d01b..5c9ffa2 100644 (file)
 #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);