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 newskysaw.cs.northwestern.edu:/home/palacios/palacios into...
Peter Dinda [Tue, 6 Sep 2011 18:55:54 +0000 (13:55 -0500)]
57 files changed:
Kconfig
Makefile
linux_module/Makefile
linux_module/iface-console.c
linux_module/iface-stream.c
linux_module/mcheck.c [new file with mode: 0644]
linux_module/mm.c
linux_module/palacios-stubs.c
linux_module/palacios-vnet-brg.c
linux_module/palacios.h
linux_module/util-hashtable.c
linux_module/vm.c
linux_usr/Makefile
linux_usr/v3_cons_sc.c [new file with mode: 0644]
linux_usr/v3_inject_ecc_scrubber_mce.c [new file with mode: 0644]
linux_usr/v3_mem.c
linux_usr/v3_net.c [deleted file]
linux_usr/v3_serial.c [deleted file]
linux_usr/v3_stream.c [new file with mode: 0644]
palacios/include/devices/lnx_virtio_pci.h
palacios/include/interfaces/vmm_stream.h
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm.h
palacios/include/palacios/vmm_barrier.h
palacios/include/palacios/vmm_bitmap.h [new file with mode: 0644]
palacios/include/palacios/vmm_decoder.h
palacios/include/palacios/vmm_dev_mgr.h
palacios/include/palacios/vmm_instr_emulator.h
palacios/include/palacios/vmm_mtrr.h [deleted file]
palacios/include/palacios/vmm_types.h
palacios/include/vnet/vnet.h
palacios/src/devices/Kconfig
palacios/src/devices/Makefile
palacios/src/devices/cga.c
palacios/src/devices/char_stream.c
palacios/src/devices/lnx_virtio_console.c [new file with mode: 0644]
palacios/src/devices/lnx_virtio_nic.c
palacios/src/devices/piix3.c
palacios/src/devices/serial.c
palacios/src/devices/vnet_nic.c
palacios/src/extensions/ext_mcheck.c
palacios/src/extensions/ext_mtrr.c [new file with mode: 0644]
palacios/src/interfaces/vmm_stream.c
palacios/src/palacios/Makefile
palacios/src/palacios/svm.c
palacios/src/palacios/vm_guest.c
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_barrier.c
palacios/src/palacios/vmm_bitmap.c [new file with mode: 0644]
palacios/src/palacios/vmm_extensions.c
palacios/src/palacios/vmm_mem_hook.c
palacios/src/palacios/vmm_mtrr.c [deleted file]
palacios/src/palacios/vmm_string.c
palacios/src/palacios/vmm_xml.c
palacios/src/palacios/vmx.c
palacios/src/palacios/vmx_handler.c
palacios/src/vnet/vnet_core.c

diff --git a/Kconfig b/Kconfig
index 6432790..5397fec 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -76,6 +76,12 @@ config VMX
          Compile with support for Intel VMX
 
 
+config FRAME_POINTER
+       bool "Compile with Frame pointers"
+       default n
+       help
+         Compiles the Palacios library with Frame pointers
+
 config DEBUG_INFO
        bool "Compile with Debug Information"
        default n
@@ -296,12 +302,6 @@ endmenu
 
 menu "Debug configuration"
 
-config CONFIG_DEBUG_INFO
-       bool "Compile with Debug information"
-       default n
-       help 
-        This adds the -g flag to the compilation flags
-
 
 ## Is unwind information useful
 
index 1b14317..22b56bb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -298,7 +298,8 @@ V3_INCLUDE      := -Ipalacios/include \
 
 CPPFLAGS        := $(V3_INCLUDE) -D__V3VEE__
 
-CFLAGS                 :=  -fno-stack-protector -Wall -Werror  -mno-red-zone -fno-common 
+CFLAGS                 :=  -fno-stack-protector -Wall -Werror  -mno-red-zone -fno-common \
+                   $(call cc-option, -Wno-unused-but-set-variable,)
 
 
 
@@ -379,9 +380,9 @@ ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
 endif
 
 ifeq ($(KBUILD_EXTMOD),)
-        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
+        ifneq ($(filter %config,$(MAKECMDGOALS)),)
                 config-targets := 1
-                ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
+                ifneq ($(filter-out %config,$(MAKECMDGOALS)),)
                         mixed-targets := 1
                 endif
         endif
@@ -407,7 +408,7 @@ ifeq ($(config-targets),1)
 include $(srctree)/Makefile.$(ARCH)
 export KBUILD_DEFCONFIG
 
-config %config: scripts_basic outputmakefile FORCE
+%config: scripts_basic outputmakefile FORCE
        $(Q)mkdir -p palacios/include/config
        $(Q)$(MAKE) $(build)=scripts/kconfig $@
 #      $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
@@ -500,8 +501,6 @@ endif
 
 ifdef V3_CONFIG_DEBUG_INFO
 CFLAGS         += -g
-else 
-CFLAGS          += -O
 endif
 
 
@@ -942,7 +941,7 @@ target-dir = $(dir $@)
        $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
 
 # Modules
-/ %/: prepare scripts FORCE
+%/: prepare scripts FORCE
        $(Q)$(MAKE) KBUILD_MODULES=$(if $(V3_CONFIG_MODULES),1) \
        $(build)=$(build-dir)
 %.ko: prepare scripts FORCE
index 137674c..d028d2e 100644 (file)
@@ -27,6 +27,7 @@ v3vee-$(V3_CONFIG_SOCKET) += iface-socket.o
 v3vee-$(V3_CONFIG_KEYED_STREAMS) += iface-keyed-stream.o
 v3vee-$(V3_CONFIG_HOST_DEVICE) += iface-host-dev.o
 v3vee-$(V3_CONFIG_GRAPHICS_CONSOLE) += iface-graphics-console.o
+v3vee-$(V3_CONFIG_EXT_MACH_CHECK) += mcheck.o
 
 v3vee-$(V3_CONFIG_VNET) +=     palacios-vnet.o \
                                palacios-vnet-ctrl.o   \
