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.


Merge branch 'devel' of ssh://palacios@newskysaw.cs.northwestern.edu/home/palacios...
Patrick Bridges [Mon, 13 Jun 2011 19:07:05 +0000 (13:07 -0600)]
28 files changed:
linux_module/Makefile
linux_module/ld.cmd
linux_module/linux-exts.c [new file with mode: 0644]
linux_module/linux-exts.h [new file with mode: 0644]
linux_module/palacios-console.c
linux_module/palacios-console.h [deleted file]
linux_module/palacios-dev.c
linux_module/palacios-file.c
linux_module/palacios-file.h [deleted file]
linux_module/palacios-graphics-console.c
linux_module/palacios-graphics-console.h
linux_module/palacios-host-dev.c
linux_module/palacios-host-dev.h [deleted file]
linux_module/palacios-inspector.c
linux_module/palacios-inspector.h [deleted file]
linux_module/palacios-keyed-stream.c
linux_module/palacios-keyed-stream.h [deleted file]
linux_module/palacios-packet.c
linux_module/palacios-packet.h [deleted file]
linux_module/palacios-socket.c
linux_module/palacios-socket.h [deleted file]
linux_module/palacios-stream.c
linux_module/palacios-stream.h [deleted file]
linux_module/palacios-vm.c
linux_module/palacios-vm.h
linux_module/palacios-vnet.c
linux_module/palacios.h
palacios/include/palacios/vmm_instr_decoder.h

index b3bd558..bedce06 100644 (file)
@@ -9,61 +9,34 @@ endif
 EXTRA_CFLAGS  += -I$(PWD)/../palacios/include/ -include autoconf.h -DMODULE=1 -D__KERNEL__=1
 
 
-v3vee-objs :=  palacios.o \
+v3vee-y :=     palacios.o \
                palacios-dev.o \
                palacios-vm.o \
                palacios-mm.o \
                palacios-queue.o \
-               palacios-hashtable.o
+               palacios-hashtable.o \
+               linux-exts.o
 
-ifdef V3_CONFIG_CONSOLE
-       v3vee-objs +=   palacios-console.o
-endif
-
-ifdef V3_CONFIG_FILE
-       v3vee-objs +=   palacios-file.o 
-endif
-
-ifdef V3_CONFIG_STREAM
-       v3vee-objs +=   palacios-stream.o \
-                       palacios-ringbuffer.o
-endif
-
-ifdef V3_CONFIG_EXT_INSPECTOR
-       v3vee-objs += palacios-inspector.o
-endif
-
-ifdef V3_CONFIG_VNET
-       v3vee-objs +=   palacios-vnet.o \
-                       palacios-vnet-ctrl.o   \
-                       palacios-vnet-brg.o
-endif
+v3vee-$(V3_CONFIG_CONSOLE) += palacios-console.o
+v3vee-$(V3_CONFIG_FILE) += palacios-file.o
+v3vee-$(V3_CONFIG_STREAM) +=   palacios-stream.o \
+                               palacios-ringbuffer.o
+v3vee-$(V3_CONFIG_EXT_INSPECTOR) += palacios-inspector.o
+v3vee-$(V3_CONFIG_PACKET) += palacios-packet.o
+v3vee-$(V3_CONFIG_SOCKET) += palacios-socket.o
+v3vee-$(V3_CONFIG_KEYED_STREAMS) += palacios-keyed-stream.o
+v3vee-$(V3_CONFIG_HOST_DEVICE) += palacios-host-dev.o
+v3vee-$(V3_CONFIG_GRAPHICS_CONSOLE) += palacios-graphics-console.o
 
-ifdef V3_CONFIG_PACKET
-       v3vee-objs += palacios-packet.o
-endif
-
-ifdef V3_CONFIG_SOCKET
-       v3vee-objs += palacios-socket.o
-endif
-
-ifdef V3_CONFIG_KEYED_STREAMS
-       v3vee-objs += palacios-keyed-stream.o
-endif
-
-ifdef V3_CONFIG_HOST_DEVICE
-       v3vee-objs += palacios-host-dev.o
-endif
-
-ifdef V3_CONFIG_GRAPHICS_CONSOLE
-       v3vee-objs += palacios-graphics-console.o
-endif
+v3vee-$(V3_CONFIG_VNET) +=     palacios-vnet.o \
+                               palacios-vnet-ctrl.o   \
+                               palacios-vnet-brg.o
 
 
 
-v3vee-objs += ../libv3vee.a 
 
 
+v3vee-objs := $(v3vee-y) ../libv3vee.a
 
 obj-m := v3vee.o
 
index 7dd7747..bd86dc7 100644 (file)
@@ -1,5 +1,12 @@
 SECTIONS
 {
+
+       _lnx_exts :
+       {
+               __start__lnx_exts = .;
+               *(_lnx_exts);
+               __stop__lnx_exts = .;   
+       }
        _v3_devices :
        {
                __start__v3_devices = .;
@@ -22,5 +29,6 @@ SECTIONS
                __stop__v3_extensions = .;
 
        }
+
 }
 
diff --git a/linux_module/linux-exts.c b/linux_module/linux-exts.c
new file mode 100644 (file)
index 0000000..d07cef0
--- /dev/null
@@ -0,0 +1,129 @@
+
+#include "linux-exts.h"
+
+/* 
+ * This is a place holder to ensure that the _lnx_exts section gets created by gcc
+ */
+
+
+static struct {} null_ext  __attribute__((__used__))                    \
+    __attribute__((unused, __section__ ("_lnx_exts"),                  \
+                  aligned(sizeof(void *))));
+
+struct vm_ext {
+    struct linux_ext * impl;
+    void * vm_data;
+    struct list_head node;
+};
+
+
+void * get_vm_ext_data(struct v3_guest * guest, char * ext_name) {
+    struct vm_ext * ext = NULL;
+
+    list_for_each_entry(ext, &(guest->exts), node) {
+       if (strncmp(ext->impl->name, ext_name, strlen(ext->impl->name)) == 0) {
+           return ext->vm_data;
+       }
+    }
+
+    return NULL;
+}
+
+
+int init_vm_extensions(struct v3_guest * guest) {
+    extern struct linux_ext * __start__lnx_exts[];
+    extern struct linux_ext * __stop__lnx_exts[];
+    struct linux_ext * ext_impl = __start__lnx_exts[0];
+    int i = 0;
+
+    while (ext_impl != __stop__lnx_exts[0]) {
+       struct vm_ext * ext = NULL;
+
+       if (ext_impl->guest_init == NULL) {
+           // We can have global extensions without per guest state
+           ext_impl = __start__lnx_exts[++i];
+           continue;
+       }
+       
+       printk("Registering Linux Extension (%s)\n", ext_impl->name);
+
+       ext = kmalloc(sizeof(struct vm_ext), GFP_KERNEL);
+       
+       if (!ext) {
+           printk("Error allocating VM extension (%s)\n", ext_impl->name);
+           return -1;
+       }
+
+       ext->impl = ext_impl;
+
+       ext_impl->guest_init(guest, &(ext->vm_data));
+
+       list_add(&(ext->node), &(guest->exts));
+
+       ext_impl = __start__lnx_exts[++i];
+    }
+    
+    return 0;
+}
+
+
+
+int deinit_vm_extensions(struct v3_guest * guest) {
+    struct vm_ext * ext = NULL;
+    struct vm_ext * tmp = NULL;
+
+    list_for_each_entry_safe(ext, tmp, &(guest->exts), node) {
+       if (ext->impl->guest_deinit) {
+           ext->impl->guest_deinit(guest, ext->vm_data);
+       } else {
+           printk("WARNING: Extension %s, does not have a guest deinit function\n", ext->impl->name);
+       }
+
+       list_del(&(ext->node));
+       kfree(ext);
+    }
+
+    return 0;
+}
+
+int init_lnx_extensions( void ) {
+    extern struct linux_ext * __start__lnx_exts[];
+    extern struct linux_ext * __stop__lnx_exts[];
+    struct linux_ext * tmp_ext = __start__lnx_exts[0];
+    int i = 0;
+
+    while (tmp_ext != __stop__lnx_exts[0]) {
+
+       printk("tmp_ext=%p\n", tmp_ext);
+
+       if (tmp_ext->init != NULL) {
+           printk("Registering Linux Extension (%s)\n", tmp_ext->name);
+           tmp_ext->init();
+       }
+
+       tmp_ext = __start__lnx_exts[++i];
+    }
+    
+    return 0;
+}
+
+
+int deinit_lnx_extensions( void ) {
+    extern struct linux_ext * __start__lnx_exts[];
+    extern struct linux_ext * __stop__lnx_exts[];
+    struct linux_ext * tmp_ext = __start__lnx_exts[0];
+    int i = 0;
+
+    while (tmp_ext != __stop__lnx_exts[0]) {
+       printk("Cleaning up Linux Extension (%s)\n", tmp_ext->name);
+       if (tmp_ext->deinit != NULL) {
+           tmp_ext->deinit();
+       } else {
+           printk("WARNING: Extension %s does not have a global deinit function\n", tmp_ext->name);
+       }
+
+       tmp_ext = __start__lnx_exts[++i];
+    }
+    
+    return 0;
+}
diff --git a/linux_module/linux-exts.h b/linux_module/linux-exts.h
new file mode 100644 (file)
index 0000000..c5aeea1
--- /dev/null
@@ -0,0 +1,34 @@
+#include "palacios.h"
+
+
+int add_mod_cmd(struct v3_guest * guest, unsigned int cmd, 
+               int (*handler)(struct v3_guest * guest, 
+                              unsigned int cmd, unsigned long arg));
+
+
+struct linux_ext {
+    char * name;
+    int (*init)( void );
+    int (*deinit)( void );
+    int (*guest_init)(struct v3_guest * guest, void ** priv_data);
+    int (*guest_deinit)(struct v3_guest * guest, void * priv_data);
+};
+
+
+
+int init_lnx_extensions( void );
+int deinit_lnx_extensions( void );
+
+int init_vm_extensions(struct v3_guest * guest);
+int deinit_vm_extensions(struct v3_guest * guest);
+
+void * get_vm_ext_data(struct v3_guest * guest, char * ext_name);
+
+
+
+#define register_extension(ext)                                        \
+    static struct linux_ext * _lnx_ext                         \
+    __attribute__((used))                                      \
+       __attribute__((unused, __section__("_lnx_exts"),                \
+                      aligned(sizeof(void *))))                \
+       = ext;
index 7ba96bd..d0c85ba 100644 (file)
 #include <interfaces/vmm_console.h>
 #include <palacios/vmm_host_events.h>
 
