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.


Added symbiotic module loader framework
Jack Lange [Wed, 10 Feb 2010 04:41:11 +0000 (22:41 -0600)]
Kconfig
palacios/include/palacios/vmm_symbiotic.h
palacios/include/palacios/vmm_symmod.h [new file with mode: 0644]
palacios/src/devices/Makefile
palacios/src/devices/keyboard.c
palacios/src/devices/lnx_virtio_symmod.c [new file with mode: 0644]
palacios/src/palacios/vmm_symbiotic.c
palacios/src/palacios/vmm_symmod.c [new file with mode: 0644]

diff --git a/Kconfig b/Kconfig
index 337f590..029cfd1 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -148,7 +148,8 @@ config SYMBIOTIC
        bool "Enable Symbiotic Functionality"
        default n
        help 
-         Enable Symbiotic components of the VMM
+         Enable Symbiotic components of the VMM. 
+         This includes the SymSpy interface.
 
 
 
index 60bbb8f..530a5fc 100644 (file)
@@ -41,7 +41,7 @@ struct v3_sym_vm_state {
     struct v3_symspy_global_state symspy_state;
 
 #ifdef CONFIG_SYMMOD
-    struct v3_symmod_global_state symmod_state;
+    struct v3_symmod_state symmod_state;
 #endif
 };
 
@@ -53,9 +53,6 @@ struct v3_sym_core_state {
     struct v3_symcall_state symcall_state;
 #endif
 
-#ifdef CONFIG_SYMMOD
-    struct v3_symmod_local_state symmod_state;
-#endif
 };
 
 
diff --git a/palacios/include/palacios/vmm_symmod.h b/palacios/include/palacios/vmm_symmod.h
new file mode 100644 (file)
index 0000000..bc7079b
--- /dev/null
@@ -0,0 +1,72 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_SYM_MOD_H__
+#define __VMM_SYM_MOD_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm_config.h>
+#include <palacios/vmm_hashtable.h>
+
+struct v3_symmod_loader_ops {
+
+    int (*load_module)(struct v3_vm_info * vm, char * name, int len, void * priv_data);
+};
+
+
+struct v3_symmod_state {
+
+    struct v3_symmod_loader_ops * loader_ops;
+    void * loader_data;
+
+
+    struct hashtable * module_table;
+};
+
+
+struct v3_sym_module {
+    char name[32];
+    uint16_t num_bytes;
+    char * data;
+};
+
+
+int v3_set_symmod_loader(struct v3_vm_info * vm, struct v3_symmod_loader_ops * ops, void * priv_data);
+
+int v3_load_sym_module(struct v3_vm_info * vm, char * mod_name);
+
+
+int v3_init_symmod_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg);
+
+
+struct v3_sym_module * v3_get_sym_module(struct v3_vm_info * vm, char * name);
+
+
+int V3_init_symmod();
+
+
+
+
+
+
+
+#endif
+
+#endif
index 8e8541b..50fea64 100644 (file)
@@ -32,4 +32,4 @@ obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o
 
 obj-$(CONFIG_PASSTHROUGH_PCI) += pci_passthrough.o
 