index 02d9761..9e13546 100644 (file)
@@ -140,7 +140,7 @@ console_write(struct file * filp, const char __user * buf, size_t size, loff_t *
 
 
     for (i = 0; i < size; i++) {
-       if (copy_from_user(&(event.scan_code), buf, 1)) {
+       if (copy_from_user(&(event.scan_code), buf + i, 1)) {
            printk("Console Write fault\n");
            return -EFAULT;
        }
@@ -217,7 +217,7 @@ static int console_connect(struct v3_guest * guest, unsigned int cmd,
 
     spin_lock_irqsave(&(cons->lock), flags);
 
-    cons_fd = anon_inode_getfd("v3-cons", &cons_fops, cons, 0);
+    cons_fd = anon_inode_getfd("v3-cons", &cons_fops, cons, O_RDWR);
 
     if (cons_fd < 0) {
        printk("Error creating console inode\n");
index 36582d9..9cb89e5 100644 (file)
 #include "iface-stream.h"
 
 
-// This is going to need to be a lot bigger...
-#define STREAM_BUF_SIZE 1024
+// This is probably overkill
+#define STREAM_RING_LEN 4096
 
 
 
 
 static struct list_head global_streams;
 
-struct stream_buffer {
+
+
+struct stream_state {
     char name[STREAM_NAME_LEN];
-    struct ringbuf * buf;
+
+    struct ringbuf * out_ring;
 
     int connected;
 
@@ -40,19 +43,24 @@ struct stream_buffer {
 
     struct v3_guest * guest;
     struct list_head stream_node;
+
+    struct v3_stream * v3_stream;
 };
 
 
 // Currently just the list of open streams
-struct vm_stream_state {
+struct vm_global_streams {
     struct list_head open_streams;
 };
 
 
-static struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const char * name) {
-    struct stream_buffer * stream = NULL;
+
+
+
+static struct stream_state * find_stream_by_name(struct v3_guest * guest, const char * name) {
+    struct stream_state * stream = NULL;
     struct list_head * stream_list = NULL;
-    struct vm_stream_state * vm_state = NULL;
+    struct vm_global_streams * vm_state = NULL;
 
     if (guest == NULL) {
        stream_list = &global_streams;
@@ -78,28 +86,119 @@ static struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const
 
 
 
+#define TMP_BUF_LEN 128
+
 static ssize_t stream_read(struct file * filp, char __user * buf, size_t size, loff_t * offset) {
-    struct stream_buffer * stream = filp->private_data;
+    struct stream_state * stream = filp->private_data;
+    ssize_t bytes_read = 0;
+    ssize_t bytes_left = size;
+    unsigned long flags;
+    char tmp_buf[TMP_BUF_LEN];
+    ssize_t total_bytes_left = 0;
+
+    // memset(tmp_buf, 0, TMP_BUF_LEN);
+
+    while (bytes_left > 0) {
+       int tmp_len = (TMP_BUF_LEN > bytes_left) ? bytes_left : TMP_BUF_LEN;
+       int tmp_read = 0;
+
+       spin_lock_irqsave(&(stream->lock), flags);
+       tmp_read = ringbuf_read(stream->out_ring, tmp_buf, tmp_len);
+       spin_unlock_irqrestore(&(stream->lock), flags);
+
+       if (tmp_read == 0) {
+           // If userspace reads more than we have
+           break;
+       }
+
+       if (copy_to_user(buf + bytes_read, tmp_buf, tmp_read)) {
+           printk("Read Fault\n");
+           return -EFAULT;
+       }
+       
+       bytes_left -= tmp_read;
+       bytes_read += tmp_read;
+    }
     
-    wait_event_interruptible(stream->intr_queue, (ringbuf_data_len(stream->buf) != 0));
 
-    return ringbuf_read(stream->buf, buf, size);
+    spin_lock_irqsave(&(stream->lock), flags); 
+    total_bytes_left = ringbuf_data_len(stream->out_ring);
+    spin_unlock_irqrestore(&(stream->lock), flags);
+
+    if (total_bytes_left > 0) {
+       wake_up_interruptible(&(stream->intr_queue));
+    }
+
+    return bytes_read;
 }
 
+static unsigned int 
+stream_poll(struct file * filp, struct poll_table_struct * poll_tb) {
+    struct stream_state * stream = filp->private_data;
+    unsigned int mask = POLLIN | POLLRDNORM;
+    unsigned long flags;
+    int data_avail = 0;
+
+    poll_wait(filp, &(stream->intr_queue), poll_tb);
+
+    spin_lock_irqsave(&(stream->lock), flags);
+    data_avail = ringbuf_data_len(stream->out_ring);
+    spin_unlock_irqrestore(&(stream->lock), flags);
+
+    if (data_avail > 0) {
+       return mask;
+    }
 
+    return 0;
+
+}
+
+static ssize_t stream_write(struct file * filp, const char __user * buf, size_t size, loff_t * offset) {
+    struct stream_state * stream = filp->private_data;
+    char * kern_buf = NULL;
+    ssize_t bytes_written = 0;
+    
+    kern_buf = kmalloc(size, GFP_KERNEL);
+
+    if (copy_from_user(kern_buf, buf, size)) {
+       printk("Stream Write Failed\n");
+       return -EFAULT;
+    };
+    
+    bytes_written = stream->v3_stream->input(stream->v3_stream, kern_buf, size);
+
+    kfree(kern_buf);
+
+    return bytes_written;
+}
+
+
+static int stream_release(struct inode * i, struct file * filp) {
+    struct stream_state * stream = filp->private_data;
+    unsigned long flags;
+    
+    spin_lock_irqsave(&(stream->lock), flags);
+    stream->connected = 0;
+    spin_unlock_irqrestore(&(stream->lock), flags);
+
+    
+    return 0;
+
+}
 
 static struct file_operations stream_fops = {
     .read = stream_read,
-    //    .release = stream_close,
-    //  .poll = stream_poll,
+    .write = stream_write,
+    .release = stream_release,
+    .poll = stream_poll,
 };
 
 
 
-static void * palacios_stream_open(const char * name, void * private_data) {
+static void * palacios_stream_open(struct v3_stream * v3_stream, 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;
+    struct stream_state * stream = NULL;
+    struct vm_global_streams * vm_state = NULL;
 
     if (guest != NULL) {
        vm_state = get_vm_ext_data(guest, "STREAM_INTERFACE");
@@ -115,10 +214,13 @@ static void * palacios_stream_open(const char * name, void * private_data) {
        return NULL;
     }
 
-    stream = kmalloc(sizeof(struct stream_buffer), GFP_KERNEL);
-       
-    stream->buf = create_ringbuf(STREAM_BUF_SIZE);
+    stream = kmalloc(sizeof(struct stream_state), GFP_KERNEL);
+    memset(stream, 0, sizeof(struct stream_state));
+
+    stream->out_ring = create_ringbuf(STREAM_RING_LEN);
+    stream->v3_stream = v3_stream;
     stream->guest = guest;
+    stream->connected = 0;
 
     strncpy(stream->name, name, STREAM_NAME_LEN - 1);
 
@@ -135,24 +237,38 @@ static void * palacios_stream_open(const char * name, void * private_data) {
 }
 
 
-static int palacios_stream_write(void * stream_ptr, char * buf, int len) {
-    struct stream_buffer * stream = (struct stream_buffer *)stream_ptr;
-    int ret = 0;
+static uint64_t palacios_stream_output(struct v3_stream * v3_stream, char * buf, int len) {
+    struct stream_state * stream = (struct stream_state *)v3_stream->host_stream_data;
+    int bytes_written = 0;
+    unsigned long flags;
+    
 
-    ret = ringbuf_write(stream->buf, buf, len);
+    if (stream->connected == 0) {
+       return 0;
+    }
+
+    while (bytes_written < len) {
+       spin_lock_irqsave(&(stream->lock), flags);
+       bytes_written += ringbuf_write(stream->out_ring, buf + bytes_written, len - bytes_written);
+       spin_unlock_irqrestore(&(stream->lock), flags);
 
-    if (ret > 0) {
        wake_up_interruptible(&(stream->intr_queue));
+
+       if (bytes_written < len) {
+           // not enough space in ringbuffer, activate user space to drain it
+           schedule();
+       }
     }
 
-    return ret;
+    
+    return bytes_written;
 }
 
 
-static void palacios_stream_close(void * stream_ptr) {
-    struct stream_buffer * stream = (struct stream_buffer *)stream_ptr;
+static void palacios_stream_close(struct v3_stream * v3_stream) {
+    struct stream_state * stream = (struct stream_state *)v3_stream->host_stream_data;
 
-    free_ringbuf(stream->buf);
+    free_ringbuf(stream->out_ring);
     list_del(&(stream->stream_node));
     kfree(stream);
 
@@ -160,7 +276,7 @@ static void palacios_stream_close(void * stream_ptr) {
 
 static struct v3_stream_hooks palacios_stream_hooks = {
     .open = palacios_stream_open,
-    .write = palacios_stream_write,
+    .output = palacios_stream_output,
     .close = palacios_stream_close,
 };
 
@@ -188,7 +304,7 @@ static int stream_deinit( void ) {
 
 static int stream_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data) {
     void __user * argp = (void __user *)arg;
-    struct stream_buffer * stream = NULL;
+    struct stream_state * stream = NULL;
     int stream_fd = 0;
     char name[STREAM_NAME_LEN];
     unsigned long flags = 0;
@@ -221,7 +337,7 @@ static int stream_connect(struct v3_guest * guest, unsigned int cmd, unsigned lo
     }
 
     
-    stream_fd = anon_inode_getfd("v3-stream", &stream_fops, stream, 0);
+    stream_fd = anon_inode_getfd("v3-stream", &stream_fops, stream, O_RDWR);
 
     if (stream_fd < 0) {
        printk("Error creating stream inode for (%s)\n", name);
@@ -235,12 +351,11 @@ static int stream_connect(struct v3_guest * guest, unsigned int cmd, unsigned lo
 
 
 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);
+    struct vm_global_streams * state = kmalloc(sizeof(struct vm_global_streams), GFP_KERNEL);
 
     INIT_LIST_HEAD(&(state->open_streams));
     *vm_data = state;
 
-
     add_guest_ctrl(guest, V3_VM_STREAM_CONNECT, stream_connect, state);
 
     return 0;
@@ -248,7 +363,7 @@ static int guest_stream_init(struct v3_guest * guest, void ** vm_data) {
 
 
 static int guest_stream_deinit(struct v3_guest * guest, void * vm_data) {
-    struct vm_stream_state * state = vm_data;
+    struct vm_global_streams * state = vm_data;
     if (!list_empty(&(state->open_streams))) {
        printk("Error shutting down VM with open streams\n");
     }
diff --git a/linux_module/mcheck.c b/linux_module/mcheck.c
new file mode 100644 (file)
index 0000000..e357e94
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+ * DebugFS interface
+ * (c) Patrick Bridges and Philip Soltero, 2011
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include <interfaces/vmm_mcheck.h>
+
+#include "palacios.h"
+#include "vm.h"
+#include "linux-exts.h"
+
+#define SCRUBBER_MCE 0x1
+#define V3_VM_INJECT_SCRUBBER_MCE (10224+20)
+
+static int inject_mce(struct v3_guest * guest, unsigned int cmd, unsigned long arg,
+                      void * priv_data)
+{
+    unsigned long type = (unsigned long)priv_data;
+    switch ( type ) {
+       case SCRUBBER_MCE:
+           return v3_mcheck_inject_scrubber_mce((struct v3_vm_info *)guest->v3_ctx, 0, arg);
+           break;
+       default:
+           // TODO: How to print an error in the host OS?
+           //PrintError("Injection of unknown machine check type %lu requested.\n", type);
+           return -1;
+           break;
+    }
+}
+
+static int guest_init(struct v3_guest * guest, void ** vm_data) {
+
+    add_guest_ctrl(guest, V3_VM_INJECT_SCRUBBER_MCE, inject_mce, (void *)SCRUBBER_MCE);
+    return 0;
+}
+
+static int guest_deinit(struct v3_guest * guest, void * vm_data) {
+    
+    return 0;
+}
+
+
+struct linux_ext mcheck_ext = {
+    .name = "MACHINE CHECK",
+    .init = NULL,
+    .deinit = NULL,
+    .guest_init = guest_init, 
+    .guest_deinit = guest_deinit
+};
+
+
+register_extension(&mcheck_ext);
index a62b55a..04dcab3 100644 (file)
@@ -65,7 +65,7 @@ static uintptr_t alloc_contig_pgs(u64 num_pages, u32 alignment) {
        start = ((alignment - (pool.base_addr % alignment)) >> 12);
     }
 
-    printk("\t Start idx %d (base_addr=%llu)\n", start, (u64)pool.base_addr);
+    printk("\t Start idx %d (base_addr=%p)\n", start, (void *)(u64)pool.base_addr);
 
     for (i = start; i < (pool.num_pages - num_pages); i += step) {
        if (get_page_bit(i) == 0) {
index be06001..05789fb 100644 (file)
@@ -85,8 +85,13 @@ static void *
 palacios_alloc(unsigned int size) {
     void * addr = NULL;
 
-    addr = kmalloc(size, GFP_KERNEL);
+    if (irqs_disabled()) {
+       addr = kmalloc(size, GFP_ATOMIC);
+    } else {
+       addr = kmalloc(size, GFP_KERNEL);
+    }
     mallocs++;
+
  
     return addr;
 }
@@ -468,7 +473,7 @@ int palacios_vmm_init( void )
     
     printk("palacios_init starting - calling init_v3\n");
     
-    Init_V3(&palacios_os_hooks, nr_cpu_ids);
+    Init_V3(&palacios_os_hooks, num_online_cpus());
 
     return 0;
 
index 81af9a4..7a605c7 100644 (file)
@@ -308,7 +308,7 @@ send_to_palacios(unsigned char * buf,
 
     vnet_brg_s.stats.pkt_to_vmm ++;
 
-    return v3_vnet_send_pkt(&pkt, NULL, 1);
+    return v3_vnet_send_pkt(&pkt, NULL);
 }
 
 
@@ -489,7 +489,7 @@ int vnet_bridge_init(void) {
        return -1;
     }
 
-    vnet_brg_s.serv_thread = kthread_run(_rx_server, NULL, "vnet-server");
+    vnet_brg_s.serv_thread = kthread_run(_rx_server, NULL, "vnet_brgd");
 
     bridge_ops.input = bridge_send_pkt;
     bridge_ops.poll = NULL;
index 8730346..633ede1 100644 (file)
@@ -15,6 +15,9 @@
 #define V3_VM_CONSOLE_CONNECT 20
 
 #define V3_VM_STOP 22
+#define V3_VM_PAUSE 23
+#define V3_VM_CONTINUE 24
+
 
 #define V3_VM_INSPECT 30
 
index ebf1d1c..669bbfb 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/errno.h>
 #include <linux/preempt.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
  
 #include "util-hashtable.h"
 
index 852733c..890cb69 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/poll.h>
 #include <linux/anon_inodes.h>
 #include <linux/sched.h>
-
+#include <linux/vmalloc.h>
 #include <linux/file.h>
 #include <linux/spinlock.h>
 #include <linux/rbtree.h>
@@ -129,10 +129,20 @@ static long v3_vm_ioctl(struct file * filp,
     switch (ioctl) {
 
        case V3_VM_STOP: {
-           printk("Stopping VM\n");
+           printk("Stopping VM (%s)\n", guest->name);
            stop_palacios_vm(guest);
            break;
        }
+       case V3_VM_PAUSE: {
+           printk("Pausing VM (%s)\n", guest->name);
+           v3_pause_vm(guest->v3_ctx);
+           break;
+       }
+       case V3_VM_CONTINUE: {
+           printk("Continuing VM (%s)\n", guest->name);
+           v3_continue_vm(guest->v3_ctx);
+           break;
+       }
 
        default: {
            struct vm_ctrl * ctrl = get_ctrl(guest, ioctl);
@@ -264,7 +274,7 @@ int stop_palacios_vm(struct v3_guest * guest) {
 
     cdev_del(&(guest->cdev));
 
-    kfree(guest->img);
+    vfree(guest->img);
     kfree(guest);
 
     return 0;
index f7ca219..a1e9bb4 100644 (file)
@@ -1,4 +1,4 @@
-all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example v3_os_debug v3_user_keyed_stream_example v3_user_keyed_stream_file
+all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_stream v3_user_host_dev_example v3_os_debug v3_user_keyed_stream_example v3_user_keyed_stream_file
 
 
 
@@ -15,15 +15,12 @@ v3_mem : v3_mem.c v3_ctrl.h
 v3_cons : v3_cons.c v3_ctrl.h
        gcc -static v3_cons.c -o v3_cons -lcurses
 
-v3_serial : v3_serial.c v3_ctrl.h
-       gcc -static v3_serial.c -pthread -o v3_serial 
+v3_stream : v3_stream.c v3_ctrl.h
+       gcc -static v3_stream.c -o v3_stream 
 
 v3_monitor : v3_cons.c v3_ctrl.h
        gcc -static v3_monitor.c -o v3_monitor
 
-v3_net : v3_net.c v3_ctrl.h
-       gcc -static v3_net.c -o v3_net
-
 v3_user_host_dev_example: v3_user_host_dev_example.c v3_user_host_dev.h v3_user_host_dev.c
        gcc -static -I../linux_module v3_user_host_dev_example.c v3_user_host_dev.c -o v3_user_host_dev_example
 
@@ -37,8 +34,8 @@ v3_user_keyed_stream_example: v3_user_keyed_stream_example.c v3_user_keyed_strea
 v3_user_keyed_stream_file: v3_user_keyed_stream_file.c v3_user_keyed_stream.h v3_user_keyed_stream.c
        gcc -static -I../linux_module v3_user_keyed_stream_file.c v3_user_keyed_stream.c -o v3_user_keyed_stream_file
 
-
-
+v3_inject_ecc_scrubber_mce: v3_inject_ecc_scrubber_mce.c
+       gcc -static -I../linux_module v3_inject_ecc_scrubber_mce.c -o v3_inject_ecc_scrubber_mce
 
 clean:
-       rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example v3_os_debug v3_user_keyed_stream_example v3_user_keyed_stream_file
+       rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_stream v3_user_host_dev_example v3_os_debug v3_user_keyed_stream_example v3_user_keyed_stream_file
diff --git a/linux_usr/v3_cons_sc.c b/linux_usr/v3_cons_sc.c
new file mode 100644 (file)
index 0000000..3b9e192
--- /dev/null
@@ -0,0 +1,618 @@
+/* 
+ * V3 Console utility
+ * Taken from Palacios console display in MINIX ( by Erik Van der Kouwe )
+ * (c) Jack lange, 2010
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h> 
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <curses.h>
+#include <termios.h>
+#include <linux/kd.h>
+#include <linux/keyboard.h>
+
+#include "v3_ctrl.h"
+
+static int use_curses = 0;
+static int debug_enable = 1;
+
+
+typedef enum { CONSOLE_CURS_SET = 1,
+              CONSOLE_CHAR_SET = 2,
+              CONSOLE_SCROLL = 3,
+              CONSOLE_UPDATE = 4,
+               CONSOLE_RESOLUTION = 5 } console_op_t;
+
+
+
+static struct {
+    WINDOW * win;
+    int x;
+    int y;
+    int rows;
+    int cols;
+    struct termios termios_old;
+    unsigned char old_kbd_mode;
+} console;
+
+
+struct cursor_msg {
+    int x;
+    int y;
+} __attribute__((packed));
+
+struct character_msg {
+    int x;
+    int y;
+    char c;
+    unsigned char style;
+} __attribute__((packed));
+
+struct scroll_msg {
+    int lines;
+} __attribute__((packed));
+
+struct resolution_msg {
+    int cols;
+    int rows;
+} __attribute__((packed));
+
+
+struct cons_msg {
+    unsigned char op;
+    union {
+       struct cursor_msg cursor;
+       struct character_msg  character;
+       struct scroll_msg scroll;
+       struct resolution_msg resolution;
+    };
+} __attribute__((packed)); 
+
+
+
+
+static int handle_char_set(struct character_msg * msg) {
+    char c = msg->c;
+
+    if (debug_enable) {
+       fprintf(stderr, "setting char (%c), at (x=%d, y=%d)\n", c, msg->x, msg->y);
+    }
+
+    if (c == 0) {
+       c = ' ';
+    }
+
+
+    if ((c < ' ') || (c >= 127)) {
+       fprintf(stderr, "unexpected control character %d\n", c);
+       c = '?';
+    }
+
+    if (use_curses) {
+       /* clip whatever falls outside the visible area to avoid errors */
+       if ((msg->x < 0) || (msg->y < 0) ||
+           (msg->x > console.win->_maxx) || 
+           (msg->y > console.win->_maxy)) {
+
+           fprintf(stderr, "Char out of range (x=%d,y=%d) MAX:(x=%d,y=%d)\n",
+                   msg->x, msg->y, console.win->_maxx, console.win->_maxy);
+           return -1;
+       }
+
+       if ((msg->x == console.win->_maxx) &&
+           (msg->y == console.win->_maxy)) {
+           return -1;
+       }
+
+       mvwaddch(console.win, msg->y, msg->x, c);
+
+    } else {
+       //stdout text display
+       while (console.y < msg->y) {
+           printf("\n");
+           console.x = 0;
+           console.y++;
+       }
+
+       while (console.x < msg->x) {
+           printf(" ");
+           console.x++;
+       }
+
+       printf("%c", c);
+       console.x++;
+
+       assert(console.x <= console.cols); 
+
+       if (console.x == console.cols) {
+           printf("\n");
+           console.x = 0;
+           console.y++;
+       }
+    }
+
+    return 0;
+}
+
+int handle_curs_set(struct cursor_msg * msg) {
+    if (debug_enable) {
+       fprintf(stderr, "cursor set: (x=%d, y=%d)\n", msg->x, msg->y);
+    }
+
+    if (use_curses) {
+       /* nothing to do now, cursor is set before update to make sure it isn't 
+        * affected by character_set
+        */
+
+       console.x = msg->x;
+       console.y = msg->y;
+    }
+    
+    return 0;
+}
+
+
+int handle_scroll(struct scroll_msg * msg) {
+    int lines = msg->lines;
+
+    if (debug_enable) {
+       fprintf(stderr, "scroll: %d lines\n", lines);
+    }
+
+
+    assert(lines >= 0);
+
+    if (use_curses) {
+       while (lines > 0) {
+           scroll(console.win);
+           lines--;
+       }
+    } else {
+       console.y -= lines;     
+    }
+}
+
+int handle_text_resolution(struct resolution_msg * msg) {
+    if (debug_enable) {
+       fprintf(stderr, "text resolution: rows=%d, cols=%d\n", msg->rows, msg->cols);
+    }
+
+
+    console.rows = msg->rows;
+    console.cols = msg->cols;
+
+    return 0;
+}
+
+int handle_update( void ) {
+    if (debug_enable) {
+       fprintf(stderr, "update\n");
+    }    
+
+    if (use_curses) {
+
+       if ( (console.x >= 0) && (console.y >= 0) &&
+            (console.x <= console.win->_maxx) &&
+            (console.y <= console.win->_maxy) ) {
+
+           wmove(console.win, console.y, console.x);
+
+       }
+
+       wrefresh(console.win);
+    } else {
+       fflush(stdout);
+    }
+}
+
+
+int handle_console_msg(int cons_fd) {
+    int ret = 0;
+    struct cons_msg msg;
+
+    ret = read(cons_fd, &msg, sizeof(struct cons_msg));
+
+    switch (msg.op) {
+       case CONSOLE_CURS_SET:
+           //      printf("Console cursor set (x=%d, y=%d)\n", msg.cursor.x, msg.cursor.y);
+           handle_curs_set(&(msg.cursor));
+           break;
+       case CONSOLE_CHAR_SET:
+           handle_char_set(&(msg.character));
+           /*      printf("Console character set (x=%d, y=%d, c=%c, style=%c)\n", 
+             msg.character.x, msg.character.y, msg.character.c, msg.character.style);*/
+           break;
+       case CONSOLE_SCROLL:
+           //  printf("Console scroll (lines=%d)\n", msg.scroll.lines);
+           handle_scroll(&(msg.scroll));
+           break;
+       case CONSOLE_UPDATE:
+           // printf("Console update\n");
+           handle_update();
+           break;
+       case CONSOLE_RESOLUTION:
+           handle_text_resolution(&(msg.resolution));
+           break;
+       default:
+           printf("Invalid console message operation (%d)\n", msg.op);
+           break;
+    }
+
+    return 0;
+}
+
+
+int send_key(int cons_fd, char scan_code) {
+
+    return 0;
+}
+
+
+
+void handle_exit(void) {
+    fprintf(stderr, "Exiting from console terminal\n");
+
+    if (use_curses) {
+       endwin();
+    }
+
+    //    tcsetattr(STDIN_FILENO, TCSANOW, &console.termios_old);
+
+    // ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE);
+}
+
+
+#define NO_KEY { 0, 0 }
+
+struct key_code {
+    unsigned char scan_code;
+    unsigned char capital;
+};
+
+static const struct key_code ascii_to_key_code[] = {             // ASCII Value Serves as Index
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x00 - 0x03
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x04 - 0x07
+    { 0x0E, 0 },    { 0x0F, 0 },    { 0x1C, 0 },    NO_KEY,      // 0x08 - 0x0B
+    NO_KEY,         { 0x1C, 0 },    NO_KEY,         NO_KEY,      // 0x0C - 0x0F
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x10 - 0x13
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x14 - 0x17
+    NO_KEY,         NO_KEY,         NO_KEY,         { 0x01, 0 }, // 0x18 - 0x1B
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x1C - 0x1F
+    { 0x39, 0 },    { 0x02, 1 },    { 0x28, 1 },    { 0x04, 1 }, // 0x20 - 0x23
+    { 0x05, 1 },    { 0x06, 1 },    { 0x08, 1 },    { 0x28, 0 }, // 0x24 - 0x27
+    { 0x0A, 1 },    { 0x0B, 1 },    { 0x09, 1 },    { 0x0D, 1 }, // 0x28 - 0x2B
+    { 0x33, 0 },    { 0x0C, 0 },    { 0x34, 0 },    { 0x35, 0 }, // 0x2C - 0x2F
+    { 0x0B, 0 },    { 0x02, 0 },    { 0x03, 0 },    { 0x04, 0 }, // 0x30 - 0x33
+    { 0x05, 0 },    { 0x06, 0 },    { 0x07, 0 },    { 0x08, 0 }, // 0x34 - 0x37
+    { 0x09, 0 },    { 0x0A, 0 },    { 0x27, 1 },    { 0x27, 0 }, // 0x38 - 0x3B
+    { 0x33, 1 },    { 0x0D, 0 },    { 0x34, 1 },    { 0x35, 1 }, // 0x3C - 0x3F
+    { 0x03, 1 },    { 0x1E, 1 },    { 0x30, 1 },    { 0x2E, 1 }, // 0x40 - 0x43
+    { 0x20, 1 },    { 0x12, 1 },    { 0x21, 1 },    { 0x22, 1 }, // 0x44 - 0x47
+    { 0x23, 1 },    { 0x17, 1 },    { 0x24, 1 },    { 0x25, 1 }, // 0x48 - 0x4B
+    { 0x26, 1 },    { 0x32, 1 },    { 0x31, 1 },    { 0x18, 1 }, // 0x4C - 0x4F
+    { 0x19, 1 },    { 0x10, 1 },    { 0x13, 1 },    { 0x1F, 1 }, // 0x50 - 0x53
+    { 0x14, 1 },    { 0x16, 1 },    { 0x2F, 1 },    { 0x11, 1 }, // 0x54 - 0x57
+    { 0x2D, 1 },    { 0x15, 1 },    { 0x2C, 1 },    { 0x1A, 0 }, // 0x58 - 0x5B
+    { 0x2B, 0 },    { 0x1B, 0 },    { 0x07, 1 },    { 0x0C, 1 }, // 0x5C - 0x5F
+    { 0x29, 0 },    { 0x1E, 0 },    { 0x30, 0 },    { 0x2E, 0 }, // 0x60 - 0x63
+    { 0x20, 0 },    { 0x12, 0 },    { 0x21, 0 },    { 0x22, 0 }, // 0x64 - 0x67
+    { 0x23, 0 },    { 0x17, 0 },    { 0x24, 0 },    { 0x25, 0 }, // 0x68 - 0x6B
+    { 0x26, 0 },    { 0x32, 0 },    { 0x31, 0 },    { 0x18, 0 }, // 0x6C - 0x6F
+    { 0x19, 0 },    { 0x10, 0 },    { 0x13, 0 },    { 0x1F, 0 }, // 0x70 - 0x73
+    { 0x14, 0 },    { 0x16, 0 },    { 0x2F, 0 },    { 0x11, 0 }, // 0x74 - 0x77
+    { 0x2D, 0 },    { 0x15, 0 },    { 0x2C, 0 },    { 0x1A, 1 }, // 0x78 - 0x7B
+    { 0x2B, 1 },    { 0x1B, 1 },    { 0x29, 1 },    { 0x0E, 0 }  // 0x7C - 0x7F
+};
+
+
+
+#define writeit(fd,c)  do { fprintf(stderr,"scancode 0x%x\n",(c)); if (write((fd),&(c),1)!=1) { return -1; } } while (0)
+
+int send_char_to_palacios_as_scancodes(int fd, unsigned char c)
+{
+    unsigned char sc;
+
+    fprintf(stderr,"key '%c'\n",c);
+
+    if (c<0x80) { 
+       struct key_code k = ascii_to_key_code[c];
+       
+       if (k.scan_code==0 && k.capital==0) { 
+           fprintf(stderr,"Cannot send key '%c' to palacios as it maps to no scancode\n",c);
+       } else {
+           if (k.capital) { 
+               //shift down
+               sc = 0x2a ; // left shift down
+               writeit(fd,sc);
+           }
+           
+           
+           sc = k.scan_code;
+           
+           writeit(fd,sc);  // key down
+           
+           sc |= 0x80;      // key up
+           
+           writeit(fd,sc);
+           
+           if (k.capital) { 
+               sc = 0x2a | 0x80;
+               writeit(fd,sc);
+           }
+       }
+           
+    } else {
+
+
+       fprintf(stderr,"Cannot send key '%c' to palacios because it is >=0x80\n",c);
+
+/*     switch (key) {  */
+/*         case 0xffe1:  //left shift */
+/*             scancode = 0x2a; */
+/*             break; */
+
+/*         case 0xffe2:  //right shift */
+/*             scancode = 0x36; */
+/*             break; */
+
+/*         case 0xffe3:  //left ctrl */
+/*         case 0xffe4:  //right ctrl */
+/*             scancode = 0x1d;   // translated as left ctrl */
+/*             break; */
+
+/*         case 0xffe7:  //left meta */
+/*         case 0xffe8:  //right meta */
+/*         case 0xffe9:  //left alt */
+/*         case 0xffea:  //right alt */
+/*             scancode = 0x38;  // translated as a left alt */
+/*             break;  */
+
+/*         case 0xff08: // backspace */
+/*             scancode = 0x0e; */
+/*             break;  */
+
+/*         case 0xff09: // tab */
+/*             scancode = 0x0f;   */
+/*             break;  */
+
+/*         case 0xff0d: // return */
+/*             scancode = 0x1c; */
+/*             break;  */
+
+/*         case 0xff1b: // escape */
+/*             scancode = 0x01; */
+/*             break;  */
+
+/*         case 0xff63: // insert */
+/*             scancode = 0x52; */
+/*             break;  */
+
+/*         case 0xffff: // delete */
+/*             scancode = 0x53; */
+/*             break;  */
+
+/*         case 0xff50: // home */
+/*             scancode = 0x47; */
+/*             break;  */
+
+/*         case 0xff57: // end */
+/*             scancode = 0x4f; */
+/*             break;  */
+               
+/*         case 0xff55: // pageup */
+/*             scancode = 0x49; */
+/*             break;  */
+
+/*         case 0xff56: // pagedown */
+/*             scancode = 0x51; */
+/*             break;  */
+
+/*         case 0xff51: // left */
+/*             scancode = 0x4b; */
+/*             break;  */
+
+/*         case 0xff52: // up */
+/*             scancode = 0x48; */
+/*             break;  */
+
+/*         case 0xff53: // right */
+/*             scancode = 0x4d; */
+/*             break;  */
+
+/*         case 0xff54: // down */
+/*             scancode = 0x50; */
+/*             break;  */
+
+/*         case 0xffbe: // f1 */
+/*             scancode = 0x3b; */
+/*             break;  */
+/*         case 0xffbf: // f2 */
+/*             scancode = 0x3c; */
+/*             break;  */
+/*         case 0xffc0: // f3 */
+/*             scancode = 0x3d; */
+/*             break;  */
+/*         case 0xffc1: // f4 */
+/*             scancode = 0x3e; */
+/*             break;  */
+/*         case 0xffc2: // f5 */
+/*             scancode = 0x3f; */
+/*             break;  */
+/*         case 0xffc3: // f6 */
+/*             scancode = 0x40; */
+/*             break;  */
+/*         case 0xffc4: // f7 */
+/*             scancode = 0x41; */
+/*             break;  */
+/*         case 0xffc5: // f8 */
+/*             scancode = 0x42; */
+/*             break;  */
+/*         case 0xffc6: // f9 */
+/*             scancode = 0x43; */
+/*             break; */
+/*         case 0xffc7: // f10 */
+/*             scancode = 0x44; */
+/*             break;  */
+/*         case 0xffc8: // f11 */
+/*             scancode = 0x57; */
+/*             break;  */
+/*         case 0xffc9: // f12 */
+/*             scancode = 0x58; */
+/*             break;  */
+
+
+/*         default: */
+/*             scancode = 0; */
+/*             fprintf(stderr,"Ignoring key 0x%x (down=%d)\n", key, down); */
+/*     } */
+/*     } */
+    
+/*     if (scancode==0) {  */
+/*     return 0; */
+/*     } */
+       
+       
+/*     return scancode; */
+       
+    }
+    return 0;
+}
+    
+int main(int argc, char* argv[]) {
+    int vm_fd;
+    int cons_fd;
+    char * vm_dev = NULL;
+    struct termios termios;
+
+    use_curses = 1;
+
+    if (argc < 2) {
+       printf("Usage: ./v3_cons <vm_device>\n");
+       return -1;
+    }
+
+    vm_dev = argv[1];
+
+
+
+    vm_fd = open(vm_dev, O_RDONLY);
+
+    if (vm_fd == -1) {
+       printf("Error opening VM device: %s\n", vm_dev);
+       return -1;
+    }
+
+    cons_fd = ioctl(vm_fd, V3_VM_CONSOLE_CONNECT, NULL); 
+
+    /* Close the file descriptor.  */ 
+    close(vm_fd); 
+
+    if (cons_fd < 0) {
+       printf("Error opening stream Console\n");
+       return -1;
+    }
+
+    tcgetattr(STDIN_FILENO, &console.termios_old);
+    atexit(handle_exit);
+
+    console.x = 0;
+    console.y = 0;
+
+
+    if (use_curses) {
+       gettmode();
+       console.win = initscr();
+       
+       if (console.win == NULL) {
+           fprintf(stderr, "Error initialization curses screen\n");
+           exit(-1);
+       }
+
+       scrollok(console.win, 1);
+    }
+
+    /*
+    termios = console.termios_old;
+    termios.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR);
+    termios.c_iflag &= ~(INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK); 
+    //termios.c_iflag &= ~(ICRNL | INLCR );    
+
+    //  termios.c_iflag |= SCANCODES; 
+    //    termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 
+    //termios.c_lflag &= ~(ICANON | IEXTEN | ISIG | NOFLSH);
+    termios.c_lflag &= ~(ICANON | ECHO);
+
+    termios.c_cc[VMIN] = 1;
+    termios.c_cc[VTIME] = 0;
+
+    tcflush(STDIN_FILENO, TCIFLUSH);
+    tcsetattr(STDIN_FILENO, TCSANOW, &termios);
+    */    
+
+    raw();
+    cbreak();
+    noecho();
+    keypad(console.win, TRUE);
+
+    //ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
+
+    while (1) {
+       int ret; 
+       int bytes_read = 0;
+       fd_set rset;
+
+       FD_ZERO(&rset);
+       FD_SET(cons_fd, &rset);
+       FD_SET(STDIN_FILENO, &rset);
+
+       ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
+       
+       //      printf("Returned from select...\n");
+
+       if (ret == 0) {
+           continue;
+       } else if (ret == -1) {
+           perror("Select returned error...\n");
+           return -1;
+       }
+
+       if (FD_ISSET(cons_fd, &rset)) {
+           if (handle_console_msg(cons_fd) == -1) {
+               printf("Console Error\n");
+               return -1;
+           }
+       }
+
+       if (FD_ISSET(STDIN_FILENO, &rset)) {
+           unsigned char key = getch();
+
+           if (key == '\\') { // ESC
+               break;
+           } else if (key == '`') {
+               unsigned char sc = 0x44; // F10
+               writeit(cons_fd,sc);
+               sc |= 0x80;
+               writeit(cons_fd,sc);
+            }else {
+               if (send_char_to_palacios_as_scancodes(cons_fd,key)) {
+                   fprintf(stderr, "Error sendign key to console\n");
+                   return -1;
+               }
+           }
+           
+       }
+    } 
+
+    close(cons_fd);
+
+    return 0; 
+}
+
+
diff --git a/linux_usr/v3_inject_ecc_scrubber_mce.c b/linux_usr/v3_inject_ecc_scrubber_mce.c
new file mode 100644 (file)
index 0000000..ec98ba8
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * V3 ECC DRAM Scrubber MCE
+ * (c) Philip Soltero, 2010
+ */
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#define V3_VM_INJECT_SCRUBBER_MCE (10224+20)
+
+int main(int argc, char * argv[]) {
+    char * end_ptr;
+    char * vm_device;
+    unsigned int cpu;
+    uint64_t address;
+    int v3_fd = 0;
+
+    if (argc <= 3) {
+        fprintf(stderr, "Usage: v3_inject_ecc_scrubber_mce <vm_device> <cpu> <hex address>\n");
+        return -1;
+    }
+
+    vm_device = argv[1];
+
+    cpu = strtol(argv[2], &end_ptr, 10);
+    if (strcmp(end_ptr, "\0") != 0) {
+        fprintf(stderr, "The specified cpu is not a valid integer '%s', in particular '%s'.\n", argv[2], end_ptr);
+        return -1;
+    }
+
+    address = strtoll(argv[3], &end_ptr, 16);
+    if (strcmp(end_ptr, "\0") != 0) {
+        fprintf(stderr, "The specified address is not a valid integer '%s', in particular '%s'.\n", argv[3], end_ptr);
+        return -1;
+    }
+
+    v3_fd = open(vm_device, O_RDONLY);
+
+    if (v3_fd == -1) {
+        fprintf(stderr, "Error opening V3Vee control device.\n");
+        return -1;
+    }
+
+    ioctl(v3_fd, V3_VM_INJECT_SCRUBBER_MCE, address);
+
+    /* Close the file descriptor.  */
+    close(v3_fd);
+
+    return 0;
+}
index e51ef18..b02cdeb 100644 (file)
@@ -48,7 +48,7 @@ int main(int argc, char * argv[]) {
     unsigned char * bitmap = NULL;
     int num_blocks = 0;    
     int reg_start = 0;
-
+    int mem_ready = 0;
 
     if (argc != 2) {
        printf("Usage: v3_mem <memory size (MB)>\n");
@@ -146,71 +146,155 @@ int main(int argc, char * argv[]) {
 
     }
     
+    while (!mem_ready) {
 
-    /* Scan bitmap for enough consecutive space */
-    {
-       // num_blocks: The number of blocks we need to find
-       // bitmap: bitmap of blocks (1 == allocatable)
-       // bitmap_entries: number of blocks in the system/number of bits in bitmap
-       // reg_start: The block index where our allocation will start
 
-       int i = 0;
-       int run_len = 0;
+       /* Scan bitmap for enough consecutive space */
+       {
+           // num_blocks: The number of blocks we need to find
+           // bitmap: bitmap of blocks (1 == allocatable)
+           // bitmap_entries: number of blocks in the system/number of bits in bitmap
+           // reg_start: The block index where our allocation will start
+           
+           int i = 0;
+           int run_len = 0;
+           
+           for (i = 0; i < bitmap_entries; i++) {
+               int i_major = i / 8;
+               int i_minor = i % 8;
+               
+               
+               if (!(bitmap[i_major] & (0x1 << i_minor))) {
+                   reg_start = i + 1; // skip the region start to next entry
+                   run_len = 0;
+                   continue;
+               }
+               
+               run_len++;
+
+               if (run_len >= num_blocks) {
+                   break;
+               }
+           }
 
-       for (i = 0; i < bitmap_entries; i++) {
-           int i_major = i / 8;
-           int i_minor = i % 8;
+       
+           if (run_len < num_blocks) {
+               fprintf(stderr, "Could not find enough consecutive memory blocks... (found %d)\n", run_len);
+               return -1;
+           }
+       }
+    
 
+       /* Offline memory blocks starting at reg_start */
+       {
+           int i = 0;
 
-           if (!(bitmap[i_major] & (0x1 << i_minor))) {
-               reg_start = i + 1; // skip the region start to next entry
-               run_len = 0;
-               continue;
-           }
+           for (i = 0; i < num_blocks; i++) {  
+               FILE * block_file = NULL;
+               char fname[256];
+
+               memset(fname, 0, 256);
+
+               snprintf(fname, 256, "%smemory%d/state", SYS_PATH, i + reg_start);
+           
+               block_file = fopen(fname, "r+");
+
+               if (block_file == NULL) {
+                   perror("Could not open block file");
+                   return -1;
+               }
 
-           run_len++;
 
-           if (run_len >= num_blocks) {
-               break;
+               printf("Offlining block %d (%s)\n", i + reg_start, fname);
+               fprintf(block_file, "offline\n");
+
+               fclose(block_file);
            }
        }
 
-       free(bitmap);
-       
-       if (run_len < num_blocks) {
-           fprintf(stderr, "Could not find enough consecutive memory blocks... (found %d)\n", run_len);
-           return -1;
-       }
-    }
-    
 
-    /* Offline memory blocks starting at reg_start */
-    {
-       int i = 0;
+       /*  We asked to offline set of blocks, but Linux could have lied. 
+        *  To be safe, check whether blocks were offlined and start again if not 
+        */
 
-       for (i = 0; i < num_blocks; i++) {      
-           FILE * block_file = NULL;
-           char fname[256];
+       {
+           int i = 0;
 
-           memset(fname, 0, 256);
+           mem_ready = 1; // Hopefully we are ok...
 
-           snprintf(fname, 256, "%smemory%d/state", SYS_PATH, i + reg_start);
-           
-           block_file = fopen(fname, "r+");
 
-           if (block_file == NULL) {
-               perror("Could not open block file");
-               return -1;
-           }
+           for (i = 0; i < num_blocks; i++) {
+               int block_fd = NULL;
+               char fname[BUF_SIZE];
+               char status_buf[BUF_SIZE];
+
 
+               memset(fname, 0, BUF_SIZE);
+               memset(status_buf, 0, BUF_SIZE);
 
-           printf("Offlining block %d (%s)\n", i + reg_start, fname);
-           fprintf(block_file, "offline\n");
+               snprintf(fname, BUF_SIZE, "%smemory%d/state", SYS_PATH, i + reg_start);
 
-           fclose(block_file);
+       
+               block_fd = open(fname, O_RDONLY);
+               
+               if (block_fd == -1) {
+                   perror("Could not open block file");
+                   return -1;
+               }
+                   
+               if (read(block_fd, status_buf, BUF_SIZE) <= 0) {
+                   perror("Could not read block status");
+                   return -1;
+               }
+
+               printf("Checking offlined block %d (%s)...", i + reg_start, fname);
+
+               int ret = strncmp(status_buf, "offline", strlen("offline"));
+
+               if (ret != 0) {
+                   int j = 0;
+                   int major = (i + reg_start) / 8;
+                   int minor = (i + reg_start) % 8;
+
+                   bitmap[major] &= ~(0x1 << minor); // mark the block as not removable in bitmap
+
+                   mem_ready = 0; // Keep searching
+
+                   printf("ERROR (%d)\n", ret);
+
+                   for (j = 0; j < i; j++) {
+                       FILE * block_file = NULL;
+                       char fname[256];
+                       
+                       memset(fname, 0, 256);
+                       
+                       snprintf(fname, 256, "%smemory%d/state", SYS_PATH, j + reg_start);
+                       
+                       block_file = fopen(fname, "r+");
+                       
+                       if (block_file == NULL) {
+                           perror("Could not open block file");
+                           return -1;
+                       }
+
+                       fprintf(block_file, "online\n");
+                       
+                       fclose(block_file);
+                   }
+                      
+
+                   break;
+               } 
+               
+               printf("OK\n");
+               
+           }
+           
+           
        }
     }
 
+    free(bitmap);
 
     /* Memory is offlined. Calculate size and phys start addr to send to Palacios */
 
diff --git a/linux_usr/v3_net.c b/linux_usr/v3_net.c
deleted file mode 100644 (file)
index 5449cd4..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 
- * V3 Control utility for Palacios network services
- * (c) Lei Xia, 2010
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h> 
-#include <sys/ioctl.h> 
-#include <sys/stat.h> 
-#include <sys/types.h> 
-#include <unistd.h> 
-#include <string.h>
-#include "v3_ctrl.h"
-
-struct v3_network {
-    unsigned char socket;
-    unsigned char packet;
-    unsigned char vnet;
-};
-
-int main(int argc, char* argv[]) {
-    int v3_fd = 0;
-    struct v3_network net;
-    int i;
-
-    if (argc <= 1) {
-       printf("Usage: ./v3_mem [socket] [packet] [vnet]\n");
-       return -1;
-    }
-
-    for (i = 1; i < argc; i++){
-       if(!strcasecmp (argv[i], "packet")){
-           net.packet = 1;
-       }else if(!strcasecmp (argv[i], "socket")){
-           net.socket = 1;
-       }else if(!strcasecmp (argv[i], "vnet")){
-           net.vnet = 1;
-       }else {
-           printf("unknown v3 network service: %s, ignored\n", argv[i]);
-       }
-    }
-
-    printf("Network service: socket: %d, packet: %d, vnet: %d\n", net.socket, net.packet, net.vnet);
-
-    v3_fd = open(v3_dev, O_RDONLY);
-
-    if (v3_fd == -1) {
-       printf("Error opening V3Vee control device\n");
-       return -1;
-    }
-
-    ioctl(v3_fd, V3_START_NETWORK, &net); 
-
-
-    /* Close the file descriptor.  */ 
-    close(v3_fd); 
-
-    return 0; 
-} 
-
diff --git a/linux_usr/v3_serial.c b/linux_usr/v3_serial.c
deleted file mode 100644 (file)
index 2f66c7f..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/* 
- * V3 Console utility
- * (c) Jack lange & Lei Xia, 2010
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h> 
-#include <sys/ioctl.h> 
-#include <sys/stat.h> 
-#include <sys/types.h> 
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <errno.h>
-#include<linux/unistd.h>
-#include <curses.h>
-
-
-#include "v3_ctrl.h"
-
-static int cons_fd = -1;
-static pthread_t input_handler;
-
-void *write_handler(void *val){
-    char read;
-    printf("Write handler active\n");
-    fflush(stdout);
-    while(1){
-       read = getchar();
-       if(write(cons_fd, &read, sizeof(char)) < 0){
-           printf("WRITE ERROR");
-       }
-    }
-}
-
-
-int main(int argc, char* argv[]) {
-    int vm_fd;
-    fd_set rset;
-    char *vm_dev = NULL;
-    char *stream; 
-
-    if (argc < 2) {
-       printf("Usage: ./v3_cons vm_device serial_number\n");
-       return -1;
-    }
-
-    vm_dev = argv[1];
-    stream = argv[2];
-
-    vm_fd = open(vm_dev, O_RDONLY);
-    if (vm_fd == -1) {
-       printf("Error opening VM device: %s\n", vm_dev);
-       return -1;
-    }
-
-    cons_fd = ioctl(vm_fd, V3_VM_SERIAL_CONNECT, stream); 
-
-    /* Close the file descriptor.  */ 
-    close(vm_fd); 
-    if (cons_fd < 0) {
-       printf("Error opening stream Console\n");
-       return -1;
-    }
-
-
-    if(pthread_create(&input_handler,0,write_handler,0)){
-       perror("pthread_create");
-       exit(-1);
-    }
-
-
-    while (1) {
-       int ret; 
-       char cons_buf[1024];
-       memset(cons_buf, 0, sizeof(cons_buf));
-       int bytes_read = 0;
-
-       FD_ZERO(&rset);
-       FD_SET(cons_fd, &rset);
-       
-       ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
-       
-       if (ret == 1) {
-           bytes_read = read(cons_fd, cons_buf, 1024);
-           cons_buf[bytes_read]='\0';
-           printf("%s", cons_buf);
-       } else {
-           printf("v3_cons ERROR: select returned %d\n", ret);
-           return -1;
-       }
-    } 
-
-
-    return 0; 
-}
-
-
diff --git a/linux_usr/v3_stream.c b/linux_usr/v3_stream.c
new file mode 100644 (file)
index 0000000..0a1f46a
--- /dev/null
@@ -0,0 +1,113 @@
+/* 
+ * V3 Console utility
+ * (c) Jack lange & Lei Xia, 2010
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h> 
+#include <sys/ioctl.h> 
+#include <sys/stat.h> 
+#include <sys/types.h> 
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <errno.h>
+#include<linux/unistd.h>
+#include <curses.h>
+
+
+#include "v3_ctrl.h"
+
+#define BUF_LEN 1025
+#define STREAM_NAME_LEN 128
+
+int main(int argc, char* argv[]) {
+    int vm_fd;
+    fd_set rset;
+    char * vm_dev = NULL;
+    char stream[STREAM_NAME_LEN];
+    char cons_buf[BUF_LEN];
+    int stream_fd = 0;
+
+    if (argc < 2) {
+       printf("Usage: ./v3_cons vm_device serial_number\n");
+       return -1;
+    }
+
+    vm_dev = argv[1];
+
+    if (strlen(argv[2]) >= STREAM_NAME_LEN) {
+       printf("ERROR: Stream name longer than maximum size (%d)\n", STREAM_NAME_LEN);
+       return -1;
+    }
+
+    memcpy(stream, argv[2], strlen(argv[2]));
+
+    vm_fd = open(vm_dev, O_RDONLY);
+    if (vm_fd == -1) {
+       printf("Error opening VM device: %s\n", vm_dev);
+       return -1;
+    }
+
+    stream_fd = ioctl(vm_fd, V3_VM_SERIAL_CONNECT, stream); 
+
+    /* Close the file descriptor.  */ 
+    close(vm_fd);
+    if (stream_fd < 0) {
+       printf("Error opening stream Console\n");
+       return -1;
+    }
+
+    while (1) {
+       int ret; 
+       int bytes_read = 0;
+       char in_buf[512];
+
+       memset(cons_buf, 0, BUF_LEN);
+
+
+       FD_ZERO(&rset);
+       FD_SET(stream_fd, &rset);
+       FD_SET(STDIN_FILENO, &rset);
+
+       ret = select(stream_fd + 1, &rset, NULL, NULL, NULL);
+       
+       if (ret == 0) {
+           continue;
+       } else if (ret == -1) {
+           perror("Select returned error\n");
+           return -1;
+       }
+
+       if (FD_ISSET(stream_fd, &rset)) {
+
+           bytes_read = read(stream_fd, cons_buf, BUF_LEN - 1);
+
+           cons_buf[bytes_read]='\0';
+           printf("%s", cons_buf);
+           fflush(stdout);
+
+       } else if (FD_ISSET(STDIN_FILENO, &rset)) {
+           fgets(in_buf, 512, stdin);
+
+           if (write(stream_fd, in_buf, strlen(in_buf)) != strlen(in_buf)) {
+               fprintf(stderr, "Error sending input bufer\n");
+               return -1;
+           }
+       } else {
+           printf("v3_cons ERROR: select returned %d\n", ret);
+           return -1;
+       }
+       
+
+    } 
+
+
+    return 0; 
+}
+
+
index 5379479..e48df2c 100644 (file)
 
 #define VIRTIO_NET_SUBDEVICE_ID 1
 #define VIRTIO_BLOCK_SUBDEVICE_ID 2
+#define VIRTIO_CONSOLE_SUBDEVICE_ID 3
 #define VIRTIO_BALLOON_SUBDEVICE_ID 5
 #define VIRTIO_SYMBIOTIC_SUBDEVICE_ID 10
 #define VIRTIO_SYMMOD_SUBDEVICE_ID 11
 #define VIRTIO_VNET_SUBDEVICE_ID 12
 
+
 #define HOST_FEATURES_PORT 0
 #define GUEST_FEATURES_PORT 4
 #define VRING_PG_NUM_PORT 8
index 513cf73..e9c49c7 100644 (file)
 
 
 
+struct v3_stream {
+    void * host_stream_data;
+    void * guest_stream_data;
+    uint64_t (*input)(struct v3_stream * stream, uint8_t * buf, uint64_t len);
+};
+
+
 #ifdef __V3VEE__
 #include <palacios/vmm.h>
 
-typedef void * v3_stream_t;
+
 
 /* VM Can be NULL */
-v3_stream_t v3_stream_open(struct v3_vm_info * vm, const char * name);
-int v3_stream_write(v3_stream_t stream, uint8_t * buf, uint32_t len);
+struct v3_stream * v3_stream_open(struct v3_vm_info * vm, const char * name,
+                                 uint64_t (*input)(struct v3_stream * stream, uint8_t * buf, uint64_t len),
+                                 void * guest_stream_data);
+
+uint64_t  v3_stream_output(struct v3_stream * stream, uint8_t * buf, uint32_t len);
 
-void v3_stream_close(v3_stream_t stream);
+void v3_stream_close(struct v3_stream * stream);
 
 #endif
 
 
 struct v3_stream_hooks {
-    void *(*open)(const char * name, void * private_data);
-    int (*write)(void * stream, char * buf, int len);
-    void (*close)(void * stream);
+    void *(*open)(struct v3_stream * stream, const char * name, void * host_vm_data);
+    uint64_t (*output)(struct v3_stream * stream, char * buf, int len);
+    void (*close)(struct v3_stream * stream);
 };
 
 
index 4360a64..51ca2de 100644 (file)
@@ -37,7 +37,7 @@
 #include <palacios/vmm_cpuid.h>
 #include <palacios/vmm_regs.h>
 #include <palacios/vmm_extensions.h>
-
+#include <palacios/vmm_barrier.h>
 
 
 #ifdef V3_CONFIG_TELEMETRY
@@ -170,7 +170,7 @@ struct v3_vm_info {
 
     v3_vm_operating_mode_t run_state;
 
-
+    struct v3_barrier barrier;
 
 
     struct v3_extensions extensions;
index 337226f..4c95f2c 100644 (file)
@@ -190,7 +190,7 @@ struct guest_info;
        if ((os_hooks) && (os_hooks)->start_kernel_thread) {            \
            (os_hooks)->start_kernel_thread(fn, arg, name);             \
        }                                                               \
-    }
+    } while (0)
 
 
 
@@ -331,6 +331,10 @@ void Shutdown_V3( void );
 struct v3_vm_info * v3_create_vm(void * cfg, void * priv_data, char * name);
 int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask);
 int v3_stop_vm(struct v3_vm_info * vm);
+int v3_pause_vm(struct v3_vm_info * vm);
+int v3_continue_vm(struct v3_vm_info * vm);
+
+
 int v3_free_vm(struct v3_vm_info * vm);
 
 int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr);
index d4b7eda..19f54fc 100644 (file)
 
 #ifdef __V3VEE__
 
+#include <palacios/vmm_lock.h>
+#include <palacios/vmm_bitmap.h>
+
 
-#include <util/vmm_lock.h>
 
 struct v3_barrier {
-    uint64_t cpus;
     int active;     // If 1, barrier is active, everyone must wait 
                     // If 0, barrier is clear, can proceed
 
+    struct v3_bitmap cpu_map;
+
     v3_lock_t lock;
 };
 
+struct v3_vm_info;
+struct guest_info;
+
+int v3_init_barrier(struct v3_vm_info * vm_info);
+int v3_deinit_barrier(struct v3_vm_info * vm_info);
 
-int v3_init_barrier(struct v3_barrier * barrier);
+int v3_raise_barrier(struct v3_vm_info * vm_info, struct guest_info * local_core);
+int v3_lower_barrier(struct v3_vm_info * vm_info);
 
-int v3_activate_barrier(struct guest_info * core);
-int v3_check_barrier(struct guest_info * core);
+int v3_wait_at_barrier(struct guest_info * core);
 
 
 #endif
diff --git a/palacios/include/palacios/vmm_bitmap.h b/palacios/include/palacios/vmm_bitmap.h
new file mode 100644 (file)
index 0000000..4842585
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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) 2011, Jack Lange <jacklange@cs.pitt.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jacklange@cs.pitt.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+
+#ifndef __VMM_BITMAP_H__
+#define __VMM_BITMAP_H__
+
+#ifdef __V3VEE__
+#include <palacios/vmm_types.h>
+
+
+
+struct v3_bitmap {
+    int num_bits;      // number of valid bit positions in the bitmap
+    uint8_t * bits;   // actual bitmap. Dynamically allocated... ugly
+};
+
+
+int v3_bitmap_init(struct v3_bitmap * bitmap, int num_bits);
+void v3_bitmap_deinit(struct v3_bitmap * bitmap);
+int v3_bitmap_reset(struct v3_bitmap * bitmap);
+
+int v3_bitmap_set(struct v3_bitmap * bitmap, int index);
+int v3_bitmap_clear(struct v3_bitmap * bitmap, int index);
+int v3_bitmap_check(struct v3_bitmap * bitmap, int index);
+
+
+
+#endif
+
+#endif
index 7f33fde..767fe25 100644 (file)
@@ -52,29 +52,31 @@ struct x86_prefixes {
        uint32_t val;
        
        struct {
-           uint_t lock   : 1;  // 0xF0
-           uint_t repne  : 1;  // 0xF2
-           uint_t repnz  : 1;  // 0xF2
-           uint_t rep    : 1;  // 0xF3
-           uint_t repe   : 1;  // 0xF3
-           uint_t repz   : 1;  // 0xF3
-           uint_t cs_override : 1;  // 0x2E
-           uint_t ss_override : 1;  // 0x36
-           uint_t ds_override : 1;  // 0x3E
-           uint_t es_override : 1;  // 0x26
-           uint_t fs_override : 1;  // 0x64
-           uint_t gs_override : 1;  // 0x65
-           uint_t br_not_taken : 1;  // 0x2E
-           uint_t br_taken   : 1;  // 0x3E
-           uint_t op_size     : 1;  // 0x66
-           uint_t addr_size   : 1;  // 0x67
-
-           uint_t rex   : 1;
+           uint32_t lock   : 1;  // 0xF0
+           uint32_t repne  : 1;  // 0xF2
+           uint32_t repnz  : 1;  // 0xF2
+           uint32_t rep    : 1;  // 0xF3
+           uint32_t repe   : 1;  // 0xF3
+           uint32_t repz   : 1;  // 0xF3
+           uint32_t cs_override : 1;  // 0x2E
+           uint32_t ss_override : 1;  // 0x36
+           uint32_t ds_override : 1;  // 0x3E
+           uint32_t es_override : 1;  // 0x26
+           uint32_t fs_override : 1;  // 0x64
+           uint32_t gs_override : 1;  // 0x65
+           uint32_t br_not_taken : 1;  // 0x2E
+           uint32_t br_taken   : 1;  // 0x3E
+           uint32_t op_size     : 1;  // 0x66
+           uint32_t addr_size   : 1;  // 0x67
+
+           uint32_t rex   : 1;
     
-           uint_t rex_rm        : 1;  // REX.B
-           uint_t rex_sib_idx   : 1;  // REX.X
-           uint_t rex_reg       : 1;  // REX.R
-           uint_t rex_op_size   : 1;  // REX.W
+           uint32_t rex_rm        : 1;  // REX.B
+           uint32_t rex_sib_idx   : 1;  // REX.X
+           uint32_t rex_reg       : 1;  // REX.R
+           uint32_t rex_op_size   : 1;  // REX.W
+
+           uint32_t rsvd          : 11;
        } __attribute__((packed));
     } __attribute__((packed));
 } __attribute__((packed));
index 87f62fc..1f10874 100644 (file)
@@ -177,16 +177,24 @@ struct v3_dev_blk_ops {
     int (*write)(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data);
 };
 
+
+struct v3_dev_net_ops_cfg{
+    void * frontend_data; 
+    char * fnt_mac;
+    int quote;
+    int poll;  /* need poll? */
+};
+
 struct v3_dev_net_ops {
     /* Backend implemented functions */
-    int (*send)(uint8_t * buf, uint32_t len, int synchronize, void * private_data);
+    int (*send)(uint8_t * buf, uint32_t len, void * private_data);
 
     /* Frontend implemented functions */
     int (*recv)(uint8_t * buf, uint32_t len, void * frnt_data);
+    int (*poll)(int quote, void * frnt_data);
 
     /* This is ugly... */
-    void * frontend_data; 
-    char fnt_mac[ETH_ALEN];
+    struct v3_dev_net_ops_cfg config;
 };
 
 struct v3_dev_console_ops {
@@ -202,11 +210,11 @@ struct v3_dev_console_ops {
 
 struct v3_dev_char_ops {
     /* Backend implemented functions */
-    int (*write)(uint8_t * buf, uint64_t len, void * private_data);
+    uint64_t (*output)(uint8_t * buf, uint64_t len, void * private_data);
     //  int (*read)(uint8_t * buf, uint64_t len, void * private_data);
 
     /* Frontend Implemented functions */
-    int (*push)(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * private_data);
+    uint64_t (*input)(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * private_data);
 };
 
 
index 7559f05..cbccaf1 100644 (file)
 
 #include <palacios/vmm_types.h>
 
+#define FLAGS_MASK 0x00000cff
+
 
 
 #define MAKE_1OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst,  addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint8_t tmp_dst = *(uint8_t *)dst;                              \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
                      "pushf; "                                         \
                      "pop %1; "                                        \
                      "popf; "                                          \
-                     : "=q"(*(uint8_t *)dst),"=q"(*flags)              \
-                     : "q"(*flags), "0"(*(uint8_t *)dst)               \
+                     : "=&q"(tmp_dst),"=q"(guest_flags)                \
+                     : "1"(guest_flags), "0"(tmp_dst)                  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
+       *(uint8_t *)dst = tmp_dst;                                      \
                                                                        \
     }
 
 #define MAKE_1OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst,  addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint16_t tmp_dst = *(uint16_t *)dst;                            \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
                      "pushf; "                                         \
                      "pop %1; "                                        \
                      "popf; "                                          \
-                     : "=q"(*(uint16_t *)dst),"=q"(*flags)             \
-                     : "q"(*flags), "0"(*(uint16_t *)dst)              \
+                     : "=&q"(tmp_dst),"=q"(guest_flags)                \
+                     : "1"(guest_flags), "0"(tmp_dst)                  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
-                                                                       \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
+       *(uint16_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_1OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst,  addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint32_t tmp_dst = *(uint32_t *)dst;                            \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
                      "pushf; "                                         \
                      "pop %1; "                                        \
                      "popf; "                                          \
-                     : "=q"(*(uint32_t *)dst),"=q"(*flags)             \
-                     : "q"(*flags), "0"(*(uint32_t *)dst)              \
+                     : "=&q"(tmp_dst),"=q"(guest_flags)                \
+                     : "1"(guest_flags), "0"(tmp_dst)                  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
                                                                        \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
+       *(uint32_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_1OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst,  addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint64_t tmp_dst = *(uint64_t *)dst;                            \
                                                                        \
        asm volatile (                                                  \
                      "pushfq; "                                        \
                      "pushfq; "                                        \
                      "pop %1; "                                        \
                      "popfq; "                                         \
-                     : "=q"(*(uint64_t *)dst),"=q"(*flags)             \
-                     : "q"(*flags), "0"(*(uint64_t *)dst)              \
+                     : "=q"(tmp_dst),"=q"(guest_flags)                 \
+                     : "q"(guest_flags), "0"(tmp_dst)                  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
                                                                        \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
+       *(uint64_t *)dst = tmp_dst;                                     \
     }
 
 
 
 #define MAKE_1OP_8_INST(iname) static inline void iname##8(addr_t * dst) { \
+       uint8_t tmp_dst = *(uint8_t *)dst;                              \
        asm volatile (                                                  \
                      #iname"b %0; "                                    \
-                     : "=q"(*(uint8_t *)dst)                           \
-                     : "0"(*(uint8_t *)dst)                            \
+                     : "=q"(tmp_dst)                                   \
+                     : "0"(tmp_dst)                                    \
+                     : "memory"                                        \
                      );                                                \
+       *(uint8_t *)dst = tmp_dst;                                      \
     }
 
 #define MAKE_1OP_16_INST(iname) static inline void iname##16(addr_t * dst) { \
+       uint16_t tmp_dst = *(uint16_t *)dst;                            \
        asm volatile (                                                  \
                      #iname"w %0; "                                    \
-                     : "=q"(*(uint16_t *)dst)                          \
-                     :  "0"(*(uint16_t *)dst)                          \
+                     : "=q"(tmp_dst)                                   \
+                     :  "0"(tmp_dst)                                   \
+                     : "memory"                                        \
                      );                                                \
+       *(uint16_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_1OP_32_INST(iname) static inline void iname##32(addr_t * dst) { \
+       uint32_t tmp_dst = *(uint32_t *)dst;                            \
        asm volatile (                                                  \
                      #iname"l %0; "                                    \
-                     : "=q"(*(uint32_t *)dst)                          \
-                     : "0"(*(uint32_t *)dst)                           \
+                     : "=q"(tmp_dst)                                   \
+                     : "0"(tmp_dst)                                    \
+                     : "memory"                                        \
                      );                                                \
+       *(uint32_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_1OP_64_INST(iname) static inline void iname##64(addr_t * dst) { \
+       uint64_t tmp_dst = *(uint64_t *)dst;                            \
        asm volatile (                                                  \
                      #iname"q %0; "                                    \
-                     : "=q"(*(uint64_t *)dst)                          \
-                     : "0"(*(uint64_t *)dst)                           \
+                     : "=q"(tmp_dst)                                   \
+                     : "0"(tmp_dst)                                    \
+                     : "memory"                                        \
                      );                                                \
+       *(uint64_t *)dst = tmp_dst;                                     \
     }
 
 
 #define MAKE_2OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint64_t tmp_dst = *(uint64_t *)dst;                            \
                                                                        \
        asm volatile (                                                  \
                      "pushfq\r\n"                                      \
                      "pushfq\r\n"                                      \
                      "pop %1\r\n"                                      \
                      "popfq\r\n"                                       \
-                     : "=q"(*(uint64_t *)dst),"=q"(*flags)             \
-                     : "q"(*(uint64_t *)src),"q"(*flags), "0"(*(uint64_t *)dst) \
+                     : "=&q"(tmp_dst),"=q"(guest_flags)                        \
+                     : "q"(*(uint64_t *)src),"1"(guest_flags), "0"(tmp_dst) \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
-                                                                       \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
+       *(uint64_t *)dst = tmp_dst;                                     \
     }
 
 
 
 
 #define MAKE_2OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint32_t tmp_dst = *(uint32_t *)dst;                            \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
                      "pushf; "                                         \
                      "pop %1; "                                        \
                      "popf; "                                          \
-                     : "=q"(*(uint32_t *)dst),"=q"(*flags)             \
-                     : "q"(*(uint32_t *)src),"q"(*flags), "0"(*(uint32_t *)dst) \
+                     : "=&q"(tmp_dst),"=q"(guest_flags)                \
+                     : "q"(*(uint32_t *)src),"1"(guest_flags), "0"(tmp_dst) \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
+       *(uint32_t *)dst = tmp_dst;                                     \
     }
 
 
 #define MAKE_2OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint16_t tmp_dst = *(uint16_t *)dst;                            \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
                      "pushf; "                                         \
                      "pop %1; "                                        \
                      "popf; "                                          \
-                     : "=q"(*(uint16_t *)dst),"=q"(*flags)             \
-                     : "q"(*(uint16_t *)src),"q"(*flags), "0"(*(uint16_t *)dst) \
+                     : "=&q"(tmp_dst),"=q"(guest_flags)                \
+                     : "q"(*(uint16_t *)src),"1"(guest_flags), "0"(tmp_dst) \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
+       *(uint16_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_2OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint8_t tmp_dst = *(uint8_t *)dst;                              \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
                      "pushf; "                                         \
                      "pop %1; "                                        \
                      "popf; "                                          \
-                     : "=q"(*(uint8_t *)dst),"=q"(*flags)              \
-                     : "q"(*(uint8_t *)src),"q"(*flags), "0"(*(uint8_t *)dst) \
+                     : "=q"(tmp_dst),"=q"(guest_flags)                 \
+                     : "q"(*(uint8_t *)src),"1"(guest_flags), "0"(tmp_dst) \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
+       *(uint8_t *)dst = tmp_dst;                                      \
     }
 
 
 #define MAKE_2OP_64STR_INST(iname) static inline void iname##64(addr_t * dst, \
                                                                addr_t * src, \
                                                                addr_t * ecx, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint64_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0;                 \
                                                                        \
        asm volatile (                                                  \
                      "pushfq; "                                        \
-                     "pushq %4; "                                      \
+                     "pushq %7; "                                      \
                      "popfq; "                                         \
                      "rep; "                                           \
                      #iname"q; "                                       \
                      "pushfq; "                                        \
                      "popq %0; "                                       \
                      "popfq; "                                         \
-                     : "=q"(*flags)                                    \
-                     : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags)       \
+                     : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \
+                     : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags)  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
     }
 
 
 #define MAKE_2OP_32STR_INST(iname) static inline void iname##32(addr_t * dst, \
                                                                addr_t * src, \
                                                                addr_t * ecx, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint32_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0;                 \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
-                     "push %4; "                                       \
+                     "push %7; "                                       \
                      "popf; "                                          \
                      "rep; "                                           \
                      #iname"l; "                                       \
                      "pushf; "                                         \
                      "pop %0; "                                        \
                      "popf; "                                          \
-                     : "=q"(*flags)                                    \
-                     : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags)       \
+                     : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \
+                     : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags)  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
     }
 
 #define MAKE_2OP_16STR_INST(iname) static inline void iname##16(addr_t * dst, \
                                                                addr_t * src, \
                                                                addr_t * ecx, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint16_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0;                 \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
-                     "push %4; "                                       \
+                     "push %7; "                                       \
                      "popf; "                                          \
                      "rep; "                                           \
                      #iname"w; "                                       \
                      "pushf; "                                         \
                      "pop %0; "                                        \
                      "popf; "                                          \
-                     : "=q"(*flags)                                    \
-                     : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags)       \
+                     : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \
+                     : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags)  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
     }
 
 
 #define MAKE_2OP_8STR_INST(iname) static inline void iname##8(addr_t * dst, \
                                                              addr_t * src, \
                                                              addr_t * ecx, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint8_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0;                  \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
-                     "push %4; "                                       \
+                     "push %7; "                                       \
                      "popf; "                                          \
                      "rep; "                                           \
                      #iname"b; "                                       \
                      "pushf; "                                         \
                      "pop %0; "                                        \
                      "popf; "                                          \
-                     : "=q"(*flags)                                    \
-                     : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags)       \
+                     : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \
+                     : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags)  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
     }
 
 
 #define MAKE_1OP_64STR_INST(iname) static inline void iname##64(addr_t * dst, \
                                                                addr_t * src, \
                                                                addr_t * ecx, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint64_t tmp_dst = 0, tmp_ecx = 0;                              \
                                                                        \
        asm volatile (                                                  \
                      "pushfq; "                                        \
-                     "pushq %4; "                                      \
+                     "pushq %6; "                                      \
                      "popfq; "                                         \
                      "rep; "                                           \
                      #iname"q; "                                       \
                      "pushfq; "                                        \
                      "popq %0; "                                       \
                      "popfq; "                                         \
-                     : "=q"(*flags)                                    \
-                     : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags)       \
+                     : "=&q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \
+                     : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags)  \
+                     : "memory"                                        \
                      );                                                \
                                                                        \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
     }
 
 
 #define MAKE_1OP_32STR_INST(iname) static inline void iname##32(addr_t * dst, \
                                                                addr_t * src, \
                                                                addr_t * ecx, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint32_t tmp_dst = 0, tmp_ecx = 0;                              \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
-                     "push %4; "                                       \
+                     "push %6; "                                       \
                      "popf; "                                          \
                      "rep; "                                           \
                      #iname"l; "                                       \
                      "pushf; "                                         \
                      "pop %0; "                                        \
                      "popf; "                                          \
-                     : "=q"(*flags)                                    \
-                     : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags)       \
+                     : "=&q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \
+                     : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags)  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+                                                                       \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
     }
 
 #define MAKE_1OP_16STR_INST(iname) static inline void iname##16(addr_t * dst, \
                                                                addr_t * src, \
                                                                addr_t * ecx, addr_t * flags) { \
-       /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & FLAGS_MASK;                       \
+       uint16_t tmp_dst = 0, tmp_ecx = 0;                              \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
-                     "push %4; "                                       \
+                     "push %6; "                                       \
                      "popf; "                                          \
                      "rep; "                                           \
                      #iname"w; "                                       \
                      "pushf; "                                         \
                      "pop %0; "                                        \
                      "popf; "                                          \
-                     : "=q"(*flags)                                    \
-                     : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags)       \
+                     : "=q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \
+                     : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags)  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
     }
 
 
                                                              addr_t * src, \
                                                              addr_t * ecx, addr_t * flags) { \
        /* Some of the flags values are not copied out in a pushf, we save them here */ \
-       addr_t flags_rsvd = *flags & ~0xfffc7fff;                       \
+       addr_t guest_flags = *flags & 0x00000cff;                       \
+       uint8_t tmp_dst = 0, tmp_ecx = 0;                               \
                                                                        \
        asm volatile (                                                  \
                      "pushf; "                                         \
-                     "push %4; "                                       \
+                     "push %6; "                                       \
                      "popf; "                                          \
                      "rep; "                                           \
                      #iname"b; "                                       \
                      "pushf; "                                         \
                      "pop %0; "                                        \
                      "popf; "                                          \
-                     : "=q"(*flags)                                    \
-                     : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags)       \
+                     : "=&q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \
+                     : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags)  \
+                     : "memory"                                        \
                      );                                                \
-       *flags |= flags_rsvd;                                           \
+       *flags &= ~FLAGS_MASK;                                          \
+       *flags |= (guest_flags & FLAGS_MASK);                           \
     }
 
 
 
 
 #define MAKE_2OP_64_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src) { \
+       uint64_t tmp_dst = *(uint64_t *)dst;                            \
        asm volatile (                                                  \
                      #iname"q %1, %0; "                                \
-                     : "=q"(*(uint64_t *)dst)                          \
-                     : "q"(*(uint64_t *)src), "0"(*(uint64_t *)dst)    \
+                     : "=&q"(tmp_dst)                                  \
+                     : "q"(*(uint64_t *)src), "0"(tmp_dst)             \
+                     : "memory"                                        \
                      );                                                \
+       *(uint64_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_2OP_32_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src) { \
+       uint32_t tmp_dst = *(uint32_t *)dst;                            \
        asm volatile (                                                  \
                      #iname"l %1, %0; "                                \
-                     : "=q"(*(uint32_t *)dst)                          \
-                     : "q"(*(uint32_t *)src), "0"(*(uint32_t *)dst)    \
+                     : "=&q"(tmp_dst)                                  \
+                     : "q"(*(uint32_t *)src), "0"(tmp_dst)             \
+                     : "memory"                                        \
                      );                                                \
-    }
+       *(uint32_t *)dst = tmp_dst;                                     \
+   }
 
 #define MAKE_2OP_16_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src) { \
+       uint16_t tmp_dst = *(uint16_t *)dst;                            \
        asm volatile (                                                  \
                      #iname"w %1, %0; "                                \
-                     : "=q"(*(uint16_t *)dst)                          \
-                     : "q"(*(uint16_t *)src), "0"(*(uint16_t *)dst)    \
+                     : "=&q"(tmp_dst)                                  \
+                     : "q"(*(uint16_t *)src), "0"(tmp_dst)             \
+                     : "memory"                                        \
                      );                                                \
+       *(uint16_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_2OP_8_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src) { \
+       uint8_t tmp_dst = *(uint8_t *)dst;                              \
        asm volatile (                                                  \
                      #iname"b %1, %0; "                                \
-                     : "=q"(*(uint8_t *)dst)                           \
-                     : "q"(*(uint8_t *)src), "0"(*(uint8_t *)dst)      \
+                     : "=&q"(tmp_dst)                                  \
+                     : "q"(*(uint8_t *)src), "0"(tmp_dst)              \
+                     : "memory"                                        \
                      );                                                \
+       *(uint8_t *)dst = tmp_dst;                                      \
     }
 
 
 
 #define MAKE_2OP_8EXT_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, uint_t dst_len) { \
        if (dst_len == 2) {                                             \
+           uint16_t tmp_dst = *(uint16_t *)dst;                        \
            asm volatile (                                              \
                          #iname" %1, %0; "                             \
-                         : "=q"(*(uint16_t *)dst)                      \
-                         : "q"(*(uint8_t *)src), "0"(*(uint16_t *)dst) \
+                         : "=&q"(tmp_dst)                              \
+                         : "q"(*(uint8_t *)src), "0"(tmp_dst)          \
+                         : "memory"                                    \
                          );                                            \
+           *(uint16_t *)dst = tmp_dst;                                 \
        } else if (dst_len == 4) {                                      \
+           uint32_t tmp_dst = *(uint32_t *)dst;                        \
            asm volatile (                                              \
                          #iname" %1, %0; "                             \
-                         : "=q"(*(uint32_t *)dst)                      \
-                         : "q"(*(uint8_t *)src), "0"(*(uint32_t *)dst) \
+                         : "=&q"(tmp_dst)                              \
+                         : "q"(*(uint8_t *)src), "0"(tmp_dst)          \
+                         : "memory"                                    \
                          );                                            \
+           *(uint32_t *)dst = tmp_dst;                                 \
        } else if (dst_len == 8) {                                      \
+           uint64_t tmp_dst = *(uint64_t *)dst;                        \
            asm volatile (                                              \
                          #iname" %1, %0; "                             \
-                         : "=q"(*(uint64_t *)dst)                      \
-                         : "q"(*(uint8_t *)src), "0"(*(uint64_t *)dst) \
+                         : "=&q"(tmp_dst)                              \
+                         : "q"(*(uint8_t *)src), "0"(tmp_dst)          \
+                         : "memory"                                    \
                          );                                            \
+           *(uint64_t *)dst = tmp_dst;                                 \
        }                                                               \
     }
 
 #define MAKE_2OP_16EXT_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, uint_t dst_len) { \
        if (dst_len == 4) {                                             \
+           uint32_t tmp_dst = *(uint32_t *)dst;                        \
            asm volatile (                                              \
                          #iname" %1, %0; "                             \
-                         : "=q"(*(uint32_t *)dst)                      \
-                         : "q"(*(uint16_t *)src), "0"(*(uint32_t *)dst) \
+                         : "=&q"(tmp_dst)                              \
+                         : "q"(*(uint16_t *)src), "0"(tmp_dst)         \
+                         : "memory"                                    \
                          );                                            \
+           *(uint32_t *)dst = tmp_dst;                                 \
        } else if (dst_len == 8) {                                      \
+           uint64_t tmp_dst = *(uint64_t *)dst;                        \
            asm volatile (                                              \
                          #iname" %1, %0; "                             \
-                         : "=q"(*(uint64_t *)dst)                      \
-                         : "q"(*(uint16_t *)src), "0"(*(uint64_t *)dst) \
+                         : "=&q"(tmp_dst)                              \
+                         : "q"(*(uint16_t *)src), "0"(tmp_dst)         \
+                         : "memory"                                    \
                          );                                            \
+           *(uint64_t *)dst = tmp_dst;                                 \
        }                                                               \
     }
 
 
 
 #define MAKE_2OUT_64_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src) { \
+       uint64_t tmp_dst = *(uint64_t *)dst;                            \
+       uint64_t tmp_src = *(uint64_t *)src;                            \
+                                                                       \
        asm volatile (                                                  \
                      #iname"q %1, %0; "                                \
-                     : "=q"(*(uint64_t *)dst), "=q"(*(uint64_t *)src)  \
-                     : "0"(*(uint64_t *)dst), "1"(*(uint64_t *)src)    \
+                     : "=&q"(tmp_dst), "=&q"(tmp_src)                  \
+                     : "0"(tmp_dst), "1"(tmp_src)                      \
+                     : "memory"                                        \
                      );                                                \
+       *(uint64_t *)src = tmp_src;                                     \
+       *(uint64_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_2OUT_32_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src) { \
+       uint32_t tmp_dst = *(uint32_t *)dst;                            \
+       uint32_t tmp_src = *(uint32_t *)src;                            \
+                                                                       \
        asm volatile (                                                  \
                      #iname"l %1, %0; "                                \
-                     : "=q"(*(uint32_t *)dst), "=q"(*(uint32_t *)src)  \
-                     :  "0"(*(uint32_t *)dst), "1"(*(uint32_t *)src)   \
+                     : "=&q"(tmp_dst), "=&q"(tmp_src)                  \
+                     :  "0"(tmp_dst), "1"(tmp_src)                     \
+                     : "memory"                                        \
                      );                                                \
+       *(uint32_t *)src = tmp_src;                                     \
+       *(uint32_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_2OUT_16_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src) { \
+       uint16_t tmp_dst = *(uint16_t *)dst;                            \
+       uint16_t tmp_src = *(uint16_t *)src;                            \
+                                                                       \
        asm volatile (                                                  \
                      #iname"w %1, %0; "                                \
-                     : "=q"(*(uint16_t *)dst), "=q"(*(uint16_t *)src)  \
-                     : "0"(*(uint16_t *)dst), "1"(*(uint16_t *)src)    \
+                     : "=&q"(tmp_dst), "=&q"(tmp_src)                  \
+                     : "0"(tmp_dst), "1"(tmp_src)                      \
+                     : "memory"                                        \
                      );                                                \
+       *(uint16_t *)src = tmp_src;                                     \
+       *(uint16_t *)dst = tmp_dst;                                     \
     }
 
 #define MAKE_2OUT_8_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src) { \
+       uint8_t tmp_dst = *(uint8_t *)dst;                              \
+       uint8_t tmp_src = *(uint8_t *)src;                              \
+                                                                       \
        asm volatile (                                                  \
                      #iname"b %1, %0; "                                \
-                     : "=q"(*(uint8_t *)dst), "=q"(*(uint8_t *)src)    \
-                     : "0"(*(uint8_t *)dst), "1"(*(uint8_t *)src)      \
+                     : "=&q"(tmp_dst), "=&q"(tmp_src)                  \
+                     : "0"(tmp_dst), "1"(tmp_src)                      \
+                     : "memory"                                        \
                      );                                                \
+       *(uint8_t *)src = tmp_src;                                      \
+       *(uint8_t *)dst = tmp_dst;                                      \
     }
 
 
diff --git a/palacios/include/palacios/vmm_mtrr.h b/palacios/include/palacios/vmm_mtrr.h
deleted file mode 100644 (file)
index 0901781..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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) 2011, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2011, 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_MTRR_H__
-#define __VMM_MTRR_H__
-
-
-#ifdef __V3VEE__
-
-#include <palacios/vmm.h>
-
-
-
-#endif
-
-#endif
index 1a17997..8d45bcd 100644 (file)
@@ -27,7 +27,7 @@
 
 
 typedef enum {SHADOW_PAGING, NESTED_PAGING} v3_paging_mode_t;
-typedef enum {VM_RUNNING, VM_STOPPED, VM_SUSPENDED, VM_ERROR, VM_EMULATING} v3_vm_operating_mode_t;
+typedef enum {VM_RUNNING, VM_STOPPED, VM_PAUSED, VM_ERROR} v3_vm_operating_mode_t;
 typedef enum {CORE_RUNNING, CORE_STOPPED} v3_core_operating_mode_t;
 
 typedef enum {REAL, /*UNREAL,*/ PROTECTED, PROTECTED_PAE, LONG, LONG_32_COMPAT, LONG_16_COMPAT} v3_cpu_mode_t;
index 949f0b2..b123d59 100644 (file)
@@ -107,7 +107,7 @@ void v3_vnet_del_bridge(uint8_t type);
 int v3_vnet_add_route(struct v3_vnet_route route);
 void v3_vnet_del_route(uint32_t route_idx);
 
-int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data, int synchronize);
+int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data);
 int v3_vnet_find_dev(uint8_t  * mac);
 int v3_vnet_stat(struct vnet_stat * stats);
 
@@ -117,13 +117,18 @@ struct v3_vnet_dev_ops {
     int (*input)(struct v3_vm_info * vm, 
                 struct v3_vnet_pkt * pkt, 
                 void * dev_data);
+
+    /* return >0 means there are more pkts in the queue to be sent */
+    int (*poll)(struct v3_vm_info * vm,
+               int quote,
+               void * dev_data);
 };
 
 int v3_init_vnet(void);        
 void v3_deinit_vnet(void);
 
 int v3_vnet_add_dev(struct v3_vm_info * info, uint8_t * mac, 
-                   struct v3_vnet_dev_ops * ops,
+                   struct v3_vnet_dev_ops * ops, int quote, int poll_state,
                    void * priv_data);
 int v3_vnet_del_dev(int dev_id);
 
index 575223b..23a88ff 100644 (file)
@@ -153,6 +153,14 @@ config DEBUG_VIRTIO_SYM
        help 
          Enable debugging for the Linux Virtio Symbiotic Device
 
+config LINUX_VIRTIO_CONSOLE
+        bool "Enable Virtio Console Device"
+        default n
+       depends on PCI
+        help
+          Enable the Virtio Console
+
+
 config LINUX_VIRTIO_NET
         bool "Enable Virtio Network Device"
         default n
@@ -451,6 +459,13 @@ config SERIAL_UART
        help 
          Include virtual serial port
 
+config DEBUG_SERIAL
+        bool "Debug Serial Port"
+        default n
+        depends on SERIAL_UART
+        help
+          Debugging virtual serial port
+
 config CHAR_STREAM
        bool "Stream based character frontend"
        depends on STREAM
index 0ab7f7f..1154059 100644 (file)
@@ -15,6 +15,7 @@ obj-$(V3_CONFIG_LINUX_VIRTIO_BLOCK) += lnx_virtio_blk.o
 obj-$(V3_CONFIG_LINUX_VIRTIO_SYM) += lnx_virtio_sym.o
 obj-$(V3_CONFIG_LINUX_VIRTIO_NET) += lnx_virtio_nic.o
 obj-$(V3_CONFIG_LINUX_VIRTIO_VNET) += lnx_virtio_vnet.o
+obj-$(V3_CONFIG_LINUX_VIRTIO_CONSOLE) += lnx_virtio_console.o
 obj-$(V3_CONFIG_VNET_NIC) += vnet_nic.o
 obj-$(V3_CONFIG_NVRAM) += nvram.o
 obj-$(V3_CONFIG_OS_DEBUG) += os_debug.o
index e9556c8..7997818 100644 (file)
@@ -1153,12 +1153,14 @@ static int cga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        PrintDebug("Enabling CGA Passthrough\n");
        if (v3_hook_write_mem(vm, V3_MEM_CORE_ANY, START_ADDR, END_ADDR, 
                              START_ADDR, &video_write_mem, dev) == -1) {
-           PrintDebug("\n\nVideo Hook failed.\n\n");
+           PrintError("\n\nVideo Hook failed.\n\n");
+           return -1;
        }
     } else {
        if (v3_hook_write_mem(vm, V3_MEM_CORE_ANY, START_ADDR, END_ADDR, 
                              video_state->framebuf_pa, &video_write_mem, dev) == -1) {
-           PrintDebug("\n\nVideo Hook failed.\n\n");
+           PrintError("\n\nVideo Hook failed.\n\n");
+           return -1;
        }
     }
 
index f0c762d..2bde181 100644 (file)
 
 
 struct stream_state {
-    v3_stream_t stream;
+    struct v3_stream * stream;
 
     struct v3_dev_char_ops char_ops;
 
+    struct v3_vm_info * vm;
+
     void * push_fn_arg;
 };
 
 
-static int serial_event_handler(struct v3_vm_info * vm, 
-                               struct v3_serial_event * evt, 
-                               void * private_data) {
-    struct stream_state * state = (struct stream_state *)private_data;
+static uint64_t  stream_input(struct v3_stream * stream, uint8_t * buf, uint64_t len) {
+    struct stream_state * state = stream->guest_stream_data;
 
-    if (state->char_ops.push != NULL){
-       state->char_ops.push(vm, evt->data, evt->len, state->push_fn_arg);
-    }
+    return state->char_ops.input(state->vm, buf, len, state->push_fn_arg);
 
-    return 0;
 }
 
-static int stream_write(uint8_t * buf, uint64_t length, void * private_data) {
+static uint64_t  stream_output(uint8_t * buf, uint64_t length, void * private_data) {
     struct stream_state * state = (struct stream_state *)private_data;
-    
-    return v3_stream_write(state->stream, buf, length);
+   
+    return v3_stream_output(state->stream, buf, length);
 }
 
 static int stream_free(struct stream_state * state) {
@@ -93,8 +90,7 @@ static int stream_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     }
 
 
-
-    state->stream = v3_stream_open(vm, stream_name);
+    state->stream = v3_stream_open(vm, stream_name, stream_input, state);
 
     if (state->stream == NULL) {
        PrintError("Could not open stream %s\n", stream_name);
@@ -102,7 +98,8 @@ static int stream_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        return -1;
     }
 
-    state->char_ops.write = stream_write;
+    state->vm = vm;
+    state->char_ops.output = stream_output;
 
     if (v3_dev_connect_char(vm, v3_cfg_val(frontend_cfg, "tag"), 
                            &(state->char_ops), frontend_cfg, 
@@ -113,7 +110,7 @@ static int stream_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        return -1;
     }
 
-    v3_hook_host_event(vm, HOST_SERIAL_EVT, V3_HOST_EVENT_HANDLER(serial_event_handler), state);
+
 
     return 0;
 }
diff --git a/palacios/src/devices/lnx_virtio_console.c b/palacios/src/devices/lnx_virtio_console.c
new file mode 100644 (file)
index 0000000..f7f2a11
--- /dev/null
@@ -0,0 +1,532 @@
+/* 
+ * 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 <devices/lnx_virtio_pci.h>
+#include <palacios/vm_guest_mem.h>
+
+#include <devices/pci.h>
+
+
+
+struct console_config {
+    uint16_t cols;
+    uint16_t rows;
+} __attribute__((packed));
+
+
+
+
+#define QUEUE_SIZE 128
+
+/* Host Feature flags */
+#define VIRTIO_CONSOLE_F_SIZE 0x1
+
+struct virtio_console_state {
+    struct console_config cons_cfg;
+    struct virtio_config virtio_cfg;
+
+    struct vm_device * pci_bus;
+    struct pci_device * pci_dev;
+    
+    struct virtio_queue queue[2];
+
+    struct v3_stream * stream;
+
+
+    struct virtio_queue * cur_queue;
+
+    struct v3_vm_info * vm;
+
+    int io_range_size;
+
+    void * backend_data;
+    struct v3_dev_char_ops * ops;
+};
+
+
+struct virtio_console_state * cons_state = NULL;
+
+static int virtio_reset(struct virtio_console_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;
+
+    /* Console configuration */
+    // virtio->virtio_cfg.host_features = VIRTIO_NOTIFY_HOST;
+
+    // Virtio Console uses two queues
+    virtio->queue[0].queue_size = QUEUE_SIZE;
+    virtio->queue[1].queue_size = QUEUE_SIZE;
+
+
+    memset(&(virtio->cons_cfg), 0, sizeof(struct console_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_kick(struct guest_info * core, struct virtio_console_state * virtio) {
+    struct virtio_queue * q = virtio->cur_queue;
+
+    PrintDebug("VIRTIO CONSOLE KICK: cur_index=%d (mod=%d), avail_index=%d\n", 
+              q->cur_avail_idx, q->cur_avail_idx % QUEUE_SIZE, q->avail->index);
+
+    while (q->cur_avail_idx < q->avail->index) {
+       struct vring_desc * tmp_desc = NULL;
+       uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
+       int desc_cnt = get_desc_count(q, desc_idx);
+       int i = 0;
+       uint32_t req_len = 0;
+
+
+       PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE);
+
+       for (i = 0; i < desc_cnt; i++) {
+           addr_t page_addr;
+           tmp_desc = &(q->desc[desc_idx]);
+           
+       
+           PrintDebug("Console output (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", 
+                      tmp_desc, 
+                      (void *)(addr_t)(tmp_desc->addr_gpa), tmp_desc->length, 
+                      tmp_desc->flags, tmp_desc->next);
+       
+           if (v3_gpa_to_hva(core, tmp_desc->addr_gpa, (addr_t *)&(page_addr)) == -1) {
+               PrintError("Could not translate block header address\n");
+               return -1;
+           }
+
+           virtio->ops->output((uint8_t *)page_addr, tmp_desc->length, virtio->backend_data);
+
+           PrintDebug("Guest Console Currently Ignored\n");
+
+           req_len += tmp_desc->length;
+           desc_idx = tmp_desc->next;
+       }
+
+       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 = req_len; // What do we set this to????
+
+       q->used->index++;
+       q->cur_avail_idx++;
+    }
+
+    if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
+       PrintDebug("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 = VIRTIO_ISR_ACTIVE;
+    }
+
+    return 0;
+}
+
+
+static uint64_t virtio_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * private_data) {
+    struct virtio_console_state * cons_state = private_data;
+    struct virtio_queue * q = &(cons_state->queue[0]);
+    int xfer_len = 0;
+    
+   PrintDebug("VIRTIO CONSOLE Handle Input: cur_index=%d (mod=%d), avail_index=%d\n", 
+              q->cur_avail_idx, q->cur_avail_idx % QUEUE_SIZE, q->avail->index);
+
+
+   if (q->cur_avail_idx != q->avail->index) {
+       uint16_t input_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
+       struct vring_desc * input_desc = NULL;
+       uint8_t * input_buf = NULL;
+
+       input_desc = &(q->desc[input_idx]);
+
+       if (v3_gpa_to_hva(&(cons_state->vm->cores[0]), input_desc->addr_gpa, (addr_t *)&(input_buf)) == -1) {
+          PrintError("Could not translate receive buffer address\n");
+          return 0;
+       }
+
+       memset(input_buf, 0, input_desc->length);
+
+       xfer_len = (input_desc->length > len) ? len : input_desc->length;
+
+       memcpy(input_buf, buf, xfer_len);
+
+       
+       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 = xfer_len;
+
+       q->used->index++;
+       q->cur_avail_idx++;
+   }
+
+
+    // say hello
+    if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
+           v3_pci_raise_irq(cons_state->pci_bus, 0, cons_state->pci_dev);
+           cons_state->virtio_cfg.pci_isr = 0x1;
+    }
+
+    return xfer_len;
+}
+
+
+static int virtio_io_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * private_data) {
+    struct virtio_console_state * virtio = (struct virtio_console_state *)private_data;
+    int port_idx = port % virtio->io_range_size;
+
+
+    PrintDebug("VIRTIO CONSOLE Write for port %d (index=%d) len=%d, value=%x\n", 
+              port, port_idx,  length, *(uint32_t *)src);
+
+
+
+    switch (port_idx) {
+       case GUEST_FEATURES_PORT:
+           if (length != 4) {
+               PrintError("Illegal write length for guest features\n");
+               return -1;
+           }
+           
+           virtio->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);
+
+
+               virtio->cur_queue->pfn = pfn;
+               
+               virtio->cur_queue->ring_desc_addr = page_addr ;
+               virtio->cur_queue->ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
+               virtio->cur_queue->ring_used_addr = ( virtio->cur_queue->ring_avail_addr + \
+                                                sizeof(struct vring_avail)    + \
+                                                (QUEUE_SIZE * sizeof(uint16_t)));
+               
+               // round up to next page boundary.
+               virtio->cur_queue->ring_used_addr = (virtio->cur_queue->ring_used_addr + 0xfff) & ~0xfff;
+
+               if (v3_gpa_to_hva(core, virtio->cur_queue->ring_desc_addr, (addr_t *)&(virtio->cur_queue->desc)) == -1) {
+                   PrintError("Could not translate ring descriptor address\n");
+                   return -1;
+               }
+
+
+               if (v3_gpa_to_hva(core, virtio->cur_queue->ring_avail_addr, (addr_t *)&(virtio->cur_queue->avail)) == -1) {
+                   PrintError("Could not translate ring available address\n");
+                   return -1;
+               }
+
+
+               if (v3_gpa_to_hva(core, virtio->cur_queue->ring_used_addr, (addr_t *)&(virtio->cur_queue->used)) == -1) {
+                   PrintError("Could not translate ring used address\n");
+                   return -1;
+               }
+
+               PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
+                          (void *)(virtio->cur_queue->ring_desc_addr),
+                          (void *)(virtio->cur_queue->ring_avail_addr),
+                          (void *)(virtio->cur_queue->ring_used_addr));
+
+               PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
+                          virtio->cur_queue->desc, virtio->cur_queue->avail, virtio->cur_queue->used);
+
+           } else {
+               PrintError("Illegal write length for page frame number\n");
+               return -1;
+           }
+           break;
+       case VRING_Q_SEL_PORT:
+           virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
+
+           if (virtio->virtio_cfg.vring_queue_selector > 1) {
+               PrintError("Virtio Console device only uses 2 queue, selected %d\n", 
+                          virtio->virtio_cfg.vring_queue_selector);
+               return -1;
+           }
+           
+           virtio->cur_queue = &(virtio->queue[virtio->virtio_cfg.vring_queue_selector]);
+
+           break;
+       case VRING_Q_NOTIFY_PORT:
+           PrintDebug("Handling Kick\n");
+           if (handle_kick(core, virtio) == -1) {
+               PrintError("Could not handle Console Notification\n");
+               return -1;
+           }
+           break;
+       case VIRTIO_STATUS_PORT:
+           virtio->virtio_cfg.status = *(uint8_t *)src;
+
+           if (virtio->virtio_cfg.status == 0) {
+               PrintDebug("Resetting device\n");
+               virtio_reset(virtio);
+           }
+
+           break;
+
+       case VIRTIO_ISR_PORT:
+           virtio->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_console_state * virtio = (struct virtio_console_state *)private_data;
+    int port_idx = port % virtio->io_range_size;
+
+
+    PrintDebug("VIRTIO CONSOLE 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 = virtio->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 = virtio->cur_queue->pfn;
+
+           break;
+       case VRING_SIZE_PORT:
+           if (length != 2) {
+               PrintError("Illegal read length for vring size\n");
+               return -1;
+           }
+               
+           *(uint16_t *)dst = virtio->cur_queue->queue_size;
+
+           break;
+
+       case VIRTIO_STATUS_PORT:
+           if (length != 1) {
+               PrintError("Illegal read length for status\n");
+               return -1;
+           }
+
+           *(uint8_t *)dst = virtio->virtio_cfg.status;
+           break;
+
+       case VIRTIO_ISR_PORT:
+           *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
+           virtio->virtio_cfg.pci_isr = 0;
+           v3_pci_lower_irq(virtio->pci_bus, 0, virtio->pci_dev);
+           break;
+
+       default:
+           if ( (port_idx >= sizeof(struct virtio_config)) && 
+                (port_idx < (sizeof(struct virtio_config) + sizeof(struct console_config))) ) {
+               int cfg_offset = port_idx - sizeof(struct virtio_config);
+               uint8_t * cfg_ptr = (uint8_t *)&(virtio->cons_cfg);
+
+               memcpy(dst, cfg_ptr + cfg_offset, length);
+               
+           } else {
+               PrintError("Read of Unhandled Virtio Read\n");
+               return -1;
+           }
+         
+           break;
+    }
+
+    return length;
+}
+
+
+
+
+static int connect_fn(struct v3_vm_info * vm, 
+                     void * frontend_data, 
+                     struct v3_dev_char_ops * ops, 
+                     v3_cfg_tree_t * cfg, 
+                     void * private_data, 
+                     void ** push_fn_arg) {
+
+    struct virtio_console_state * state = (struct virtio_console_state *)frontend_data;
+
+    state->ops = ops;
+    state->backend_data = private_data;
+
+    state->ops->input = virtio_input;
+    *push_fn_arg = state;
+
+    return 0;
+}
+
+static int virtio_free(struct virtio_console_state * virtio) {
+
+    // unregister from PCI
+
+    V3_Free(virtio);
+    return 0;
+}
+
+
+static struct v3_device_ops dev_ops = {
+    .free = (int (*)(void *))virtio_free,
+
+};
+
+
+
+
+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_console_state * virtio_state = NULL;
+    struct pci_device * pci_dev = NULL;
+    char * dev_id = v3_cfg_val(cfg, "ID");
+
+    PrintDebug("Initializing VIRTIO Console device\n");
+
+    if (pci_bus == NULL) {
+       PrintError("VirtIO devices require a PCI Bus");
+       return -1;
+    }
+
+    
+    virtio_state = (struct virtio_console_state *)V3_Malloc(sizeof(struct virtio_console_state));
+    memset(virtio_state, 0, sizeof(struct virtio_console_state));
+    
+
+    cons_state = virtio_state;
+    cons_state->vm = vm;
+
+   
+
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state);
+
+    if (dev == NULL) {
+       PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(virtio_state);
+       return -1;
+    }
+
+    // PCI initialization
+    {
+       struct v3_pci_bar bars[6];
+       int num_ports = sizeof(struct virtio_config) + sizeof(struct console_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_CONSOLE", bars,
+                                        NULL, NULL, NULL, virtio_state);
+
+       if (!pci_dev) {
+           PrintError("Could not register PCI Device\n");
+           v3_remove_device(dev);
+           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_CONSOLE_DEV_ID;
+       pci_dev->config_header.class = PCI_CLASS_DISPLAY;
+       pci_dev->config_header.subclass = PCI_DISPLAY_SUBCLASS_OTHER;
+    
+       pci_dev->config_header.subsystem_id = VIRTIO_CONSOLE_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);
+
+    if (v3_dev_add_char_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
+       PrintError("Could not register %s as frontend\n", dev_id);
+       v3_remove_device(dev);
+       return -1;
+    }
+
+
+    return 0;
+}
+
+
+device_register("LNX_VIRTIO_CONSOLE", virtio_init)
index 952cc52..6300eb8 100644 (file)
@@ -195,7 +195,6 @@ static int tx_one_pkt(struct guest_info * core,
 {
     uint8_t * buf = NULL;
     uint32_t len = buf_desc->length;
-    int synchronize = virtio->tx_notify;
 
     if (v3_gpa_to_hva(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
        PrintDebug("Could not translate buffer address\n");
@@ -207,7 +206,7 @@ static int tx_one_pkt(struct guest_info * core,
        v3_hexdump(buf, len, NULL, 0);
     }
 
-    if(virtio->net_ops->send(buf, len, synchronize, virtio->backend_data) < 0){
+    if(virtio->net_ops->send(buf, len, virtio->backend_data) < 0){
        virtio->stats.tx_dropped ++;
        return -1;
     }
@@ -265,11 +264,12 @@ static inline void disable_cb(struct virtio_queue *queue) {
 }
 
 static int handle_pkt_tx(struct guest_info * core, 
-                        struct virtio_net_state * virtio_state) 
+                        struct virtio_net_state * virtio_state,
+                        int quote)
 {
     struct virtio_queue *q = &(virtio_state->tx_vq);
-    int txed = 0;
-    unsigned long flags; 
+    int txed = 0, left = 0;
+    unsigned long flags;
 
     if (!q->ring_avail_addr) {
        return -1;
@@ -314,8 +314,11 @@ static int handle_pkt_tx(struct guest_info * core,
        q->used->index ++;
        
        q->cur_avail_idx ++;
-
-       txed ++;
+       
+       if(++txed >= quote && quote > 0){
+           left = (q->cur_avail_idx != q->avail->index);
+           break;
+       }
     }
 
     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
@@ -327,11 +330,13 @@ static int handle_pkt_tx(struct guest_info * core,
        virtio_state->stats.rx_interrupts ++;
     }
 
+    V3_Print("Virtio Intr Line %d\n", virtio_state->pci_dev->config_header.intr_line);
+
     if(txed > 0) {
-       V3_Net_Print(2, "Virtio Handle TX: txed pkts: %d\n", txed);
+       V3_Net_Print(2, "Virtio Handle TX: txed pkts: %d, left %d\n", txed, left);
     }
 
-    return 0;
+    return left;
 
 exit_error:
        
@@ -449,15 +454,15 @@ static int virtio_io_write(struct guest_info *core,
                    /* receive queue refill */
                    virtio->stats.tx_interrupts ++;
                } else if (queue_idx == 1){
-                   if (handle_pkt_tx(core, virtio) == -1) {
-                       PrintError("Could not handle Virtio NIC tx kick\n");
+                   if (handle_pkt_tx(core, virtio, 0) < 0) {
+                       PrintError("Virtio NIC: Error to handle packet TX\n");
                        return -1;
                    }
                    virtio->stats.tx_interrupts ++;
                } else if (queue_idx == 2){
                    /* ctrl */
                } else {
-                   PrintError("Wrong queue index %d\n", queue_idx);
+                   PrintError("Virtio NIC: Wrong queue index %d\n", queue_idx);
                }       
                break;          
            }
@@ -495,7 +500,7 @@ static int virtio_io_read(struct guest_info *core,
     switch (port_idx) {
        case HOST_FEATURES_PORT:
            if (length != 4) {
-               PrintError("Illegal read length for host features\n");
+               PrintError("Virtio NIC: Illegal read length for host features\n");
                //return -1;
            }
            *(uint32_t *)dst = virtio->virtio_cfg.host_features;
@@ -503,7 +508,7 @@ static int virtio_io_read(struct guest_info *core,
 
        case VRING_PG_NUM_PORT:
            if (length != 4) {
-               PrintError("Illegal read length for page frame number\n");
+               PrintError("Virtio NIC: Illegal read length for page frame number\n");
                return -1;
            }
            switch (queue_idx) {
@@ -523,7 +528,7 @@ static int virtio_io_read(struct guest_info *core,
 
        case VRING_SIZE_PORT:
            if (length != 2) {
-               PrintError("Illegal read length for vring size\n");
+               PrintError("Virtio NIC: Illegal read length for vring size\n");
                return -1;
            }
            switch (queue_idx) {
@@ -543,7 +548,7 @@ static int virtio_io_read(struct guest_info *core,
 
        case VIRTIO_STATUS_PORT:
            if (length != 1) {
-               PrintError("Illegal read length for status\n");
+               PrintError("Virtio NIC: Illegal read length for status\n");
                return -1;
            }
            *(uint8_t *)dst = virtio->virtio_cfg.status;
@@ -578,7 +583,7 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
     unsigned long flags;
     uint8_t kick_guest = 0;
 
-    V3_Net_Print(2, "Virtio-NIC: virtio_rx: size: %d\n", size);
+    V3_Net_Print(2, "Virtio NIC: virtio_rx: size: %d\n", size);
 
     if (!q->ring_avail_addr) {
        V3_Net_Print(2, "Virtio NIC: RX Queue not set\n");
@@ -627,7 +632,7 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
                len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
                                        virtio, buf_desc, buf+offset, size-offset, 0);  
                if (len < 0){
-                   V3_Net_Print(2, "Virtio NIC:merged buffer, %d buffer size %d\n", 
+                   V3_Net_Print(2, "Virtio NIC: merged buffer, %d buffer size %d\n", 
                                 hdr.num_buffers, len);
                    q->cur_avail_idx = old_idx;
                    goto err_exit;
@@ -752,22 +757,10 @@ static struct v3_device_ops dev_ops = {
 };
 
 
-static int virtio_tx_flush(void * args){
-    struct virtio_net_state *virtio  = (struct virtio_net_state *)args;
+static int virtio_poll(int quote, void * data){
+    struct virtio_net_state * virtio  = (struct virtio_net_state *)data;
 
-    V3_Print("Virtio TX Poll Thread Starting for %s\n", 
-            virtio->vm->name);
-
-    while(1){
-       if(virtio->tx_notify == 0){
-           handle_pkt_tx(&(virtio->vm->cores[0]), virtio);
-           v3_yield(NULL);
-       }else {
-           vnet_thread_sleep(-1);
-       }
-    }
-
-    return 0;
+    return handle_pkt_tx(&(virtio->vm->cores[0]), virtio, quote);
 }
 
 static int register_dev(struct virtio_dev_state * virtio, 
@@ -780,7 +773,7 @@ static int register_dev(struct virtio_dev_state * virtio,
     int i;
 
     /* This gets the number of ports, rounded up to a power of 2 */
-    net_state->io_range_size = 1; // must be a power of 2
+    net_state->io_range_size = 1;
     while (tmp_ports > 0) {
        tmp_ports >>= 1;
        net_state->io_range_size <<= 1;
@@ -797,7 +790,7 @@ static int register_dev(struct virtio_dev_state * virtio,
        bars[i].type = PCI_BAR_NONE;
     }
     
-    PrintDebug("Virtio-NIC io_range_size = %d\n", 
+    PrintDebug("Virtio NIC: io_range_size = %d\n", 
               net_state->io_range_size);
     
     bars[0].type = PCI_BAR_IO;
@@ -808,7 +801,7 @@ static int register_dev(struct virtio_dev_state * virtio,
     bars[0].private_data = net_state;
     
     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
-                                    0, 4/*PCI_AUTO_DEV_NUM*/, 0,
+                                    0, PCI_AUTO_DEV_NUM, 0,
                                     "LNX_VIRTIO_NIC", bars,
                                     NULL, NULL, NULL, net_state);
     
@@ -837,6 +830,8 @@ static int register_dev(struct virtio_dev_state * virtio,
        
     virtio_init_state(net_state);
 
+    V3_Print("Virtio NIC: Registered Intr Line %d\n", pci_dev->config_header.intr_line);
+
     /* Add backend to list of devices */
     list_add(&(net_state->dev_link), &(virtio->dev_list));
 
@@ -936,11 +931,12 @@ static int connect_fn(struct v3_vm_info * info,
                                    &timer_ops,net_state);
 
     ops->recv = virtio_rx;
-    ops->frontend_data = net_state;
-    memcpy(ops->fnt_mac, virtio->mac, ETH_ALEN);
-
-    net_state->poll_thread = vnet_start_thread(virtio_tx_flush, 
-                                              (void *)net_state, "Virtio_Poll");
+    ops->poll = virtio_poll;
+    ops->config.frontend_data = net_state;
+    ops->config.poll = 1;
+    ops->config.quote = 64;
+    ops->config.fnt_mac = V3_Malloc(ETH_ALEN);  
+    memcpy(ops->config.fnt_mac, virtio->mac, ETH_ALEN);
 
     net_state->status = 1;
 
@@ -956,7 +952,7 @@ static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     memcpy(macstr, str, strlen(str));
 
     if (pci_bus == NULL) {
-       PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
+       PrintError("Virtio NIC: Virtio device require a PCI Bus");
        return -1;
     }
 
index ab82bdb..8752943 100644 (file)
@@ -361,7 +361,15 @@ static int reset_piix3(struct v3_southbridge * piix3) {
 }
 
 
-//irq is pirq_rc[intr_pin + pci_dev_num - 1] & 0x3
+//irq is pirq_rc[intr_pin + pci_dev_num - 1] & 0xf
+/*
+struct pirq_rc_reg {
+       uint8_t irq         : 4;
+       uint8_t rsvd        : 3;
+       uint8_t disabled    : 1; // (1=disabled, 0=enabled)
+}
+*/
+
 
 static int raise_pci_irq(struct pci_device * pci_dev, void * dev_data) {
     struct v3_southbridge * piix3 = dev_data;
@@ -372,7 +380,15 @@ static int raise_pci_irq(struct pci_device * pci_dev, void * dev_data) {
     
     //PrintError("Raising PCI IRQ %d, %p\n", piix3_cfg->pirq_rc[irq_index], piix3->vm);
     
-    v3_raise_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index]);
+    if (piix3_cfg->pirq_rc[irq_index] < 16) {
+       v3_raise_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index] & 0xf);
+    } else {
+       PrintError("Tried to raise interrupt on disabled PIRQ entry (%d)\n", irq_index);
+       PrintError("\tpirq_rc values: 0=0x%x, 1=0x%x, 2=0x%x, 3=0x%x\n", 
+                  piix3_cfg->pirq_rc[0], piix3_cfg->pirq_rc[1],
+                  piix3_cfg->pirq_rc[2], piix3_cfg->pirq_rc[3]);
+       return -1;
+    }
 
     return 0;
 }
@@ -388,7 +404,15 @@ static int lower_pci_irq(struct pci_device * pci_dev, void * dev_data) {
     
     //    PrintError("Lowering PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
     
-    v3_lower_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index]);
+    if (piix3_cfg->pirq_rc[irq_index] < 16) {
+       v3_lower_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index] & 0xf);
+    } else {
+       PrintError("Tried to lower interrupt on disabled PIRQ entry (%d)\n", irq_index);
+       PrintError("\tpirq_rc values: 0=0x%x, 1=0x%x, 2=0x%x, 3=0x%x\n", 
+                  piix3_cfg->pirq_rc[0], piix3_cfg->pirq_rc[1],
+                  piix3_cfg->pirq_rc[2], piix3_cfg->pirq_rc[3]);
+       return -1;
+    }
 
     return 0;
 }
index f0d405d..52c3202 100644 (file)
@@ -393,6 +393,8 @@ static int queue_data(struct v3_vm_info * vm, struct serial_port * com,
            com->lsr.oe = 1; //overrun error bit set
        }
 
+       updateIRQ(vm, com);
+
        return 0;
     }
     
@@ -411,9 +413,7 @@ static int queue_data(struct v3_vm_info * vm, struct serial_port * com,
        com->lsr.thre = 0; //reset thre and temt bits.
        com->lsr.temt = 0;
     }
-    
-    updateIRQ(vm, com);
-    
+        
     return 0;
 }
 
@@ -486,9 +486,10 @@ static int write_data_port(struct guest_info * core, uint16_t port,
 
        /* JRL: Some buffering would probably be a good idea here.... */
        if (com_port->ops) {
-           com_port->ops->write(val, 1, com_port->backend_data);
+           com_port->ops->output(val, 1, com_port->backend_data);
        } else {
            queue_data(core->vm_info, com_port, &(com_port->tx_buffer), *val);
+           updateIRQ(core->vm_info, com_port);
        }
     }
     
@@ -896,7 +897,7 @@ static int init_serial_port(struct serial_port * com) {
     return 0;
 }
 
-static int serial_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * priv_data){
+static uint64_t serial_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * priv_data){
     struct serial_port * com_port = (struct serial_port *)priv_data;
     int i;
 
@@ -904,6 +905,8 @@ static int serial_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, voi
        queue_data(vm, com_port, &(com_port->rx_buffer), buf[i]);
     }
 
+    updateIRQ(vm, com_port);
+
     return len;
 }
 
@@ -937,7 +940,7 @@ static int connect_fn(struct v3_vm_info * vm,
     com->ops = ops;
     com->backend_data = private_data;
 
-    com->ops->push = serial_input;
+    com->ops->input = serial_input;
     *push_fn_arg = com;
 
     return 0;
index ac484a0..d66384d 100644 (file)
@@ -42,7 +42,7 @@ struct vnet_nic_state {
 
 /* called by frontend, send pkt to VNET */
 static int vnet_nic_send(uint8_t * buf, uint32_t len, 
-                        int synchronize, void * private_data) {
+                        void * private_data) {
     struct vnet_nic_state * vnetnic = (struct vnet_nic_state *)private_data;
 
     struct v3_vnet_pkt pkt;
@@ -58,12 +58,12 @@ static int vnet_nic_send(uint8_t * buf, uint32_t len,
        v3_hexdump(buf, len, NULL, 0);
     }
 
-    return v3_vnet_send_pkt(&pkt, NULL, synchronize);
+    return v3_vnet_send_pkt(&pkt, NULL);
 }
 
 
 /* send pkt to frontend device */
-static int virtio_input(struct v3_vm_info * info, 
+static int fnt_input(struct v3_vm_info * info, 
                        struct v3_vnet_pkt * pkt, 
                        void * private_data){
     struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
@@ -72,7 +72,16 @@ static int virtio_input(struct v3_vm_info * info,
                pkt->size, pkt->src_id, pkt->src_type, pkt->dst_id, pkt->dst_type);
        
     return vnetnic->net_ops.recv(pkt->data, pkt->size,
-                                vnetnic->net_ops.frontend_data);
+                                vnetnic->net_ops.config.frontend_data);
+}
+
+
+/* poll pkt from frontend device */
+static int fnt_poll(struct v3_vm_info * info,
+                       int quote, void * private_data){
+    struct vnet_nic_state *vnetnic = (struct vnet_nic_state *)private_data;
+
+    return vnetnic->net_ops.poll(quote, vnetnic->net_ops.config.frontend_data);
 }
 
 
@@ -90,7 +99,8 @@ static struct v3_device_ops dev_ops = {
 };
 
 static struct v3_vnet_dev_ops vnet_dev_ops = {
-    .input = virtio_input,
+    .input = fnt_input,
+    .poll = fnt_poll,
 };
 
 
@@ -123,9 +133,11 @@ static int vnet_nic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     }
 
     PrintDebug("Vnet-nic: Connect %s to frontend %s\n", 
-             dev_id, v3_cfg_val(frontend_cfg, "tag"));
+              dev_id, v3_cfg_val(frontend_cfg, "tag"));
 
-    if ((vnet_dev_id = v3_vnet_add_dev(vm, vnetnic->net_ops.fnt_mac, &vnet_dev_ops, (void *)vnetnic)) == -1) {
+    if ((vnet_dev_id = v3_vnet_add_dev(vm, vnetnic->net_ops.config.fnt_mac, 
+                                      &vnet_dev_ops, vnetnic->net_ops.config.quote, 
+                                      vnetnic->net_ops.config.poll, (void *)vnetnic)) == -1) {
        PrintError("Vnet-nic device %s fails to registered to VNET\n", dev_id);
        
        v3_remove_device(dev);
index 51605ae..2ab04ca 100644 (file)
@@ -545,6 +545,25 @@ int v3_mcheck_inject_nb_mce(struct v3_vm_info * const vm, const uint32_t cpu,
     return 0;
 }
 
+int v3_mcheck_inject_scrubber_mce(struct v3_vm_info *info, int cpu, uint64_t dst)
+{
+    struct mc4_stat_msr stat;
+    struct mc4_addr_msr addr;
+
+    stat.value = 0;
+    stat.error_code = 0x810;
+    stat.error_code_ext = 0x8;
+    stat.uecc = 1;
+    stat.addr_v = 1;
+    stat.en = 1;
+    stat.uc = 1;
+    stat.val = 1;
+
+    addr.addr64 = dst;
+
+    return v3_mcheck_inject_nb_mce(info, cpu, stat, addr);
+}
+
 static struct v3_extension_impl mcheck_impl = {
     .name = MCHECK,
     .init = init_mcheck,
diff --git a/palacios/src/extensions/ext_mtrr.c b/palacios/src/extensions/ext_mtrr.c
new file mode 100644 (file)
index 0000000..7ff0dc0
--- /dev/null
@@ -0,0 +1,625 @@
+/* 
+ * 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_extensions.h>
+#include <palacios/vmm_msr.h>
+
+
+
+#define MTRR_CAP          0xfe
+
+#define MTRR_PHYS_BASE_0  0x200
+#define MTRR_PHYS_MASK_0  0x201
+#define MTRR_PHYS_BASE_1  0x202
+#define MTRR_PHYS_MASK_1  0x203
+#define MTRR_PHYS_BASE_2  0x204
+#define MTRR_PHYS_MASK_2  0x205
+#define MTRR_PHYS_BASE_3  0x206
+#define MTRR_PHYS_MASK_3  0x207
+#define MTRR_PHYS_BASE_4  0x208
+#define MTRR_PHYS_MASK_4  0x209
+#define MTRR_PHYS_BASE_5  0x20a
+#define MTRR_PHYS_MASK_5  0x20b
+#define MTRR_PHYS_BASE_6  0x20c
+#define MTRR_PHYS_MASK_6  0x20d
+#define MTRR_PHYS_BASE_7  0x20e
+#define MTRR_PHYS_MASK_7  0x20f
+
+#define MTRR_FIX_64K_00000 0x250
+#define MTRR_FIX_16K_80000 0x258
+#define MTRR_FIX_16K_A0000 0x259
+#define MTRR_FIX_4K_C0000  0x268
+#define MTRR_FIX_4K_C8000  0x269
+#define MTRR_FIX_4K_D0000  0x26a
+#define MTRR_FIX_4K_D8000  0x26b
+#define MTRR_FIX_4K_E0000  0x26c
+#define MTRR_FIX_4K_E8000  0x26d
+#define MTRR_FIX_4K_F0000  0x26e
+#define MTRR_FIX_4K_F8000  0x26f
+
+#define PAT                0x277
+
+#define MTRR_DEF_TYPE      0x2ff
+
+
+
+
+struct ia32_pat {
+    union {
+       uint64_t value;
+
+       struct {
+           uint64_t pa_0            : 3;
+           uint64_t rsvd0           : 5;
+           uint64_t pa_1            : 3;
+           uint64_t rsvd1           : 5;
+           uint64_t pa_2            : 3;
+           uint64_t rsvd2           : 5;
+           uint64_t pa_3            : 3;
+           uint64_t rsvd3           : 5;
+           uint64_t pa_4            : 3;
+           uint64_t rsvd4           : 5;
+           uint64_t pa_5            : 3;
+           uint64_t rsvd5           : 5;
+           uint64_t pa_6            : 3;
+           uint64_t rsvd6           : 5;
+           uint64_t pa_7            : 3;
+           uint64_t rsvd7           : 5;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct mtrr_cap {
+    union {
+       uint64_t value;
+
+       struct {
+           uint64_t var_reg_cnt     : 8;
+           uint64_t fix             : 1;
+           uint64_t rsvd0           : 1;
+           uint64_t wr_combine      : 1;
+           uint64_t rsvd1           : 53;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+struct mtrr_def_type {
+    union {
+       uint64_t value;
+
+       struct {
+           uint64_t def_type        : 8;
+           uint64_t rsvd0           : 2;
+           uint64_t fixed_enable    : 1;
+           uint64_t mtrr_emable     : 1;
+           uint64_t rsvd1           : 52;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct mtrr_phys_base {
+    union {
+       uint64_t value;
+       
+       struct {
+           uint64_t type            : 8;
+           uint64_t rsvd0           : 4;
+           uint64_t base            : 40;
+           uint64_t rsvd1           : 12;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+    
+struct mtrr_phys_mask {
+    union {
+       uint64_t value;
+       
+       struct {
+           uint64_t rsvd0           : 11;
+           uint64_t valid           : 1;
+           uint64_t mask            : 40;
+           uint64_t rsvd1           : 12;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+struct mtrr_fixed {
+    union {
+       uint64_t value;
+       uint8_t types[8];
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+/* AMD Specific Registers */
+#define SYSCONFIG          0xc0010010
+#define TOP_MEM            0xc001001a
+#define TOP_MEM2           0xc001001d
+
+#define IORR_BASE0         0xc0010016
+#define IORR_MASK0         0xc0010017
+#define IORR_BASE1         0xc0010018
+#define IORR_MASK1         0xc0010019
+
+struct syscfg_reg {
+    union {
+       uint64_t value;
+
+       struct {
+           uint64_t rsvd0          : 18;
+           uint64_t mfde           : 1; // 1 = enables RdMem and WrMem bits in fixed-range MTRRs
+           uint64_t mfdm           : 1; // 1 = software can modify RdMem and WrMem bits
+           uint64_t mvdm           : 1; // 1 = enables TOP_MEM reg and var range MTRRs
+           uint64_t tom2           : 1; // 1 = enables TOP_MEM2 reg
+           uint64_t tom2_force_wb  : 1; // 1 = enables default mem type for 4GB-TOP_MEM2 range
+           uint64_t rsvd1          : 41;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+struct top_of_mem_reg {
+    union {
+       uint64_t value;
+       
+       struct {
+           uint64_t rsvd0          : 23;
+           uint64_t phys_addr      : 29;
+           uint64_t rsvd1          : 12;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct iorr_base {
+    union {
+       uint64_t value;
+       
+       struct {
+           uint64_t rsvd0          : 3;
+           uint64_t wrmem          : 1; // 1 = writes go to memory, 0 = writes go to mmap IO
+           uint64_t rdmem          : 1; // 1 = reads go to memory, 0 = reads go to mmap IO
+           uint64_t rsvd1          : 7;
+           uint64_t base           : 40;
+           uint64_t rsvd2          : 12;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+struct iorr_mask {
+    union {
+       uint64_t value;
+
+       struct {
+           uint64_t rsvd0          : 11;
+           uint64_t valid          : 1;
+           uint64_t mask           : 40;
+           uint64_t rsvd1          : 12;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+/* Intel Specific Registers */
+#define SMRR_PHYS_BASE 0x1f2
+#define SMRR_PHYS_MASK 0x1f3
+
+struct smrr_phys_base {
+    union {
+       uint64_t value;
+
+       struct {
+           uint64_t type            : 8;
+           uint64_t rsvd0           : 4;
+           uint64_t base            : 20;
+           uint64_t rsvd1           : 32;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+struct smrr_phys_mask {
+    union {
+       uint64_t value;
+
+       struct {
+           uint64_t rsvd0           : 11;
+           uint64_t valid           : 1;
+           uint64_t mask            : 20;
+           uint64_t rsvd1           : 32;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+struct mtrr_state {
+    struct ia32_pat pat;
+    struct mtrr_cap cap;
+    struct mtrr_def_type def_type;
+    struct mtrr_phys_base bases[8];
+    struct mtrr_phys_mask masks[8];
+
+    struct mtrr_fixed fixed_64k;
+    struct mtrr_fixed fixed_16k[2];
+    struct mtrr_fixed fixed_4k[8];
+
+    /* AMD specific registers */
+    struct syscfg_reg amd_syscfg;
+    struct top_of_mem_reg amd_tom;
+    struct top_of_mem_reg amd_tom2;
+
+    struct iorr_base iorr_bases[2];
+    struct iorr_mask iorr_masks[2];
+
+    /* Intel Specific registers */
+    struct smrr_phys_base intel_smrr_base;
+    struct smrr_phys_mask intel_smrr_mask;
+
+};
+
+static void init_state(struct mtrr_state * state) {
+    state->pat.value = 0x0007040600070406LL;
+    state->cap.value = 0x0000000000000508LL;
+
+    state->amd_syscfg.value = 0x0000000000020601LL;
+    state->amd_tom.value = 0x0000000004000000LL;
+
+    return;
+}
+
+static int mtrr_cap_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    dst->value = state->cap.value;
+    return 0;
+}
+
+static int mtrr_cap_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    state->cap.value = src.value;
+    return 0;
+}
+
+static int pat_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    dst->value = state->pat.value;
+    return 0;
+}
+
+static int pat_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    state->pat.value = src.value;
+    return 0;
+}
+
+static int def_type_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    dst->value = state->def_type.value;
+    return 0;
+}
+
+static int def_type_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    state->def_type.value = src.value;
+    return 0;
+}
+
+
+static int mtrr_phys_base_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int base_index = (msr - MTRR_PHYS_BASE_0) / 2;
+    dst->value = state->bases[base_index].value;
+    return 0;
+}
+
+static int mtrr_phys_base_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int base_index = (msr - MTRR_PHYS_BASE_0) / 2;
+    state->bases[base_index].value = src.value;
+    return 0;
+}
+
+static int mtrr_phys_mask_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int mask_index = (msr - MTRR_PHYS_MASK_0) / 2;
+    dst->value = state->masks[mask_index].value;
+    return 0;
+}
+
+static int mtrr_phys_mask_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int mask_index = (msr - MTRR_PHYS_MASK_0) / 2;
+    state->masks[mask_index].value = src.value;
+    return 0;
+}
+
+static int mtrr_fix_64k_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    dst->value = state->fixed_64k.value;
+    return 0;
+}
+
+static int mtrr_fix_64k_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    state->fixed_64k.value = src.value;
+    return 0;
+}
+
+static int mtrr_fix_16k_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int index = msr - MTRR_FIX_16K_80000;
+    dst->value = state->fixed_16k[index].value;
+    return 0;
+}
+
+static int mtrr_fix_16k_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int index = msr - MTRR_FIX_16K_80000;
+    state->fixed_16k[index].value = src.value;
+    return 0;
+}
+
+static int mtrr_fix_4k_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int index = msr - MTRR_FIX_4K_C0000;
+    dst->value = state->fixed_4k[index].value;
+    return 0;
+}
+
+static int mtrr_fix_4k_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int index = msr - MTRR_FIX_4K_C0000;
+    state->fixed_4k[index].value = src.value;
+    return 0;
+}
+
+/* AMD specific registers */
+static int amd_syscfg_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    dst->value = state->amd_syscfg.value;
+    return 0;
+}
+
+static int amd_syscfg_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    state->amd_syscfg.value = src.value;
+    return 0;
+}
+
+static int amd_top_mem_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+
+    if (msr == TOP_MEM) {
+       dst->value = state->amd_tom.value;
+    } else if (msr == TOP_MEM2) {
+       dst->value = state->amd_tom2.value;
+    }
+
+    return 0;
+}
+
+static int amd_top_mem_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    
+    if (msr == TOP_MEM) {
+       state->amd_tom.value = src.value;
+    } else if (msr == TOP_MEM2) {
+       state->amd_tom2.value = src.value;
+    }
+
+    return 0;
+}
+
+
+static int amd_iorr_base_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int base_index = (msr - IORR_BASE0) / 2;
+    dst->value = state->iorr_bases[base_index].value;
+    return 0;
+}
+
+static int amd_iorr_base_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int base_index = (msr - IORR_BASE0) / 2;
+    state->iorr_bases[base_index].value = src.value;
+    return 0;
+}
+
+static int amd_iorr_mask_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int mask_index = (msr - IORR_MASK0) / 2;
+    dst->value = state->iorr_masks[mask_index].value;
+    return 0;
+}
+
+static int amd_iorr_mask_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    int mask_index = (msr - IORR_MASK0) / 2;
+    state->iorr_masks[mask_index].value = src.value;
+    return 0;
+}
+
+
+static int intel_smrr_base_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    dst->value = state->intel_smrr_base.value;
+    return 0;
+}
+
+static int intel_smrr_base_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    state->intel_smrr_base.value = src.value;
+    return 0;
+}
+
+static int intel_smrr_mask_read(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    dst->value = state->intel_smrr_mask.value;
+    return 0;
+}
+
+static int intel_smrr_mask_write(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    state->intel_smrr_mask.value = src.value;
+    return 0;
+}
+
+
+static int deinit_mtrrs(struct v3_vm_info * vm, void * priv_data) {
+    struct mtrr_state * state = (struct mtrr_state *)priv_data;
+    
+    v3_unhook_msr(vm, MTRR_CAP);
+    v3_unhook_msr(vm, PAT);
+    v3_unhook_msr(vm, MTRR_DEF_TYPE);
+
+    v3_unhook_msr(vm, MTRR_PHYS_BASE_0);
+    v3_unhook_msr(vm, MTRR_PHYS_BASE_1);
+    v3_unhook_msr(vm, MTRR_PHYS_BASE_2);
+    v3_unhook_msr(vm, MTRR_PHYS_BASE_3);
+    v3_unhook_msr(vm, MTRR_PHYS_BASE_4);
+    v3_unhook_msr(vm, MTRR_PHYS_BASE_5);
+    v3_unhook_msr(vm, MTRR_PHYS_BASE_6);
+    v3_unhook_msr(vm, MTRR_PHYS_BASE_7);
+    v3_unhook_msr(vm, MTRR_PHYS_MASK_0);
+    v3_unhook_msr(vm, MTRR_PHYS_MASK_1);
+    v3_unhook_msr(vm, MTRR_PHYS_MASK_2);
+    v3_unhook_msr(vm, MTRR_PHYS_MASK_3);
+    v3_unhook_msr(vm, MTRR_PHYS_MASK_4);
+    v3_unhook_msr(vm, MTRR_PHYS_MASK_5);
+    v3_unhook_msr(vm, MTRR_PHYS_MASK_6);
+    v3_unhook_msr(vm, MTRR_PHYS_MASK_7);
+
+    v3_unhook_msr(vm, MTRR_FIX_64K_00000);
+    v3_unhook_msr(vm, MTRR_FIX_16K_80000);
+    v3_unhook_msr(vm, MTRR_FIX_16K_A0000);
+    v3_unhook_msr(vm, MTRR_FIX_4K_C0000);
+    v3_unhook_msr(vm, MTRR_FIX_4K_C8000);
+    v3_unhook_msr(vm, MTRR_FIX_4K_D0000);
+    v3_unhook_msr(vm, MTRR_FIX_4K_D8000);
+    v3_unhook_msr(vm, MTRR_FIX_4K_E0000);
+    v3_unhook_msr(vm, MTRR_FIX_4K_E8000);
+    v3_unhook_msr(vm, MTRR_FIX_4K_F0000);
+    v3_unhook_msr(vm, MTRR_FIX_4K_F8000);
+
+    /* AMD specific */
+    v3_unhook_msr(vm, SYSCONFIG);
+    v3_unhook_msr(vm, TOP_MEM);
+    v3_unhook_msr(vm, TOP_MEM2);
+
+    v3_unhook_msr(vm, IORR_BASE0);
+    v3_unhook_msr(vm, IORR_BASE1);
+    v3_unhook_msr(vm, IORR_MASK0);
+    v3_unhook_msr(vm, IORR_MASK1);
+           
+    /* Intel Specfic */
+    v3_unhook_msr(vm, SMRR_PHYS_BASE);
+    v3_unhook_msr(vm, SMRR_PHYS_MASK);
+
+
+    V3_Free(state);
+    return 0;
+}
+
+
+static int init_mtrrs(struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
+    struct mtrr_state * state = NULL;
+    int ret = 0;
+
+    state = V3_Malloc(sizeof(struct mtrr_state));
+    memset(state, 0, sizeof(struct mtrr_state));
+
+    *priv_data = state;
+
+    init_state(state);
+    
+    // hook MSRs
+    ret |= v3_hook_msr(vm, MTRR_CAP, mtrr_cap_read, mtrr_cap_write, state);
+    ret |= v3_hook_msr(vm, PAT, pat_read, pat_write, state);
+    ret |= v3_hook_msr(vm, MTRR_DEF_TYPE, def_type_read, def_type_write, state);
+
+    ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_0, mtrr_phys_base_read, mtrr_phys_base_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_1, mtrr_phys_base_read, mtrr_phys_base_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_2, mtrr_phys_base_read, mtrr_phys_base_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_3, mtrr_phys_base_read, mtrr_phys_base_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_4, mtrr_phys_base_read, mtrr_phys_base_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_5, mtrr_phys_base_read, mtrr_phys_base_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_6, mtrr_phys_base_read, mtrr_phys_base_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_BASE_7, mtrr_phys_base_read, mtrr_phys_base_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_0, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_1, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_2, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_3, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_4, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_5, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_6, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
+    ret |= v3_hook_msr(vm, MTRR_PHYS_MASK_7, mtrr_phys_mask_read, mtrr_phys_mask_write, state);
+
+    ret |= v3_hook_msr(vm, MTRR_FIX_64K_00000, mtrr_fix_64k_read, mtrr_fix_64k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_16K_80000, mtrr_fix_16k_read, mtrr_fix_16k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_16K_A0000, mtrr_fix_16k_read, mtrr_fix_16k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_4K_C0000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_4K_C8000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_4K_D0000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_4K_D8000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_4K_E0000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_4K_E8000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_4K_F0000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
+    ret |= v3_hook_msr(vm, MTRR_FIX_4K_F8000, mtrr_fix_4k_read, mtrr_fix_4k_write, state);
+    
+    /* AMD Specific */
+    ret |= v3_hook_msr(vm, SYSCONFIG, amd_syscfg_read, amd_syscfg_write, state);
+    ret |= v3_hook_msr(vm, TOP_MEM, amd_top_mem_read, amd_top_mem_write, state);
+    ret |= v3_hook_msr(vm, TOP_MEM2, amd_top_mem_read, amd_top_mem_write, state);
+
+    ret |= v3_hook_msr(vm, IORR_BASE0, amd_iorr_base_read, amd_iorr_base_write, state);
+    ret |= v3_hook_msr(vm, IORR_BASE1, amd_iorr_base_read, amd_iorr_base_write, state);
+    ret |= v3_hook_msr(vm, IORR_MASK0, amd_iorr_mask_read, amd_iorr_mask_write, state);
+    ret |= v3_hook_msr(vm, IORR_MASK1, amd_iorr_mask_read, amd_iorr_mask_write, state);
+    
+
+    /* INTEL specific */
+    ret |= v3_hook_msr(vm, SMRR_PHYS_BASE, intel_smrr_base_read, intel_smrr_base_write, state);
+    ret |= v3_hook_msr(vm, SMRR_PHYS_MASK, intel_smrr_mask_read, intel_smrr_mask_write, state);
+
+    if (ret != 0) {
+       PrintError("Failed to hook all MTRR MSRs. Aborting...\n");
+       deinit_mtrrs(vm, state);
+       return -1;
+    }
+
+
+    return 0;
+}
+
+
+
+
+static struct v3_extension_impl mtrr_impl = {
+    .name = "MTRRS",
+    .init = init_mtrrs,
+    .deinit = deinit_mtrrs,
+    .core_init = NULL,
+    .core_deinit = NULL,
+    .on_entry = NULL,
+    .on_exit = NULL
+};
+
+register_extension(&mtrr_impl);
index 66ce081..377a545 100644 (file)
 static struct v3_stream_hooks * stream_hooks = NULL;
 
 // VM can be NULL
-v3_stream_t v3_stream_open(struct v3_vm_info * vm, const char * name) {
+struct v3_stream * v3_stream_open(struct v3_vm_info * vm, const char * name, 
+                                 uint64_t (*input)(struct v3_stream * stream, uint8_t * buf, uint64_t len),
+                                 void * guest_stream_data) {
+    struct v3_stream * stream = NULL;
+
     V3_ASSERT(stream_hooks != NULL);
     V3_ASSERT(stream_hooks->open != NULL);
 
-    return stream_hooks->open(name, vm->host_priv_data);
+    stream = V3_Malloc(sizeof(struct v3_stream *));
+
+    stream->input = input;
+    stream->guest_stream_data = guest_stream_data;
+    stream->host_stream_data = stream_hooks->open(stream, name, vm->host_priv_data);
+
+    return stream;
 }
 
-int v3_stream_write(v3_stream_t stream, uint8_t * buf, uint32_t len) {
+uint64_t v3_stream_output(struct v3_stream * stream, uint8_t * buf, uint32_t len) {
     V3_ASSERT(stream_hooks != NULL);
-    V3_ASSERT(stream_hooks->write != NULL);
+    V3_ASSERT(stream_hooks->output != NULL);
 
-    return stream_hooks->write(stream, buf, len);
+    return stream_hooks->output(stream, buf, len);
 }
 
-void v3_stream_close(v3_stream_t stream) {
+void v3_stream_close(struct v3_stream * stream) {
     V3_ASSERT(stream_hooks != NULL);
     V3_ASSERT(stream_hooks->close != NULL);
 
-    return stream_hooks->close(stream);
-}
-
+    stream_hooks->close(stream);
 
+    V3_Free(stream);
+}
 
 
 
index 4c55738..63a822b 100644 (file)
@@ -33,9 +33,9 @@ obj-y := \
        vmm_xml.o \
        vmm_mem_hook.o \
        vmm_extensions.o \
-       vmm_mtrr.o \
        vmm_multitree.o \
-
+       vmm_bitmap.o \
+       vmm_barrier.o \
 
 
 
index f366a76..c3bce64 100644 (file)
@@ -1,4 +1,3 @@
-
 /* 
  * This file is part of the Palacios Virtual Machine Monitor developed
  * by the V3VEE Project with funding from the United States National 
@@ -36,6 +35,8 @@
 #include <palacios/svm_msr.h>
 
 #include <palacios/vmm_rbtree.h>
+#include <palacios/vmm_barrier.h>
+
 
 #include <palacios/vmm_direct_paging.h>
 
@@ -86,11 +87,12 @@ static int v3_svm_handle_efer_write(struct guest_info * core, uint_t msr, struct
     int status;
 
     // Call arch-independent handler
-    if ((status = v3_handle_efer_write(core, msr, src, priv_data)) != 0)
+    if ((status = v3_handle_efer_write(core, msr, src, priv_data)) != 0) {
        return status;
+    }
 
     // SVM-specific code
-    if (core->shdw_pg_mode == NESTED_PAGING) {
+    {
        // Ensure that hardware visible EFER.SVME bit is set (SVM Enable)
        struct efer_64 * hw_efer = (struct efer_64 *)&(core->ctrl_regs.efer);
        hw_efer->svme = 1;
@@ -691,6 +693,8 @@ int v3_start_svm_guest(struct guest_info * info) {
            break;
        }
 
+       v3_wait_at_barrier(info);
+
 
        if (info->vm_info->run_state == VM_STOPPED) {
            info->core_run_state = CORE_STOPPED;
index 62d2a94..7bd275f 100644 (file)
@@ -30,7 +30,7 @@
 #include <palacios/vmm_sprintf.h>
 #include <palacios/vmm_xed.h>
 #include <palacios/vmm_direct_paging.h>
-
+#include <palacios/vmm_barrier.h>
 
 
 v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
@@ -539,6 +539,8 @@ int v3_init_vm(struct v3_vm_info * vm) {
     v3_init_intr_routers(vm);
     v3_init_ext_manager(vm);
 
+    v3_init_barrier(vm);
+
     // Initialize the memory map
     if (v3_init_mem_map(vm) == -1) {
        PrintError("Could not initialize shadow map\n");
@@ -637,6 +639,8 @@ int v3_free_vm_internal(struct v3_vm_info * vm) {
     v3_deinit_intr_routers(vm);
     v3_deinit_host_events(vm);
 
+    v3_deinit_barrier(vm);
+
     v3_deinit_cpuid_map(vm);
     v3_deinit_msr_map(vm);
     v3_deinit_io_map(vm);
index d60e55a..078ae4a 100644 (file)
@@ -154,7 +154,8 @@ void Shutdown_V3() {
     if ((os_hooks) && (os_hooks->call_on_cpu)) {
        for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
            if (v3_cpu_types[i] != V3_INVALID_CPU) {
-               deinit_cpu((void *)(addr_t)i);
+               V3_Call_On_CPU(i, deinit_cpu, (void *)(addr_t)i);
+               //deinit_cpu((void *)(addr_t)i);
            }
        }
     }
@@ -404,6 +405,36 @@ int v3_stop_vm(struct v3_vm_info * vm) {
 }
 
 
+int v3_pause_vm(struct v3_vm_info * vm) {
+
+    if (vm->run_state != VM_RUNNING) {
+       PrintError("Tried to pause a VM that was not running\n");
+       return -1;
+    }
+
+    while (v3_raise_barrier(vm, NULL) == -1);
+
+    vm->run_state = VM_PAUSED;
+
+    return 0;
+}
+
+
+int v3_continue_vm(struct v3_vm_info * vm) {
+
+    if (vm->run_state != VM_PAUSED) {
+       PrintError("Tried to continue a VM that was not paused\n");
+       return -1;
+    }
+
+    v3_lower_barrier(vm);
+
+    vm->run_state = VM_RUNNING;
+
+    return 0;
+}
+
+
 int v3_free_vm(struct v3_vm_info * vm) {
     int i = 0;
     // deinitialize guest (free memory, etc...)
index 614ceca..ab0aae4 100644 (file)
  */
 
 
-#include <util/vmm_barrier.h>
+#include <palacios/vmm_barrier.h>
+#include <palacios/vmm.h>
+#include <palacios/vm_guest.h>
 
+int v3_init_barrier(struct v3_vm_info * vm_info) {
+    struct v3_barrier * barrier = &(vm_info->barrier);
 
-
-int v3_init_barrier(struct v3_barrier * barrier) {
     memset(barrier, 0, sizeof(struct v3_barrier));
+    v3_bitmap_init(&(barrier->cpu_map), vm_info->num_cores); 
     v3_lock_init(&(barrier->lock));
 
     return 0;
 }
 
+int v3_deinit_barrier(struct v3_vm_info * vm_info) {
+    struct v3_barrier * barrier = &(vm_info->barrier);
+
+    v3_bitmap_deinit(&(barrier->cpu_map));
+    v3_lock_deinit(&(barrier->lock));
+
+    return 0;
+}
+
+
+/* Barrier synchronization primitive
+ *   -- This call will block until all the guest cores are waiting at a common synchronization point
+ *      in a yield loop. The core will block at the sync point until the barrier is lowered.
+ * 
+ *   ARGUMENTS: 
+ *       vm_info -- The VM for which the barrier is being activated
+ *       local_core -- The core whose thread this function is being called from, or NULL 
+ *                     if the calling thread is not associated with a VM's core context
+ */
 
-int v3_activate_barrier(struct guest_info * core, struct v3_barrier * barrier) {
+int v3_raise_barrier(struct v3_vm_info * vm_info, struct guest_info * local_core) {
+    struct v3_barrier * barrier = &(vm_info->barrier);
     addr_t flag;
     int acquired = 0;
-    
+    int all_blocked = 0;
+
+    int local_vcpu = -1;
+    int i = 0;
+
+
+
     flag = v3_lock_irqsave(barrier->lock);
 
     if (barrier->active == 0) {
@@ -44,11 +73,49 @@ int v3_activate_barrier(struct guest_info * core, struct v3_barrier * barrier) {
     v3_unlock_irqrestore(barrier->lock, flag);
 
     if (acquired == 0) {
+       /* If we are in a core context and the barrier has already been acquired 
+          we'll be safe and let the other barrier proceed. We will still report an error 
+          though to allow possible cleanups to occur at the call site.
+       */
+       if (local_core != NULL) {
+           v3_wait_at_barrier(local_core);
+       }
+
        return -1;
     }
 
+    // If we are raising the barrier from a core context
+    //   we have to mark ourselves blocked first to avoid deadlock
+    if (local_core != NULL) {
+       local_vcpu = local_core->vcpu_id;
+       v3_bitmap_set(&(barrier->cpu_map), local_vcpu);
+    }
+
 
-    // wait for barrier catch
+    // send out interrupts to force exits on all cores
+    for (i = 0; i < vm_info->num_cores; i++) {
+       if (vm_info->cores[i].vcpu_id != local_vcpu) {
+           v3_interrupt_cpu(vm_info, vm_info->cores[i].pcpu_id, 0);
+       }
+    }
+
+    // wait for barrier catch on all cores
+    while (all_blocked == 0) {
+       all_blocked = 1;
+
+       for (i = 0; i < vm_info->num_cores; i++) {
+           if (v3_bitmap_check(&(barrier->cpu_map), i) == 0) {
+               // There is still a core that is not waiting at the barrier
+               all_blocked = 0;
+           }
+       }
+
+       if (all_blocked == 1) {
+           break;
+       }
+
+       v3_yield(local_core);
+    }
 
 
     return 0;
@@ -56,20 +123,52 @@ int v3_activate_barrier(struct guest_info * core, struct v3_barrier * barrier) {
 
 
 
+/* Lowers a barrier that has already been raised
+ *    guest cores will automatically resume execution 
+ *    once this has been called
+ * 
+ *   TODO: Need someway to check that the barrier is active
+ */
+
+int v3_lower_barrier(struct v3_vm_info * vm_info) {
+    struct v3_barrier * barrier = &(vm_info->barrier);
+
+    // Clear the active flag, so cores won't wait 
+    barrier->active = 0;
 
-int v3_deactivate_barrier(struct v3_barrier * barrier) {
+    // Clear all the cpu flags, so cores will proceed
+    v3_bitmap_reset(&(barrier->cpu_map));
 
+    return 0;
 }
 
 
-int v3_check_barrier(struct guest_info * core, struct v3_barrier * barrier) {
+/* 
+ * Syncronization point for guest cores
+ *    -- called as part of the main VMM event loop for each core
+ *    -- if a barrier has been activated then the core will signal  
+ *       it has reached the barrier and sit in a yield loop until the 
+ *       barrier has been lowered
+ */
+int v3_wait_at_barrier(struct guest_info * core) {
+    struct v3_barrier * barrier = &(core->vm_info->barrier);
 
-    if (barrier->activated == 0) {
+    if (barrier->active == 0) {
        return 0;
     }
+
+    /*  Barrier has been activated. 
+     *  Wait here until it's lowered
+     */
+    
     
-    // set cpu bit
+    // set cpu bit in barrier bitmap
+    v3_bitmap_set(&(barrier->cpu_map), core->vcpu_id);
 
     // wait for cpu bit to clear
+    while (v3_bitmap_check(&(barrier->cpu_map), core->vcpu_id) == 1) {
+       v3_yield(core);
+    }
 
+    return 0;
 }
diff --git a/palacios/src/palacios/vmm_bitmap.c b/palacios/src/palacios/vmm_bitmap.c
new file mode 100644 (file)
index 0000000..c056a5b
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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) 2011, Jack Lange <jacklange@cs.pitt.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jacklange@cs.pitt.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm_bitmap.h>
+#include <palacios/vmm.h>
+
+
+int v3_bitmap_init(struct v3_bitmap * bitmap, int num_bits) {
+    int num_bytes = (num_bits / 8) + ((num_bits % 8) > 0);
+
+    bitmap->num_bits = num_bits;
+    bitmap->bits = V3_Malloc(num_bytes);
+
+    if (bitmap->bits == NULL) {
+       PrintError("Could not allocate bitmap of %d bits\n", num_bits);
+       return -1;
+    }
+    
+    memset(bitmap->bits, 0, num_bytes);
+
+    return 0;
+}
+
+
+void v3_bitmap_deinit(struct v3_bitmap * bitmap) {
+    V3_Free(bitmap->bits);
+}
+
+
+int v3_bitmap_reset(struct v3_bitmap * bitmap) {
+    int num_bytes = (bitmap->num_bits / 8) + ((bitmap->num_bits % 8) > 0);
+
+    memset(bitmap->bits, 0, num_bytes);
+
+    return 0;
+}
+
+int v3_bitmap_set(struct v3_bitmap * bitmap, int index) {
+    int major = index / 8;
+    int minor = index % 8;
+    int old_val = 0;
+
+    if (index > (bitmap->num_bits - 1)) {
+       PrintError("Index out of bitmap range: (pos = %d) (num_bits = %d)\n", 
+                  index, bitmap->num_bits);
+       return -1;
+    }
+
+    old_val = (bitmap->bits[major] & (0x1 << minor));
+    bitmap->bits[major] |= (0x1 << minor);
+
+    return old_val;
+}
+
+
+int v3_bitmap_clear(struct v3_bitmap * bitmap, int index) {
+    int major = index / 8;
+    int minor = index % 8;
+    int old_val = 0;
+
+    if (index > (bitmap->num_bits - 1)) {
+       PrintError("Index out of bitmap range: (pos = %d) (num_bits = %d)\n", 
+                  index, bitmap->num_bits);
+       return -1;
+    }
+
+    old_val = (bitmap->bits[major] & (0x1 << minor));
+    bitmap->bits[major] &= ~(0x1 << minor);
+
+    return old_val;
+}
+
+int v3_bitmap_check(struct v3_bitmap * bitmap, int index) {
+    int major = index / 8;
+    int minor = index % 8;
+
+    if (index > (bitmap->num_bits - 1)) {
+       PrintError("Index out of bitmap range: (pos = %d) (num_bits = %d)\n", 
+                  index, bitmap->num_bits);
+       return -1;
+    }
+
+    return (bitmap->bits[major] & (0x1 << minor));
+}
+
index defad8f..b46af1b 100644 (file)
 
 static struct hashtable * ext_table = NULL;
 
+/*
+ * This is a place holder to ensure that the _v3_extensions section gets created by gcc
+ */
+static struct {} null_ext  __attribute__((__used__))                    \
+    __attribute__((unused, __section__ ("_v3_extensions"),                \
+                   aligned(sizeof(addr_t))));
+
+
 
 static uint_t ext_hash_fn(addr_t key) {
     char * name = (char *)key;
index 298bc8f..a0753cf 100644 (file)
@@ -394,7 +394,20 @@ static int free_hook(struct v3_vm_info * vm, struct mem_hook * hook) {
 // We do not support unhooking subregions
 int v3_unhook_mem(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr_start) {
     struct v3_mem_region * reg = v3_get_mem_region(vm, core_id, guest_addr_start);
-    struct mem_hook * hook = reg->priv_data;
+    struct mem_hook * hook = NULL;
+
+    if (reg == NULL) {
+       PrintError("Could not find region at %p\n", (void *)guest_addr_start);
+       return -1;
+    }
+
+    hook = reg->priv_data;
+
+    if (hook == NULL) {
+       PrintError("Trying to unhook region that is not a hook at %p\n", (void *)guest_addr_start);
+       return -1;
+    }
+
 
     free_hook(vm, hook);
 
diff --git a/palacios/src/palacios/vmm_mtrr.c b/palacios/src/palacios/vmm_mtrr.c
deleted file mode 100644 (file)
index 5e27afc..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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) 2011, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2011, 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_mtrr.h>
-#include <palacios/vmm_extensions.h>
-#include <palacios/vmm.h>
-#include <palacios/vm_guest.h>
-#include <palacios/vmm_msr.h>
-
-
-#define MTRR_CAP_MSR       0x00fe
-#define MTRR_PHYS_BASE_0   0x0200
-#define MTRR_PHYS_BASE_1   0x0202
-#define MTRR_PHYS_BASE_2   0x0204
-#define MTRR_PHYS_BASE_3   0x0206
-#define MTRR_PHYS_BASE_4   0x0208
-#define MTRR_PHYS_BASE_5   0x020a
-#define MTRR_PHYS_BASE_6   0x020c
-#define MTRR_PHYS_BASE_7   0x020e
-#define MTRR_PHYS_MASK_0   0x0201
-#define MTRR_PHYS_MASK_1   0x0203
-#define MTRR_PHYS_MASK_2   0x0205
-#define MTRR_PHYS_MASK_3   0x0207
-#define MTRR_PHYS_MASK_4   0x0209
-#define MTRR_PHYS_MASK_5   0x020b
-#define MTRR_PHYS_MASK_6   0x020d
-#define MTRR_PHYS_MASK_7   0x020f
-#define MTRR_FIX_64K_00000 0x0250
-#define MTRR_FIX_16K_80000 0x0258
-#define MTRR_FIX_16K_A0000 0x0259
-#define MTRR_FIX_4K_C0000  0x0268
-#define MTRR_FIX_4K_C8000  0x0269
-#define MTRR_FIX_4K_D0000  0x026a
-#define MTRR_FIX_4K_D8000  0x026b
-#define MTRR_FIX_4K_E0000  0x026c
-#define MTRR_FIX_4K_E8000  0x026d
-#define MTRR_FIX_4K_F0000  0x026e
-#define MTRR_FIX_4K_F8000  0x026f
-
-
-struct mtrr_cap {
-
-
-};
-
-
-struct mtrr_state {
-    struct mtrr_cap cap;
-    
-};
-
-
-static int mtrr_cap_read(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data) {
-    return 0;
-}
-
-static int mtrr_cap_write(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data) {
-
-    return 0;
-}
-
-
-
-static int init_mtrrs(struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
-
-
-    V3_Print("Intializing MTRR extension\n");
-
-    v3_hook_msr(vm, MTRR_CAP_MSR, mtrr_cap_read, mtrr_cap_write, NULL);
-        
-
-    return 0;
-}
-
-
-static struct v3_extension_impl mtrr_ext = {
-    .name = "MTRRS",
-    .init = init_mtrrs,
-    .deinit = NULL,
-    .core_init = NULL,
-    .core_deinit = NULL
-};
-
-
-
-register_extension(&mtrr_ext);
index 725fa17..75a8975 100644 (file)
@@ -460,10 +460,14 @@ size_t strcspn(const char * s, const char * reject) {
        for (i = 0; i < reject_len; i++) {
            if (s[cnt] == reject[i]) {
                match = 1;
-               cnt++;
                break;
            }
        }
+
+       if (!match) {
+           cnt++;
+       }
+
     }
 
     return cnt;
index d6963c8..d09a176 100644 (file)
@@ -53,8 +53,6 @@ struct v3_xml_root {       // additional data for the root tag
     char *str_ptr;         // original xml string
     char *tmp_start;              // start of work area
     char *tmp_end;              // end of work area
-    char **ent;           // general entities (ampersand sequences)
-    char ***attr;         // default attributes
     short standalone;     // non-zero if <?xml standalone="yes"?>
     char err[V3_XML_ERRL]; // error string
 };
@@ -62,23 +60,24 @@ struct v3_xml_root {       // additional data for the root tag
 static char * empty_attrib_list[] = { NULL }; // empty, null terminated array of strings
 
 
+
 static void * tmp_realloc(void * old_ptr, size_t old_size, size_t new_size) {
-    void * new_buf = V3_Malloc(new_size);
+    void * new_buf = NULL; 
 
+    new_buf = V3_Malloc(new_size);
+    
     if (new_buf == NULL) {
         return NULL;
     }
 
+    memset(new_buf, 0, new_size);
+
     memcpy(new_buf, old_ptr, old_size);
     V3_Free(old_ptr);
 
     return new_buf;
 }
 
-
-
-
-
 // set an error string and return root
 static void v3_xml_err(struct v3_xml_root * root, char * xml_str, const char * err, ...) {
     va_list ap;
@@ -136,8 +135,6 @@ struct v3_xml * v3_xml_idx(struct v3_xml * xml, int idx) {
 // returns the value of the requested tag attribute or NULL if not found
 const char * v3_xml_attr(struct v3_xml * xml, const char * attr) {
     int i = 0;
-    int j = 1;
-    struct v3_xml_root * root = (struct v3_xml_root *)xml;
 
     if ((!xml) || (!xml->attr)) {
        return NULL;
@@ -151,24 +148,7 @@ const char * v3_xml_attr(struct v3_xml * xml, const char * attr) {
        return xml->attr[i + 1]; // found attribute
     }
 
-    while (root->xml.parent != NULL) {
-       root = (struct v3_xml_root *)root->xml.parent; // root tag
-    }
-
-    for (i = 0; 
-        ( (root->attr[i] != NULL) && 
-          (strcasecmp(xml->name, root->attr[i][0]) != 0) ); 
-        i++);
-
-    if (! root->attr[i]) {
-       return NULL; // no matching default attributes
-    }
-
-    while ((root->attr[i][j] != NULL) && (strcasecmp(attr, root->attr[i][j]) != 0)) {
-       j += 3;
-    }
-
-    return (root->attr[i][j] != NULL) ? root->attr[i][j + 1] : NULL; // found default
+    return NULL; // found default
 }
 
 // same as v3_xml_get but takes an already initialized va_list
@@ -219,11 +199,10 @@ static struct v3_xml * v3_xml_set_flag(struct v3_xml * xml, short flag)
 // for cdata sections, ' ' for attribute normalization, or '*' for non-cdata
 // attribute normalization. Returns s, or if the decoded string is longer than
 // s, returns a malloced string that must be freed.
-static char * v3_xml_decode(char * s, char ** ent, char t) {
+static char * v3_xml_decode(char * s, char t) {
     char * e;
     char * r = s;
-    char * m = s;
-    long b, c, d, l;
+    long c, l;
 
     // normalize line endings
     for (; *s; s++) { 
@@ -266,28 +245,6 @@ static char * v3_xml_decode(char * s, char ** ent, char t) {
            *(s++) = c; 
 
             memmove(s, strchr(s, ';') + 1, strlen(strchr(s, ';')));
-        } else if ( ( (*s == '&') && 
-                     ((t == '&') || (t == ' ') || (t == '*'))) ||
-                   ( (*s == '%') && (t == '%'))) { 
-           // entity reference`
-
-            for ( (b = 0); 
-                 (ent[b]) && (strncmp(s + 1, ent[b], strlen(ent[b])) != 0);
-                 (b += 2)); // find entity in entity list
-
-            if (ent[b++]) { // found a match
-                if (((c = strlen(ent[b])) - 1) > ((e = strchr(s, ';')) - s)) {
-                    l = (d = (s - r)) + c + strlen(e); // new length
-                    r = ((r == m) ? strcpy(V3_Malloc(l), r) : tmp_realloc(r, strlen(r), l));
-                    e = strchr((s = r + d), ';'); // fix up pointers
-                }
-
-                memmove(s + c, e + 1, strlen(e)); // shift rest of string
-                strncpy(s, ent[b], c); // copy in replacement text
-            } else {
-               // not a known entity
-               s++;
-           }
         } else if ( ( (t == ' ') || (t == '*')) && 
                    (isspace(*s))) {
            *(s++) = ' ';
@@ -331,16 +288,23 @@ static void v3_xml_char_content(struct v3_xml_root * root, char * s, size_t len,
     }
 
     s[len] = '\0'; // null terminate text (calling functions anticipate this)
-    len = strlen(s = v3_xml_decode(s, root->ent, t)) + 1;
+    len = strlen(s = v3_xml_decode(s, t)) + 1;
 
-    if (! *(xml->txt)) {
+    if (xml->txt[0] == '\0') { // empty string
        // initial character content
        xml->txt = s;
     } else { 
+
        // allocate our own memory and make a copy
-        xml->txt = (xml->flags & V3_XML_TXTM) ? 
-           (tmp_realloc(xml->txt, strlen(xml->txt), (l = strlen(xml->txt)) + len)) : 
-           (strcpy(V3_Malloc((l = strlen(xml->txt)) + len), xml->txt));
+       if (xml->flags & V3_XML_TXTM) {
+           xml->txt = (tmp_realloc(xml->txt, strlen(xml->txt), (l = strlen(xml->txt)) + len));
+       } else {
+           char * tmp = NULL;
+
+           tmp = V3_Malloc((l = strlen(xml->txt)) + len);
+           strcpy(tmp, xml->txt);
+           xml->txt = tmp;
+       }
 
         strcpy(xml->txt + l, s); // add new char content
        
@@ -367,37 +331,6 @@ static int v3_xml_close_tag(struct v3_xml_root * root, char * name, char * s) {
     return 0;
 }
 
-#if 0
-// checks for circular entity references, returns non-zero if no circular
-// references are found, zero otherwise
-static int v3_xml_ent_ok(char * name, char * s, char ** ent) {
-    int i;
-
-    for (; ; s++) {
-        while ((*s != '\0') && (*s != '&')) {
-           // find next entity reference
-           s++; 
-       }
-
-        if (*s == '\0') {
-           return 1;
-       }
-
-        if (strncmp(s + 1, name, strlen(name)) == 0) {
-           // circular ref.
-           return 0;
-       }
-
-        for (i = 0; (ent[i]) && (strncmp(ent[i], s + 1, strlen(ent[i]))); i += 2);
-
-        if ((ent[i] != NULL) && (v3_xml_ent_ok(name, ent[i + 1], ent) == 0)) {
-           return 0;
-       }
-    }
-}
-#endif
-
-
 
 // frees a tag attribute list
 static void v3_xml_free_attr(char **attr) {
@@ -416,16 +349,6 @@ static void v3_xml_free_attr(char **attr) {
 
     m = attr[i + 1]; // list of which names and values are malloced
 
-    for (i = 0; m[i]; i++) {
-        if (m[i] & V3_XML_NAMEM) {
-           V3_Free(attr[i * 2]);
-       }
-
-        if (m[i] & V3_XML_TXTM) {
-           V3_Free(attr[(i * 2) + 1]);
-       }
-    }
-
     V3_Free(m);
     V3_Free(attr);
 }
@@ -437,8 +360,6 @@ static void v3_xml_free_attr(char **attr) {
 
 // returns a new empty v3_xml structure with the given root tag name
 static struct v3_xml * v3_xml_new(const char * name) {
-    static char * ent[] = { "lt;", "&#60;", "gt;", "&#62;", "quot;", "&#34;",
-                           "apos;", "&#39;", "amp;", "&#38;", NULL };
 
     struct v3_xml_root * root = (struct v3_xml_root *)V3_Malloc(sizeof(struct v3_xml_root));
     memset(root, 0, sizeof(struct v3_xml_root));
@@ -448,11 +369,6 @@ static struct v3_xml * v3_xml_new(const char * name) {
     root->xml.txt = "";
     memset(root->err, 0, V3_XML_ERRL);
 
-    root->ent = V3_Malloc(sizeof(ent));
-    memcpy(root->ent, ent, sizeof(ent));
-
-    root->xml.attr = empty_attrib_list;
-    root->attr = (char ***)(empty_attrib_list);
 
     return &root->xml;
 }
@@ -579,9 +495,7 @@ static struct v3_xml * parse_str(char * buf, size_t len) {
     char last_char; 
     char * tag_ptr;
     char ** attr; 
-    char ** tmp_attr = NULL; // initialize a to avoid compile warning
     int attr_idx;
-    int i, j;
 
     root->str_ptr = buf;
 
@@ -626,17 +540,7 @@ static struct v3_xml * parse_str(char * buf, size_t len) {
                *(buf++) = '\0';
            }
 
-           // check if attribute follows tag
-            if ((*buf) && (*buf != '/') && (*buf != '>')) {
-               // there is an attribute
-               // find attributes for correct tag
-                for ((i = 0); 
-                    ((tmp_attr = root->attr[i]) && 
-                     (strcasecmp(tmp_attr[0], tag_ptr) != 0)); 
-                    (i++)) ;
-               
-               // 'tmp_attr' now points to the attribute list associated with 'tag_ptr'
-           }
+       
 
            // attributes are name value pairs, 
            //     2nd to last entry is null  (end of list)
@@ -660,7 +564,7 @@ static struct v3_xml * parse_str(char * buf, size_t len) {
                                        (2 * sizeof(char *))), 
                                       ((attr_cnt * (2 * sizeof(char *))) + 
                                        (2 * sizeof(char *))));
-               
+
                    attr[last_idx] = tmp_realloc(attr[last_idx - 2], 
                                                 attr_cnt,
                                                 (attr_cnt + 1)); 
@@ -668,7 +572,6 @@ static struct v3_xml * parse_str(char * buf, size_t len) {
                    attr = V3_Malloc(4 * sizeof(char *)); 
                    attr[last_idx] = V3_Malloc(2);
                }
-               
 
                 attr[attr_idx] = buf; // set attribute name
                 attr[val_idx] = ""; // temporary attribute value
@@ -678,9 +581,9 @@ static struct v3_xml * parse_str(char * buf, size_t len) {
                 buf += strcspn(buf, V3_XML_WS "=/>");
 
                 if ((*buf == '=') || isspace(*buf)) {
-                    
+
                    *(buf++) = '\0'; // null terminate tag attribute name
-                   
+
                    // eat whitespace (and more multiple '=' ?)
                    buf += strspn(buf, V3_XML_WS "=");
 
@@ -702,20 +605,7 @@ static struct v3_xml * parse_str(char * buf, size_t len) {
                            return NULL;
                         }
 
-                        for (j = 1; 
-                            ( (tmp_attr) && (tmp_attr[j]) && 
-                              (strcasecmp(tmp_attr[j], attr[attr_idx]) != 0)); 
-                            j += 3);
-
-                        attr[val_idx] = v3_xml_decode(attr[val_idx], root->ent, 
-                                                     ((tmp_attr && tmp_attr[j]) ? 
-                                                      *tmp_attr[j + 2] : 
-                                                      ' '));
-                       
-                        if ( (attr[val_idx] < tag_ptr) || 
-                            (attr[val_idx] > buf) ) {
-                            attr[last_idx][attr_cnt - 1] = V3_XML_TXTM; // value malloced
-                       }
+                        attr[val_idx] = v3_xml_decode(attr[val_idx], ' ');
                     }
                 }
 
@@ -801,6 +691,11 @@ static struct v3_xml * parse_str(char * buf, size_t len) {
         *buf = '\0';
         tag_ptr = ++buf;
 
+       /* Eat leading whitespace */
+       while (*buf && isspace(*buf)) {
+           buf++;
+       }
+
         if (*buf && (*buf != '<')) { 
            // tag character content
             while (*buf && (*buf != '<')) {
@@ -849,8 +744,6 @@ struct v3_xml * v3_xml_parse(char * buf) {
 // free the memory allocated for the v3_xml structure
 void v3_xml_free(struct v3_xml * xml) {
     struct v3_xml_root * root = (struct v3_xml_root *)xml;
-    int i, j;
-    char **a, *s;
 
     if (xml == NULL) {
         return;
@@ -861,36 +754,13 @@ void v3_xml_free(struct v3_xml * xml) {
 
     if (xml->parent == NULL) { 
        // free root tag allocations
-        
-       for (i = 10; root->ent[i]; i += 2) {
-           // 0 - 9 are default entites (<>&"')
-            if ((s = root->ent[i + 1]) < root->tmp_start || s > root->tmp_end) {
-               V3_Free(s);
-           }
-       }
-
-       V3_Free(root->ent); // free list of general entities
-
-        for (i = 0; (a = root->attr[i]); i++) {
-            for (j = 1; a[j++]; j += 2) {
-               // free malloced attribute values
-                if (a[j] && (a[j] < root->tmp_start || a[j] > root->tmp_end)) {
-                   V3_Free(a[j]);
-               }
-           }
-            V3_Free(a);
-        }
-
-        if (root->attr[0]) {
-           // free default attribute list
-           V3_Free(root->attr);
-       }
-
        V3_Free(root->str_ptr); // malloced xml data
     }
 
     v3_xml_free_attr(xml->attr); // tag attributes
 
+
+
     if ((xml->flags & V3_XML_TXTM)) {
        // character content
        V3_Free(xml->txt); 
@@ -908,6 +778,9 @@ void v3_xml_free(struct v3_xml * xml) {
 
 
 
+/* Adding XML data */
+
+
 
 
 // sets the character content for the given tag and returns the tag
@@ -1129,8 +1002,8 @@ static char *ampencode(const char *s, size_t len, char **dst, size_t *dlen,
 // its length excedes max. start is the location of the previous tag in the
 // parent tag's character content. Returns *s.
 static char *toxml_r(struct v3_xml * xml, char **s, size_t *len, size_t *max,
-                    size_t start, char ***attr) {
-    int i, j;
+                    size_t start) {
+    int i;
     char *txt = (xml->parent) ? xml->parent->txt : "";
     size_t off = 0;
 
@@ -1158,23 +1031,10 @@ static char *toxml_r(struct v3_xml * xml, char **s, size_t *len, size_t *max,
         *len += sprintf(*s + *len, "\"");
     }
 
-    for (i = 0; attr[i] && strcmp(attr[i][0], xml->name); i++);
-    for (j = 1; attr[i] && attr[i][j]; j += 3) { // default attributes
-        if (! attr[i][j + 1] || v3_xml_attr(xml, attr[i][j]) != attr[i][j + 1])
-            continue; // skip duplicates and non-values
-        while (*len + strlen(attr[i][j]) + 7 > *max) {
-           // reallocate s
-            *s = tmp_realloc(*s, *max, *max + V3_XML_BUFSIZE);
-           *max += V3_XML_BUFSIZE;
-       }
-
-        *len += sprintf(*s + *len, " %s=\"", attr[i][j]);
-        ampencode(attr[i][j + 1], -1, s, len, max, 1);
-        *len += sprintf(*s + *len, "\"");
-    }
+  
     *len += sprintf(*s + *len, ">");
 
-    *s = (xml->child) ? toxml_r(xml->child, s, len, max, 0, attr) //child
+    *s = (xml->child) ? toxml_r(xml->child, s, len, max, 0) //child
                       : ampencode(xml->txt, -1, s, len, max, 0);  //data
     
     while (*len + strlen(xml->name) + 4 > *max) {
@@ -1186,7 +1046,7 @@ static char *toxml_r(struct v3_xml * xml, char **s, size_t *len, size_t *max,
     *len += sprintf(*s + *len, "</%s>", xml->name); // close tag
 
     while (txt[off] && off < xml->off) off++; // make sure off is within bounds
-    return (xml->ordered) ? toxml_r(xml->ordered, s, len, max, off, attr)
+    return (xml->ordered) ? toxml_r(xml->ordered, s, len, max, off)
                           : ampencode(txt + off, -1, s, len, max, 0);
 }
 
@@ -1204,7 +1064,7 @@ char * v3_xml_tostr(struct v3_xml * xml) {
 
 
     xml->parent = xml->ordered = NULL;
-    s = toxml_r(xml, &s, &len, &max, 0, root->attr);
+    s = toxml_r(xml, &s, &len, &max, 0);
     xml->parent = p;
     xml->ordered = o;
 
index 20c0c5f..f1d0939 100644 (file)
@@ -549,7 +549,7 @@ int v3_deinit_vmx_vmcs(struct guest_info * core) {
     struct vmx_data * vmx_state = core->vmm_data;
 
     V3_FreePages((void *)(vmx_state->vmcs_ptr_phys), 1);
-    V3_FreePages(vmx_state->msr_area, 1);
+    V3_FreePages(V3_PAddr(vmx_state->msr_area), 1);
 
     V3_Free(vmx_state);
 
@@ -993,6 +993,7 @@ int v3_reset_vmx_vm_core(struct guest_info * core, addr_t rip) {
 
 
 void v3_init_vmx_cpu(int cpu_id) {
+    addr_t vmx_on_region = 0;
 
     if (cpu_id == 0) {
        if (v3_init_vmx_hw(&hw_info) == -1) {
@@ -1005,17 +1006,18 @@ void v3_init_vmx_cpu(int cpu_id) {
 
 
     // Setup VMXON Region
-    host_vmcs_ptrs[cpu_id] = allocate_vmcs();
+    vmx_on_region = allocate_vmcs();
 
-    PrintDebug("VMXON pointer: 0x%p\n", (void *)host_vmcs_ptrs[cpu_id]);
 
-    if (vmx_on(host_vmcs_ptrs[cpu_id]) == VMX_SUCCESS) {
+    if (vmx_on(vmx_on_region) == VMX_SUCCESS) {
         V3_Print("VMX Enabled\n");
+       host_vmcs_ptrs[cpu_id] = vmx_on_region;
     } else {
-        PrintError("VMX initialization failure\n");
-        return;
+        V3_Print("VMX already enabled\n");
+       V3_FreePages((void *)vmx_on_region, 1);
     }
-    
+
+    PrintDebug("VMXON pointer: 0x%p\n", (void *)host_vmcs_ptrs[cpu_id]);    
 
     {
        struct vmx_sec_proc_ctrls sec_proc_ctrls;
@@ -1038,5 +1040,16 @@ void v3_init_vmx_cpu(int cpu_id) {
 void v3_deinit_vmx_cpu(int cpu_id) {
     extern v3_cpu_arch_t v3_cpu_types[];
     v3_cpu_types[cpu_id] = V3_INVALID_CPU;
-    V3_FreePages((void *)host_vmcs_ptrs[cpu_id], 1);
+
+    if (host_vmcs_ptrs[cpu_id] != 0) {
+       V3_Print("Disabling VMX\n");
+
+       if (vmx_off() != VMX_SUCCESS) {
+           PrintError("Error executing VMXOFF\n");
+       }
+
+       V3_FreePages((void *)host_vmcs_ptrs[cpu_id], 1);
+
+       host_vmcs_ptrs[cpu_id] = 0;
+    }
 }
index 5af3122..be86fe2 100644 (file)
@@ -102,6 +102,9 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf
                     PrintError("Page fault in unimplemented paging mode\n");
                     return -1;
                 }
+           } else if ((uint8_t)exit_info->int_info == 2) {
+               // NMI. Don't do anything
+               V3_Print("NMI Exception Received\n");
             } else {
                 PrintError("Unknown exception: 0x%x\n", (uint8_t)exit_info->int_info);
                 v3_print_GPRs(info);
index b82c905..4669029 100644 (file)
@@ -10,7 +10,7 @@
  * Copyright (c) 2010, Lei Xia <lxia@northwestern.edu> 
  * Copyright (c) 2009, Yuan Tang <ytang@northwestern.edu>  
  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
+ * All rights reserved
  *
  * Author: Lei Xia <lxia@northwestern.edu>
  *        Yuan Tang <ytang@northwestern.edu>
@@ -24,6 +24,8 @@
 #include <vnet/vnet_host.h>
 #include <vnet/vnet_vmm.h>
 
+#include <palacios/vmm_queue.h>
+
 #ifndef V3_CONFIG_DEBUG_VNET
 #undef Vnet_Debug
 #define Vnet_Debug(fmt, args...)
@@ -43,9 +45,15 @@ struct vnet_dev {
     uint8_t mac_addr[ETH_ALEN];
     struct v3_vm_info * vm;
     struct v3_vnet_dev_ops dev_ops;
+
+    int poll;
+
+#define VNET_MAX_QUOTE 64
+    int quote;
+       
     void * private_data;
 
-    struct list_head node;
+    struct list_head node;\r
 } __attribute__((packed));
 
 
@@ -88,13 +96,6 @@ struct queue_entry{
     uint32_t size_alloc;
 };
 
-#define VNET_QUEUE_SIZE 1024
-struct vnet_queue {
-    struct queue_entry buf[VNET_QUEUE_SIZE];
-    int head, tail;
-    int count;
-    vnet_lock_t lock;
-};
 
 static struct {
     struct list_head routes;
@@ -112,9 +113,10 @@ static struct {
     vnet_lock_t lock;
     struct vnet_stat stats;
 
-    struct vnet_thread * pkt_flush_thread;
+   /* device queue that are waiting to be polled */
+    struct v3_queue * poll_devs;
 
-    struct vnet_queue pkt_q;
+    struct vnet_thread * pkt_flush_thread;
 
     struct hashtable * route_cache;
 } vnet_state;
@@ -469,17 +471,17 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt) {
 }
 
 
-int vnet_tx_one_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
+int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
     struct route_list * matched_routes = NULL;
     unsigned long flags;
     int i;
 
     int cpu = V3_Get_CPU();
     Vnet_Print(2, "VNET/P Core: cpu %d: pkt (size %d, src_id:%d, src_type: %d, dst_id: %d, dst_type: %d)\n",
-                 cpu, pkt->size, pkt->src_id, 
-                 pkt->src_type, pkt->dst_id, pkt->dst_type);
+              cpu, pkt->size, pkt->src_id, 
+              pkt->src_type, pkt->dst_id, pkt->dst_type);
     if(net_debug >= 4){
-           v3_hexdump(pkt->data, pkt->size, NULL, 0);
+       v3_hexdump(pkt->data, pkt->size, NULL, 0);
     }
 
     flags = vnet_lock_irqsave(vnet_state.lock);
@@ -546,66 +548,8 @@ int vnet_tx_one_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
 }
 
 
-static int vnet_pkt_enqueue(struct v3_vnet_pkt * pkt){
-    unsigned long flags;
-    struct queue_entry * entry;
-    struct vnet_queue * q = &(vnet_state.pkt_q);
-    uint16_t num_pages;
-
-    flags = vnet_lock_irqsave(q->lock);
-
-    if (q->count >= VNET_QUEUE_SIZE){
-       Vnet_Print(1, "VNET Queue overflow!\n");
-       vnet_unlock_irqrestore(q->lock, flags);
-       return -1;
-    }
-       
-    q->count ++;
-    entry = &(q->buf[q->tail++]);
-    q->tail %= VNET_QUEUE_SIZE;
-       
-    vnet_unlock_irqrestore(q->lock, flags);
-
-    /* this is ugly, but should happen very unlikely */
-    while(entry->use);
-
-    if(entry->size_alloc < pkt->size){
-       if(entry->data != NULL){
-           Vnet_FreePages(Vnet_PAddr(entry->data), (entry->size_alloc / PAGE_SIZE));
-           entry->data = NULL;
-       }
-
-       num_pages = 1 + (pkt->size / PAGE_SIZE);
-       entry->data = Vnet_VAddr(Vnet_AllocPages(num_pages));
-       if(entry->data == NULL){
-           return -1;
-       }
-       entry->size_alloc = PAGE_SIZE * num_pages;
-    }
-
-    entry->pkt.data = entry->data;
-    memcpy(&(entry->pkt), pkt, sizeof(struct v3_vnet_pkt));
-    memcpy(entry->data, pkt->data, pkt->size);
-
-    entry->use = 1;
-
-    return 0;
-}
-
-
-int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data, int synchronize) {
-    if(synchronize){
-       vnet_tx_one_pkt(pkt, NULL);
-    }else {
-       vnet_pkt_enqueue(pkt);
-       Vnet_Print(2, "VNET/P Core: Put pkt into Queue: pkt size %d\n", pkt->size);
-    }
-       
-    return 0;
-}
-
 int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac, 
-                   struct v3_vnet_dev_ops *ops,
+                   struct v3_vnet_dev_ops *ops, int quote, int poll_state,
                    void * priv_data){
     struct vnet_dev * new_dev = NULL;
     unsigned long flags;
@@ -622,6 +566,8 @@ int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac,
     new_dev->private_data = priv_data;
     new_dev->vm = vm;
     new_dev->dev_id = 0;
+    new_dev->quote = quote<VNET_MAX_QUOTE?quote:VNET_MAX_QUOTE;
+    new_dev->poll = poll_state;
 
     flags = vnet_lock_irqsave(vnet_state.lock);
 
@@ -758,41 +704,39 @@ void v3_vnet_del_bridge(uint8_t type) {
 }
 
 
+/* can be instanieoued to multiple threads
+  * that runs on multiple cores 
+  * or it could be running on a dedicated side core
+  */
 static int vnet_tx_flush(void *args){
-    unsigned long flags;
-    struct queue_entry * entry;
-    struct vnet_queue * q = &(vnet_state.pkt_q);
+    struct vnet_dev * dev = NULL;
+    int ret;
 
-    Vnet_Print(0, "VNET/P Handing Pkt Thread Starting ....\n");
+    Vnet_Print(0, "VNET/P Polling Thread Starting ....\n");
 
     /* we need thread sleep/wakeup in Palacios */
     while(!vnet_thread_should_stop()){
-       flags = vnet_lock_irqsave(q->lock);
-
-       if (q->count <= 0){
-           vnet_unlock_irqrestore(q->lock, flags);
-           Vnet_Yield();
-       }else {
-           q->count --;
-           entry = &(q->buf[q->head++]);
-           q->head %= VNET_QUEUE_SIZE;
-
-           vnet_unlock_irqrestore(q->lock, flags);
+       dev = (struct vnet_dev *)v3_dequeue(vnet_state.poll_devs);
+       if(dev != NULL){
+           if(dev->poll && dev->dev_ops.poll != NULL){
+               ret = dev->dev_ops.poll(dev->vm, dev->quote, dev->private_data);
 
-           /* this is ugly, but should happen very unlikely */
-           while(!entry->use);
-           vnet_tx_one_pkt(&(entry->pkt), NULL);
-
-           /* asynchronizely release allocated memory for buffer entry here */     
-           entry->use = 0;
+               if (ret < 0){
+                   PrintDebug("VNET/P: poll from device %p error!\n", dev);
+               }
 
-           Vnet_Print(2, "vnet_tx_flush: pkt (size %d)\n", entry->pkt.size);   
+               v3_enqueue(vnet_state.poll_devs, (addr_t)dev); 
+           }
+       }else { /* no device needs to be polled */
+          /* sleep here? */
+           Vnet_Yield();
        }
     }
 
     return 0;
 }
 
+
 int v3_init_vnet() {
     memset(&vnet_state, 0, sizeof(vnet_state));
        
@@ -803,20 +747,20 @@ int v3_init_vnet() {
     vnet_state.num_routes = 0;
 
     if (vnet_lock_init(&(vnet_state.lock)) == -1){
-        PrintError("VNET/P Core: Fails to initiate lock\n");
+        PrintError("VNET/P: Fails to initiate lock\n");
     }
 
     vnet_state.route_cache = vnet_create_htable(0, &hash_fn, &hash_eq);
     if (vnet_state.route_cache == NULL) {
-        PrintError("VNET/P Core: Fails to initiate route cache\n");
+        PrintError("VNET/P: Fails to initiate route cache\n");
         return -1;
     }
 
-    vnet_lock_init(&(vnet_state.pkt_q.lock));
+    vnet_state.poll_devs = v3_create_queue();
 
-    vnet_state.pkt_flush_thread = vnet_start_thread(vnet_tx_flush, NULL, "VNET_Pkts");
+    vnet_state.pkt_flush_thread = vnet_start_thread(vnet_tx_flush, NULL, "vnetd");
 
-    Vnet_Debug("VNET/P Core is initiated\n");
+    Vnet_Debug("VNET/P is initiated\n");
 
     return 0;
 }