+#include "palacios-vm.h"
 #include "palacios.h"
-#include "palacios-console.h"
 #include "palacios-queue.h"
+#include "linux-exts.h"
 
 typedef enum { CONSOLE_CURS_SET = 1,
               CONSOLE_CHAR_SET = 2,
@@ -28,6 +29,23 @@ typedef enum { CONSOLE_CURS_SET = 1,
 
 
 
+struct palacios_console {
+    struct gen_queue * queue;
+    spinlock_t lock;
+
+    int open;
+    int connected;
+
+    wait_queue_head_t intr_queue;
+
+    unsigned int width;
+    unsigned int height;
+
+    struct v3_guest * guest;
+};
+
+
+
 struct cursor_msg {
     int x;
     int y;
@@ -186,8 +204,9 @@ static struct file_operations cons_fops = {
 
 
 
-int connect_console(struct v3_guest * guest) {
-    struct palacios_console * cons = &(guest->console);
+static int console_connect(struct v3_guest * guest, unsigned int cmd, 
+                          unsigned long arg, void * priv_data) {
+    struct palacios_console * cons = priv_data;
     int cons_fd = 0;
     unsigned long flags;
 
@@ -219,7 +238,7 @@ int connect_console(struct v3_guest * guest) {
 
 static void * palacios_tty_open(void * private_data, unsigned int width, unsigned int height) {
     struct v3_guest * guest = (struct v3_guest *)private_data;
-    struct palacios_console * cons = &(guest->console);
+    struct palacios_console * cons = kmalloc(sizeof(struct palacios_console), GFP_KERNEL);
 
     printk("Guest initialized virtual console (Guest=%s)\n", guest->name);
 
@@ -234,19 +253,20 @@ static void * palacios_tty_open(void * private_data, unsigned int width, unsigne
     }
 
 
-    cons->width = width;
-    cons->height = height;
-
     cons->queue = create_queue(CONSOLE_QUEUE_LEN);
     spin_lock_init(&(cons->lock));
     init_waitqueue_head(&(cons->intr_queue));
 
     cons->guest = guest;
 
-    cons->open = 1;
     cons->connected = 0;
+    cons->width = width;
+    cons->height = height;
+    cons->open = 1;
 
 
+    add_guest_ctrl(guest, V3_VM_CONSOLE_CONNECT, console_connect, cons);
+
     return cons;
 }
 
@@ -369,8 +389,25 @@ static struct v3_console_hooks palacios_console_hooks = {
 
 
 
-int palacios_init_console( void ) {
+
+
+
+static int console_init( void ) {
     V3_Init_Console(&palacios_console_hooks);
     
     return 0;
 }
+
+
+
+
+static struct linux_ext console_ext = {
+    .name = "CONSOLE",
+    .init = console_init,
+    .deinit = NULL,
+    .guest_init = NULL,
+    .guest_deinit = NULL
+};
+
+
+register_extension(&console_ext);
diff --git a/linux_module/palacios-console.h b/linux_module/palacios-console.h
deleted file mode 100644 (file)
index 9e443e5..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Palacios VM Stream Console interface
- * (c) Jack Lange, 2010
- */
-
-#ifndef __PALACIOS_CONSOLE_H__
-#define __PALACIOS_CONSOLE_H__
-
-
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-
-
-struct palacios_console {
-    struct gen_queue * queue;
-    spinlock_t lock;
-
-    int open;
-    int connected;
-
-    wait_queue_head_t intr_queue;
-
-    unsigned int width;
-    unsigned int height;
-
-    struct v3_guest * guest;
-};
-
-
-
-struct v3_guest;
-
-
-int connect_console(struct v3_guest * guest);
-
-int palacios_init_console( void );
-
-
-#endif
index cf8e0fe..f640403 100644 (file)
 #include "palacios.h"
 #include "palacios-mm.h"
 #include "palacios-vm.h"
-#include "palacios-stream.h"
-#include "palacios-file.h"
-#include "palacios-serial.h"
-#include "palacios-socket.h"
-#include "palacios-vnet.h"
-#include "palacios-packet.h"
 
-#ifdef V3_CONFIG_EXT_INSPECTOR
-#include "palacios-inspector.h"
-#endif
+#include "linux-exts.h"
 
-#ifdef V3_CONFIG_KEYED_STREAMS
-#include "palacios-keyed-stream.h"
-#endif
 
 
 MODULE_LICENSE("GPL");
@@ -51,9 +40,6 @@ static u8 v3_minor_map[MAX_VMS / 8] = {[0 ... (MAX_VMS / 8) - 1] = 0};
 struct class * v3_class = NULL;
 static struct cdev ctrl_dev;
 
-void * v3_base_addr = NULL;
-unsigned int v3_pages = 0;
-
 static int register_vm( void ) {
     int i, j = 0;
     int avail = 0;
@@ -137,12 +123,8 @@ static long v3_dev_ioctl(struct file * filp,
 
            printk("Launching VM\n");
 
-           INIT_LIST_HEAD(&(guest->streams));
-           INIT_LIST_HEAD(&(guest->files));
-           INIT_LIST_HEAD(&(guest->sockets));
-#ifdef V3_CONFIG_HOST_DEVICE
-           INIT_LIST_HEAD(&(guest->hostdev.devs));
-#endif
+           INIT_LIST_HEAD(&(guest->exts));
+
            init_completion(&(guest->start_done));
            init_completion(&(guest->thread_done));
 
@@ -208,8 +190,6 @@ static struct file_operations v3_ctrl_fops = {
 };
 
 
-extern unsigned int v3_pages;
-extern void * v3_base_addr;
 
 static int __init v3_init(void) {
     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
@@ -218,6 +198,16 @@ static int __init v3_init(void) {
 
     palacios_init_mm();
 
+
+    // Initialize Palacios
+    
+    palacios_vmm_init();
+
+
+    // initialize extensions
+    init_lnx_extensions();
+
+
     v3_class = class_create(THIS_MODULE, "vms");
     if (IS_ERR(v3_class)) {
        printk("Failed to register V3 VM device class\n");
@@ -251,53 +241,7 @@ static int __init v3_init(void) {
        goto failure1;
     }
 
-    if ((v3_pages > 0) && (v3_base_addr != NULL)) {
-       add_palacios_memory(__pa(v3_base_addr), v3_pages);
-    }
-
-    // Initialize Palacios
-    
-    palacios_vmm_init();
-
-#ifdef V3_CONFIG_STREAM
-    palacios_init_stream();
-#endif
-
-#ifdef V3_CONFIG_FILE
-    palacios_file_init();
-#endif
-
-#ifdef V3_CONFIG_KEYED_STREAMS
-    palacios_init_keyed_streams();
-#endif
-
-#ifdef V3_CONFIG_CONSOLE
-    palacios_init_console();
-#endif
-
-#ifdef V3_CONFIG_GRAPHICS_CONSOLE
-    palacios_init_graphics_console();
-#endif
-
-#ifdef V3_CONFIG_EXT_INSPECTOR
-    palacios_init_inspector();
-#endif
-
-#ifdef V3_CONFIG_SOCKET
-    palacios_socket_init();
-#endif
-
-#ifdef V3_CONFIG_PACKET
-    palacios_init_packet(NULL);
-#endif
 
-#ifdef V3_CONFIG_VNET
-    palacios_vnet_init();
-#endif
-
-#ifdef V3_CONFIG_HOST_DEVICE
-    palacios_init_host_dev();
-#endif
 
     return 0;
 
@@ -339,30 +283,7 @@ static void __exit v3_exit(void) {
     class_destroy(v3_class);
 
 
-
-#ifdef V3_CONFIG_EXT_INSPECTOR
-    palacios_deinit_inspector();
-#endif
-
-#ifdef V3_CONFIG_FILE
-    palacios_file_deinit();
-#endif
-
-#ifdef V3_CONFIG_STREAM
-    palacios_deinit_stream();
-#endif
-
-#ifdef V3_CONFIG_SOCKET
-    palacios_socket_deinit();
-#endif
-
-#ifdef V3_CONFIG_PACKET
-    palacios_deinit_packet(NULL);
-#endif
-
-#ifdef V3_CONFIG_VNET
-    palacios_vnet_deinit();
-#endif
+    deinit_lnx_extensions();
 
     palacios_deinit_mm();
 
index 2f414b5..396183b 100644 (file)
 #include <linux/module.h>
 
 #include "palacios.h"
+#include "linux-exts.h"
 
 #include <interfaces/vmm_file.h>
 
 static struct list_head global_files;
 
+
 struct palacios_file {
     struct file * filp;
 
@@ -30,10 +32,26 @@ struct palacios_file {
 };
 
 
+// Currently this just holds the list of open files
+struct vm_file_state {
+    struct list_head open_files;
+};
+
+
 
 static void * palacios_file_open(const char * path, int mode, void * private_data) {
     struct v3_guest * guest = (struct v3_guest *)private_data;
-    struct palacios_file * pfile = NULL;
+    struct palacios_file * pfile = NULL;       
+    struct vm_file_state * vm_state = NULL;
+
+    if (guest != NULL) {
+       vm_state = get_vm_ext_data(guest, "FILE_INTERFACE");
+       
+       if (vm_state == NULL) {
+           printk("ERROR: Could not locate vm file state for extension FILE_INTERFACE\n");
+           return NULL;
+       }
+    }
     
     pfile = kmalloc(sizeof(struct palacios_file), GFP_KERNEL);
     memset(pfile, 0, sizeof(struct palacios_file));
@@ -62,7 +80,7 @@ static void * palacios_file_open(const char * path, int mode, void * private_dat
     if (guest == NULL) {
        list_add(&(pfile->file_node), &(global_files));
     } else {
-       list_add(&(pfile->file_node), &(guest->files));
+       list_add(&(pfile->file_node), &(vm_state->open_files));
     } 
 
 
@@ -150,7 +168,8 @@ static struct v3_file_hooks palacios_file_hooks = {
 };
 
 
-int palacios_file_init( void ) {
+
+static int file_init( void ) {
     INIT_LIST_HEAD(&(global_files));
 
     V3_Init_File(&palacios_file_hooks);
@@ -159,10 +178,38 @@ int palacios_file_init( void ) {
 }
 
 
-int palacios_file_deinit( void ) {
+static int file_deinit( void ) {
     if (!list_empty(&(global_files))) {
        printk("Error removing module with open files\n");
     }
 
     return 0;
 }
+
+static int guest_file_init(struct v3_guest * guest, void ** vm_data) {
+    struct vm_file_state * state = kmalloc(sizeof(struct vm_file_state), GFP_KERNEL);
+    
+    INIT_LIST_HEAD(&(state->open_files));
+
+    *vm_data = state;
+
+    return 0;
+}
+
+
+static int guest_file_deinit(struct v3_guest * guest, void * vm_data) {
+    
+    return 0;
+}
+
+
+static struct linux_ext file_ext = {
+    .name = "FILE_INTERFACE",
+    .init = file_init, 
+    .deinit = file_deinit,
+    .guest_init = guest_file_init,
+    .guest_deinit = guest_file_deinit
+};
+
+
+register_extension(&file_ext);
diff --git a/linux_module/palacios-file.h b/linux_module/palacios-file.h
deleted file mode 100644 (file)
index 280585a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __PALACIOS_FILE_H__
-#define __PALACISO_FILE_H__
-
-int palacios_file_init(void);
-int palacios_file_deinit(void);
-
-#endif
index 21c9457..e1d9216 100644 (file)
 
 #include <interfaces/vmm_console.h>
 #include <palacios/vmm_host_events.h>
+#include "palacios-graphics-console.h"
+
 
 #include "palacios.h"
-#include "palacios-graphics-console.h"
+#include "linux-exts.h"
+#include "palacios-vm.h"
 
 #include <linux/vmalloc.h>
 
 
 */
 
+
+
+struct palacios_graphics_console {
+    // descriptor for the data in the shared frame buffer
+    struct v3_frame_buffer_spec spec;
+
+    // the actual shared frame buffer
+    // Note that "shared" here means shared between palacios and us
+    // This data could of course also be shared with userland
+    void * data;
+
+    int cons_refcount;
+    int data_refcount;
+
+    uint32_t num_updates;
+
+    // Currently keystrokes and mouse movements are ignored
+
+    // currently, we will not worry about locking this
+    // lock_t ...
+};
+
+
 static v3_graphics_console_t g_open(void * priv_data, 
                                    struct v3_frame_buffer_spec *desired_spec,
                                    struct v3_frame_buffer_spec *actual_spec)
 {
     struct v3_guest * guest = (struct v3_guest *)priv_data;
-    struct palacios_graphics_console *gc = (struct palacios_graphics_console *) &(guest->graphics_console);
+    struct palacios_graphics_console * gc = NULL;
     uint32_t mem;
 
-    if(gc->data) { 
+    if (guest == NULL) {
+       return 0;
+    }
+
+    gc = get_vm_ext_data(guest, "GRAPHICS_CONSOLE_INTERFACE");
+    
+    if (gc == NULL) {
+       printk("palacios: Could not locate graphics console data for extension GRAPHICS_CONSOLE_INTERFACE\n");
+       return 0;
+    }
+
+    if (gc->data != NULL) { 
        printk("palacios: framebuffer already allocated - returning it\n");
-       *actual_spec=gc->spec;
+
+       *actual_spec = gc->spec;
        gc->cons_refcount++;
        gc->data_refcount++;
+
        return gc;
     }
 
@@ -69,7 +108,6 @@ static v3_graphics_console_t g_open(void * priv_data,
 
     *actual_spec = gc->spec;
 
-    gc->guest=guest;
     
     gc->cons_refcount++;
     gc->data_refcount++;
@@ -86,17 +124,17 @@ static  void g_close(v3_graphics_console_t cons)
     gc->cons_refcount--;
     gc->data_refcount--;
 
-    if (gc->data_refcount<gc->cons_refcount) { 
+    if (gc->data_refcount < gc->cons_refcount) { 
        printk("palacios: error!   data refcount is less than console refcount for graphics console\n");
     }
 
-    if (gc->cons_refcount>0) { 
+    if (gc->cons_refcount > 0) { 
        return;
     } else {
-       if (gc->cons_refcount<0) { 
+       if (gc->cons_refcount < 0) { 
            printk("palacios: error!  refcount for graphics console is negative on close!\n");
        }
-       if (gc->data_refcount>0) { 
+       if (gc->data_refcount > 0) { 
            printk("palacios: error!  refcount for graphics console data is positive on close - LEAKING MEMORY\n");
            return;
        }
@@ -167,25 +205,29 @@ static int g_changed(v3_graphics_console_t cons)
 
 
 
-static int palacios_graphics_console_key(struct palacios_graphics_console *cons, uint8_t scancode)
+static int palacios_graphics_console_key(struct v3_guest * guest, 
+                                        struct palacios_graphics_console *cons, 
+                                        uint8_t scancode)
 {
     struct v3_keyboard_event e;
-    e.status=0;
-    e.scan_code=scancode;
+    e.status = 0;
+    e.scan_code = scancode;
 
-    v3_deliver_keyboard_event(cons->guest->v3_ctx,&e);
+    v3_deliver_keyboard_event(guest->v3_ctx, &e);
     
     return 0;
 }
 
-static int palacios_graphics_console_mouse(struct palacios_graphics_console *cons, uint8_t x, uint8_t y, uint8_t buttons)
+static int palacios_graphics_console_mouse(struct v3_guest * guest, 
+                                          struct palacios_graphics_console *cons, 
+                                          uint8_t x, uint8_t y, uint8_t buttons)
 {
     struct v3_mouse_event e;
     e.data[0]=x;
     e.data[1]=y;
     e.data[2]=buttons;   // These three are completely wrong, of course - ignoring mouse for now
 
-    v3_deliver_mouse_event(cons->guest->v3_ctx,&e);
+    v3_deliver_mouse_event(guest->v3_ctx,&e);
 
     return 0;
 }
@@ -204,7 +246,7 @@ static struct v3_graphics_console_hooks palacios_graphics_console_hooks =
 };
 
 
-int palacios_init_graphics_console( void ) {
+static int graphics_console_init( void ) {
 
     V3_Init_Graphics_Console(&palacios_graphics_console_hooks);
     
@@ -212,13 +254,14 @@ int palacios_init_graphics_console( void ) {
 }
 
 
-int palacios_graphics_console_user_query(struct palacios_graphics_console *cons, 
-                                        struct v3_fb_query_response __user *u)
-{
+static int fb_query(struct v3_guest * guest, unsigned int cmd, unsigned long arg, 
+                   void * priv_data) {
+    
+    struct palacios_graphics_console * cons = priv_data;
     struct v3_fb_query_response q;
     
     
-    if (copy_from_user(&q,(void __user *) u, sizeof(struct v3_fb_query_response))) { 
+    if (copy_from_user(&q, (void __user *) arg, sizeof(struct v3_fb_query_response))) { 
        printk("palacios: copy from user in getting query in fb\n");
        return -EFAULT;
     }
@@ -258,7 +301,7 @@ int palacios_graphics_console_user_query(struct palacios_graphics_console *cons,
                printk("palacios: unable to copy fb content to user\n");
                return -EFAULT;
            }
-           q.updated=1;
+           q.updated = 1;
        }
            break;
            
@@ -267,7 +310,7 @@ int palacios_graphics_console_user_query(struct palacios_graphics_console *cons,
     }
 
     // now we'll copy back any changes we made to the query/response structure
-    if (copy_to_user((void __user *) u, (void*)&q, sizeof(struct v3_fb_query_response))) { 
+    if (copy_to_user((void __user *) arg, (void*)&q, sizeof(struct v3_fb_query_response))) { 
        printk("palacios: unable to copy fb response to user\n");
        return -EFAULT;
     }
@@ -276,24 +319,28 @@ int palacios_graphics_console_user_query(struct palacios_graphics_console *cons,
 
 }
 
-int palacios_graphics_console_user_input(struct palacios_graphics_console *cons,
-                                        struct v3_fb_input __user  *u)
-{
+static int fb_input(struct v3_guest * guest, 
+                   unsigned int cmd, 
+                   unsigned long arg, 
+                   void * priv_data) {
+
+    struct palacios_graphics_console * cons = priv_data;
     struct v3_fb_input inp;
-    int rc=0;
+    int rc = 0;
 
 
-    if (copy_from_user(&inp,(void __user *) u, sizeof(struct v3_fb_input))) { 
+    if (copy_from_user(&inp, (void __user *) arg, sizeof(struct v3_fb_input))) { 
        printk("palacios: copy from user in getting input in fb\n");
        return -EFAULT;
     }
        
-    if (inp.data_type==V3_FB_KEY || inp.data_type==V3_FB_BOTH) { 
-       rc = palacios_graphics_console_key(cons,inp.scan_code);
+    if ((inp.data_type == V3_FB_KEY) || (inp.data_type == V3_FB_BOTH)) { 
+       rc = palacios_graphics_console_key(guest, cons, inp.scan_code);
     }
 
-    if (inp.data_type==V3_FB_MOUSE || inp.data_type==V3_FB_BOTH) { 
-       rc |= palacios_graphics_console_mouse(cons,inp.mouse_data[0],inp.mouse_data[1],inp.mouse_data[2]);
+    if ((inp.data_type == V3_FB_MOUSE) || (inp.data_type == V3_FB_BOTH)) { 
+       rc |= palacios_graphics_console_mouse(guest, cons, inp.mouse_data[0],
+                                             inp.mouse_data[1], inp.mouse_data[2]);
     }
 
     if (rc) { 
@@ -302,3 +349,35 @@ int palacios_graphics_console_user_input(struct palacios_graphics_console *cons,
        return 0;
     }
 }
+
+
+static int graphics_console_guest_init(struct v3_guest * guest, void ** vm_data) {
+    struct palacios_graphics_console * graphics_cons = kmalloc(sizeof(struct palacios_graphics_console), GFP_KERNEL);
+
+    if (!graphics_cons) { 
+       printk("palacios: filed to do guest_init for graphics console\n");
+       return -1;
+    }
+
+    memset(graphics_cons, 0, sizeof(struct palacios_graphics_console));
+
+    *vm_data = graphics_cons;
+
+    add_guest_ctrl(guest, V3_VM_FB_INPUT, fb_input, graphics_cons);
+    add_guest_ctrl(guest, V3_VM_FB_QUERY, fb_query, graphics_cons);
+
+    return 0;
+}
+
+
+
+static struct linux_ext graphics_cons_ext = {
+    .name = "GRAPHICS_CONSOLE_INTERFACE",
+    .init = graphics_console_init,
+    .deinit = NULL,
+    .guest_init = graphics_console_guest_init,
+    .guest_deinit = NULL
+};
+
+
+register_extension(&graphics_cons_ext);
index 417a26b..aef5330 100644 (file)
@@ -8,26 +8,6 @@
 
 #include <interfaces/vmm_graphics_console.h>
 
-struct palacios_graphics_console {
-    // descriptor for the data in the shared frame buffer
-    struct v3_frame_buffer_spec spec;
-    // the actual shared frame buffer
-    // Note that "shared" here means shared between palacios and us
-    // This data could of course also be shared with userland
-    void *data;
-
-    struct v3_guest * guest;
-
-    int cons_refcount;
-    int data_refcount;
-
-    uint32_t num_updates;
-
-    // Currently keystrokes and mouse movements are ignored
-
-    // currently, we will not worry about locking this
-    // lock_t ...
-};
 
 
 // This is the data structure that is passed back and forth with user-land
@@ -48,13 +28,6 @@ struct v3_fb_input {
 };
 
 
-int palacios_init_graphics_console(void);
-
-int palacios_graphics_console_user_query(struct palacios_graphics_console *cons, 
-                                        struct v3_fb_query_response __user *fb);
-
-int palacios_graphics_console_user_input(struct palacios_graphics_console *cons,
-                                        struct v3_fb_input __user  *in);
 
 
 #endif
index 29cb303..927b5ad 100644 (file)
 #include <interfaces/vmm_host_dev.h>
 
 #include "palacios.h"
-#include "palacios-host-dev.h"
 #include "palacios-host-dev-user.h"
-
-
+#include "linux-exts.h"
+#include "palacios-vm.h"
 
 /*
   There are two things in this file:
         // 1 on success, negative on error
      }
     
+     Note that the current model has deferred rendezvous and allows
+     for user-side device disconnection and reconnection.  It is important
+     to note that this implementation does NOT deal with state discrepency
+     between the palacios-side and the user-side.   For example, a user-side
+     device can disconnect, a palacios-side request can then fail, and 
+     when the user-side device reconnects, it is unaware of this failure.  
 
 */
 
 
+struct palacios_host_dev {
+    spinlock_t      lock;
+    struct list_head devs;
+};
+
+
 #define MAX_URL 256
 
 #define RENDEZVOUS_WAIT_SECS  60
@@ -596,13 +607,22 @@ static struct file_operations host_dev_fops = {
 
 
 
-    
-int connect_host_dev(struct v3_guest * guest, char *url) 
+static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data) 
 {
+    void __user * argp = (void __user *)arg;
+    char url[MAX_URL];
+    struct palacios_host_dev * host_dev = priv_data;
     struct palacios_host_device_user *dev;
     unsigned long f1, f2;
     int i;
 
+
+
+    if (copy_from_user(url, argp, MAX_URL)) {
+       printk("copy from user error getting url for host device connect...\n");
+       return -EFAULT;
+    }
+
     // currently only support user: types:
     if (strncasecmp(url,"user:",5)) { 
        ERROR("palacios: do not currently support host devices of type in \"%s\"\n",url);
@@ -615,22 +635,22 @@ int connect_host_dev(struct v3_guest * guest, char *url)
     // URL.  If we don't find it after a while, we give up
     
     for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
-       spin_lock_irqsave(&(guest->hostdev.lock),f1);
-       list_for_each_entry(dev,&(guest->hostdev.devs), node) {
+       spin_lock_irqsave(&(host_dev->lock),f1);
+       list_for_each_entry(dev,&(host_dev->devs), node) {
            if (!strncasecmp(url,dev->url,MAX_URL)) { 
                // found it
                spin_lock_irqsave(&(dev->lock),f2);
                if (dev->connected) { 
                    ERROR("palacios: device for \"%s\" is already connected!\n",url);
                    spin_unlock_irqrestore(&(dev->lock),f2);
-                   spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+                   spin_unlock_irqrestore(&(host_dev->lock),f1);
                    return -1;
                } else {
                    dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
                    if (dev->fd<0) { 
                        ERROR("palacios: cannot create fd for device \"%s\"\n",url);
                        spin_unlock_irqrestore(&(dev->lock),f2);
-                       spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+                       spin_unlock_irqrestore(&(host_dev->lock),f1);
                        return -1;
                    }
                    dev->connected=1;
@@ -645,13 +665,13 @@ int connect_host_dev(struct v3_guest * guest, char *url)
                    }
                    INFO("palacios: connected fd for device \"%s\"\n",url);
                    spin_unlock_irqrestore(&(dev->lock),f2);
-                   spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+                   spin_unlock_irqrestore(&(host_dev->lock),f1);
                    return dev->fd;
                }
                spin_unlock_irqrestore(&(dev->lock),f2);
            }
        }
-       spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+       spin_unlock_irqrestore(&(host_dev->lock),f1);
        
        ssleep(RENDEZVOUS_RETRY_SECS);
     }
@@ -675,21 +695,68 @@ int connect_host_dev(struct v3_guest * guest, char *url)
 
 **************************************************************************************/
 
-static v3_host_dev_t palacios_host_dev_open(char *url,
-                                           v3_bus_class_t bus,
-                                           v3_guest_dev_t gdev,
-                                           void *host_priv_data)
+
+/* Attempt to rendezvous with the user device if no device is currently connected */
+static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev)
+{
+    unsigned long f;
+    int i;
+
+    if (dev->connected) { 
+       return 0;
+    }
+
+   
+    INFO("palacios: attempting new rendezvous for host device \"%s\"\n",dev->url);
+
+    // Now wait until we are noticed!
+    for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
+       spin_lock_irqsave(&(dev->lock),f);
+       if (dev->connected) { 
+           INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
+           spin_unlock_irqrestore(&(dev->lock),f);
+           return 0;
+       }
+       spin_unlock_irqrestore(&(dev->lock),f);
+       ssleep(RENDEZVOUS_RETRY_SECS);
+    }
+    
+    ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",dev->url);
+
+    // We stay in the list because a future rendezvous might happen
+    
+    return -1;
+}
+
+
+/* Creates the device without rendezvous */
+static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
+                                                    v3_bus_class_t bus,
+                                                    v3_guest_dev_t gdev,
+                                                    void *host_priv_data)
 {
     struct v3_guest *guest= (struct v3_guest*)host_priv_data;
     struct palacios_host_device_user *dev;
-    unsigned long f1,f2;
-    int i;
+    struct palacios_host_dev * host_dev = NULL;
+    unsigned long f;
 
     /*
       I will create the device in the list and then wait
       for the user side to attach
     */
 
+    if (guest == NULL) {
+       return 0;
+    }
+    
+
+    host_dev = get_vm_ext_data(guest, "HOST_DEVICE_INTERFACE");
+
+    if (host_dev == NULL) {
+       printk("Error locating vm host data for HOST_DEVICE_INTERFACE\n");
+       return 0;
+    }
+
 
     if (strncasecmp(url,"user:",5)) { 
        ERROR("palacios: do not currently support devices of type in \"%s\"\n",url);
@@ -697,16 +764,16 @@ static v3_host_dev_t palacios_host_dev_open(char *url,
     }
 
     // Check to see if a device of this url already exists, which would be ugly
-    spin_lock_irqsave(&(guest->hostdev.lock),f1);
-    list_for_each_entry(dev,&(guest->hostdev.devs), node) {
+    spin_lock_irqsave(&(host_dev->lock),f);
+    list_for_each_entry(dev,&(host_dev->devs), node) {
        if (!strncasecmp(url,dev->url,MAX_URL)) { 
            // found it
-           spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+           spin_unlock_irqrestore(&(host_dev->lock),f);
            ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
            return NULL;
        }
     }
-    spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+    spin_unlock_irqrestore(&(host_dev->lock),f);
 
 
     INFO("palacios: creating host device \"%s\"\n",url);
@@ -731,47 +798,40 @@ static v3_host_dev_t palacios_host_dev_open(char *url,
     init_waitqueue_head(&(dev->user_wait_queue));
     init_waitqueue_head(&(dev->host_wait_queue));
 
-    INFO("palacios: attempting to rendezvous with user side of host device \"%s\"\n",url);
-    
     // Insert ourselves into the list
-    spin_lock_irqsave(&(guest->hostdev.lock),f1);
-    list_add(&(dev->node),&(guest->hostdev.devs));
-    spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+    spin_lock_irqsave(&(host_dev->lock),f);
+    list_add(&(dev->node),&(host_dev->devs));
+    spin_unlock_irqrestore(&(host_dev->lock),f);
+
+    INFO("palacios: host device \"%s\" created with deferred rendezvous\n",url);
+
+    return dev;
 
-    
-    // Now wait until we are noticed!
-    for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
-       spin_lock_irqsave(&(dev->lock),f2);
-       if (dev->connected){ 
-           INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
-           spin_unlock_irqrestore(&(dev->lock),f2);
-           return dev;
-       }
-       spin_unlock_irqrestore(&(dev->lock),f2);
-       ssleep(RENDEZVOUS_RETRY_SECS);
-    }
-    
-    ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",url);
-    
-    // get us out of the list
-    spin_lock_irqsave(&(guest->hostdev.lock),f1);
-    list_del(&(dev->node));
-    spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
-    
-    palacios_host_dev_user_free(dev);
-    
-    return NULL;
 }
 
+
+
 static int palacios_host_dev_close(v3_host_dev_t hostdev)
 {
     unsigned long f1, f2;
 
     struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
-    
+    struct palacios_host_dev * host_dev = NULL;
+
     INFO("palacios: closing host device \"%s\"\n",dev->url);
 
-    spin_lock_irqsave(&(dev->guest->hostdev.lock),f1);
+    if ((dev == NULL) || (dev->guest == NULL)) {
+       return -1;
+    }
+
+    host_dev = get_vm_ext_data(dev->guest, "HOST_DEVICE_INTERFACE");
+
+    
+    if (host_dev == NULL) {
+       return -1;
+    }
+
+    spin_lock_irqsave(&(host_dev->lock),f1);
 
     spin_lock_irqsave(&(dev->lock),f2);
 
@@ -783,7 +843,7 @@ static int palacios_host_dev_close(v3_host_dev_t hostdev)
     list_del(&(dev->node));
     
     spin_unlock_irqrestore(&(dev->lock),f2);
-    spin_unlock_irqrestore(&(dev->guest->hostdev.lock),f1);
+    spin_unlock_irqrestore(&(host_dev->lock),f1);
     
     palacios_host_dev_user_free(dev);
 
@@ -807,17 +867,18 @@ static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: guest issued i/o read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
        return 0;
     }
 
-    if (!dev->connected) {
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       ERROR("palacios: guest issued i/o read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
        return 0;
     }
+
     
     
     // resize request (no data)
@@ -881,14 +942,15 @@ static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: guest issued memory read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
        return 0;
     }
-    if (!dev->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       ERROR("palacios: guest issued memory read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
        return 0;
     }
     
@@ -952,14 +1014,15 @@ static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: guest issued config read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
        return 0;
     }
-    if (!dev->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       ERROR("palacios: guest issued config read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
        return 0;
     }
     
@@ -1024,14 +1087,15 @@ static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: guest issued i/o write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
        return 0;
     }
-    if (!dev->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       ERROR("palacios: guest issued i/o write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
        return 0;
     }
 
@@ -1096,14 +1160,15 @@ static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: guest issued memory write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
        return 0;
     }
-    if (!dev->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       ERROR("palacios: guest issued memory write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
        return 0;
     }
     
@@ -1170,14 +1235,15 @@ static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: guest issued config write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
        return 0;
     }
-    if (!dev->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       ERROR("palacios: guest issued config write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
        return 0;
     }
     
@@ -1240,7 +1306,7 @@ static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
 
 
 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
-    .open                      = palacios_host_dev_open,
+    .open                      = palacios_host_dev_open_deferred,
     .close                      = palacios_host_dev_close,
     .read_io                    = palacios_host_dev_read_io,
     .write_io                   = palacios_host_dev_write_io,
@@ -1253,9 +1319,44 @@ static struct v3_host_dev_hooks palacios_host_dev_hooks = {
 
 
 
-int palacios_init_host_dev( void ) 
-{
+static int host_dev_init( void ) {
     V3_Init_Host_Device_Support(&palacios_host_dev_hooks);
     
     return 0;
 }
+
+
+static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) {
+    struct palacios_host_dev * host_dev = kmalloc(sizeof(struct palacios_host_dev), GFP_KERNEL);
+
+    if (!host_dev) { 
+       ERROR("palacios: failed to do guest_init for host device\n");
+       return -1;
+    }
+    
+    
+    INIT_LIST_HEAD(&(host_dev->devs));
+    spin_lock_init(&(host_dev->lock));
+
+    *vm_data = host_dev;
+
+
+    add_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT, host_dev_connect, host_dev);
+
+    return 0;
+}
+
+
+
+
+
+static struct linux_ext host_dev_ext = {
+    .name = "HOST_DEVICE_INTERFACE",
+    .init = host_dev_init,
+    .deinit = NULL,
+    .guest_init = host_dev_guest_init,
+    .guest_deinit = NULL
+};
+
+
+register_extension(&host_dev_ext);
diff --git a/linux_module/palacios-host-dev.h b/linux_module/palacios-host-dev.h
deleted file mode 100644 (file)
index d444b7d..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Palacios Host Device Interface + User-space interface 
- * (c) Peter Dinda, 2011
- */
-
-#ifndef __PALACIOS_HOST_DEV_H__
-#define __PALACIOS_HOST_DEV_H__
-
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include "palacios-host-dev-user.h"
-
-struct v3_guest;
-
-/*
-   This is the collection of host devices that
-   a single guest has
-*/
-struct palacios_host_dev {
-    spinlock_t      lock;
-    struct list_head devs;
-};
-
-
-
-int connect_host_dev(struct v3_guest * guest, char *url);
-
-int palacios_init_host_dev( void );
-
-
-#endif
index a3b5ac9..340821b 100644 (file)
 #include <interfaces/inspector.h>
 
 #include "palacios.h"
+#include "palacios-vm.h"
+#include "linux-exts.h"
 
 struct dentry * v3_dir = NULL;
 
 
-int palacios_init_inspector( void ) {
-
-    v3_dir = debugfs_create_dir("v3vee", NULL);
-
-    if (IS_ERR(v3_dir)) {
-       printk("Error creating v3vee debugfs directory\n");
-       return -1;
-    }
-
-    return 0;
-}
-
-
-int palacios_deinit_inspector( void ) {
-    debugfs_remove(v3_dir);
-    return 0;
-}
 
 
 
@@ -66,7 +51,8 @@ static int dfs_register_tree(struct dentry * dir, v3_inspect_node_t * root) {
 }
 
 
-int inspect_vm(struct v3_guest * guest) {
+static int inspect_vm(struct v3_guest * guest, unsigned int cmd, unsigned long arg,
+                     void * priv_data) {
     v3_inspect_node_t * root = v3_get_inspection_root(guest->v3_ctx);
     struct dentry * guest_dir = NULL;
 
@@ -86,3 +72,47 @@ int inspect_vm(struct v3_guest * guest) {
     dfs_register_tree(guest_dir, root);
     return 0;
 }
+
+
+
+static int init_inspector( void ) {
+
+    v3_dir = debugfs_create_dir("v3vee", NULL);
+
+    if (IS_ERR(v3_dir)) {
+       printk("Error creating v3vee debugfs directory\n");
+       return -1;
+    }
+
+    return 0;
+}
+
+
+static int deinit_inspector( void ) {
+    debugfs_remove(v3_dir);
+    return 0;
+}
+
+
+static int guest_init(struct v3_guest * guest, void ** vm_data) {
+
+    add_guest_ctrl(guest, V3_VM_INSPECT, inspect_vm, NULL);
+    return 0;
+}
+
+static int guest_deinit(struct v3_guest * guest, void * vm_data) {
+    
+    return 0;
+}
+
+
+struct linux_ext inspector_ext = {
+    .name = "INSPECTOR",
+    .init = init_inspector, 
+    .deinit = deinit_inspector,
+    .guest_init = guest_init, 
+    .guest_deinit = guest_deinit
+};
+
+
+register_extension(&inspector_ext);
diff --git a/linux_module/palacios-inspector.h b/linux_module/palacios-inspector.h
deleted file mode 100644 (file)
index ad966df..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* 
- * DebugFS interface
- * (c) Jack Lange, 2011
- */
-
-#include "palacios.h"
-
-int palacios_init_inspector( void );
-int palacios_deinit_inspector( void );
-
-
-
-int inspect_vm(struct v3_guest * guest);
-
index b3fbe2b..ef185a5 100644 (file)
@@ -1,6 +1,6 @@
 #include "palacios.h"
-#include "palacios-keyed-stream.h"
 #include "palacios-hashtable.h"
+#include "linux-exts.h"
 
 #define sint64_t int64_t
 #include <interfaces/vmm_keyed_stream.h>
@@ -275,7 +275,7 @@ static struct v3_keyed_stream_hooks hooks = {
 };
 
 
-int palacios_init_keyed_streams()
+static int init_keyed_streams( void )
 {
     streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
 
@@ -290,8 +290,20 @@ int palacios_init_keyed_streams()
 
 }
 
-int palacios_deinit_keyed_streams()
+static int deinit_keyed_streams( void )
 {
     printk("DEINIT OF PALACIOS KEYED STREAMS NOT IMPLEMENTED - WE HAVE JUST LEAKED MEMORY!\n");
     return -1;
 }
+
+
+static struct linux_ext key_stream_ext = {
+    .name = "KEYED_STREAM_INTERFACE",
+    .init = init_keyed_streams,
+    .deinit = deinit_keyed_streams,
+    .guest_init = NULL,
+    .guest_deinit = NULL
+};
+
+
+register_extension(&key_stream_ext);
diff --git a/linux_module/palacios-keyed-stream.h b/linux_module/palacios-keyed-stream.h
deleted file mode 100644 (file)
index 218ed51..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Palacios VM Keyed Stream Interface (for checkpoint/restore)
- * Copyright (c) 2011 Peter Dinda <pdinda@northwestern.edu>
- */
-
-#ifndef __PALACIOS_KEYED_STREAM_H__
-#define __PALACIOS_KEYED_STREAM_H__
-
-
-
-int palacios_init_keyed_streams(void);
-int palacios_deinit_keyed_streams(void);
-
-
-#endif
index 83404de..d51c7e7 100644 (file)
 #include <palacios/vmm_host_events.h>
 #include <vnet/vnet.h>
 
+
 #define __V3VEE__
 #include <palacios/vmm_hashtable.h>
 #include <palacios/vmm_ethernet.h>
 #undef __V3VEE__
 
 #include "palacios.h"
-#include "palacios-packet.h"
-
+#include "linux-exts.h"
 struct palacios_packet_state {
     struct socket * raw_sock;
     uint8_t inited;
@@ -140,11 +140,6 @@ palacios_packet_send(const char * pkt, unsigned int len, void * private_data) {
     size = sock_sendmsg(packet_state.raw_sock, &msg, len);
     set_fs(oldfs);
 
-    if(vnet_debug >= 4){
-       printk("Palacios Packet: send pkt to NIC (size: %d)\n", len);
-       print_hex_dump(NULL, "pkt_header: ", 0, 20, 20, pkt, 20, 0);
-       printk("palacios_packet_send return: %d\n", size);
-    }
 
     return size;
 }
@@ -189,7 +184,7 @@ recv_pkt(char * pkt, int len) {
 }
 
 
-void
+static void
 send_raw_packet_to_palacios(char * pkt,
                               int len,
                               struct v3_vm_info * vm) {
@@ -218,10 +213,6 @@ static int packet_server(void * arg) {
            break;
        }
 
-       if(vnet_debug >= 4){
-           printk("Palacios Packet: receive pkt from NIC (size: %d)\n",size);
-           print_hex_dump(NULL, "pkt_header: ", 0, 10, 10, pkt, 20, 0);
-       }
 
        /* if VNET is enabled, send to VNET */
        // ...
@@ -242,7 +233,9 @@ static int packet_server(void * arg) {
 }
 
 
-int palacios_init_packet(const char * eth_dev) {
+static int packet_init( void ) {
+
+    const char * eth_dev = NULL;
 
     if(packet_state.inited == 0){
        packet_state.inited = 1;
@@ -259,14 +252,32 @@ int palacios_init_packet(const char * eth_dev) {
        packet_state.server_thread = kthread_run(packet_server, NULL, "raw-packet-server");
     }
        
+
+    // REGISTER GLOBAL CONTROL to add devices...
+
     return 0;
 }
 
-void palacios_deinit_packet(const char * eth_dev) {
+static int packet_deinit( void ) {
+
 
     kthread_stop(packet_state.server_thread);
     packet_state.raw_sock->ops->release(packet_state.raw_sock);
     v3_free_htable(packet_state.mac_vm_cache, 0, 1);
     packet_state.inited = 0;
+
+    return 0;
 }
 
+
+
+static struct linux_ext pkt_ext = {
+    .name = "PACKET_INTERFACE",
+    .init = packet_init,
+    .deinit = packet_deinit,
+    .guest_init = NULL,
+    .guest_deinit = NULL
+};
+
+
+register_extension(&pkt_ext);
diff --git a/linux_module/palacios-packet.h b/linux_module/palacios-packet.h
deleted file mode 100644 (file)
index 9b26e40..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Palacios VM Raw Packet interface
- * (c) Lei Xia, 2010
- */
-
-#ifndef __PALACIOS_PACKET_H__
-#define __PALACIOS_PACKET_H__
-
-int palacios_init_packet(const char * eth_dev);
-int palacios_deinit_packet(void);
-
-#endif
index 8d17d8f..e572ec9 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/list.h>
 
 #include "palacios.h"
+#include "linux-exts.h"
 
 
 struct palacios_socket {
@@ -43,19 +44,32 @@ struct palacios_socket {
 
 static struct list_head global_sockets;
 
+
+// currently just the list of created sockets
+struct vm_socket_state {
+    struct list_head socket_list;
+};
+
+
 //ignore the arguments given here currently
 static void * 
-palacios_tcp_socket(
-       const int bufsize,
-       const int nodelay,
-       const int nonblocking,
-       void * private_data
-)
-{
+palacios_tcp_socket(const int bufsize, const int nodelay, 
+                   const int nonblocking, void * private_data) {
     struct v3_guest * guest = (struct v3_guest *)private_data;
     struct palacios_socket * sock = NULL;
+    struct vm_socket_state * vm_state = NULL;
     int err;
 
+    if (guest != NULL) {
+        vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
+        
+        if (vm_state == NULL) {
+            printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
+            return NULL;
+        }
+    }
+
+
     sock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
     memset(sock, 0, sizeof(struct palacios_socket));
 
@@ -71,7 +85,7 @@ palacios_tcp_socket(
     if (guest == NULL) {
        list_add(&(sock->sock_node), &global_sockets);
     } else {
-       list_add(&(sock->sock_node), &(guest->sockets));
+       list_add(&(sock->sock_node), &(vm_state->socket_list));
     }
     
     return sock;
@@ -87,8 +101,19 @@ palacios_udp_socket(
 {
     struct v3_guest * guest = (struct v3_guest *)private_data;
     struct palacios_socket * sock = NULL;
+    struct vm_socket_state * vm_state = NULL;
     int err;
 
+    if (guest != NULL) {
+        vm_state = get_vm_ext_data(guest, "SOCKET_INTERFACE");
+        
+        if (vm_state == NULL) {
+            printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
+            return NULL;
+        }
+    }
+
+
     sock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
     memset(sock, 0, sizeof(struct palacios_socket));
 
@@ -105,7 +130,7 @@ palacios_udp_socket(
     if (guest == NULL) {
        list_add(&(sock->sock_node), &global_sockets);
     } else {
-       list_add(&(sock->sock_node), &(guest->sockets));
+       list_add(&(sock->sock_node), &(vm_state->socket_list));
     }
 
     return sock;
@@ -160,21 +185,27 @@ palacios_listen(
        return sock->sock->ops->listen(sock->sock, backlog);
 }
 
-static void * 
-palacios_accept(
-       const void * sock_ptr,
-       unsigned int * remote_ip,
-       unsigned int * port
-)
-{
+static void * palacios_accept(const void * sock_ptr, unsigned int * remote_ip, unsigned int * port) {
+
     struct palacios_socket * sock = (struct palacios_socket *)sock_ptr;
     struct palacios_socket * newsock = NULL;
+    struct vm_socket_state * vm_state = NULL;
     int err;
 
     if (sock == NULL) {
        return NULL;
     }
     
+    if (sock->guest != NULL) {
+        vm_state = get_vm_ext_data(sock->guest, "SOCKET_INTERFACE");
+        
+        if (vm_state == NULL) {
+            printk("ERROR: Could not locate vm socket state for extension SOCKET_INTERFACE\n");
+            return NULL;
+        }
+    }
+
+
     newsock = kmalloc(sizeof(struct palacios_socket), GFP_KERNEL);
 
     err = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &(newsock->sock));
@@ -202,7 +233,7 @@ palacios_accept(
     if (sock->guest == NULL) {
        list_add(&(newsock->sock_node), &global_sockets);
     } else {
-       list_add(&(newsock->sock_node), &(sock->guest->sockets));
+       list_add(&(newsock->sock_node), &(vm_state->socket_list));
     }
 
     return newsock;
@@ -413,7 +444,7 @@ palacios_recvfrom_ip(
        return err;
 }
 
-struct v3_socket_hooks palacios_sock_hooks = {
+static struct v3_socket_hooks palacios_sock_hooks = {
        .tcp_socket = palacios_tcp_socket,
        .udp_socket = palacios_udp_socket,
        .close = palacios_close,
@@ -431,15 +462,27 @@ struct v3_socket_hooks palacios_sock_hooks = {
        .recvfrom_ip = palacios_recvfrom_ip,
 };
 
-int palacios_socket_init( void ) {
+static int socket_init( void ) {
        V3_Init_Sockets(&palacios_sock_hooks);
        INIT_LIST_HEAD(&global_sockets);
        return 0;
 }
 
-void palacios_socket_deinit( void ) {
+static int socket_deinit( void ) {
     if (!list_empty(&(global_sockets))) {
        printk("Error removing module with open sockets\n");
     }
+
+    return 0;
 }
 
+
+static struct linux_ext socket_ext = {
+    .name = "SOCKET_INTERFACE",
+    .init = socket_init,
+    .deinit = socket_deinit,
+    .guest_init = NULL,
+    .guest_deinit = NULL
+};
+
+register_extension(&socket_ext);
diff --git a/linux_module/palacios-socket.h b/linux_module/palacios-socket.h
deleted file mode 100644 (file)
index 394802e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Palacios VM Raw Packet interface
- * (c) Lei Xia, 2010
- */
-
-#ifndef __PALACIOS_SOCKET_H__
-#define __PALACIOS_SOCKET_H__
-
-int palacios_socket_init(void);
-int palacios_socket_deinit(void);
-
-#endif
index 340d27f..411c119 100644 (file)
@@ -6,12 +6,38 @@
 #include <linux/errno.h>
 #include <linux/percpu.h>
 #include <linux/sched.h>
+#include <linux/uaccess.h>
+
 
 #include <interfaces/vmm_stream.h>
-#include "palacios-stream.h"
+#include "linux-exts.h"
+#include "palacios-ringbuffer.h"
+#include "palacios-vm.h"
+
+#define STREAM_BUF_SIZE 1024
+#define STREAM_NAME_LEN 128
+
+
 
 static struct list_head global_streams;
 
+struct stream_buffer {
+    char name[STREAM_NAME_LEN];
+    struct ringbuf * buf;
+
+    wait_queue_head_t intr_queue;
+    spinlock_t lock;
+
+    struct v3_guest * guest;
+    struct list_head stream_node;
+};
+
+
+// Currently just the list of open streams
+struct vm_stream_state {
+    struct list_head open_streams;
+};
+
 static int stream_enqueue(struct stream_buffer * stream, char * buf, int len) {
     int bytes = 0;
 
@@ -21,7 +47,7 @@ static int stream_enqueue(struct stream_buffer * stream, char * buf, int len) {
 }
 
 
-int stream_dequeue(struct stream_buffer * stream, char * buf, int len) {
+static int stream_dequeue(struct stream_buffer * stream, char * buf, int len) {
     int bytes = 0;
 
     bytes = ringbuf_read(stream->buf, buf, len);
@@ -29,25 +55,31 @@ int stream_dequeue(struct stream_buffer * stream, char * buf, int len) {
     return bytes;
 }
 
-int stream_datalen(struct stream_buffer * stream){
+static int stream_datalen(struct stream_buffer * stream){
     return ringbuf_data_len(stream->buf);
 }
 
 
-int open_stream(const char * name) {
-    return -1;
-}
 
 
 
-struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const char * name) {
+static struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const char * name) {
     struct stream_buffer * stream = NULL;
     struct list_head * stream_list = NULL;
+    struct vm_stream_state * vm_state = NULL;
+
 
     if (guest == NULL) {
        stream_list = &global_streams;
     } else {
-       stream_list = &(guest->streams);
+       vm_state = get_vm_ext_data(guest, "STREAM_INTERFACE");
+
+       if (vm_state == NULL) {
+           printk("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
+           return NULL;
+       }
+
+       stream_list = &(vm_state->open_streams);
     }
 
     list_for_each_entry(stream,  stream_list, stream_node) {
@@ -63,6 +95,16 @@ struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const char *
 static void * palacios_stream_open(const char * name, void * private_data) {
     struct v3_guest * guest = (struct v3_guest *)private_data;
     struct stream_buffer * stream = NULL;
+    struct vm_stream_state * vm_state = NULL;
+
+    if (guest != NULL) {
+       vm_state = get_vm_ext_data(guest, "STREAM_INTERFACE");
+
+       if (vm_state == NULL) {
+           printk("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
+           return NULL;
+       }
+    }
 
     if (find_stream_by_name(guest, name) != NULL) {
        printk("Stream already exists\n");
@@ -82,7 +124,7 @@ static void * palacios_stream_open(const char * name, void * private_data) {
     if (guest == NULL) {
        list_add(&(stream->stream_node), &(global_streams));
     } else {
-       list_add(&(stream->stream_node), &(guest->streams));
+       list_add(&(stream->stream_node), &(vm_state->open_streams));
     } 
 
     return stream;
@@ -112,21 +154,75 @@ static void palacios_stream_close(void * stream_ptr) {
 
 }
 
-struct v3_stream_hooks palacios_stream_hooks = {
+static struct v3_stream_hooks palacios_stream_hooks = {
     .open = palacios_stream_open,
     .write = palacios_stream_write,
     .close = palacios_stream_close,
 };
 
 
-void palacios_init_stream() {
+static int stream_init( void ) {
     INIT_LIST_HEAD(&(global_streams));
     V3_Init_Stream(&palacios_stream_hooks);
+    
+    return 0;
 }
 
 
-void palacios_deinit_stream() {
+static int stream_deinit( void ) {
     if (!list_empty(&(global_streams))) {
        printk("Error removing module with open streams\n");
     }
+
+    return 0;
 }
+
+static int stream_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data) {
+    void __user * argp = (void __user *)arg;
+    char path_name[STREAM_NAME_LEN];
+    
+    if (copy_from_user(path_name, argp, STREAM_NAME_LEN)) {
+       printk("%s(%d): copy from user error...\n", __FILE__, __LINE__);
+       return -EFAULT;
+    }
+    
+    printk("ERROR: Opening Streams is currently not implemented...\n");
+
+    return -EFAULT;
+}
+
+
+static int guest_stream_init(struct v3_guest * guest, void ** vm_data) {
+    struct vm_stream_state * state = kmalloc(sizeof(struct vm_stream_state), GFP_KERNEL);
+
+    INIT_LIST_HEAD(&(state->open_streams));
+    *vm_data = state;
+
+
+    add_guest_ctrl(guest, V3_VM_STREAM_CONNECT, stream_connect, state);
+
+    return 0;
+}
+
+
+static int guest_stream_deinit(struct v3_guest * guest, void * vm_data) {
+    struct vm_stream_state * state = vm_data;
+    if (!list_empty(&(state->open_streams))) {
+       printk("Error shutting down VM with open streams\n");
+    }
+
+    return 0;
+}
+
+
+
+static struct linux_ext stream_ext = {
+    .name = "STREAM_INTERFACE",
+    .init = stream_init,
+    .deinit = stream_deinit,
+    .guest_init = guest_stream_init,
+    .guest_deinit = guest_stream_deinit
+};
+
+
+register_extension(&stream_ext);
diff --git a/linux_module/palacios-stream.h b/linux_module/palacios-stream.h
deleted file mode 100644 (file)
index d3b73e1..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 
- * Palacios Stream interface
- * (c) Lei Xia, 2010
- */
-
-#ifndef __PALACIOS_STREAM_H__
-#define __PALACIOS_STREAM_H__
-
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include "palacios.h"
-#include "palacios-ringbuffer.h"
-
-#define _V3VEE_
-//#include <palacios/vmm_ringbuffer.h>
-#undef _V3VEE_
-
-#define STREAM_BUF_SIZE 1024
-#define STREAM_NAME_LEN 128
-
-struct stream_buffer {
-    char name[STREAM_NAME_LEN];
-    struct ringbuf * buf;
-
-    wait_queue_head_t intr_queue;
-    spinlock_t lock;
-
-    struct v3_guest * guest;
-    struct list_head stream_node;
-};
-
-
-void palacios_init_stream(void);
-void palacios_deinit_stream(void);
-
-int stream_dequeue(struct stream_buffer * stream, char * buf, int len);
-int stream_datalen(struct stream_buffer * stream);
-
-struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const char * name);
-
-int open_stream(const char * name);
-#endif
-
index 4f53bcb..04b338a 100644 (file)
 #include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/spinlock.h>
-
+#include <linux/rbtree.h>
 
 #include <palacios/vmm.h>
 
 #include "palacios.h"
 #include "palacios-vm.h"
+#include "linux-exts.h"
+
+
+struct vm_ctrl {
+    unsigned int cmd;
+
+    int (*handler)(struct v3_guest * guest, 
+                  unsigned int cmd, unsigned long arg, 
+                  void * priv_data);
+
+    void * priv_data;
+
+    struct rb_node tree_node;
+};
+
+
+static inline struct vm_ctrl * __insert_ctrl(struct v3_guest * vm, 
+                                            struct vm_ctrl * ctrl) {
+    struct rb_node ** p = &(vm->vm_ctrls.rb_node);
+    struct rb_node * parent = NULL;
+    struct vm_ctrl * tmp_ctrl = NULL;
+
+    while (*p) {
+       parent = *p;
+       tmp_ctrl = rb_entry(parent, struct vm_ctrl, tree_node);
+
+       if (ctrl->cmd < tmp_ctrl->cmd) {
+           p = &(*p)->rb_left;
+       } else if (ctrl->cmd > tmp_ctrl->cmd) {
+           p = &(*p)->rb_right;
+       } else {
+           return tmp_ctrl;
+       }
+    }
+
+    rb_link_node(&(ctrl->tree_node), parent, p);
+
+    return NULL;
+}
+
+
+
+int add_guest_ctrl(struct v3_guest * guest, unsigned int cmd, 
+                  int (*handler)(struct v3_guest * guest, 
+                                 unsigned int cmd, unsigned long arg, 
+                                 void * priv_data),
+                  void * priv_data) {
+    struct vm_ctrl * ctrl = kmalloc(sizeof(struct vm_ctrl), GFP_KERNEL);
+
+    if (ctrl == NULL) {
+       printk("Error: Could not allocate vm ctrl %d\n", cmd);
+       return -1;
+    }
+
+    ctrl->cmd = cmd;
+    ctrl->handler = handler;
+    ctrl->priv_data = priv_data;
+
+    if (__insert_ctrl(guest, ctrl) != NULL) {
+       printk("Could not insert guest ctrl %d\n", cmd);
+       kfree(ctrl);
+       return -1;
+    }
+    
+    rb_insert_color(&(ctrl->tree_node), &(guest->vm_ctrls));
+
+    return 0;
+}
+
+
+static struct vm_ctrl * get_ctrl(struct v3_guest * guest, unsigned int cmd) {
+    struct rb_node * n = guest->vm_ctrls.rb_node;
+    struct vm_ctrl * ctrl = NULL;
+
+    while (n) {
+       ctrl = rb_entry(n, struct vm_ctrl, tree_node);
+
+       if (cmd < ctrl->cmd) {
+           n = n->rb_left;
+       } else if (cmd > ctrl->cmd) {
+           n = n->rb_right;
+       } else {
+           return ctrl;
+       }
+    }
+
+    return NULL;
+}
+
 
-#ifdef V3_CONFIG_STREAM
-#include "palacios-stream.h"
-#endif
 
-#ifdef V3_CONFIG_CONSOLE
-#include "palacios-console.h"
-#endif
 
-#ifdef V3_CONFIG_EXT_INSPECTOR
-#include "palacios-inspector.h"
-#endif
 
-#ifdef V3_CONFIG_GRAPHICS_CONSOLE
-#include "palacios-graphics-console.h"
-#endif
 
-#ifdef V3_CONFIG_HOST_DEVICE
-#include "palacios-host-dev.h"
-#define HOST_DEV_URL_LEN 256
-#endif
 
 extern struct class * v3_class;
-#define STREAM_NAME_LEN 128
+
 
 static long v3_vm_ioctl(struct file * filp,
                        unsigned int ioctl, unsigned long arg) {
@@ -62,74 +135,17 @@ static long v3_vm_ioctl(struct file * filp,
            break;
        }
 
-       case V3_VM_CONSOLE_CONNECT: {
-#ifdef V3_CONFIG_CONSOLE
-           return connect_console(guest);
-#else
-           printk("Console support not available\n");
-           return -EFAULT;
-#endif
-           break;
-       }
-
-       case V3_VM_STREAM_CONNECT: {
-#ifdef V3_CONFIG_STREAM
-           void __user * argp = (void __user *)arg;
-           char path_name[STREAM_NAME_LEN];
+       default: {
+           struct vm_ctrl * ctrl = get_ctrl(guest, ioctl);
 
-           if (copy_from_user(path_name, argp, STREAM_NAME_LEN)) {
-               printk("%s(%d): copy from user error...\n", __FILE__, __LINE__);
-               return -EFAULT;
+           if (ctrl) {
+               return ctrl->handler(guest, ioctl, arg, ctrl->priv_data);
            }
-
-           return open_stream(path_name);
-#else
-           printk("Stream support Not available\n");
-           return -EFAULT;
-#endif
-           break;
-       }
-
-       case V3_VM_HOST_DEV_CONNECT: {
-#ifdef V3_CONFIG_HOST_DEVICE
-           void __user * argp = (void __user *)arg;
-           char host_dev_url[HOST_DEV_URL_LEN];
-
-           if (copy_from_user(host_dev_url, argp, HOST_DEV_URL_LEN)) {
-               printk("copy from user error getting url for host device connect...\n");
-               return -EFAULT;
-           }
-
-           return connect_host_dev(guest,host_dev_url);
-#else
-           printk("palacios: Host device support not available\n");
-           return -EFAULT;
-#endif
-           break;
-       }
-
-       case V3_VM_FB_INPUT: 
-#ifdef V3_CONFIG_GRAPHICS_CONSOLE
-           return palacios_graphics_console_user_input(&(guest->graphics_console),
-                                                       (struct v3_fb_input __user *) arg) ;
-#else
-           return -EFAULT;
-#endif
-           break;
            
-       case V3_VM_FB_QUERY: 
-#ifdef V3_CONFIG_GRAPHICS_CONSOLE
-           return palacios_graphics_console_user_query(&(guest->graphics_console),
-                                                       (struct v3_fb_query_response __user *) arg);
-#else
-           return -EFAULT;
-#endif
-           break;
-
-
-       default: 
-           printk("\tUnhandled\n");
+           
+           printk("\tUnhandled ctrl cmd: %d\n", ioctl);
            return -EINVAL;
+       }
     }
 
     return 0;
@@ -178,6 +194,16 @@ int start_palacios_vm(void * arg)  {
     // allow_signal(SIGKILL);
     unlock_kernel();
     
+    init_vm_extensions(guest);
+
+    guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name);
+
+    if (guest->v3_ctx == NULL) { 
+       printk("palacios: failed to create vm\n");
+       complete(&(guest->start_done));
+       return -1;
+    }
+
 
     printk("Creating VM device: Major %d, Minor %d\n", MAJOR(guest->vm_dev), MINOR(guest->vm_dev));
 
@@ -192,6 +218,7 @@ int start_palacios_vm(void * arg)  {
 
     if (err) {
        printk("Fails to add cdev\n");
+       v3_free_vm(guest->v3_ctx);
        complete(&(guest->start_done));
        return -1;
     }
@@ -199,15 +226,7 @@ int start_palacios_vm(void * arg)  {
     if (device_create(v3_class, NULL, guest->vm_dev, guest, "v3-vm%d", MINOR(guest->vm_dev)) == NULL){
        printk("Fails to create device\n");
        cdev_del(&(guest->cdev));
-       complete(&(guest->start_done));
-       return -1;
-    }
-
-    guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name);
-
-    if (guest->v3_ctx == NULL) { 
-       printk("palacios: failed to create vm\n");
-       cdev_del(&(guest->cdev));
+       v3_free_vm(guest->v3_ctx);
        complete(&(guest->start_done));
        return -1;
     }
@@ -216,12 +235,6 @@ int start_palacios_vm(void * arg)  {
 
     printk("palacios: launching vm\n");
 
-
-#ifdef V3_CONFIG_EXT_INSPECTOR
-    inspect_vm(guest);
-#endif
-
-
     if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { 
        printk("palacios: launch of vm failed\n");
        device_destroy(v3_class, guest->vm_dev);
index e0c5f74..3423d34 100644 (file)
 int start_palacios_vm(void * arg);
 int stop_palacios_vm(struct v3_guest * guest);
 
+
+int add_guest_ctrl(struct v3_guest * guest,  unsigned int cmd, 
+                 int (*handler)(struct v3_guest * guest, 
+                                unsigned int cmd, unsigned long arg,
+                                void * priv_data),
+                 void * priv_data);
+
+
+
 #endif
index 4f3cbd5..1584ab1 100644 (file)
@@ -277,7 +277,7 @@ static struct vnet_host_hooks vnet_host_hooks = {
 
 
 
-int palacios_vnet_init( void ) {
+static int vnet_init( void ) {
     init_vnet(&vnet_host_hooks);
        
     vnet_bridge_init();
@@ -289,12 +289,23 @@ int palacios_vnet_init( void ) {
 }
 
 
-void palacios_vnet_deinit( void ) {
+static int vnet_deinit( void ) {
     deinit_vnet();
 
     vnet_bridge_deinit();
     vnet_ctrl_deinit();
 
     printk("V3 VNET Deinited\n");
+
+    return 0;
 }
 
+static struct linux_ext vnet_ext = {
+    .name = "VNET",
+    .init = vnet_init,
+    .deinit = vnet_deinit,
+    .guest_init = NULL,
+    .guest_deinit = NULL
+};
+
+register_extension(&vnet_ext);
index 9fe9c29..df9aabe 100644 (file)
@@ -6,18 +6,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 
-#ifdef V3_CONFIG_CONSOLE
-#include "palacios-console.h"
-#endif
-
-#ifdef V3_CONFIG_GRAPHICS_CONSOLE
-#include "palacios-graphics-console.h"
-#endif
-
-#ifdef V3_CONFIG_HOST_DEVICE
-#include "palacios-host-dev.h"
-#endif
-
 
 /* Global Control IOCTLs */
 #define V3_START_GUEST 10
@@ -29,6 +17,8 @@
 #define V3_VM_STREAM_CONNECT 21
 #define V3_VM_STOP 22
 
+#define V3_VM_INSPECT 30
+
 #define V3_VM_FB_INPUT (256+1)
 #define V3_VM_FB_QUERY (256+2)
 
@@ -46,11 +36,6 @@ struct v3_mem_region {
     unsigned long long num_pages;
 };
 
-struct v3_network {
-    unsigned char socket;
-    unsigned char packet;
-    unsigned char vnet;
-};
 
 void * trace_malloc(size_t size, gfp_t flags);
 void trace_free(const void * objp);
@@ -64,22 +49,9 @@ struct v3_guest {
 
     char name[128];
 
-    struct list_head files;
-    struct list_head streams;
-    struct list_head sockets;
-
-#ifdef V3_CONFIG_CONSOLE
-    struct palacios_console console;
-#endif
-
-#ifdef V3_CONFIG_GRAPHICS_CONSOLE
-    struct palacios_graphics_console graphics_console;
-#endif
-
-#ifdef V3_CONFIG_HOST_DEVICE
-    struct palacios_host_dev hostdev;
-#endif
 
+    struct rb_root vm_ctrls;
+    struct list_head exts;
 
     struct completion start_done;
     struct completion thread_done;
@@ -94,11 +66,6 @@ struct v3_guest {
 
 
 
-
-
-extern void send_key_to_palacios(unsigned char status, unsigned char scan_code);
-
-
 int palacios_vmm_init( void );
 int palacios_vmm_exit( void );
 
index 623ca4d..ebab425 100644 (file)
@@ -482,7 +482,9 @@ static inline int decode_cr(struct guest_info * core,
  */
 #define MASK_DISPLACEMENT(reg, mode) ({                                        \
            sint64_t val = 0;                                           \
-           if (mode == DISP8) {                                        \
+           if (mode == DISP0) {                                        \
+               val = reg;                                              \
+           } else if (mode == DISP8) {                                 \
                val = (sint8_t)(reg & 0xff);                            \
            } else if (mode == DISP16) {                                \
                val = (sint16_t)(reg & 0xffff);                         \
@@ -499,6 +501,9 @@ static inline int decode_cr(struct guest_info * core,
 #define ADDR_MASK(val, length) ({                            \
             ullong_t mask = 0x0LL;                           \
             switch (length) {                                \
+               case 1:                                       \
+                   mask = 0x0000000000000ffLL;               \
+                   break;                                    \
                 case 2:                                              \
                     mask = 0x00000000000fffffLL;             \
                     break;                                   \
@@ -549,37 +554,41 @@ static  int decode_rm_operand16(struct guest_info * core,
            mod_mode = DISP8;
        } else if (modrm->mod == 2) {
            mod_mode = DISP16;
+       } else {
+           PrintError("Instruction format error: Invalid mod_rm mode (%d)\n", modrm->mod);
+           v3_print_instr(instr);
+           return -1;
        }
 
        switch (modrm->rm) {
            case 0:
-               base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
+               base_addr = gprs->rbx + ADDR_MASK(gprs->rsi, 2);
                break;
            case 1:
-               base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
+               base_addr = gprs->rbx + ADDR_MASK(gprs->rdi, 2);
                break;
            case 2:
-               base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
+               base_addr = gprs->rbp + ADDR_MASK(gprs->rsi, 2);
                break;
            case 3:
-               base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
+               base_addr = gprs->rbp + ADDR_MASK(gprs->rdi, 2);
                break;
            case 4:
-               base_addr = gprs->rsi;
+               base_addr = ADDR_MASK(gprs->rsi, 2);
                break;
            case 5:
-               base_addr = gprs->rdi;
+               base_addr = ADDR_MASK(gprs->rdi, 2);
                break;
            case 6:
                if (modrm->mod == 0) {
                    base_addr = 0;
                    mod_mode = DISP16;
                } else {
-                   base_addr = gprs->rbp;
+                   base_addr = ADDR_MASK(gprs->rbp, 2);
                }
                break;
            case 7:
-               base_addr = gprs->rbx;
+               base_addr = ADDR_MASK(gprs->rbx, 2);
                break;
        }
 
@@ -654,6 +663,10 @@ static int decode_rm_operand32(struct guest_info * core,
            mod_mode = DISP8;
        } else if (modrm->mod == 2) {
            mod_mode = DISP32;
+       } else {
+           PrintError("Instruction format error: Invalid mod_rm mode (%d)\n", modrm->mod);
+           v3_print_instr(instr);
+           return -1;
        }
     
        switch (modrm->rm) {
@@ -828,6 +841,10 @@ int decode_rm_operand64(struct guest_info * core, uint8_t * modrm_instr,
            mod_mode = DISP8;
        } else if (modrm->mod == 2) {
            mod_mode = DISP32;
+       } else {
+           PrintError("Instruction format error: Invalid mod_rm mode (%d)\n", modrm->mod);
+           v3_print_instr(instr);
+           return -1;
        }
     
        if (rm_val == 4) {