-obj-$(CONFIG_SYMBIOTIC_MODULES) += lnx_virtio_symmod.o
+obj-$(CONFIG_SYMMOD) += lnx_virtio_symmod.o
index 72b004d..eef0ec0 100644 (file)
@@ -318,7 +318,9 @@ static int pull_from_output_queue(struct vm_device * dev, uint8_t * value) {
 
 
 #include <palacios/vmm_telemetry.h>
-
+#ifdef CONFIG_SYMMOD
+#include <palacios/vmm_symmod.h>
+#endif
 
 static int key_event_handler(struct v3_vm_info * vm, 
                             struct v3_keyboard_event * evt, 
@@ -365,12 +367,19 @@ static int key_event_handler(struct v3_vm_info * vm,
        
        PrintDebug("Toggling Debugging\n");     
        v3_dbg_enable ^= 1;
-    } else if (evt->scan_code == 0x41) { // F7 telemetry dump
+
+    } 
 #ifdef CONFIG_TELEMETRY
+
+    else if (evt->scan_code == 0x41) { // F7 telemetry dump
        v3_print_telemetry(vm);
+    } 
 #endif
+#ifdef CONFIG_SYMMOD
+    else if (evt->scan_code == 0x40) { // F6 Test symmod load
+       v3_load_sym_module(vm, "test");
     }
-
+#endif
 
 
     addr_t irq_state = v3_lock_irqsave(state->kb_lock);
diff --git a/palacios/src/devices/lnx_virtio_symmod.c b/palacios/src/devices/lnx_virtio_symmod.c
new file mode 100644 (file)
index 0000000..b1e4a28
--- /dev/null
@@ -0,0 +1,565 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+#include <palacios/vm_guest_mem.h>
+#include <devices/lnx_virtio_pci.h>
+#include <palacios/vmm_symmod.h>
+
+#include <devices/pci.h>
+
+
+#define QUEUE_SIZE 128
+#define NUM_QUEUES 2
+
+struct sym_config {
+} __attribute__((packed));
+
+
+
+struct virtio_sym_state {
+    struct sym_config sym_cfg;
+    struct virtio_config virtio_cfg;
+
+
+    struct vm_device * pci_bus;
+    struct pci_device * pci_dev;
+
+
+#define NOTIFY_QUEUE 0
+#define LOADER_QUEUE 1
+    struct virtio_queue queue[NUM_QUEUES];
+
+    struct virtio_queue * cur_queue;
+
+    int notifier_active;
+
+    int io_range_size;
+};
+
+
+
+// structure of the symmod notifier ring structures
+struct symmod_hdr {
+    uint32_t num_bytes;
+    char name[32];
+} __attribute__((packed));
+
+
+static int virtio_reset(struct virtio_sym_state * virtio) {
+
+    memset(virtio->queue, 0, sizeof(struct virtio_queue) * 2);
+
+    virtio->cur_queue = &(virtio->queue[0]);
+
+    virtio->virtio_cfg.status = 0;
+    virtio->virtio_cfg.pci_isr = 0;
+
+    virtio->queue[0].queue_size = QUEUE_SIZE;
+    virtio->queue[1].queue_size = QUEUE_SIZE;
+
+
+    memset(&(virtio->sym_cfg), 0, sizeof(struct sym_config));
+
+    return 0;
+}
+
+
+
+static int get_desc_count(struct virtio_queue * q, int index) {
+    struct vring_desc * tmp_desc = &(q->desc[index]);
+    int cnt = 1;
+    
+    while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
+       tmp_desc = &(q->desc[tmp_desc->next]);
+       cnt++;
+    }
+
+    return cnt;
+}
+
+
+
+
+static int handle_xfer_kick(struct guest_info * core, struct virtio_sym_state * sym_state) {
+    struct virtio_queue * q = sym_state->cur_queue;
+    
+    PrintDebug("SYMMOD: VIRTIO SYMMOD Kick on loader queue\n");
+
+    while (q->cur_avail_idx < q->avail->index) {
+       struct vring_desc * hdr_desc = NULL;
+       struct vring_desc * buf_desc = NULL;
+       struct vring_desc * status_desc = NULL;
+       uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
+       uint16_t desc_cnt = get_desc_count(q, desc_idx);
+       struct symmod_hdr * hdr = NULL;
+       int i;
+       uint32_t xfer_len = 0;
+       uint8_t status = 0;
+       uint8_t * status_ptr = NULL;
+       struct v3_sym_module * module = NULL;
+       uint32_t offset = 0;
+
+
+       PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE);
+
+       if (desc_cnt < 3) {
+           PrintError("Symmod loads must include at least 3 descriptors (cnt=%d)\n", desc_cnt);
+           return -1;
+       }
+       
+       hdr_desc = &(q->desc[desc_idx]);
+
+       if (guest_pa_to_host_va(core, hdr_desc->addr_gpa, (addr_t *)&hdr) == -1) {
+           PrintError("Could not translate SYMMOD header address\n");
+           return -1;
+       }
+
+       desc_idx = hdr_desc->next;
+
+       module = v3_get_sym_module(core->vm_info, hdr->name);
+
+       for (i = 0; i < desc_cnt - 2; i++) {
+           uint8_t tmp_status = 0;
+           uint8_t * buf = NULL;
+
+           buf_desc = &(q->desc[desc_idx]);
+
+           if (guest_pa_to_host_va(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
+               PrintError("Could not translate buffer address\n");
+               return -1;
+           }
+
+           memcpy(buf, module->data + offset, buf_desc->length);
+
+           if (tmp_status != 0) {
+               PrintError("Error loading module segment\n");
+               status = tmp_status;
+           }
+
+
+           offset += buf_desc->length;
+           xfer_len += buf_desc->length;
+           desc_idx = buf_desc->next;
+       }
+
+       status_desc = &(q->desc[desc_idx]);
+
+       if (guest_pa_to_host_va(core, status_desc->addr_gpa, (addr_t *)&status_ptr) == -1) {
+           PrintError("SYMMOD Error could not translate status address\n");
+           return -1;
+       }
+
+       xfer_len += status_desc->length;
+       *status_ptr = status;
+
+       q->used->ring[q->used->index % QUEUE_SIZE].id = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
+       q->used->ring[q->used->index % QUEUE_SIZE].length = xfer_len; // set to total inbound xfer length
+
+       q->used->index++;
+       q->cur_avail_idx++;
+    }
+
+
+    if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
+       PrintDebug("Raising IRQ %d\n",  sym_state->pci_dev->config_header.intr_line);
+       v3_pci_raise_irq(sym_state->pci_bus, 0, sym_state->pci_dev);
+       sym_state->virtio_cfg.pci_isr = 1;
+    }
+
+
+    return 0;
+}
+
+
+static int virtio_io_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * private_data) {
+    struct virtio_sym_state * sym_state = (struct virtio_sym_state *)private_data;
+    int port_idx = port % sym_state->io_range_size;
+
+
+    PrintDebug("SYMMOD: VIRTIO SYMMOD Write for port %d len=%d, value=%x\n", 
+              port, length, *(uint32_t *)src);
+    PrintDebug("SYMMOD: port idx=%d\n", port_idx);
+
+
+    switch (port_idx) {
+       case GUEST_FEATURES_PORT:
+           if (length != 4) {
+               PrintError("Illegal write length for guest features\n");
+               return -1;
+           }
+           
+           sym_state->virtio_cfg.guest_features = *(uint32_t *)src;
+
+           break;
+       case VRING_PG_NUM_PORT:
+           if (length == 4) {
+               addr_t pfn = *(uint32_t *)src;
+               addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
+
+               sym_state->cur_queue->pfn = pfn;
+               
+               sym_state->cur_queue->ring_desc_addr = page_addr ;
+               sym_state->cur_queue->ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
+               sym_state->cur_queue->ring_used_addr = ( sym_state->cur_queue->ring_avail_addr + \
+                                                sizeof(struct vring_avail)    + \
+                                                (QUEUE_SIZE * sizeof(uint16_t)));
+               
+               // round up to next page boundary.
+               sym_state->cur_queue->ring_used_addr = (sym_state->cur_queue->ring_used_addr + 0xfff) & ~0xfff;
+
+               if (guest_pa_to_host_va(core, sym_state->cur_queue->ring_desc_addr, (addr_t *)&(sym_state->cur_queue->desc)) == -1) {
+                   PrintError("Could not translate ring descriptor address\n");
+                   return -1;
+               }
+
+
+               if (guest_pa_to_host_va(core, sym_state->cur_queue->ring_avail_addr, (addr_t *)&(sym_state->cur_queue->avail)) == -1) {
+                   PrintError("Could not translate ring available address\n");
+                   return -1;
+               }
+
+
+               if (guest_pa_to_host_va(core, sym_state->cur_queue->ring_used_addr, (addr_t *)&(sym_state->cur_queue->used)) == -1) {
+                   PrintError("Could not translate ring used address\n");
+                   return -1;
+               }
+
+               PrintDebug("SYMMOD: RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
+                          (void *)(sym_state->cur_queue->ring_desc_addr),
+                          (void *)(sym_state->cur_queue->ring_avail_addr),
+                          (void *)(sym_state->cur_queue->ring_used_addr));
+
+               PrintDebug("SYMMOD: RingDesc=%p, Avail=%p, Used=%p\n", 
+                          sym_state->cur_queue->desc, sym_state->cur_queue->avail, sym_state->cur_queue->used);
+
+           } else {
+               PrintError("Illegal write length for page frame number\n");
+               return -1;
+           }
+           break;
+       case VRING_Q_SEL_PORT:
+           sym_state->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
+
+           if (sym_state->virtio_cfg.vring_queue_selector > NUM_QUEUES) {
+               PrintError("Virtio Symbiotic device has no qeueues. Selected %d\n", 
+                          sym_state->virtio_cfg.vring_queue_selector);
+               return -1;
+           }
+           
+           sym_state->cur_queue = &(sym_state->queue[sym_state->virtio_cfg.vring_queue_selector]);
+
+           break;
+       case VRING_Q_NOTIFY_PORT: {
+           uint16_t queue_idx = *(uint16_t *)src;
+
+           PrintDebug("SYMMOD: Handling Kick\n");
+
+           if (queue_idx == 0) {
+               sym_state->notifier_active = 1;
+
+           } else if (queue_idx == 1) {
+               if (handle_xfer_kick(core, sym_state) == -1) {
+                   PrintError("Could not handle Symbiotic Notification\n");
+                   return -1;
+               }
+           } else {
+               PrintError("Kick on invalid queue (%d)\n", queue_idx);
+               return -1;
+           }
+
+           break;
+       }
+       case VIRTIO_STATUS_PORT:
+           sym_state->virtio_cfg.status = *(uint8_t *)src;
+
+           if (sym_state->virtio_cfg.status == 0) {
+               PrintDebug("SYMMOD: Resetting device\n");
+               virtio_reset(sym_state);
+           }
+
+           break;
+
+       case VIRTIO_ISR_PORT:
+           sym_state->virtio_cfg.pci_isr = *(uint8_t *)src;
+           break;
+       default:
+           return -1;
+           break;
+    }
+
+    return length;
+}
+
+
+static int virtio_io_read(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * private_data) {
+
+    struct virtio_sym_state * sym_state = (struct virtio_sym_state *)private_data;
+    int port_idx = port % sym_state->io_range_size;
+
+/*
+    PrintDebug("SYMMOD: VIRTIO SYMBIOTIC Read  for port %d (index =%d), length=%d\n", 
+              port, port_idx, length);
+*/
+    switch (port_idx) {
+       case HOST_FEATURES_PORT:
+           if (length != 4) {
+               PrintError("Illegal read length for host features\n");
+               return -1;
+           }
+
+           *(uint32_t *)dst = sym_state->virtio_cfg.host_features;
+       
+           break;
+       case VRING_PG_NUM_PORT:
+           if (length != 4) {
+               PrintError("Illegal read length for page frame number\n");
+               return -1;
+           }
+
+           *(uint32_t *)dst = sym_state->cur_queue->pfn;
+
+           break;
+       case VRING_SIZE_PORT:
+           if (length != 2) {
+               PrintError("Illegal read length for vring size\n");
+               return -1;
+           }
+               
+           *(uint16_t *)dst = sym_state->cur_queue->queue_size;
+
+           break;
+
+       case VIRTIO_STATUS_PORT:
+           if (length != 1) {
+               PrintError("Illegal read length for status\n");
+               return -1;
+           }
+
+           *(uint8_t *)dst = sym_state->virtio_cfg.status;
+           break;
+
+       case VIRTIO_ISR_PORT:
+           *(uint8_t *)dst = sym_state->virtio_cfg.pci_isr;
+           sym_state->virtio_cfg.pci_isr = 0;
+           v3_pci_lower_irq(sym_state->pci_bus, 0, sym_state->pci_dev);
+           break;
+
+       default:
+           if ( (port_idx >= sizeof(struct virtio_config)) && 
+                (port_idx < (sizeof(struct virtio_config) + sizeof(struct sym_config))) ) {
+               int cfg_offset = port_idx - sizeof(struct virtio_config);
+               uint8_t * cfg_ptr = (uint8_t *)&(sym_state->sym_cfg);
+
+               memcpy(dst, cfg_ptr + cfg_offset, length);
+               
+           } else {
+               PrintError("Read of Unhandled Virtio Read\n");
+               return -1;
+           }
+         
+           break;
+    }
+
+    return length;
+}
+
+
+
+
+static int virtio_load_module(struct v3_vm_info * vm, char * name, int mod_size, void * priv_data) {
+    struct virtio_sym_state * virtio = (struct virtio_sym_state *)priv_data;
+    //   struct virtio_queue * q = virtio->cur_queue;
+    struct virtio_queue * q = &(virtio->queue[NOTIFY_QUEUE]);
+
+    if (strlen(name) >= 32) {
+       PrintError("Module name is too long... (%d bytes) limit is 32\n", (uint32_t)strlen(name));
+       return -1;
+    }
+
+    PrintDebug("SYMMOD: VIRTIO SYMMOD Loader: Loading Module (size=%d)\n", mod_size);
+
+    //queue is not set yet
+    if (q->ring_avail_addr == 0) {
+       PrintError("Queue is not set\n");
+       return -1;
+    }
+
+    
+    if (q->cur_avail_idx < q->avail->index) {
+       uint16_t notifier_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
+       struct symmod_hdr * notifier = NULL;
+       struct vring_desc * notifier_desc = NULL;
+
+       PrintDebug("SYMMOD: Descriptor index=%d\n", q->cur_avail_idx % q->queue_size);
+
+       notifier_desc = &(q->desc[notifier_idx]);
+
+       PrintDebug("SYMMOD: Notifier Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", notifier_desc, 
+                  (void *)(notifier_desc->addr_gpa), notifier_desc->length, notifier_desc->flags, notifier_desc->next);        
+
+       if (guest_pa_to_host_va(&(vm->cores[0]), notifier_desc->addr_gpa, (addr_t *)&(notifier)) == -1) {
+           PrintError("Could not translate receive buffer address\n");
+           return -1;
+       }
+
+       // clear the notifier
+       memset(notifier, 0, sizeof(struct symmod_hdr));
+
+       // set the module name
+       memcpy(notifier->name, name, strlen(name));
+
+       // set module length
+       notifier->num_bytes = mod_size;
+
+       
+       q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
+
+       q->used->ring[q->used->index % q->queue_size].length = sizeof(struct symmod_hdr);
+
+       q->used->index++;
+       q->cur_avail_idx++;
+    }
+
+    if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
+       PrintDebug("SYMMOD: Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
+       v3_pci_raise_irq(virtio->pci_bus, 0, virtio->pci_dev);
+       virtio->virtio_cfg.pci_isr = 0x1;
+    }
+
+
+    return 0;
+}
+
+
+
+
+static struct v3_device_ops dev_ops = {
+    .free = NULL,
+    .reset = NULL,
+    .start = NULL,
+    .stop = NULL,
+};
+
+
+
+static struct v3_symmod_loader_ops loader_ops = {
+    .load_module = virtio_load_module,
+};
+
+
+static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
+    struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
+    struct virtio_sym_state * virtio_state = NULL;
+    struct pci_device * pci_dev = NULL;
+    char * name = v3_cfg_val(cfg, "name");
+
+    PrintDebug("SYMMOD: Initializing VIRTIO Symbiotic Module device\n");
+
+    if (pci_bus == NULL) {
+       PrintError("VirtIO devices require a PCI Bus");
+       return -1;
+    }
+    
+    virtio_state  = (struct virtio_sym_state *)V3_Malloc(sizeof(struct virtio_sym_state));
+    memset(virtio_state, 0, sizeof(struct virtio_sym_state));
+
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
+
+    if (v3_attach_device(vm, dev) == -1) {
+       PrintError("Could not attach device %s\n", name);
+       return -1;
+    }
+
+
+    // PCI initialization
+    {
+       struct v3_pci_bar bars[6];
+       int num_ports = sizeof(struct virtio_config) + sizeof(struct sym_config);
+       int tmp_ports = num_ports;
+       int i;
+
+
+       // This gets the number of ports, rounded up to a power of 2
+       virtio_state->io_range_size = 1; // must be a power of 2
+
+       while (tmp_ports > 0) {
+           tmp_ports >>= 1;
+           virtio_state->io_range_size <<= 1;
+       }
+       
+       // this is to account for any low order bits being set in num_ports
+       // if there are none, then num_ports was already a power of 2 so we shift right to reset it
+       if ((num_ports & ((virtio_state->io_range_size >> 1) - 1)) == 0) {
+           virtio_state->io_range_size >>= 1;
+       }
+
+
+       for (i = 0; i < 6; i++) {
+           bars[i].type = PCI_BAR_NONE;
+       }
+
+       bars[0].type = PCI_BAR_IO;
+       bars[0].default_base_port = -1;
+       bars[0].num_ports = virtio_state->io_range_size;
+
+       bars[0].io_read = virtio_io_read;
+       bars[0].io_write = virtio_io_write;
+       bars[0].private_data = virtio_state;
+
+       pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
+                                        0, PCI_AUTO_DEV_NUM, 0,
+                                        "LNX_VIRTIO_SYMMOD", bars,
+                                        NULL, NULL, NULL, virtio_state);
+
+       if (!pci_dev) {
+           PrintError("Could not register PCI Device\n");
+           return -1;
+       }
+       
+       pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
+       pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
+       
+
+       pci_dev->config_header.device_id = VIRTIO_SYMMOD_DEV_ID;
+       pci_dev->config_header.class = PCI_CLASS_MEMORY;
+       pci_dev->config_header.subclass = PCI_MEM_SUBCLASS_RAM;
+    
+       pci_dev->config_header.subsystem_id = VIRTIO_SYMMOD_SUBDEVICE_ID;
+
+
+       pci_dev->config_header.intr_pin = 1;
+
+       pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
+
+
+       virtio_state->pci_dev = pci_dev;
+       virtio_state->pci_bus = pci_bus;
+    }
+
+    virtio_reset(virtio_state);
+
+    v3_set_symmod_loader(vm, &loader_ops, virtio_state);
+
+    return 0;
+}
+
+
+device_register("LNX_VIRTIO_SYMMOD", virtio_init)
index c8943f0..239efdc 100644 (file)
@@ -64,7 +64,10 @@ int v3_init_symbiotic_vm(struct v3_vm_info * vm) {
 #endif
 
 #ifdef CONFIG_SYMMOD
-
+    if (v3_init_symmod_vm(vm, vm->cfg_data->cfg) == -1) {
+       PrintError("Error initializing global SymMod state\n");
+       return -1;
+    }
 #endif
 
 
diff --git a/palacios/src/palacios/vmm_symmod.c b/palacios/src/palacios/vmm_symmod.c
new file mode 100644 (file)
index 0000000..d52f01e
--- /dev/null
@@ -0,0 +1,68 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+#include <palacios/vmm.h>
+#include <palacios/vmm_symmod.h>
+#include <palacios/vmm_symbiotic.h>
+#include <palacios/vm_guest.h>
+
+
+int V3_init_symmod() {
+
+    return -1;
+}
+
+
+
+int v3_init_symmod_vm(struct v3_vm_info * info, v3_cfg_tree_t * cfg) {
+    return 0;
+}
+
+
+
+int v3_set_symmod_loader(struct v3_vm_info * vm, struct v3_symmod_loader_ops * ops, void * priv_data) {
+    struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
+
+
+    symmod_state->loader_ops = ops;
+    symmod_state->loader_data = priv_data;
+
+    return 0;
+}
+
+
+
+static char test_module_data[16] = {"hello"};
+
+static struct v3_sym_module test_module = {
+    .name = "test",
+    .num_bytes = 16,
+    .data = test_module_data,
+};
+
+int v3_load_sym_module(struct v3_vm_info * vm, char * mod_name) {
+    struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
+
+    PrintDebug("Loading Module (%s)\n", mod_name);
+
+    return symmod_state->loader_ops->load_module(vm, mod_name, 16, symmod_state->loader_data);
+}
+
+struct v3_sym_module * v3_get_sym_module(struct v3_vm_info * vm, char * name) {
+    return &test_module;
+}