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.


minor changes to organization
Kyle Hale [Fri, 17 Jun 2011 19:51:21 +0000 (14:51 -0500)]
176 files changed:
Kconfig
Makefile
linux_module/Makefile
linux_module/ld.cmd [moved from linux_module/link.cmd with 76% similarity]
linux_module/ld.symmod.cmd [new file with mode: 0644]
linux_module/palacios-debugfs.h [deleted file]
linux_module/palacios-dev.c
linux_module/palacios-graphics-console.c [new file with mode: 0644]
linux_module/palacios-graphics-console.h [new file with mode: 0644]
linux_module/palacios-hashtable.c [new file with mode: 0644]
linux_module/palacios-hashtable.h [new file with mode: 0644]
linux_module/palacios-host-dev-user.h [new file with mode: 0644]
linux_module/palacios-host-dev.c [new file with mode: 0644]
linux_module/palacios-host-dev.h [new file with mode: 0644]
linux_module/palacios-inspector.c [moved from linux_module/palacios-debugfs.c with 80% similarity]
linux_module/palacios-inspector.h [new file with mode: 0644]
linux_module/palacios-keyed-stream.c [new file with mode: 0644]
linux_module/palacios-keyed-stream.h [new file with mode: 0644]
linux_module/palacios-packet.c
linux_module/palacios-packet.h
linux_module/palacios-serial.c [deleted file]
linux_module/palacios-socket.c
linux_module/palacios-socket.h
linux_module/palacios-stream.c
linux_module/palacios-stream.h
linux_module/palacios-vm.c
linux_module/palacios-vnet-brg.c [new file with mode: 0644]
linux_module/palacios-vnet-ctrl.c [new file with mode: 0644]
linux_module/palacios-vnet.c
linux_module/palacios-vnet.h
linux_module/palacios.c
linux_module/palacios.h
linux_usr/Makefile
linux_usr/v3_os_debug.c [new file with mode: 0644]
linux_usr/v3_user_host_dev.c [new file with mode: 0644]
linux_usr/v3_user_host_dev.h [new file with mode: 0644]
linux_usr/v3_user_host_dev_example.c [new file with mode: 0644]
linux_usr/x0vncserver [new file with mode: 0755]
palacios/include/palacios/svm.h
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmcs.h
palacios/include/palacios/vmm.h
palacios/include/palacios/vmm_barrier.h
palacios/include/palacios/vmm_ctrl_regs.h
palacios/include/palacios/vmm_decoder.h
palacios/include/palacios/vmm_dev_mgr.h
palacios/include/palacios/vmm_ethernet.h
palacios/include/palacios/vmm_instr_decoder.h
palacios/include/palacios/vmm_mptable.h [deleted file]
palacios/include/palacios/vmm_paging.h
palacios/include/palacios/vmm_shadow_paging.h
palacios/include/palacios/vmm_symbiotic.h
palacios/include/palacios/vmm_telemetry.h
palacios/include/palacios/vmm_time.h
palacios/include/palacios/vmm_types.h
palacios/include/palacios/vmx.h
palacios/include/palacios/vmx_assist.h
palacios/include/palacios/vmx_ept.h
palacios/include/palacios/vmx_handler.h
palacios/include/palacios/vmx_hw_info.h
palacios/include/palacios/vmx_lowlevel.h
palacios/include/vnet/vnet.h [moved from palacios/include/palacios/vmm_vnet.h with 86% similarity]
palacios/include/vnet/vnet_base.h [copied from palacios/include/palacios/vmm_instrument.h with 52% similarity]
palacios/include/vnet/vnet_hashtable.h [new file with mode: 0644]
palacios/include/vnet/vnet_host.h [new file with mode: 0644]
palacios/include/vnet/vnet_vmm.h [moved from palacios/include/palacios/vmm_instrument.h with 51% similarity]
palacios/lib/i386/Makefile
palacios/lib/i386/v3-xed-compat.c
palacios/lib/x86_64/Makefile
palacios/src/devices/8254.c
palacios/src/devices/8259a.c
palacios/src/devices/Kconfig
palacios/src/devices/Makefile
palacios/src/devices/apic.c
palacios/src/devices/cga.c
palacios/src/devices/filedisk.c
palacios/src/devices/generic.c
palacios/src/devices/ide.c
palacios/src/devices/io_apic.c
palacios/src/devices/keyboard.c
palacios/src/devices/lnx_virtio_blk.c
palacios/src/devices/lnx_virtio_nic.c
palacios/src/devices/lnx_virtio_vnet.c
palacios/src/devices/mcheck.c
palacios/src/devices/mptable.c [moved from palacios/src/palacios/vmm_mptable.c with 97% similarity]
palacios/src/devices/ne2k.c
palacios/src/devices/netdisk.c
palacios/src/devices/nic_bridge.c
palacios/src/devices/nvram.c
palacios/src/devices/pci.c
palacios/src/devices/pci_front.c
palacios/src/devices/ramdisk.c
palacios/src/devices/rtl8139.c
palacios/src/devices/serial.c
palacios/src/devices/swapbypass_cache.c
palacios/src/devices/swapbypass_cache2.c
palacios/src/devices/vga.c
palacios/src/devices/vnet_nic.c
palacios/src/extensions/Kconfig
palacios/src/extensions/Makefile
palacios/src/extensions/ext_inspector.c
palacios/src/extensions/ext_vtime.c
palacios/src/interfaces/Makefile
palacios/src/interfaces/null.c [new file with mode: 0644]
palacios/src/palacios/Makefile
palacios/src/palacios/mmu/Makefile
palacios/src/palacios/mmu/vmm_shdw_pg_cache.c
palacios/src/palacios/mmu/vmm_shdw_pg_cache_32.h
palacios/src/palacios/mmu/vmm_shdw_pg_kvm.c
palacios/src/palacios/mmu/vmm_shdw_pg_kvm_32.h
palacios/src/palacios/mmu/vmm_shdw_pg_kvm_32pae.h
palacios/src/palacios/mmu/vmm_shdw_pg_kvm_64.h
palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass.c
palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_32.h
palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_64.h
palacios/src/palacios/mmu/vmm_shdw_pg_tlb.c
palacios/src/palacios/mmu/vmm_shdw_pg_tlb_32.h
palacios/src/palacios/mmu/vmm_shdw_pg_tlb_64.h
palacios/src/palacios/svm.c
palacios/src/palacios/svm_handler.c
palacios/src/palacios/svm_io.c
palacios/src/palacios/vm_guest.c
palacios/src/palacios/vm_guest_mem.c
palacios/src/palacios/vmcs.c
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_barrier.c
palacios/src/palacios/vmm_binaries.S
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_config_class.h
palacios/src/palacios/vmm_cpuid.c
palacios/src/palacios/vmm_ctrl_regs.c
palacios/src/palacios/vmm_decoder.c
palacios/src/palacios/vmm_dev_mgr.c
palacios/src/palacios/vmm_direct_paging.c
palacios/src/palacios/vmm_direct_paging_32.h
palacios/src/palacios/vmm_direct_paging_32pae.h
palacios/src/palacios/vmm_direct_paging_64.h
palacios/src/palacios/vmm_emulator.c
palacios/src/palacios/vmm_execve_hook.c [deleted file]
palacios/src/palacios/vmm_extensions.c
palacios/src/palacios/vmm_halt.c
palacios/src/palacios/vmm_instrument.c [deleted file]
palacios/src/palacios/vmm_intr.c
palacios/src/palacios/vmm_io.c
palacios/src/palacios/vmm_linux_syscall_map.c [deleted file]
palacios/src/palacios/vmm_mem.c
palacios/src/palacios/vmm_mem_hook.c
palacios/src/palacios/vmm_mpi_accel.c [deleted file]
palacios/src/palacios/vmm_paging.c
palacios/src/palacios/vmm_paging_debug.h
palacios/src/palacios/vmm_process_environment.c [deleted file]
palacios/src/palacios/vmm_queue.c
palacios/src/palacios/vmm_shadow_paging.c
palacios/src/palacios/vmm_sprintf.c
palacios/src/palacios/vmm_string.c
palacios/src/palacios/vmm_symbiotic.c
palacios/src/palacios/vmm_symspy.c
palacios/src/palacios/vmm_syscall_hijack.c [deleted file]
palacios/src/palacios/vmm_telemetry.c
palacios/src/palacios/vmm_time.c
palacios/src/palacios/vmm_v3dec.c
palacios/src/palacios/vmm_xed.c
palacios/src/palacios/vmm_xml.c
palacios/src/palacios/vmx.c
palacios/src/palacios/vmx_assist.c
palacios/src/palacios/vmx_ctrl_regs.c
palacios/src/palacios/vmx_ept.c
palacios/src/palacios/vmx_handler.c
palacios/src/palacios/vmx_hw_info.c
palacios/src/palacios/vmx_io.c
palacios/src/vnet/Makefile [new file with mode: 0644]
palacios/src/vnet/null.c [new file with mode: 0644]
palacios/src/vnet/vnet_core.c [moved from palacios/src/palacios/vmm_vnet_core.c with 68% similarity]
palacios/src/vnet/vnet_hashtable.c [new file with mode: 0644]
palacios/src/vnet/vnet_host.c [new file with mode: 0644]
scripts/kconfig/confdata.c

diff --git a/Kconfig b/Kconfig
index 3c98783..acf7ebf 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -163,13 +163,6 @@ config EXPERIMENTAL
          The purpose of this option is to allow features under development to be committed to the mainline
          to more easily track changes and provide access to multiple developers
 
-config VNET
-        depends on EXPERIMENTAL
-        bool "Enable Vnet in Palacios"
-        default n
-        help
-          Enable the Vnet in Palacios
-
 
 config INSPECTOR
        bool "Enable VM inspection"
@@ -178,50 +171,6 @@ config INSPECTOR
        help 
          Enable inspection framework for vm internal state
 
-config SW_INTERRUPTS
-    bool "Enable interception and hooking of software interrupts"
-    depends on EXPERIMENTAL
-    default n
-    help
-      This feature will cause the VMM to intercept the execution
-      of software interrupts (i.e. the INTn instruction) and enable
-      any INT vector to be hooked
-
-config SWINTR_PASSTHROUGH
-    bool "Hook all unhandled sofware interrupts for passthrough"
-    depends on SW_INTERRUPTS
-    default n
-    help
-      If enabled, this will cause all software interrupts 
-      (INT instruction vectors) to be hooked for passthrough.
-      May reduce performance but useful for debugging.
-
-config SYSCALL_HIJACK
-    bool "Enable System Call Hijacking"
-    depends on SW_INTERRUPTS
-    default n
-    help
-      Enable the VMM to hijack system calls executed by the guest.
-      If enabled, the VMM will hook execution of INT 80
-      (support for Fast-System Calls coming soon)
-
-config SYSCALL_PASSTHROUGH
-    bool "Hook all unhandled system calls for passthrough"
-    depends on SYSCALL_HIJACK
-    default n
-    help
-      If enabled, this option will cause all system calls
-      that are not explicitly hooked to be hooked for 
-      passthrough. This is useful for debugging.
-
-config HIJACK_SYSCALL_MSR
-    bool "Intercept Syscall-related MSR reads & writes"
-    depends on SYSCALL_HIJACK 
-    default n
-    help
-      Allow the VMM to intercept reads and writes to MSRs
-      related to SYSCALL and SYSENTER instructions. Specifically,
-      it will intercept R/W to STAR, CSTAR, and LSTAR.
 
 endmenu
 
@@ -336,7 +285,23 @@ menuconfig SYMMOD
 
 endmenu
 
+menu "VNET"
 
+config VNET
+        bool "Enable Vnet in Palacios"
+        default n
+        help
+          Enable the Vnet in Palacios
+
+config DEBUG_VNET
+        depends on VNET
+        bool "Enable Vnet Debug in Palacios"
+        default n
+        help
+          Enable the Vnet debug in Palacios
+
+
+endmenu
 
 menu "Debug configuration"
 
@@ -446,12 +411,6 @@ config DEBUG_DEV_MGR
        help 
          This turns on debugging for the device manager
 
-config DEBUG_VNET
-        depends on EXPERIMENTAL && VNET
-        bool "Enable Vnet Debug in Palacios"
-        default n
-        help
-          Enable the Vnet debug in Palacios
 
 config DEBUG_SYSCALL_HIJACK
         bool "Enable Syscall Hijack Debug in Palacios"
index ed13298..1b14317 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -436,6 +436,7 @@ libs-y              := palacios/lib/$(ARCH)/
 devices-y       := palacios/src/devices/
 interfaces-y    := palacios/src/interfaces/
 extensions-y    := palacios/src/extensions/
+vnet-y          := palacios/src/vnet/
 modules-y       := modules/
 
 
@@ -467,7 +468,7 @@ palacios/include/autoconf.h: ;
 endif
 
 
-ifdef CONFIG_LINUX
+ifdef V3_CONFIG_LINUX
 DEFAULT_EXTRA_TARGETS=linux_module
 else
 DEFAULT_EXTRA_TARGETS=
@@ -480,24 +481,24 @@ endif
 all: palacios $(DEFAULT_EXTRA_TARGETS)
 
 
-ifdef CONFIG_LINUX
+ifdef V3_CONFIG_LINUX
 CFLAGS          += -mcmodel=kernel 
 else
 CFLAGS          += -fPIC
 endif
 
-ifdef CONFIG_FRAME_POINTER
+ifdef V3_CONFIG_FRAME_POINTER
 CFLAGS         += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
 else
 CFLAGS         += -fomit-frame-pointer
 endif
 
 
-ifdef CONFIG_UNWIND_INFO
+ifdef V3_CONFIG_UNWIND_INFO
 CFLAGS         += -fasynchronous-unwind-tables
 endif
 
-ifdef CONFIG_DEBUG_INFO
+ifdef V3_CONFIG_DEBUG_INFO
 CFLAGS         += -g
 else 
 CFLAGS          += -O
@@ -530,7 +531,7 @@ export      INSTALL_PATH ?= /build
 
 
 palacios-dirs  := $(patsubst %/,%,$(filter %/,  \
-                    $(core-y) $(devices-y) $(interfaces-y) $(extensions-y) $(libs-y)) $(modules-y))
+                    $(core-y) $(devices-y) $(interfaces-y) $(extensions-y) $(vnet-y) $(libs-y)) $(modules-y))
 
 
 
@@ -541,7 +542,7 @@ palacios-dirs       := $(patsubst %/,%,$(filter %/,  \
 
 palacios-cleandirs := $(sort $(palacios-dirs) $(patsubst %/,%,$(filter %/, \
                        $(core-n) $(core-) $(devices-n) $(devices-) \
-                       $(interfaces-n) $(interfaces-) $(extensions-n) $(extensions-) $(modules-n) $(modules-))))
+                       $(interfaces-n) $(interfaces-) $(extensions-n) $(extensions-) $(vnet-n) $(vnet-) $(modules-n) $(modules-))))
 
 
 
@@ -550,6 +551,7 @@ devices-y   := $(patsubst %/, %/built-in.o, $(devices-y))
 interfaces-y    := $(patsubst %/, %/built-in.o, $(interfaces-y))
 extensions-y    := $(patsubst %/, %/built-in.o, $(extensions-y))
 libs-y         := $(patsubst %/, %/built-in.o, $(libs-y))
+vnet-y          := $(patsubst %/, %/built-in.o, $(vnet-y))
 modules-y       := $(patsubst %/, %/built-in.o, $(modules-y))
 #lnxmod-y        := $(patsubst %/, %/built-in.o, $(lnxmod-y))
 
@@ -575,7 +577,7 @@ modules-y       := $(patsubst %/, %/built-in.o, $(modules-y))
 
 
 
-palacios := $(core-y) $(devices-y) $(interfaces-y) $(extensions-y) $(libs-y) $(modules-y)
+palacios := $(core-y) $(devices-y) $(interfaces-y) $(extensions-y) $(vnet-y) $(libs-y) $(modules-y)
 
 
 # Rule to link palacios - also used during CONFIG_CONFIGKALLSYMS
@@ -621,7 +623,7 @@ palacios: libv3vee.a
 
 
 linux_module/v3vee.ko: linux_module/*.c linux_module/*.h libv3vee.a
-       cd linux_module/ && make CONFIG_LINUX_KERN=$(CONFIG_LINUX_KERN)
+       cd linux_module/ && make
        cp linux_module/v3vee.ko v3vee.ko
 
 
@@ -941,10 +943,10 @@ target-dir = $(dir $@)
 
 # Modules
 / %/: prepare scripts FORCE
-       $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+       $(Q)$(MAKE) KBUILD_MODULES=$(if $(V3_CONFIG_MODULES),1) \
        $(build)=$(build-dir)
 %.ko: prepare scripts FORCE
-       $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1)   \
+       $(Q)$(MAKE) KBUILD_MODULES=$(if $(V3_CONFIG_MODULES),1)   \
        $(build)=$(build-dir) $(@:.ko=.o)
        $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
 
index 181df3c..b3bd558 100644 (file)
@@ -1,32 +1,66 @@
+include $(PWD)/../.config
 
-LDFLAGS += --whole-archive  --script=$(PWD)/link.cmd
+LDFLAGS += --whole-archive  --script=$(PWD)/ld.cmd
 
-EXTRA_CFLAGS  += -I$(PWD)/../palacios/include/ -DMODULE=1 -D__KERNEL__=1
+ifdef V3_CONFIG_SYMMOD
+LDFLAGS += --script=$(PWD)/ld.symmod.cmd
+endif
+
+EXTRA_CFLAGS  += -I$(PWD)/../palacios/include/ -include autoconf.h -DMODULE=1 -D__KERNEL__=1
 
 
-v3vee-objs:=   palacios.o \
+v3vee-objs :=  palacios.o \
                palacios-dev.o \
                palacios-vm.o \
-               palacios-file.o \
-               palacios-console.o \
                palacios-mm.o \
-               palacios-serial.o \
-               palacios-stream.o \
                palacios-queue.o \
-               palacios-ringbuffer.o \
-               palacios-debugfs.o
+               palacios-hashtable.o
+
+ifdef V3_CONFIG_CONSOLE
+       v3vee-objs +=   palacios-console.o
+endif
+
+ifdef V3_CONFIG_FILE
+       v3vee-objs +=   palacios-file.o 
+endif
 
+ifdef V3_CONFIG_STREAM
+       v3vee-objs +=   palacios-stream.o \
+                       palacios-ringbuffer.o
+endif
 
-ifdef CONFIG_PALACIOS_VNET
-               v3vee-objs += palacios-vnet.o           
+ifdef V3_CONFIG_EXT_INSPECTOR
+       v3vee-objs += palacios-inspector.o
 endif
-ifdef CONFIG_PALACIOS_PACKET
-               v3vee-objs += palacios-packet.o
+
+ifdef V3_CONFIG_VNET
+       v3vee-objs +=   palacios-vnet.o \
+                       palacios-vnet-ctrl.o   \
+                       palacios-vnet-brg.o
 endif
-ifdef CONFIG_PALACIOS_SOCKET
-               v3vee-objs += palacios-socket.o
+
+ifdef V3_CONFIG_PACKET
+       v3vee-objs += palacios-packet.o
 endif
 
+ifdef V3_CONFIG_SOCKET
+       v3vee-objs += palacios-socket.o
+endif
+
+ifdef V3_CONFIG_KEYED_STREAMS
+       v3vee-objs += palacios-keyed-stream.o
+endif
+
+ifdef V3_CONFIG_HOST_DEVICE
+       v3vee-objs += palacios-host-dev.o
+endif
+
+ifdef V3_CONFIG_GRAPHICS_CONSOLE
+       v3vee-objs += palacios-graphics-console.o
+endif
+
+
+
 v3vee-objs += ../libv3vee.a 
 
 
@@ -36,10 +70,10 @@ obj-m := v3vee.o
 
 
 all:
-       $(MAKE) -C $(CONFIG_LINUX_KERN) M=$(PWD) modules
+       $(MAKE) -C $(V3_CONFIG_LINUX_KERN) M=$(PWD) modules
 
 
 
 clean:
-       $(MAKE) -C $(CONFIG_LINUX_KERN) M=$(PWD) clean
+       $(MAKE) -C $(V3_CONFIG_LINUX_KERN) M=$(PWD) clean
 
similarity index 76%
rename from linux_module/link.cmd
rename to linux_module/ld.cmd
index 6c014d8..7dd7747 100644 (file)
@@ -8,13 +8,6 @@ SECTIONS
 
        }
        
-/*     _v3_capsules :
-       {
-               __start__v3_capsules = .;
-               *(_v3_capsules);
-               __stop__v3_capsules = .;
-       }
-*/
        _v3_shdw_pg_impls :
        {
                __start__v3_shdw_pg_impls = .;
diff --git a/linux_module/ld.symmod.cmd b/linux_module/ld.symmod.cmd
new file mode 100644 (file)
index 0000000..ea46409
--- /dev/null
@@ -0,0 +1,10 @@
+SECTIONS
+{
+       _v3_capsules :
+       {
+               __start__v3_capsules = .;
+               *(_v3_capsules);
+               __stop__v3_capsules = .;
+       }
+}
+
diff --git a/linux_module/palacios-debugfs.h b/linux_module/palacios-debugfs.h
deleted file mode 100644 (file)
index 1caad52..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* 
- * DebugFS interface
- * (c) Jack Lange, 2011
- */
-
-#include "palacios.h"
-
-int palacios_init_debugfs( void );
-int palacios_deinit_debugfs( void );
-
-
-
-int dfs_register_vm(struct v3_guest * guest);
-
index e1143f8..cf8e0fe 100644 (file)
 #include "palacios-vnet.h"
 #include "palacios-packet.h"
 
-#ifdef CONFIG_DEBUG_FS
-#include "palacios-debugfs.h"
+#ifdef V3_CONFIG_EXT_INSPECTOR
+#include "palacios-inspector.h"
 #endif
 
+#ifdef V3_CONFIG_KEYED_STREAMS
+#include "palacios-keyed-stream.h"
+#endif
+
+
 MODULE_LICENSE("GPL");
 
 int mod_allocs = 0;
@@ -56,7 +61,7 @@ static int register_vm( void ) {
     for (i = 0; i < sizeof(v3_minor_map); i++) {
        if (v3_minor_map[i] != 0xff) {
            for (j = 0; j < 8; j++) {
-               if (!v3_minor_map[i] & (0x1 << j)) {
+               if (!(v3_minor_map[i] & (0x1 << j))) {
                    avail = 1;
                    v3_minor_map[i] |= (0x1 << j);
                    break;
@@ -116,7 +121,7 @@ static long v3_dev_ioctl(struct file * filp,
            guest->img_size = user_image.size;
 
            printk("Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
-           guest->img = kmalloc(guest->img_size, GFP_KERNEL);
+           guest->img = vmalloc(guest->img_size);
 
            if (IS_ERR(guest->img)) {
                printk("Error: Could not allocate space for guest image\n");
@@ -135,10 +140,31 @@ static long v3_dev_ioctl(struct file * filp,
            INIT_LIST_HEAD(&(guest->streams));
            INIT_LIST_HEAD(&(guest->files));
            INIT_LIST_HEAD(&(guest->sockets));
+#ifdef V3_CONFIG_HOST_DEVICE
+           INIT_LIST_HEAD(&(guest->hostdev.devs));
+#endif
            init_completion(&(guest->start_done));
            init_completion(&(guest->thread_done));
 
-           kthread_run(start_palacios_vm, guest, guest->name);
+           { 
+               struct task_struct * launch_thread = NULL;
+               // At some point we're going to want to allow the user to specify a CPU mask
+               // But for now, well just launch from the local core, and rely on the global cpu mask
+
+               preempt_disable();
+               launch_thread = kthread_create(start_palacios_vm, guest, guest->name);
+               
+               if (IS_ERR(launch_thread)) {
+                   preempt_enable();
+                   printk("Palacios error creating launch thread for vm (%s)\n", guest->name);
+                   return -EFAULT;
+               }
+
+               kthread_bind(launch_thread, smp_processor_id());
+               preempt_enable();
+
+               wake_up_process(launch_thread);
+           }
 
            wait_for_completion(&(guest->start_done));
 
@@ -162,14 +188,6 @@ static long v3_dev_ioctl(struct file * filp,
                return -EFAULT;
            }
 
-           // Mem test...
-           /*
-             {
-             void * vaddr = __va(alloc_palacios_pgs(131072, 4096));
-             memset(vaddr, 0xfe492fe2, mem.num_pages * 4096);
-             }
-           */
-
            break;
        }
 
@@ -241,25 +259,44 @@ static int __init v3_init(void) {
     
     palacios_vmm_init();
 
+#ifdef V3_CONFIG_STREAM
     palacios_init_stream();
+#endif
+
+#ifdef V3_CONFIG_FILE
     palacios_file_init();
+#endif
+
+#ifdef V3_CONFIG_KEYED_STREAMS
+    palacios_init_keyed_streams();
+#endif
+
+#ifdef V3_CONFIG_CONSOLE
     palacios_init_console();
+#endif
 
+#ifdef V3_CONFIG_GRAPHICS_CONSOLE
+    palacios_init_graphics_console();
+#endif
 
-#ifdef CONFIG_DEBUG_FS
-    palacios_init_debugfs();
+#ifdef V3_CONFIG_EXT_INSPECTOR
+    palacios_init_inspector();
 #endif
 
-#ifdef CONFIG_PALACIOS_SOCKET
+#ifdef V3_CONFIG_SOCKET
     palacios_socket_init();
 #endif
 
-#ifdef CONFIG_PALACIOS_PACKET
+#ifdef V3_CONFIG_PACKET
     palacios_init_packet(NULL);
 #endif
 
-#ifdef CONFIG_PALACIOS_VNET
-    palacios_init_vnet();
+#ifdef V3_CONFIG_VNET
+    palacios_vnet_init();
+#endif
+
+#ifdef V3_CONFIG_HOST_DEVICE
+    palacios_init_host_dev();
 #endif
 
     return 0;
@@ -303,12 +340,29 @@ static void __exit v3_exit(void) {
 
 
 
-#ifdef CONFIG_DEBUG_FS
-    palacios_deinit_debugfs();
+#ifdef V3_CONFIG_EXT_INSPECTOR
+    palacios_deinit_inspector();
 #endif
 
+#ifdef V3_CONFIG_FILE
     palacios_file_deinit();
+#endif
+
+#ifdef V3_CONFIG_STREAM
     palacios_deinit_stream();
+#endif
+
+#ifdef V3_CONFIG_SOCKET
+    palacios_socket_deinit();
+#endif
+
+#ifdef V3_CONFIG_PACKET
+    palacios_deinit_packet(NULL);
+#endif
+
+#ifdef V3_CONFIG_VNET
+    palacios_vnet_deinit();
+#endif
 
     palacios_deinit_mm();
 
diff --git a/linux_module/palacios-graphics-console.c b/linux_module/palacios-graphics-console.c
new file mode 100644 (file)
index 0000000..3cd70c9
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Palacios VM Graphics Console Interface (shared framebuffer between palacios and host)
+ * Copyright (c) 2011 Peter Dinda <pdinda@northwestern.edu>
+ */
+
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
+#include <linux/sched.h>
+
+#include <interfaces/vmm_console.h>
+#include <palacios/vmm_host_events.h>
+
+#include "palacios.h"
+#include "palacios-graphics-console.h"
+
+#include <linux/vmalloc.h>
+
+/*
+
+  This is an implementation of the Palacios Graphics Console interface that
+  is designed to interact with a vnc server running in user space, 
+  typically something based on x0vncserver.  
+
+  The basic idea is that we manage a frame buffer that we share with
+  palacios.   Palacios draws whatever it likes on it.  
+  The user-land vncserver will send us requests   for fb updates, which
+  we implement by copying the FB to it.   When the user-land sends us characters, etc,
+  we deliver those immediately to palacios via the deliver_key and deliver_mouse
+  event interfaces.  The end-result is that whatever the graphics system
+  in palacios renders is visible via vnc.
+
+*/
+
+static v3_graphics_console_t g_open(void * priv_data, 
+                                   struct v3_frame_buffer_spec *desired_spec,
+                                   struct v3_frame_buffer_spec *actual_spec)
+{
+    struct v3_guest * guest = (struct v3_guest *)priv_data;
+    struct palacios_graphics_console *gc = (struct palacios_graphics_console *) &(guest->graphics_console);
+    uint32_t mem;
+
+    if(gc->data) { 
+       printk("palacios: framebuffer already allocated - returning it\n");
+       *actual_spec=gc->spec;
+       gc->cons_refcount++;
+       gc->data_refcount++;
+       return gc;
+    }
+
+    mem = desired_spec->width * desired_spec->height * desired_spec->bytes_per_pixel;
+
+    printk("palacios: allocating %u bytes for %u by %u by %u buffer\n",
+          mem, desired_spec->width, desired_spec->height, desired_spec->bytes_per_pixel);
+
+    gc->data = vmalloc(mem);
+
+    if (!(gc->data)) { 
+       printk("palacios: unable to allocate memory for frame buffer\n");
+       return 0;
+    }
+
+    gc->spec = *desired_spec;
+
+    *actual_spec = gc->spec;
+
+    gc->guest=guest;
+    
+    gc->cons_refcount++;
+    gc->data_refcount++;
+
+    printk("palacios: allocated frame buffer\n");
+
+    return gc;
+}
+
+static  void g_close(v3_graphics_console_t cons)
+{
+    struct palacios_graphics_console *gc = (struct palacios_graphics_console *) cons;
+
+    gc->cons_refcount--;
+    gc->data_refcount--;
+
+    if (gc->data_refcount<gc->cons_refcount) { 
+       printk("palacios: error!   data refcount is less than console refcount for graphics console\n");
+    }
+
+    if (gc->cons_refcount>0) { 
+       return;
+    } else {
+       if (gc->cons_refcount<0) { 
+           printk("palacios: error!  refcount for graphics console is negative on close!\n");
+       }
+       if (gc->data_refcount>0) { 
+           printk("palacios: error!  refcount for graphics console data is positive on close - LEAKING MEMORY\n");
+           return;
+       }
+       if (gc->data) { 
+           kfree(gc->data);
+           gc->data=0;
+       }
+    }
+}
+
+static void * g_get_data_read(v3_graphics_console_t cons, 
+                             struct v3_frame_buffer_spec *cur_spec)
+{
+    struct palacios_graphics_console *gc = (struct palacios_graphics_console *) cons;
+    
+    if (gc->data_refcount<=0) { 
+       printk("palacios: error!  data refcount is <= 0 in get_data_read\n");
+    }
+
+    gc->data_refcount++;
+    
+    *cur_spec=gc->spec;
+    
+    return gc->data;
+}
+
+static void g_release_data_read(v3_graphics_console_t cons)
+{
+    struct palacios_graphics_console *gc = (struct palacios_graphics_console *) cons;
+    
+    gc->data_refcount--;
+
+    if (gc->data_refcount<=0) { 
+       printk("palacios: error!  data refcount is <= zero in release_data_read\n");
+    }
+    
+}
+
+static void *g_get_data_rw(v3_graphics_console_t cons, 
+                          struct v3_frame_buffer_spec *cur_spec)
+{
+    return g_get_data_read(cons,cur_spec);
+}
+
+
+static void g_release_data_rw(v3_graphics_console_t cons)
+{
+    return g_release_data_read(cons);
+}
+
+
+static int g_changed(v3_graphics_console_t cons)
+{
+    struct palacios_graphics_console *gc = 
+       (struct palacios_graphics_console *) cons;
+
+#if 0
+    int rc =  !(gc->num_updates % 1000);
+    
+    gc->num_updates++;
+    
+    return rc;
+#else
+    return 1;
+#endif
+}
+
+
+
+static int palacios_graphics_console_key(struct palacios_graphics_console *cons, uint8_t scancode)
+{
+    struct v3_keyboard_event e;
+    e.status=0;
+    e.scan_code=scancode;
+
+    v3_deliver_keyboard_event(cons->guest->v3_ctx,&e);
+    
+    return 0;
+}
+
+static int palacios_graphics_console_mouse(struct palacios_graphics_console *cons, uint8_t x, uint8_t y, uint8_t buttons)
+{
+    struct v3_mouse_event e;
+    e.data[0]=x;
+    e.data[1]=y;
+    e.data[2]=buttons;   // These three are completely wrong, of course - ignoring mouse for now
+
+    v3_deliver_mouse_event(cons->guest->v3_ctx,&e);
+
+    return 0;
+}
+
+static struct v3_graphics_console_hooks palacios_graphics_console_hooks = 
+{
+    .open  = g_open,
+    .close = g_close,
+
+    .get_data_read = g_get_data_read,
+    .release_data_read = g_release_data_read,
+    .get_data_rw = g_get_data_rw,
+    .release_data_rw = g_release_data_rw,
+
+    .changed = g_changed,
+};
+
+
+int palacios_init_graphics_console( void ) {
+
+    V3_Init_Graphics_Console(&palacios_graphics_console_hooks);
+    
+    return 0;
+}
+
+
+int palacios_graphics_console_user_query(struct palacios_graphics_console *cons, 
+                                        struct v3_fb_query_response __user *u)
+{
+    struct v3_fb_query_response q;
+    
+    
+    if (copy_from_user(&q,(void __user *) u, sizeof(struct v3_fb_query_response))) { 
+       printk("palacios: copy from user in getting query in fb\n");
+       return -EFAULT;
+    }
+    
+    switch (q.request_type) { 
+       case V3_FB_SPEC:
+           // returns only the spec for the FB
+           q.spec = cons->spec;
+
+           break;
+
+       case V3_FB_UPDATE: 
+           // returns whether an update is available for the region
+           // currently always true
+           q.updated = 1;
+
+           break;
+
+       case V3_FB_DATA_BOX: {
+           // Not curently implemented
+           printk("palacios: request for data in bounding box unsupported currently\n");
+           return -EFAULT;
+
+       }
+
+           break;
+           
+       case V3_FB_DATA_ALL: {
+           // First let's sanity check to see if they are requesting the same
+           // spec that we have
+           if (memcmp(&(q.spec),&(cons->spec),sizeof(struct v3_frame_buffer_spec))) { 
+               printk("palacios: request for data with non-matching fb spec \n");
+               return -EFAULT;
+           }
+           // Now let's indicate an update is in the pointer and copy across the data
+           if (copy_to_user(q.data,cons->data,cons->spec.width*cons->spec.height*cons->spec.bytes_per_pixel)) { 
+               printk("palacios: unable to copy fb content to user\n");
+               return -EFAULT;
+           }
+           q.updated=1;
+       }
+           break;
+           
+       default:
+           return -EFAULT;
+    }
+
+    // now we'll copy back any changes we made to the query/response structure
+    if (copy_to_user((void __user *) u, (void*)&q, sizeof(struct v3_fb_query_response))) { 
+       printk("palacios: unable to copy fb response to user\n");
+       return -EFAULT;
+    }
+
+    return 0;
+
+}
+
+int palacios_graphics_console_user_input(struct palacios_graphics_console *cons,
+                                        struct v3_fb_input __user  *u)
+{
+    struct v3_fb_input inp;
+    int rc=0;
+
+
+    if (copy_from_user(&inp,(void __user *) u, sizeof(struct v3_fb_input))) { 
+       printk("palacios: copy from user in getting input in fb\n");
+       return -EFAULT;
+    }
+       
+    if (inp.data_type==V3_FB_KEY || inp.data_type==V3_FB_BOTH) { 
+       rc = palacios_graphics_console_key(cons,inp.scan_code);
+    }
+
+    if (inp.data_type==V3_FB_MOUSE || inp.data_type==V3_FB_BOTH) { 
+       rc |= palacios_graphics_console_mouse(cons,inp.mouse_data[0],inp.mouse_data[1],inp.mouse_data[2]);
+    }
+
+    if (rc) { 
+       return -EFAULT;
+    } else {
+       return 0;
+    }
+}
diff --git a/linux_module/palacios-graphics-console.h b/linux_module/palacios-graphics-console.h
new file mode 100644 (file)
index 0000000..417a26b
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Palacios VM Graphics Console Interface (shared framebuffer between palacios and host)
+ * Copyright (c) 2011 Peter Dinda <pdinda@northwestern.edu>
+ */
+
+#ifndef __PALACIOS_GRAPHICS_CONSOLE_H__
+#define __PALACIOS_GRAPHICS_CONSOLE_H__
+
+#include <interfaces/vmm_graphics_console.h>
+
+struct palacios_graphics_console {
+    // descriptor for the data in the shared frame buffer
+    struct v3_frame_buffer_spec spec;
+    // the actual shared frame buffer
+    // Note that "shared" here means shared between palacios and us
+    // This data could of course also be shared with userland
+    void *data;
+
+    struct v3_guest * guest;
+
+    int cons_refcount;
+    int data_refcount;
+
+    uint32_t num_updates;
+
+    // Currently keystrokes and mouse movements are ignored
+
+    // currently, we will not worry about locking this
+    // lock_t ...
+};
+
+
+// This is the data structure that is passed back and forth with user-land
+// ioctl
+struct v3_fb_query_response {
+    enum { V3_FB_DATA_ALL, V3_FB_DATA_BOX, V3_FB_UPDATE, V3_FB_SPEC } request_type;
+    struct v3_frame_buffer_spec spec;    // in: desired spec; out: actual spec
+    uint32_t x, y, w, h;                 // region to copy (0s = all) in/out args
+    int updated;                         // whether this region has been updated or not
+    void __user *data;                   // user space pointer to copy data to
+};
+
+// This is what userland sends down for input events
+struct v3_fb_input {
+    enum { V3_FB_KEY, V3_FB_MOUSE, V3_FB_BOTH}             data_type;
+    uint8_t                              scan_code;
+    uint8_t                              mouse_data[3];
+};
+
+
+int palacios_init_graphics_console(void);
+
+int palacios_graphics_console_user_query(struct palacios_graphics_console *cons, 
+                                        struct v3_fb_query_response __user *fb);
+
+int palacios_graphics_console_user_input(struct palacios_graphics_console *cons,
+                                        struct v3_fb_input __user  *in);
+
+
+#endif
diff --git a/linux_module/palacios-hashtable.c b/linux_module/palacios-hashtable.c
new file mode 100644 (file)
index 0000000..6c025fc
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * Palacios Hash Table 
+ * (c) Lei Xia, 2011
+ */
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/preempt.h>
+#include <linux/sched.h>
+#include "palacios-hashtable.h"
+
+
+struct hash_entry {
+    addr_t key;
+    addr_t value;
+    uint_t hash;
+    struct hash_entry * next;
+};
+
+struct hashtable {
+    uint_t table_length;
+    struct hash_entry ** table;
+    uint_t entry_count;
+    uint_t load_limit;
+    uint_t prime_index;
+    uint_t (*hash_fn) (addr_t key);
+    int (*eq_fn) (addr_t key1, addr_t key2);
+};
+
+
+/* HASH FUNCTIONS */
+
+static inline uint_t do_hash(struct hashtable * htable, addr_t key) {
+    /* Aim to protect against poor hash functions by adding logic here
+     * - logic taken from java 1.4 hashtable source */
+    uint_t i = htable->hash_fn(key);
+    i += ~(i << 9);
+    i ^=  ((i >> 14) | (i << 18)); /* >>> */
+    i +=  (i << 4);
+    i ^=  ((i >> 10) | (i << 22)); /* >>> */
+
+    return i;
+}
+
+
+/* HASH AN UNSIGNED LONG */
+/* LINUX UNSIGHED LONG HASH FUNCTION */
+#ifdef __32BIT__
+/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
+#define GOLDEN_RATIO_PRIME 0x9e370001UL
+//#define BITS_PER_LONG 32
+#elif  defined(__64BIT__)
+/*  2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
+#define GOLDEN_RATIO_PRIME 0x9e37fffffffc0001UL
+//#define BITS_PER_LONG 64
+#else
+#error Define GOLDEN_RATIO_PRIME for your wordsize.
+#endif
+
+ulong_t palacios_hash_long(ulong_t val, uint_t bits) {
+    ulong_t hash = val;
+
+#ifdef __PALACIOS_64BIT__
+    /*  Sigh, gcc can't optimise this alone like it does for 32 bits. */
+    ulong_t n = hash;
+    n <<= 18;
+    hash -= n;
+    n <<= 33;
+    hash -= n;
+    n <<= 3;
+    hash += n;
+    n <<= 3;
+    hash -= n;
+    n <<= 4;
+    hash += n;
+    n <<= 2;
+    hash += n;
+#else
+    /* On some cpus multiply is faster, on others gcc will do shifts */
+    hash *= GOLDEN_RATIO_PRIME;
+#endif
+
+    /* High bits are more random, so use them. */
+    return hash >> (BITS_PER_LONG - bits);
+}
+
+/* HASH GENERIC MEMORY BUFFER */
+/* ELF HEADER HASH FUNCTION */
+ulong_t palacios_hash_buffer(uchar_t * msg, uint_t length) {
+    ulong_t hash = 0;
+    ulong_t temp = 0;
+    uint_t i;
+
+    for (i = 0; i < length; i++) {
+       hash = (hash << 4) + *(msg + i) + i;
+       if ((temp = (hash & 0xF0000000))) {
+           hash ^= (temp >> 24);
+       }
+       hash &= ~temp;
+    }
+    return hash;
+}
+
+/* indexFor */
+static inline uint_t indexFor(uint_t table_length, uint_t hash_value) {
+    return (hash_value % table_length);
+};
+
+#define freekey(X) kfree(X)
+
+
+static void * tmp_realloc(void * old_ptr, uint_t old_size, uint_t new_size) {
+    void * new_buf = kmalloc(new_size, GFP_KERNEL);
+
+    if (new_buf == NULL) {
+       return NULL;
+    }
+
+    memcpy(new_buf, old_ptr, old_size);
+    kfree(old_ptr);
+
+    return new_buf;
+}
+
+
+/*
+  Credit for primes table: Aaron Krowne
+  http://br.endernet.org/~akrowne/
+  http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+*/
+static const uint_t primes[] = { 
+    53, 97, 193, 389,
+    769, 1543, 3079, 6151,
+    12289, 24593, 49157, 98317,
+    196613, 393241, 786433, 1572869,
+    3145739, 6291469, 12582917, 25165843,
+    50331653, 100663319, 201326611, 402653189,
+    805306457, 1610612741 };
+
+
+// this assumes that the max load factor is .65
+static const uint_t load_factors[] = {
+    35, 64, 126, 253,
+    500, 1003, 2002, 3999,
+    7988, 15986, 31953, 63907,
+    127799, 255607, 511182, 1022365,
+    2044731, 4089455, 8178897, 16357798,
+    32715575, 65431158, 130862298, 261724573,
+    523449198, 1046898282 };
+
+const uint_t prime_table_len = sizeof(primes) / sizeof(primes[0]);
+
+struct hashtable * palacios_create_htable(uint_t min_size,
+                                   uint_t (*hash_fn) (addr_t),
+                                   int (*eq_fn) (addr_t, addr_t)) {
+    struct hashtable * htable;
+    uint_t prime_index;
+    uint_t size = primes[0];
+
+    /* Check requested hashtable isn't too large */
+    if (min_size > (1u << 30)) {
+       return NULL;
+    }
+
+    /* Enforce size as prime */
+    for (prime_index = 0; prime_index < prime_table_len; prime_index++) {
+        if (primes[prime_index] > min_size) { 
+           size = primes[prime_index]; 
+           break; 
+       }
+    }
+
+    htable = (struct hashtable *)kmalloc(sizeof(struct hashtable), GFP_KERNEL);
+
+    if (htable == NULL) {
+       return NULL; /*oom*/
+    }
+
+    htable->table = (struct hash_entry **)kmalloc(sizeof(struct hash_entry*) * size, GFP_KERNEL);
+
+    if (htable->table == NULL) { 
+       kfree(htable); 
+       return NULL;  /*oom*/
+    }
+
+    memset(htable->table, 0, size * sizeof(struct hash_entry *));
+
+    htable->table_length  = size;
+    htable->prime_index   = prime_index;
+    htable->entry_count   = 0;
+    htable->hash_fn       = hash_fn;
+    htable->eq_fn         = eq_fn;
+    htable->load_limit    = load_factors[prime_index];
+
+    return htable;
+}
+
+
+static int hashtable_expand(struct hashtable * htable) {
+    /* Double the size of the table to accomodate more entries */
+    struct hash_entry ** new_table;
+    struct hash_entry * tmp_entry;
+    struct hash_entry ** entry_ptr;
+    uint_t new_size;
+    uint_t i;
+    uint_t index;
+
+    /* Check we're not hitting max capacity */
+    if (htable->prime_index == (prime_table_len - 1)) {
+       return 0;
+    }
+
+    new_size = primes[++(htable->prime_index)];
+
+    new_table = (struct hash_entry **)kmalloc(sizeof(struct hash_entry*) * new_size, GFP_KERNEL);
+
+    if (new_table != NULL) {
+        memset(new_table, 0, new_size * sizeof(struct hash_entry *));
+        /* This algorithm is not 'stable'. ie. it reverses the list
+         * when it transfers entries between the tables */
+
+        for (i = 0; i < htable->table_length; i++) {
+
+           while ((tmp_entry = htable->table[i]) != NULL) {
+               htable->table[i] = tmp_entry->next;
+          
+               index = indexFor(new_size, tmp_entry->hash);
+           
+               tmp_entry->next = new_table[index];
+           
+               new_table[index] = tmp_entry;
+           }
+        }
+
+        kfree(htable->table);
+
+        htable->table = new_table;
+    } else {
+       /* Plan B: realloc instead */
+
+       //new_table = (struct hash_entry **)realloc(htable->table, new_size * sizeof(struct hash_entry *));
+       new_table = (struct hash_entry **)tmp_realloc(htable->table, primes[htable->prime_index - 1], 
+                                                     new_size * sizeof(struct hash_entry *));
+
+       if (new_table == NULL) {
+           (htable->prime_index)--;
+           return 0;
+       }
+
+       htable->table = new_table;
+
+       memset(new_table[htable->table_length], 0, new_size - htable->table_length);
+
+       for (i = 0; i < htable->table_length; i++) {
+
+           for (entry_ptr = &(new_table[i]), tmp_entry = *entry_ptr; 
+                tmp_entry != NULL; 
+                tmp_entry = *entry_ptr) {
+
+               index = indexFor(new_size, tmp_entry->hash);
+
+               if (i == index) {
+                   entry_ptr = &(tmp_entry->next);
+               } else {
+                   *entry_ptr = tmp_entry->next;
+                   tmp_entry->next = new_table[index];
+                   new_table[index] = tmp_entry;
+               }
+           }
+       }
+    }
+
+    htable->table_length = new_size;
+
+    htable->load_limit   = load_factors[htable->prime_index];
+
+    return -1;
+}
+
+uint_t palacios_htable_count(struct hashtable * htable) {
+    return htable->entry_count;
+}
+
+int palacios_htable_insert(struct hashtable * htable, addr_t key, addr_t value) {
+    /* This method allows duplicate keys - but they shouldn't be used */
+    uint_t index;
+    struct hash_entry * new_entry;
+
+    if (++(htable->entry_count) > htable->load_limit) {
+       /* Ignore the return value. If expand fails, we should
+        * still try cramming just this value into the existing table
+        * -- we may not have memory for a larger table, but one more
+        * element may be ok. Next time we insert, we'll try expanding again.*/
+       hashtable_expand(htable);
+    }
+
+    new_entry = (struct hash_entry *)kmalloc(sizeof(struct hash_entry), GFP_KERNEL);
+
+    if (new_entry == NULL) { 
+       (htable->entry_count)--; 
+       return 0; /*oom*/
+    }
+
+    new_entry->hash = do_hash(htable, key);
+
+    index = indexFor(htable->table_length, new_entry->hash);
+
+    new_entry->key = key;
+    new_entry->value = value;
+
+    new_entry->next = htable->table[index];
+
+    htable->table[index] = new_entry;
+
+    return -1;
+}
+
+
+int palacios_htable_change(struct hashtable * htable, addr_t key, addr_t value, int free_value) {
+    struct hash_entry * tmp_entry;
+    uint_t hash_value;
+    uint_t index;
+
+    hash_value = do_hash(htable, key);
+
+    index = indexFor(htable->table_length, hash_value);
+
+    tmp_entry = htable->table[index];
+
+    while (tmp_entry != NULL) {
+        /* Check hash value to short circuit heavier comparison */
+        if ((hash_value == tmp_entry->hash) && (htable->eq_fn(key, tmp_entry->key))) {
+
+           if (free_value) {
+               kfree((void *)(tmp_entry->value));
+           }
+
+           tmp_entry->value = value;
+           return -1;
+        }
+        tmp_entry = tmp_entry->next;
+    }
+    return 0;
+}
+
+
+
+int palacios_htable_inc(struct hashtable * htable, addr_t key, addr_t value) {
+    struct hash_entry * tmp_entry;
+    uint_t hash_value;
+    uint_t index;
+
+    hash_value = do_hash(htable, key);
+
+    index = indexFor(htable->table_length, hash_value);
+
+    tmp_entry = htable->table[index];
+
+    while (tmp_entry != NULL) {
+        /* Check hash value to short circuit heavier comparison */
+        if ((hash_value == tmp_entry->hash) && (htable->eq_fn(key, tmp_entry->key))) {
+
+           tmp_entry->value += value;
+           return -1;
+        }
+        tmp_entry = tmp_entry->next;
+    }
+    return 0;
+}
+
+
+int palacios_htable_dec(struct hashtable * htable, addr_t key, addr_t value) {
+    struct hash_entry * tmp_entry;
+    uint_t hash_value;
+    uint_t index;
+
+    hash_value = do_hash(htable, key);
+
+    index = indexFor(htable->table_length, hash_value);
+
+    tmp_entry = htable->table[index];
+
+    while (tmp_entry != NULL) {
+        /* Check hash value to short circuit heavier comparison */
+        if ((hash_value == tmp_entry->hash) && (htable->eq_fn(key, tmp_entry->key))) {
+
+           tmp_entry->value -= value;
+           return -1;
+        }
+        tmp_entry = tmp_entry->next;
+    }
+    return 0;
+}
+
+
+/* returns value associated with key */
+addr_t palacios_htable_search(struct hashtable * htable, addr_t key) {
+    struct hash_entry * cursor;
+    uint_t hash_value;
+    uint_t index;
+  
+    hash_value = do_hash(htable, key);
+  
+    index = indexFor(htable->table_length, hash_value);
+  
+    cursor = htable->table[index];
+  
+    while (cursor != NULL) {
+       /* Check hash value to short circuit heavier comparison */
+       if ((hash_value == cursor->hash) && 
+           (htable->eq_fn(key, cursor->key))) {
+           return cursor->value;
+       }
+    
+       cursor = cursor->next;
+    }
+  
+    return (addr_t)NULL;
+}
+
+
+/* returns value associated with key */
+addr_t palacios_htable_remove(struct hashtable * htable, addr_t key, int free_key) {
+    /* TODO: consider compacting the table when the load factor drops enough,
+     *       or provide a 'compact' method. */
+  
+    struct hash_entry * cursor;
+    struct hash_entry ** entry_ptr;
+    addr_t value;
+    uint_t hash_value;
+    uint_t index;
+  
+    hash_value = do_hash(htable, key);
+
+    index = indexFor(htable->table_length, hash_value);
+
+    entry_ptr = &(htable->table[index]);
+    cursor = *entry_ptr;
+
+    while (cursor != NULL) {
+       /* Check hash value to short circuit heavier comparison */
+       if ((hash_value == cursor->hash) && 
+           (htable->eq_fn(key, cursor->key))) {
+     
+           *entry_ptr = cursor->next;
+           htable->entry_count--;
+           value = cursor->value;
+      
+           if (free_key) {
+               freekey((void *)(cursor->key));
+           }
+           kfree(cursor);
+      
+           return value;
+       }
+
+       entry_ptr = &(cursor->next);
+       cursor = cursor->next;
+    }
+    return (addr_t)NULL;
+}
+
+
+/* destroy */
+void palacios_free_htable(struct hashtable * htable, int free_values, int free_keys) {
+    uint_t i;
+    struct hash_entry * cursor;
+    struct hash_entry * tmp;
+    struct hash_entry **table = htable->table;
+
+    if (free_values) {
+       for (i = 0; i < htable->table_length; i++) {
+           cursor = table[i];
+      
+           while (cursor != NULL) { 
+               tmp = cursor; 
+               cursor = cursor->next; 
+
+               if (free_keys) {
+                   freekey((void *)(tmp->key)); 
+               }
+               kfree((void *)(tmp->value)); 
+               kfree(tmp); 
+           }
+       }
+    } else {
+       for (i = 0; i < htable->table_length; i++) {
+           cursor = table[i];
+
+           while (cursor != NULL) { 
+               struct hash_entry * tmp;
+
+               tmp = cursor; 
+               cursor = cursor->next; 
+       
+               if (free_keys) {
+                   freekey((void *)(tmp->key)); 
+               }
+               kfree(tmp); 
+           }
+       }
+    }
+  
+    kfree(htable->table);
+    kfree(htable);
+}
+
diff --git a/linux_module/palacios-hashtable.h b/linux_module/palacios-hashtable.h
new file mode 100644 (file)
index 0000000..3d46202
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef __PALACIOS_HASHTABLE_H__
+#define __PALACIOS_HASHTABLE_H__
+
+struct hashtable;
+
+#define __32BIT__
+
+/* Example of use:
+ *
+ *      struct hashtable  *h;
+ *      struct some_key   *k;
+ *      struct some_value *v;
+ *
+ *      static uint_t         hash_from_key_fn( void *k );
+ *      static int                  keys_equal_fn ( void *key1, void *key2 );
+ *
+ *      h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ *      k = (struct some_key *)     malloc(sizeof(struct some_key));
+ *      v = (struct some_value *)   malloc(sizeof(struct some_value));
+ *
+ *      (initialise k and v to suitable values)
+ * 
+ *      if (! hashtable_insert(h,k,v) )
+ *      {     exit(-1);               }
+ *
+ *      if (NULL == (found = hashtable_search(h,k) ))
+ *      {    printf("not found!");                  }
+ *
+ *      if (NULL == (found = hashtable_remove(h,k) ))
+ *      {    printf("Not found\n");                 }
+ *
+ */
+
+/* Macros may be used to define type-safe(r) hashtable access functions, with
+ * methods specialized to take known key and value types as parameters.
+ * 
+ * Example:
+ *
+ * Insert this at the start of your file:
+ *
+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
+ *
+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
+ * These operate just like hashtable_insert etc., with the same parameters,
+ * but their function signatures have 'struct some_key *' rather than
+ * 'void *', and hence can generate compile time errors if your program is
+ * supplying incorrect data as a key (and similarly for value).
+ *
+ * Note that the hash and key equality functions passed to create_hashtable
+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
+ * a difficult issue as they're only defined and passed once, and the other
+ * functions will ensure that only valid keys are supplied to them.
+ *
+ * The cost for this checking is increased code size and runtime overhead
+ * - if performance is important, it may be worth switching back to the
+ * unsafe methods once your program has been debugged with the safe methods.
+ * This just requires switching to some simple alternative defines - eg:
+ * #define insert_some hashtable_insert
+ *
+ */
+
+typedef unsigned char uchar_t;
+typedef unsigned int uint_t;
+typedef unsigned long long ullong_t;
+typedef unsigned long ulong_t;
+typedef ulong_t addr_t;
+
+
+#define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype)            \
+    static int fnname (struct hashtable * htable, keytype key, valuetype value) { \
+       return v3_htable_insert(htable, (addr_t)key, (addr_t)value);    \
+    }
+
+#define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype)            \
+    static valuetype * fnname (struct hashtable * htable, keytype  key) { \
+       return (valuetype *) (v3_htable_search(htable, (addr_t)key));   \
+    }
+
+#define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype, free_key)  \
+    static valuetype * fnname (struct hashtable * htable, keytype key) { \
+       return (valuetype *) (v3_htable_remove(htable, (addr_t)key, free_key)); \
+    }
+
+
+
+
+
+/* These cannot be inlined because they are referenced as fn ptrs */
+ulong_t palacios_hash_long(ulong_t val, uint_t bits);
+ulong_t palacios_hash_buffer(uchar_t * msg, uint_t length);
+
+
+
+struct hashtable * palacios_create_htable(uint_t min_size,
+                                   uint_t (*hashfunction) (addr_t key),
+                                   int (*key_eq_fn) (addr_t key1, addr_t key2));
+
+void palacios_free_htable(struct hashtable * htable, int free_values, int free_keys);
+
+/*
+ * returns non-zero for successful insertion
+ *
+ * This function will cause the table to expand if the insertion would take
+ * the ratio of entries to table size over the maximum load factor.
+ *
+ * This function does not check for repeated insertions with a duplicate key.
+ * The value returned when using a duplicate key is undefined -- when
+ * the hashtable changes size, the order of retrieval of duplicate key
+ * entries is reversed.
+ * If in doubt, remove before insert.
+ */
+int palacios_htable_insert(struct hashtable * htable, addr_t key, addr_t value);
+
+int palacios_htable_change(struct hashtable * htable, addr_t key, addr_t value, int free_value);
+
+
+// returns the value associated with the key, or NULL if none found
+addr_t palacios_htable_search(struct hashtable * htable, addr_t key);
+
+// returns the value associated with the key, or NULL if none found
+addr_t palacios_htable_remove(struct hashtable * htable, addr_t key, int free_key);
+
+uint_t palacios_htable_count(struct hashtable * htable);
+
+// Specialty functions for a counting hashtable 
+int palacios_htable_inc(struct hashtable * htable, addr_t key, addr_t value);
+int palacios_htable_dec(struct hashtable * htable, addr_t key, addr_t value);
+
+
+#endif
diff --git a/linux_module/palacios-host-dev-user.h b/linux_module/palacios-host-dev-user.h
new file mode 100644 (file)
index 0000000..4f1334f
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef _PALACIOS_HOST_DEV_USER_H_
+#define _PALACIOS_HOST_DEV_USER_H_
+
+/*
+ * Palacios Host Device Interface + User-space interface 
+ * (c) Peter Dinda, 2011
+ */
+
+
+#define V3_VM_HOST_DEV_CONNECT (10244+1)
+
+/* to detemine whether a host request is available, poll the fd for read */
+
+/* make a request for reading/writing guest or injecting irq */
+/* the arguemnt is a pointer to a palacios_host_dev_user_op struct */
+/* return is negative on error, positive to indicate bytes read/written or irq injected*/
+#define V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL  (10244+2)
+
+/* find out the size of the current host request, if one is pending */
+/* you find out if one is pending by read poll/select on the fd */
+/* the argument is a pointer to a uint64_t that will give the total size */
+/* ioctl returns 1 if a request is ready, 0 if there is no request */
+/* -EFAULT if there is a an error */
+#define V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL  (10244+3)
+
+/* get the current host request, if one is available */
+/* the argument is a pointer to a palacios_host_dev_host_request_response */
+/* of the needed size */
+/* ioctl returns 1 if a request is ready+copied, 0 if there is no request */
+/* -EFAULT if there is a an error */
+#define V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL  (10244+4)
+
+/* write back the response to the previously pulled host request */
+/* the argument is a pointer to a palacios_host_dev_host_request_response */
+#define V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL (10244+5)
+
+
+#ifdef __KERNEL__
+#define USER __user
+#else
+#define USER
+#endif
+
+struct palacios_host_dev_user_op {
+#define PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST  1
+#define PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST 2
+#define PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST   3
+    uint32_t        type;   // type of operation (from the #defs above)
+    void            *gpa;   // physical address in guest to read or write
+    void USER      *data;   // user address of data that will be read or written
+    uint64_t        len;    // number of bytes to move
+
+    uint8_t         irq;    // irq to inject
+};
+
+
+struct palacios_host_dev_host_request_response {
+    // data_len must remain the first field in this structure
+    uint64_t  data_len;    // size of the structure + occupied data
+    uint64_t  len;         // size of the structure in total
+#define PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO     1
+#define PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO    2
+#define PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM    3
+#define PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM   4
+#define PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF   5
+#define PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF  6
+    uint32_t  type;        // one of the types given above
+    uint16_t  port;        // port number, for IO
+    void      *gpa;         // physical address in the guest for memory ops
+    uint64_t  conf_addr;   // address in the configuration for configuration ops
+
+    uint64_t  op_len;      // response: bytes read/written to the device
+                           // request: bytes to read/write
+                            
+    uint8_t   data[0];     // data (if any)
+
+} ;
+
+
+
+#endif
diff --git a/linux_module/palacios-host-dev.c b/linux_module/palacios-host-dev.c
new file mode 100644 (file)
index 0000000..c20e0fa
--- /dev/null
@@ -0,0 +1,1021 @@
+/* 
+ * Host device interface + user-space device interface
+ * (c) 2011 Peter Dinda
+ */
+
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/anon_inodes.h>
+#include <linux/file.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#include <interfaces/vmm_host_dev.h>
+
+#include "palacios.h"
+#include "palacios-host-dev.h"
+#include "palacios-host-dev-user.h"
+
+
+
+/*
+  There are two things in this file:
+
+
+  1. An implementation of the Palacios host device interface that will
+     accept any URL from Palacios.  Currently, the only URL type it will
+     handle is user:<name>, but it should be clear how to extend with
+     other types.
+
+     Palacios opens a host device by issuing something like this:
+
+         palacios_host_dev_open( impl="user:foo" busclass=pci, opaque )
+
+     This will attempt to rendezvous with the user space device The
+     rendevzous retry and timeout periods can be set below.
+
+  2. An implementation of user: urls - the host interface is mapped
+     into an RPC-like interface to/from user space via a file
+     interface.   
+
+     The user space gets a file descriptor like this:
+
+     int vmfd = open("/dev/v3-vmX",...);
+
+     int devfd = ioctl(vmfd,V3_HOST_DEV_CONNECT,"user:foo"); 
+
+     This will attempt to rendezvous with the host side.
+
+     If it returns successfully, you can now issue synchronous,
+     blocking RPCs to the guest to read/write its memory and inject
+     irqs.  This means that a user->host request is handled
+     immediately, and independently of any host->user request. 
+
+     struct palacios_host_dev_user_op op;
+
+     // fill out op
+     op.type = PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST; 
+     ...
+
+     ioctl(devfd, V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL, &op);
+
+     // return value is # bytes read or written; or 0 if irq injected
+     // negative value is error
+
+     The interface from the host to the user side is asynchronous
+     blocking RPC.  Any host device will have at most one outstanding
+     request from palacios.  The implementation here stores the
+     request until the user side is ready to accept it.  The user side
+     can check if there is a request via a poll/select or an ioctl.
+     The ioctl also returns the needed size for the request structure.
+     After the user side has a request, it is expected to process it,
+     perhaps making user->host requests as described above, and then
+     return a response.  Only one host->user request should be in
+     progress at any time in the user space.
+
+     What this looks like is:
+     
+     poll(...devfd for read...) or select(...devfd for read...)
+
+     if (devfd is marked readable) { 
+         uint64_t size;
+
+         ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&size);
+         // returns 1 if there is a request, 0 if not, negative on err
+
+         struct palacios_host_dev_host_request_response *req;
+
+         req = allocate req to be at least size bytes long
+
+         ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL,req)
+         // returns 1 if there is a request, 0 if not, negative on err
+        
+         // process request, perhaps using above user->host request
+         // build response structure
+         // resp.data_len == size of structure including relevant data at end
+
+         ioctl(devfd,V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL,resp);
+        // returns 0 if there is no outstanding request (user error)
+        // 1 on success, negative on error
+     }
+    
+
+*/
+
+
+#define MAX_URL 256
+
+#define RENDEZVOUS_WAIT_SECS  60
+#define RENDEZVOUS_RETRY_SECS 1
+
+
+struct palacios_host_device_user {
+    spinlock_t lock;
+    int      connected;    // is the user space connected to this?
+    int      waiting;      // am I waiting for a user-space response?
+
+    int      fd;           // what is the user space fd?
+
+    char     url[MAX_URL]; // what is the url describing the device
+
+    v3_guest_dev_t guestdev; // what is the palacios-side device
+
+    wait_queue_head_t  user_wait_queue; // user space processes waiting on us (should be only one)
+    wait_queue_head_t  host_wait_queue; // host threads (should only be one) waiting on user space
+
+    struct v3_guest                                *guest; // my guest
+    struct palacios_host_dev_host_request_response *req;   // curent request
+    struct palacios_host_dev_host_request_response *resp;  // curent response
+
+    struct list_head  node;   // for adding me to the list of hostdevs this VM has
+};
+
+
+/**************************************************************************************
+  Utility functions
+*************************************************************************************/
+
+static void palacios_host_dev_user_free(struct palacios_host_device_user *dev)
+{
+    if (dev->req) {
+       kfree(dev->req);
+       dev->req=0;
+    } 
+    if (dev->resp) { 
+       kfree(dev->resp);
+       dev->resp=0;
+    }
+    kfree(dev);
+}
+
+static int palacios_resize_reqresp(struct palacios_host_dev_host_request_response **r, uint64_t data_size, int copy)
+{
+    if (!*r) { 
+       // allocate it
+       *r = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
+       if (!*r) { 
+           return -1;
+       } else {
+           (*r)->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
+           return 0;
+       }
+    } else {
+       //let it go if it's big enough
+       uint64_t cur_len = (*r)->len-sizeof(struct palacios_host_dev_host_request_response);
+
+       if (data_size<=cur_len) { 
+           // do nothing
+           return 0;
+       } else {
+           struct palacios_host_dev_host_request_response *new;
+
+           if (!copy) { 
+               kfree(*r);
+               *r=0;
+           }
+           new = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
+           if (!new) { 
+               return -1;
+           } else {
+               new->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
+               if (copy) { 
+                   memcpy(new->data,(*r)->data,(*r)->data_len-sizeof(struct palacios_host_dev_host_request_response));
+                   new->data_len=(*r)->data_len;
+                   kfree(*r);
+               }
+               *r=new;
+               return 0;
+           }
+       }
+    }
+}
+
+static void cycle_request_response(struct palacios_host_device_user *dev)
+{
+    // wake up user side so that polls fall through
+    wake_up_interruptible(&(dev->user_wait_queue));
+    // put us to sleep until the user side wakes us up
+    wait_event_interruptible((dev->host_wait_queue), (dev->waiting==0));
+}
+
+static void cycle_response_request(struct palacios_host_device_user *dev)
+{
+    // wake up host side
+    wake_up_interruptible(&(dev->host_wait_queue));
+}
+
+    
+/*********************************************************************************************
+
+    Interface to user space
+
+ *********************************************************************************************/ 
+
+
+
+static unsigned int host_dev_poll(struct file * filp, 
+                                 struct poll_table_struct * poll_tb) 
+{
+
+    struct palacios_host_device_user * dev = filp->private_data;
+    unsigned long f;
+
+    if (!dev->connected) { 
+       return -EFAULT;
+    }
+
+    spin_lock_irqsave(&(dev->lock),f);
+
+    if (dev->waiting) { 
+       // Yes, we have a request if you want it!
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return  POLLIN | POLLRDNORM;
+    } 
+
+    // No request yet, so we need to wait for one to show up.
+
+    // register ourselves on the user wait queue
+    poll_wait(filp, &(dev->user_wait_queue), poll_tb);
+
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    // We will get called again when that queue is woken up
+
+    return 0;
+}
+
+
+static int host_dev_release(struct inode * i, struct file * filp) 
+{
+    struct palacios_host_device_user *dev = filp->private_data;
+    unsigned long f;
+
+    printk("palacios: user side is closing host device \"%s\"\n",dev->url);
+    
+    spin_lock_irqsave(&(dev->lock), f);
+    dev->connected = 0;
+    spin_unlock_irqrestore(&(dev->lock), f);
+
+    // it is the palacios->host interface's responsibility to ignore
+    // reads/writes until connected is true
+
+    return 0;
+}
+
+
+static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg)
+{
+    void __user *argp = (void __user *)arg;
+
+    struct palacios_host_device_user *dev = fp->private_data;
+
+
+    if (!dev->connected) { 
+       return -EFAULT;
+    }
+    
+    switch (val) { 
+       case V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL: {
+           
+           struct palacios_host_dev_user_op op;
+           
+           if (copy_from_user(&op,argp,sizeof(struct palacios_host_dev_user_op))) { 
+               printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
+               return -EFAULT;
+           }
+           
+           switch (op.type) { 
+               case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: {
+                   void *temp = kmalloc(op.len,GFP_KERNEL);
+
+                   if (!temp) { 
+                       printk("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
+                       return -EFAULT;
+                   }
+                   
+                   if (v3_host_dev_read_guest_mem(dev->guestdev,
+                                                  dev,
+                                                  op.gpa,
+                                                  temp,
+                                                  op.len) != op.len) {
+                       printk("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
+                       kfree(temp);
+                       return -EFAULT;
+                   }
+                   
+                   if (copy_to_user(op.data,temp,op.len)) { 
+                       printk("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
+                       kfree(temp);
+                       return -EFAULT;
+                   }
+
+                   kfree(temp);
+
+                   return op.len;
+               }
+                   break;
+                   
+
+               case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
+
+                   void *temp = kmalloc(op.len,GFP_KERNEL);
+
+                   if (!temp) { 
+                       printk("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
+                       return -EFAULT;
+                   }
+                   
+                   if (copy_from_user(temp,op.data,op.len)) { 
+                       printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
+                       kfree(temp);
+                       return -EFAULT;
+                   }
+                   
+                   if (v3_host_dev_write_guest_mem(dev->guestdev,
+                                                   dev,
+                                                   op.gpa,
+                                                   temp,
+                                                   op.len) != op.len) {
+                       printk("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
+                       kfree(temp);
+                       return -EFAULT;
+                   }
+
+                   kfree(temp);
+                   
+                   return op.len;
+               }
+                   break;
+
+               case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST: {
+
+                   return  v3_host_dev_raise_irq(dev->guestdev, dev, op.irq);
+               }
+                   break;
+
+               default:
+                   printk("palacios: unknown user request to host device \"%s\"\n",dev->url);
+                   return -EFAULT;
+                   break;
+           }
+       }
+           break;
+
+       case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
+           
+           unsigned long f;
+           
+           spin_lock_irqsave(&(dev->lock),f);
+           
+           if (!(dev->waiting)) { 
+               spin_unlock_irqrestore(&(dev->lock),f);
+               return 0; // no request available now
+           } 
+           
+           if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) { 
+               printk("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
+               spin_unlock_irqrestore(&(dev->lock),f);
+               return -EFAULT; // failed to copy!
+           }
+           
+           spin_unlock_irqrestore(&(dev->lock),f);
+
+           return 1; // have request for you
+           
+       }
+           
+           break;
+           
+       case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
+           
+           unsigned long f;
+           
+           spin_lock_irqsave(&(dev->lock),f);
+           
+           if (!(dev->waiting)) { 
+               spin_unlock_irqrestore(&(dev->lock),f);
+               return 0; // no request available now
+           } 
+           
+           if (copy_to_user(argp,dev->req,dev->req->data_len)) { 
+               printk("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
+               spin_unlock_irqrestore(&(dev->lock),f);
+               return -EFAULT; // failed to copy!
+           }
+           
+           spin_unlock_irqrestore(&(dev->lock),f);
+           
+           return 1; // copied request for you
+       }
+           break;
+           
+       case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
+
+           unsigned long f;
+           uint64_t user_datalen;
+           
+           spin_lock_irqsave(&(dev->lock),f);
+           
+           if (!(dev->waiting)) { 
+               spin_unlock_irqrestore(&(dev->lock),f);
+               return 0; // no request outstanding, so we do not need a response!
+           }
+           
+           if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) { 
+               printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
+               spin_unlock_irqrestore(&(dev->lock),f);
+               return -EFAULT; // failed to copy!
+           } 
+           
+           if (palacios_resize_reqresp(&(dev->resp),user_datalen,0)) {
+               printk("palacios: unable to resize to accept request of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
+               spin_unlock_irqrestore(&(dev->lock),f);
+               return -EFAULT;
+           } 
+           
+           if (copy_from_user(dev->resp, argp, user_datalen)) { 
+               printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
+               spin_unlock_irqrestore(&(dev->lock),f);
+               return -EFAULT; // failed to copy!
+           } 
+           
+           // now have valid response!
+           dev->waiting=0;
+
+           // wake the palacios side up so that it sees it
+           cycle_response_request(dev);
+
+           spin_unlock_irqrestore(&(dev->lock),f);
+
+           return 1; // done
+       }
+           break;
+           
+       default:
+           printk("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
+           return -EFAULT;
+           break;
+    }
+    
+}
+
+
+
+
+static struct file_operations host_dev_fops = {
+    .poll     = host_dev_poll,
+    .release  = host_dev_release,
+    .ioctl    = host_dev_ioctl,
+};
+
+
+
+    
+int connect_host_dev(struct v3_guest * guest, char *url) 
+{
+    struct palacios_host_device_user *dev;
+    unsigned long f1, f2;
+    int i;
+
+    // currently only support user: types:
+    if (strncasecmp(url,"user:",5)) { 
+       printk("palacios: do not currently support host devices of type in \"%s\"\n",url);
+       return -1;
+    }
+    
+    printk("palacios: attempting to rendezvous with palacios side of host device \"%s\"\n",url);
+    
+    // We will scan the list looking for the relevant
+    // URL.  If we don't find it after a while, we give up
+    
+    for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
+       spin_lock_irqsave(&(guest->hostdev.lock),f1);
+       list_for_each_entry(dev,&(guest->hostdev.devs), node) {
+           if (!strncasecmp(url,dev->url,MAX_URL)) { 
+               // found it
+               spin_lock_irqsave(&(dev->lock),f2);
+               if (dev->connected) { 
+                   printk("palacios: device for \"%s\" is already connected!\n",url);
+                   spin_unlock_irqrestore(&(dev->lock),f2);
+                   spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+                   return -1;
+               } else {
+                   dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
+                   if (dev->fd<0) { 
+                       printk("palacios: cannot create fd for device \"%s\"\n",url);
+                       spin_unlock_irqrestore(&(dev->lock),f2);
+                       spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+                       return -1;
+                   }
+                   dev->connected=1;
+                   dev->waiting=0;
+                   if (dev->req) { 
+                       kfree(dev->req);
+                       dev->req=0;
+                   } 
+                   if (dev->resp) { 
+                       kfree(dev->resp);
+                       dev->resp=0;
+                   }
+                   printk("palacios: connected fd for device \"%s\"\n",url);
+                   spin_unlock_irqrestore(&(dev->lock),f2);
+                   spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+                   return dev->fd;
+               }
+               spin_unlock_irqrestore(&(dev->lock),f2);
+           }
+       }
+       spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+       
+       ssleep(RENDEZVOUS_RETRY_SECS);
+    }
+    
+    printk("palacios: timeout waiting for connection for device \"%s\"",url);
+    
+    return -1;
+    
+}
+
+
+
+
+
+
+
+
+/***************************************************************************************
+
+   Following this is the implementation of the palacios->host interface
+
+**************************************************************************************/
+
+static v3_host_dev_t palacios_host_dev_open(char *url,
+                                           v3_bus_class_t bus,
+                                           v3_guest_dev_t gdev,
+                                           void *host_priv_data)
+{
+    struct v3_guest *guest= (struct v3_guest*)host_priv_data;
+    struct palacios_host_device_user *dev;
+    unsigned long f1,f2;
+    int i;
+
+    /*
+      I will create the device in the list and then wait
+      for the user side to attach
+    */
+
+
+    if (strncasecmp(url,"user:",5)) { 
+       printk("palacios: do not currently support devices of type in \"%s\"\n",url);
+       return NULL;
+    }
+
+    // Check to see if a device of this url already exists, which would be ugly
+    spin_lock_irqsave(&(guest->hostdev.lock),f1);
+    list_for_each_entry(dev,&(guest->hostdev.devs), node) {
+       if (!strncasecmp(url,dev->url,MAX_URL)) { 
+           // found it
+           spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+           printk("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
+           return NULL;
+       }
+    }
+    spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+
+
+    printk("palacios: creating host device \"%s\"\n",url);
+
+    dev = kmalloc(sizeof(struct palacios_host_device_user),GFP_KERNEL);
+    
+    if (!dev) { 
+       printk("palacios: cannot allocate for host device \"%s\"\n",url);
+       return NULL;
+    }
+
+    memset(dev,0,sizeof(struct palacios_host_device_user));
+    
+    strncpy(dev->url,url,MAX_URL);
+    
+    dev->guestdev=gdev;
+    
+    dev->guest=guest;
+
+    spin_lock_init(&(dev->lock));
+
+    init_waitqueue_head(&(dev->user_wait_queue));
+    init_waitqueue_head(&(dev->host_wait_queue));
+
+    printk("palacios: attempting to rendezvous with user side of host device \"%s\"\n",url);
+    
+    // Insert ourselves into the list
+    spin_lock_irqsave(&(guest->hostdev.lock),f1);
+    list_add(&(dev->node),&(guest->hostdev.devs));
+    spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+
+    
+    // Now wait until we are noticed!
+    for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
+       spin_lock_irqsave(&(dev->lock),f2);
+       if (dev->connected){ 
+           printk("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
+           spin_unlock_irqrestore(&(dev->lock),f2);
+           return dev;
+       }
+       spin_unlock_irqrestore(&(dev->lock),f2);
+       ssleep(RENDEZVOUS_RETRY_SECS);
+    }
+    
+    printk("palacios: timeout waiting for user side to connect to host device \"%s\"",url);
+    
+    // get us out of the list
+    spin_lock_irqsave(&(guest->hostdev.lock),f1);
+    list_del(&(dev->node));
+    spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+    
+    palacios_host_dev_user_free(dev);
+    
+    return NULL;
+}
+
+static int palacios_host_dev_close(v3_host_dev_t hostdev)
+{
+    unsigned long f1, f2;
+
+    struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
+    
+    printk("palacios: closing host device \"%s\"\n",dev->url);
+
+    spin_lock_irqsave(&(dev->guest->hostdev.lock),f1);
+
+    spin_lock_irqsave(&(dev->lock),f2);
+
+    if (dev->connected) { 
+       dev->connected=0;
+       // After this, any user side request will return -EFAULT
+    }
+
+    list_del(&(dev->node));
+    
+    spin_unlock_irqrestore(&(dev->lock),f2);
+    spin_unlock_irqrestore(&(dev->guest->hostdev.lock),f1);
+    
+    palacios_host_dev_user_free(dev);
+
+    return 0;
+}
+
+
+
+       
+static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
+                                         uint16_t      port,
+                                         void          *dest,
+                                         uint64_t      len)
+{
+    struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
+    unsigned long f;
+    uint64_t op_len;
+
+    spin_lock_irqsave(&(dev->lock),f);
+    
+    if (dev->waiting) { 
+       printk("palacios: guest issued i/o read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+
+    if (!dev->connected) {
+       printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    
+    // resize request and response in case they will need it
+    palacios_resize_reqresp(&(dev->req),0,0); // request doesn't carry data
+
+    dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
+    dev->req->port=port;
+    dev->req->op_len=len;
+    dev->req->gpa=0;
+    dev->req->conf_addr=0;
+    dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
+
+    dev->waiting=1;
+    
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    // hand over to the user space and wait for it to respond
+    cycle_request_response(dev);
+
+    // We're back!   So now we'll hand the response back to Palacios
+
+    spin_lock_irqsave(&(dev->lock),f);
+
+    op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
+
+    memcpy(dest,dev->resp->data, op_len);
+    
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    return op_len;
+}
+
+static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
+                                          void *        gpa,
+                                          void          *dest,
+                                          uint64_t      len)
+{
+    struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
+    unsigned long f;
+    uint64_t op_len;
+
+    spin_lock_irqsave(&(dev->lock),f);
+    
+    if (dev->waiting) { 
+       printk("palacios: guest issued memory read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    if (!dev->connected) {
+       printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    
+    // resize request and response in case they will need it
+    palacios_resize_reqresp(&(dev->req),0,0); // request doesn't carry data
+
+    dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
+    dev->req->port=0;
+    dev->req->op_len=len;
+    dev->req->gpa=gpa;
+    dev->req->conf_addr=0;
+    dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
+
+    dev->waiting=1;
+    
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    // hand over to the user space and wait for it to respond
+    cycle_request_response(dev);
+
+    // We're back!   So now we'll hand the response back to Palacios
+
+    spin_lock_irqsave(&(dev->lock),f);
+
+    op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
+
+    memcpy(dest,dev->resp->data, op_len);
+    
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    return op_len;
+}
+
+static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
+                                           uint64_t      offset,
+                                           void          *dest,
+                                           uint64_t      len)
+{
+    struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
+    unsigned long f;
+    uint64_t op_len;
+
+    spin_lock_irqsave(&(dev->lock),f);
+    
+    if (dev->waiting) { 
+       printk("palacios: guest issued config read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    if (!dev->connected) {
+       printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    
+    // resize request and response in case they will need it
+    palacios_resize_reqresp(&(dev->req),0,0); // request doesn't carry data
+
+    dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
+    dev->req->port=0;
+    dev->req->op_len=len;
+    dev->req->gpa=0;
+    dev->req->conf_addr=offset;
+    dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
+
+    dev->waiting=1;
+    
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    // hand over to the user space and wait for it to respond
+    cycle_request_response(dev);
+
+    // We're back!   So now we'll hand the response back to Palacios
+
+    spin_lock_irqsave(&(dev->lock),f);
+
+    op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
+
+    memcpy(dest,dev->resp->data, op_len);
+    
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    return op_len;
+}
+
+
+static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
+                                          uint16_t      port,
+                                          void          *src,
+                                          uint64_t      len)
+{
+    struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
+    unsigned long f;
+    uint64_t op_len;
+
+    spin_lock_irqsave(&(dev->lock),f);
+    
+    if (dev->waiting) { 
+       printk("palacios: guest issued i/o write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    if (!dev->connected) {
+       printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+
+    // resize request and response in case they will need it
+    palacios_resize_reqresp(&(dev->req),len,0); // make room for data
+
+    dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
+    dev->req->port=port;
+    dev->req->op_len=len;
+    dev->req->gpa=0;
+    dev->req->conf_addr=0;
+    dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
+
+    memcpy(dev->req->data,src,len);
+
+    dev->waiting=1;
+    
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    // hand over to the user space and wait for it to respond
+    cycle_request_response(dev);
+
+    // We're back!   So now we'll hand the response back to Palacios
+
+    spin_lock_irqsave(&(dev->lock),f);
+
+    op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
+
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    return op_len;
+}
+
+
+static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
+                                           void *        gpa,
+                                           void          *src,
+                                           uint64_t      len)
+{
+    struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
+    unsigned long f;
+    uint64_t op_len;
+
+    spin_lock_irqsave(&(dev->lock),f);
+    
+    if (dev->waiting) { 
+       printk("palacios: guest issued memory write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    if (!dev->connected) {
+       printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    
+    // resize request and response in case they will need it
+    palacios_resize_reqresp(&(dev->req),len,0); // make room for data
+
+    dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
+    dev->req->port=0;
+    dev->req->op_len=len;
+    dev->req->gpa=gpa;
+    dev->req->conf_addr=0;
+    dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
+
+    memcpy(dev->req->data,src,len);
+
+    dev->waiting=1;
+    
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    // hand over to the user space and wait for it to respond
+    cycle_request_response(dev);
+
+    // We're back!   So now we'll hand the response back to Palacios
+
+    spin_lock_irqsave(&(dev->lock),f);
+
+    op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
+
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    return op_len;
+}
+
+
+static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
+{
+    // we don't care
+    return 0;
+}
+
+
+static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
+                                            uint64_t      offset,
+                                            void          *src,
+                                            uint64_t      len)
+{
+    struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
+    unsigned long f;
+    uint64_t op_len;
+
+    spin_lock_irqsave(&(dev->lock),f);
+    
+    if (dev->waiting) { 
+       printk("palacios: guest issued config write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    if (!dev->connected) {
+       printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       spin_unlock_irqrestore(&(dev->lock),f);
+       return 0;
+    }
+    
+    // resize request and response in case they will need it
+    palacios_resize_reqresp(&(dev->req),len,0); // make room for data
+
+    dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
+    dev->req->port=0;
+    dev->req->op_len=len;
+    dev->req->gpa=0;
+    dev->req->conf_addr=offset;
+    dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
+
+    memcpy(dev->req->data,src,len);
+
+    dev->waiting=1;
+    
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    // hand over to the user space and wait for it to respond
+    cycle_request_response(dev);
+
+    // We're back!   So now we'll hand the response back to Palacios
+
+    spin_lock_irqsave(&(dev->lock),f);
+
+    op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
+
+    spin_unlock_irqrestore(&(dev->lock),f);
+
+    return op_len;
+ }
+
+
+
+
+static struct v3_host_dev_hooks palacios_host_dev_hooks = {
+    .open                      = palacios_host_dev_open,
+    .close                      = palacios_host_dev_close,
+    .read_io                    = palacios_host_dev_read_io,
+    .write_io                   = palacios_host_dev_write_io,
+    .read_mem                   = palacios_host_dev_read_mem,
+    .write_mem                  = palacios_host_dev_write_mem,
+    .read_config                = palacios_host_dev_read_conf,
+    .write_config               = palacios_host_dev_write_conf,
+    .ack_irq                    = palacios_host_dev_ack_irq,
+};
+
+
+
+int palacios_init_host_dev( void ) {
+    V3_Init_Host_Device_Support(&palacios_host_dev_hooks);
+    
+    return 0;
+}
diff --git a/linux_module/palacios-host-dev.h b/linux_module/palacios-host-dev.h
new file mode 100644 (file)
index 0000000..d444b7d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Palacios Host Device Interface + User-space interface 
+ * (c) Peter Dinda, 2011
+ */
+
+#ifndef __PALACIOS_HOST_DEV_H__
+#define __PALACIOS_HOST_DEV_H__
+
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include "palacios-host-dev-user.h"
+
+struct v3_guest;
+
+/*
+   This is the collection of host devices that
+   a single guest has
+*/
+struct palacios_host_dev {
+    spinlock_t      lock;
+    struct list_head devs;
+};
+
+
+
+int connect_host_dev(struct v3_guest * guest, char *url);
+
+int palacios_init_host_dev( void );
+
+
+#endif
similarity index 80%
rename from linux_module/palacios-debugfs.c
rename to linux_module/palacios-inspector.c
index b35120e..a3b5ac9 100644 (file)
@@ -15,7 +15,7 @@
 struct dentry * v3_dir = NULL;
 
 
-int palacios_init_debugfs( void ) {
+int palacios_init_inspector( void ) {
 
     v3_dir = debugfs_create_dir("v3vee", NULL);
 
@@ -28,7 +28,7 @@ int palacios_init_debugfs( void ) {
 }
 
 
-int palacios_deinit_debugfs( void ) {
+int palacios_deinit_inspector( void ) {
     debugfs_remove(v3_dir);
     return 0;
 }
@@ -66,14 +66,23 @@ static int dfs_register_tree(struct dentry * dir, v3_inspect_node_t * root) {
 }
 
 
-int dfs_register_vm(struct v3_guest * guest) {
+int inspect_vm(struct v3_guest * guest) {
     v3_inspect_node_t * root = v3_get_inspection_root(guest->v3_ctx);
+    struct dentry * guest_dir = NULL;
+
 
     if (root == NULL) {
        printk("No inspection root found\n");
        return -1;
     }
 
-    dfs_register_tree(v3_dir, root);
+    guest_dir = debugfs_create_dir(guest->name, v3_dir);
+
+    if (IS_ERR(guest_dir)) {
+       printk("Error Creating inspector tree for VM \"%s\"\n", guest->name);
+       return -1;
+    }
+
+    dfs_register_tree(guest_dir, root);
     return 0;
 }
diff --git a/linux_module/palacios-inspector.h b/linux_module/palacios-inspector.h
new file mode 100644 (file)
index 0000000..ad966df
--- /dev/null
@@ -0,0 +1,14 @@
+/* 
+ * DebugFS interface
+ * (c) Jack Lange, 2011
+ */
+
+#include "palacios.h"
+
+int palacios_init_inspector( void );
+int palacios_deinit_inspector( void );
+
+
+
+int inspect_vm(struct v3_guest * guest);
+
diff --git a/linux_module/palacios-keyed-stream.c b/linux_module/palacios-keyed-stream.c
new file mode 100644 (file)
index 0000000..b3fbe2b
--- /dev/null
@@ -0,0 +1,297 @@
+#include "palacios.h"
+#include "palacios-keyed-stream.h"
+#include "palacios-hashtable.h"
+
+#define sint64_t int64_t
+#include <interfaces/vmm_keyed_stream.h>
+
+/*
+  Streams are stored in a hash table
+  The values for this hash table are hash tables associted with 
+  each stream.   A keyed stream for a "mem:" stream is 
+  an instance of the structure given here 
+*/
+
+#define DEF_NUM_STREAMS 16
+#define DEF_NUM_KEYS    128
+#define DEF_SIZE        128
+
+struct mem_stream {
+    char     *data;
+    uint32_t  size;
+    uint32_t  data_max;
+    uint32_t  ptr;
+};
+
+static struct mem_stream *create_mem_stream(void)
+{
+    struct mem_stream *m = kmalloc(sizeof(struct mem_stream),GFP_KERNEL);
+
+    if (!m) {
+       return 0;
+    }
+
+    m->data = kmalloc(DEF_SIZE,GFP_KERNEL);
+    
+    if (!m->data) { 
+       kfree(m);
+       return 0;
+    }
+
+    m->size=DEF_SIZE;
+    m->ptr=0;
+    m->data_max=0;
+    
+    return m;
+}
+
+static void destroy_mem_stream(struct mem_stream *m)
+{
+    if (m) {
+       if (m->data) {
+           kfree(m->data);
+       }
+       m->data=0;
+       kfree(m);
+    }
+}
+    
+static int expand_mem_stream(struct mem_stream *m, uint32_t new_size)
+{
+    void *data = kmalloc(new_size,GFP_KERNEL);
+    uint32_t nc;
+
+    if (!data) { 
+       return -1;
+    }
+    
+    nc = (new_size<m->data_max) ? new_size : m->data_max;
+
+    memcpy(data,m->data,nc);
+
+    kfree(m->data);
+
+    m->data=data;
+    m->size=new_size;
+    if (m->size<m->data_max) { 
+       m->data_max=m->size;
+    }
+   
+    return 0;
+}
+
+static uint32_t write_mem_stream(struct mem_stream *m,
+                                void *data,
+                                uint32_t len)
+{
+    if ((m->ptr + len) > m->size) { 
+       if (expand_mem_stream(m,m->ptr + len)) { 
+           return 0;
+       }
+    }
+    memcpy(m->data+m->ptr,data,len);
+    m->ptr+=len;
+    m->data_max=m->ptr;
+    
+    return len;
+
+}
+
+static uint32_t read_mem_stream(struct mem_stream *m,
+                               void *data,
+                               uint32_t len)
+{
+    if ((m->ptr + len) > m->data_max) { 
+       return 0;
+    }
+    memcpy(data,m->data+m->ptr,len);
+    m->ptr+=len;
+    
+    return len;
+
+}
+
+
+static void reset_mem_stream(struct mem_stream *m)
+{
+    m->ptr=0;
+}
+
+
+static inline uint_t hash_func(addr_t key)
+{
+    return palacios_hash_buffer((uchar_t*)key,strlen((uchar_t*)key));
+}
+
+static inline int hash_comp(addr_t k1, addr_t k2)
+{
+    return strcasecmp((char*)k1,(char*)k2)==0;
+}
+
+
+// This stores all the streams
+static struct hashtable *streams=0;
+
+
+static v3_keyed_stream_t open_stream(char *url,
+                                    v3_keyed_stream_open_t ot)
+{
+    if (strncasecmp(url,"mem:",4)) { 
+       printk("Only in-memory streams are currently supported\n");
+       return 0;
+    }
+
+    switch (ot) { 
+       case V3_KS_RD_ONLY:
+       case V3_KS_WR_ONLY:
+           return (v3_keyed_stream_t) palacios_htable_search(streams,(addr_t)(url+4));
+           break;
+       case V3_KS_WR_ONLY_CREATE: {
+           struct hashtable *s = (struct hashtable *) palacios_htable_search(streams,(addr_t)(url+4));
+
+           if (!s) { 
+                s = palacios_create_htable(DEF_NUM_KEYS,hash_func,hash_comp);
+                if (!s) { 
+                    printk("Cannot allocate in-memory keyed stream %s\n",url);
+                    return 0;
+                }
+                if (!palacios_htable_insert(streams,(addr_t)(url+4),(addr_t)s)) { 
+                    printk("Cannot insert in-memory keyed stream %s\n",url);
+                    return 0;
+                }
+           }
+
+           return s;
+           
+       }
+
+           break;
+    }
+    
+    return 0;
+    
+}
+
+
+static void close_stream(v3_keyed_stream_t stream)
+{
+    // nothing to do
+    return;
+}
+
+static v3_keyed_stream_key_t open_key(v3_keyed_stream_t stream,
+                                     char *key)
+{
+    struct hashtable *s = (struct hashtable *) stream;
+
+    struct mem_stream *m;
+
+    m = (struct mem_stream *) palacios_htable_search(s,(addr_t)key);
+
+    if (!m) { 
+       m = create_mem_stream();
+       
+       if (!m) { 
+           printk("Cannot allocate keyed stream for key %s\n",key);
+           return 0;
+       }
+
+       if (!palacios_htable_insert(s,(addr_t)key,(addr_t)m)) {
+           printk("Cannot insert keyed stream for key %s\n",key);
+           destroy_mem_stream(m);
+           return 0;
+       }
+    }
+
+    reset_mem_stream(m);
+    return m;
+
+}
+
+static void close_key(v3_keyed_stream_t stream, 
+                     v3_keyed_stream_key_t key)
+{
+    // nothing to do
+    return;
+}
+
+static sint64_t write_key(v3_keyed_stream_t stream, 
+                         v3_keyed_stream_key_t key,
+                         void *buf,
+                         sint64_t len)
+{
+    struct mem_stream *m = (struct mem_stream *) key;
+    uint32_t mylen;
+    uint32_t writelen;
+
+    if (len<0) { 
+       return len;
+    }
+    
+    mylen = (uint32_t) len;
+
+    writelen=write_mem_stream(m,buf,mylen);
+
+    if (writelen!=mylen) { 
+       printk("Failed to write all data for key\n");
+       return -1;
+    } else {
+       return (sint64_t)writelen;
+    }
+}
+
+static sint64_t read_key(v3_keyed_stream_t stream, 
+                        v3_keyed_stream_key_t key,
+                        void *buf,
+                        sint64_t len)
+{
+    struct mem_stream *m = (struct mem_stream *) key;
+    uint32_t mylen;
+    uint32_t readlen;
+    
+    if (len<0) { 
+       return len;
+    }
+    
+    mylen = (uint32_t) len;
+
+    readlen=read_mem_stream(m,buf,mylen);
+
+    if (readlen!=mylen) { 
+       printk("Failed to read all data for key\n");
+       return -1;
+    } else {
+       return (sint64_t)readlen;
+    }
+}
+    
+static struct v3_keyed_stream_hooks hooks = {
+    .open = open_stream,
+    .close = close_stream,
+    .open_key = open_key,
+    .close_key = close_key,
+    .read_key = read_key,
+    .write_key = write_key
+};
+
+
+int palacios_init_keyed_streams()
+{
+    streams = palacios_create_htable(DEF_NUM_STREAMS,hash_func,hash_comp);
+
+    if (!streams) { 
+       printk("Failed to allocated stream pool\n");
+       return -1;
+    }
+
+    V3_Init_Keyed_Streams(&hooks);
+    
+    return 0;
+
+}
+
+int palacios_deinit_keyed_streams()
+{
+    printk("DEINIT OF PALACIOS KEYED STREAMS NOT IMPLEMENTED - WE HAVE JUST LEAKED MEMORY!\n");
+    return -1;
+}
diff --git a/linux_module/palacios-keyed-stream.h b/linux_module/palacios-keyed-stream.h
new file mode 100644 (file)
index 0000000..218ed51
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Palacios VM Keyed Stream Interface (for checkpoint/restore)
+ * Copyright (c) 2011 Peter Dinda <pdinda@northwestern.edu>
+ */
+
+#ifndef __PALACIOS_KEYED_STREAM_H__
+#define __PALACIOS_KEYED_STREAM_H__
+
+
+
+int palacios_init_keyed_streams(void);
+int palacios_deinit_keyed_streams(void);
+
+
+#endif
index 1907507..83404de 100644 (file)
  
 #include <interfaces/vmm_packet.h>
 #include <palacios/vmm_host_events.h>
-#include <palacios/vmm_vnet.h>
-#include <palacios/vmm_ethernet.h>
-
-/* We should be able to use type define from Palacios header files */
-typedef unsigned char uchar_t;
-typedef unsigned int uint_t;
-typedef unsigned long long ullong_t;
-typedef unsigned long ulong_t;
-typedef ulong_t addr_t;
+#include <vnet/vnet.h>
 
 #define __V3VEE__
 #include <palacios/vmm_hashtable.h>
+#include <palacios/vmm_ethernet.h>
 #undef __V3VEE__
 
 #include "palacios.h"
@@ -147,14 +140,11 @@ palacios_packet_send(const char * pkt, unsigned int len, void * private_data) {
     size = sock_sendmsg(packet_state.raw_sock, &msg, len);
     set_fs(oldfs);
 
-#if 1
-    {
-       printk("Palacios Packet: send pkt to NIC (size: %d)\n", 
-                       len);
+    if(vnet_debug >= 4){
+       printk("Palacios Packet: send pkt to NIC (size: %d)\n", len);
        print_hex_dump(NULL, "pkt_header: ", 0, 20, 20, pkt, 20, 0);
        printk("palacios_packet_send return: %d\n", size);
     }
-#endif
 
     return size;
 }
@@ -228,13 +218,10 @@ static int packet_server(void * arg) {
            break;
        }
 
-#if 1
-    {
-       printk("Palacios Packet: receive pkt from NIC (size: %d)\n", 
-                       size);
-       print_hex_dump(NULL, "pkt_header: ", 0, 10, 10, pkt, 20, 0);
-    }
-#endif
+       if(vnet_debug >= 4){
+           printk("Palacios Packet: receive pkt from NIC (size: %d)\n",size);
+           print_hex_dump(NULL, "pkt_header: ", 0, 10, 10, pkt, 20, 0);
+       }
 
        /* if VNET is enabled, send to VNET */
        // ...
@@ -244,7 +231,7 @@ static int packet_server(void * arg) {
        // ...
 
 
-       vm = (struct v3_vm_info *)v3_htable_search(packet_state.mac_vm_cache, (addr_t)pkt);
+       vm = (struct v3_vm_info *)v3_htable_search(packet_state.mac_vm_cache, (addr_t)pkt);
        if(vm != NULL){
            printk("Find destinated VM 0x%p\n", vm);
            send_raw_packet_to_palacios(pkt, size, vm);
index 476f473..9b26e40 100644 (file)
@@ -7,5 +7,6 @@
 #define __PALACIOS_PACKET_H__
 
 int palacios_init_packet(const char * eth_dev);
+int palacios_deinit_packet(void);
 
 #endif
diff --git a/linux_module/palacios-serial.c b/linux_module/palacios-serial.c
deleted file mode 100644 (file)
index 355f4d4..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/* 
- * VM Serial Controls
- * (c) Lei Xia, 2010
- */
-
-#include <linux/device.h>
-#include <linux/cdev.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-#include <linux/poll.h>
-#include <linux/anon_inodes.h>
-#include <linux/file.h>
-
-#include <palacios/vmm.h>
-#include <palacios/vmm_host_events.h>
-
-#include "palacios.h"
-#include "palacios-stream.h"
-
-
-void
-send_serial_input_to_palacios( unsigned char *input,
-                              unsigned int len,
-                              struct v3_vm_info * vm ) {
-    struct v3_serial_event event;
-
-    if (len > 128) {
-       len = 128;
-    }
-
-    memcpy(event.data, input, len);
-    event.len = len;
-       
-    v3_deliver_serial_event(vm, &event);
-}
-
-static ssize_t 
-serial_read(struct file * filp, char __user * buf, size_t size, loff_t * offset) {
-
-    int len = 0;
-    char temp[128];
-    struct stream_buffer * stream = filp->private_data;
-       
-    memset(temp, 0, 128);
-
-    if (size > 128) {
-       size = 128;
-    }
-       
-    len =  stream_dequeue(stream, temp, size);
-       
-    if (copy_to_user(buf, temp, len)) {
-       printk("Read fault\n");
-       return -EFAULT;
-    }
-
-    printk("Returning %d bytes\n", len);
-
-    return len;
-}
-
-static ssize_t 
-serial_write(struct file * filp, const char __user * buf, size_t size, loff_t * offset) {
-    char temp[128];
-    struct stream_buffer * stream = filp->private_data;
-    struct v3_vm_info * vm;
-
-    memset(temp, 0, 128);
-
-    if (size > 128) {
-       size = 128;
-    }
-
-    if (copy_from_user(temp, buf, size)) {
-       printk("Write fault\n");
-       return -EFAULT;
-    }
-
-    vm = stream->guest->v3_ctx;
-    send_serial_input_to_palacios(temp, size, vm);
-   
-    return size;
-}
-
-
-static unsigned int 
-serial_poll(struct file * filp, struct poll_table_struct * poll_tb) {
-    unsigned int mask = 0;
-    struct stream_buffer *stream = filp->private_data;
-  
-    poll_wait(filp, &(stream->intr_queue), poll_tb);
-
-    if(stream_datalen(stream) > 0){
-       mask = POLLIN | POLLRDNORM;
-    }
-       
-    printk("polling v3 serial\n");
-
-    return mask;
-}
-
-static struct file_operations v3_cons_fops = {
-    .read     = serial_read,
-    .write    = serial_write,
-    .poll     = serial_poll,
-};
-
-
-int open_serial(char * name) {
-    int cons_fd;
-    void *stream;
-
-    printk("open path: %s\n", name);
-
-    stream = find_stream_by_name(NULL, name);
-
-    if (stream == NULL) {
-       return -1;
-    }
-
-    cons_fd = anon_inode_getfd("v3-cons", &v3_cons_fops, stream, 0);
-    
-    if (cons_fd < 0) {
-       printk("Error creating serial inode\n");
-       return cons_fd;
-    }
-
-    printk("Returning new serial fd\n");
-           
-    return cons_fd;
-}
index 28b613f..8d17d8f 100644 (file)
@@ -436,3 +436,10 @@ int palacios_socket_init( void ) {
        INIT_LIST_HEAD(&global_sockets);
        return 0;
 }
+
+void palacios_socket_deinit( void ) {
+    if (!list_empty(&(global_sockets))) {
+       printk("Error removing module with open sockets\n");
+    }
+}
+
index 098b6dd..394802e 100644 (file)
@@ -7,5 +7,6 @@
 #define __PALACIOS_SOCKET_H__
 
 int palacios_socket_init(void);
+int palacios_socket_deinit(void);
 
 #endif
index e79f093..340d27f 100644 (file)
@@ -12,7 +12,7 @@
 
 static struct list_head global_streams;
 
-int stream_enqueue(struct stream_buffer * stream, char * buf, int len) {
+static int stream_enqueue(struct stream_buffer * stream, char * buf, int len) {
     int bytes = 0;
 
     bytes = ringbuf_write(stream->buf, buf, len);
@@ -34,6 +34,12 @@ int stream_datalen(struct stream_buffer * stream){
 }
 
 
+int open_stream(const char * name) {
+    return -1;
+}
+
+
+
 struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const char * name) {
     struct stream_buffer * stream = NULL;
     struct list_head * stream_list = NULL;
index f3b21a0..d3b73e1 100644 (file)
@@ -32,11 +32,12 @@ struct stream_buffer {
 
 void palacios_init_stream(void);
 void palacios_deinit_stream(void);
-int stream_enqueue(struct stream_buffer * stream, char * buf, int len);
+
 int stream_dequeue(struct stream_buffer * stream, char * buf, int len);
 int stream_datalen(struct stream_buffer * stream);
 
 struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const char * name);
 
+int open_stream(const char * name);
 #endif
 
index 0e1f51e..dd422c3 100644 (file)
 #include <linux/file.h>
 #include <linux/spinlock.h>
 
-#ifdef CONFIG_DEBUG_FS
-#include "palacios-debugfs.h"
-#endif
 
 #include <palacios/vmm.h>
 
 #include "palacios.h"
-#include "palacios-console.h"
-#include "palacios-serial.h"
 #include "palacios-vm.h"
 
+#ifdef V3_CONFIG_STREAM
+#include "palacios-stream.h"
+#endif
+
+#ifdef V3_CONFIG_CONSOLE
+#include "palacios-console.h"
+#endif
+
+#ifdef V3_CONFIG_EXT_INSPECTOR
+#include "palacios-inspector.h"
+#endif
+
+#ifdef V3_CONFIG_GRAPHICS_CONSOLE
+#include "palacios-graphics-console.h"
+#endif
+
+#ifdef V3_CONFIG_HOST_DEVICE
+#include "palacios-host-dev.h"
+#endif
 
 extern struct class * v3_class;
 #define STREAM_NAME_LEN 128
 
 static long v3_vm_ioctl(struct file * filp,
                        unsigned int ioctl, unsigned long arg) {
-    void __user * argp = (void __user *)arg;
-    char path_name[STREAM_NAME_LEN];
 
     struct v3_guest * guest = filp->private_data;
 
@@ -43,24 +55,74 @@ static long v3_vm_ioctl(struct file * filp,
 
     switch (ioctl) {
 
+       case V3_VM_STOP: {
+           printk("Stopping VM\n");
+           stop_palacios_vm(guest);
+           break;
+       }
+
        case V3_VM_CONSOLE_CONNECT: {
+#ifdef V3_CONFIG_CONSOLE
            return connect_console(guest);
+#else
+           printk("Console support not available\n");
+           return -EFAULT;
+#endif
            break;
        }
-       case V3_VM_SERIAL_CONNECT: {
+
+       case V3_VM_STREAM_CONNECT: {
+#ifdef V3_CONFIG_STREAM
+           void __user * argp = (void __user *)arg;
+           char path_name[STREAM_NAME_LEN];
+
            if (copy_from_user(path_name, argp, STREAM_NAME_LEN)) {
-               printk("copy from user error getting guest image...\n");
+               printk("%s(%d): copy from user error...\n", __FILE__, __LINE__);
                return -EFAULT;
            }
 
-           return open_serial(path_name);
+           return open_stream(path_name);
+#else
+           printk("Stream support Not available\n");
+           return -EFAULT;
+#endif
            break;
        }
-       case V3_VM_STOP: {
-           printk("Stopping VM\n");
-           stop_palacios_vm(guest);
+
+       case V3_VM_HOST_DEV_CONNECT: {
+#ifdef V3_CONFIG_HOST_DEV
+           if (copy_from_user(host_dev_url, argp, HOST_DEV_URL_LEN)) {
+               printk("copy from user error getting url for host device connect...\n");
+               return -EFAULT;
+           }
+
+           return connect_host_dev(guest,host_dev_url);
+#else
+           printk("palacios: Host device support not available\n");
+           return -EFAULT;
+#endif
            break;
        }
+
+       case V3_VM_FB_INPUT: 
+#ifdef V3_CONFIG_GRAPHICS_CONSOLE
+           return palacios_graphics_console_user_input(&(guest->graphics_console),
+                                                       (struct v3_fb_input __user *) arg) ;
+#else
+           return -EFAULT;
+#endif
+           break;
+           
+       case V3_VM_FB_QUERY: 
+#ifdef V3_CONFIG_GRAPHICS_CONSOLE
+           return palacios_graphics_console_user_query(&(guest->graphics_console),
+                                                       (struct v3_fb_query_response __user *) arg);
+#else
+           return -EFAULT;
+#endif
+           break;
+
+
        default: 
            printk("\tUnhandled\n");
            return -EINVAL;
@@ -83,7 +145,6 @@ static ssize_t v3_vm_read(struct file * filp, char __user * buf, size_t size, lo
 
 
 static ssize_t v3_vm_write(struct file * filp, const char __user * buf, size_t size, loff_t * offset) {
-    
 
     return 0;
 }
@@ -99,7 +160,6 @@ static struct file_operations v3_vm_fops = {
 };
 
 
-
 extern int vm_running;
 extern u32 pg_allocs;
 extern u32 pg_frees;
@@ -112,7 +172,7 @@ int start_palacios_vm(void * arg)  {
 
     lock_kernel();
     daemonize(guest->name);
-//    allow_signal(SIGKILL);
+    // allow_signal(SIGKILL);
     unlock_kernel();
     
 
@@ -120,12 +180,13 @@ int start_palacios_vm(void * arg)  {
 
     if (guest->v3_ctx == NULL) { 
        printk("palacios: failed to create vm\n");
+       complete(&(guest->start_done));
        return -1;
     }
 
     printk("Creating VM device: Major %d, Minor %d\n", MAJOR(guest->vm_dev), MINOR(guest->vm_dev));
 
-    cdev_init(&(guest->cdev), &v3_vm_fops);    
+    cdev_init(&(guest->cdev), &v3_vm_fops);
 
     guest->cdev.owner = THIS_MODULE;
     guest->cdev.ops = &v3_vm_fops;
@@ -136,27 +197,34 @@ int start_palacios_vm(void * arg)  {
 
     if (err) {
        printk("Fails to add cdev\n");
+       v3_free_vm(guest->v3_ctx);
+       complete(&(guest->start_done));
        return -1;
     }
 
     if (device_create(v3_class, NULL, guest->vm_dev, guest, "v3-vm%d", MINOR(guest->vm_dev)) == NULL){
        printk("Fails to create device\n");
+       cdev_del(&(guest->cdev));
+       v3_free_vm(guest->v3_ctx);
+       complete(&(guest->start_done));
        return -1;
     }
 
     complete(&(guest->start_done));
 
-    printk("palacios: launching vm\n");   
-
+    printk("palacios: launching vm\n");
 
 
-#if CONFIG_DEBUG_FS
-    dfs_register_vm(guest);
+#ifdef V3_CONFIG_EXT_INSPECTOR
+    inspect_vm(guest);
 #endif
 
 
     if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { 
        printk("palacios: launch of vm failed\n");
+       device_destroy(v3_class, guest->vm_dev);
+       cdev_del(&(guest->cdev));
+       v3_free_vm(guest->v3_ctx);
        return -1;
     }
     
diff --git a/linux_module/palacios-vnet-brg.c b/linux_module/palacios-vnet-brg.c
new file mode 100644 (file)
index 0000000..e87d422
--- /dev/null
@@ -0,0 +1,520 @@
+/* 
+   Palacios VNET Host Bridge
+   (c) Lei Xia, 2010
+ */
+#include <linux/spinlock.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <linux/inet.h>
+#include <linux/kthread.h>
+
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/net.h>
+#include <linux/string.h>
+#include <linux/preempt.h>
+#include <linux/sched.h>
+#include <asm/msr.h>
+
+#include <vnet/vnet.h>
+#include <vnet/vnet_hashtable.h>
+#include "palacios-vnet.h"
+
+#define VNET_SERVER_PORT 9000
+
+struct vnet_link {
+    uint32_t dst_ip;
+    uint16_t dst_port;
+    
+    struct socket * sock;
+    struct sockaddr_in sock_addr;
+    vnet_brg_proto_t sock_proto;
+
+    struct nic_statistics stats;
+
+    uint32_t idx;
+
+    struct list_head node;
+};
+
+
+struct vnet_brg_state {
+    uint8_t status;
+
+    uint32_t num_links;
+    uint32_t link_idx;
+    struct list_head link_list;
+    struct hashtable *ip2link;
+
+    spinlock_t lock;
+
+    struct socket * serv_sock;
+    struct sockaddr_in serv_addr;
+    vnet_brg_proto_t serv_proto;
+       
+    struct task_struct * serv_thread;
+
+    void * brg_data; /* private data from vnet_core */
+
+    struct vnet_brg_stats stats;
+};
+
+
+static struct vnet_brg_state vnet_brg_s;
+
+
+int vnet_brg_stats(struct vnet_brg_stats * stats){
+    memcpy(stats, &(vnet_brg_s.stats), sizeof(*stats));
+
+    return 0;
+}
+
+static inline struct vnet_link * _link_by_ip(uint32_t ip) {
+    return (struct vnet_link *)vnet_htable_search(vnet_brg_s.ip2link, (addr_t)&ip);
+}
+
+static inline struct vnet_link * _link_by_idx(int idx) {
+    struct vnet_link * link = NULL;
+
+    list_for_each_entry(link, &(vnet_brg_s.link_list), node) {
+               
+       if (link->idx == idx) {
+           return link;
+       }
+    }
+    return NULL;
+}
+
+
+static void _delete_link(struct vnet_link * link){
+    unsigned long flags;
+
+    link->sock->ops->release(link->sock);
+
+    spin_lock_irqsave(&(vnet_brg_s.lock), flags);
+    list_del(&(link->node));
+    vnet_htable_remove(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), 0);
+    vnet_brg_s.num_links --;
+    spin_unlock_irqrestore(&(vnet_brg_s.lock), flags);
+
+    printk("VNET Bridge: Link deleted, ip 0x%x, port: %d, idx: %d\n", 
+          link->dst_ip, 
+          link->dst_port, 
+          link->idx);
+
+    kfree(link);
+    link = NULL;
+}
+
+void vnet_brg_delete_link(uint32_t idx){
+    struct vnet_link * link = _link_by_idx(idx);
+
+    if(link){
+       _delete_link(link);
+    }
+}
+
+static void deinit_links_list(void){
+    struct vnet_link * link;
+
+    list_for_each_entry(link, &(vnet_brg_s.link_list), node) {
+       _delete_link(link);
+    }
+}
+
+static uint32_t _create_link(struct vnet_link * link) {
+    int err;
+    unsigned long flags;
+    int protocol;
+
+    switch(link->sock_proto){
+       case UDP:
+           protocol = IPPROTO_UDP;
+           break;
+       case TCP:
+           protocol = IPPROTO_TCP;
+           break;
+
+       default:
+           printk("Unsupported VNET Server Protocol\n");
+           return -1;
+    }
+   
+    if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &link->sock)) < 0) {
+       printk("Could not create socket for VNET Link, error %d\n", err);
+       return -1;
+    }
+
+    memset(&link->sock_addr, 0, sizeof(struct sockaddr));
+
+    link->sock_addr.sin_family = AF_INET;
+    link->sock_addr.sin_addr.s_addr = link->dst_ip;
+    link->sock_addr.sin_port = htons(link->dst_port);
+
+    if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0) < 0)) {
+       printk("Could not connect to remote VNET Server, error %d\n", err);
+       return -1;
+    }
+
+    spin_lock_irqsave(&(vnet_brg_s.lock), flags);
+    list_add(&(link->node), &(vnet_brg_s.link_list));
+    vnet_brg_s.num_links ++;
+    link->idx = ++ vnet_brg_s.link_idx;
+    vnet_htable_insert(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), (addr_t)link);
+    spin_unlock_irqrestore(&(vnet_brg_s.lock), flags);
+
+    printk("VNET Bridge: Link created, ip 0x%x, port: %d, idx: %d, link: %p, protocol: %s\n", 
+          link->dst_ip, 
+          link->dst_port, 
+          link->idx, 
+          link,
+          ((link->sock_proto==UDP)?"UDP":"TCP"));
+
+    return link->idx;
+}
+
+
+uint32_t vnet_brg_add_link(uint32_t ip, uint16_t port, vnet_brg_proto_t proto){
+     struct vnet_link * new_link = NULL;
+     uint32_t idx;
+
+     new_link = kmalloc(sizeof(struct vnet_link), GFP_KERNEL);
+     if (!new_link) {
+       return -1;
+     }
+     memset(new_link, 0, sizeof(struct vnet_link));
+
+     new_link->dst_ip = ip;
+     new_link->dst_port = port;
+     new_link->sock_proto = proto;
+
+     idx = _create_link(new_link);
+     if (idx < 0) {
+       printk("Could not create link\n");
+       kfree(new_link);
+       return -1;
+     }
+
+     return idx;
+}
+
+
+int vnet_brg_link_stats(uint32_t link_idx, struct nic_statistics * stats){
+     struct vnet_link * link;
+
+     link = _link_by_idx(link_idx);
+     if(!link){
+        return -1;
+     }
+
+     memcpy(stats, &(link->stats), sizeof(*stats));
+
+     return 0;
+}
+     
+
+static int 
+_udp_send(struct socket * sock, 
+        struct sockaddr_in * addr,
+        unsigned char * buf,  int len) {
+    struct msghdr msg;
+    struct iovec iov;
+    mm_segment_t oldfs;
+    int size = 0;
+
+         
+    if (sock->sk == NULL) {
+       return 0;
+    }
+
+    iov.iov_base = buf;
+    iov.iov_len = len;
+
+    msg.msg_flags = 0;
+    msg.msg_name = addr;
+    msg.msg_namelen = sizeof(struct sockaddr_in);
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = NULL;
+
+    oldfs = get_fs();
+    set_fs(KERNEL_DS);
+    size = sock_sendmsg(sock, &msg, len);
+    set_fs(oldfs);
+
+    return size;
+}
+
+
+
+static int 
+_udp_recv(struct socket * sock, 
+        struct sockaddr_in * addr,
+        unsigned char * buf, int len) {
+    struct msghdr msg;
+    struct iovec iov;
+    mm_segment_t oldfs;
+    int size = 0;
+    
+    if (sock->sk == NULL) {
+       return 0;
+    }
+
+    iov.iov_base = buf;
+    iov.iov_len = len;
+    
+    msg.msg_flags = 0;
+    msg.msg_name = addr;
+    msg.msg_namelen = sizeof(struct sockaddr_in);
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = NULL;
+    
+    oldfs = get_fs();
+    set_fs(KERNEL_DS);
+    size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
+       
+    set_fs(oldfs);
+    
+    return size;
+}
+
+/* send packets to VNET core */
+static int 
+send_to_palacios(unsigned char * buf, 
+                int len,
+                int link_id){
+    struct v3_vnet_pkt pkt;
+    pkt.size = len;
+    pkt.src_type = LINK_EDGE;
+    pkt.src_id = link_id;
+    memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
+    pkt.data = buf;
+
+    if(net_debug >= 2){
+       printk("VNET Lnx Bridge: send pkt to VNET core (size: %d, src_id: %d, src_type: %d)\n", 
+                       pkt.size,  pkt.src_id, pkt.src_type);
+       if(net_debug >= 4){
+           print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt.data, pkt.size, 0);
+       }
+    }
+
+    vnet_brg_s.stats.pkt_to_vmm ++;
+
+    return v3_vnet_send_pkt(&pkt, NULL, 1);
+}
+
+
+/* send packet to extern network */
+static int 
+bridge_send_pkt(struct v3_vm_info * vm, 
+               struct v3_vnet_pkt * pkt, 
+               void * private_data) {
+    struct vnet_link * link;
+
+    if(net_debug >= 2){
+       printk("VNET Lnx Host Bridge: packet received from VNET Core ... pkt size: %d, link: %d\n",
+                       pkt->size,
+                       pkt->dst_id);
+       if(net_debug >= 4){
+           print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt->data, pkt->size, 0);
+       }
+    }
+
+    vnet_brg_s.stats.pkt_from_vmm ++;
+
+    link = _link_by_idx(pkt->dst_id);
+    if (link != NULL) {
+       switch(link->sock_proto){
+           case UDP:
+               _udp_send(link->sock, &(link->sock_addr), pkt->data, pkt->size);
+               vnet_brg_s.stats.pkt_to_phy ++;
+               break;
+           case TCP:
+               vnet_brg_s.stats.pkt_to_phy ++;
+               break;  
+
+           default:
+               printk("VNET Server: Invalid Link Protocol\n");
+               vnet_brg_s.stats.pkt_drop_vmm ++;
+       }
+       link->stats.tx_bytes += pkt->size;
+       link->stats.tx_pkts ++;
+    } else {
+       printk("VNET Bridge Linux Host: wrong dst link, idx: %d, discards the packet\n", pkt->dst_id);
+       vnet_brg_s.stats.pkt_drop_vmm ++;
+    }
+
+    return 0;
+}
+
+
+static int init_vnet_serv(void) {
+    int protocol;
+    int err;
+
+    switch(vnet_brg_s.serv_proto){
+       case UDP:
+           protocol = IPPROTO_UDP;
+           break;
+       case TCP:
+           protocol = IPPROTO_TCP;
+           break;
+
+       default:
+           printk("Unsupported VNET Server Protocol\n");
+           return -1;
+    }
+        
+    if ((err = sock_create(AF_INET, SOCK_DGRAM, protocol, &vnet_brg_s.serv_sock)) < 0) {
+       printk("Could not create VNET server socket, error: %d\n", err);
+       return -1;
+    }
+
+    memset(&vnet_brg_s.serv_addr, 0, sizeof(struct sockaddr));
+
+    vnet_brg_s.serv_addr.sin_family = AF_INET;
+    vnet_brg_s.serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    vnet_brg_s.serv_addr.sin_port = htons(VNET_SERVER_PORT);
+
+    if ((err = vnet_brg_s.serv_sock->ops->bind(vnet_brg_s.serv_sock, (struct sockaddr *)&(vnet_brg_s.serv_addr), sizeof(struct sockaddr))) < 0) {
+       printk("Could not bind VNET server socket to port %d, error: %d\n", VNET_SERVER_PORT, err);
+       return -1;
+    }
+
+    printk("VNET server bind to port: %d\n", VNET_SERVER_PORT);
+
+    if(vnet_brg_s.serv_proto == TCP){
+       if((err = vnet_brg_s.serv_sock->ops->listen(vnet_brg_s.serv_sock, 32)) < 0){
+           printk("VNET Server error listening on port %d, error %d\n", VNET_SERVER_PORT, err);
+           return -1;
+       }
+    }
+
+    return 0;
+}
+
+static int _udp_server(void * arg) {
+    unsigned char * pkt;
+    struct sockaddr_in pkt_addr;
+    struct vnet_link * link = NULL;
+    int len;
+
+    printk("Palacios VNET Bridge: UDP receiving server ..... \n");
+
+    pkt = kmalloc(MAX_PACKET_LEN, GFP_KERNEL);
+    while (!kthread_should_stop()) {
+       
+       len = _udp_recv(vnet_brg_s.serv_sock, &pkt_addr, pkt, MAX_PACKET_LEN); 
+       if(len < 0) {
+           printk("Receive error: Could not get packet, error %d\n", len);
+           continue;
+       }
+
+       link = _link_by_ip(pkt_addr.sin_addr.s_addr);
+       if (link == NULL){
+           printk("VNET Server: No VNET Link match the src IP\n");
+           vnet_brg_s.stats.pkt_drop_phy ++;
+           continue;
+       }
+       
+       vnet_brg_s.stats.pkt_from_phy ++;
+       link->stats.rx_bytes += len;
+       link->stats.rx_pkts ++;
+
+       send_to_palacios(pkt, len, link->idx);
+    }
+
+    kfree(pkt);
+
+    return 0;
+}
+
+
+static int _rx_server(void * arg) {
+    
+    if(vnet_brg_s.serv_proto == UDP){
+       _udp_server(NULL);
+    }else if(vnet_brg_s.serv_proto == TCP) {
+       //accept new connection
+       //use select to receive pkt from physical network
+       //or create new kthread to handle each connection?
+    }else {
+       printk ("VNET Server: Unsupported Protocol\n");
+       return -1;
+    }
+
+    return 0;
+}
+
+static inline unsigned int hash_fn(addr_t hdr_ptr) {    
+    return vnet_hash_buffer((uint8_t *)hdr_ptr, sizeof(uint32_t));
+}
+
+static inline int hash_eq(addr_t key1, addr_t key2) {  
+    return (memcmp((uint8_t *)key1, (uint8_t *)key2, sizeof(uint32_t)) == 0);
+}
+
+
+int vnet_bridge_init(void) {
+    struct v3_vnet_bridge_ops bridge_ops;
+
+    if(vnet_brg_s.status != 0) {
+       return -1;
+    }  
+    vnet_brg_s.status = 1;     
+       
+    memset(&vnet_brg_s, 0, sizeof(struct vnet_brg_state));
+
+    INIT_LIST_HEAD(&(vnet_brg_s.link_list));
+    spin_lock_init(&(vnet_brg_s.lock));
+
+    vnet_brg_s.serv_proto = UDP;
+
+    vnet_brg_s.ip2link = vnet_create_htable(10, hash_fn, hash_eq);
+    if(vnet_brg_s.ip2link == NULL){
+       printk("Failure to initiate VNET link hashtable\n");
+       return -1;
+    }
+       
+    if(init_vnet_serv() < 0){
+       printk("Failure to initiate VNET server\n");
+       return -1;
+    }
+
+    vnet_brg_s.serv_thread = kthread_run(_rx_server, NULL, "vnet-server");
+
+    bridge_ops.input = bridge_send_pkt;
+    bridge_ops.poll = NULL;
+       
+    if( v3_vnet_add_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL) < 0){
+       printk("VNET LNX Bridge: Fails to register bridge to VNET core");
+    }
+
+    printk("VNET Linux Bridge initiated\n");
+
+    return 0;
+}
+
+
+void vnet_bridge_deinit(void){
+
+    v3_vnet_del_bridge(HOST_LNX_BRIDGE);
+
+    kthread_stop(vnet_brg_s.serv_thread);
+    vnet_brg_s.serv_sock->ops->release(vnet_brg_s.serv_sock);
+
+    deinit_links_list();
+
+    vnet_free_htable(vnet_brg_s.ip2link, 0, 0);
+
+    vnet_brg_s.status = 0;
+}
+
+
diff --git a/linux_module/palacios-vnet-ctrl.c b/linux_module/palacios-vnet-ctrl.c
new file mode 100644 (file)
index 0000000..f0bbac5
--- /dev/null
@@ -0,0 +1,961 @@
+/* 
+   Palacios VNET Control Module
+   (c) Lei Xia, 2010
+ */
+#include <linux/spinlock.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <linux/inet.h>
+#include <linux/kthread.h>
+
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/net.h>
+#include <linux/string.h>
+#include <linux/preempt.h>
+#include <linux/sched.h>
+#include <asm/msr.h>
+
+#include <vnet/vnet.h>
+#include <vnet/vnet_hashtable.h>
+#include "palacios-vnet.h"
+
+#define VNET_SERVER_PORT 9000
+
+struct vnet_route_iter {
+    struct v3_vnet_route route;
+    uint32_t idx;
+
+    struct list_head node;
+};
+
+
+struct vnet_link_iter {
+    uint32_t dst_ip;
+    uint16_t dst_port;
+    vnet_brg_proto_t proto;
+    uint32_t idx;
+
+    struct list_head node;
+};
+
+
+struct vnet_ctrl_state {
+    uint8_t status;
+
+    uint32_t num_links;
+    uint32_t num_routes;
+       
+    struct list_head route_list;
+    struct list_head link_iter_list;
+
+    spinlock_t lock;
+
+    struct proc_dir_entry * vnet_proc_root;
+};
+
+
+static struct vnet_ctrl_state vnet_ctrl_s;
+
+
+static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) {
+    char * token;
+
+    printk("Parsing MAC (%s)\n", str);
+       
+    *qual = MAC_NOSET;
+    if(strnicmp("any", str, strlen(str)) == 0){
+       *qual = MAC_ANY;
+       return 0;
+    }else if(strnicmp("none", str, strlen(str)) == 0){
+       *qual = MAC_NONE;
+       return 0;
+    }else{
+       if (strstr(str, "-")) {
+           token = strsep(&str, "-");
+
+           if (strnicmp("not", token, strlen("not")) == 0) {
+               *qual = MAC_NOT;
+           } else {
+               printk("Invalid MAC String token (%s)\n", token);
+               return -1;
+           }
+       }
+
+       if (strstr(str, ":")) {
+           int i = 0;
+
+           if(*qual == MAC_NOSET){
+               *qual = MAC_ADDR;
+           }
+
+           for (i = 0; i < 6; i++) {
+               token = strsep(&str, ":");
+               if (!token) {
+                   printk("Invalid MAC String token (%s)\n", token);
+                   return -1;
+               }
+               mac[i] = simple_strtol(token, &token, 16);
+           }
+           printk("MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+               
+       }else {
+           printk("Invalid MAC String token (%s)\n", token);
+           return -1;
+       }
+               
+    }
+
+    return 0;
+}
+
+
+static int str2mac(char * str, uint8_t * mac){
+    int i = 0;
+    char *hex = NULL;
+       
+    for (i = 0; i < ETH_ALEN; i++) {           
+       hex = strsep(&str, ":");
+       if (!hex) {
+           printk("Invalid MAC String token (%s)\n", str);
+           return -1;
+       }
+       mac[i] = simple_strtol(hex, &hex, 16);
+    }
+       
+    return 0;
+}
+
+
+static inline struct vnet_link_iter * link_by_ip(uint32_t ip) {
+    struct vnet_link_iter * link = NULL;
+
+    list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
+
+       if (link->dst_ip == ip) {
+           return link;
+       }
+    }
+       
+    return NULL;
+}
+
+static inline struct vnet_link_iter * link_by_idx(int idx) {
+    struct vnet_link_iter * link = NULL;
+
+    list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
+       if (link->idx == idx) {
+           return link;
+       }
+    }
+       
+    return NULL;
+}
+
+
+static int parse_route_str(char * str, struct v3_vnet_route * route) {
+    char * token = NULL;
+    struct vnet_link_iter * link = NULL;
+
+    // src MAC
+    token = strsep(&str, " ");
+    if (!token) {
+       return -1;
+    }
+    parse_mac_str(token, &(route->src_mac_qual), route->src_mac);
+
+    // dst MAC
+    token = strsep(&str, " ");
+    if (!token) {
+       return -1;
+    }
+    parse_mac_str(token, &(route->dst_mac_qual), route->dst_mac);
+
+    // dst LINK type
+    token = strsep(&str, " ");
+    if (!token) {
+       return -1;
+    }
+    printk("dst type =(%s)\n", token);
+    
+    if (strnicmp("interface", token, strlen("interface")) == 0) {
+       route->dst_type = LINK_INTERFACE;
+    } else if (strnicmp("edge", token, strlen("edge")) == 0) {
+       route->dst_type = LINK_EDGE;
+    } else {
+       printk("Invalid Destination Link Type (%s)\n", token);
+       return -1;
+    }
+
+    // dst link
+    token = strsep(&str, " ");
+    if (!token) {
+       return -1;
+    }
+    printk("dst ID=(%s)\n", token);
+
+    // Figure out link here
+    if (route->dst_type == LINK_EDGE) {
+       uint32_t link_ip;
+
+       // Figure out Link Here
+       if (in4_pton(token, strlen(token), (uint8_t *)&(link_ip), '\0', NULL) != 1) {
+           printk("Invalid Dst IP address (%s)\n", token);
+           return -EFAULT;
+       }
+
+       link = link_by_ip(link_ip);
+       if (link != NULL){
+           route->dst_id = link->idx;
+       }else{
+           printk("can not find dst link %s\n", token);
+           return -1;
+       }
+
+       printk("link_ip = %d, link_id = %d\n", link_ip, link->idx);     
+    } else if (route->dst_type == LINK_INTERFACE) {
+       uint8_t mac[ETH_ALEN];
+       
+       if(str2mac(token, mac) == -1){
+          printk("wrong MAC format (%s)\n", token);
+          return -1;
+       }
+          
+       route->dst_id = v3_vnet_find_dev(mac);
+       if (route->dst_id == -1){
+           printk("can not find dst device %s\n", token);
+           return -1;
+       }               
+    } else {
+       printk("Unsupported dst link type\n");
+       return -1;
+    }
+
+    route->src_id = -1;
+    route->src_type = -1;
+
+    // src LINK
+    token = strsep(&str, " ");
+
+    printk("SRC type = %s\n", token);
+
+    if (!token) {
+       return -1;
+    }
+
+    if (strnicmp("interface", token, strlen("interface")) == 0) {
+       route->src_type = LINK_INTERFACE;
+    } else if (strnicmp("edge", token, strlen("edge")) == 0) {
+       route->src_type = LINK_EDGE;
+    } else if (strnicmp("any", token, strlen("any")) == 0) {
+       route->src_type = LINK_ANY;
+    } else {
+       printk("Invalid Src link type (%s)\n", token);
+       return -1;
+    }
+
+
+    if (route->src_type == LINK_ANY) {
+       route->src_id = -1;
+    } else if (route->src_type == LINK_EDGE) {
+       uint32_t src_ip;
+       token = strsep(&str, " ");
+
+       if (!token) {
+           return -1;
+       }
+
+       // Figure out Link Here
+       if (in4_pton(token, strlen(token), (uint8_t *)&(src_ip), '\0', NULL) != 1) {
+           printk("Invalid SRC IP address (%s)\n", token);
+           return -EFAULT;
+       }
+
+       link = link_by_ip(src_ip);
+       if (link != NULL){
+           route->src_id = link->idx;
+       }else{
+           printk("can not find src link %s\n", token);
+           return -1;
+       }
+    } else if(route->src_type == LINK_INTERFACE){
+       uint8_t mac[ETH_ALEN];
+       
+       if(str2mac(token, mac) == -1){
+          printk("wrong MAC format (%s)\n", token);
+          return -1;
+       }
+          
+       route->src_id = v3_vnet_find_dev(mac);
+       if (route->src_id == -1){
+           printk("can not find dst device %s\n", token);
+           return -1;
+       }               
+    } else {
+       printk("Invalid link type\n");
+       return -1;
+    }
+
+    return 0;
+}
+
+
+static void * route_seq_start(struct seq_file * s, loff_t * pos) {
+    struct vnet_route_iter * route_iter = NULL;
+    loff_t i = 0;
+
+    if (*pos >= vnet_ctrl_s.num_routes) {
+       return NULL;
+    }
+
+    list_for_each_entry(route_iter, &(vnet_ctrl_s.route_list), node) {
+       if (i == *pos) {
+           break;
+       }
+
+       i++;
+    }
+
+    return route_iter;
+}
+
+
+static void * route_seq_next(struct seq_file * s, void * v, loff_t * pos) {
+    struct vnet_route_iter * route_iter = NULL;
+
+    route_iter = list_entry(((struct vnet_route_iter *)v)->node.next, struct vnet_route_iter, node);
+
+    // Check if the list has looped
+    if (&(route_iter->node) == &(vnet_ctrl_s.route_list)) {
+       return NULL;
+    }
+
+    *pos += 1;
+
+    return route_iter;
+}
+
+static void route_seq_stop(struct seq_file * s, void * v) {
+
+    return;
+}
+
+static void * link_seq_start(struct seq_file * s, loff_t * pos) {
+    struct vnet_link_iter * link_iter = NULL;
+    loff_t i = 0;
+
+    if (*pos >= vnet_ctrl_s.num_links) {
+       return NULL;
+    }
+
+    list_for_each_entry(link_iter, &(vnet_ctrl_s.link_iter_list), node) {
+       if (i == *pos) {
+           break;
+       }
+
+       i++;
+    }
+
+    return link_iter;
+}
+
+static int route_seq_show(struct seq_file * s, void * v) {
+    struct vnet_route_iter * route_iter = v;
+    struct v3_vnet_route * route = &(route_iter->route);
+
+    seq_printf(s, "%d:\t", route_iter->idx);
+
+    seq_printf(s, "\nSrc:\t");
+    switch (route->src_mac_qual) {
+       case MAC_ANY:
+           seq_printf(s, "any ");
+           break;
+       case MAC_NONE:
+           seq_printf(s, "none ");
+           break;
+       case MAC_NOT:
+           seq_printf(s, "not-%2x:%2x:%2x:%2x:%2x:%2x ", 
+                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
+                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
+           break;
+       default:
+           seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
+                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
+                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
+           break;
+    }
+
+    seq_printf(s, "\nDst:\t");
+    switch (route->dst_mac_qual) {
+       case MAC_ANY:
+           seq_printf(s, "any ");
+           break;
+       case MAC_NONE:
+           seq_printf(s, "none ");
+           break;
+       case MAC_NOT:
+           seq_printf(s, "not-%x:%x:%x:%x:%x:%x ", 
+                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
+                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
+           break;
+       default:
+           seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
+                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
+                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
+           break;
+    }
+
+    seq_printf(s, "\nDst-Type:\t");
+    switch (route->dst_type) {
+       case LINK_EDGE: {
+           struct vnet_link_iter * link = (struct vnet_link_iter *)link_by_idx(route->dst_id);
+           seq_printf(s, "EDGE %pI4", &link->dst_ip);
+           break;
+       }
+       case LINK_INTERFACE: {
+           seq_printf(s, "INTERFACE ");
+           seq_printf(s, "%d ", route->dst_id);
+           break;
+       }
+       default:
+           seq_printf(s, "Invalid Dst Link Type (%d) ", route->dst_type);
+           break;
+    }
+
+    seq_printf(s, "\nSrc-Type:\t");
+    switch (route->src_type) {
+       case LINK_EDGE: {
+           struct vnet_link_iter * link = (struct vnet_link_iter *)link_by_idx(route->src_id);
+           seq_printf(s, "EDGE %pI4", &link->dst_ip);
+           break;
+       }
+       case LINK_INTERFACE: {
+           seq_printf(s, "INTERFACE %d", route->src_id);
+           break;
+       }
+       case LINK_ANY:
+           seq_printf(s, "ANY");
+           break;
+       default:
+           seq_printf(s, "Invalid Src Link Type (%d) ", route->src_type);
+           break;
+    }
+
+    seq_printf(s, "\n");
+
+    return 0;
+}
+
+static void * link_seq_next(struct seq_file * s, void * v, loff_t * pos) {
+    struct vnet_link_iter * link_iter = NULL;
+
+    link_iter = list_entry(((struct vnet_link_iter *)v)->node.next, struct vnet_link_iter, node);
+
+    // Check if the list has looped
+    if (&(link_iter->node) == &(vnet_ctrl_s.link_iter_list)) {
+       return NULL;
+    }
+
+    *pos += 1;
+
+    return link_iter;
+}
+
+static void link_seq_stop(struct seq_file * s, void * v) {
+
+    return;
+}
+
+static int link_seq_show(struct seq_file * s, void * v) {
+    struct vnet_link_iter * link_iter = v;
+    struct nic_statistics stats;
+
+    vnet_brg_link_stats(link_iter->idx, &stats);
+
+    seq_printf(s, "%d:\t%pI4\t%d\n\t\tReceived Pkts: %lld, Received Bytes %lld\n\t\tSent Pkts: %lld, Sent Bytes: %lld\n\n", 
+              link_iter->idx,
+              &link_iter->dst_ip,
+              link_iter->dst_port,
+              stats.rx_pkts,
+              stats.rx_bytes,
+              stats.tx_pkts,
+              stats.tx_bytes);
+
+    return 0;
+}
+
+
+static struct seq_operations route_seq_ops = {
+    .start = route_seq_start, 
+    .next = route_seq_next,
+    .stop = route_seq_stop,
+    .show = route_seq_show
+};
+
+
+static struct seq_operations link_seq_ops = {
+    .start = link_seq_start,
+    .next = link_seq_next,
+    .stop = link_seq_stop,
+    .show = link_seq_show
+};
+
+
+static int route_open(struct inode * inode, struct file * file) {
+    return seq_open(file, &route_seq_ops);
+}
+
+
+static int link_open(struct inode * inode, struct file * file) {
+    return seq_open(file, &link_seq_ops);
+}
+
+
+
+static int inject_route(struct vnet_route_iter * route) {
+    unsigned long flags;
+    
+    route->idx = v3_vnet_add_route(route->route);
+
+    spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+    list_add(&(route->node), &(vnet_ctrl_s.route_list));
+    vnet_ctrl_s.num_routes ++;
+    spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
+
+    printk("VNET Control: One route added to VNET core\n");
+
+    return 0;
+}
+
+
+static void delete_route(struct vnet_route_iter * route) {
+    unsigned long flags;
+
+    v3_vnet_del_route(route->idx);
+
+    spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+    list_del(&(route->node));
+    vnet_ctrl_s.num_routes --;
+    spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
+
+    printk("VNET Control: Route %d deleted from VNET\n", route->idx);
+
+    kfree(route);
+    route = NULL;
+}
+
+
+/* Format:
+  * add src-MAC dst-MAC dst-TYPE [dst-ID] src-TYPE [src-ID]
+  *
+  * src-MAC = dst-MAC = not-MAC|any|none|MAC 
+  * dst-TYPE = edge|interface 
+  * src-TYPE = edge|interface|any
+  * dst-ID = src-ID = IP|MAC
+  * MAC=xx:xx:xx:xx:xx:xx
+  * IP = xxx.xxx.xxx.xxx
+  *
+  *
+  * del route-idx
+  *
+  */
+static ssize_t 
+route_write(struct file * file, 
+           const char * buf, 
+           size_t size, 
+           loff_t * ppos) {
+    char route_buf[256];
+    char * buf_iter = NULL;
+    char * line_str = route_buf;
+    char * token = NULL;
+
+    if (size >= 256) {
+       return -EFAULT;
+    }
+
+    if (copy_from_user(route_buf, buf, size)) {
+       return -EFAULT;
+    }
+
+    route_buf[size] = '\0';
+    printk("Route written: %s\n", route_buf);
+
+    while ((buf_iter = strsep(&line_str, "\r\n"))) {
+
+       token = strsep(&buf_iter, " ");
+       if (!token) {
+           return -EFAULT;
+       }
+       
+       if (strnicmp("ADD", token, strlen("ADD")) == 0) {
+           struct vnet_route_iter * new_route = NULL;
+           new_route = kmalloc(sizeof(struct vnet_route_iter), GFP_KERNEL);
+           
+           if (!new_route) {
+               return -ENOMEM;
+           }
+           
+           memset(new_route, 0, sizeof(struct vnet_route_iter));
+           
+           if (parse_route_str(buf_iter, &(new_route->route)) == -1) {
+               kfree(new_route);
+               return -EFAULT;
+           }
+           
+           if (inject_route(new_route) != 0) {
+               kfree(new_route);
+               return -EFAULT;
+           }
+       } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
+           char * idx_str = NULL;
+           uint32_t d_idx;
+           
+           idx_str = strsep(&buf_iter, " ");
+           
+           if (!idx_str) {
+               printk("Missing route idx in DEL Route command\n");
+               return -EFAULT;
+           }
+
+           d_idx = simple_strtoul(idx_str, &idx_str, 10);
+
+           v3_vnet_del_route(d_idx);
+               
+           printk("VNET Control: One route deleted\n");                
+
+       } else {
+           printk("Invalid Route command string\n");
+       }
+    }
+
+    return size;
+}
+
+
+static void delete_link(struct vnet_link_iter * link){
+    unsigned long flags;
+
+    vnet_brg_delete_link(link->idx);
+
+    spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+    list_del(&(link->node));
+    vnet_ctrl_s.num_links --;
+    spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
+
+    kfree(link);
+    link = NULL;
+}
+
+
+static void deinit_links_list(void){
+    struct vnet_link_iter * link;
+
+    list_for_each_entry(link, &(vnet_ctrl_s.link_iter_list), node) {
+       delete_link(link);
+    }
+}
+
+static void deinit_routes_list(void){
+   struct vnet_route_iter * route;
+
+   list_for_each_entry(route, &(vnet_ctrl_s.route_list), node) {
+       delete_route(route);
+   }
+}
+
+/* ADD dst-ip 9000 [udp|tcp] */
+/* DEL link-idx */
+static ssize_t 
+link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
+    char link_buf[256];
+    char * link_iter = NULL;
+    char * line_str = link_buf;
+    char * token = NULL;
+
+    if (size >= 256) {
+       return -EFAULT;
+    }
+
+    if (copy_from_user(link_buf, buf, size)) {
+       return -EFAULT;
+    }
+
+    while ((link_iter = strsep(&line_str, "\r\n"))) {
+       printk("Link written: %s\n", link_buf);
+       
+       token = strsep(&link_iter, " ");
+       
+       if (!token) {
+           return -EFAULT;
+       }
+       
+       if (strnicmp("ADD", token, strlen("ADD")) == 0) {
+           struct vnet_link_iter * link = NULL;
+           char * ip_str = NULL;
+           uint32_t d_ip;
+           uint16_t d_port;
+           vnet_brg_proto_t d_proto;
+           int link_idx;
+           unsigned long flags;
+           
+           ip_str = strsep(&link_iter, " ");
+           
+           if ((!ip_str) || (!link_iter)) {
+               printk("Missing fields in ADD Link command\n");
+               return -EFAULT;
+           }
+           
+           if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(d_ip), '\0', NULL) != 1) {
+               printk("Invalid Dst IP address (%s)\n", ip_str);
+               return -EFAULT;
+           }
+
+           d_port = simple_strtol(link_iter, &link_iter, 10);
+           d_proto = UDP;
+
+           link_idx = vnet_brg_add_link(d_ip, d_port, d_proto);
+           if(link_idx < 0){
+               printk("VNET Control: Failed to create link\n");
+               return -EFAULT;
+           }
+
+           link = kmalloc(sizeof(struct vnet_link_iter), GFP_KERNEL);
+           memset(link, 0, sizeof(struct vnet_link_iter));
+
+           link->dst_ip = d_ip;
+           link->dst_port = d_port;
+           link->proto = d_proto;
+           link->idx = link_idx;
+
+           spin_lock_irqsave(&(vnet_ctrl_s.lock), flags);
+           list_add(&(link->node), &(vnet_ctrl_s.link_iter_list));
+           vnet_ctrl_s.num_links ++;
+           spin_unlock_irqrestore(&(vnet_ctrl_s.lock), flags);
+       } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
+           char * idx_str = NULL;
+           uint32_t d_idx;
+           
+           idx_str = strsep(&link_iter, " ");
+           
+           if (!idx_str) {
+               printk("Missing link idx in DEL Link command\n");
+               return -EFAULT;
+           }
+
+           d_idx = simple_strtoul(idx_str, &idx_str, 10);
+
+           vnet_brg_delete_link(d_idx);
+               
+           printk("VNET Control: One link deleted\n");         
+       } else {
+           printk("Invalid Link command string\n");
+       }
+    }
+
+    return size;
+}
+
+
+static struct file_operations route_fops = {
+    .owner = THIS_MODULE,
+    .open = route_open, 
+    .read = seq_read,
+    .write = route_write,
+    .llseek = seq_lseek,
+    .release = seq_release
+};
+
+
+static struct file_operations link_fops = {
+    .owner = THIS_MODULE,
+    .open = link_open, 
+    .read = seq_read,
+    .write = link_write,
+    .llseek = seq_lseek,
+    .release = seq_release
+};
+
+
+static ssize_t 
+debug_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
+    char in_buf[32];
+    char * in_iter = NULL;
+    char * line_str = in_buf;
+    int level = -1; 
+
+    if (size >= 32) {
+       return -EFAULT;
+    }
+
+    if (copy_from_user(in_buf, buf, size)) {
+       return -EFAULT;
+    }
+
+    in_iter = strsep(&line_str, "\r\n");
+    level = simple_strtol(in_iter, &in_iter, 10);
+
+    printk("VNET Control: Set VNET Debug level to %d\n", level);
+
+    if(level >= 0){
+       net_debug = level;
+    }
+
+    return size;
+}
+
+
+static int debug_show(struct seq_file * file, void * v){
+    seq_printf(file, "Current NET Debug Level: %d\n", net_debug);
+       
+    return 0;
+}
+
+static int debug_open(struct inode * inode, struct file * file) {
+    return single_open(file, debug_show, NULL);
+}
+
+static struct file_operations debug_fops = {
+    .owner = THIS_MODULE,
+    .open = debug_open, 
+    .read = seq_read,
+    .write = debug_write,
+    .llseek = seq_lseek,
+    .release = seq_release
+};
+
+static int stat_show(struct seq_file * file, void * v){
+    struct vnet_stat stats;
+    struct vnet_brg_stats brg_stats;
+
+    v3_vnet_stat(&stats);
+
+    seq_printf(file, "VNET Core\n");
+    seq_printf(file, "\tReceived Packets: %d\n", stats.rx_pkts);
+    seq_printf(file, "\tReceived Bytes: %lld\n", stats.rx_bytes);
+    seq_printf(file, "\tTransmitted Packets: %d\n", stats.tx_pkts);
+    seq_printf(file, "\tTransmitted Bytes: %lld\n", stats.tx_bytes);
+
+    vnet_brg_stats(&brg_stats);
+   
+    seq_printf(file, "\nVNET Bridge Server\n");
+    seq_printf(file, "\tReceived From VMM: %lld\n", brg_stats.pkt_from_vmm);
+    seq_printf(file, "\tSent To VMM: %lld\n", brg_stats.pkt_to_vmm);
+    seq_printf(file, "\tDropped From VMM: %lld\n", brg_stats.pkt_drop_vmm);
+    seq_printf(file, "\tReceived From Extern Network: %lld\n", brg_stats.pkt_from_phy);
+    seq_printf(file, "\tSent To Extern Network: %lld\n", brg_stats.pkt_to_phy);
+    seq_printf(file, "\tDropped From Extern Network: %lld\n", brg_stats.pkt_drop_phy);
+
+    return 0;
+}
+
+static int stat_open(struct inode * inode, struct file * file) {
+    return single_open(file, stat_show, NULL);
+}
+
+static struct file_operations stat_fops = {
+    .owner = THIS_MODULE,
+    .open = stat_open, 
+    .read = seq_read,
+    .llseek = seq_lseek,
+    .release = seq_release
+};
+
+
+static int init_proc_files(void) {
+    struct proc_dir_entry * route_entry = NULL;
+    struct proc_dir_entry * link_entry = NULL;
+    struct proc_dir_entry * stat_entry = NULL;
+    struct proc_dir_entry * debug_entry = NULL;
+    struct proc_dir_entry * vnet_root = NULL;
+
+    vnet_root = proc_mkdir("vnet", NULL);
+    if (vnet_root == NULL) {
+       return -1;
+    }
+
+    route_entry = create_proc_entry("routes", 0, vnet_root);
+    if (route_entry == NULL) {
+       remove_proc_entry("vnet", NULL);
+       return -1;
+    }
+    route_entry->proc_fops = &route_fops;
+       
+
+    link_entry = create_proc_entry("links", 0, vnet_root);
+    if (link_entry == NULL) {
+       remove_proc_entry("routes", vnet_root);
+       remove_proc_entry("vnet", NULL);
+       return -1;
+    }
+    link_entry->proc_fops = &link_fops;
+       
+
+    stat_entry = create_proc_entry("stats", 0, vnet_root);
+    if(stat_entry == NULL) {
+       remove_proc_entry("links", vnet_root);
+       remove_proc_entry("routes", vnet_root);
+       remove_proc_entry("vnet", NULL);
+       return -1;
+    }
+    stat_entry->proc_fops = &stat_fops;
+
+
+    debug_entry = create_proc_entry("debug", 0, vnet_root);
+    if(debug_entry == NULL) {
+       remove_proc_entry("links", vnet_root);
+       remove_proc_entry("routes", vnet_root);
+       remove_proc_entry("stats", vnet_root);
+       remove_proc_entry("vnet", NULL);
+       return -1;
+    }
+    debug_entry->proc_fops = &debug_fops;
+
+    vnet_ctrl_s.vnet_proc_root = vnet_root;
+
+    return 0;
+}
+
+
+static void destroy_proc_files(void) {
+    struct proc_dir_entry * vnet_root = vnet_ctrl_s.vnet_proc_root;
+
+    remove_proc_entry("debug", vnet_root);
+    remove_proc_entry("links", vnet_root);
+    remove_proc_entry("routes", vnet_root);
+    remove_proc_entry("stats", vnet_root);
+    remove_proc_entry("vnet", NULL);   
+}
+
+
+int vnet_ctrl_init(void) {
+    if(vnet_ctrl_s.status != 0) {
+       return -1;
+    }  
+    vnet_ctrl_s.status = 1;    
+       
+    memset(&vnet_ctrl_s, 0, sizeof(struct vnet_ctrl_state));
+
+    INIT_LIST_HEAD(&(vnet_ctrl_s.link_iter_list));
+    INIT_LIST_HEAD(&(vnet_ctrl_s.route_list));
+    spin_lock_init(&(vnet_ctrl_s.lock));
+
+    init_proc_files();
+       
+    printk("VNET Linux control module initiated\n");
+
+    return 0;
+}
+
+
+void vnet_ctrl_deinit(void){
+    destroy_proc_files();
+
+    deinit_links_list();
+    deinit_routes_list();
+
+    vnet_ctrl_s.status = 0;
+}
+
+
index 3f6f899..4f3cbd5 100644 (file)
 /* 
-   Palacios VNET interface
-   (c) Lei Xia, 2010
+   Palacios VNET Host Hooks Implementations
+   (c) Lei Xia, 2011
  */
-#include <linux/spinlock.h>
-#include <linux/seq_file.h>
-#include <linux/proc_fs.h>
-#include <asm/uaccess.h>
-#include <linux/inet.h>
+#include <linux/kernel.h>
 #include <linux/kthread.h>
-
-#include <linux/netdevice.h>
-#include <linux/ip.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/preempt.h>
+#include <linux/spinlock.h>
+#include <linux/gfp.h>
 #include <linux/sched.h>
-#include <asm/msr.h>
-
-#include <palacios/vmm_vnet.h>
+#include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <asm/delay.h>
+#include <linux/timer.h>
+
+#include <vnet/vnet.h>
+#include "palacios-mm.h"
 #include "palacios-vnet.h"
 
-//#define DEBUG_VNET_BRIGE
+static void host_print(const char *    fmt, ...) {
 
-#define VNET_UDP_PORT 9000
+    va_list ap;
+    va_start(ap, fmt);
+    vprintk(fmt, ap);
+    va_end(ap);
 
-struct palacios_vnet_route {
-    struct v3_vnet_route route;
-
-    int route_idx;
-
-    struct list_head node;
-};
+    return;
+}
 
 
-struct vnet_link {
-    uint32_t dst_ip;
-    uint16_t dst_port;
+static void * host_allocate_pages(int num_pages, unsigned int alignment){
+    uintptr_t addr = 0; 
+    struct page * pgs = NULL;
+    int order = get_order(num_pages * PAGE_SIZE);
+        
+    pgs = alloc_pages(GFP_KERNEL, order);
     
-    struct socket * sock;
-    struct sockaddr_in sock_addr;
-
-    int link_idx;
-
-    struct list_head node;
-};
-
-struct palacios_vnet_state {
-    uint32_t num_routes;
-    uint32_t num_links; 
-
-    struct list_head route_list;
-    struct list_head link_list;
-
-    struct socket * serv_sock;
-    struct sockaddr_in serv_addr;
-
-    /* The thread recving pkts from sockets. */
-    struct task_struct * serv_thread;
-    spinlock_t lock;
-
-    unsigned long pkt_sent, pkt_recv, pkt_drop, pkt_udp_recv, pkt_udp_send;
-};
-
-
-static struct palacios_vnet_state vnet_state;
-
-
-struct vnet_link * link_by_ip(uint32_t ip) {
-    struct vnet_link * link = NULL;
-
-    list_for_each_entry(link, &(vnet_state.link_list), node) {
-
-       if (link->dst_ip == ip) {
-           return link;
-       }
-    }
-
-    return NULL;
+    WARN(!pgs, "Could not allocate pages\n");
+       
+    addr = page_to_pfn(pgs) << PAGE_SHIFT; 
+   
+    return (void *)addr;
 }
 
-struct vnet_link * link_by_idx(int idx) {
-    struct vnet_link * link = NULL;
-
-    list_for_each_entry(link, &(vnet_state.link_list), node) {
 
-       if (link->link_idx == idx) {
-           return link;
-       }
-    }
-    return NULL;
+static void host_free_pages(void * page_paddr, int num_pages) {
+    uintptr_t pg_addr = (uintptr_t)page_paddr;
+       
+    __free_pages(pfn_to_page(pg_addr >> PAGE_SHIFT), get_order(num_pages * PAGE_SIZE));
 }
 
-struct palacios_vnet_route * route_by_idx(int idx) {
-    struct palacios_vnet_route * route = NULL;
 
-    list_for_each_entry(route, &(vnet_state.route_list), node) {
-
-       if (route->route_idx == idx) {
-           return route;
-       }
-    }
+static void *
+host_alloc(unsigned int size) {
+    void * addr;
+    addr =  kmalloc(size, GFP_KERNEL);
 
-    return NULL;
+    return addr;
 }
 
-
-static int parse_mac_str(char * str, uint8_t * qual, uint8_t * mac) {
-    char * token;
-
-    printk("Parsing MAC (%s)\n", str);
-       
-    *qual = MAC_NOSET;
-    if(strnicmp("any", str, strlen(str)) == 0){
-       *qual = MAC_ANY;
-       return 0;
-    }else if(strnicmp("none", str, strlen(str)) == 0){
-       *qual = MAC_NONE;
-       return 0;
-    }else{
-       if (strstr(str, "-")) {
-           token = strsep(&str, "-");
-
-           if (strnicmp("not", token, strlen("not")) == 0) {
-               *qual = MAC_NOT;
-           } else {
-               printk("Invalid MAC String token (%s)\n", token);
-               return -1;
-           }
-       }
-
-       if (strstr(str, ":")) {
-           int i = 0;
-
-           if(*qual == MAC_NOSET){
-               *qual = MAC_ADDR;
-           }
-
-           for (i = 0; i < 6; i++) {
-               token = strsep(&str, ":");
-               if (!token) {
-                   printk("Invalid MAC String token (%s)\n", token);
-                   return -1;
-               }
-               mac[i] = simple_strtol(token, &token, 16);
-           }
-           printk("MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-               
-       }else {
-           printk("Invalid MAC String token (%s)\n", token);
-           return -1;
-       }
-               
-    }
-
-    return 0;
+static void
+host_free(
+       void *                  addr
+)
+{
+    kfree(addr);
+    return;
 }
 
+static void *
+host_vaddr_to_paddr(void * vaddr)
+{
+    return (void*) __pa(vaddr);
 
-static int str2mac(char * str, uint8_t * mac){
-    int i = 0;
-    char *hex = NULL;
-       
-    for (i = 0; i < ETH_ALEN; i++) {           
-       hex = strsep(&str, ":");
-       if (!hex) {
-           printk("Invalid MAC String token (%s)\n", str);
-           return -1;
-       }
-       mac[i] = simple_strtol(hex, &hex, 16);
-    }
-       
-    return 0;
 }
 
-
-/* Format:
-  * add src-MAC dst-MAC dst-TYPE [dst-ID] src-TYPE [src-ID]
-  *
-  * src-MAC = dst-MAC = not-MAC|any|none|MAC 
-  * dst-TYPE = edge|interface 
-  * src-TYPE = edge|interface|any
-  * dst-ID = src-ID = IP|MAC
-  * MAC=xx:xx:xx:xx:xx:xx
-  * IP = xxx.xxx.xxx.xxx
-  */
-static int parse_route_str(char * str, struct v3_vnet_route * route) {
-    char * token = NULL;
-    struct vnet_link *link = NULL;
-
-    // src MAC
-    token = strsep(&str, " ");
-    if (!token) {
-       return -1;
-    }
-    parse_mac_str(token, &(route->src_mac_qual), route->src_mac);
-
-    // dst MAC
-    token = strsep(&str, " ");
-    if (!token) {
-       return -1;
-    }
-    parse_mac_str(token, &(route->dst_mac_qual), route->dst_mac);
-
-    // dst LINK type
-    token = strsep(&str, " ");
-    if (!token) {
-       return -1;
-    }
-    printk("dst type =(%s)\n", token);
-    
-    if (strnicmp("interface", token, strlen("interface")) == 0) {
-       route->dst_type = LINK_INTERFACE;
-    } else if (strnicmp("edge", token, strlen("edge")) == 0) {
-       route->dst_type = LINK_EDGE;
-    } else {
-       printk("Invalid Destination Link Type (%s)\n", token);
-       return -1;
-    }
-
-    // dst link
-    token = strsep(&str, " ");
-    if (!token) {
-       return -1;
-    }
-    printk("dst link ID=(%s)\n", token);
-
-    // Figure out link here
-    if (route->dst_type == LINK_EDGE) {
-       uint32_t link_ip;
-
-       // Figure out Link Here
-       if (in4_pton(token, strlen(token), (uint8_t *)&(link_ip), '\0', NULL) != 1) {
-           printk("Invalid Dst IP address (%s)\n", token);
-           return -EFAULT;
-       }
-
-       link = link_by_ip(link_ip);
-       if (link != NULL){
-           route->dst_id = link->link_idx;
-       }else{
-           printk("can not find dst link %s\n", token);
-           return -1;
-       }
-
-       printk("link_ip = %d, link_id = %d\n", link_ip, link->link_idx);        
-    } else if (route->dst_type == LINK_INTERFACE) {
-       uint8_t mac[ETH_ALEN];
-       
-       if(str2mac(token, mac) == -1){
-          printk("wrong MAC format (%s)\n", token);
-          return -1;
-       }
-          
-       route->dst_id = v3_vnet_find_dev(mac);
-       if (route->dst_id == -1){
-           printk("can not find dst device %s\n", token);
-           return -1;
-       }               
-    } else {
-       printk("Unsupported dst link type\n");
-       return -1;
-    }
-
-    route->src_id = -1;
-    route->src_type = -1;
-
-    // src LINK
-    token = strsep(&str, " ");
-
-    printk("SRC type = %s\n", token);
-
-    if (!token) {
-       return -1;
-    }
-
-    if (strnicmp("interface", token, strlen("interface")) == 0) {
-       route->src_type = LINK_INTERFACE;
-    } else if (strnicmp("edge", token, strlen("edge")) == 0) {
-       route->src_type = LINK_EDGE;
-    } else if (strnicmp("any", token, strlen("any")) == 0) {
-       route->src_type = LINK_ANY;
-    } else {
-       printk("Invalid Src link type (%s)\n", token);
-       return -1;
-    }
-
-
-    if (route->src_type == LINK_ANY) {
-       route->src_id = -1;
-    } else if (route->src_type == LINK_EDGE) {
-       uint32_t src_ip;
-       token = strsep(&str, " ");
-
-       if (!token) {
-           return -1;
-       }
-
-       // Figure out Link Here
-       if (in4_pton(token, strlen(token), (uint8_t *)&(src_ip), '\0', NULL) != 1) {
-           printk("Invalid SRC IP address (%s)\n", token);
-           return -EFAULT;
-       }
-
-       link = link_by_ip(src_ip);
-       if (link != NULL){
-           route->src_id = link->link_idx;
-       }else{
-           printk("can not find src link %s\n", token);
-           return -1;
-       }
-    } else if(route->src_type == LINK_INTERFACE){
-       uint8_t mac[ETH_ALEN];
-       
-       if(str2mac(token, mac) == -1){
-          printk("wrong MAC format (%s)\n", token);
-          return -1;
-       }
-          
-       route->src_id = v3_vnet_find_dev(mac);
-       if (route->src_id == -1){
-           printk("can not find dst device %s\n", token);
-           return -1;
-       }               
-    } else {
-       printk("Invalid link type\n");
-       return -1;
-    }
-
-    return 0;
+static void *
+host_paddr_to_vaddr(void * paddr)
+{
+    return __va(paddr);
 }
 
 
+static void *
+host_start_kernel_thread(
+       int (*fn)(void * arg),
+       void * arg,
+       char * thread_name) {
+    struct task_struct * thread = NULL;
 
+    thread = kthread_run(fn, arg, thread_name );
 
-static void * route_seq_start(struct seq_file * s, loff_t * pos) {
-    struct palacios_vnet_route * route_iter = NULL;
-    loff_t i = 0;
-
-
-    if (*pos >= vnet_state.num_routes) {
-       return NULL;
-    }
-
-    list_for_each_entry(route_iter, &(vnet_state.route_list), node) {
-
-       if (i == *pos) {
-           break;
-       }
-
-       i++;
-    }
-
-    return route_iter;
+    return thread;
 }
 
+static void host_kthread_sleep(long timeout){
+    set_current_state(TASK_INTERRUPTIBLE);
 
-static void * link_seq_start(struct seq_file * s, loff_t * pos) {
-    struct vnet_link * link_iter = NULL;
-    loff_t i = 0;
-
-    if (*pos >= vnet_state.num_links) {
-       return NULL;
-    }
-
-    list_for_each_entry(link_iter, &(vnet_state.link_list), node) {
-
-       if (i == *pos) {
-           break;
-       }
-
-       i++;
+    if(timeout <= 0){
+       schedule();
+    }else {
+       schedule_timeout(timeout);
     }
 
-    return link_iter;
+    return;
 }
 
-
-
-static void * route_seq_next(struct seq_file * s, void * v, loff_t * pos) {
-    struct palacios_vnet_route * route_iter = NULL;
-
-    route_iter = list_entry(((struct palacios_vnet_route *)v)->node.next, struct palacios_vnet_route, node);
-
-    // Check if the list has looped
-    if (&(route_iter->node) == &(vnet_state.route_list)) {
-       return NULL;
-    }
-
-    *pos += 1;
-
-    return route_iter;
+static void host_kthread_wakeup(void * thread){
+    struct task_struct * kthread = (struct task_struct *)thread;
+       
+    wake_up_process(kthread);
 }
 
+static void host_kthread_stop(void * thread){
+    struct task_struct * kthread = (struct task_struct *)thread;
 
-static void * link_seq_next(struct seq_file * s, void * v, loff_t * pos) {
-    struct vnet_link * link_iter = NULL;
-
-    link_iter = list_entry(((struct vnet_link *)v)->node.next, struct vnet_link, node);
-
-    // Check if the list has looped
-    if (&(link_iter->node) == &(vnet_state.link_list)) {
-       return NULL;
-    }
-
-    *pos += 1;
-
-    return link_iter;
+    kthread_stop(kthread);
 }
 
+static int host_kthread_should_stop(void){
+    return kthread_should_stop();
+}
 
-static void route_seq_stop(struct seq_file * s, void * v) {
-    printk("route_seq_stop\n");
 
-    return;
+static void host_udelay(unsigned long usecs){
+    udelay(usecs);
 }
 
 
-static void link_seq_stop(struct seq_file * s, void * v) {
-    printk("link_seq_stop\n");
 
+static void
+host_yield_cpu(void)
+{
+    schedule();
     return;
 }
 
-static int route_seq_show(struct seq_file * s, void * v) {
-    struct palacios_vnet_route * route_iter = v;
-    struct v3_vnet_route * route = &(route_iter->route);
-
-    seq_printf(s, "%d:\t", route_iter->route_idx);
-
-    seq_printf(s, "\nSrc:\t");
-    switch (route->src_mac_qual) {
-       case MAC_ANY:
-           seq_printf(s, "any ");
-           break;
-       case MAC_NONE:
-           seq_printf(s, "none ");
-           break;
-       case MAC_NOT:
-           seq_printf(s, "not-%2x:%2x:%2x:%2x:%2x:%2x ", 
-                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
-                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
-           break;
-       default:
-           seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
-                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
-                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
-           break;
-    }
+static void *
+host_mutex_alloc(void)
+{
+    spinlock_t * lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
 
-    seq_printf(s, "\nDst:\t");
-    switch (route->dst_mac_qual) {
-       case MAC_ANY:
-           seq_printf(s, "any ");
-           break;
-       case MAC_NONE:
-           seq_printf(s, "none ");
-           break;
-       case MAC_NOT:
-           seq_printf(s, "not-%x:%x:%x:%x:%x:%x ", 
-                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
-                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
-           break;
-       default:
-           seq_printf(s, "%x:%x:%x:%x:%x:%x ", 
-                      route->src_mac[0], route->src_mac[1], route->src_mac[2],
-                      route->src_mac[3], route->src_mac[4], route->src_mac[5]);
-           break;
+    if (lock) {
+       spin_lock_init(lock);
     }
 
-    seq_printf(s, "\nDst-Type:\t");
-    switch (route->dst_type) {
-       case LINK_EDGE: {
-           struct vnet_link * link = (struct vnet_link *)link_by_idx(route->dst_id);
-           seq_printf(s, "EDGE %pI4", &link->dst_ip);
-           break;
-       }
-       case LINK_INTERFACE: {
-           seq_printf(s, "INTERFACE ");
-           seq_printf(s, "%d ", route->dst_id);
-           break;
-       }
-       default:
-           seq_printf(s, "Invalid Dst Link Type (%d) ", route->dst_type);
-           break;
-    }
-
-    seq_printf(s, "\nSrc-Type:\t");
-    switch (route->src_type) {
-       case LINK_EDGE: {
-           struct vnet_link * link = (struct vnet_link *)link_by_idx(route->src_id);
-           seq_printf(s, "EDGE %pI4", &link->dst_ip);
-           break;
-       }
-       case LINK_INTERFACE: {
-           seq_printf(s, "INTERFACE %d", route->src_id);
-           break;
-       }
-       case LINK_ANY:
-           seq_printf(s, "ANY");
-           break;
-       default:
-           seq_printf(s, "Invalid Src Link Type (%d) ", route->src_type);
-           break;
-    }
-
-
-    seq_printf(s, "\n");
-
-    return 0;
-}
-
-
-static int link_seq_show(struct seq_file * s, void * v) {
-    struct vnet_link * link_iter = v;
-
-    seq_printf(s, "%d:\t%pI4\t%d\n", 
-              link_iter->link_idx,
-              &link_iter->dst_ip,
-              link_iter->dst_port);
-
-    return 0;
-}
-
-
-static struct seq_operations route_seq_ops = {
-    .start = route_seq_start, 
-    .next = route_seq_next,
-    .stop = route_seq_stop,
-    .show = route_seq_show
-};
-
-
-static struct seq_operations link_seq_ops = {
-    .start = link_seq_start,
-    .next = link_seq_next,
-    .stop = link_seq_stop,
-    .show = link_seq_show
-};
-
-
-static int route_open(struct inode * inode, struct file * file) {
-    return seq_open(file, &route_seq_ops);
+    return lock;
 }
 
-
-static int link_open(struct inode * inode, struct file * file) {
-    return seq_open(file, &link_seq_ops);
+static void
+host_mutex_free(
+       void * mutex
+) 
+{
+    kfree(mutex);
 }
 
-static int inject_route(struct palacios_vnet_route * route) {
-    unsigned long flags;
-
-    v3_vnet_add_route(route->route);
-
-    spin_lock_irqsave(&(vnet_state.lock), flags);
-    list_add(&(route->node), &(vnet_state.route_list));
-    route->route_idx = vnet_state.num_routes++;
-    spin_unlock_irqrestore(&(vnet_state.lock), flags);
-
-    printk("Palacios-vnet: One route added to VNET core\n");
-
-    return 0;
-}
-
-static ssize_t 
-route_write(struct file * file, 
-           const char * buf, 
-           size_t size, 
-           loff_t * ppos) {
-    char route_buf[256];
-    char * buf_iter = NULL;
-    char * line_str = route_buf;
-    char * token = NULL;
-
-    if (size >= 256) {
-       return -EFAULT;
-    }
-
-    if (copy_from_user(route_buf, buf, size)) {
-       return -EFAULT;
-    }
-
-    printk("Route written: %s\n", route_buf);
-
-    while ((buf_iter = strsep(&line_str, "\r\n"))) {
-
-       token = strsep(&buf_iter, " ");
-       if (!token) {
-           return -EFAULT;
-       }
-       
-       if (strnicmp("ADD", token, strlen("ADD")) == 0) {
-           struct palacios_vnet_route * new_route = NULL;
-           new_route = kmalloc(sizeof(struct palacios_vnet_route), GFP_KERNEL);
-           
-           if (!new_route) {
-               return -ENOMEM;
-           }
-           
-           memset(new_route, 0, sizeof(struct palacios_vnet_route));
-           
-           if (parse_route_str(buf_iter, &(new_route->route)) == -1) {
-               kfree(new_route);
-               return -EFAULT;
-           }
-           
-           if (inject_route(new_route) != 0) {
-               return -EFAULT;
-           }
-       } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
-           printk("I should delete the route here\n");
-       } else {
-           printk("Invalid Route command string\n");
-       }
-    }
-
-    return size;
+static void 
+host_mutex_lock(void * mutex, 
+               int must_spin)
+{
+    spin_lock((spinlock_t *)mutex);
 }
 
-
-static int create_link(struct vnet_link * link) {
-    int err;
-    unsigned long flags;
-
-    if ( (err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &link->sock)) < 0) {
-       printk("Could not create socket\n");
-       return -1;
-    }
-
-    memset(&link->sock_addr, 0, sizeof(struct sockaddr));
-
-    link->sock_addr.sin_family = AF_INET;
-    link->sock_addr.sin_addr.s_addr = link->dst_ip;
-    link->sock_addr.sin_port = htons(link->dst_port);
-
-    if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0) < 0)) {
-       printk("Could not connect to remote host\n");
-       return -1;
-    }
-
-    // We use the file pointer because we are in the kernel
-    // This is only used to assigned File Descriptors for user space, so it is available here
-    // link->sock->file = link;
-
-    spin_lock_irqsave(&(vnet_state.lock), flags);
-    list_add(&(link->node), &(vnet_state.link_list));
-    link->link_idx = vnet_state.num_links++;
-    spin_unlock_irqrestore(&(vnet_state.lock), flags);
-
-    printk("VNET Bridge: Link created, ip %d, port: %d, idx: %d, link: %p\n", 
-          link->dst_ip, 
-          link->dst_port, 
-          link->link_idx, 
-          link);
-
-    return 0;
+static void 
+host_mutex_unlock(void * mutex) 
+{
+    spin_unlock((spinlock_t *)mutex);
 }
 
 
-/* ADD dst-ip 9000 */
-static ssize_t 
-link_write(struct file * file, const char * buf, size_t size, loff_t * ppos) {
-    char link_buf[256];
-    char * link_iter = NULL;
-    char * line_str = link_buf;
-    char * token = NULL;
-
-    if (size >= 256) {
-       return -EFAULT;
-    }
-
-    if (copy_from_user(link_buf, buf, size)) {
-       return -EFAULT;
-    }
-
-    while ((link_iter = strsep(&line_str, "\r\n"))) {
-       printk("Link written: %s\n", link_buf);
-       
-       token = strsep(&link_iter, " ");
-       
-       if (!token) {
-           return -EFAULT;
-       }
-       
-       if (strnicmp("ADD", token, strlen("ADD")) == 0) {
-           struct vnet_link * new_link = NULL;
-           char * ip_str = NULL;
-           uint32_t ip;
-           
-           ip_str = strsep(&link_iter, " ");
-           
-           if ((!ip_str) || (!link_iter)) {
-               printk("Missing fields in ADD Link command\n");
-               return -EFAULT;
-           }
-           
-           if (in4_pton(ip_str, strlen(ip_str), (uint8_t *)&(ip), '\0', NULL) != 1) {
-               printk("Invalid Dst IP address (%s)\n", ip_str);
-               return -EFAULT;
-           }
-
-           new_link = kmalloc(sizeof(struct vnet_link), GFP_KERNEL);
-
-           if (!new_link) {
-               return -ENOMEM;
-           }
-
-           memset(new_link, 0, sizeof(struct vnet_link));
-
-           new_link->dst_ip = ip;
-           new_link->dst_port = simple_strtol(link_iter, &link_iter, 10);
-           
-           if (create_link(new_link) != 0) {
-               printk("Could not create link\n");
-               kfree(new_link);
-               return -EFAULT;
-           }
-
-       } else if (strnicmp("DEL", token, strlen("DEL")) == 0) {
-           printk("Link deletion not supported\n");
-       } else {
-           printk("Invalid Link command string\n");
-       }
-    }
-
-    return size;
-}
-
 
-static struct file_operations route_fops = {
-    .owner = THIS_MODULE,
-    .open = route_open, 
-    .read = seq_read,
-    .write = route_write,
-    .llseek = seq_lseek,
-    .release = seq_release
-};
 
+struct host_timer {
+    struct timer_list timer;
+    unsigned long interval;
 
-static struct file_operations link_fops = {
-    .owner = THIS_MODULE,
-    .open = link_open, 
-    .read = seq_read,
-    .write = link_write,
-    .llseek = seq_lseek,
-    .release = seq_release
+    int active;
+    void (* timer_fun)(void * private_data);
+    void * pri_data;
 };
 
 
-static int init_proc_files(void) {
-    struct proc_dir_entry * route_entry = NULL;
-    struct proc_dir_entry * link_entry = NULL;
-    struct proc_dir_entry * vnet_root = NULL;
-
-
-    vnet_root = proc_mkdir("vnet", NULL);
-    if (vnet_root == NULL) {
-       return -1;
-    }
-
-    route_entry = create_proc_entry("routes", 0, vnet_root);
-
-    if (route_entry == NULL) {
-       remove_proc_entry("vnet", NULL);
-       return -1;
-    }
-
-    route_entry->proc_fops = &route_fops;
+void timeout_fn(unsigned long arg){
+    struct host_timer * timer = (struct host_timer *)arg;
 
-
-    link_entry = create_proc_entry("links", 0, vnet_root);
-
-    if (link_entry == NULL) {
-       remove_proc_entry("routes", vnet_root);
-       remove_proc_entry("vnet", NULL);
-       return -1;
+    if(timer->active){
+       timer->timer_fun(timer->pri_data);
+       
+       mod_timer(&(timer->timer), timer->interval);
     }
-
-    link_entry->proc_fops = &link_fops;
-
-    return 0;
-
 }
 
+static void *
+host_create_timer(unsigned long interval, 
+                 void (* timer_fun)(void * priv_data), 
+                 void * data){
+    struct host_timer * timer = (struct host_timer *)kmalloc(sizeof(struct host_timer), GFP_KERNEL);
 
+    timer->interval = interval;
+    timer->timer_fun = timer_fun;
+    timer->pri_data = data;
 
-static int 
-udp_send(struct socket * sock, 
-        struct sockaddr_in * addr,
-        unsigned char * buf,  int len) {
-    struct msghdr msg;
-    struct iovec iov;
-    mm_segment_t oldfs;
-    int size = 0;
-
-         
-    if (sock->sk == NULL) {
-       return 0;
-    }
-
-    iov.iov_base = buf;
-    iov.iov_len = len;
+    init_timer(&(timer->timer));
 
-    msg.msg_flags = 0;
-    msg.msg_name = addr;
-    msg.msg_namelen = sizeof(struct sockaddr_in);
-    msg.msg_control = NULL;
-    msg.msg_controllen = 0;
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-    msg.msg_control = NULL;
+    timer->timer.data = (unsigned long)timer;
+    timer->timer.function = timeout_fn;
+    timer->timer.expires = interval;
 
-    oldfs = get_fs();
-    set_fs(KERNEL_DS);
-    size = sock_sendmsg(sock, &msg, len);
-    set_fs(oldfs);
-
-    return size;
+    return timer;
 }
 
+static void
+host_start_timer(void * vnet_timer){
+    struct host_timer * timer = (struct host_timer *)vnet_timer;
 
-
-static int 
-udp_recv(struct socket * sock, 
-        struct sockaddr_in * addr,
-        unsigned char * buf, int len) {
-    struct msghdr msg;
-    struct iovec iov;
-    mm_segment_t oldfs;
-    int size = 0;
-    
-    if (sock->sk == NULL) {
-       return 0;
-    }
-
-    iov.iov_base = buf;
-    iov.iov_len = len;
-    
-    msg.msg_flags = 0;
-    msg.msg_name = addr;
-    msg.msg_namelen = sizeof(struct sockaddr_in);
-    msg.msg_control = NULL;
-    msg.msg_controllen = 0;
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-    msg.msg_control = NULL;
-    
-    oldfs = get_fs();
-    set_fs(KERNEL_DS);
-    size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
-       
-    set_fs(oldfs);
-    
-    return size;
+    timer->active = 1;
+    add_timer(&(timer->timer));
 }
 
-//send packets from Network to VNET core
-static int 
-send_to_palacios(unsigned char * buf, 
-                int len,
-                int link_id){
-    struct v3_vnet_pkt pkt;
-    pkt.size = len;
-    pkt.src_type = LINK_EDGE;
-    pkt.src_id = link_id;
-    memcpy(pkt.header, buf, ETHERNET_HEADER_LEN);
-    pkt.data = buf;
-
-#ifdef CONFIG_PALACIOS_VNET_DEBUG
-    {
-       printk("VNET Lnx Bridge: send pkt to VNET core (size: %d, src_id: %d, src_type: %d)\n", 
-                       pkt.size,  pkt.src_id, pkt.src_type);
-
-       print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt.data, pkt.size, 0);
-    }
-#endif
+static void
+host_reset_timer(void * vnet_timer, unsigned long interval){
+    struct host_timer * timer = (struct host_timer *)timer;
 
-    return v3_vnet_send_pkt(&pkt, NULL);;
+    timer->interval = interval;
 }
 
+static void
+host_stop_timer(void * vnet_timer){
+    struct host_timer * timer = (struct host_timer *)vnet_timer;
 
-//send packet from VNET core to Network
-static int 
-bridge_send_pkt(struct v3_vm_info * vm, 
-               struct v3_vnet_pkt * pkt, 
-               void * private_data) {
-    struct vnet_link * link;
-
-    #ifdef CONFIG_PALACIOS_VNET_DEBUG
-          {
-               printk("VNET Lnx Host Bridge: packet received from VNET Core ... len: %d, pkt size: %d, link: %d\n",
-                       len,
-                       pkt->size,
-                       pkt->dst_id);
-
-               print_hex_dump(NULL, "pkt_data: ", 0, 20, 20, pkt->data, pkt->size, 0);
-          }
-    #endif
-
-    vnet_state.pkt_recv ++;
-
-    link = link_by_idx(pkt->dst_id);
-    if (link != NULL) {
-       udp_send(link->sock, &(link->sock_addr), pkt->data, pkt->size);
-       vnet_state.pkt_udp_send ++;
-    } else {
-       printk("VNET Bridge Linux Host: wrong dst link, idx: %d, discards the packet\n", pkt->dst_id);
-       vnet_state.pkt_drop ++;
-    }
-
-    return 0;
+    timer->active = 0;
+    del_timer(&(timer->timer));
 }
 
+static void
+host_del_timer(void * vnet_timer){
+    struct host_timer * timer = (struct host_timer *)vnet_timer;
 
-static void 
-poll_pkt(struct v3_vm_info * vm, 
-        void * private_data) {
-
+    del_timer(&(timer->timer));
 
+    kfree(timer);
 }
 
 
 
-static int init_vnet_serv(void) {
-     
-    if (sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vnet_state.serv_sock) < 0) {
-       printk("Could not create socket\n");
-       return -1;
-    }
 
-    memset(&vnet_state.serv_addr, 0, sizeof(struct sockaddr));
 
-    vnet_state.serv_addr.sin_family = AF_INET;
-    vnet_state.serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-    vnet_state.serv_addr.sin_port = htons(VNET_UDP_PORT);
+static struct vnet_host_hooks vnet_host_hooks = {
+    .timer_create      = host_create_timer,
+    .timer_del         = host_del_timer,
+    .timer_start               = host_start_timer,
+    .timer_stop                = host_stop_timer,
+    .timer_reset       = host_reset_timer,
 
-    if (vnet_state.serv_sock->ops->bind(vnet_state.serv_sock, (struct sockaddr *)&(vnet_state.serv_addr), sizeof(struct sockaddr)) < 0) {
-       printk("Could not bind VNET server socket to port %d\n", VNET_UDP_PORT);
-       return -1;
-    }
+    .thread_start      = host_start_kernel_thread,
+    .thread_sleep      = host_kthread_sleep,
+    .thread_wakeup     = host_kthread_wakeup,
+    .thread_stop       = host_kthread_stop,
+    .thread_should_stop        = host_kthread_should_stop,
+    .udelay    = host_udelay,
 
-    printk("VNET server bind to port: %d\n", VNET_UDP_PORT);
+    .yield_cpu         = host_yield_cpu,
+    .mutex_alloc       = host_mutex_alloc,
+    .mutex_free        = host_mutex_free,
+    .mutex_lock        = host_mutex_lock, 
+    .mutex_unlock      = host_mutex_unlock,
 
-    return 0;
-}
+    .print                     = host_print,
+    .allocate_pages    = host_allocate_pages,
+    .free_pages        = host_free_pages,
+    .malloc            = host_alloc,
+    .free                      = host_free,
+    .vaddr_to_paddr            = host_vaddr_to_paddr,
+    .paddr_to_vaddr            = host_paddr_to_vaddr,
+};
 
-static int vnet_server(void * arg) {
-    unsigned char pkt[ETHERNET_PACKET_LEN];
-    struct sockaddr_in pkt_addr;
-    struct vnet_link *link = NULL;
-    int len;
-    int link_id;
 
-    printk("Palacios VNET Bridge: UDP receiving server ..... \n");
 
-    while (!kthread_should_stop()) {
-       
-       len = udp_recv(vnet_state.serv_sock, &pkt_addr, pkt, ETHERNET_PACKET_LEN); 
-       if(len < 0) {
-           printk("Receive error: Could not get packet, error %d\n", len);
-           continue;
-       }
-
-       link = link_by_ip(ntohl(pkt_addr.sin_addr.s_addr));
-       if (link != NULL){
-           link_id= link->link_idx;
-       }
-       else { 
-           link_id= 0;
-       }
+int palacios_vnet_init( void ) {
+    init_vnet(&vnet_host_hooks);
        
-       vnet_state.pkt_udp_recv ++;
-
-       send_to_palacios(pkt, len, link_id);
-    }
+    vnet_bridge_init();
+    vnet_ctrl_init();
 
+    printk("V3 VNET Inited\n");
+        
     return 0;
 }
 
 
-int  palacios_init_vnet(void) {
-    struct v3_vnet_bridge_ops bridge_ops;
-       
-    memset(&vnet_state, 0, sizeof(struct palacios_vnet_state));
-
-    INIT_LIST_HEAD(&(vnet_state.link_list));
-    INIT_LIST_HEAD(&(vnet_state.route_list));
-    spin_lock_init(&(vnet_state.lock));
+void palacios_vnet_deinit( void ) {
+    deinit_vnet();
 
-    init_proc_files();
-    if(init_vnet_serv() < 0){
-       printk("Failure to initiate VNET server\n");
-       return -1;
-    }
+    vnet_bridge_deinit();
+    vnet_ctrl_deinit();
 
-    vnet_state.serv_thread = kthread_run(vnet_server, NULL, "vnet-server");
-
-    //kthread_run(profiling, NULL, "Profiling");
-
-    bridge_ops.input = bridge_send_pkt;
-    bridge_ops.poll = poll_pkt;
-       
-    v3_vnet_add_bridge(NULL, &bridge_ops, HOST_LNX_BRIDGE, NULL);
-
-    printk("Palacios VNET Linux Bridge initiated\n");
-
-    return 0;
+    printk("V3 VNET Deinited\n");
 }
 
index 98f8dce..56ac9f1 100644 (file)
@@ -1,14 +1,38 @@
 /*
- * Palacios VNET Linux Bridge
+ * Palacios VNET Host Header
  * (c) Lei Xia, 2010
  */
 
-#ifndef __PALACIOS_VNET_BRIDGE_H__
-#define __PALACIOS_VNET_BRIDGE_H__
+#ifndef __PALACIOS_VNET_H__
+#define __PALACIOS_VNET_H__
 
-#include <palacios/vmm_vnet.h>
+#include <vnet/vnet.h>
+
+int  palacios_vnet_init(void);
+void palacios_vnet_deinit(void);
+
+typedef enum {UDP, TCP, RAW, NONE} vnet_brg_proto_t;
+
+struct vnet_brg_stats{
+    uint64_t pkt_from_vmm;
+    uint64_t pkt_to_vmm;
+    uint64_t pkt_drop_vmm;
+    uint64_t pkt_from_phy;
+    uint64_t pkt_to_phy;
+    uint64_t pkt_drop_phy;
+};
+
+void vnet_brg_delete_link(uint32_t idx);
+uint32_t vnet_brg_add_link(uint32_t ip, uint16_t port, vnet_brg_proto_t proto);
+int vnet_brg_link_stats(uint32_t link_idx, struct nic_statistics * stats);
+int vnet_brg_stats(struct vnet_brg_stats * stats);
+int  vnet_bridge_init(void);
+void vnet_bridge_deinit(void);
+
+
+int vnet_ctrl_init(void);
+void vnet_ctrl_deinit(void);
 
-int  palacios_init_vnet(void);
 
 #endif
 
index 7a3238e..fc64360 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/kthread.h>
 #include <asm/uaccess.h>
+#include <linux/smp.h>
 #include <linux/smp_lock.h>
 
 #include <palacios/vmm.h>
@@ -139,9 +140,12 @@ palacios_xcall(
        void *                  arg
 )
 {
-  printk("palacios_xcall: Doing 'xcall' to local cpu\n");
-  fn(arg);
-  return;
+
+
+    // We set wait to 1, but I'm not sure this is necessary
+    smp_call_function_single(cpu_id, fn, arg, 1);
+    
+    return;
 }
 
 struct lnx_thread_arg {
@@ -206,13 +210,17 @@ palacios_start_thread_on_cpu(int cpu_id,
     thread_info->arg = arg;
     thread_info->name = thread_name;
 
-    thread = kthread_run( lnx_thread_target, thread_info, thread_name );
+
+    thread = kthread_create( lnx_thread_target, thread_info, thread_name );
 
     if (IS_ERR(thread)) {
        printk("Palacios error creating thread: %s\n", thread_name);
        return NULL;
     }
 
+    kthread_bind(thread, cpu_id);
+    wake_up_process(thread);
+
     return thread;
 }
 
@@ -222,23 +230,15 @@ palacios_start_thread_on_cpu(int cpu_id,
 static unsigned int 
 palacios_get_cpu(void) 
 {
-#if 1
-    return 0;
-    // return smp_processor_id();
-    // id = get_cpu(); put_cpu(id);
-    // return this_cpu;
-#else
-               struct cpumask mask;    
-               unsigned int set;
-
-               if(sched_getaffinity(0,&mask)<0){
-                       panic("sched_getaffinity failed");
-                       return -1;
-               }
-               set = cpumask_first(&mask);
-               printk("***mask.bits: %d",set);
-               return set;
-#endif
+
+    /* We want to call smp_processor_id()
+     * But this is not safe if kernel preemption is possible 
+     * We need to ensure that the palacios threads are bound to a give cpu
+     */
+
+    unsigned int cpu_id = get_cpu(); 
+    put_cpu();
+    return cpu_id;
 }
 
 /**
@@ -252,6 +252,9 @@ palacios_get_cpu(void)
  * If it ever changes to induce side effects, we'll need to figure something
  * else out...
  */
+
+#include <asm/apic.h>
+
 static void
 palacios_interrupt_cpu(
        struct v3_vm_info *     vm, 
@@ -259,9 +262,12 @@ palacios_interrupt_cpu(
        int                     vector
 )
 {
-    // panic("palacios_interrupt_cpu");
-       //  printk("Faking interruption of target CPU by not doing anything since there is only one CPU\n");
-  return;
+    if (vector == 0) {
+       smp_send_reschedule(cpu_id);
+    } else {
+       apic->send_IPI_mask(cpumask_of(cpu_id), vector);
+    }
+    return;
 }
 
 /**
@@ -342,6 +348,8 @@ palacios_hook_interrupt(struct v3_vm_info * vm,
     return 0;
 }
 
+
+
 /**
  * Acknowledges an interrupt.
  */
@@ -362,7 +370,8 @@ static unsigned int
 palacios_get_cpu_khz(void) 
 {
     printk("cpu_khz is %u\n",cpu_khz);
-    if (cpu_khz==0) { 
+
+    if (cpu_khz == 0) { 
        printk("faking cpu_khz to 1000000\n");
        return 1000000;
     } else {
@@ -390,33 +399,29 @@ palacios_yield_cpu(void)
 static void *
 palacios_mutex_alloc(void)
 {
-  spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
-  if (lock)
-       spin_lock_init(lock);
-  return lock;
+    spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+
+    if (lock) {
+       spin_lock_init(lock);
+    }
+    
+    return lock;
 }
 
 /**
  * Frees a mutex.
  */
 static void
-palacios_mutex_free(
-       void *                  mutex
-) 
-{
-  kfree(mutex);
+palacios_mutex_free(void * mutex) {
+    kfree(mutex);
 }
 
 /**
  * Locks a mutex.
  */
 static void 
-palacios_mutex_lock(
-       void *                  mutex, 
-       int                     must_spin
-)
-{
-  spin_lock((spinlock_t*)mutex);
+palacios_mutex_lock(void * mutex, int must_spin) {
+    spin_lock((spinlock_t *)mutex);
 }
 
 /**
@@ -427,7 +432,7 @@ palacios_mutex_unlock(
        void *                  mutex
 ) 
 {
-  spin_unlock((spinlock_t*)mutex);
+    spin_unlock((spinlock_t *)mutex);
 }
 
 /**
@@ -466,8 +471,7 @@ int palacios_vmm_init( void )
     
     printk("palacios_init starting - calling init_v3\n");
     
-    Init_V3(&palacios_os_hooks, 1);
-        
+    Init_V3(&palacios_os_hooks, nr_cpu_ids);
 
     return 0;
 
index 9f27187..9fe9c29 100644 (file)
@@ -6,7 +6,18 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 
+#ifdef V3_CONFIG_CONSOLE
 #include "palacios-console.h"
+#endif
+
+#ifdef V3_CONFIG_GRAPHICS_CONSOLE
+#include "palacios-graphics-console.h"
+#endif
+
+#ifdef V3_CONFIG_HOST_DEVICE
+#include "palacios-host-dev.h"
+#endif
+
 
 /* Global Control IOCTLs */
 #define V3_START_GUEST 10
 
 /* VM Specific IOCTLs */
 #define V3_VM_CONSOLE_CONNECT 20
-#define V3_VM_SERIAL_CONNECT 21
+#define V3_VM_STREAM_CONNECT 21
 #define V3_VM_STOP 22
 
+#define V3_VM_FB_INPUT (256+1)
+#define V3_VM_FB_QUERY (256+2)
+
+#define V3_VM_HOST_DEV_CONNECT (10244+1)
+
+
 struct v3_guest_img {
     unsigned long long size;
     void * guest_data;
@@ -51,7 +68,18 @@ struct v3_guest {
     struct list_head streams;
     struct list_head sockets;
 
+#ifdef V3_CONFIG_CONSOLE
     struct palacios_console console;
+#endif
+
+#ifdef V3_CONFIG_GRAPHICS_CONSOLE
+    struct palacios_graphics_console graphics_console;
+#endif
+
+#ifdef V3_CONFIG_HOST_DEVICE
+    struct palacios_host_dev hostdev;
+#endif
+
 
     struct completion start_done;
     struct completion thread_done;
index 2fc1ad8..439494c 100644 (file)
@@ -1,4 +1,5 @@
-all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net
+all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example v3_os_debug
+
 
 
 v3_ctrl : v3_ctrl.c v3_ctrl.h
@@ -23,5 +24,12 @@ v3_monitor : v3_cons.c v3_ctrl.h
 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
+
+v3_os_debug: v3_os_debug.c v3_user_host_dev.h v3_user_host_dev.c
+       gcc -static -I../linux_module v3_os_debug.c v3_user_host_dev.c -o v3_os_debug
+
+
 clean:
-       rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_serial v3_net
+       rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example v3_os_debug
diff --git a/linux_usr/v3_os_debug.c b/linux_usr/v3_os_debug.c
new file mode 100644 (file)
index 0000000..c530964
--- /dev/null
@@ -0,0 +1,128 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/select.h>
+#include <malloc.h>
+
+#include "v3_user_host_dev.h"
+
+void usage()
+{
+    fprintf(stderr,"v3_user_host_dev_example /dev/v3-vm0 user:mydev busywait|select\n");
+}
+
+
+int do_work(struct palacios_host_dev_host_request_response *req, 
+           struct palacios_host_dev_host_request_response **resp)
+{
+    uint64_t datasize;
+
+    switch (req->type) {
+    case PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO: {
+      if (req->port==0xc0c0) {
+       uint64_t i;
+       uint64_t numchars;
+       numchars = req->data_len - sizeof(struct palacios_host_dev_host_request_response);
+       for (i=0;i<numchars;i++) { 
+         putchar(req->data[i]);
+       }
+       *resp = malloc(sizeof(struct palacios_host_dev_host_request_response));
+       **resp=*req;
+       (*resp)->len = (*resp)->data_len = sizeof(struct palacios_host_dev_host_request_response);
+       (*resp)->op_len = numchars;
+      } else {
+       printf("Huh?  Unknown port %d\n",req->port);
+      }
+    }
+      break;
+
+      default:
+       printf("Huh?  Unknown request %d\n", req->type);
+    }
+    
+    
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    int devfd;
+    int mode=0;
+    char *vm, *url;
+
+    if (argc!=4) { 
+       usage();
+       exit(-1);
+    }
+    
+    vm=argv[1];
+    url=argv[2];
+    mode = argv[3][0]=='s';
+
+    fprintf(stderr,"Attempting to rendezvous with host device %s on vm %s\n", url, vm);
+    
+    if ((devfd = v3_user_host_dev_rendezvous(vm,url))<0) { 
+       perror("failed to rendezvous");
+       exit(-1);
+    }
+    
+    fprintf(stderr,"Rendezvous succeeded, I will now operate in %s mode\n", mode==0 ? "busywait" : "select");
+    
+    if (mode==0) { 
+       //busywait
+
+       struct palacios_host_dev_host_request_response *req;
+       struct palacios_host_dev_host_request_response *resp;
+       uint64_t datasize;
+
+       while (1) { 
+           while (!(v3_user_host_dev_have_request(devfd))) { 
+           }
+           v3_user_host_dev_pull_request(devfd, &req);
+
+           do_work(req, &resp);
+           
+           v3_user_host_dev_push_response(devfd, resp);
+
+           free(resp);
+           free(req);
+       }
+    } else {
+
+       struct palacios_host_dev_host_request_response *req;
+       struct palacios_host_dev_host_request_response *resp;
+       uint64_t datasize;
+       fd_set   readset;
+       int rc;
+
+       // select-based operation so that you can wait for multiple things
+       
+       while (1) { 
+           FD_ZERO(&readset);
+           FD_SET(devfd,&readset);
+
+           rc = select(devfd+1, &readset, 0, 0, 0);  // pick whatever you want to select on, just include devfd
+
+           if (rc>0) { 
+               if (FD_ISSET(devfd,&readset)) { 
+                   // a request is read for us!
+                   v3_user_host_dev_pull_request(devfd, &req);
+
+                   do_work(req, &resp);
+                   
+                   v3_user_host_dev_push_response(devfd, resp);
+                   
+                   free(resp);
+                   free(req);
+               }
+           }
+       }
+    }
+
+    v3_user_host_dev_depart(devfd);
+
+    return 0;
+                   
+}
diff --git a/linux_usr/v3_user_host_dev.c b/linux_usr/v3_user_host_dev.c
new file mode 100644 (file)
index 0000000..709db76
--- /dev/null
@@ -0,0 +1,132 @@
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "v3_user_host_dev.h"
+
+
+int v3_user_host_dev_rendezvous(char *vmdev, char *url)
+{
+    int vmfd;
+    int devfd;
+    char buf[256];
+
+
+    strcpy(buf,url);
+    buf[255]=0;
+
+    if ((vmfd=open(vmdev,O_RDWR))<0) { 
+       return -1;
+    }
+
+    devfd = ioctl(vmfd,V3_VM_HOST_DEV_CONNECT,buf);
+    
+    close(vmfd);
+
+    return devfd;
+
+}
+int v3_user_host_dev_depart(int devfd)
+{
+    return close(devfd);
+}
+
+
+int v3_user_host_dev_have_request(int devfd)
+{
+    uint64_t len;
+
+    int rc=ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&len);
+
+    return rc==1;
+}
+
+int v3_user_host_dev_pull_request(int devfd, struct palacios_host_dev_host_request_response **req)
+{
+    uint64_t len;
+    int rc;
+
+    rc=ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&len);
+
+    if (rc<=0) { 
+       return -1;
+    } else {
+       struct palacios_host_dev_host_request_response *r = malloc(len);
+       
+       rc=ioctl(devfd, V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL,r);
+       
+       if (rc<=0) { 
+           free(r);
+           return -1;
+       } else {
+           *req=r;
+           return 0;
+       }
+    }
+}
+               
+
+int v3_user_host_dev_push_response(int devfd, struct palacios_host_dev_host_request_response *resp)
+{
+    int rc;
+
+    rc=ioctl(devfd, V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL,resp);
+       
+    if (rc<=0) { 
+       return -1;
+    } else {
+       return 0;
+    }
+}
+               
+
+
+static uint64_t do_user(int devfd, struct palacios_host_dev_user_op *op)
+{
+    return ioctl(devfd, V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL,op);
+}
+
+uint64_t v3_user_host_dev_read_guest_mem(int devfd, void *gpa, void *dest, uint64_t len)
+{
+    struct palacios_host_dev_user_op op;
+
+    op.type= PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST;
+    op.gpa=gpa;
+    op.data=dest;
+    op.len=len;
+    op.irq=0;
+    
+    return do_user(devfd,&op);
+}
+
+uint64_t v3_user_host_dev_write_guest_mem(int devfd, void *gpa, void *src, uint64_t len)
+{
+    struct palacios_host_dev_user_op op;
+
+    op.type= PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST;
+    op.gpa=gpa;
+    op.data=src;
+    op.len=len;
+    op.irq=0;
+    
+    return do_user(devfd,&op);
+}
+
+int      v3_user_host_dev_inject_irq(int devfd, uint8_t irq)
+{
+    struct palacios_host_dev_user_op op;
+
+    op.type= PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST;
+    op.gpa=0;
+    op.data=0;
+    op.len=0;
+    op.irq=irq;
+    
+    return do_user(devfd,&op);
+}
+
+
+
diff --git a/linux_usr/v3_user_host_dev.h b/linux_usr/v3_user_host_dev.h
new file mode 100644 (file)
index 0000000..523150f
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _V3_USER_HOST_DEV_
+#define _V3_USER_HOST_DEV_
+
+#include <stdint.h>
+#include "palacios-host-dev-user.h"
+
+int v3_user_host_dev_rendezvous(char *vmdev, char *url); // returns devfd for use in poll/select
+int v3_user_host_dev_depart(int devfd);
+
+int v3_user_host_dev_have_request(int devfd);
+int v3_user_host_dev_pull_request(int devfd, struct palacios_host_dev_host_request_response **req);
+int v3_user_host_dev_push_response(int devfd, struct palacios_host_dev_host_request_response *resp);
+
+uint64_t v3_user_host_dev_read_guest_mem(int devfd, void *gpa, void *dest, uint64_t len);
+uint64_t v3_user_host_dev_write_guest_mem(int devfd, void *gpa, void *src, uint64_t len);
+int      v3_user_host_dev_inject_guest_irq(int devfd, uint8_t irq);
+
+#endif
+
diff --git a/linux_usr/v3_user_host_dev_example.c b/linux_usr/v3_user_host_dev_example.c
new file mode 100644 (file)
index 0000000..833f3c5
--- /dev/null
@@ -0,0 +1,124 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/select.h>
+#include <malloc.h>
+
+#include "v3_user_host_dev.h"
+
+void usage()
+{
+    fprintf(stderr,"v3_host_dev_example /dev/v3-vm0 user:mydev busywait|select\n");
+}
+
+
+int do_work(struct palacios_host_dev_host_request_response *req, 
+           struct palacios_host_dev_host_request_response **resp)
+{
+    uint64_t datasize;
+    
+    //
+    //
+    // Process request here, perhaps calling these functions:
+    //
+    // uint64_t v3_user_host_dev_read_guest_mem(int devfd, void *gpa, void *dest, uint64_t len);
+    // uint64_t v3_user_host_dev_write_guest_mem(int devfd, void *gpa, void *src, uint64_t len);
+    // int      v3_user_host_dev_inject_guest_irq(int devfd, uint8_t irq);
+    //
+    // determine datasize - # bytes to include in response
+    //
+    // now built a response
+    *resp = malloc(sizeof(struct palacios_host_dev_host_request_response) + datasize);
+    (*resp)->data_len = sizeof(struct palacios_host_dev_host_request_response) + datasize;
+
+    //
+    // Fill out the fields of the response - notice that there are six kinds of things to response to:
+    //   - read/write device port
+    //   - read/write device mem
+    //   - read/write device configuration space
+
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    int devfd;
+    int mode=0;
+    char *vm, *url;
+
+    if (argc!=4) { 
+       usage();
+       exit(-1);
+    }
+    
+    vm=argv[1];
+    url=argv[2];
+    mode = argv[3][0]=='s';
+
+    fprintf(stderr,"Attempting to rendezvous with host device %s on vm %s\n", url, vm);
+    
+    if ((devfd = v3_user_host_dev_rendezvous(vm,url))<0) { 
+       perror("failed to rendezvous");
+       exit(-1);
+    }
+    
+    fprintf(stderr,"Rendezvous succeeded, I will now operate in %s mode\n", mode==0 ? "busywait" : "select");
+    
+    if (mode==0) { 
+       //busywait
+
+       struct palacios_host_dev_host_request_response *req;
+       struct palacios_host_dev_host_request_response *resp;
+       uint64_t datasize;
+
+       while (1) { 
+           while (!(v3_user_host_dev_have_request(devfd))) { 
+           }
+           v3_user_host_dev_pull_request(devfd, &req);
+
+           do_work(req, &resp);
+           
+           v3_user_host_dev_push_response(devfd, resp);
+
+           free(resp);
+           free(req);
+       }
+    } else {
+
+       struct palacios_host_dev_host_request_response *req;
+       struct palacios_host_dev_host_request_response *resp;
+       uint64_t datasize;
+       fd_set   readset;
+       int rc;
+
+       // select-based operation so that you can wait for multiple things
+       
+       while (1) { 
+           FD_ZERO(&readset);
+           FD_SET(devfd,&readset);
+
+           rc = select(devfd+1, &readset, 0, 0, 0);  // pick whatever you want to select on, just include devfd
+
+           if (rc>0) { 
+               if (FD_ISSET(devfd,&readset)) { 
+                   // a request is read for us!
+                   v3_user_host_dev_pull_request(devfd, &req);
+
+                   do_work(req, &resp);
+                   
+                   v3_user_host_dev_push_response(devfd, resp);
+                   
+                   free(resp);
+                   free(req);
+               }
+           }
+       }
+    }
+
+    v3_user_host_dev_depart(devfd);
+
+    return 0;
+                   
+}
diff --git a/linux_usr/x0vncserver b/linux_usr/x0vncserver
new file mode 100755 (executable)
index 0000000..d173fe8
Binary files /dev/null and b/linux_usr/x0vncserver differ
index a0078ca..665b1c2 100644 (file)
@@ -82,11 +82,16 @@ void v3_init_svm_cpu(int cpu_id);
 void v3_deinit_svm_cpu(int cpu_id);
 
 
+
 int v3_init_svm_vmcb(struct guest_info * core, v3_vm_class_t vm_class);
 int v3_deinit_svm_vmcb(struct guest_info * core);
 
 int v3_svm_enter(struct guest_info * info);
 int v3_start_svm_guest(struct guest_info *info);
+int v3_reset_svm_vm_core(struct guest_info * core, addr_t rip);
+
+
+
 
 #endif
 
index 1eba744..5792543 100644 (file)
 
 
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
 #include <palacios/vmm_telemetry.h>
 #endif
 
 
-#ifdef CONFIG_SYMBIOTIC
+#ifdef V3_CONFIG_SYMBIOTIC
 #include <palacios/vmm_symbiotic.h>
 struct v3_sym_core_state;
 #endif
 
-#ifdef CONFIG_SYSCALL_HIJACK
+#ifdef V3_CONFIG_SYSCALL_HIJACK
 #include <palacios/vmm_syscall_hijack.h>
 #include <palacios/vmm_execve_hook.h>
 #endif
@@ -95,7 +95,7 @@ struct guest_info {
     /* This structure is how we get exceptions for the guest */
     struct v3_excp_state excp_state;
 
-#ifdef CONFIG_SYSCALL_HIJACK
+#ifdef V3_CONFIG_SYSCALL_HIJACK
     struct v3_syscall_hook_map sc_hook_map;
     struct v3_execve_varchunk var_dump;
     struct v3_exec_hooks exec_hooks;
@@ -118,7 +118,7 @@ struct guest_info {
     
     uint64_t num_exits;
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     struct v3_core_telemetry core_telem;
 #endif
 
@@ -127,7 +127,7 @@ struct guest_info {
 
     void * decoder_state;
 
-#ifdef CONFIG_SYMBIOTIC
+#ifdef V3_CONFIG_SYMBIOTIC
     /* Symbiotic state */
     struct v3_sym_core_state sym_core_state;
 #endif
@@ -140,7 +140,10 @@ struct guest_info {
     v3_core_operating_mode_t core_run_state;
 
     /* the logical cpu on which this core runs */
-    uint32_t cpu_id;
+    uint32_t pcpu_id;
+    
+    /* The virtual core # of this cpu (what the guest sees this core as) */
+    uint32_t vcpu_id;
      
 };
 
@@ -156,8 +159,6 @@ struct v3_vm_info {
     uint32_t mem_align;
     struct v3_mem_map mem_map;
 
-    v3_paging_size_t paging_size; // for nested paging
-
     struct v3_mem_hooks mem_hooks;
 
     struct v3_shdw_impl_state shdw_impl;
@@ -185,12 +186,12 @@ struct v3_vm_info {
 
     struct v3_extensions extensions;
 
-#ifdef CONFIG_SYMBIOTIC
+#ifdef V3_CONFIG_SYMBIOTIC
     /* Symbiotic state */
     struct v3_sym_vm_state sym_vm_state;
 #endif
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     uint_t enable_telemetry;
     struct v3_telemetry_state telemetry;
 #endif
index c80a23c..f8028b5 100644 (file)
@@ -50,6 +50,9 @@ struct vmcs_field_encoding {
 
 
 typedef enum {
+    /* 16 bit control field */
+    VMCS_VPID                    = 0x00000000,
+    /* 16 bit guest state */
     VMCS_GUEST_ES_SELECTOR       = 0x00000800,
     VMCS_GUEST_CS_SELECTOR       = 0x00000802,
     VMCS_GUEST_SS_SELECTOR       = 0x00000804,
@@ -87,16 +90,35 @@ typedef enum {
     VMCS_VAPIC_ADDR_HIGH              = 0x00002013,
     VMCS_APIC_ACCESS_ADDR             = 0x00002014,
     VMCS_APIC_ACCESS_ADDR_HIGH        = 0x00002015,
+    VMCS_EPT_PTR                      = 0x0000201A,
+    VMCS_EPT_PTR_HIGH                 = 0x0000201B,
+    /* 64 bit read only data field */
+    VMCS_GUEST_PHYS_ADDR              = 0x00002400,
+    VMCS_GUEST_PHYS_ADDR_HIGH         = 0x00002401,
     /* 64 bit guest state fields */
     VMCS_LINK_PTR                     = 0x00002800,
     VMCS_LINK_PTR_HIGH                = 0x00002801,
-    VMCS_GUEST_DBG_CTL               = 0x00002802,
-    VMCS_GUEST_DBG_CTL_HIGH          = 0x00002803,
+    VMCS_GUEST_DBG_CTL                = 0x00002802,
+    VMCS_GUEST_DBG_CTL_HIGH           = 0x00002803,
+    VMCS_GUEST_PAT                    = 0x00002804,
+    VMCS_GUEST_PAT_HIGH               = 0x00002805,
     VMCS_GUEST_EFER                   = 0x00002806,
     VMCS_GUEST_EFER_HIGH              = 0x00002807,
     VMCS_GUEST_PERF_GLOBAL_CTRL       = 0x00002808,
     VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH  = 0x00002809,
-
+    VMCS_GUEST_PDPTE0                 = 0x0000280A,
+    VMCS_GUEST_PDPTE0_HIGH            = 0x0000280B,
+    VMCS_GUEST_PDPTE1                 = 0x0000280C,
+    VMCS_GUEST_PDPTE1_HIGH            = 0x0000280D,
+    VMCS_GUEST_PDPTE2                 = 0x0000280E,
+    VMCS_GUEST_PDPTE2_HIGH            = 0x0000280F,
+    VMCS_GUEST_PDPTE3                 = 0x00002810,
+    VMCS_GUEST_PDPTE3_HIGH            = 0x00002811,
+    /* 64 bit host state fields */
+    VMCS_HOST_PAT                     = 0x00002c00,
+    VMCS_HOST_PAT_HIGH                = 0x00002c01,
+    VMCS_HOST_EFER                    = 0x00002c02,
+    VMCS_HOST_EFER_HIGH               = 0x00002c03,
     VMCS_HOST_PERF_GLOBAL_CTRL        = 0x00002c04,
     VMCS_HOST_PERF_GLOBAL_CTRL_HIGH   = 0x00002c05,
     /* 32 bit control fields */
@@ -116,6 +138,8 @@ typedef enum {
     VMCS_ENTRY_INSTR_LEN              = 0x0000401A,
     VMCS_TPR_THRESHOLD                = 0x0000401C,
     VMCS_SEC_PROC_CTRLS               = 0x0000401e,
+    VMCS_PLE_GAP                      = 0x00004020,
+    VMCS_PLE_WINDOW                   = 0x00004022,
     /* 32 bit Read Only data fields */
     VMCS_INSTR_ERR                    = 0x00004400,
     VMCS_EXIT_REASON                  = 0x00004402,
@@ -124,7 +148,7 @@ typedef enum {
     VMCS_IDT_VECTOR_INFO              = 0x00004408,
     VMCS_IDT_VECTOR_ERR               = 0x0000440A,
     VMCS_EXIT_INSTR_LEN               = 0x0000440C,
-    VMCS_EXIT_INSTR_INFO               = 0x0000440E,
+    VMCS_EXIT_INSTR_INFO              = 0x0000440E,
     /* 32 bit Guest state fields */
     VMCS_GUEST_ES_LIMIT               = 0x00004800,
     VMCS_GUEST_CS_LIMIT               = 0x00004802,
@@ -148,6 +172,7 @@ typedef enum {
     VMCS_GUEST_ACTIVITY_STATE         = 0x00004826,
     VMCS_GUEST_SMBASE                 = 0x00004828,
     VMCS_GUEST_SYSENTER_CS            = 0x0000482A,
+    VMCS_PREEMPT_TIMER                = 0x0000482E,
     /* 32 bit host state field */
     VMCS_HOST_SYSENTER_CS             = 0x00004C00,
     /* Natural Width Control Fields */
@@ -246,6 +271,42 @@ struct vmx_exception_bitmap {
 
 
 
+struct vmx_intr_state {
+    union {
+       uint32_t value;
+       struct {
+           uint32_t block_sti    : 1;
+           uint32_t block_mov_ss : 1;
+           uint32_t block_smi    : 1;
+           uint32_t block_nmi    : 1;
+           uint32_t rsvd        : 28;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct vmx_pending_dbg_excps {
+    union {
+       uint64_t value;
+
+       struct {
+           uint32_t lo;
+           uint32_t hi;
+       } __attribute__((packed));
+
+       struct {
+           uint64_t b0       : 1;
+           uint64_t b1       : 1;
+           uint64_t b2       : 1;
+           uint64_t b3       : 1;
+           uint64_t rsvd1    : 8;
+           uint64_t bp_set   : 1;
+           uint64_t rsvd2    : 1;
+           uint64_t bp_ss    : 1;
+           uint64_t rsvd3   : 49;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
 
 /* Segment Selector Access Rights (32 bits) */
 /* INTEL Manual: 20-4 vol 3B */
@@ -273,6 +334,14 @@ struct vmcs_segment {
 };
 
 
+struct vmcs_msr_entry {
+    uint32_t index;
+    uint32_t rsvd;
+    uint32_t lo;
+    uint32_t hi;
+} __attribute__((packed));
+
+
 struct vmcs_interrupt_state {
     union {
        uint32_t val;
index 5cb1db1..337226f 100644 (file)
@@ -182,34 +182,16 @@ struct guest_info;
         })
 
 
-#ifdef CONFIG_MULTITHREAD_OS
-
-#define V3_CREATE_THREAD(fn, arg, name)        ({                      \
-       void * thread = NULL;                                                   \
-       extern struct v3_os_hooks * os_hooks;                   \
-       if ((os_hooks) && (os_hooks)->start_kernel_thread) {    \
-           thread = (os_hooks)->start_kernel_thread(fn, arg, name);    \
-       }                                                       \
-       thread;                                         \
-    })
-
-
-#define V3_THREAD_SLEEP()              \
-    do{                                                        \
-       extern struct v3_os_hooks * os_hooks;                   \
-       if ((os_hooks) && (os_hooks)->kernel_thread_sleep) {    \
-           (os_hooks)->kernel_thread_sleep();  \
-       }                                                       \
-    }while(0)
+#ifdef V3_CONFIG_MULTITHREAD_OS
 
+#define V3_CREATE_THREAD(fn, arg, name)                                        \
+    do {                                                               \
+       extern struct v3_os_hooks * os_hooks;                           \
+       if ((os_hooks) && (os_hooks)->start_kernel_thread) {            \
+           (os_hooks)->start_kernel_thread(fn, arg, name);             \
+       }                                                               \
+    }
 
-#define V3_THREAD_WAKEUP(thread)               \
-    do{                                                        \
-       extern struct v3_os_hooks * os_hooks;                   \
-       if ((os_hooks) && (os_hooks)->kernel_thread_wakeup) {   \
-           (os_hooks)->kernel_thread_wakeup(thread);   \
-       }                                                       \
-    }while(0)
 
 
 
@@ -260,7 +242,7 @@ typedef enum v3_vm_class {V3_INVALID_VM, V3_PC_VM, V3_CRAY_VM} v3_vm_class_t;
 
 
 // Maybe make this a define....
-typedef enum v3_cpu_arch {V3_INVALID_CPU, V3_SVM_CPU, V3_SVM_REV3_CPU, V3_VMX_CPU, V3_VMX_EPT_CPU} v3_cpu_arch_t;
+typedef enum v3_cpu_arch {V3_INVALID_CPU, V3_SVM_CPU, V3_SVM_REV3_CPU, V3_VMX_CPU, V3_VMX_EPT_CPU, V3_VMX_EPT_UG_CPU} v3_cpu_arch_t;
 
 
 v3_cpu_mode_t v3_get_host_cpu_mode();
@@ -270,7 +252,7 @@ void v3_yield_cond(struct guest_info * info);
 void v3_print_cond(const char * fmt, ...);
 
 
-#ifdef CONFIG_MULTITHREAD_OS
+#ifdef V3_CONFIG_MULTITHREAD_OS
 void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector);
 #endif
 
@@ -279,6 +261,7 @@ v3_cpu_arch_t v3_get_cpu_type(int cpu_id);
 
 
 int v3_vm_enter(struct guest_info * info);
+int v3_reset_vm_core(struct guest_info * core, addr_t rip);
 
 
 #endif /*!__V3VEE__ */
@@ -318,9 +301,7 @@ struct v3_os_hooks {
 
 
 
-    void * (*start_kernel_thread)(int (*fn)(void * arg), void * arg, char * thread_name); 
-    void (*kernel_thread_sleep)(void);
-    void (*kernel_thread_wakeup)(void * thread);
+    void (*start_kernel_thread)(int (*fn)(void * arg), void * arg, char * thread_name); 
     void (*interrupt_cpu)(struct v3_vm_info * vm, int logical_cpu, int vector);
     void (*call_on_cpu)(int logical_cpu, void (*fn)(void * arg), void * arg);
     void * (*start_thread_on_cpu)(int cpu_id, int (*fn)(void * arg), void * arg, char * thread_name);
index 4513c09..d4b7eda 100644 (file)
@@ -26,8 +26,7 @@
 #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
 
@@ -35,6 +34,10 @@ struct v3_barrier {
 };
 
 
+int v3_init_barrier(struct v3_barrier * barrier);
+
+int v3_activate_barrier(struct guest_info * core);
+int v3_check_barrier(struct guest_info * core);
 
 
 #endif
index 3cc1932..0b3336a 100644 (file)
 #define EFER_MSR                 0xc0000080
 
 // KCH: for system-call interposition
-#define STAR_MSR                 0xc0000081
-#define LSTAR_MSR                0xc0000082
-#define CSTAR_MSR                0xc0000083
-#define SF_MASK_MSR              0xc0000084
-#define FS_BASE_MSR              0xc0000100
-#define GS_BASE_MSR              0xc0000101
-#define KERN_GS_BASE_MSR         0xc0000102
+#define STAR_MSR                 0xc0000081 /* Legacy mode SYSCALL target */
+#define LSTAR_MSR                0xc0000082 /* Long mode SYSCALL target */
+#define CSTAR_MSR                0xc0000083 /* compat mode SYSCALL target */
+#define SF_MASK_MSR              0xc0000084 /* EFLAGS mask for syscall */
+#define FS_BASE_MSR              0xc0000100 /* 64-bit FS base */
+#define GS_BASE_MSR              0xc0000101 /* 64-bit GS base */
+#define KERN_GS_BASE_MSR         0xc0000102 /* swapGS GS shadow */
+
+/* Intel specific */
+#define IA32_SYSENTER_CS_MSR     0x00000174
+#define IA32_SYSENTER_ESP_MSR    0x00000175
+#define IA32_SYSENTER_EIP_MSR    0x00000176
 
 struct cr0_real {
     uint_t pe    : 1;
@@ -231,6 +236,9 @@ int v3_handle_lstar_read(struct guest_info * core, uint_t msr, struct v3_msr * d
 int v3_handle_cstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
 int v3_handle_cstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data);
 
+int v3_handle_seeip_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
+int v3_handle_seeip_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data);
+
 int v3_handle_vm_cr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
 int v3_handle_vm_cr_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data);
 
index 82253be..7f33fde 100644 (file)
@@ -48,30 +48,35 @@ struct x86_operand {
 } __attribute__((packed));
 
 struct x86_prefixes {
-    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;
+    union {
+       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;
     
-    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
-
+           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
+       } __attribute__((packed));
+    } __attribute__((packed));
 } __attribute__((packed));
 
 
index c9999bd..87f62fc 100644 (file)
@@ -102,14 +102,14 @@ int V3_init_devices();
 int V3_deinit_devices();
 
 
-#ifdef CONFIG_KEYED_STREAMS
+#ifdef V3_CONFIG_KEYED_STREAMS
 #include <interfaces/vmm_keyed_stream.h>
 #endif 
 
 struct v3_device_ops {
     int (*free)(void * private_data);
 
-#ifdef CONFIG_KEYED_STREAMS
+#ifdef V3_CONFIG_KEYED_STREAMS
     int (*checkpoint)(struct vm_device *dev, v3_keyed_stream_t stream);
     int (*restore)(struct vm_device *dev, v3_keyed_stream_t stream);
 #endif
index 2b9319b..1fd00ac 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef __ETHERNET_H__
 #define __ETHERNET_H__
 
+#include <palacios/vmm.h>
+
 #define ETHERNET_HEADER_LEN 14
 #define ETHERNET_MTU   1500
 #define ETHERNET_PACKET_LEN (ETHERNET_HEADER_LEN + ETHERNET_MTU)
 
 #define MAX_PACKET_LEN (ETHERNET_HEADER_LEN + MAX_MTU)
 
+#ifdef V3_CONFIG_VNET
+extern int net_debug;
+#endif
 
-extern int v3_net_debug;
+struct nic_statistics {
+    uint64_t tx_pkts;
+    uint64_t tx_bytes;
+    uint64_t tx_dropped;
+
+    uint64_t rx_pkts;
+    uint64_t rx_bytes;
+    uint64_t rx_dropped;
+
+    uint32_t tx_interrupts;
+    uint32_t rx_interrupts;
+};
 
 #ifdef __V3VEE__
 
@@ -40,7 +56,7 @@ extern int v3_net_debug;
 
 #define V3_Net_Print(level, fmt, args...)                                      \
     do {                                                               \
-       if(level <= v3_net_debug) {   \
+       if(level <= net_debug) {   \
            extern struct v3_os_hooks * os_hooks;                       \
            if ((os_hooks) && (os_hooks)->print) {                      \
                (os_hooks)->print((fmt), ##args);                       \
@@ -48,19 +64,7 @@ extern int v3_net_debug;
        }                                                       \
     } while (0)        
 
-struct nic_statistics {
-    uint64_t tx_pkts;
-    uint64_t tx_bytes;
-    uint64_t tx_dropped;
-       
-    uint64_t rx_pkts;
-    uint64_t rx_bytes;
-    uint64_t rx_dropped;
 
-    uint32_t tx_interrupts;
-    uint32_t rx_interrupts;
-};
-    
 static inline int is_multicast_ethaddr(const uint8_t * addr)
 {
     V3_ASSERT(ETH_ALEN == 6);
index 7c48244..60ff80a 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <palacios/vmm_types.h>
 
-
 /* .... Giant fucking switch tables */
 
 
@@ -263,6 +262,8 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr,
                case LONG:
                    if (instr->prefixes.rex_op_size) {
                        return 8;
+                   } else {
+                       return 4;
                    }
                case PROTECTED:
                case PROTECTED_PAE:
@@ -336,6 +337,7 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr,
            return -1;
        
     }
+
     return 0;
 }
 
@@ -452,7 +454,7 @@ static inline int decode_cr(struct guest_info * core,
 
     struct v3_ctrl_regs * crs = &(core->ctrl_regs);
 
-    PrintDebug("\t Ctrl regs %d\n", reg_code);
+//    PrintDebug("\t Ctrl regs %d\n", reg_code);
 
     switch (reg_code) {
        case 0:
diff --git a/palacios/include/palacios/vmm_mptable.h b/palacios/include/palacios/vmm_mptable.h
deleted file mode 100644 (file)
index eb6a630..0000000
+++ /dev/null
@@ -1,39 +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) 2010, Peter Dinda <pdinda@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Peter Dinda <pdinda@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_MPTABLE_H__
-#define __VMM_MPTABLE_H__
-
-/*
-  This module is responsible for injecting an appropriate description of
-  the multicore guest into the the guest's memory in the form
-  of an Intel Multiprocessor Specification-compatible MP table. 
-
-  The guest BIOS must cooperate in having preallocated space for the table
-*/
-
-#include <palacios/vm_guest.h>
-#include <palacios/vmm_mem.h>
-#include <palacios/vmm_types.h>
-
-// Note that this must be run *after* the rombios has been mapped in
-// AND the rombios needs to be COPIED in so that we can edit it
-int v3_inject_mptable(struct v3_vm_info *vm);
-
-#endif
index a4f8974..3026e67 100644 (file)
@@ -581,7 +581,7 @@ const uchar_t * v3_page_type_to_str(page_type_t type);
 
 
 void PrintPTEntry(struct guest_info * info, page_type_t type, addr_t vaddr, void * entry);
-void PrintHostPageTables(struct guest_info * info,  addr_t cr3);
+void PrintHostPageTables(struct guest_info * info,  v3_cpu_mode_t cpu_mode, addr_t cr3);
 void PrintGuestPageTables(struct guest_info * info, addr_t cr3);
 void PrintHostPageTree(struct guest_info * info, addr_t virtual_addr, addr_t cr3);
 void PrintGuestPageTree(struct guest_info * info, addr_t virtual_addr, addr_t cr3);
index b619a04..22b0651 100644 (file)
@@ -63,7 +63,7 @@ struct v3_shdw_pg_state {
 
     void * local_impl_data;
 
-#ifdef CONFIG_SHADOW_PAGING_TELEMETRY
+#ifdef V3_CONFIG_SHADOW_PAGING_TELEMETRY
     uint_t guest_faults;
 #endif
 
index 0c581fd..676f901 100644 (file)
 
 #include <palacios/vmm_symspy.h>
 
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
 #include <palacios/vmm_symcall.h>
 #endif
 
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
 #include <palacios/vmm_symmod.h>
 #endif
 
@@ -40,7 +40,7 @@
 struct v3_sym_vm_state {
     struct v3_symspy_global_state symspy_state;
 
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
     struct v3_symmod_state symmod_state;
 #endif
 };
@@ -49,7 +49,7 @@ struct v3_sym_vm_state {
 struct v3_sym_core_state {
     struct v3_symspy_local_state symspy_state;
     
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
     struct v3_symcall_state symcall_state;
 #endif
 
index 8fab683..0677e2d 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifdef __V3VEE__
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
 
 #include <palacios/vmm_rbtree.h>
 #include <palacios/vmm_list.h>
index c9248b8..329fce6 100644 (file)
@@ -92,7 +92,7 @@ static inline uint64_t v3_get_host_time(struct vm_time *t) {
 
 // Returns *monotonic* guest time.
 static inline uint64_t v3_get_guest_time(struct vm_time *t) {
-#ifdef CONFIG_TIME_HIDE_VM_COST
+#ifdef V3_CONFIG_TIME_HIDE_VM_COST
     V3_ASSERT(t->exit_time);
     return t->exit_time + t->guest_host_offset;
 #else
index 4ef72d4..1a17997 100644 (file)
@@ -30,8 +30,6 @@ 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 {CORE_RUNNING, CORE_STOPPED} v3_core_operating_mode_t;
 
-typedef enum {PAGING_4KB, PAGING_2MB} v3_paging_size_t;
-
 typedef enum {REAL, /*UNREAL,*/ PROTECTED, PROTECTED_PAE, LONG, LONG_32_COMPAT, LONG_16_COMPAT} v3_cpu_mode_t;
 typedef enum {PHYSICAL_MEM, VIRTUAL_MEM} v3_mem_mode_t;
 
index 7a0a039..acadf22 100644 (file)
@@ -7,12 +7,10 @@
  * and the University of New Mexico.  You can find out more at 
  * http://www.v3vee.org
  *
- * Copyright (c) 2008, Peter Dinda <pdinda@northwestern.edu> 
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <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: Peter Dinda <pdinda@northwestern.edu>
  * Author: Jack Lange <jarusl@cs.northwestern.edu>
  *
  * This is free software.  You are permitted to use,
@@ -37,9 +35,6 @@
 #define VMM_ERROR          3
 
 
-
-
-
 struct vmx_pin_ctrls {
     union {
         uint32_t value;
@@ -101,7 +96,8 @@ struct vmx_sec_proc_ctrls {
            uint_t enable_rdtscp   : 1;
            uint_t virt_x2apic     : 1;
            uint_t enable_vpid     : 1;
-           uint_t unrstrct_guest  : 1;
+           uint_t wbinvd_exit     : 1;
+           uint_t unrstrct_guest  : 1; /* un restricted guest (CAN RUN IN REAL MODE) */
            uint_t rsvd1           : 2;
            uint_t pause_loop_exit : 1;
            uint_t rsvd2           : 21;
@@ -183,7 +179,7 @@ struct tss_descriptor {
     uint_t      zero4       : 5;
     uint_t      rsvd2       : 19;
 #endif
-}__attribute__((packed));
+} __attribute__((packed));
 
 struct vmcs_host_state {
     struct v3_segment  gdtr;
@@ -193,16 +189,14 @@ struct vmcs_host_state {
 
 
 
-
-
 struct vmx_data {
     vmx_state_t state;
     vmxassist_state_t assist_state;
     struct vmcs_host_state host_state;
 
-    addr_t vmcs_ptr_phys;
 
-    uint8_t ia32e_avail;
+
+    addr_t vmcs_ptr_phys;
 
     v3_reg_t guest_cr4; /// corresponds to the CR4 Read shadow
 
@@ -213,6 +207,10 @@ struct vmx_data {
     struct vmx_sec_proc_ctrls sec_proc_ctrls;
     struct vmx_exit_ctrls exit_ctrls;
     struct vmx_entry_ctrls entry_ctrls;
+
+    struct vmx_exception_bitmap excp_bmap;
+
+    void * msr_area;
 };
 
 int v3_is_vmx_capable();
@@ -221,6 +219,7 @@ void v3_init_vmx_cpu(int cpu_id);
 void v3_deinit_vmx_cpu(int cpu_id);
 
 int v3_start_vmx_guest(struct guest_info* info);
+int v3_reset_vmx_vm_core(struct guest_info * core, addr_t rip);
 int v3_vmx_enter(struct guest_info * info);
 
 int v3_init_vmx_vmcs(struct guest_info * info, v3_vm_class_t vm_class);
index d9fc31d..5a38743 100644 (file)
@@ -1,26 +1,20 @@
-/*
- * vmx_assist.h: Context definitions for the VMXASSIST world switch.
+/* 
+ * 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.  
  *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
+ * 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
  *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
+ * Copyright (c) 2011, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
  *
- * Leendert van Doorn, leendert@watson.ibm.com
- * Copyright (c) 2005, International Business Machines Corporation.
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
 #ifndef _VMX_ASSIST_H_
 #ifdef __V3VEE__
 
 #include <palacios/vm_guest.h>
+#include <palacios/vmx.h>
 
-#define VMXASSIST_BASE         0xD0000
-#define VMXASSIST_MAGIC        0x17101966
 
+#define VMXASSIST_GDT     0x10000
+#define VMXASSIST_TSS     0x40000
+#define VMXASSIST_START   0xd0000
+#define VMXASSIST_1to1_PT 0xde000 // We'll shove this at the end, and pray to god VMXASSIST doesn't mess with it
 
-struct vmx_assist_header {
-    uint64_t rsvd; // 8 bytes of nothing
-    uint32_t magic;
-    uint32_t new_ctx_gpa;
-    uint32_t old_ctx_gpa;
-} __attribute__((packed));
-
-
-union vmcs_arbytes {
-    struct arbyte_fields {
-        unsigned int seg_type : 4,
-            s         : 1,
-            dpl       : 2,
-            p         : 1,
-            reserved0 : 4,
-            avl       : 1,
-            reserved1 : 1,
-            default_ops_size: 1,
-            g         : 1,
-            null_bit  : 1,
-            reserved2 : 15;
-    } __attribute__((packed)) fields;
-    unsigned int bytes;
-} __attribute__((packed));
-
-struct vmx_assist_segment {
-    uint32_t sel;
-    uint32_t limit;
-    uint32_t base;
-    union vmcs_arbytes arbytes;
-} __attribute__((packed));
-
-/*
- * World switch state
- */
-struct vmx_assist_context {
-    uint32_t  eip;        /* execution pointer */
-    uint32_t  esp;        /* stack pointer */
-    uint32_t  eflags;     /* flags register */
-    uint32_t  cr0;
-    uint32_t  cr3;        /* page table directory */
-    uint32_t  cr4;
-
-    uint32_t  idtr_limit; /* idt */
-    uint32_t  idtr_base;
-
-    uint32_t  gdtr_limit; /* gdt */
-    uint32_t  gdtr_base;
-
-    struct vmx_assist_segment cs;
-    struct vmx_assist_segment ds;
-    struct vmx_assist_segment es;
-    struct vmx_assist_segment ss;
-    struct vmx_assist_segment fs;
-    struct vmx_assist_segment gs;
-    struct vmx_assist_segment tr;
-    struct vmx_assist_segment ldtr;
-
-
-    unsigned char rm_irqbase[2];
-} __attribute__((packed));
-
-typedef struct vmx_assist_context vmx_assist_context_t;
 
 int v3_vmxassist_ctx_switch(struct guest_info * info);
-
+int v3_vmxassist_init(struct guest_info * core, struct vmx_data * vmx_state);
 
 #endif
 
 #endif /* _VMX_ASSIST_H_ */
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
index 55cb363..a9dac1c 100644 (file)
 
 #ifdef __V3VEE__
 
+#include <palacios/vmx_hw_info.h>
+
 /* The actual format of these data structures is specified as being machine 
    dependent. Thus the lengths of the base address fields are defined as variable. 
    To be safe we assume the maximum(?) size fields 
+
+   From Intel Manual...
+   N is the physical-address width supported by the logical processor. Software can determine a processor's
+   physical-address width by executing CPUID with 80000008H in EAX. The physical address
+   width is returned in bits 7:0 of EAX.
 */
 
 
+struct ept_exit_qual {
+    union {
+       uint64_t value;
+       struct {
+           uint64_t rd_op       : 1;
+           uint64_t wr_op       : 1;
+           uint64_t ifetch      : 1;
+           uint64_t present     : 1;
+           uint64_t write       : 1;
+           uint64_t exec        : 1;
+           uint64_t rsvd1       : 1;
+           uint64_t addr_valid  : 1;
+           uint64_t addr_type   : 1;
+           uint64_t rsvd2       : 1;
+           uint64_t nmi_unblock : 1;
+           uint64_t rsvd3      : 53;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
 typedef struct vmx_eptp {
-    uint8_t psmt            : 3;
-    uint8_t pwl1            : 3;
-    uint8_t rsvd1           : 6;
-    uint64_t pml_base_addr  : 39;
+    uint64_t psmt            : 3; /* (0=UC, 6=WB) */
+    uint64_t pwl1            : 3; /* 1 less than EPT page-walk length (?)*/
+    uint64_t rsvd1           : 6;
+    uint64_t pml_base_addr  : 39; 
     uint16_t rsvd2          : 13;
 } __attribute__((packed)) vmx_eptp_t;
 
 
-typedef struct vmx_pml4 {
-    uint8_t read            : 1;
-    uint8_t write           : 1;
-    uint8_t exec            : 1;
-    uint8_t rsvd1           : 5;
-    uint8_t ignore1         : 4;
+typedef struct ept_pml4 {
+    uint64_t read            : 1;
+    uint64_t write           : 1;
+    uint64_t exec            : 1;
+    uint64_t rsvd1           : 5;
+    uint64_t ignore1         : 4;
     uint64_t pdp_base_addr  : 39;
-    uint8_t rsvd2           : 1;
-    uint32_t ignore2        : 12;
-} __attribute__((packed)) vmx_pml4_t;
-
-
-typedef struct vmx_pdp_1GB {
-    uint8_t read            : 1;
-    uint8_t write           : 1;
-    uint8_t exec            : 1;
-    uint8_t mt              : 3;
-    uint8_t ipat            : 1;
-    uint8_t large_page      : 1;
-    uint8_t ignore1         : 4;
-    uint32_t rsvd1          : 18;
-    uint32_t page_base_addr : 21;
-    uint8_t rsvd2           : 1;
-    uint32_t ignore2        : 12;
-} __attribute__((packed)) vmx_pdp_1GB_t;
-
-typedef struct vmx_pdp {
-    uint8_t read            : 1;
-    uint8_t write           : 1;
-    uint8_t exec            : 1;
-    uint8_t rsvd1           : 4;
-    uint8_t large_page      : 1;
-    uint8_t ignore1         : 4;
-    uint32_t page_base_addr : 39;
-    uint8_t rsvd2           : 1;
-    uint32_t ignore2        : 12;
-} __attribute__((packed)) vmx_pdp_t;
-
-
-typedef struct vmx_pde_2MB {
-    uint8_t read            : 1;
-    uint8_t write           : 1;
-    uint8_t exec            : 1;
-    uint8_t mt              : 3;
-    uint8_t ipat            : 1;
-    uint8_t large_page      : 1;
-    uint8_t ignore1         : 4;
-    uint32_t rsvd1          : 9;
-    uint32_t page_base_addr : 30;
-    uint8_t rsvd2           : 1;
-    uint32_t ignore2        : 12;
-} __attribute__((packed)) vmx_pde_2MB_t;
-
-
-typedef struct vmx_pde {
-    uint8_t read            : 1;
-    uint8_t write           : 1;
-    uint8_t exec            : 1;
-    uint8_t rsvd1           : 4;
-    uint8_t large_page      : 1;
-    uint8_t ignore1         : 4;
-    uint32_t page_base_addr : 39;
-    uint8_t rsvd2           : 1;
-    uint32_t ignore2        : 12;
-} __attribute__((packed)) vmx_pde_t;
-
-
-
-typedef struct vmx_pte {
-    uint8_t read            : 1;
-    uint8_t write           : 1;
-    uint8_t exec            : 1;
-    uint8_t mt              : 3;
-    uint8_t ipat            : 1;
-    uint8_t ignore1         : 5;
-    uint32_t page_base_addr : 39;
-    uint8_t rsvd2           : 1;
-    uint32_t ignore2        : 12;
-} __attribute__((packed)) vmx_pte_t;
+    uint64_t rsvd2           : 1;
+    uint64_t ignore2        : 12;
+} __attribute__((packed)) ept_pml4_t;
+
+
+typedef struct ept_pdp_1GB {
+    uint64_t read            : 1;
+    uint64_t write           : 1;
+    uint64_t exec            : 1;
+    uint64_t mt              : 3;
+    uint64_t ipat            : 1;
+    uint64_t large_page      : 1;
+    uint64_t ignore1         : 4;
+    uint64_t rsvd1          : 18;
+    uint64_t page_base_addr : 21;
+    uint64_t rsvd2           : 1;
+    uint64_t ignore2        : 12;
+} __attribute__((packed)) ept_pdp_1GB_t;
+
+typedef struct ept_pdp {
+    uint64_t read            : 1;
+    uint64_t write           : 1;
+    uint64_t exec            : 1;
+    uint64_t rsvd1           : 4;
+    uint64_t large_page      : 1;
+    uint64_t ignore1         : 4;
+    uint64_t pd_base_addr   : 39;
+    uint64_t rsvd2           : 1;
+    uint64_t ignore2        : 12;
+} __attribute__((packed)) ept_pdp_t;
+
+
+typedef struct ept_pde_2MB {
+    uint64_t read            : 1;
+    uint64_t write           : 1;
+    uint64_t exec            : 1;
+    uint64_t mt              : 3;
+    uint64_t ipat            : 1;
+    uint64_t large_page      : 1;
+    uint64_t ignore1         : 4;
+    uint64_t rsvd1          : 9;
+    uint64_t page_base_addr : 30;
+    uint64_t rsvd2           : 1;
+    uint64_t ignore2        : 12;
+} __attribute__((packed)) ept_pde_2MB_t;
+
+
+typedef struct ept_pde {
+    uint64_t read            : 1;
+    uint64_t write           : 1;
+    uint64_t exec            : 1;
+    uint64_t rsvd1           : 4;
+    uint64_t large_page      : 1;
+    uint64_t ignore1         : 4;
+    uint64_t pt_base_addr   : 39;
+    uint64_t rsvd2           : 1;
+    uint64_t ignore2        : 12;
+} __attribute__((packed)) ept_pde_t;
+
+
+
+typedef struct ept_pte {
+    uint64_t read            : 1;
+    uint64_t write           : 1;
+    uint64_t exec            : 1;
+    uint64_t mt              : 3;
+    uint64_t ipat            : 1;
+    uint64_t ignore1         : 5;
+    uint64_t page_base_addr  : 39;
+    uint64_t rsvd2           : 1;
+    uint64_t ignore2         : 12;
+} __attribute__((packed)) ept_pte_t;
+
+int v3_init_ept(struct guest_info * core, struct vmx_hw_info * hw_info);
+int v3_handle_ept_fault(struct guest_info * core, addr_t fault_addr, struct ept_exit_qual * ept_qual);
+
 
 #endif 
 
index 2845e21..20561f8 100644 (file)
@@ -61,12 +61,12 @@ typedef enum {
     VMEXIT_IO_INSTR                         = 30,
     VMEXIT_RDMSR                            = 31,
     VMEXIT_WRMSR                            = 32,
-    VMEXIT_ENTRY_FAIL_INVALID_GUEST_STATE   = 33,
-    VMEXIT_ENTRY_FAIL_MSR_LOAD              = 34,
+    VMEXIT_INVALID_GUEST_STATE              = 33,
+    VMEXIT_INVALID_MSR_LOAD                 = 34,
     VMEXIT_MWAIT                            = 36,
     VMEXIT_MONITOR                          = 39,
     VMEXIT_PAUSE                            = 40,
-    VMEXIT_ENTRY_FAILURE_MACHINE_CHECK      = 41,
+    VMEXIT_INVALID_MACHINE_CHECK            = 41,
     VMEXIT_TPR_BELOW_THRESHOLD              = 43,
     VMEXIT_APIC                             = 44,
     VMEXIT_GDTR_IDTR                        = 46,
@@ -153,7 +153,7 @@ struct VMExitDBGQual {
 } __attribute__((packed));
 
 
-struct VMExitTSQual {
+ struct VMExitTSQual {
     uint32_t selector   : 16; // selector of destination TSS 
     uint32_t rsvd       : 14; // reserved to 0
     uint32_t src        : 2; // (0: CALL ; 1: IRET ; 2: JMP ; 3: Task gate in IDT)
@@ -200,6 +200,20 @@ struct vmx_exit_idt_vec_info {
 
 
 
+struct vmx_basic_exit_info {
+    union {
+       uint32_t value;
+       struct {
+           uint16_t reason;
+           uint16_t rsvd1         :12;
+           uint8_t  mtf_pending   : 1;
+           uint8_t  vmx_root_op   : 1;
+           uint8_t  rsvd2         : 1;
+           uint8_t  entry_error   : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
 
 struct vmx_exit_info {
     uint32_t instr_len;
@@ -212,6 +226,10 @@ struct vmx_exit_info {
     uint32_t int_err;
 
     addr_t guest_linear_addr;
+
+    /* EPT INFO */
+    addr_t ept_fault_addr;
+
 };
 
 
index e130545..c11dcb1 100644 (file)
@@ -53,15 +53,15 @@ struct vmx_basic_msr {
        } __attribute__((packed));
 
        struct {    uint32_t revision;
-           uint32_t regionSize   : 13;
-           uint8_t rsvd1         : 3; /* Always 0 */
-           uint8_t physWidth     : 1; /* VMCS address field widths 
+           uint64_t regionSize   : 13;
+           uint64_t rsvd1         : 3; /* Always 0 */
+           uint64_t physWidth     : 1; /* VMCS address field widths 
                                          (1=32bits, 0=natural width) */
-           uint8_t smm           : 1;
-           uint8_t memType       : 4; /* 0 = UC, 6 = WriteBack */
-           uint8_t io_str_info   : 1;
-           uint8_t def1_maybe_0  : 1; /* 1="Any VMX ctrls that default to 1 may be cleared to 0" */
-           uint32_t rsvd2        : 8; /* Always 0 */
+           uint64_t smm           : 1;
+           uint64_t memType       : 4; /* 0 = UC, 6 = WriteBack */
+           uint64_t io_str_info   : 1;
+           uint64_t def1_maybe_0  : 1; /* 1="Any VMX ctrls that default to 1 may be cleared to 0" */
+           uint64_t rsvd2        : 8; /* Always 0 */
        }  __attribute__((packed));
     }  __attribute__((packed));
 }  __attribute__((packed));
@@ -75,17 +75,17 @@ struct vmx_misc_msr {
        } __attribute__((packed));
 
        struct {
-           uint8_t tsc_multiple       : 5; /* Bit position in TSC field that drives vmx timer step */
-           uint8_t exits_store_LMA    : 1;
-           uint8_t can_halt           : 1;
-           uint8_t can_shtdown        : 1;
-           uint8_t can_wait_for_sipi  : 1;
-           uint8_t rsvd1              : 7;
-           uint16_t num_cr3_targets   : 9;
-           uint8_t max_msr_cache_size : 3; /* (512 * (max_msr_cache_size + 1)) == max msr load/store list size */
-           uint8_t SMM_ctrl_avail     : 1;
-           uint8_t rsvd2              : 3; 
-           uint32_t MSEG_rev_id;
+           uint64_t tsc_multiple       : 5; /* Bit position in TSC field that drives vmx timer step */
+           uint64_t exits_store_LMA    : 1;
+           uint64_t can_halt           : 1;
+           uint64_t can_shtdown        : 1;
+           uint64_t can_wait_for_sipi  : 1;
+           uint64_t rsvd1              : 7;
+           uint64_t num_cr3_targets    : 9;
+           uint64_t max_msr_cache_size : 3; /* (512 * (max_msr_cache_size + 1)) == max msr load/store list size */
+           uint64_t SMM_ctrl_avail     : 1;
+           uint64_t rsvd2              : 3; 
+           uint64_t MSEG_rev_id;
        }  __attribute__((packed));
     }  __attribute__((packed));
 } __attribute__((packed));
@@ -99,29 +99,29 @@ struct vmx_ept_msr {
        } __attribute__((packed));
 
        struct {
-           uint8_t exec_only_ok             : 1;
-           uint8_t rsvd1                    : 5;
-           uint8_t pg_walk_len4             : 1; /* support for a page walk of length 4 */
-           uint8_t rsvd2                    : 1;
-           uint8_t ept_uc_ok                : 1; /* EPT page tables can be uncacheable */
-           uint8_t rsvd3                    : 5;
-           uint8_t ept_wb_ok                : 1; /* EPT page tables can be writeback */
-           uint8_t rsvd4                    : 1;
-           uint8_t ept_2MB_ok               : 1; /* 2MB EPT pages supported */
-           uint8_t ept_1GB_ok               : 1; /* 1GB EPT pages supported */
-           uint8_t rsvd5                    : 2;
-           uint8_t INVEPT_avail             : 1; /* INVEPT instruction is available */
-           uint8_t rsvd6                    : 4;
-           uint8_t INVEPT_single_ctx_avail  : 1;
-           uint8_t INVEPT_all_ctx_avail     : 1;
-           uint8_t rsvd7                    : 5;
-           uint8_t INVVPID_avail            : 1;
-           uint8_t rsvd8                    : 7;
-           uint8_t INVVPID_1addr_avail      : 1;
-           uint8_t INVVPID_single_ctx_avail : 1;
-           uint8_t INVVPID_all_ctx_avail    : 1;
-           uint8_t INVVPID_single_ctx_w_glbls_avail : 1;
-           uint32_t rsvd9                   : 20;
+           uint64_t exec_only_ok             : 1;
+           uint64_t rsvd1                    : 5;
+           uint64_t pg_walk_len4             : 1; /* support for a page walk of length 4 */
+           uint64_t rsvd2                    : 1;
+           uint64_t ept_uc_ok                : 1; /* EPT page tables can be uncacheable */
+           uint64_t rsvd3                    : 5;
+           uint64_t ept_wb_ok                : 1; /* EPT page tables can be writeback */
+           uint64_t rsvd4                    : 1;
+           uint64_t ept_2MB_ok               : 1; /* 2MB EPT pages supported */
+           uint64_t ept_1GB_ok               : 1; /* 1GB EPT pages supported */
+           uint64_t rsvd5                    : 2;
+           uint64_t INVEPT_avail             : 1; /* INVEPT instruction is available */
+           uint64_t rsvd6                    : 4;
+           uint64_t INVEPT_single_ctx_avail  : 1;
+           uint64_t INVEPT_all_ctx_avail     : 1;
+           uint64_t rsvd7                    : 5;
+           uint64_t INVVPID_avail            : 1;
+           uint64_t rsvd8                    : 7;
+           uint64_t INVVPID_1addr_avail      : 1;
+           uint64_t INVVPID_single_ctx_avail : 1;
+           uint64_t INVVPID_all_ctx_avail    : 1;
+           uint64_t INVVPID_single_ctx_w_glbls_avail : 1;
+           uint64_t rsvd9                   : 20;
        }  __attribute__((packed));
     }  __attribute__((packed));
 }__attribute__((packed));
@@ -152,15 +152,19 @@ struct vmx_hw_info {
     struct vmx_ctrl_field proc_ctrls;
     struct vmx_ctrl_field exit_ctrls;
     struct vmx_ctrl_field entry_ctrls;
-    struct vmx_ctrl_field proc_ctrls_2;
+    struct vmx_ctrl_field sec_proc_ctrls;
 
     struct vmx_cr_field cr0;
     struct vmx_cr_field cr4;
+
 };
 
 
+
+
 int v3_init_vmx_hw(struct vmx_hw_info * hw_info);
 
+uint32_t v3_vmx_get_ctrl_features(struct vmx_ctrl_field * fields);
 
 
 
index ce6a440..fd63406 100644 (file)
@@ -97,17 +97,17 @@ static inline int vmcs_load(addr_t vmcs_ptr) {
     return VMX_SUCCESS;
 }
 
-static inline int vmcs_store(addr_t vmcs_ptr) {
-    uint64_t vmcs_ptr_64 = (uint64_t)vmcs_ptr;
+static inline uint64_t vmcs_store() {
+    uint64_t vmcs_ptr = 0;
 
     __asm__ __volatile__ (
                VMPTRST_OPCODE
                EAX_07_MODRM
                :
-               : "a"(&vmcs_ptr_64)
+               : "a"(&vmcs_ptr)
                : "memory");
 
-    return VMX_SUCCESS;
+    return vmcs_ptr;
 }
 
 static inline int vmcs_read(vmcs_field_t vmcs_field, void * dst) {
similarity index 86%
rename from palacios/include/palacios/vmm_vnet.h
rename to palacios/include/vnet/vnet.h
index 0f8c793..949f0b2 100644 (file)
@@ -1,3 +1,4 @@
+
 /* 
  * This file is part of the Palacios Virtual Machine Monitor developed
  * by the V3VEE Project with funding from the United States National 
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
-#ifndef __VNET_CORE_H__
-#define __VNET_CORE_H__
+#ifndef __VNET_H__
+#define __VNET_H__
 
-#include <palacios/vmm.h>
 #include <palacios/vmm_ethernet.h>
+#include <vnet/vnet_base.h>
+#include <vnet/vnet_host.h>
+#include <vnet/vnet_vmm.h>
 
 #define MAC_NOSET      0
 #define MAC_ANY        11
@@ -38,8 +41,6 @@
 
 #define VNET_HASH_SIZE         17
 
-extern int v3_vnet_debug;
-
 struct v3_vnet_route {
     uint8_t src_mac[ETH_ALEN];
     uint8_t dst_mac[ETH_ALEN];
@@ -87,20 +88,25 @@ struct vnet_stat{
 
 struct v3_vnet_bridge_ops {
     int (*input)(struct v3_vm_info * vm, 
-               struct v3_vnet_pkt * pkt,
-               void * private_data);
+                struct v3_vnet_pkt * pkt,
+                void * private_data);
     void (*poll)(struct v3_vm_info * vm,  
-               void * private_data);
+                void * private_data);
 };
 
 #define HOST_LNX_BRIDGE 1
 #define CTL_VM_BRIDGE  2
 
 int v3_vnet_add_bridge(struct v3_vm_info * vm,
-               struct v3_vnet_bridge_ops * ops,
-               uint8_t type,
-               void * priv_data);
+                      struct v3_vnet_bridge_ops * ops,
+                      uint8_t type,
+                      void * priv_data);
+
+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_find_dev(uint8_t  * mac);
 int v3_vnet_stat(struct vnet_stat * stats);
@@ -109,8 +115,8 @@ int v3_vnet_stat(struct vnet_stat * stats);
 
 struct v3_vnet_dev_ops {
     int (*input)(struct v3_vm_info * vm, 
-               struct v3_vnet_pkt * pkt, 
-               void * dev_data);
+                struct v3_vnet_pkt * pkt, 
+                void * dev_data);
 };
 
 int v3_init_vnet(void);        
similarity index 52%
copy from palacios/include/palacios/vmm_instrument.h
copy to palacios/include/vnet/vnet_base.h
index 63b2be2..fd2e5e5 100644 (file)
@@ -1,4 +1,5 @@
-/*
+
+/* 
  * 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.  
@@ -7,33 +8,30 @@
  * 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> 
+ * Copyright (c) 2011, Lei Xia <lxia@northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
  * All rights reserved.
  *
- * Author: Chang Bae <c.s.bae@u.northwestern.edu>
+ * Author: Lei Xia <lxia@northwestern.edu>
  *
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
-#ifndef __VMM_INSTRUMENT_H__
-#define __VMM_INSTRUMENT_H__
-
-#ifdef __V3VEE__
-
-#ifdef CONFIG_INSTRUMENT_VMM 
-
-#include <palacios/vmm_types.h>
-#include <palacios/vmm_ringbuffer.h>
+#ifndef __VNET_BASE_H__
+#define __VNET_BASE_H__
 
+#ifndef __V3VEE__
 
-void v3_init_instrumentation() __attribute__((__no_instrument_function__));
+typedef unsigned char uchar_t;
+typedef unsigned int uint_t;
+typedef unsigned long long ullong_t;
+typedef unsigned long ulong_t;
+typedef ulong_t addr_t;
 
-#endif // INSTRUMENT_VMM
+#endif
 
-#endif // __V3VEE__
 
-#endif // 
+#endif
 
 
diff --git a/palacios/include/vnet/vnet_hashtable.h b/palacios/include/vnet/vnet_hashtable.h
new file mode 100644 (file)
index 0000000..c0a46b8
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+  Copyright (c) 2002, 2004, Christopher Clark
+  All rights reserved.
+  
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+  
+  * Neither the name of the original author; nor the names of any contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+  
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/* Modifications made by Lei Xia <lxia@northwestern.edu> */
+
+
+#ifndef __VNET_HASHTABLE_H__
+#define __VNET_HASHTABLE_H__
+#include <vnet/vnet_base.h>
+
+struct hashtable;
+
+/* Example of use:
+ *
+ *      struct hashtable  *h;
+ *      struct some_key   *k;
+ *      struct some_value *v;
+ *
+ *      static uint_t         hash_from_key_fn( void *k );
+ *      static int                  keys_equal_fn ( void *key1, void *key2 );
+ *
+ *      h = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ *      k = (struct some_key *)     malloc(sizeof(struct some_key));
+ *      v = (struct some_value *)   malloc(sizeof(struct some_value));
+ *
+ *      (initialise k and v to suitable values)
+ * 
+ *      if (! hashtable_insert(h,k,v) )
+ *      {     exit(-1);               }
+ *
+ *      if (NULL == (found = hashtable_search(h,k) ))
+ *      {    printf("not found!");                  }
+ *
+ *      if (NULL == (found = hashtable_remove(h,k) ))
+ *      {    printf("Not found\n");                 }
+ *
+ */
+
+/* Macros may be used to define type-safe(r) hashtable access functions, with
+ * methods specialized to take known key and value types as parameters.
+ * 
+ * Example:
+ *
+ * Insert this at the start of your file:
+ *
+ * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value);
+ * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value);
+ *
+ * This defines the functions 'insert_some', 'search_some' and 'remove_some'.
+ * These operate just like hashtable_insert etc., with the same parameters,
+ * but their function signatures have 'struct some_key *' rather than
+ * 'void *', and hence can generate compile time errors if your program is
+ * supplying incorrect data as a key (and similarly for value).
+ *
+ * Note that the hash and key equality functions passed to create_hashtable
+ * still take 'void *' parameters instead of 'some key *'. This shouldn't be
+ * a difficult issue as they're only defined and passed once, and the other
+ * functions will ensure that only valid keys are supplied to them.
+ *
+ * The cost for this checking is increased code size and runtime overhead
+ * - if performance is important, it may be worth switching back to the
+ * unsafe methods once your program has been debugged with the safe methods.
+ * This just requires switching to some simple alternative defines - eg:
+ * #define insert_some hashtable_insert
+ *
+ */
+
+/* These cannot be inlined because they are referenced as fn ptrs */
+unsigned long vnet_hash_long(unsigned long val, unsigned int bits);
+unsigned long vnet_hash_buffer(unsigned char * msg, unsigned int length);
+
+struct hashtable * vnet_create_htable(unsigned int min_size,
+                                   unsigned int (*hashfunction) (addr_t key),
+                                   int (*key_eq_fn) (addr_t key1, addr_t key2));
+
+void vnet_free_htable(struct hashtable * htable, int free_values, int free_keys);
+
+/*
+ * returns non-zero for successful insertion
+ *
+ * This function will cause the table to expand if the insertion would take
+ * the ratio of entries to table size over the maximum load factor.
+ *
+ * This function does not check for repeated insertions with a duplicate key.
+ * The value returned when using a duplicate key is undefined -- when
+ * the hashtable changes size, the order of retrieval of duplicate key
+ * entries is reversed.
+ * If in doubt, remove before insert.
+ */
+int vnet_htable_insert(struct hashtable * htable, addr_t key, addr_t value);
+
+// returns the value associated with the key, or NULL if none found
+addr_t vnet_htable_search(struct hashtable * htable, addr_t key);
+
+// returns the value associated with the key, or NULL if none found
+addr_t vnet_htable_remove(struct hashtable * htable, addr_t key, int free_key);
+
+unsigned int vnet_htable_count(struct hashtable * htable);
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/palacios/include/vnet/vnet_host.h b/palacios/include/vnet/vnet_host.h
new file mode 100644 (file)
index 0000000..5fe3cff
--- /dev/null
@@ -0,0 +1,273 @@
+/* 
+ * 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, Lei Xia <lxia@northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Lei Xia <lxia@northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VNET_HOST_H__
+#define __VNET_HOST_H__
+
+#include <vnet/vnet_base.h>
+#include <vnet/vnet_vmm.h>
+
+struct vnet_thread {
+    void * host_thread;
+};
+
+struct vnet_timer {
+    void * host_timer;
+};
+
+typedef unsigned long vnet_lock_t;
+
+
+
+struct vnet_host_hooks {
+    void *(*thread_start)(int (*fn)(void * arg), 
+                         void * arg, 
+                         char * thread_name);
+
+    void (*thread_sleep)(long timeout);
+    void (*thread_wakeup)(void * thread);
+    void (*thread_stop)(void * thread);
+    int (*thread_should_stop)(void);
+
+    void *(*timer_create)(unsigned long interval, 
+                         void (* timer_fun)(void * priv_data), 
+                         void * data);
+
+    void (*timer_del)(void * timer);
+    void (*timer_start)(void * timer);
+    void (*timer_stop)(void * timer);
+    void (*timer_reset)(void * timer, unsigned long interval);
+
+    void (*udelay)(unsigned long usecs);
+
+    /* duplicate part from os_hooks */
+    void (*yield_cpu)(void); 
+    void (*print)(const char * format, ...)
+       __attribute__ ((format (printf, 1, 2)));
+  
+    void *(*allocate_pages)(int num_pages, unsigned int alignment);
+    void (*free_pages)(void * page, int num_pages);
+
+    void *(*malloc)(unsigned int size);
+    void (*free)(void * addr);
+
+    void *(*paddr_to_vaddr)(void * addr);
+    void *(*vaddr_to_paddr)(void * addr);
+
+    void *(*mutex_alloc)(void);
+    void (*mutex_free)(void * mutex);
+    void (*mutex_lock)(void * mutex, int must_spin);
+    void (*mutex_unlock)(void * mutex);
+};
+
+
+
+#ifdef __V3VEE__
+
+extern struct vnet_host_hooks * host_hooks;
+
+
+/* MEMORY ALLOCATE/DEALLOCATE */
+
+#define PAGE_SIZE_4KB 4096
+               
+/* 4KB-aligned */
+static inline void * Vnet_AllocPages(int num_pages){
+    if ((host_hooks) && host_hooks->allocate_pages) {
+       return host_hooks->allocate_pages(num_pages, PAGE_SIZE_4KB);
+    }
+
+    return NULL;
+}
+
+static inline void Vnet_FreePages(void * page, int num_pages){
+    if ((host_hooks) && host_hooks->free_pages) {      
+       host_hooks->free_pages(page, num_pages);
+    }
+} 
+
+static inline void * Vnet_VAddr(void * addr) {
+    if ((host_hooks) && host_hooks->paddr_to_vaddr){
+       return host_hooks->paddr_to_vaddr(addr);
+    }
+
+    return NULL;
+}
+
+static inline void * Vnet_PAddr(void * addr) {
+    if ((host_hooks) && host_hooks->vaddr_to_paddr) {
+       return host_hooks->vaddr_to_paddr(addr);
+    }
+
+    return NULL;
+}
+
+static inline void * Vnet_Malloc(uint32_t size){
+    if ((host_hooks) && host_hooks->malloc) {
+       return host_hooks->malloc(size);
+    }
+
+    return NULL;
+}
+
+static inline void Vnet_Free(void * addr){  
+    if ((host_hooks) && host_hooks->free) {
+       host_hooks->free(addr);
+    }
+}
+
+
+static inline void Vnet_Yield(void){
+    if ((host_hooks) && (host_hooks)->yield_cpu) {
+       host_hooks->yield_cpu();
+    }
+}
+
+/* THREAD FUNCTIONS */
+struct vnet_thread * vnet_start_thread(int (*func)(void *), 
+                                      void * arg, char * name);
+
+static inline void vnet_thread_sleep(long timeout){
+    if((host_hooks) && host_hooks->thread_sleep){
+       host_hooks->thread_sleep(timeout);
+    }
+}
+
+static inline void vnet_thread_wakeup(struct vnet_thread * thread){
+    if((host_hooks) && host_hooks->thread_wakeup){
+       host_hooks->thread_wakeup(thread->host_thread);
+    }
+}
+
+
+static inline void vnet_thread_stop(struct vnet_thread * thread){
+    if((host_hooks) && host_hooks->thread_stop){
+       host_hooks->thread_stop(thread->host_thread);
+    }
+}
+
+static inline int vnet_thread_should_stop(void){
+    if((host_hooks) && host_hooks->thread_should_stop){
+       return host_hooks->thread_should_stop();
+    }
+
+    return 0;
+}
+
+static inline void  vnet_udelay(unsigned long usecs){
+    if((host_hooks) && host_hooks->udelay){
+       host_hooks->udelay(usecs);
+    }
+}
+
+/* TIMER FUNCTIONS */
+/* interval, in jittes */
+struct vnet_timer * vnet_create_timer(unsigned long interval, 
+                                     void (* timer_fun)(void * priv_data), 
+                                     void * pri_data);
+
+static inline void vnet_del_timer(struct vnet_timer * timer){
+    if((host_hooks) && host_hooks->timer_del){
+       host_hooks->timer_del(timer->host_timer);
+       Vnet_Free(timer);
+    }
+}
+       
+static inline void vnet_start_timer(struct vnet_timer * timer){
+    if((host_hooks) && host_hooks->timer_start){
+       host_hooks->timer_start(timer->host_timer);
+    }
+}
+
+static inline void vnet_stop_timer(struct vnet_timer * timer){
+    if((host_hooks) && host_hooks->timer_stop){
+       host_hooks->timer_stop(timer->host_timer);
+    }
+}
+
+static inline void vnet_reset_timer(struct vnet_timer * timer, 
+                                   unsigned long new_interval){
+    if((host_hooks) && host_hooks->timer_reset){
+       host_hooks->timer_reset(timer->host_timer, new_interval);
+    }
+}
+
+
+
+#define Vnet_Print(level, fmt, args...)                                        \
+    do {                                                               \
+       extern int net_debug;                                           \
+       if(level <= net_debug) {                                        \
+           extern struct vnet_host_hooks * host_hooks;                 \
+           if ((host_hooks) && (host_hooks)->print) {                  \
+               (host_hooks)->print((fmt), ##args);                     \
+           }                                                           \
+       }                                                               \
+    } while (0)        
+
+
+#define Vnet_Debug(fmt, args...)                                       \
+    do {                                                               \
+           extern struct vnet_host_hooks * host_hooks;                 \
+           if ((host_hooks) && (host_hooks)->print) {                  \
+               (host_hooks)->print((fmt), ##args);                     \
+           }                                                           \
+    } while (0)        
+
+
+
+
+/* Lock Utilities */
+int vnet_lock_init(vnet_lock_t * lock);
+
+static inline void vnet_lock_deinit(vnet_lock_t * lock) {
+    host_hooks->mutex_free((void *)*lock);
+    *lock = 0;
+}
+
+static inline void vnet_lock(vnet_lock_t lock) {
+    host_hooks->mutex_lock((void *)lock, 0);    
+}
+
+static inline void vnet_unlock(vnet_lock_t lock) {
+    host_hooks->mutex_unlock((void *)lock);
+}
+
+static inline unsigned long vnet_lock_irqsave(vnet_lock_t lock) {
+    //addr_t irq_state = v3_irq_save();
+    host_hooks->mutex_lock((void *)lock, 1);
+    return 0;
+}
+
+
+static inline void vnet_unlock_irqrestore(vnet_lock_t lock, addr_t irq_state) {
+    host_hooks->mutex_unlock((void *)lock);
+    //v3_irq_restore(irq_state);
+}
+
+#endif
+
+
+void init_vnet(struct vnet_host_hooks * hooks);
+void deinit_vnet(void);
+
+
+#endif
+
similarity index 51%
rename from palacios/include/palacios/vmm_instrument.h
rename to palacios/include/vnet/vnet_vmm.h
index 63b2be2..054cff2 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* 
  * 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.  
@@ -7,33 +7,25 @@
  * 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> 
+ * Copyright (c) 2011, Lei Xia <lxia@northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
  * All rights reserved.
  *
- * Author: Chang Bae <c.s.bae@u.northwestern.edu>
+ * Author: Lei Xia <lxia@northwestern.edu>
  *
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
-#ifndef __VMM_INSTRUMENT_H__
-#define __VMM_INSTRUMENT_H__
+#ifndef __VNET_VMM_H__
+#define __VNET_VMM_H__
 
-#ifdef __V3VEE__
+#include <palacios/vmm.h>
+#include <palacios/vmm_string.h>
+#include <palacios/vmm_sprintf.h>
 
-#ifdef CONFIG_INSTRUMENT_VMM 
 
-#include <palacios/vmm_types.h>
-#include <palacios/vmm_ringbuffer.h>
-
-
-void v3_init_instrumentation() __attribute__((__no_instrument_function__));
-
-#endif // INSTRUMENT_VMM
-
-#endif // __V3VEE__
-
-#endif // 
 
+#endif
 
index 593cb48..2579781 100644 (file)
@@ -1,4 +1,4 @@
 obj-y := null.o
 
-obj-$(CONFIG_XED) :=   libxed.a \
+obj-$(V3_CONFIG_XED) :=        libxed.a \
                        v3-xed-compat.o 
index 7a5f62c..6ce5f10 100644 (file)
@@ -4,19 +4,19 @@
 /* Standard I/O predefined streams
 */
 static FILE   _streams = {0, 0, 0, 0, 0, NULL, NULL, 0, 0};
-#ifdef CONFIG_BUILT_IN_STDIN
+#ifdef V3_CONFIG_BUILT_IN_STDIN
 FILE  *stdin = (&_streams);
 #endif
 
-#ifdef CONFIG_BUILT_IN_STDOUT
+#ifdef V3_CONFIG_BUILT_IN_STDOUT
 FILE  *stdout = (&_streams);
 #endif
 
-#ifdef CONFIG_BUILT_IN_STDERR
+#ifdef V3_CONFIG_BUILT_IN_STDERR
 FILE  *stderr = (&_streams);
 #endif
 
-#ifdef CONFIG_BUILT_IN_FPRINTF
+#ifdef V3_CONFIG_BUILT_IN_FPRINTF
 int fprintf(FILE *file, char *fmt, ...) {
    // PrintDebug("In fprintf!!\n");
    return 0;
@@ -24,21 +24,21 @@ int fprintf(FILE *file, char *fmt, ...) {
 }
 #endif
 
-#ifdef CONFIG_BUILT_IN_PRINTF
+#ifdef V3_CONFIG_BUILT_IN_PRINTF
 int printf(char *fmt, ...) {
    // PrintDebug("In fprintf!!\n");
    return 0;
 }
 #endif
 
-#ifdef CONFIG_BUILT_IN_FFLUSH
+#ifdef V3_CONFIG_BUILT_IN_FFLUSH
 int fflush(FILE *stream) {
     //PrintDebug("In fflush!!\n");
     return 0;
 }
 #endif
 
-#ifdef CONFIG_BUILT_IN_ABORT
+#ifdef V3_CONFIG_BUILT_IN_ABORT
 void abort(void)
 {
    //PrintDebug("Abort!!\n");
index 2d97a1b..8853e97 100644 (file)
@@ -1,4 +1,4 @@
 obj-y := null.o
 
-obj-$(CONFIG_XED) :=   libxed32e.a \
-                       v3-xed-compat.o
+obj-$(V3_CONFIG_XED) :=        libxed32e.a \
+                               v3-xed-compat.o
index b945d2b..4b30a67 100644 (file)
@@ -27,7 +27,7 @@
 #include <palacios/vmm_io.h>
 
 
-#ifndef CONFIG_DEBUG_PIT
+#ifndef V3_CONFIG_DEBUG_PIT
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -54,8 +54,8 @@
  */
 typedef enum {NOT_RUNNING, PENDING, RUNNING} channel_run_state_t;
 typedef enum {NOT_WAITING, WAITING_LOBYTE, WAITING_HIBYTE} channel_access_state_t;
-typedef enum {LATCH_COUNT, LOBYTE_ONLY, HIBYTE_ONLY, LOBYTE_HIBYTE} channel_access_mode_t;
-typedef enum {IRQ_ON_TERM_CNT, ONE_SHOT, RATE_GEN, SQR_WAVE, SW_STROBE, HW_STROBE} channel_op_mode_t;
+typedef enum {LATCH_COUNT = 0, LOBYTE_ONLY = 1, HIBYTE_ONLY = 2, LOBYTE_HIBYTE = 3} channel_access_mode_t;
+typedef enum {IRQ_ON_TERM_CNT = 0, ONE_SHOT = 1, RATE_GEN = 2, SQR_WAVE = 3, SW_STROBE = 4, HW_STROBE = 5} channel_op_mode_t;
 
 
 struct channel {
@@ -162,7 +162,7 @@ static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t osc
     } else {
        ushort_t reload_val = ch->reload_value; 
 
-       if (ch->op_mode == SW_STROBE) {
+       if ((ch->op_mode == SW_STROBE) || (ch->op_mode == IRQ_ON_TERM_CNT)) {
            reload_val = 0xffff;
        }
 
@@ -430,10 +430,12 @@ static int handle_speaker_write(uint8_t *speaker, struct channel * ch, char val)
 }
 
 static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
-    ch->op_mode = cmd.op_mode;
-    ch->access_mode = cmd.access_mode;
 
+    ch->access_mode = cmd.access_mode;
 
+    if (ch->access_mode != 0) {
+       ch->op_mode = cmd.op_mode;
+    }
 
 
     switch (cmd.access_mode) {
@@ -660,7 +662,7 @@ static int pit_free(void * private_data) {
     return 0;
 }
 
-#ifdef CONFIG_KEYED_STREAMS
+#ifdef V3_CONFIG_KEYED_STREAMS
 static int pit_checkpoint(struct vm_device *dev, v3_keyed_stream_t stream)
 {
     struct pit *p = (struct pit *) (dev->private_data);
@@ -716,7 +718,7 @@ static int pit_restore(struct vm_device *dev, v3_keyed_stream_t stream)
 
 static struct v3_device_ops dev_ops = {
     .free = (int (*)(void *))pit_free,
-#ifdef CONFIG_KEYED_STREAMS
+#ifdef V3_CONFIG_KEYED_STREAMS
     .checkpoint = pit_checkpoint,
     .restore = pit_restore,
 #endif
@@ -763,7 +765,7 @@ static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        return -1;
     }
 
-#ifdef CONFIG_DEBUG_PIT
+#ifdef V3_CONFIG_DEBUG_PIT
     PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
     //PrintTrace(reload_val);
     PrintDebug("\n");
@@ -789,7 +791,7 @@ static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     init_channel(&(pit_state->ch_1));
     init_channel(&(pit_state->ch_2));
 
-#ifdef CONFIG_DEBUG_PIT
+#ifdef V3_CONFIG_DEBUG_PIT
     PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
     //PrintTraceLL(pit_state->pit_counter);
     PrintDebug("\n");
index 0d5e5ff..c24402d 100644 (file)
@@ -25,7 +25,7 @@
 #include <palacios/vmm_dev_mgr.h>
 #include <palacios/vm_guest.h>
 
-#ifndef CONFIG_DEBUG_PIC
+#ifndef V3_CONFIG_DEBUG_PIC
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -216,7 +216,7 @@ static int pic_raise_intr(struct v3_vm_info * vm, void * private_data, int irq)
        return -1;
     }
 
-#ifdef CONFIG_MULTITHREAD_OS
+#ifdef V3_CONFIG_MULTITHREAD_OS
     v3_interrupt_cpu(vm, 0, 0);
 #endif
 
index 35b8523..d49bb9e 100644 (file)
@@ -18,6 +18,7 @@ config DEBUG_APIC
 
 config IO_APIC
        bool "IOAPIC"
+       depends on APIC
        default y
        help 
          Includes the Virtual IO APIC
@@ -30,6 +31,13 @@ config DEBUG_IO_APIC
          Enable debugging for the IO APIC
 
 
+config MPTABLE
+       bool "MPTABLE"
+       default y
+       depends on APIC
+       help 
+         Includes the MPTABLE to map the APICs and IO-APIC
+
 
 config BOCHS_DEBUG
        bool "Bochs Debug Console Device"
@@ -148,7 +156,7 @@ config DEBUG_VIRTIO_SYM
 config LINUX_VIRTIO_NET
         bool "Enable Virtio Network Device"
         default n
-       depends on PCI && EXPERIMENTAL
+       depends on PCI
         help
           Enable the Virtio Net
 
@@ -163,7 +171,7 @@ config DEBUG_VIRTIO_NET
 config LINUX_VIRTIO_VNET
         bool "Enable Virtio VNET interface"
         default n
-        depends on PCI && EXPERIMENTAL && VNET
+        depends on PCI && VNET
         help
           Enable the Virtio VNET interface for Control VM
 
@@ -178,12 +186,12 @@ config DEBUG_LINUX_VIRTIO_VNET
 config VNET_NIC
         bool "Enable VNET Backend Device"
         default n
-       depends on PCI && EXPERIMENTAL && VNET
+       depends on PCI && VNET
         help
           Enable the VNET backend device
 
 config DEBUG_VNET_NIC
-        bool "VNET NIC Device Debugging"
+        bool "VNET Backend Device Debugging"
         default n
         depends on VNET_NIC && DEBUG_ON
         help
@@ -394,7 +402,7 @@ config DISK_MODEL
 config VGA
        bool "VGA"
        default n
-       depends on !PASSTHROUGH_VIDEO && GRAPHICS_CONSOLE
+       depends GRAPHICS_CONSOLE
        help
          Includes the Virtual VGA video support, and will 
           eventually also include SVGA
@@ -412,7 +420,6 @@ config DEBUG_VGA
 config CGA
        bool "CGA"
        default n
-       depends on !PASSTHROUGH_VIDEO
        help
          Includes the Virtual CGA video support
 
@@ -427,14 +434,14 @@ config DEBUG_CGA
 config TELNET_CONSOLE
        bool "Telnet Virtual Console"
        default n
-       depends on CGA && !PASSTHROUGH_VIDEO
+       depends on CGA
        help
          Includes the virtual telnet console 
 
 config CURSES_CONSOLE
        bool "Curses Virtual Console"
        default n
-       depends on CGA && !PASSTHROUGH_VIDEO
+       depends on CGA && CONSOLE
        help
          Includes the virtual curses console 
 
@@ -446,6 +453,7 @@ config SERIAL_UART
 
 config CHAR_STREAM
        bool "Stream based character frontend"
+       depends on STREAM
        default n
        help
          Include Stream based character device frontend
index 51b43e9..f3a553e 100644 (file)
@@ -1,49 +1,50 @@
-obj-$(CONFIG_APIC) += apic.o
-obj-$(CONFIG_IO_APIC) += io_apic.o
-obj-$(CONFIG_PIT) += 8254.o
-obj-$(CONFIG_PIC) += 8259a.o
-obj-$(CONFIG_BOCHS_DEBUG) += bochs_debug.o
-obj-$(CONFIG_GENERIC) += generic.o
-obj-$(CONFIG_I440FX) += i440fx.o
-obj-$(CONFIG_IDE) += ide.o
-obj-$(CONFIG_SERIAL_UART) += serial.o
-
-obj-$(CONFIG_KEYBOARD) += keyboard.o
-obj-$(CONFIG_LINUX_VIRTIO_BALLOON) += lnx_virtio_balloon.o
-obj-$(CONFIG_LINUX_VIRTIO_BLOCK) += lnx_virtio_blk.o
-obj-$(CONFIG_LINUX_VIRTIO_SYM) += lnx_virtio_sym.o
-obj-$(CONFIG_LINUX_VIRTIO_NET) += lnx_virtio_nic.o
-obj-$(CONFIG_LINUX_VIRTIO_VNET) += lnx_virtio_vnet.o
-obj-$(CONFIG_VNET_NIC) += vnet_nic.o
-obj-$(CONFIG_NVRAM) += nvram.o
-obj-$(CONFIG_OS_DEBUG) += os_debug.o
-obj-$(CONFIG_PCI) += pci.o
-obj-$(CONFIG_PIIX3) += piix3.o
-obj-$(CONFIG_SWAPBYPASS_DISK_CACHE) += swapbypass_cache.o
-obj-$(CONFIG_SWAPBYPASS_DISK_CACHE2) += swapbypass_cache2.o
-obj-$(CONFIG_DISK_MODEL) += disk_model.o
-obj-$(CONFIG_NIC_BRIDGE) += nic_bridge.o
-
-obj-$(CONFIG_NE2K) += ne2k.o
-obj-$(CONFIG_RTL8139) += rtl8139.o
-
-obj-$(CONFIG_TMPDISK) += tmpdisk.o
-obj-$(CONFIG_RAMDISK) += ramdisk.o 
-obj-$(CONFIG_NETDISK) += netdisk.o 
-obj-$(CONFIG_FILEDISK) += filedisk.o
-
-obj-$(CONFIG_CGA) += cga.o
-obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o
-obj-$(CONFIG_CURSES_CONSOLE) += curses_cons.o
-
-obj-$(CONFIG_PASSTHROUGH_PCI) += pci_passthrough.o
-
-obj-$(CONFIG_SYMMOD) += lnx_virtio_symmod.o
-obj-$(CONFIG_CHAR_STREAM) += char_stream.o
-
-obj-$(CONFIG_MCHECK) += mcheck.o
-
-obj-$(CONFIG_VGA) += vga.o
-
-obj-$(CONFIG_PCI_FRONT) += pci_front.o
+obj-$(V3_CONFIG_APIC) += apic.o
+obj-$(V3_CONFIG_IO_APIC) += io_apic.o
+obj-$(V3_CONFIG_MPTABLE) += mptable.o
+obj-$(V3_CONFIG_PIT) += 8254.o
+obj-$(V3_CONFIG_PIC) += 8259a.o
+obj-$(V3_CONFIG_BOCHS_DEBUG) += bochs_debug.o
+obj-$(V3_CONFIG_GENERIC) += generic.o
+obj-$(V3_CONFIG_I440FX) += i440fx.o
+obj-$(V3_CONFIG_IDE) += ide.o
+obj-$(V3_CONFIG_SERIAL_UART) += serial.o
+
+obj-$(V3_CONFIG_KEYBOARD) += keyboard.o
+obj-$(V3_CONFIG_LINUX_VIRTIO_BALLOON) += lnx_virtio_balloon.o
+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_VNET_NIC) += vnet_nic.o
+obj-$(V3_CONFIG_NVRAM) += nvram.o
+obj-$(V3_CONFIG_OS_DEBUG) += os_debug.o
+obj-$(V3_CONFIG_PCI) += pci.o
+obj-$(V3_CONFIG_PIIX3) += piix3.o
+obj-$(V3_CONFIG_SWAPBYPASS_DISK_CACHE) += swapbypass_cache.o
+obj-$(V3_CONFIG_SWAPBYPASS_DISK_CACHE2) += swapbypass_cache2.o
+obj-$(V3_CONFIG_DISK_MODEL) += disk_model.o
+obj-$(V3_CONFIG_NIC_BRIDGE) += nic_bridge.o
+
+obj-$(V3_CONFIG_NE2K) += ne2k.o
+obj-$(V3_CONFIG_RTL8139) += rtl8139.o
+
+obj-$(V3_CONFIG_TMPDISK) += tmpdisk.o
+obj-$(V3_CONFIG_RAMDISK) += ramdisk.o 
+obj-$(V3_CONFIG_NETDISK) += netdisk.o 
+obj-$(V3_CONFIG_FILEDISK) += filedisk.o
+
+obj-$(V3_CONFIG_CGA) += cga.o
+obj-$(V3_CONFIG_TELNET_CONSOLE) += telnet_cons.o
+obj-$(V3_CONFIG_CURSES_CONSOLE) += curses_cons.o
+
+obj-$(V3_CONFIG_PASSTHROUGH_PCI) += pci_passthrough.o
+
+obj-$(V3_CONFIG_SYMMOD) += lnx_virtio_symmod.o
+obj-$(V3_CONFIG_CHAR_STREAM) += char_stream.o
+
+obj-$(V3_CONFIG_MCHECK) += mcheck.o
+
+obj-$(V3_CONFIG_VGA) += vga.o
+
+obj-$(V3_CONFIG_PCI_FRONT) += pci_front.o
 
index e038bb2..5d6da5e 100644 (file)
 #include <palacios/vmm_types.h>
 
 
+#include <palacios/vmm_queue.h>
+#include <palacios/vmm_lock.h>
+
+/* The locking in this file is nasty.
+ * There are 3 different locking approaches that are taken, depending on the APIC operation
+ * 1. Queue locks. Actual irq insertions are done via queueing irq ops at the dest apic. 
+ *    The destination apic's core is responsible for draining the queue, and actually 
+ *    setting the vector table. 
+ * 2. State lock. This is a standard lock taken when internal apic state is read/written. 
+ *    When an irq's destination is determined this lock is taken to examine the apic's 
+ *    addressability. 
+ * 3. VM barrier lock. This is taken when actual VM core state is changed (via SIPI). 
+ */
+
 
 
-#ifndef CONFIG_DEBUG_APIC
+#ifndef V3_CONFIG_DEBUG_APIC
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #else
@@ -165,6 +179,7 @@ struct apic_msr {
 
 
 
+
 typedef enum {INIT_ST, 
              SIPI, 
              STARTED} ipi_state_t; 
@@ -225,6 +240,9 @@ struct apic_state {
 
     struct v3_timer * timer;
 
+
+    struct v3_queue irq_queue;
+
     uint32_t eoi;
 
 
@@ -236,6 +254,8 @@ struct apic_state {
 struct apic_dev_state {
     int num_apics;
   
+    v3_lock_t state_lock;
+
     struct apic_state apics[0];
 } __attribute__((packed));
 
@@ -304,6 +324,9 @@ static void init_apic_state(struct apic_state * apic, uint32_t id) {
     apic->spec_eoi.val = 0x00000000;
 
 
+    v3_init_queue(&(apic->irq_queue));
+
+
 }
 
 
@@ -312,9 +335,9 @@ static void init_apic_state(struct apic_state * apic, uint32_t id) {
 
 static int read_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]);
+    struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
 
-    PrintDebug("apic %u: core %u: MSR read\n", apic->lapic_id.val, core->cpu_id);
+    PrintDebug("apic %u: core %u: MSR read\n", apic->lapic_id.val, core->vcpu_id);
 
     dst->value = apic->base_addr;
 
@@ -324,16 +347,16 @@ static int read_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t * dst, v
 
 static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]);
-    struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->cpu_id, apic->base_addr);
+    struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
+    struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->vcpu_id, apic->base_addr);
 
 
-    PrintDebug("apic %u: core %u: MSR write\n", apic->lapic_id.val, core->cpu_id);
+    PrintDebug("apic %u: core %u: MSR write\n", apic->lapic_id.val, core->vcpu_id);
 
     if (old_reg == NULL) {
        // uh oh...
        PrintError("apic %u: core %u: APIC Base address region does not exit...\n",
-                  apic->lapic_id.val, core->cpu_id);
+                  apic->lapic_id.val, core->vcpu_id);
        return -1;
     }
     
@@ -343,11 +366,11 @@ static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, vo
 
     apic->base_addr = src.value;
 
-    if (v3_hook_full_mem(core->vm_info, core->cpu_id, apic->base_addr, 
+    if (v3_hook_full_mem(core->vm_info, core->vcpu_id, apic->base_addr, 
                         apic->base_addr + PAGE_SIZE_4KB, 
                         apic_read, apic_write, apic_dev) == -1) {
        PrintError("apic %u: core %u: Could not hook new APIC Base address\n",
-                  apic->lapic_id.val, core->cpu_id);
+                  apic->lapic_id.val, core->vcpu_id);
 
        return -1;
     }
@@ -357,11 +380,10 @@ static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, vo
 }
 
 
+
+
+
 // irq_num is the bit offset into a 256 bit buffer...
-// return values
-//    -1 = error
-//     0 = OK, no interrupt needed now
-//     1 = OK, interrupt needed now
 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
     int major_offset = (irq_num & ~0x00000007) >> 3;
     int minor_offset = irq_num & 0x00000007;
@@ -370,14 +392,7 @@ static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
     uint8_t flag = 0x1 << minor_offset;
 
 
-    if (irq_num <= 15 || irq_num>255) {
-       PrintError("apic %u: core %d: Attempting to raise an invalid interrupt: %d\n", 
-                  apic->lapic_id.val, apic->core->cpu_id, irq_num);
-       return -1;
-    }
-
-
-    PrintDebug("apic %u: core %d: Raising APIC IRQ %d\n", apic->lapic_id.val, apic->core->cpu_id, irq_num);
+    PrintDebug("apic %u: core %d: Raising APIC IRQ %d\n", apic->lapic_id.val, apic->core->vcpu_id, irq_num);
 
     if (*req_location & flag) {
        PrintDebug("Interrupt %d  coallescing\n", irq_num);
@@ -389,13 +404,37 @@ static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
        return 1;
     } else {
        PrintDebug("apic %u: core %d: Interrupt  not enabled... %.2x\n", 
-                  apic->lapic_id.val, apic->core->cpu_id,*en_location);
+                  apic->lapic_id.val, apic->core->vcpu_id, *en_location);
     }
 
     return 0;
 }
 
 
+static int add_apic_irq_entry(struct apic_state * apic, uint8_t irq_num) {
+
+    if (irq_num <= 15) {
+       PrintError("core %d: Attempting to raise an invalid interrupt: %d\n", 
+                   apic->core->vcpu_id, irq_num);
+       return -1;
+    }
+
+    v3_enqueue(&(apic->irq_queue), (addr_t)irq_num);
+
+    return 0;
+}
+
+static void drain_irq_entries(struct apic_state * apic) {
+    uint32_t irq = 0;
+
+    while ((irq = (uint32_t)v3_dequeue(&(apic->irq_queue))) != 0) {
+       activate_apic_irq(apic, irq);
+    }
+
+}
+
+
+
 
 static int get_highest_isr(struct apic_state * apic) {
     int i = 0, j = 0;
@@ -455,7 +494,7 @@ static int apic_do_eoi(struct apic_state * apic) {
        
        *svc_location &= ~flag;
 
-#ifdef CONFIG_CRAY_XT
+#ifdef V3_CONFIG_CRAY_XT
        
        if ((isr_irq == 238) || 
            (isr_irq == 239)) {
@@ -524,7 +563,7 @@ static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_t
 
     if (del_mode == APIC_FIXED_DELIVERY) {
        //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
-       return activate_apic_irq(apic, vec_num);
+       return add_apic_irq_entry(apic, vec_num);
     } else {
        PrintError("apic %u: core ?: Unhandled Delivery Mode\n", apic->lapic_id.val);
        return -1;
@@ -533,77 +572,108 @@ static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_t
 
 
 
-static inline int should_deliver_cluster_ipi(struct guest_info * dst_core, 
+static inline int should_deliver_cluster_ipi(struct apic_dev_state * apic_dev,
+                                            struct guest_info * dst_core, 
                                             struct apic_state * dst_apic, uint8_t mda) {
 
+    int ret = 0;
+
+
     if         ( ((mda & 0xf0) == (dst_apic->log_dst.dst_log_id & 0xf0)) &&  /* (I am in the cluster and */
          ((mda & 0x0f) & (dst_apic->log_dst.dst_log_id & 0x0f)) ) {  /*  I am in the set)        */
+       ret = 1;
+    } else {
+       ret = 0;
+    }
+
 
+    if (ret == 1) {
        PrintDebug("apic %u core %u: accepting clustered IRQ (mda 0x%x == log_dst 0x%x)\n",
-                  dst_apic->lapic_id.val, dst_core->cpu_id, mda, 
+                  dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
                   dst_apic->log_dst.dst_log_id);
-       
-       return 1;
     } else {
        PrintDebug("apic %u core %u: rejecting clustered IRQ (mda 0x%x != log_dst 0x%x)\n",
-                  dst_apic->lapic_id.val, dst_core->cpu_id, mda, 
+                  dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
                   dst_apic->log_dst.dst_log_id);
-       return 0;
     }
+
+    return ret;
+
 }
 
-static inline int should_deliver_flat_ipi(struct guest_info * dst_core,
+static inline int should_deliver_flat_ipi(struct apic_dev_state * apic_dev,
+                                         struct guest_info * dst_core,
                                          struct apic_state * dst_apic, uint8_t mda) {
 
-    if (dst_apic->log_dst.dst_log_id & mda) {  // I am in the set 
+    int ret = 0;
 
-       PrintDebug("apic %u core %u: accepting flat IRQ (mda 0x%x == log_dst 0x%x)\n",
-                  dst_apic->lapic_id.val, dst_core->cpu_id, mda, 
-                  dst_apic->log_dst.dst_log_id);
 
-       return 1;
+    if ((dst_apic->log_dst.dst_log_id & mda) != 0) {  // I am in the set 
+       ret = 1;
+    } else {
+       ret = 0;
+    }
 
-  } else {
 
+    if (ret == 1) {
+       PrintDebug("apic %u core %u: accepting flat IRQ (mda 0x%x == log_dst 0x%x)\n",
+                  dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
+                  dst_apic->log_dst.dst_log_id);
+    } else {
        PrintDebug("apic %u core %u: rejecting flat IRQ (mda 0x%x != log_dst 0x%x)\n",
-                  dst_apic->lapic_id.val, dst_core->cpu_id, mda, 
+                  dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
                   dst_apic->log_dst.dst_log_id);
-       return 0;
-  }
+    }
+
+
+    return ret;
 }
 
 
 
-static int should_deliver_ipi(struct guest_info * dst_core, 
+static int should_deliver_ipi(struct apic_dev_state * apic_dev, 
+                             struct guest_info * dst_core, 
                              struct apic_state * dst_apic, uint8_t mda) {
+    addr_t flags = 0;
+    int ret = 0;
 
+    flags = v3_lock_irqsave(apic_dev->state_lock);
 
     if (dst_apic->dst_fmt.model == 0xf) {
 
        if (mda == 0xff) {
            /* always deliver broadcast */
-           return 1;
+           ret = 1;
+       } else {
+           ret = should_deliver_flat_ipi(apic_dev, dst_core, dst_apic, mda);
        }
-
-       return should_deliver_flat_ipi(dst_core, dst_apic, mda);
-
     } else if (dst_apic->dst_fmt.model == 0x0) {
 
        if (mda == 0xff) {
            /*  always deliver broadcast */
-           return 1;
+           ret = 1;
+       } else {
+           ret = should_deliver_cluster_ipi(apic_dev, dst_core, dst_apic, mda);
        }
 
-       return should_deliver_cluster_ipi(dst_core, dst_apic, mda);
-
     } else {
+       ret = -1;
+    }
+    
+    v3_unlock_irqrestore(apic_dev->state_lock, flags);
+
+
+    if (ret == -1) {
        PrintError("apic %u core %u: invalid destination format register value 0x%x for logical mode delivery.\n", 
-                  dst_apic->lapic_id.val, dst_core->cpu_id, dst_apic->dst_fmt.model);
-       return -1;
+                  dst_apic->lapic_id.val, dst_core->vcpu_id, dst_apic->dst_fmt.model);
     }
+
+    return ret;
 }
 
 
+
+
 // Only the src_apic pointer is used
 static int deliver_ipi(struct apic_state * src_apic, 
                       struct apic_state * dst_apic, 
@@ -620,44 +690,30 @@ static int deliver_ipi(struct apic_state * src_apic,
            // lowest priority - 
            // caller needs to have decided which apic to deliver to!
 
-           int do_xcall;
+           PrintDebug("delivering IRQ %d to core %u\n", vector, dst_core->vcpu_id); 
 
-           PrintDebug("delivering IRQ %d to core %u\n", vector, dst_core->cpu_id); 
-
-           do_xcall = activate_apic_irq(dst_apic, vector);
+           add_apic_irq_entry(dst_apic, vector);
            
-           if (do_xcall < 0) { 
-               PrintError("Failed to activate apic irq!\n");
-               return -1;
-           }
-
-           if (do_xcall && (dst_apic != src_apic)) { 
-               // Assume core # is same as logical processor for now
-               // TODO FIX THIS FIX THIS
-               // THERE SHOULD BE:  guestapicid->virtualapicid map,
-               //                   cpu_id->logical processor map
-               //     host maitains logical proc->phsysical proc
+#ifdef V3_CONFIG_MULTITHREAD_OS
+           if (dst_apic != src_apic) { 
                PrintDebug(" non-local core with new interrupt, forcing it to exit now\n"); 
-
-#ifdef CONFIG_MULTITHREAD_OS
-               v3_interrupt_cpu(dst_core->vm_info, dst_core->cpu_id, 0);
-#else
-               V3_ASSERT(0);
-#endif
+               v3_interrupt_cpu(dst_core->vm_info, dst_core->pcpu_id, 0);
            }
+#endif
+
 
            break;
        }
        case APIC_INIT_DELIVERY: { 
 
-           PrintDebug(" INIT delivery to core %u\n", dst_core->cpu_id);
+           PrintDebug(" INIT delivery to core %u\n", dst_core->vcpu_id);
 
            // TODO: any APIC reset on dest core (shouldn't be needed, but not sure...)
 
            // Sanity check
            if (dst_apic->ipi_state != INIT_ST) { 
                PrintError(" Warning: core %u is not in INIT state (mode = %d), ignored (assuming this is the deassert)\n",
-                          dst_core->cpu_id, dst_apic->ipi_state);
+                          dst_core->vcpu_id, dst_apic->ipi_state);
                // Only a warning, since INIT INIT SIPI is common
                break;
            }
@@ -680,27 +736,14 @@ static int deliver_ipi(struct apic_state * src_apic,
            // Sanity check
            if (dst_apic->ipi_state != SIPI) { 
                PrintError(" core %u is not in SIPI state (mode = %d), ignored!\n",
-                          dst_core->cpu_id, dst_apic->ipi_state);
+                          dst_core->vcpu_id, dst_apic->ipi_state);
                break;
            }
 
-           // Write the RIP, CS, and descriptor
-           // assume the rest is already good to go
-           //
-           // vector VV -> rip at 0
-           //              CS = VV00
-           //  This means we start executing at linear address VV000
-           //
-           // So the selector needs to be VV00
-           // and the base needs to be VV000
-           //
-           dst_core->rip = 0;
-           dst_core->segments.cs.selector = vector << 8;
-           dst_core->segments.cs.limit = 0xffff;
-           dst_core->segments.cs.base = vector << 12;
+           v3_reset_vm_core(dst_core, vector);
 
            PrintDebug(" SIPI delivery (0x%x -> 0x%x:0x0) to core %u\n",
-                      vector, dst_core->segments.cs.selector, dst_core->cpu_id);
+                      vector, dst_core->segments.cs.selector, dst_core->vcpu_id);
            // Maybe need to adjust the APIC?
            
            // We transition the target core to SIPI state
@@ -713,10 +756,18 @@ static int deliver_ipi(struct apic_state * src_apic,
            
            break;                                                      
        }
+
+       case APIC_EXTINT_DELIVERY: // EXTINT
+           /* Two possible things to do here: 
+            * 1. Ignore the IPI and assume the 8259a (PIC) will handle it
+            * 2. Add 32 to the vector and inject it...
+            * We probably just want to do 1 here, and assume the raise_irq() will hit the 8259a.
+            */
+           return 0;
+
        case APIC_SMI_DELIVERY: 
        case APIC_RES1_DELIVERY: // reserved                                            
        case APIC_NMI_DELIVERY:
-       case APIC_EXTINT_DELIVERY: // ExtInt
        default:
            PrintError("IPI %d delivery is unsupported\n", del_mode); 
            return -1;
@@ -726,24 +777,29 @@ static int deliver_ipi(struct apic_state * src_apic,
     
 }
 
-static struct apic_state * find_physical_apic(struct apic_dev_state *apic_dev, struct int_cmd_reg *icr)
-{
+static struct apic_state * find_physical_apic(struct apic_dev_state * apic_dev, uint32_t dst_idx) {
+    struct apic_state * dst_apic = NULL;
+    addr_t flags;
     int i;
-    
-    if (icr->dst >0 && icr->dst < apic_dev->num_apics) { 
+
+    flags = v3_lock_irqsave(apic_dev->state_lock);
+
+    if ( (dst_idx > 0) && (dst_idx < apic_dev->num_apics) ) { 
        // see if it simply is the core id
-       if (apic_dev->apics[icr->dst].lapic_id.val == icr->dst) { 
-           return &(apic_dev->apics[icr->dst]);
+       if (apic_dev->apics[dst_idx].lapic_id.val == dst_idx) { 
+            dst_apic = &(apic_dev->apics[dst_idx]);
        }
     }
 
-    for (i=0;i<apic_dev->num_apics;i++) { 
-       if (apic_dev->apics[i].lapic_id.val == icr->dst) { 
-           return &(apic_dev->apics[i]);
+    for (i = 0; i < apic_dev->num_apics; i++) { 
+       if (apic_dev->apics[i].lapic_id.val == dst_idx) { 
+           dst_apic =  &(apic_dev->apics[i]);
        }
     }
-    
-    return NULL;
+
+    v3_unlock_irqrestore(apic_dev->state_lock, flags);
+
+    return dst_apic;
 
 }
 
@@ -769,9 +825,9 @@ static int route_ipi(struct apic_dev_state * apic_dev,
        case APIC_SHORTHAND_NONE:  // no shorthand
            if (icr->dst_mode == APIC_DEST_PHYSICAL) { 
 
-               dest_apic=find_physical_apic(apic_dev,icr);
+               dest_apic = find_physical_apic(apic_dev, icr->dst);
                
-               if (dest_apic==NULL) { 
+               if (dest_apic == NULL) { 
                    PrintError("apic: Attempted send to unregistered apic id=%u\n", icr->dst);
                    return -1;
                }
@@ -783,29 +839,32 @@ static int route_ipi(struct apic_dev_state * apic_dev,
                }
 
 
-               V3_Print("apic: done\n");
-
+               PrintDebug("apic: done\n");
 
            } else if (icr->dst_mode == APIC_DEST_LOGICAL) {
                
-               if (icr->del_mode!=APIC_LOWEST_DELIVERY ) { 
+               if (icr->del_mode != APIC_LOWEST_DELIVERY) { 
+                   int i;
+                   uint8_t mda = icr->dst;
+
                    // logical, but not lowest priority
                    // we immediately trigger
                    // fixed, smi, reserved, nmi, init, sipi, etc
-                   int i;
-                   
-                   uint8_t mda = icr->dst;
+
                    
                    for (i = 0; i < apic_dev->num_apics; i++) { 
+                       int del_flag = 0;
                        
                        dest_apic = &(apic_dev->apics[i]);
                        
-                       int del_flag = should_deliver_ipi(dest_apic->core, dest_apic, mda);
+                       del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
                        
                        if (del_flag == -1) {
+
                            PrintError("apic: Error checking delivery mode\n");
                            return -1;
                        } else if (del_flag == 1) {
+
                            if (deliver_ipi(src_apic, dest_apic, 
                                            icr->vec, icr->del_mode) == -1) {
                                PrintError("apic: Error: Could not deliver IPI\n");
@@ -813,18 +872,19 @@ static int route_ipi(struct apic_dev_state * apic_dev,
                            }
                        }
                    }
-               } else {  //APIC_LOWEST_DELIVERY
-                   // logical, lowest priority
-                   int i;
+               } else {  // APIC_LOWEST_DELIVERY
                    struct apic_state * cur_best_apic = NULL;
                    uint8_t mda = icr->dst;
-                  
+                   int i;
+
+                   // logical, lowest priority
+
                    for (i = 0; i < apic_dev->num_apics; i++) { 
                        int del_flag = 0;
 
                        dest_apic = &(apic_dev->apics[i]);
                        
-                       del_flag = should_deliver_ipi(dest_apic->core, dest_apic, mda);
+                       del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
                        
                        if (del_flag == -1) {
                            PrintError("apic: Error checking delivery mode\n");
@@ -832,11 +892,18 @@ static int route_ipi(struct apic_dev_state * apic_dev,
                            return -1;
                        } else if (del_flag == 1) {
                            // update priority for lowest priority scan
-                           if (!cur_best_apic) {
+                           addr_t flags = 0;
+
+                           flags = v3_lock_irqsave(apic_dev->state_lock);
+
+                           if (cur_best_apic == 0) {
                                cur_best_apic = dest_apic;  
                            } else if (dest_apic->task_prio.val < cur_best_apic->task_prio.val) {
                                cur_best_apic = dest_apic;
                            } 
+
+                           v3_unlock_irqrestore(apic_dev->state_lock, flags);
+
                        }                       
                    }
 
@@ -872,6 +939,7 @@ static int route_ipi(struct apic_dev_state * apic_dev,
                }
            } else if (icr->dst_mode == APIC_DEST_LOGICAL) {  /* logical delivery */
                PrintError("apic: use of logical delivery in self (untested)\n");
+
                if (deliver_ipi(src_apic, src_apic, icr->vec, icr->del_mode) == -1) {
                    PrintError("apic: Could not deliver IPI to self (logical)\n");
                    return -1;
@@ -911,18 +979,18 @@ static int route_ipi(struct apic_dev_state * apic_dev,
 // External function, expected to acquire lock on apic
 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]);
+    struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
     addr_t reg_addr  = guest_addr - apic->base_addr;
     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
     uint32_t val = 0;
 
 
     PrintDebug("apic %u: core %u: at %p: Read apic address space (%p)\n",
-              apic->lapic_id.val, core->cpu_id, apic, (void *)guest_addr);
+              apic->lapic_id.val, core->vcpu_id, apic, (void *)guest_addr);
 
     if (msr->apic_enable == 0) {
        PrintError("apic %u: core %u: Read from APIC address space with disabled APIC, apic msr=0x%llx\n",
-                  apic->lapic_id.val, core->cpu_id, apic->base_addr_msr.value);
+                  apic->lapic_id.val, core->vcpu_id, apic->base_addr_msr.value);
        return -1;
     }
 
@@ -1135,7 +1203,7 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
 
        default:
            PrintError("apic %u: core %u: Read from Unhandled APIC Register: %x (getting zero)\n", 
-                      apic->lapic_id.val, core->cpu_id, (uint32_t)reg_addr);
+                      apic->lapic_id.val, core->vcpu_id, (uint32_t)reg_addr);
            return -1;
     }
 
@@ -1147,7 +1215,7 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
        *val_ptr = *(((uint8_t *)&val) + byte_addr);
 
     } else if ((length == 2) && 
-              ((reg_addr & 0x3) == 0x3)) {
+              ((reg_addr & 0x3) != 0x3)) {
        uint_t byte_addr = reg_addr & 0x3;
        uint16_t * val_ptr = (uint16_t *)dst;
        *val_ptr = *(((uint16_t *)&val) + byte_addr);
@@ -1158,12 +1226,12 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
 
     } else {
        PrintError("apic %u: core %u: Invalid apic read length (%d)\n", 
-                  apic->lapic_id.val, core->cpu_id, length);
+                  apic->lapic_id.val, core->vcpu_id, length);
        return -1;
     }
 
     PrintDebug("apic %u: core %u: Read finished (val=%x)\n", 
-              apic->lapic_id.val, core->cpu_id, *(uint32_t *)dst);
+              apic->lapic_id.val, core->vcpu_id, *(uint32_t *)dst);
 
     return length;
 }
@@ -1174,27 +1242,28 @@ static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, ui
  */
 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
+    struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
     addr_t reg_addr  = guest_addr - apic->base_addr;
     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
     uint32_t op_val = *(uint32_t *)src;
+    addr_t flags = 0;
 
     PrintDebug("apic %u: core %u: at %p and priv_data is at %p\n",
-              apic->lapic_id.val, core->cpu_id, apic, priv_data);
+              apic->lapic_id.val, core->vcpu_id, apic, priv_data);
 
     PrintDebug("apic %u: core %u: write to address space (%p) (val=%x)\n", 
-              apic->lapic_id.val, core->cpu_id, (void *)guest_addr, *(uint32_t *)src);
+              apic->lapic_id.val, core->vcpu_id, (void *)guest_addr, *(uint32_t *)src);
 
     if (msr->apic_enable == 0) {
        PrintError("apic %u: core %u: Write to APIC address space with disabled APIC, apic msr=0x%llx\n",
-                  apic->lapic_id.val, core->cpu_id, apic->base_addr_msr.value);
+                  apic->lapic_id.val, core->vcpu_id, apic->base_addr_msr.value);
        return -1;
     }
 
 
     if (length != 4) {
        PrintError("apic %u: core %u: Invalid apic write length (%d)\n", 
-                  apic->lapic_id.val, length, core->cpu_id);
+                  apic->lapic_id.val, length, core->vcpu_id);
        return -1;
     }
 
@@ -1230,14 +1299,14 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
        case EXT_APIC_FEATURE_OFFSET:
 
            PrintError("apic %u: core %u: Attempting to write to read only register %p (error)\n", 
-                      apic->lapic_id.val, core->cpu_id, (void *)reg_addr);
+                      apic->lapic_id.val, core->vcpu_id, (void *)reg_addr);
 
            break;
 
            // Data registers
        case APIC_ID_OFFSET:
            //V3_Print("apic %u: core %u: my id is being changed to %u\n", 
-           //       apic->lapic_id.val, core->cpu_id, op_val);
+           //       apic->lapic_id.val, core->vcpu_id, op_val);
 
            apic->lapic_id.val = op_val;
            break;
@@ -1246,11 +1315,15 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
            break;
        case LDR_OFFSET:
            PrintDebug("apic %u: core %u: setting log_dst.val to 0x%x\n",
-                      apic->lapic_id.val, core->cpu_id, op_val);
+                      apic->lapic_id.val, core->vcpu_id, op_val);
+           flags = v3_lock_irqsave(apic_dev->state_lock);
            apic->log_dst.val = op_val;
+           v3_unlock_irqrestore(apic_dev->state_lock, flags);
            break;
        case DFR_OFFSET:
+           flags = v3_lock_irqsave(apic_dev->state_lock);
            apic->dst_fmt.val = op_val;
+           v3_unlock_irqrestore(apic_dev->state_lock, flags);
            break;
        case SPURIOUS_INT_VEC_OFFSET:
            apic->spurious_int.val = op_val;
@@ -1344,18 +1417,19 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
            tmp_icr = apic->int_cmd;
 
            //      V3_Print("apic %u: core %u: sending cmd 0x%llx to apic %u\n", 
-           //       apic->lapic_id.val, core->cpu_id,
+           //       apic->lapic_id.val, core->vcpu_id,
            //       apic->int_cmd.val, apic->int_cmd.dst);
 
            if (route_ipi(apic_dev, apic, &tmp_icr) == -1) { 
                PrintError("IPI Routing failure\n");
                return -1;
            }
+
            break;
        }
        case INT_CMD_HI_OFFSET: {
            apic->int_cmd.hi = op_val;
-           V3_Print("apic %u: core %u: writing command high=0x%x\n", apic->lapic_id.val, core->cpu_id,apic->int_cmd.hi);
+           V3_Print("apic %u: core %u: writing command high=0x%x\n", apic->lapic_id.val, core->vcpu_id,apic->int_cmd.hi);
 
            break;
        }
@@ -1364,12 +1438,12 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
        case SEOI_OFFSET:
        default:
            PrintError("apic %u: core %u: Write to Unhandled APIC Register: %x (ignored)\n", 
-                      apic->lapic_id.val, core->cpu_id, (uint32_t)reg_addr);
+                      apic->lapic_id.val, core->vcpu_id, (uint32_t)reg_addr);
 
            return -1;
     }
 
-    PrintDebug("apic %u: core %u: Write finished\n", apic->lapic_id.val, core->cpu_id);
+    PrintDebug("apic %u: core %u: Write finished\n", apic->lapic_id.val, core->vcpu_id);
 
     return length;
 
@@ -1382,11 +1456,18 @@ static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, u
 
 static int apic_intr_pending(struct guest_info * core, void * private_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
-    int req_irq = get_highest_irr(apic);
-    int svc_irq = get_highest_isr(apic);
+    struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
+    int req_irq = 0;    
+    int svc_irq = 0;
+
+    // Activate all queued IRQ entries
+    drain_irq_entries(apic);
+
+    // Check for newly activated entries
+    req_irq = get_highest_irr(apic);
+    svc_irq = get_highest_isr(apic);
 
-    //    PrintDebug("apic %u: core %u: req_irq=%d, svc_irq=%d\n",apic->lapic_id.val,info->cpu_id,req_irq,svc_irq);
+    //    PrintDebug("apic %u: core %u: req_irq=%d, svc_irq=%d\n",apic->lapic_id.val,info->vcpu_id,req_irq,svc_irq);
 
     if ((req_irq >= 0) && 
        (req_irq > svc_irq)) {
@@ -1400,7 +1481,7 @@ static int apic_intr_pending(struct guest_info * core, void * private_data) {
 
 static int apic_get_intr_number(struct guest_info * core, void * private_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
+    struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
     int req_irq = get_highest_irr(apic);
     int svc_irq = get_highest_isr(apic);
 
@@ -1439,25 +1520,16 @@ int v3_apic_raise_intr(struct v3_vm_info * vm, uint32_t irq, uint32_t dst, void
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)
        (((struct vm_device*)dev_data)->private_data);
     struct apic_state * apic = &(apic_dev->apics[dst]); 
-    int do_xcall;
 
     PrintDebug("apic %u core ?: raising interrupt IRQ %u (dst = %u).\n", apic->lapic_id.val, irq, dst); 
 
-    do_xcall = activate_apic_irq(apic, irq);
+    add_apic_irq_entry(apic, irq);
 
-    if (do_xcall < 0) { 
-       PrintError("Failed to activate apic irq\n");
-       return -1;
-    }
-    
-    if (do_xcall > 0 && (V3_Get_CPU() != dst)) {
-#ifdef CONFIG_MULTITHREAD_OS
+#ifdef V3_CONFIG_MULTITHREAD_OS   
+    if ((V3_Get_CPU() != dst)) {
        v3_interrupt_cpu(vm, dst, 0);
-#else
-       V3_ASSERT(0);
-#endif
-
     }
+#endif
 
     return 0;
 }
@@ -1466,7 +1538,7 @@ int v3_apic_raise_intr(struct v3_vm_info * vm, uint32_t irq, uint32_t dst, void
 
 static int apic_begin_irq(struct guest_info * core, void * private_data, int irq) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
+    struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
     int major_offset = (irq & ~0x00000007) >> 3;
     int minor_offset = irq & 0x00000007;
     uint8_t *req_location = apic->int_req_reg + major_offset;
@@ -1481,7 +1553,7 @@ static int apic_begin_irq(struct guest_info * core, void * private_data, int irq
     } else {
        // do nothing... 
        //PrintDebug("apic %u: core %u: begin irq for %d ignored since I don't own it\n",
-       //         apic->lapic_id.val, core->cpu_id, irq);
+       //         apic->lapic_id.val, core->vcpu_id, irq);
     }
 
     return 0;
@@ -1497,7 +1569,7 @@ static void apic_update_time(struct guest_info * core,
                             uint64_t cpu_cycles, uint64_t cpu_freq, 
                             void * priv_data) {
     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
-    struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
+    struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
 
     // The 32 bit GCC runtime is a pile of shit
 #ifdef __V3_64BIT__
@@ -1516,7 +1588,7 @@ static void apic_update_time(struct guest_info * core,
     if ((apic->tmr_init_cnt == 0) || 
        ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
          (apic->tmr_cur_cnt == 0))) {
-       //PrintDebug("apic %u: core %u: APIC timer not yet initialized\n",apic->lapic_id.val,info->cpu_id);
+       //PrintDebug("apic %u: core %u: APIC timer not yet initialized\n",apic->lapic_id.val,info->vcpu_id);
        return;
     }
 
@@ -1548,7 +1620,7 @@ static void apic_update_time(struct guest_info * core,
            break;
        default:
            PrintError("apic %u: core %u: Invalid Timer Divider configuration\n",
-                      apic->lapic_id.val, core->cpu_id);
+                      apic->lapic_id.val, core->vcpu_id);
            return;
     }
 
@@ -1563,18 +1635,18 @@ static void apic_update_time(struct guest_info * core,
 
        // raise irq
        PrintDebug("apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n",
-                  apic->lapic_id.val, core->cpu_id,
+                  apic->lapic_id.val, core->vcpu_id,
                   apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
 
        if (apic_intr_pending(core, priv_data)) {
            PrintDebug("apic %u: core %u: Overriding pending IRQ %d\n", 
-                      apic->lapic_id.val, core->cpu_id, 
+                      apic->lapic_id.val, core->vcpu_id, 
                       apic_get_intr_number(core, priv_data));
        }
 
        if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
            PrintError("apic %u: core %u: Could not raise Timer interrupt\n",
-                      apic->lapic_id.val, core->cpu_id);
+                      apic->lapic_id.val, core->vcpu_id);
        }
     
        if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
@@ -1645,6 +1717,7 @@ static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
                                                  sizeof(struct apic_state) * vm->num_cores);
 
     apic_dev->num_apics = vm->num_cores;
+    v3_lock_init(&(apic_dev->state_lock));
 
     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, apic_dev);
 
@@ -1673,12 +1746,12 @@ static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
            return -1;
        }
 
-       v3_hook_full_mem(vm, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, apic_dev);
+       v3_hook_full_mem(vm, core->vcpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, apic_dev);
 
        PrintDebug("apic %u: (setup device): done, my id is %u\n", i, apic->lapic_id.val);
     }
 
-#ifdef CONFIG_DEBUG_APIC
+#ifdef V3_CONFIG_DEBUG_APIC
     for (i = 0; i < vm->num_cores; i++) {
        struct apic_state * apic = &(apic_dev->apics[i]);
        PrintDebug("apic: sanity check: apic %u (at %p) has id %u and msr value %llx and core at %p\n",
index b720c6b..e9556c8 100644 (file)
 #include <devices/console.h>
 
 
-#if CONFIG_DEBUG_CGA >= 2
+#if V3_CONFIG_DEBUG_CGA >= 2
 #define PrintVerbose PrintDebug
 #else
 #define PrintVerbose(fmt, args...)
 #endif
-#if CONFIG_DEBUG_CGA == 0
+#if V3_CONFIG_DEBUG_CGA == 0
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -443,7 +443,7 @@ static void passthrough_out(uint16_t port, const void * src, uint_t length) {
     }
 }
 
-#if CONFIG_DEBUG_CGA >= 2
+#if V3_CONFIG_DEBUG_CGA >= 2
 static unsigned long get_value(const void *ptr, int len) {
   unsigned long value = 0;
 
index 629b4ed..f7fe7ec 100644 (file)
@@ -23,7 +23,7 @@
 #include <interfaces/vmm_file.h>
 #include <palacios/vm_guest.h>
 
-#ifndef CONFIG_DEBUG_FILEDISK
+#ifndef V3_CONFIG_DEBUG_FILEDISK
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index 73b778a..8fd525c 100644 (file)
 #include <palacios/vmm_dev_mgr.h>
 #include <palacios/vm_guest_mem.h>
 
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
 #include <interfaces/vmm_host_dev.h>
 #endif
 
-#ifndef CONFIG_DEBUG_GENERIC
+#ifndef V3_CONFIG_DEBUG_GENERIC
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -45,7 +45,7 @@ typedef enum {GENERIC_IGNORE,
 
 struct generic_internal {
     enum {GENERIC_PHYSICAL, GENERIC_HOST} forward_type;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
     v3_host_dev_t                         host_dev;
 #endif
     struct vm_device                      *dev; // me
@@ -88,7 +88,7 @@ static int generic_write_port_passthrough(struct guest_info * core,
            }
            return length;
            break;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
        case GENERIC_HOST:
            if (state->host_dev) { 
                return v3_host_dev_write_io(state->host_dev,port,src,length);
@@ -109,7 +109,7 @@ static int generic_write_port_print_and_passthrough(struct guest_info * core, ui
     uint_t i;
     int rc;
 
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct generic_internal *state = (struct generic_internal *) priv_data;
 #endif
 
@@ -162,7 +162,7 @@ static int generic_read_port_passthrough(struct guest_info * core,
            }
            return length;
            break;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
        case GENERIC_HOST:
            if (state->host_dev) { 
                return v3_host_dev_read_io(state->host_dev,port,dst,length);
@@ -183,7 +183,7 @@ static int generic_read_port_print_and_passthrough(struct guest_info * core, uin
     uint_t i;
     int rc;
 
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct generic_internal *state = (struct generic_internal *) priv_data;
 #endif
 
@@ -217,7 +217,7 @@ static int generic_read_port_ignore(struct guest_info * core, uint16_t port, voi
 static int generic_read_port_print_and_ignore(struct guest_info * core, uint16_t port, void * src, 
                                              uint_t length, void * priv_data) {
    
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct generic_internal *state = (struct generic_internal *) priv_data;
 #endif
 
@@ -242,7 +242,7 @@ static int generic_write_port_print_and_ignore(struct guest_info * core, uint16_
                                              uint_t length, void * priv_data) {
     int i;
 
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct generic_internal *state = (struct generic_internal *) priv_data;
 #endif
 
@@ -278,7 +278,7 @@ static int generic_write_mem_passthrough(struct guest_info * core,
            memcpy(V3_VAddr((void*)gpa),src,len);
            return len;
            break;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
        case GENERIC_HOST:
            if (state->host_dev) { 
                return v3_host_dev_write_mem(state->host_dev,gpa,src,len);
@@ -300,7 +300,7 @@ static int generic_write_mem_print_and_passthrough(struct guest_info * core,
                                                   uint_t              len,
                                                   void              * priv)
 {
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct vm_device *dev = (struct vm_device *) priv;
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 #endif
@@ -332,7 +332,7 @@ static int generic_write_mem_print_and_ignore(struct guest_info * core,
                                              uint_t              len,
                                              void              * priv)
 {
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct vm_device *dev = (struct vm_device *) priv;
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 #endif
@@ -359,7 +359,7 @@ static int generic_read_mem_passthrough(struct guest_info * core,
            memcpy(dst,V3_VAddr((void*)gpa),len);
            return len;
            break;
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
        case GENERIC_HOST:
            if (state->host_dev) { 
                return v3_host_dev_read_mem(state->host_dev,gpa,dst,len);
@@ -382,7 +382,7 @@ static int generic_read_mem_print_and_passthrough(struct guest_info * core,
                                                  uint_t              len,
                                                  void              * priv)
 {
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct vm_device *dev = (struct vm_device *) priv;
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 #endif
@@ -405,7 +405,7 @@ static int generic_read_mem_ignore(struct guest_info * core,
                                   uint_t              len,
                                   void              * priv)
 {
-#ifdef CONFIG_DEBUG_GENERIC
+#ifdef V3_CONFIG_DEBUG_GENERIC
     struct vm_device *dev = (struct vm_device *) priv;
     struct generic_internal *state = (struct generic_internal *) dev->private_data;
 #endif
@@ -439,7 +439,7 @@ static int generic_free(struct generic_internal * state) {
     
     PrintDebug("generic (%s): deinit_device\n", state->name);
     
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
     if (state->host_dev) { 
        v3_host_dev_close(state->host_dev);
        state->host_dev=0;
@@ -622,7 +622,7 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct generic_internal * state = NULL;
     char * dev_id = v3_cfg_val(cfg, "ID");
     char * forward = v3_cfg_val(cfg, "forward");
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
     char * host_dev = v3_cfg_val(cfg, "hostdev");
 #endif
     v3_cfg_tree_t * port_cfg = v3_cfg_subtree(cfg, "ports");
@@ -645,7 +645,7 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        if (!strcasecmp(forward,"physical_device")) { 
            state->forward_type=GENERIC_PHYSICAL;
        } else if (!strcasecmp(forward,"host_device")) { 
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
            state->forward_type=GENERIC_HOST;
 #else
            PrintError("generic (%s): cannot configure host device since host device support is not built in\n", state->name);
@@ -670,7 +670,7 @@ static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     state->dev=dev;
 
 
-#ifdef CONFIG_HOST_DEVICE
+#ifdef V3_CONFIG_HOST_DEVICE
     if (state->forward_type==GENERIC_HOST) { 
        if (!host_dev) { 
            PrintError("generic (%s): host forwarding requested, but no host device given\n", state->name);
index ef42d61..3ef7d4d 100644 (file)
@@ -26,7 +26,7 @@
 #include "ide-types.h"
 #include "atapi-types.h"
 
-#ifndef CONFIG_DEBUG_IDE
+#ifndef V3_CONFIG_DEBUG_IDE
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -356,7 +356,7 @@ static int dma_write(struct guest_info * core, struct ide_internal * ide, struct
 #include "ata.h"
 
 
-#ifdef CONFIG_DEBUG_IDE
+#ifdef V3_CONFIG_DEBUG_IDE
 static void print_prd_table(struct ide_internal * ide, struct ide_channel * channel) {
     struct ide_dma_prd prd_entry;
     int index = 0;
@@ -400,7 +400,7 @@ static int dma_read(struct guest_info * core, struct ide_internal * ide, struct
     // Read in the data buffer....
     // Read a sector/block at a time until the prd entry is full.
 
-#ifdef CONFIG_DEBUG_IDE
+#ifdef V3_CONFIG_DEBUG_IDE
     print_prd_table(ide, channel);
 #endif
 
index b9375a8..3579fde 100644 (file)
@@ -23,7 +23,7 @@
 #include <devices/apic.h>
 #include <palacios/vm_guest.h>
 
-#ifndef CONFIG_DEBUG_IO_APIC
+#ifndef V3_CONFIG_DEBUG_IO_APIC
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index 5eb7d6b..e974503 100644 (file)
@@ -28,7 +28,7 @@
 #include <palacios/vm_guest.h>
 
 
-#ifndef CONFIG_DEBUG_KEYBOARD
+#ifndef V3_CONFIG_DEBUG_KEYBOARD
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -335,7 +335,7 @@ static int pull_from_output_queue(struct keyboard_internal * state, uint8_t * va
 
 
 #include <palacios/vmm_telemetry.h>
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
 #include <palacios/vmm_symmod.h>
 #endif
 
@@ -353,7 +353,7 @@ static int key_event_handler(struct v3_vm_info * vm,
        }
        //      PrintGuestPageTables(info, info->shdw_pg_state.guest_cr3);
     } 
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
     else if (evt->scan_code == 0x43) { // F9 Sym test
        struct guest_info * core = &(vm->cores[0]);
        PrintDebug("Testing sym call\n");
@@ -385,13 +385,13 @@ static int key_event_handler(struct v3_vm_info * vm,
        v3_dbg_enable ^= 1;
 
     } 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
 
     else if (evt->scan_code == 0x41) { // F7 telemetry dump
        v3_print_telemetry(vm);
     } 
 #endif
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
     else if (evt->scan_code == 0x40) { // F6 Test symmod load
        v3_load_sym_capsule(vm, "lnx_test");
     }
index 7e26b30..d47243a 100644 (file)
@@ -26,7 +26,7 @@
 
 
 
-#ifndef CONFIG_DEBUG_VIRTIO_BLK
+#ifndef V3_CONFIG_DEBUG_VIRTIO_BLK
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index 07c7d7b..3c519aa 100644 (file)
@@ -25,7 +25,7 @@
 #include <devices/lnx_virtio_pci.h>
 #include <palacios/vm_guest_mem.h>
 #include <palacios/vmm_sprintf.h>
-#include <palacios/vmm_vnet.h>
+#include <vnet/vnet.h>
 #include <palacios/vmm_lock.h>
 #include <palacios/vmm_util.h>
 #include <devices/pci.h>
 #include <palacios/vmm_time.h>
 
 
-#ifndef CONFIG_DEBUG_VIRTIO_NET
+#ifndef V3_CONFIG_DEBUG_VIRTIO_NET
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
 
+#ifndef V3_CONFIG_VNET
+static int net_debug = 0;
+#endif
+
 #define TX_QUEUE_SIZE 4096
 #define RX_QUEUE_SIZE 4096
 #define CTRL_QUEUE_SIZE 64
@@ -117,13 +121,17 @@ struct virtio_net_state {
     struct vm_device * dev;
     struct pci_device * pci_dev; 
     int io_range_size;
+
+    uint16_t status;
     
     struct virtio_queue rx_vq;         /* idx 0*/
     struct virtio_queue tx_vq;         /* idx 1*/
     struct virtio_queue ctrl_vq;       /* idx 2*/
 
+    uint8_t mergeable_rx_bufs;
+
     struct v3_timer * timer;
-    void * poll_thread;
+    struct vnet_thread * poll_thread;
 
     struct nic_statistics stats;
 
@@ -165,11 +173,13 @@ static int virtio_init_state(struct virtio_net_state * virtio)
     virtio->ctrl_vq.cur_avail_idx = 0;
 
     virtio->virtio_cfg.pci_isr = 0;
+
+    virtio->mergeable_rx_bufs = 0;
        
     virtio->virtio_cfg.host_features = 0 | (1 << VIRTIO_NET_F_MAC);
-       //                                 (1 << VIRTIO_NET_F_GSO) | 
-       //                                 (1 << VIRTIO_NET_F_HOST_UFO) | 
-               //                         (1 << VIRTIO_NET_F_HOST_TSO4);
+    if(virtio->mergeable_rx_bufs) {
+       virtio->virtio_cfg.host_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
+    }
 
     if ((v3_lock_init(&(virtio->rx_lock)) == -1) ||
        (v3_lock_init(&(virtio->tx_lock)) == -1)){
@@ -185,7 +195,7 @@ static int tx_one_pkt(struct guest_info * core,
 {
     uint8_t * buf = NULL;
     uint32_t len = buf_desc->length;
-    int synchronize = 1; // (virtio->tx_notify == 1)?1:0;
+    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");
@@ -193,7 +203,7 @@ static int tx_one_pkt(struct guest_info * core,
     }
 
     V3_Net_Print(2, "Virtio-NIC: virtio_tx: size: %d\n", len);
-    if(v3_net_debug >= 4){
+    if(net_debug >= 4){
        v3_hexdump(buf, len, NULL, 0);
     }
 
@@ -214,8 +224,7 @@ static inline int copy_data_to_desc(struct guest_info * core,
                  struct vring_desc * desc, 
                  uchar_t * buf, 
                  uint_t buf_len,
-                 uint_t offset)
-{
+                 uint_t dst_offset){
     uint32_t len;
     uint8_t * desc_buf = NULL;
 
@@ -223,8 +232,8 @@ static inline int copy_data_to_desc(struct guest_info * core,
        PrintDebug("Could not translate buffer address\n");
        return -1;
     }
-    len = (desc->length < buf_len)?(desc->length - offset):buf_len;
-    memcpy(desc_buf+offset, buf, len);
+    len = (desc->length < buf_len)?(desc->length - dst_offset):buf_len;
+    memcpy(desc_buf+dst_offset, buf, len);
 
     return len;
 }
@@ -243,11 +252,15 @@ static inline int get_desc_count(struct virtio_queue * q, int index) {
 }
 
 static inline void enable_cb(struct virtio_queue *queue){
-    queue->used->flags &= ~ VRING_NO_NOTIFY_FLAG;
+    if(queue->used){
+       queue->used->flags &= ~ VRING_NO_NOTIFY_FLAG;
+    }
 }
 
 static inline void disable_cb(struct virtio_queue *queue) {
-    queue->used->flags |= VRING_NO_NOTIFY_FLAG;
+    if(queue->used){
+       queue->used->flags |= VRING_NO_NOTIFY_FLAG;
+    }
 }
 
 static int handle_pkt_tx(struct guest_info * core, 
@@ -255,7 +268,7 @@ static int handle_pkt_tx(struct guest_info * core,
 {
     struct virtio_queue *q = &(virtio_state->tx_vq);
     int txed = 0;
-    unsigned long flags;
+    unsigned long flags; 
 
     if (!q->ring_avail_addr) {
        return -1;
@@ -263,7 +276,7 @@ static int handle_pkt_tx(struct guest_info * core,
 
     flags = v3_lock_irqsave(virtio_state->tx_lock);
     while (q->cur_avail_idx != q->avail->index) {
-       struct virtio_net_hdr *hdr = NULL;
+       struct virtio_net_hdr_mrg_rxbuf * hdr = NULL;
        struct vring_desc * hdr_desc = NULL;
        addr_t hdr_addr = 0;
        uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
@@ -280,15 +293,20 @@ static int handle_pkt_tx(struct guest_info * core,
            goto exit_error;
        }
 
-       hdr = (struct virtio_net_hdr *)hdr_addr;
+       hdr = (struct virtio_net_hdr_mrg_rxbuf *)hdr_addr;
        desc_idx = hdr_desc->next;
 
+       V3_Net_Print(2, "Virtio NIC: TX hdr count : %d\n", hdr->num_buffers);
+
        /* here we assumed that one ethernet pkt is not splitted into multiple buffer */        
        struct vring_desc * buf_desc = &(q->desc[desc_idx]);
        if (tx_one_pkt(core, virtio_state, buf_desc) == -1) {
            PrintError("Virtio NIC: Error handling nic operation\n");
            goto exit_error;
        }
+       if(buf_desc->next & VIRTIO_NEXT_FLAG){
+           V3_Net_Print(2, "Virtio NIC: TX more buffer need to read\n");
+       }
            
        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 = buf_desc->length; /* What do we set this to???? */
@@ -301,7 +319,6 @@ static int handle_pkt_tx(struct guest_info * core,
 
     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
 
-    //virtio_state->virtio_cfg.pci_isr == 0 && 
     if (txed && !(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
        v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
        virtio_state->virtio_cfg.pci_isr = 0x1;
@@ -397,7 +414,7 @@ static int virtio_io_write(struct guest_info *core,
                    virtio_setup_queue(core, virtio, &virtio->tx_vq, pfn, page_addr);
                    if(virtio->tx_notify == 0){
                        disable_cb(&virtio->tx_vq);
-                       V3_THREAD_WAKEUP(virtio->poll_thread);
+                       vnet_thread_wakeup(virtio->poll_thread);
                    }
                    break;
                case 2:
@@ -548,13 +565,11 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
     struct virtio_queue * q = &(virtio->rx_vq);
     struct virtio_net_hdr_mrg_rxbuf hdr;
-    uint32_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
     uint32_t data_len;
-    //uint32_t offset = 0;
     unsigned long flags;
 
     V3_Net_Print(2, "Virtio-NIC: virtio_rx: size: %d\n", size);
-    if(v3_net_debug >= 4){
+    if(net_debug >= 4){
        v3_hexdump(buf, size, NULL, 0);
     }
 
@@ -575,6 +590,7 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
        uint16_t hdr_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
        struct vring_desc * hdr_desc = NULL;
        struct vring_desc * buf_desc = NULL;
+       uint32_t hdr_len = 0;
        uint32_t len;
 
        hdr_desc = &(q->desc[hdr_idx]);
@@ -584,44 +600,64 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
            goto err_exit;
        }
 
-#if 0 /* merged buffer */
-       for(buf_idx = hdr_desc->next; offset < data_len; buf_idx = q->desc[hdr_idx].next) {
-           uint32_t len = 0;
-           buf_desc = &(q->desc[buf_idx]);
+       hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
 
-           len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf + offset, data_len - offset, 0);     
-           offset += len;
-           if (offset < data_len) {
-               buf_desc->flags = VIRTIO_NEXT_FLAG;             
-           }
-           buf_desc->length = len;
-           hdr.num_buffers ++;
-       }
-       buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
-       memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr_mrg_rxbuf));
-#endif
+       if(virtio->mergeable_rx_bufs){/* merged buffer */
+           uint32_t offset = 0;
+           len = 0;
+           hdr.num_buffers = 0;
 
-       hdr.num_buffers = 1;
-       memcpy((void *)hdr_addr, &hdr, sizeof(struct virtio_net_hdr_mrg_rxbuf));
-       if (data_len == 0) {
+           hdr_desc = &(q->desc[buf_idx]);
            hdr_desc->flags &= ~VIRTIO_NEXT_FLAG;
-       }
 
-       buf_idx = hdr_desc->next;
-       buf_desc = &(q->desc[buf_idx]);
-       len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf, data_len, 0);           
-       if (len < data_len) {
-           V3_Net_Print(2, "Virtio NIC: ring buffer len less than pkt size, merged buffer not supported\n");
-           virtio->stats.rx_dropped ++;
-               
-           goto err_exit;
-       }
-       buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
+           len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, hdr_desc, buf, data_len, hdr_len);
+           offset += 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 = data_len + hdr_len; /* This should be the total length of data sent to guest (header+pkt_data) */
-       q->used->index++;
-       q->cur_avail_idx++;
+           hdr.num_buffers ++;
+           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 = hdr_len + len;
+           q->cur_avail_idx ++;
+
+           while(offset < data_len) {
+               buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
+               buf_desc = &(q->desc[buf_idx]);
+
+               len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf + offset, data_len - offset, 0);     
+               if (len <= 0){
+                   V3_Net_Print(2, "Virtio NIC:merged buffer, %d buffer size %d\n", hdr.num_buffers, data_len);
+                   virtio->stats.rx_dropped ++;
+                   goto err_exit;
+               }
+               offset += len;
+               buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
+
+               hdr.num_buffers ++;
+               q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
+               q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].length = len;
+               q->cur_avail_idx ++;   
+           }
+           q->used->index += hdr.num_buffers;
+           copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, hdr_desc, (uchar_t *)&hdr, hdr_len, 0);
+       }else{
+           hdr_desc = &(q->desc[buf_idx]);
+           copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, hdr_desc, (uchar_t *)&hdr, hdr_len, 0);
+
+           buf_idx = hdr_desc->next;
+           buf_desc = &(q->desc[buf_idx]);
+           len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), virtio, buf_desc, buf, data_len, 0);       
+           if (len < data_len) {
+               V3_Net_Print(2, "Virtio NIC: ring buffer len less than pkt size, merged buffer not supported, buffer size %d\n", len);
+               virtio->stats.rx_dropped ++;
+               
+               goto err_exit;
+           }
+           buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
+               
+           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 = data_len + hdr_len; /* This should be the total length of data sent to guest (header+pkt_data) */
+           q->used->index++;
+           q->cur_avail_idx++;
+       } 
 
        virtio->stats.rx_pkts ++;
        virtio->stats.rx_bytes += size;
@@ -632,15 +668,12 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
        /* kick guest to refill the queue */
        virtio->virtio_cfg.pci_isr = 0x1;       
        v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
-       v3_interrupt_cpu(virtio->virtio_dev->vm, virtio->virtio_dev->vm->cores[0].cpu_id, 0);
+       v3_interrupt_cpu(virtio->virtio_dev->vm, virtio->virtio_dev->vm->cores[0].pcpu_id, 0);
        virtio->stats.rx_interrupts ++;
        
        goto err_exit;
     }
 
-    V3_Net_Print(2, "pci_isr %d, virtio flags %d\n",  virtio->virtio_cfg.pci_isr, q->avail->flags);
-    //virtio->virtio_cfg.pci_isr == 0 && 
-
     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
        V3_Net_Print(2, "Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
 
@@ -653,9 +686,9 @@ static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
     v3_unlock_irqrestore(virtio->rx_lock, flags);
 
     /* notify guest if it is in guest mode */
-    /* ISSUE: What is gonna happen if guest thread is running on the same core as this thread? */
-    if(virtio->rx_notify == 1){
-       v3_interrupt_cpu(virtio->virtio_dev->vm, virtio->virtio_dev->vm->cores[0].cpu_id, 0);
+    if(virtio->rx_notify == 1 && 
+       V3_Get_CPU() != virtio->virtio_dev->vm->cores[0].pcpu_id){
+       v3_interrupt_cpu(virtio->virtio_dev->vm, virtio->virtio_dev->vm->cores[0].pcpu_id, 0);
     }
 
     return 0;
@@ -700,7 +733,7 @@ static int virtio_tx_flush(void * args){
            handle_pkt_tx(&(virtio->vm->cores[0]), virtio);
            v3_yield(NULL);
        }else {
-           V3_THREAD_SLEEP();
+           vnet_thread_sleep(-1);
        }
     }
 
@@ -779,6 +812,7 @@ static int register_dev(struct virtio_dev_state * virtio,
     return 0;
 }
 
+
 #define RATE_UPPER_THRESHOLD 10  /* 10000 pkts per second, around 100Mbits */
 #define RATE_LOWER_THRESHOLD 1
 #define PROFILE_PERIOD 10000 /*us*/
@@ -790,10 +824,13 @@ static void virtio_nic_timer(struct guest_info * core,
     uint64_t period_us;
     static int profile_ms = 0;
 
+    if(!net_state->status){ /* VNIC is not in working status */
+       return;
+    }
+
     period_us = (1000*cpu_cycles)/cpu_freq;
     net_state->past_us += period_us;
 
-#if 0
     if(net_state->past_us > PROFILE_PERIOD){ 
        uint32_t tx_rate, rx_rate;
        
@@ -807,7 +844,7 @@ static void virtio_nic_timer(struct guest_info * core,
            V3_Print("Virtio NIC: Switch TX to VMM driven mode\n");
            disable_cb(&(net_state->tx_vq));
            net_state->tx_notify = 0;
-           V3_THREAD_WAKEUP(net_state->poll_thread);
+           vnet_thread_wakeup(net_state->poll_thread);
        }
 
        if(tx_rate < RATE_LOWER_THRESHOLD && net_state->tx_notify == 0){
@@ -828,7 +865,6 @@ static void virtio_nic_timer(struct guest_info * core,
 
        net_state->past_us = 0;
     }
-#endif
 
     profile_ms += period_us/1000;
     if(profile_ms > 20000){
@@ -867,11 +903,15 @@ static int connect_fn(struct v3_vm_info * info,
        
     net_state->timer = v3_add_timer(&(info->cores[0]),&timer_ops,net_state);
 
+    PrintError("net_state 0x%p\n", (void *)net_state);
+
     ops->recv = virtio_rx;
     ops->frontend_data = net_state;
     memcpy(ops->fnt_mac, virtio->mac, ETH_ALEN);
 
-    net_state->poll_thread = V3_CREATE_THREAD(virtio_tx_flush, (void *)net_state, "Virtio_Poll");
+    net_state->poll_thread = vnet_start_thread(virtio_tx_flush, (void *)net_state, "Virtio_Poll");
+
+    net_state->status = 1;
 
     return 0;
 }
index 87f158d..e604b9e 100644 (file)
 #include <palacios/vmm_dev_mgr.h>
 #include <palacios/vm_guest_mem.h>
 #include <devices/lnx_virtio_pci.h>
-#include <palacios/vmm_vnet.h>
+#include <vnet/vnet.h>
 #include <palacios/vmm_sprintf.h>
 #include <devices/pci.h>
 
 
-#ifndef CONFIG_DEBUG_LINUX_VIRTIO_VNET
+#ifndef V3_CONFIG_DEBUG_LINUX_VIRTIO_VNET
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index 78ddaa2..ec93d7f 100644 (file)
@@ -34,7 +34,7 @@
 #include <palacios/vmm_string.h>
 #include <palacios/vmm_cpuid.h>
 
-#ifndef CONFIG_DEBUG_MCHECK
+#ifndef V3_CONFIG_DEBUG_MCHECK
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
similarity index 97%
rename from palacios/src/palacios/vmm_mptable.c
rename to palacios/src/devices/mptable.c
index 4b21fcc..3b6a463 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <palacios/vmm.h>
-#include <palacios/vmm_mptable.h>
 #include <palacios/vmm_string.h>
 #include <palacios/vm_guest_mem.h>
 
@@ -364,7 +363,20 @@ static int write_mptable(void * target, uint32_t numcores) {
     ioapic->ioapic_flags.en = 1;
     ioapic->ioapic_address = IOAPIC_ADDR;
 
+
+    // The MPTABLE IRQ mappings are kind of odd. 
+    // We don't include a bus IRQ 2, and instead remap Bus IRQ 0 to dest irq 2
+
+
     for (irq = 0; irq < 16; irq++) { 
+       uint8_t dst_irq = irq;
+
+       if (irq == 0) {
+           dst_irq = 2;
+       } else if (irq == 2) {
+           continue;
+       }
+
        interrupt = (struct mp_table_io_interrupt_assignment *)cur;
        memset((void *)interrupt, 0, sizeof(struct mp_table_io_interrupt_assignment));
 
@@ -375,7 +387,7 @@ static int write_mptable(void * target, uint32_t numcores) {
        interrupt->source_bus_id = 0;
        interrupt->source_bus_irq = irq;
        interrupt->dest_ioapic_id = numcores;
-       interrupt->dest_ioapic_intn = irq;
+       interrupt->dest_ioapic_intn = dst_irq;
 
        cur += sizeof(struct mp_table_io_interrupt_assignment);
     }
@@ -397,8 +409,7 @@ static int write_mptable(void * target, uint32_t numcores) {
     return 0;
 }
 
-
-int v3_inject_mptable(struct v3_vm_info * vm) {
+static int mptable_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     void * target = NULL;
 
     if (v3_gpa_to_hva(&(vm->cores[0]), BIOS_MP_TABLE_DEFAULT_LOCATION, (addr_t *)&target) == -1) { 
@@ -441,3 +452,7 @@ int v3_inject_mptable(struct v3_vm_info * vm) {
 
     return 0;
 }
+
+
+
+device_register("MPTABLE", mptable_init)
index 939bd28..ad0bda8 100644 (file)
@@ -28,7 +28,7 @@
 #include <palacios/vm_guest.h>
 #include <palacios/vmm_sprintf.h>
 
-#ifndef CONFIG_DEBUG_NE2K
+#ifndef V3_CONFIG_DEBUG_NE2K
 #undef PrintDebug
 #define PrintDebug(fmts, args...)
 #endif
@@ -347,7 +347,7 @@ static int ne2k_update_irq(struct ne2k_state * nic_state) {
 
 static int tx_one_pkt(struct ne2k_state * nic_state, uchar_t *pkt, uint32_t length) {
        
-#ifdef CONFIG_DEBUG_NE2K
+#ifdef V3_CONFIG_DEBUG_NE2K
     PrintDebug("NE2000: Send Packet:\n");
     v3_hexdump(pkt, length, NULL, 0);
 #endif    
@@ -484,7 +484,7 @@ static int rx_one_pkt(struct ne2k_state * nic_state, const uchar_t * pkt,  uint3
 static int ne2k_rx(uint8_t * buf, uint32_t size, void * private_data){
     struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
   
-#ifdef CONFIG_DEBUG_NE2K
+#ifdef V3_CONFIG_DEBUG_NE2K
     PrintDebug("\nNe2k: Packet Received:\n");
     v3_hexdump(buf, size, NULL, 0);
 #endif    
index 9a1509a..a4c4fc8 100644 (file)
@@ -21,7 +21,7 @@
 #include <palacios/vmm_dev_mgr.h>
 #include <interfaces/vmm_socket.h>
 
-#ifndef CONFIG_DEBUG_IDE
+#ifndef V3_CONFIG_DEBUG_IDE
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index 5eec5e6..518fa75 100644 (file)
@@ -25,7 +25,7 @@
 #include <palacios/vmm_sprintf.h>
 #include <interfaces/vmm_packet.h>
 
-#ifndef CONFIG_DEBUG_NIC_BRIDGE
+#ifndef V3_CONFIG_DEBUG_NIC_BRIDGE
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -39,7 +39,7 @@ static int bridge_send(uint8_t * buf, uint32_t len,
                       int synchronize,
                       void * private_data) {
 
-#ifdef CONFIG_DEBUG_NIC_BRIDGE
+#ifdef V3_CONFIG_DEBUG_NIC_BRIDGE
     {
        PrintDebug("NIC Bridge: send pkt size: %d\n", len);
        v3_hexdump(buf, len, NULL, 0);
@@ -54,7 +54,7 @@ static int packet_input(struct v3_vm_info * vm,
                        void * private_data) {
     struct nic_bridge_state * bridge = (struct nic_bridge_state *)private_data;
  
-#ifdef CONFIG_DEBUG_NIC_BRIDGE
+#ifdef V3_CONFIG_DEBUG_NIC_BRIDGE
     {
        PrintDebug("NIC Bridge: recv pkt size: %d\n", evt->size);
        v3_hexdump(evt->pkt, evt->size, NULL, 0);
index 785d38b..86ca02e 100644 (file)
@@ -30,7 +30,7 @@
 #include <palacios/vm_guest.h>
 
 
-#ifndef CONFIG_DEBUG_NVRAM
+#ifndef V3_CONFIG_DEBUG_NVRAM
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -127,7 +127,7 @@ struct rtc_stata {
 struct rtc_statb {
     uint8_t        sum    : 1;  // 1=summer (daylight savings)
     uint8_t        h24    : 1;  // 1=24h clock
-    uint8_t        dm     : 1;  // 1=date/time is in bcd, 0=binary
+    uint8_t        dm     : 1;  // 0=date/time is in bcd, 1=binary
     uint8_t        rec    : 1;  // 1=rectangular signal
     uint8_t        ui     : 1;  // 1=update interrupt
     uint8_t        ai     : 1;  // 1=alarm interrupt
@@ -297,7 +297,7 @@ static void update_time(struct nvram_internal * data, uint64_t period_us) {
     uint8_t * houra    = (uint8_t *)&(data->mem_state[NVRAM_REG_HOUR_ALARM]);
     uint8_t hour24;
 
-    uint8_t bcd = (statb->dm == 1);
+    uint8_t bcd = (statb->dm == 0);
     uint8_t carry = 0;
     uint8_t nextday = 0;
     uint32_t  periodic_period;
@@ -659,8 +659,8 @@ static int init_nvram_state(struct v3_vm_info * vm, struct nvram_internal * nvra
     set_memory(nvram, NVRAM_REG_STAT_A, 0x26); 
 
     // RTC status B
-    // 00000100 = not setting, no interrupts, blocked rect signal, bcd mode, 24 hour, normal time
-    set_memory(nvram, NVRAM_REG_STAT_B, 0x06); 
+    // 00000010 = not setting, no interrupts, blocked rect signal, bcd mode (bit 3 = 0), 24 hour, normal time
+    set_memory(nvram, NVRAM_REG_STAT_B, 0x02); 
 
 
     // RTC status C
index 1f4976b..0400751 100644 (file)
@@ -37,7 +37,7 @@
 
 
 
-#ifndef CONFIG_DEBUG_PCI
+#ifndef V3_CONFIG_DEBUG_PCI
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -104,7 +104,7 @@ struct pci_internal {
 
 
 
-#ifdef CONFIG_DEBUG_PCI
+#ifdef V3_CONFIG_DEBUG_PCI
 
 static void pci_dump_state(struct pci_internal * pci_state) {
     struct rb_node * node = v3_rb_first(&(pci_state->bus_list[0].devices));
@@ -922,7 +922,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
     // add the device
     add_device_to_bus(bus, pci_dev);
 
-#ifdef CONFIG_DEBUG_PCI
+#ifdef V3_CONFIG_DEBUG_PCI
     pci_dump_state(pci_state);
 #endif
 
@@ -990,7 +990,7 @@ struct pci_device * v3_pci_register_passthrough_device(struct vm_device * pci,
     // add the device
     add_device_to_bus(bus, pci_dev);
 
-#ifdef CONFIG_DEBUG_PCI
+#ifdef V3_CONFIG_DEBUG_PCI
     pci_dump_state(pci_state);
 #endif
 
index 487ab5c..70dc980 100644 (file)
@@ -57,7 +57,7 @@
 #include <interfaces/vmm_host_dev.h>
 
 
-#ifndef CONFIG_DEBUG_PCI_FRONT
+#ifndef V3_CONFIG_DEBUG_PCI_FRONT
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index 4598707..05e9bda 100644 (file)
@@ -21,7 +21,7 @@
 #include <palacios/vmm_dev_mgr.h>
 
 
-#ifndef CONFIG_DEBUG_RAMDISK
+#ifndef V3_CONFIG_DEBUG_RAMDISK
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index 199d0d7..4ef93df 100644 (file)
@@ -28,7 +28,7 @@
 
 
 
-#ifndef CONFIG_DEBUG_RTL8139
+#ifndef V3_CONFIG_DEBUG_RTL8139
 #undef PrintDebug
 #define PrintDebug(fmts, args...)
 #endif
@@ -1174,7 +1174,7 @@ static int tx_one_packet(struct rtl8139_state * nic_state, int descriptor){
     v3_gpa_to_hva(&(nic_state->vm->cores[0]), (addr_t)pkt_gpa, &hostva);
     pkt = (uchar_t *)hostva;
 
-#ifdef CONFIG_DEBUG_RTL8139
+#ifdef V3_CONFIG_DEBUG_RTL8139
     v3_hexdump(pkt, txsize, NULL, 0);
 #endif
 
index 0efb5cc..f0d405d 100644 (file)
@@ -31,7 +31,7 @@
 #include <devices/serial.h>
 
 
-#ifndef CONFIG_DEBUG_SERIAL
+#ifndef V3_CONFIG_DEBUG_SERIAL
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index 951590e..ec2bba8 100644 (file)
@@ -23,7 +23,7 @@
 #include <palacios/vm_guest.h>
 
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
 #include <palacios/vmm_telemetry.h>
 #endif
 
@@ -60,7 +60,7 @@ struct swap_state {
 
     union swap_header * hdr;
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
     uint32_t pages_in;
     uint32_t pages_out;
 #endif
@@ -164,7 +164,7 @@ static int swap_read(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * pri
        int i = 0;
        // Notify the shadow paging layer
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
        swap->pages_in += length / 4096;
 #endif
 
@@ -219,7 +219,7 @@ static int swap_write(uint8_t * buf,  uint64_t lba, uint64_t num_bytes, void * p
     if ((swap->active == 1) && (offset != 0)) {
        int i = 0;
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
        swap->pages_out += length / 4096;
 #endif
 
@@ -253,7 +253,7 @@ static struct v3_device_ops dev_ops = {
 };
 
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
 static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
     struct vm_device * dev = (struct vm_device *)private_data;
     struct swap_state * swap = (struct swap_state *)(dev->private_data);
@@ -314,7 +314,7 @@ static int swap_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        return -1;
     }
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
     if (vm->enable_telemetry == 1) {
        v3_add_telemetry_cb(vm, telemetry_cb, dev);
     }
index bc83762..dfd51ba 100644 (file)
@@ -24,7 +24,7 @@
 #include <palacios/vmm_hashtable.h>
 
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
 #include <palacios/vmm_telemetry.h>
 #endif
 
@@ -83,7 +83,7 @@ struct swap_state {
     struct v3_dev_blk_ops * ops;
     void * private_data;
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
     uint32_t pages_in;
     uint32_t pages_out;
 #endif
@@ -235,7 +235,7 @@ static int buf_read(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * priv
        swap->unswapped_pages += (length / 4096);
 
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
        swap->pages_in += length / 4096;
 #endif
 
@@ -384,7 +384,7 @@ static int buf_write(uint8_t * buf,  uint64_t lba, uint64_t num_bytes, void * pr
 
        swap->swapped_pages += written_pages;
        
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
        swap->pages_out += length / 4096;
 #endif
 
@@ -506,7 +506,7 @@ static struct v3_device_ops dev_ops = {
 };
 
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
 static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
     struct swap_state * swap = (struct swap_state *)private_data;
 
@@ -583,7 +583,7 @@ static int connect_fn(struct v3_vm_info * vm,
     }
 
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
 
     if (vm->enable_telemetry == 1) {
        v3_add_telemetry_cb(vm, telemetry_cb, swap);
index ce28940..6e5687c 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "vga_regs.h"
 
-#ifndef CONFIG_DEBUG_VGA
+#ifndef V3_CONFIG_DEBUG_VGA
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -1194,7 +1194,7 @@ static int vga_write(struct guest_info * core,
 #endif
                    // rotate data right
                    if (ror) { 
-                       data = (data>>ror) | data<<(8-ror);
+                       data = (data>>ror) | (data<<(8-ror));
                    }
                    
 #if DEBUG_DEEP_MEM
@@ -1384,7 +1384,7 @@ static int vga_write(struct guest_info * core,
                uint8_t data = ((uint8_t *)src)[i];
 
                if (ror) {
-                   data = (data>>ror) | data<<(8-ror);
+                   data = (data>>ror) | (data<<(8-ror));
                }
 
                uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
index 05117e5..ac484a0 100644 (file)
@@ -19,7 +19,7 @@
  */
 //backend device for Virtio NIC
 
-#include <palacios/vmm_vnet.h>
+#include <vnet/vnet.h>
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
 #include <devices/lnx_virtio_pci.h>
@@ -28,7 +28,7 @@
 #include <palacios/vmm_sprintf.h>
 #include <palacios/vmm_ethernet.h>
 
-#ifndef CONFIG_DEBUG_VNET_NIC
+#ifndef V3_CONFIG_DEBUG_VNET_NIC
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -54,7 +54,7 @@ static int vnet_nic_send(uint8_t * buf, uint32_t len,
 
     V3_Net_Print(2, "VNET-NIC: send pkt (size: %d, src_id: %d, src_type: %d)\n", 
                   pkt.size, pkt.src_id, pkt.src_type);
-    if(v3_net_debug >= 4){
+    if(net_debug >= 4){
        v3_hexdump(buf, len, NULL, 0);
     }
 
index c7b7d69..22d1dcc 100644 (file)
@@ -38,4 +38,48 @@ config EXT_INSPECTOR
        help
          Provides the inspection extension
 
+config SW_INTERRUPTS
+    bool "Enable interception and hooking of software interrupts"
+    default n
+    help
+      This feature will cause the VMM to intercept the execution
+      of software interrupts (i.e. the INTn instruction) and enable
+      any INT vector to be hooked
+
+config SWINTR_PASSTHROUGH
+    bool "Hook all unhandled sofware interrupts for passthrough"
+    depends on SW_INTERRUPTS
+    default n
+    help
+      If enabled, this will cause all software interrupts 
+      (INT instruction vectors) to be hooked for passthrough.
+      May reduce performance but useful for debugging.
+
+config SYSCALL_HIJACK
+    bool "Enable System Call Hijacking"
+    depends on SW_INTERRUPTS
+    default n
+    help
+      Enable the VMM to hijack system calls executed by the guest.
+      If enabled, the VMM will hook execution of INT 80
+      (support for Fast-System Calls coming soon)
+
+config SYSCALL_PASSTHROUGH
+    bool "Hook all unhandled system calls for passthrough"
+    depends on SYSCALL_HIJACK
+    default n
+    help
+      If enabled, this option will cause all system calls
+      that are not explicitly hooked to be hooked for 
+      passthrough. This is useful for debugging.
+
+config HIJACK_SYSCALL_MSR
+    bool "Intercept Syscall-related MSR reads & writes"
+    depends on SYSCALL_HIJACK 
+    default n
+    help
+      Allow the VMM to intercept reads and writes to MSRs
+      related to SYSCALL and SYSENTER instructions. Specifically,
+      it will intercept R/W to STAR, CSTAR, and LSTAR.
+
 endmenu
index ac19202..ca51193 100644 (file)
@@ -1,5 +1,11 @@
 obj-y += null.o
-obj-$(CONFIG_EXT_MTRRS) += ext_mtrr.o
-obj-$(CONFIG_EXT_VTSC) += ext_vtsc.o
-obj-$(CONFIG_EXT_VTIME) += ext_vtime.o
-obj-$(CONFIG_EXT_INSPECTOR) += ext_inspector.o
+obj-$(V3_CONFIG_EXT_MTRRS) += ext_mtrr.o
+obj-$(V3_CONFIG_EXT_VTSC) += ext_vtsc.o
+obj-$(V3_CONFIG_EXT_VTIME) += ext_vtime.o
+obj-$(V3_CONFIG_EXT_INSPECTOR) += ext_inspector.o
+
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_syscall_hijack.o 
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_linux_syscall_map.o
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_mpi_accel.o
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_process_environment.o
+obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_execve_hook.o
index 7b89a91..5a440c1 100644 (file)
@@ -53,7 +53,7 @@ static int init_inspector_core(struct guest_info * core, void * priv_data) {
     struct v3_inspector_state * vm_state = priv_data;
     char core_name[50];
 
-    snprintf(core_name, 50, "core.%d", core->cpu_id);
+    snprintf(core_name, 50, "core.%d", core->vcpu_id);
 
     {
        struct v3_mtree * core_node = v3_mtree_create_subtree(&(vm_state->state_tree), core_name);
index 665d6be..6fd9931 100644 (file)
@@ -155,7 +155,7 @@ static int init() {
     if (khz) {
        time_state->guest_cpu_freq = atoi(khz);
        PrintDebug("Core %d CPU frequency requested at %d khz.\n", 
-                  info->cpu_id, time_state->guest_cpu_freq);
+                  info->pcpu_id, time_state->guest_cpu_freq);
     } 
     
     if ( (khz == NULL) || 
index df4e3dd..9d2c6f3 100644 (file)
@@ -1,10 +1,11 @@
-obj-$(CONFIG_SOCKET) +=  vmm_socket.o
-obj-$(CONFIG_PACKET) +=  vmm_packet.o
-obj-$(CONFIG_FILE) += vmm_file.o
-obj-$(CONFIG_CONSOLE) += vmm_console.o
-obj-$(CONFIG_STREAM) += vmm_stream.o
-obj-$(CONFIG_GRAPHICS_CONSOLE) += vmm_graphics_console.o
-obj-$(CONFIG_KEYED_STREAMS) += vmm_keyed_stream.o
-obj-$(CONFIG_HOST_DEVICE) += vmm_host_dev.o
+obj-$(V3_CONFIG_SOCKET) +=  vmm_socket.o
+obj-$(V3_CONFIG_PACKET) +=  vmm_packet.o
+obj-$(V3_CONFIG_FILE) += vmm_file.o
+obj-$(V3_CONFIG_CONSOLE) += vmm_console.o
+obj-$(V3_CONFIG_STREAM) += vmm_stream.o
+obj-$(V3_CONFIG_GRAPHICS_CONSOLE) += vmm_graphics_console.o
+obj-$(V3_CONFIG_KEYED_STREAMS) += vmm_keyed_stream.o
+obj-$(V3_CONFIG_HOST_DEVICE) += vmm_host_dev.o
 
+obj-y += null.o
 
diff --git a/palacios/src/interfaces/null.c b/palacios/src/interfaces/null.c
new file mode 100644 (file)
index 0000000..1828c44
--- /dev/null
@@ -0,0 +1,6 @@
+/** \file
+ * Do nothing module.
+ *
+ * This file only exists to appease the kbuild gods.
+ */
+
index 672f7aa..4985623 100644 (file)
@@ -32,7 +32,6 @@ obj-y := \
        vmm_cpuid.o \
        vmm_xml.o \
        vmm_mem_hook.o \
-       vmm_mptable.o \
        vmm_extensions.o \
        vmm_mtrr.o \
        vmm_multitree.o \
@@ -40,45 +39,36 @@ obj-y := \
 
 
 
-obj-$(CONFIG_XED) +=   vmm_xed.o
-obj-$(CONFIG_V3_DECODER) += vmm_v3dec.o
+obj-$(V3_CONFIG_XED) +=        vmm_xed.o
+obj-$(V3_CONFIG_V3_DECODER) += vmm_v3dec.o
 
-obj-$(CONFIG_SVM) +=    svm.o \
-                       svm_io.o \
-                       svm_lowlevel.o \
-                       svm_msr.o \
-                       svm_pause.o \
-                       svm_wbinvd.o \
-                       svm_handler.o \
-                       vmcb.o
+obj-$(V3_CONFIG_SVM) +=    svm.o \
+                          svm_io.o \
+                          svm_lowlevel.o \
+                          svm_msr.o \
+                          svm_pause.o \
+                          svm_wbinvd.o \
+                          svm_handler.o \
+                          vmcb.o
 
-obj-$(CONFIG_VMX) +=   vmx.o \
-                       vmx_handler.o \
-                       vmx_io.o \
-                       vmx_lowlevel.o \
-                       vmx_msr.o \
-                       vmx_hw_info.o \
-                       vmcs.o \
-                       vmx_ctrl_regs.o \
-                       vmx_assist.o
+obj-$(V3_CONFIG_VMX) +=        vmx.o \
+                               vmx_handler.o \
+                               vmx_io.o \
+                               vmx_lowlevel.o \
+                               vmx_msr.o \
+                               vmx_hw_info.o \
+                               vmcs.o \
+                               vmx_ctrl_regs.o \
+                               vmx_assist.o \
+                               vmx_ept.o 
 
 
 
 
-obj-$(CONFIG_INSTRUMENT_VMM) += vmm_instrument.o
-obj-$(CONFIG_TELEMETRY) += vmm_telemetry.o 
+obj-$(V3_CONFIG_TELEMETRY) += vmm_telemetry.o 
 
-obj-$(CONFIG_VNET) += vmm_vnet_core.o
-
-
-obj-$(CONFIG_SYMBIOTIC) += vmm_symbiotic.o vmm_symspy.o
-obj-$(CONFIG_SYMCALL) += vmm_symcall.o
-obj-$(CONFIG_SYMMOD) += vmm_symmod.o
-
-obj-$(CONFIG_SYSCALL_HIJACK) += vmm_syscall_hijack.o 
-obj-$(CONFIG_SYSCALL_HIJACK) += vmm_linux_syscall_map.o
-obj-$(CONFIG_SYSCALL_HIJACK) += vmm_mpi_accel.o
-obj-$(CONFIG_SYSCALL_HIJACK) += vmm_process_environment.o
-obj-$(CONFIG_SYSCALL_HIJACK) += vmm_execve_hook.o
+obj-$(V3_CONFIG_SYMBIOTIC) += vmm_symbiotic.o vmm_symspy.o
+obj-$(V3_CONFIG_SYMCALL) += vmm_symcall.o
+obj-$(V3_CONFIG_SYMMOD) += vmm_symmod.o
 
 obj-y += mmu/
index 0089d17..7b3a3ef 100644 (file)
@@ -1,3 +1,3 @@
-obj-$(CONFIG_SHADOW_PAGING_VTLB) += vmm_shdw_pg_tlb.o
-obj-$(CONFIG_SWAPBYPASS) += vmm_shdw_pg_swapbypass.o
-obj-$(CONFIG_SHADOW_PAGING_CACHE1) += vmm_shdw_pg_cache.o
+obj-$(V3_CONFIG_SHADOW_PAGING_VTLB) += vmm_shdw_pg_tlb.o
+obj-$(V3_CONFIG_SWAPBYPASS) += vmm_shdw_pg_swapbypass.o
+obj-$(V3_CONFIG_SHADOW_PAGING_CACHE1) += vmm_shdw_pg_cache.o
index 5ca6a0b..32e9d24 100644 (file)
@@ -31,7 +31,7 @@
 
 #define V3_CACHED_PG 0x1
 
-#ifndef CONFIG_DEBUG_SHDW_PG_CACHE
+#ifndef V3_CONFIG_DEBUG_SHDW_PG_CACHE
 #undef PrintDebug
 #define PrintDebug(fmt, ...)
 #endif
index 2aae928..fab26fd 100644 (file)
@@ -277,7 +277,7 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * core, addr_t fault
     pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
     addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
 
-    struct v3_mem_region * shdw_reg =  v3_get_mem_region(core->vm_info, core->cpu_id, guest_pa);
+    struct v3_mem_region * shdw_reg =  v3_get_mem_region(core->vm_info, core->vcpu_id, guest_pa);
 
     if (shdw_reg == NULL) {
        // Inject a machine check in the guest
@@ -459,7 +459,7 @@ static int handle_4MB_shadow_pagefault_pte_32(struct guest_info * core,
     PrintDebug("Handling 4MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
     PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
 
-    struct v3_mem_region * shdw_reg = v3_get_mem_region(core->vm_info, core->cpu_id, guest_fault_pa);
+    struct v3_mem_region * shdw_reg = v3_get_mem_region(core->vm_info, core->vcpu_id, guest_fault_pa);
 
  
     if (shdw_reg == NULL) {
index 250cbba..c955790 100644 (file)
 #include <palacios/vmm_paging.h>
 
 
-#ifndef CONFIG_DEBUG_SHDW_CACHE
+#ifndef V3_CONFIG_DEBUG_SHDW_CACHE
 #undef PrintDebug
 #define PrintDebug(fmt, ...)
 #endif
 
-#ifdef CONFIG_SHADOW_CACHE
+#ifdef V3_CONFIG_SHADOW_CACHE
 
 struct pde_chain {
     addr_t shadow_pdes[NR_PTE_CHAIN_ENTRIES];
index 7334cfa..8a2e094 100644 (file)
@@ -1,6 +1,6 @@
 
 
-#ifdef CONFIG_SHADOW_CACHE
+#ifdef V3_CONFIG_SHADOW_CACHE
 
 static inline int activate_shadow_pt_32(struct guest_info * core) {
     struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(core->ctrl_regs.cr3);
@@ -274,7 +274,7 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * core, addr_t fault
     pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
     addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
 
-    struct v3_mem_region * shdw_reg =  v3_get_mem_region(core->vm_info, core->cpu_id, guest_pa);
+    struct v3_mem_region * shdw_reg =  v3_get_mem_region(core->vm_info, core->vcpu_id, guest_pa);
 
     if (shdw_reg == NULL) {
        // Inject a machine check in the guest
@@ -322,7 +322,7 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * core, addr_t fault
 
        if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) ||
            (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) {
-           addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, core->cpu_id, guest_pa);
+           addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, core->vcpu_id, guest_pa);
       
            shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
 
@@ -408,7 +408,7 @@ static int handle_4MB_shadow_pagefault_32(struct guest_info * core,
     PrintDebug("Handling 4MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
     PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
 
-    struct v3_mem_region * shdw_reg = v3_get_mem_region(core->vm_info, core->cpu_id, guest_fault_pa);
+    struct v3_mem_region * shdw_reg = v3_get_mem_region(core->vm_info, core->vcpu_id, guest_fault_pa);
 
  
     if (shdw_reg == NULL) {
@@ -431,7 +431,7 @@ static int handle_4MB_shadow_pagefault_32(struct guest_info * core,
 
        if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || 
            (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) {
-           addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, core->cpu_id, guest_fault_pa);
+           addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, core->vcpu_id, guest_fault_pa);
 
            shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
 
index 4afe7ea..473414b 100644 (file)
@@ -1,6 +1,6 @@
 
 
-#ifdef CONFIG_SHADOW_CACHE
+#ifdef V3_CONFIG_SHADOW_CACHE
 
 static inline int activate_shadow_pt_32pae(struct guest_info * info) {
     PrintError("Activating 32 bit PAE page tables not implemented\n");
index c1d92f4..93a84eb 100644 (file)
@@ -1,6 +1,6 @@
 
 
-#ifdef CONFIG_SHADOW_CACHE
+#ifdef V3_CONFIG_SHADOW_CACHE
 
 #define PT64_NX_MASK (1ULL << 63)
 //#define SHOW_ALL 
@@ -534,7 +534,7 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * core, addr_t fault
 
     PrintDebug("Handling PTE fault\n");
 
-    struct v3_mem_region * shdw_reg =  v3_get_mem_region(core->vm_info, core->cpu_id, guest_pa);
+    struct v3_mem_region * shdw_reg =  v3_get_mem_region(core->vm_info, core->vcpu_id, guest_pa);
 
 
 
@@ -607,7 +607,7 @@ pte_noerror:
            int inherited_ar_user = ((inherited_ar & PT_USER_MASK) == PT_USER_MASK) ? 1 : 0;
            int inherited_ar_writable = ((inherited_ar & PT_WRITABLE_MASK) == PT_WRITABLE_MASK) ? 1 : 0;
 
-           addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, core->cpu_id, guest_pa);
+           addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, core->vcpu_id, guest_pa);
       
            shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
       
@@ -722,7 +722,7 @@ static int handle_2MB_shadow_pagefault_64(struct guest_info * core,
     PrintDebug("Handling 2MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
     PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
 
-    struct v3_mem_region * shdw_reg = v3_get_mem_region(core->vm_info, core->cpu_id, guest_fault_pa);
+    struct v3_mem_region * shdw_reg = v3_get_mem_region(core->vm_info, core->vcpu_id, guest_fault_pa);
 
     int fixed = 0;
     int write_pt = 0;
@@ -743,7 +743,7 @@ static int handle_2MB_shadow_pagefault_64(struct guest_info * core,
 
        if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || 
            (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) {
-           addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, core->cpu_id, guest_fault_pa);
+           addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, core->vcpu_id, guest_fault_pa);
 
            shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
 
index e8c7209..0b0a776 100644 (file)
@@ -27,7 +27,7 @@
 #include <palacios/vmm_hashtable.h>
 
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
 #include <palacios/vmm_telemetry.h>
 #endif
 
@@ -86,7 +86,7 @@ struct v3_swap_dev {
 struct swapbypass_vm_state {
     struct v3_swap_dev devs[256];
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
     uint32_t read_faults;
     uint32_t write_faults;
     uint32_t flushes;
@@ -135,7 +135,7 @@ static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core);
 
 
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
 static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
     struct swapbypass_vm_state * swap_state = (struct swapbypass_vm_state *)(vm->shdw_impl.impl_data);
 
@@ -206,7 +206,7 @@ static addr_t map_swp_page(struct v3_vm_info * vm, pte32_t * shadow_pte, pte32_t
 
     if (shdw_ptr_list == NULL) {
        shdw_ptr_list = (struct list_head *)V3_Malloc(sizeof(struct list_head));
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
        swap_state->list_size++;
 #endif
        INIT_LIST_HEAD(shdw_ptr_list);
@@ -217,7 +217,7 @@ static addr_t map_swp_page(struct v3_vm_info * vm, pte32_t * shadow_pte, pte32_t
 
     if (shdw_ptr == NULL) {
        PrintError("MEMORY LEAK\n");
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
        telemetry_cb(vm, NULL, "");
 #endif
        return 0;
@@ -343,7 +343,7 @@ int v3_swap_flush(struct v3_vm_info * vm) {
 
     //    PrintDebug("Flushing Symbiotic Swap table\n");
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
     swap_state->flushes++;
 #endif
 
@@ -393,7 +393,7 @@ static int sb_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     memset(sb_state, 0, sizeof(struct swapbypass_vm_state));
     sb_state->shdw_ptr_ht = v3_create_htable(0, swap_hash_fn, swap_eq_fn);
 
-#ifdef CONFIG_SWAPBYPASS_TELEMETRY
+#ifdef V3_CONFIG_SWAPBYPASS_TELEMETRY
     if (vm->enable_telemetry) {
        v3_add_telemetry_cb(vm, telemetry_cb, NULL);
     }
index 1aee15a..3b745af 100644 (file)
@@ -205,7 +205,7 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault
     pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
     addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
 
-    struct v3_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->cpu_id, guest_pa);
+    struct v3_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->vcpu_id, guest_pa);
 
     if (shdw_reg == NULL) {
        // Inject a machine check in the guest
@@ -241,7 +241,7 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault
 
 
 
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef V3_CONFIG_SYMBIOTIC_SWAP_TELEMETRY
            if (error_code.write == 0) {
                info->vm_info->swap_state.read_faults++;
            } else {
@@ -301,7 +301,7 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault
                        
                        shadow_pte->page_base_addr = swp_pg_pa;
                        
-#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
+#ifdef V3_CONFIG_SYMBIOTIC_SWAP_TELEMETRY
                        info->vm_info->swap_state.mapped_pages++;
 #endif
                        //              PrintError("Swap fault handled\n");
@@ -430,7 +430,7 @@ static int handle_4MB_shadow_pagefault_32(struct guest_info * info,
     PrintDebug("Handling 4MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
     PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
 
-    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
+    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->vcpu_id, guest_fault_pa);
 
  
     if (shdw_reg == NULL) {
index b4068b2..cb29966 100644 (file)
@@ -408,7 +408,7 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault
 
     PrintDebug("Handling PTE fault\n");
 
-    struct v3_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->cpu_id, guest_pa);
+    struct v3_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->vcpu_id, guest_pa);
 
 
 
@@ -543,7 +543,7 @@ static int handle_2MB_shadow_pagefault_64(struct guest_info * info,
     PrintDebug("Handling 2MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
     PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
 
-    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
+    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->vcpu_id, guest_fault_pa);
 
  
     if (shdw_reg == NULL) {
index f38f6ba..60b2d21 100644 (file)
@@ -24,7 +24,7 @@
 #include <palacios/vm_guest_mem.h>
 
 
-#ifndef CONFIG_DEBUG_SHDW_PG_VTLB
+#ifndef V3_CONFIG_DEBUG_SHDW_PG_VTLB
 #undef PrintDebug
 #define PrintDebug(fmt, ...)
 #endif
index b3f4e43..e638056 100644 (file)
@@ -218,7 +218,7 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault
     pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
     addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
 
-    struct v3_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->cpu_id, guest_pa);
+    struct v3_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->vcpu_id, guest_pa);
 
     if (shdw_reg == NULL) {
        // Inject a machine check in the guest
@@ -353,7 +353,7 @@ static int handle_4MB_shadow_pagefault_pte_32(struct guest_info * info,
     PrintDebug("Handling 4MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
     PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
 
-    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
+    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->vcpu_id, guest_fault_pa);
 
  
     if (shdw_reg == NULL) {
@@ -448,7 +448,7 @@ static int handle_4MB_shadow_pagefault_pde_32(struct guest_info * info,
     PrintDebug("Handling 4MB fault with large page (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
     PrintDebug("LargeShadowPDE=%p, LargeGuestPDE=%p\n", large_shadow_pde, large_guest_pde);
 
-    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
+    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->vcpu_id, guest_fault_pa);
 
  
     if (shdw_reg == NULL) {
index 38aebe6..4f31b7f 100644 (file)
@@ -426,7 +426,7 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault
 
     PrintDebug("Handling PTE fault\n");
 
-    struct v3_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->cpu_id, guest_pa);
+    struct v3_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->vcpu_id, guest_pa);
 
 
 
@@ -558,7 +558,7 @@ static int handle_2MB_shadow_pagefault_pde_64(struct guest_info * info,
     PrintDebug("Handling 2MB fault with large page (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
     PrintDebug("LargeShadowPDE=%p, LargeGuestPDE=%p\n", large_shadow_pde, large_guest_pde);
 
-    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
+    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->vcpu_id, guest_fault_pa);
  
     if (shdw_reg == NULL) {
        // Inject a machine check in the guest
@@ -640,7 +640,7 @@ static int handle_2MB_shadow_pagefault_pte_64(struct guest_info * info,
     PrintDebug("Handling 2MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
     PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
 
-    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
+    struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->vcpu_id, guest_fault_pa);
 
  
     if (shdw_reg == NULL) {
index 5aa0e30..a2cbbc1 100644 (file)
@@ -1,3 +1,4 @@
+
 /* 
  * This file is part of the Palacios Virtual Machine Monitor developed
  * by the V3VEE Project with funding from the United States National 
@@ -44,7 +45,7 @@
 #include <palacios/vmm_sprintf.h>
 
 
-#ifndef CONFIG_DEBUG_SVM
+#ifndef V3_CONFIG_DEBUG_SVM
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -53,7 +54,7 @@
 uint32_t v3_last_exit;
 
 // This is a global pointer to the host's VMCB
-static addr_t host_vmcbs[CONFIG_MAX_CPUS] = { [0 ... CONFIG_MAX_CPUS - 1] = 0};
+static addr_t host_vmcbs[V3_CONFIG_MAX_CPUS] = { [0 ... V3_CONFIG_MAX_CPUS - 1] = 0};
 
 
 
@@ -105,7 +106,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
 
     ctrl_area->instrs.HLT = 1;
 
-#ifdef CONFIG_TIME_VIRTUALIZE_TSC
+#ifdef V3_CONFIG_TIME_VIRTUALIZE_TSC
     ctrl_area->instrs.RDTSC = 1;
     ctrl_area->svm_instrs.RDTSCP = 1;
 #endif
@@ -136,7 +137,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
     ctrl_area->instrs.shutdown_evts = 1;
 
     /* KCH: intercept SW Interrupts (INT instr) */
-#ifdef CONFIG_SW_INTERRUPTS
+#ifdef V3_CONFIG_SW_INTERRUPTS
     ctrl_area->instrs.INTn = 1;
 #endif
 
@@ -228,8 +229,14 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
                &v3_handle_efer_write, 
                core);
 
-#ifdef CONFIG_HIJACK_MSR
-    /* KCH: for SYSCALL and SYSENTER interception */
+#ifdef V3_CONFIG_HIJACK_SYSCALL_MSR
+    /* KCH: we're not hooking these to TRAP them,
+            instead, we're going to catch the target EIP.
+            Hopefully this EIP is the entry point in the ELF located in the 
+            vsyscall page. We can inject checks into the code segment such that
+            we don't have to exit on uninteresting system calls. This should
+            give us much better performance than INT 80, and should even obviate
+            the need to deal with software interrupts at all */
     v3_hook_msr(core->vm_info, STAR_MSR,
         &v3_handle_star_read,
         &v3_handle_star_write,
@@ -242,6 +249,15 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
         &v3_handle_cstar_read,
         &v3_handle_cstar_write,
         core);
+    
+    /* KCH: this probably isn't necessary, as
+        SYSENTER is only used in legacy mode. In fact,
+        in long mode it results in an illegal instruction
+        exception */
+    v3_hook_msr(core->vm_info, IA32_SYSENTER_EIP_MSR,
+        &v3_handle_seeip_read,
+        &v3_handle_seeip_write,
+        core);
 #endif
 
     if (core->shdw_pg_mode == SHADOW_PAGING) {
@@ -347,7 +363,7 @@ static int update_irq_exit_state(struct guest_info * info) {
 
     if ((info->intr_core_state.irq_pending == 1) && (guest_ctrl->guest_ctrl.V_IRQ == 0)) {
        
-#ifdef CONFIG_DEBUG_INTERRUPTS
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
        PrintDebug("INTAK cycle completed for irq %d\n", info->intr_core_state.irq_vector);
 #endif
 
@@ -358,7 +374,7 @@ static int update_irq_exit_state(struct guest_info * info) {
     }
 
     if ((info->intr_core_state.irq_started == 1) && (guest_ctrl->exit_int_info.valid == 0)) {
-#ifdef CONFIG_DEBUG_INTERRUPTS
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
        PrintDebug("Interrupt %d taken by guest\n", info->intr_core_state.irq_vector);
 #endif
 
@@ -366,7 +382,7 @@ static int update_irq_exit_state(struct guest_info * info) {
        info->intr_core_state.irq_started = 0;
 
     } else if ((info->intr_core_state.irq_started == 1) && (guest_ctrl->exit_int_info.valid == 1)) {
-#ifdef CONFIG_DEBUG_INTERRUPTS
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
        PrintDebug("EXIT INT INFO is set (vec=%d)\n", guest_ctrl->exit_int_info.vector);
 #endif
     }
@@ -392,7 +408,7 @@ static int update_irq_entry_state(struct guest_info * info) {
        if (info->excp_state.excp_error_code_valid) {
            guest_ctrl->EVENTINJ.error_code = info->excp_state.excp_error_code;
            guest_ctrl->EVENTINJ.ev = 1;
-#ifdef CONFIG_DEBUG_INTERRUPTS
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
            PrintDebug("Injecting exception %d with error code %x\n", excp, guest_ctrl->EVENTINJ.error_code);
 #endif
        }
@@ -401,7 +417,7 @@ static int update_irq_entry_state(struct guest_info * info) {
        
        guest_ctrl->EVENTINJ.valid = 1;
 
-#ifdef CONFIG_DEBUG_INTERRUPTS
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
        PrintDebug("<%d> Injecting Exception %d (CR2=%p) (EIP=%p)\n", 
                   (int)info->num_exits, 
                   guest_ctrl->EVENTINJ.vector, 
@@ -411,7 +427,7 @@ static int update_irq_entry_state(struct guest_info * info) {
 
        v3_injecting_excp(info, excp);
     } else if (info->intr_core_state.irq_started == 1) {
-#ifdef CONFIG_DEBUG_INTERRUPTS
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
        PrintDebug("IRQ pending from previous injection\n");
 #endif
        guest_ctrl->guest_ctrl.V_IRQ = 1;
@@ -429,7 +445,7 @@ static int update_irq_entry_state(struct guest_info * info) {
                guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
                guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf;
 
-#ifdef CONFIG_DEBUG_INTERRUPTS
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
                PrintDebug("Injecting Interrupt %d (EIP=%p)\n", 
                           guest_ctrl->guest_ctrl.V_INTR_VECTOR, 
                           (void *)(addr_t)info->rip);
@@ -519,7 +535,7 @@ int v3_svm_enter(struct guest_info * info) {
     guest_state->rip = info->rip;
     guest_state->rsp = info->vm_regs.rsp;
 
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
     if (info->sym_core_state.symcall_state.sym_call_active == 0) {
        update_irq_entry_state(info);
     }
@@ -536,7 +552,7 @@ int v3_svm_enter(struct guest_info * info) {
       (void *)(addr_t)info->rip);
     */
 
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
     if (info->sym_core_state.symcall_state.sym_call_active == 1) {
        if (guest_ctrl->guest_ctrl.V_IRQ == 1) {
            V3_Print("!!! Injecting Interrupt during Sym call !!!\n");
@@ -589,7 +605,7 @@ int v3_svm_enter(struct guest_info * info) {
     exit_info2 = guest_ctrl->exit_info2;
 
 
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
     if (info->sym_core_state.symcall_state.sym_call_active == 0) {
        update_irq_exit_state(info);
     }
@@ -622,29 +638,31 @@ int v3_start_svm_guest(struct guest_info * info) {
     //    vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
     //  vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
 
-    PrintDebug("Starting SVM core %u\n", info->cpu_id);
+    PrintDebug("Starting SVM core %u (on logical core %u)\n", info->vcpu_id, info->pcpu_id);
 
-    if (info->cpu_id == 0) {
+    if (info->vcpu_id == 0) {
        info->core_run_state = CORE_RUNNING;
        info->vm_info->run_state = VM_RUNNING;
     } else  { 
-       PrintDebug("SVM core %u: Waiting for core initialization\n", info->cpu_id);
+       PrintDebug("SVM core %u (on %u): Waiting for core initialization\n", info->vcpu_id, info->pcpu_id);
 
        while (info->core_run_state == CORE_STOPPED) {
            v3_yield(info);
-           //PrintDebug("SVM core %u: still waiting for INIT\n",info->cpu_id);
+           //PrintDebug("SVM core %u: still waiting for INIT\n", info->vcpu_id);
        }
 
-       PrintDebug("SVM core %u initialized\n", info->cpu_id);
+       PrintDebug("SVM core %u(on %u) initialized\n", info->vcpu_id, info->pcpu_id);
     } 
 
-    PrintDebug("SVM core %u: I am starting at CS=0x%x (base=0x%p, limit=0x%x),  RIP=0x%p\n", 
-              info->cpu_id, info->segments.cs.selector, (void *)(info->segments.cs.base), 
+    PrintDebug("SVM core %u(on %u): I am starting at CS=0x%x (base=0x%p, limit=0x%x),  RIP=0x%p\n", 
+              info->vcpu_id, info->pcpu_id, 
+              info->segments.cs.selector, (void *)(info->segments.cs.base), 
               info->segments.cs.limit, (void *)(info->rip));
 
 
 
-    PrintDebug("SVM core %u: Launching SVM VM (vmcb=%p)\n", info->cpu_id, (void *)info->vmm_data);
+    PrintDebug("SVM core %u: Launching SVM VM (vmcb=%p) (on cpu %u)\n", 
+              info->vcpu_id, (void *)info->vmm_data, info->pcpu_id);
     //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
     
     v3_start_time(info);
@@ -663,17 +681,17 @@ int v3_start_svm_guest(struct guest_info * info) {
            
            info->vm_info->run_state = VM_ERROR;
            
-           V3_Print("SVM core %u: SVM ERROR!!\n", info->cpu_id); 
+           V3_Print("SVM core %u: SVM ERROR!!\n", info->vcpu_id); 
            
            v3_print_guest_state(info);
            
-           V3_Print("SVM core %u: SVM Exit Code: %p\n", info->cpu_id, (void *)(addr_t)guest_ctrl->exit_code); 
+           V3_Print("SVM core %u: SVM Exit Code: %p\n", info->vcpu_id, (void *)(addr_t)guest_ctrl->exit_code); 
            
-           V3_Print("SVM core %u: exit_info1 low = 0x%.8x\n", info->cpu_id, *(uint_t*)&(guest_ctrl->exit_info1));
-           V3_Print("SVM core %u: exit_info1 high = 0x%.8x\n", info->cpu_id, *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
+           V3_Print("SVM core %u: exit_info1 low = 0x%.8x\n", info->vcpu_id, *(uint_t*)&(guest_ctrl->exit_info1));
+           V3_Print("SVM core %u: exit_info1 high = 0x%.8x\n", info->vcpu_id, *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
            
-           V3_Print("SVM core %u: exit_info2 low = 0x%.8x\n", info->cpu_id, *(uint_t*)&(guest_ctrl->exit_info2));
-           V3_Print("SVM core %u: exit_info2 high = 0x%.8x\n", info->cpu_id, *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
+           V3_Print("SVM core %u: exit_info2 low = 0x%.8x\n", info->vcpu_id, *(uint_t*)&(guest_ctrl->exit_info2));
+           V3_Print("SVM core %u: exit_info2 high = 0x%.8x\n", info->vcpu_id, *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
            
            linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
            
@@ -683,9 +701,9 @@ int v3_start_svm_guest(struct guest_info * info) {
                v3_gva_to_hva(info, linear_addr, &host_addr);
            }
            
-           V3_Print("SVM core %u: Host Address of rip = 0x%p\n", info->cpu_id, (void *)host_addr);
+           V3_Print("SVM core %u: Host Address of rip = 0x%p\n", info->vcpu_id, (void *)host_addr);
            
-           V3_Print("SVM core %u: Instr (15 bytes) at %p:\n", info->cpu_id, (void *)host_addr);
+           V3_Print("SVM core %u: Instr (15 bytes) at %p:\n", info->vcpu_id, (void *)host_addr);
            v3_dump_mem((uint8_t *)host_addr, 15);
            
            v3_print_stack(info);
@@ -700,9 +718,11 @@ int v3_start_svm_guest(struct guest_info * info) {
        }
 
        
+
 /*
-       if ((info->num_exits % 5000) == 0) {
+       if ((info->num_exits % 50000) == 0) {
            V3_Print("SVM Exit number %d\n", (uint32_t)info->num_exits);
+           v3_print_guest_state(info);
        }
 */
        
@@ -716,6 +736,31 @@ int v3_start_svm_guest(struct guest_info * info) {
 
 
 
+int v3_reset_svm_vm_core(struct guest_info * core, addr_t rip) {
+    // init vmcb_bios
+
+    // Write the RIP, CS, and descriptor
+    // assume the rest is already good to go
+    //
+    // vector VV -> rip at 0
+    //              CS = VV00
+    //  This means we start executing at linear address VV000
+    //
+    // So the selector needs to be VV00
+    // and the base needs to be VV000
+    //
+    core->rip = 0;
+    core->segments.cs.selector = rip << 8;
+    core->segments.cs.limit = 0xffff;
+    core->segments.cs.base = rip << 12;
+
+    return 0;
+}
+
+
+
+
+
 
 /* Checks machine SVM capability */
 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
@@ -780,6 +825,7 @@ static int has_svm_nested_paging() {
 }
 
 
+
 void v3_init_svm_cpu(int cpu_id) {
     reg_ex_t msr;
     extern v3_cpu_arch_t v3_cpu_types[];
index 8822116..da85eb2 100644 (file)
 #include <palacios/vmm_direct_paging.h>
 #include <palacios/vmm_syscall_hijack.h>
 
-#ifndef CONFIG_DEBUG_SVM
+#ifndef V3_CONFIG_DEBUG_SVM
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
 #include <palacios/vmm_telemetry.h>
 #endif
 
@@ -48,7 +48,7 @@
 
 int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_info1, addr_t exit_info2) {
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     if (info->vm_info->enable_telemetry) {
        v3_telemetry_start_exit(info);
     }
@@ -115,7 +115,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
 
            break;
        case VMEXIT_CR0_WRITE: 
-#ifdef CONFIG_DEBUG_CTRL_REGS
+#ifdef V3_CONFIG_DEBUG_CTRL_REGS
            PrintDebug("CR0 Write\n");
 #endif
            if (v3_handle_cr0_write(info) == -1) {
@@ -123,7 +123,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
            }
            break;
        case VMEXIT_CR0_READ: 
-#ifdef CONFIG_DEBUG_CTRL_REGS
+#ifdef V3_CONFIG_DEBUG_CTRL_REGS
            PrintDebug("CR0 Read\n");
 #endif
            if (v3_handle_cr0_read(info) == -1) {
@@ -131,7 +131,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
            }
            break;
        case VMEXIT_CR3_WRITE: 
-#ifdef CONFIG_DEBUG_CTRL_REGS
+#ifdef V3_CONFIG_DEBUG_CTRL_REGS
            PrintDebug("CR3 Write\n");
 #endif
            if (v3_handle_cr3_write(info) == -1) {
@@ -140,7 +140,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
 
            break;
        case  VMEXIT_CR3_READ: 
-#ifdef CONFIG_DEBUG_CTRL_REGS
+#ifdef V3_CONFIG_DEBUG_CTRL_REGS
            PrintDebug("CR3 Read\n");
 #endif
            if (v3_handle_cr3_read(info) == -1) {
@@ -148,7 +148,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
            }
            break;
        case VMEXIT_CR4_WRITE: 
-#ifdef CONFIG_DEBUG_CTRL_REGS
+#ifdef V3_CONFIG_DEBUG_CTRL_REGS
            PrintDebug("CR4 Write\n");
 #endif
            if (v3_handle_cr4_write(info) == -1) {
@@ -156,7 +156,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
            }    
            break;
        case  VMEXIT_CR4_READ: 
-#ifdef CONFIG_DEBUG_CTRL_REGS
+#ifdef V3_CONFIG_DEBUG_CTRL_REGS
            PrintDebug("CR4 Read\n");
 #endif
            if (v3_handle_cr4_read(info) == -1) {
@@ -166,7 +166,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
        case VMEXIT_EXCP14: {
            addr_t fault_addr = exit_info2;
            pf_error_t * error_code = (pf_error_t *)&(exit_info1);
-#ifdef CONFIG_DEBUG_SHADOW_PAGING
+#ifdef V3_CONFIG_DEBUG_SHADOW_PAGING
            PrintDebug("PageFault at %p (error=%d)\n", 
                       (void *)fault_addr, *(uint_t *)error_code);
 #endif
@@ -205,7 +205,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
         break;
        case VMEXIT_INVLPG: 
            if (info->shdw_pg_mode == SHADOW_PAGING) {
-#ifdef CONFIG_DEBUG_SHADOW_PAGING
+#ifdef V3_CONFIG_DEBUG_SHADOW_PAGING
                PrintDebug("Invlpg\n");
 #endif
                if (v3_handle_shadow_invlpg(info) == -1) {
@@ -227,7 +227,10 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
                return -1;
            }
 
-           break;          
+           break;      
+       case VMEXIT_NMI:
+           // handled by interrupt dispatcher
+           break;
        case VMEXIT_INTR:
            // handled by interrupt dispatch earlier
            break;
@@ -235,7 +238,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
            //   handle_svm_smi(info); // ignored for now
            break;
        case VMEXIT_HLT:
-#ifdef CONFIG_DEBUG_HALT
+#ifdef V3_CONFIG_DEBUG_HALT
            PrintDebug("Guest halted\n");
 #endif
            if (v3_handle_halt(info) == -1) {
@@ -249,7 +252,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
            }
            break;
        case VMEXIT_WBINVD:   
-#ifdef CONFIG_DEBUG_EMULATOR
+#ifdef V3_CONFIG_DEBUG_EMULATOR
            PrintDebug("WBINVD\n");
 #endif
            if (v3_handle_svm_wbinvd(info) == -1) { 
@@ -257,7 +260,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
            }
            break;
         case VMEXIT_RDTSC:
-#ifdef CONFIG_DEBUG_TIME
+#ifdef V3_CONFIG_DEBUG_TIME
            PrintDebug("RDTSC/RDTSCP\n");
 #endif 
            if (v3_handle_rdtsc(info) == -1) {
@@ -266,7 +269,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
            }
            break;
         case VMEXIT_RDTSCP:
-#ifdef CONFIG_DEBUG_TIME
+#ifdef V3_CONFIG_DEBUG_TIME
            PrintDebug("RDTSCP\n");
 #endif 
            if (v3_handle_rdtscp(info) == -1) {
@@ -319,7 +322,7 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i
     }
     // END OF SWITCH (EXIT_CODE)
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     if (info->vm_info->enable_telemetry) {
        v3_telemetry_end_exit(info, exit_code);
     }
index 1aa76ae..405acc2 100644 (file)
@@ -24,7 +24,7 @@
 #include <palacios/vmm_decoder.h>
 #include <palacios/vm_guest_mem.h>
 
-#ifndef CONFIG_DEBUG_IO
+#ifndef V3_CONFIG_DEBUG_IO
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index e0d55a5..6f40a87 100644 (file)
@@ -31,7 +31,7 @@
 #include <palacios/vmm_xed.h>
 #include <palacios/vmm_direct_paging.h>
 
-#ifdef CONFIG_SYSCALL_HIJACK
+#ifdef V3_CONFIG_SYSCALL_HIJACK
 #include <palacios/vmm_syscall_hijack.h>
 #include <palacios/vmm_mpi_accel.h>
 #endif
@@ -492,14 +492,14 @@ static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_dat
     v3_print_guest_state(core);
     
     // init SVM/VMX
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
     if ((cpu_type == V3_SVM_CPU) || (cpu_type == V3_SVM_REV3_CPU)) {
        cpu_valid = 1;
        PrintDebugVMCB((vmcb_t *)(core->vmm_data));
     }
 #endif
-#ifdef CONFIG_VMX
-    if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_CPU)) {
+#ifdef V3_CONFIG_VMX
+    if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_CPU) || (cpu_type == V3_VMX_EPT_UG_CPU)) {
        cpu_valid = 1;
        v3_print_vmcs();
     }
@@ -514,13 +514,13 @@ static int info_hcall(struct guest_info * core, uint_t hcall_id, void * priv_dat
 }
 
 
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
 #include <palacios/svm.h>
 #include <palacios/svm_io.h>
 #include <palacios/svm_msr.h>
 #endif
 
-#ifdef CONFIG_VMX
+#ifdef V3_CONFIG_VMX
 #include <palacios/vmx.h>
 #include <palacios/vmx_io.h>
 #include <palacios/vmx_msr.h>
@@ -532,7 +532,7 @@ int v3_init_vm(struct v3_vm_info * vm) {
 
 
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     v3_init_telemetry(vm);
 #endif
 
@@ -561,7 +561,7 @@ int v3_init_vm(struct v3_vm_info * vm) {
     v3_init_time_vm(vm);
 
 
-#ifdef CONFIG_SYMBIOTIC
+#ifdef V3_CONFIG_SYMBIOTIC
     v3_init_symbiotic_vm(vm);
 #endif
 
@@ -570,16 +570,17 @@ int v3_init_vm(struct v3_vm_info * vm) {
 
     // init SVM/VMX
     switch (cpu_type) {
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
            v3_init_svm_io_map(vm);
            v3_init_svm_msr_map(vm);
            break;
 #endif
-#ifdef CONFIG_VMX
+#ifdef V3_CONFIG_VMX
        case V3_VMX_CPU:
        case V3_VMX_EPT_CPU:
+       case V3_VMX_EPT_UG_CPU:
            v3_init_vmx_io_map(vm);
            v3_init_vmx_msr_map(vm);
            break;
@@ -604,22 +605,23 @@ int v3_free_vm_internal(struct v3_vm_info * vm) {
 
 
 
-#ifdef CONFIG_SYMBIOTIC
+#ifdef V3_CONFIG_SYMBIOTIC
     v3_deinit_symbiotic_vm(vm);
 #endif
 
     // init SVM/VMX
     switch (cpu_type) {
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
            v3_deinit_svm_io_map(vm);
            v3_deinit_svm_msr_map(vm);
            break;
 #endif
-#ifdef CONFIG_VMX
+#ifdef V3_CONFIG_VMX
        case V3_VMX_CPU:
        case V3_VMX_EPT_CPU:
+       case V3_VMX_EPT_UG_CPU:
            v3_deinit_vmx_io_map(vm);
            v3_deinit_vmx_msr_map(vm);
            break;
@@ -645,7 +647,7 @@ int v3_free_vm_internal(struct v3_vm_info * vm) {
     v3_deinit_io_map(vm);
     v3_deinit_hypercall_map(vm);
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     v3_deinit_telemetry(vm);
 #endif
 
@@ -664,7 +666,7 @@ int v3_init_core(struct guest_info * core) {
     /*
      * Initialize the subsystem data strutures
      */
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     v3_init_core_telemetry(core);
 #endif
 
@@ -679,29 +681,21 @@ int v3_init_core(struct guest_info * core) {
     v3_init_decoder(core);
 
 
-#ifdef CONFIG_SYMBIOTIC
+#ifdef V3_CONFIG_SYMBIOTIC
     v3_init_symbiotic_core(core);
 #endif
 
 // KCH
-#ifdef CONFIG_SYSCALL_HIJACK
+#ifdef V3_CONFIG_SYSCALL_HIJACK
     v3_init_exec_hooks(core);
     v3_init_mpi_accel(core);
-    //v3_hook_swintr(core, 0x80, v3_syscall_handler, NULL);
-    /* hook a poll syscall */
-    //v3_hook_syscall(core, 5, v3_sysopen_handler, NULL);
-    //v3_hook_syscall(core, 21, v3_sysmount_handler, NULL);
-    //char * args[2];
-    //args[0] = "./envtest";
-    //args[1] = "LD_PRELOAD=./libcwrap.so";
-    //v3_hook_syscall(core, 11, v3_sysexecve_handler, (void*)args);
 #endif  
 
     // init SVM/VMX
 
 
     switch (cpu_type) {
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
            if (v3_init_svm_vmcb(core, vm->vm_class) == -1) {
@@ -710,9 +704,10 @@ int v3_init_core(struct guest_info * core) {
            }
            break;
 #endif
-#ifdef CONFIG_VMX
+#ifdef V3_CONFIG_VMX
        case V3_VMX_CPU:
        case V3_VMX_EPT_CPU:
+       case V3_VMX_EPT_UG_CPU:
            if (v3_init_vmx_vmcs(core, vm->vm_class) == -1) {
                PrintError("Error in VMX initialization\n");
                return -1;
@@ -733,7 +728,7 @@ int v3_free_core(struct guest_info * core) {
     v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
 
     
-#ifdef CONFIG_SYMBIOTIC
+#ifdef V3_CONFIG_SYMBIOTIC
     v3_deinit_symbiotic_core(core);
 #endif
 
@@ -748,12 +743,12 @@ int v3_free_core(struct guest_info * core) {
 
     v3_free_passthrough_pts(core);
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     v3_deinit_core_telemetry(core);
 #endif
 
     switch (cpu_type) {
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
            if (v3_deinit_svm_vmcb(core) == -1) {
@@ -762,9 +757,10 @@ int v3_free_core(struct guest_info * core) {
            }
            break;
 #endif
-#ifdef CONFIG_VMX
+#ifdef V3_CONFIG_VMX
        case V3_VMX_CPU:
        case V3_VMX_EPT_CPU:
+       case V3_VMX_EPT_UG_CPU:
            if (v3_deinit_vmx_vmcs(core) == -1) {
                PrintError("Error in VMX initialization\n");
                return -1;
index 0fd6075..caf8a89 100644 (file)
@@ -64,7 +64,7 @@ int v3_hpa_to_hva(addr_t hpa, addr_t * hva) {
 }
 
 int v3_gpa_to_hpa(struct guest_info * info, addr_t gpa, addr_t * hpa) {
-    struct v3_mem_region * reg = v3_get_mem_region(info->vm_info, info->cpu_id, gpa);
+    struct v3_mem_region * reg = v3_get_mem_region(info->vm_info, info->vcpu_id, gpa);
 
     if (reg == NULL) {
        PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (NULL REGION)\n", 
index f8fe322..9e5bd77 100644 (file)
@@ -202,6 +202,11 @@ int v3_update_vmcs_ctrl_fields(struct guest_info * info) {
 
     vmx_ret |= check_vmcs_write(VMCS_EXIT_CTRLS, arch_data->exit_ctrls.value);
     vmx_ret |= check_vmcs_write(VMCS_ENTRY_CTRLS, arch_data->entry_ctrls.value);
+    vmx_ret |= check_vmcs_write(VMCS_EXCP_BITMAP, arch_data->excp_bmap.value);
+
+    if (info->shdw_pg_mode == NESTED_PAGING) {
+       vmx_ret |= check_vmcs_write(VMCS_EPT_PTR, info->direct_map_pt);
+    }
 
     return vmx_ret;
 }
@@ -226,17 +231,11 @@ int v3_vmx_save_vmcs(struct guest_info * info) {
     check_vmcs_read(VMCS_GUEST_DR7, &(info->dbg_regs.dr7));
 
     check_vmcs_read(VMCS_GUEST_RFLAGS, &(info->ctrl_regs.rflags));
-    if (((struct vmx_data *)info->vmm_data)->ia32e_avail) {
+
 #ifdef __V3_64BIT__
-        check_vmcs_read(VMCS_GUEST_EFER, &(info->ctrl_regs.efer));
-#else
-       uint32_t hi, lo;
-        check_vmcs_read(VMCS_GUEST_EFER, &hi);
-        check_vmcs_read(VMCS_GUEST_EFER_HIGH, &lo);
-        info->ctrl_regs.efer = ((uint64_t) hi << 32) | lo;
+    check_vmcs_read(VMCS_GUEST_EFER, &(info->ctrl_regs.efer));
 #endif
-    }
-
+    
     error =  v3_read_vmcs_segments(&(info->segments));
 
     return error;
@@ -259,9 +258,12 @@ int v3_vmx_restore_vmcs(struct guest_info * info) {
 
     check_vmcs_write(VMCS_GUEST_RFLAGS, info->ctrl_regs.rflags);
 
-    if (((struct vmx_data *)info->vmm_data)->ia32e_avail) {
-        check_vmcs_write(VMCS_GUEST_EFER, info->ctrl_regs.efer);
-    }
+#ifdef __V3_64BIT__
+    check_vmcs_write(VMCS_GUEST_EFER, info->ctrl_regs.efer);
+#endif
+
+
+
 
     error = v3_write_vmcs_segments(&(info->segments));
 
@@ -324,16 +326,6 @@ int v3_update_vmcs_host_state(struct guest_info * info) {
     vmx_ret |= check_vmcs_write(VMCS_HOST_IDTR_BASE, arch_data->host_state.idtr.base);
     vmx_ret |= check_vmcs_write(VMCS_HOST_TR_BASE, arch_data->host_state.tr.base);
 
-#define FS_BASE_MSR 0xc0000100
-#define GS_BASE_MSR 0xc0000101
-
-    // FS.BASE MSR
-    v3_get_msr(FS_BASE_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
-    vmx_ret |= check_vmcs_write(VMCS_HOST_FS_BASE, tmp_msr.value);    
-
-    // GS.BASE MSR
-    v3_get_msr(GS_BASE_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
-    vmx_ret |= check_vmcs_write(VMCS_HOST_GS_BASE, tmp_msr.value);    
 
 
 
@@ -421,8 +413,12 @@ int v3_update_vmcs_host_state(struct guest_info * info) {
 #define SYSENTER_CS_MSR 0x00000174
 #define SYSENTER_ESP_MSR 0x00000175
 #define SYSENTER_EIP_MSR 0x00000176
+#define FS_BASE_MSR 0xc0000100
+#define GS_BASE_MSR 0xc0000101
+#define EFER_MSR 0xc0000080
 
-   // SYSENTER CS MSR
+
+    // SYSENTER CS MSR
     v3_get_msr(SYSENTER_CS_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
     vmx_ret |= check_vmcs_write(VMCS_HOST_SYSENTER_CS, tmp_msr.lo);
 
@@ -434,6 +430,33 @@ int v3_update_vmcs_host_state(struct guest_info * info) {
     v3_get_msr(SYSENTER_EIP_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
     vmx_ret |= check_vmcs_write(VMCS_HOST_SYSENTER_EIP, tmp_msr.value);
 
+
+    // FS.BASE MSR
+    v3_get_msr(FS_BASE_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
+    vmx_ret |= check_vmcs_write(VMCS_HOST_FS_BASE, tmp_msr.value);    
+
+    // GS.BASE MSR
+    v3_get_msr(GS_BASE_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
+    vmx_ret |= check_vmcs_write(VMCS_HOST_GS_BASE, tmp_msr.value);    
+
+
+    // EFER
+    v3_get_msr(EFER_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
+    vmx_ret |= check_vmcs_write(VMCS_HOST_EFER, tmp_msr.value);
+
+    // PERF GLOBAL CONTROL
+
+    // PAT
+
+
+    // save STAR, LSTAR, FMASK, KERNEL_GS_BASE MSRs in MSR load/store area
+
+    
+
+    
+
+
+
     return vmx_ret;
 }
 
@@ -541,6 +564,12 @@ static void print_guest_state()
     print_vmcs_field(VMCS_GUEST_CR4);
     print_vmcs_field(VMCS_GUEST_DR7);
 
+    // if save IA32_EFER
+    print_vmcs_field(VMCS_GUEST_EFER);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_GUEST_EFER_HIGH);
+#endif
+
 
     PrintDebug("\n");
 
@@ -556,6 +585,14 @@ static void print_guest_state()
     print_vmcs_field(VMCS_GUEST_SYSENTER_ESP);
     print_vmcs_field(VMCS_GUEST_SYSENTER_EIP);
 
+
+    // if save IA32_PAT
+    print_vmcs_field(VMCS_GUEST_PAT);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_GUEST_PAT_HIGH);
+#endif
+
+    //if load  IA32_PERF_GLOBAL_CTRL
     print_vmcs_field(VMCS_GUEST_PERF_GLOBAL_CTRL);
 #ifdef __V3_32BIT__
     print_vmcs_field(VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH);
@@ -564,12 +601,17 @@ static void print_guest_state()
     print_vmcs_field(VMCS_GUEST_SMBASE);
 
 
+
+
     PrintDebug("GUEST_NON_REGISTER_STATE\n");
 
     print_vmcs_field(VMCS_GUEST_ACTIVITY_STATE);
     print_vmcs_field(VMCS_GUEST_INT_STATE);
     print_vmcs_field(VMCS_GUEST_PENDING_DBG_EXCP);
 
+    // if VMX preempt timer
+    print_vmcs_field(VMCS_PREEMPT_TIMER);
+
 }
        
 static void print_host_state()
@@ -582,6 +624,15 @@ static void print_host_state()
     print_vmcs_field(VMCS_HOST_CR3);
     print_vmcs_field(VMCS_HOST_CR4);
     
+
+
+    // if load IA32_EFER
+    print_vmcs_field(VMCS_HOST_EFER);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_HOST_EFER_HIGH);
+#endif
+
+
     PrintDebug("\n");
     print_vmcs_field(VMCS_HOST_CS_SELECTOR);
     print_vmcs_field(VMCS_HOST_SS_SELECTOR);
@@ -603,6 +654,14 @@ static void print_host_state()
     print_vmcs_field(VMCS_HOST_SYSENTER_ESP);
     print_vmcs_field(VMCS_HOST_SYSENTER_EIP);
 
+
+    // if load IA32_PAT
+    print_vmcs_field(VMCS_HOST_PAT);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_HOST_PAT_HIGH);
+#endif
+
+    // if load IA32_PERF_GLOBAL_CTRL
     print_vmcs_field(VMCS_HOST_PERF_GLOBAL_CTRL);
 #ifdef __V3_32BIT__
     print_vmcs_field(VMCS_HOST_PERF_GLOBAL_CTRL_HIGH);
@@ -614,6 +673,8 @@ static void print_exec_ctrls() {
     PrintDebug("VMCS_EXEC_CTRL_FIELDS\n");
     print_vmcs_field(VMCS_PIN_CTRLS);
     print_vmcs_field(VMCS_PROC_CTRLS);
+    
+    // if activate secondary controls
     print_vmcs_field(VMCS_SEC_PROC_CTRLS);
     
     print_vmcs_field(VMCS_EXCP_BITMAP);
@@ -648,20 +709,28 @@ static void print_exec_ctrls() {
     print_vmcs_field(VMCS_CR3_TGT_VAL_2);
     print_vmcs_field(VMCS_CR3_TGT_VAL_3);
 
+    // Check max number of CR3 targets... may continue...
+
+
     PrintDebug("\n");
 
+    // if virtualize apic accesses
     print_vmcs_field(VMCS_APIC_ACCESS_ADDR);    
 #ifdef __V3_32BIT__
     print_vmcs_field(VMCS_APIC_ACCESS_ADDR_HIGH);
 #endif
 
+    // if use tpr shadow
     print_vmcs_field(VMCS_VAPIC_ADDR);    
 #ifdef __V3_32BIT__
     print_vmcs_field(VMCS_VAPIC_ADDR_HIGH);
 #endif
 
+    // if use tpr shadow
     print_vmcs_field(VMCS_TPR_THRESHOLD);
 
+
+    // if use MSR bitmaps
     print_vmcs_field(VMCS_MSR_BITMAP);
 #ifdef __V3_32BIT__
     print_vmcs_field(VMCS_MSR_BITMAP_HIGH);
@@ -671,6 +740,50 @@ static void print_exec_ctrls() {
 #ifdef __V3_32BIT__
     print_vmcs_field(VMCS_EXEC_PTR_HIGH);
 #endif
+
+
+}
+
+static void print_ept_state() {
+    V3_Print("VMCS EPT INFO\n");
+
+    // if enable vpid
+    print_vmcs_field(VMCS_VPID);
+
+    print_vmcs_field(VMCS_EPT_PTR);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_EPT_PTR_HIGH);
+#endif
+
+    print_vmcs_field(VMCS_GUEST_PHYS_ADDR);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_GUEST_PHYS_ADDR_HIGH);
+#endif
+
+
+
+    print_vmcs_field(VMCS_GUEST_PDPTE0);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_GUEST_PDPTE0_HIGH);
+#endif
+
+    print_vmcs_field(VMCS_GUEST_PDPTE1);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_GUEST_PDPTE1_HIGH);
+#endif
+
+    print_vmcs_field(VMCS_GUEST_PDPTE2);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_GUEST_PDPTE2_HIGH);
+#endif
+
+    print_vmcs_field(VMCS_GUEST_PDPTE3);
+#ifdef __V3_32BIT__
+    print_vmcs_field(VMCS_GUEST_PDPTE3_HIGH);
+#endif
+
+
+
 }
 
 
@@ -692,6 +805,11 @@ static void print_exit_ctrls() {
     print_vmcs_field(VMCS_EXIT_MSR_LOAD_ADDR_HIGH);
 #endif
 
+
+    // if pause loop exiting
+    print_vmcs_field(VMCS_PLE_GAP);
+    print_vmcs_field(VMCS_PLE_WINDOW);
+
 }
 
 
@@ -750,14 +868,13 @@ void v3_print_vmcs() {
     print_guest_state();
     print_host_state();
 
+    print_ept_state();
+
     print_exec_ctrls();
     print_exit_ctrls();
     print_entry_ctrls();
     print_exit_info();
 
-
-
-
 }
 
 
@@ -775,11 +892,7 @@ int v3_vmcs_get_field_len(vmcs_field_t field) {
            if (enc->access_type == 1) {
                return 4;
            } else {
-#ifdef __V3_64BIT__
-               return 8;
-#else
-               return 4;
-#endif
+               return sizeof(addr_t);
            }
        }
        case 2:
@@ -802,7 +915,7 @@ int v3_vmcs_get_field_len(vmcs_field_t field) {
 
 
 
-
+static const char VMCS_VPID_STR[] = "VPID";
 static const char VMCS_GUEST_ES_SELECTOR_STR[] = "GUEST_ES_SELECTOR";
 static const char VMCS_GUEST_CS_SELECTOR_STR[] = "GUEST_CS_SELECTOR";
 static const char VMCS_GUEST_SS_SELECTOR_STR[] = "GUEST_SS_SELECTOR";
@@ -838,12 +951,32 @@ static const char VMCS_VAPIC_ADDR_STR[] = "VAPIC_PAGE_ADDR";
 static const char VMCS_VAPIC_ADDR_HIGH_STR[] = "VAPIC_PAGE_ADDR_HIGH";
 static const char VMCS_APIC_ACCESS_ADDR_STR[] = "APIC_ACCESS_ADDR";
 static const char VMCS_APIC_ACCESS_ADDR_HIGH_STR[] = "APIC_ACCESS_ADDR_HIGH";
+static const char VMCS_EPT_PTR_STR[] = "VMCS_EPT_PTR";
+static const char VMCS_EPT_PTR_HIGH_STR[] = "VMCS_EPT_PTR_HIGH";
+static const char VMCS_GUEST_PHYS_ADDR_STR[] = "VMCS_GUEST_PHYS_ADDR";
+static const char VMCS_GUEST_PHYS_ADDR_HIGH_STR[] = "VMCS_GUEST_PHYS_ADDR_HIGH";
 static const char VMCS_LINK_PTR_STR[] = "VMCS_LINK_PTR";
 static const char VMCS_LINK_PTR_HIGH_STR[] = "VMCS_LINK_PTR_HIGH";
 static const char VMCS_GUEST_DBG_CTL_STR[] = "GUEST_DEBUG_CTL";
 static const char VMCS_GUEST_DBG_CTL_HIGH_STR[] = "GUEST_DEBUG_CTL_HIGH";
+static const char VMCS_GUEST_PAT_STR[] = "GUEST_PAT";
+static const char VMCS_GUEST_PAT_HIGH_STR[] = "GUEST_PAT_HIGH";
+static const char VMCS_GUEST_EFER_STR[] = "GUEST_EFER";
+static const char VMCS_GUEST_EFER_HIGH_STR[] = "GUEST_EFER_HIGH";
 static const char VMCS_GUEST_PERF_GLOBAL_CTRL_STR[] = "GUEST_PERF_GLOBAL_CTRL";
 static const char VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH_STR[] = "GUEST_PERF_GLOBAL_CTRL_HIGH";
+static const char VMCS_GUEST_PDPTE0_STR[] = "GUEST_PDPTE0";
+static const char VMCS_GUEST_PDPTE0_HIGH_STR[] = "GUEST_PDPTE0_HIGH";
+static const char VMCS_GUEST_PDPTE1_STR[] = "GUEST_PDPTE1";
+static const char VMCS_GUEST_PDPTE1_HIGH_STR[] = "GUEST_PDPTE1_HIGH";
+static const char VMCS_GUEST_PDPTE2_STR[] = "GUEST_PDPTE2";
+static const char VMCS_GUEST_PDPTE2_HIGH_STR[] = "GUEST_PDPTE2_HIGH";
+static const char VMCS_GUEST_PDPTE3_STR[] = "GUEST_PDPTE3";
+static const char VMCS_GUEST_PDPTE3_HIGH_STR[] = "GUEST_PDPTE3_HIGH";
+static const char VMCS_HOST_PAT_STR[] = "HOST_PAT";
+static const char VMCS_HOST_PAT_HIGH_STR[] = "HOST_PAT_HIGH";
+static const char VMCS_HOST_EFER_STR[] = "VMCS_HOST_EFER";
+static const char VMCS_HOST_EFER_HIGH_STR[] = "VMCS_HOST_EFER_HIGH";
 static const char VMCS_HOST_PERF_GLOBAL_CTRL_STR[] = "HOST_PERF_GLOBAL_CTRL";
 static const char VMCS_HOST_PERF_GLOBAL_CTRL_HIGH_STR[] = "HOST_PERF_GLOBAL_CTRL_HIGH";
 static const char VMCS_PIN_CTRLS_STR[] = "PIN_VM_EXEC_CTRLS";
@@ -862,6 +995,8 @@ static const char VMCS_ENTRY_EXCP_ERR_STR[] = "VM_ENTRY_EXCEPTION_ERROR";
 static const char VMCS_ENTRY_INSTR_LEN_STR[] = "VM_ENTRY_INSTR_LENGTH";
 static const char VMCS_TPR_THRESHOLD_STR[] = "TPR_THRESHOLD";
 static const char VMCS_SEC_PROC_CTRLS_STR[] = "VMCS_SEC_PROC_CTRLS";
+static const char VMCS_PLE_GAP_STR[] = "PLE_GAP";
+static const char VMCS_PLE_WINDOW_STR[] = "PLE_WINDOW";
 static const char VMCS_INSTR_ERR_STR[] = "VM_INSTR_ERROR";
 static const char VMCS_EXIT_REASON_STR[] = "EXIT_REASON";
 static const char VMCS_EXIT_INT_INFO_STR[] = "VM_EXIT_INT_INFO";
@@ -892,6 +1027,7 @@ static const char VMCS_GUEST_INT_STATE_STR[] = "GUEST_INT_STATE";
 static const char VMCS_GUEST_ACTIVITY_STATE_STR[] = "GUEST_ACTIVITY_STATE";
 static const char VMCS_GUEST_SMBASE_STR[] = "GUEST_SMBASE";
 static const char VMCS_GUEST_SYSENTER_CS_STR[] = "GUEST_SYSENTER_CS";
+static const char VMCS_PREEMPT_TIMER_STR[] = "PREEMPT_TIMER";
 static const char VMCS_HOST_SYSENTER_CS_STR[] = "HOST_SYSENTER_CS";
 static const char VMCS_CR0_MASK_STR[] = "CR0_GUEST_HOST_MASK";
 static const char VMCS_CR4_MASK_STR[] = "CR4_GUEST_HOST_MASK";
@@ -944,6 +1080,8 @@ static const char VMCS_HOST_RIP_STR[] = "HOST_RIP";
 
 const char * v3_vmcs_field_to_str(vmcs_field_t field) {   
     switch (field) {
+       case VMCS_VPID:
+           return VMCS_VPID_STR;
         case VMCS_GUEST_ES_SELECTOR:
             return VMCS_GUEST_ES_SELECTOR_STR;
         case VMCS_GUEST_CS_SELECTOR:
@@ -1014,6 +1152,14 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) {
             return VMCS_APIC_ACCESS_ADDR_STR;
         case VMCS_APIC_ACCESS_ADDR_HIGH:
             return VMCS_APIC_ACCESS_ADDR_HIGH_STR;
+       case VMCS_EPT_PTR:
+           return VMCS_EPT_PTR_STR;
+       case VMCS_EPT_PTR_HIGH:
+           return VMCS_EPT_PTR_HIGH_STR;
+       case VMCS_GUEST_PHYS_ADDR:
+           return VMCS_GUEST_PHYS_ADDR_STR;
+       case VMCS_GUEST_PHYS_ADDR_HIGH:
+           return VMCS_GUEST_PHYS_ADDR_HIGH_STR;
         case VMCS_LINK_PTR:
             return VMCS_LINK_PTR_STR;
         case VMCS_LINK_PTR_HIGH:
@@ -1022,10 +1168,42 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) {
             return VMCS_GUEST_DBG_CTL_STR;
         case VMCS_GUEST_DBG_CTL_HIGH:
             return VMCS_GUEST_DBG_CTL_HIGH_STR;
-        case VMCS_GUEST_PERF_GLOBAL_CTRL:
+       case VMCS_GUEST_PAT:
+           return VMCS_GUEST_PAT_STR;
+       case VMCS_GUEST_PAT_HIGH:
+           return VMCS_GUEST_PAT_HIGH_STR;
+       case VMCS_GUEST_EFER:
+           return VMCS_GUEST_EFER_STR;
+       case VMCS_GUEST_EFER_HIGH:
+           return VMCS_GUEST_EFER_HIGH_STR;
+       case VMCS_GUEST_PERF_GLOBAL_CTRL:
             return VMCS_GUEST_PERF_GLOBAL_CTRL_STR;
         case VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH:
             return VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH_STR;
+       case VMCS_GUEST_PDPTE0:
+           return VMCS_GUEST_PDPTE0_STR;
+       case VMCS_GUEST_PDPTE0_HIGH:
+           return VMCS_GUEST_PDPTE0_HIGH_STR;
+       case VMCS_GUEST_PDPTE1:
+           return VMCS_GUEST_PDPTE1_STR;
+       case VMCS_GUEST_PDPTE1_HIGH:
+           return VMCS_GUEST_PDPTE1_HIGH_STR;
+       case VMCS_GUEST_PDPTE2:
+           return VMCS_GUEST_PDPTE2_STR;
+       case VMCS_GUEST_PDPTE2_HIGH:
+           return VMCS_GUEST_PDPTE2_HIGH_STR;
+       case VMCS_GUEST_PDPTE3:
+           return VMCS_GUEST_PDPTE3_STR;
+       case VMCS_GUEST_PDPTE3_HIGH:
+           return VMCS_GUEST_PDPTE3_HIGH_STR;
+       case VMCS_HOST_PAT:
+           return VMCS_HOST_PAT_STR;
+       case VMCS_HOST_PAT_HIGH:
+           return VMCS_HOST_PAT_HIGH_STR;
+       case VMCS_HOST_EFER:
+           return VMCS_HOST_EFER_STR;
+       case VMCS_HOST_EFER_HIGH:
+           return VMCS_HOST_EFER_HIGH_STR;
         case VMCS_HOST_PERF_GLOBAL_CTRL:
             return VMCS_HOST_PERF_GLOBAL_CTRL_STR;
         case VMCS_HOST_PERF_GLOBAL_CTRL_HIGH:
@@ -1062,6 +1240,10 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) {
             return VMCS_TPR_THRESHOLD_STR;
        case VMCS_SEC_PROC_CTRLS:
            return VMCS_SEC_PROC_CTRLS_STR;
+       case VMCS_PLE_GAP:
+           return VMCS_PLE_GAP_STR;
+       case VMCS_PLE_WINDOW:
+           return VMCS_PLE_WINDOW_STR;
         case VMCS_INSTR_ERR:
             return VMCS_INSTR_ERR_STR;
         case VMCS_EXIT_REASON:
@@ -1122,7 +1304,9 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) {
             return VMCS_GUEST_SMBASE_STR;
         case VMCS_GUEST_SYSENTER_CS:
             return VMCS_GUEST_SYSENTER_CS_STR;
-        case VMCS_HOST_SYSENTER_CS:
+       case VMCS_PREEMPT_TIMER:
+           return VMCS_PREEMPT_TIMER_STR;
+        case VMCS_HOST_SYSENTER_CS:        
             return VMCS_HOST_SYSENTER_CS_STR;
         case VMCS_CR0_MASK:
             return VMCS_CR0_MASK_STR;
index cb38aab..d60e55a 100644 (file)
 #include <palacios/vmm_sprintf.h>
 #include <palacios/vmm_extensions.h>
 
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
 #include <palacios/svm.h>
 #endif
-#ifdef CONFIG_VMX
+#ifdef V3_CONFIG_VMX
 #include <palacios/vmx.h>
 #endif
 
-#ifdef CONFIG_VNET
-#include <palacios/vmm_vnet.h>
-#endif
-
 
-v3_cpu_arch_t v3_cpu_types[CONFIG_MAX_CPUS];
+v3_cpu_arch_t v3_cpu_types[V3_CONFIG_MAX_CPUS];
 struct v3_os_hooks * os_hooks = NULL;
 int v3_dbg_enable = 0;
 
 
 
+
 static void init_cpu(void * arg) {
     uint32_t cpu_id = (uint32_t)(addr_t)arg;
 
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
     if (v3_is_svm_capable()) {
         PrintDebug("Machine is SVM Capable\n");
         v3_init_svm_cpu(cpu_id);
        
     } else 
 #endif
-#ifdef CONFIG_VMX
+#ifdef V3_CONFIG_VMX
     if (v3_is_vmx_capable()) {
        PrintDebug("Machine is VMX Capable\n");
        v3_init_vmx_cpu(cpu_id);
@@ -72,16 +69,17 @@ static void deinit_cpu(void * arg) {
 
 
     switch (v3_cpu_types[cpu_id]) {
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
            PrintDebug("Deinitializing SVM CPU %d\n", cpu_id);
            v3_deinit_svm_cpu(cpu_id);
            break;
 #endif
-#ifdef CONFIG_VMX
+#ifdef V3_CONFIG_VMX
        case V3_VMX_CPU:
        case V3_VMX_EPT_CPU:
+       case V3_VMX_EPT_UG_CPU:
            PrintDebug("Deinitializing VMX CPU %d\n", cpu_id);
            v3_deinit_vmx_cpu(cpu_id);
            break;
@@ -103,7 +101,7 @@ void Init_V3(struct v3_os_hooks * hooks, int num_cpus) {
     // Set global variables. 
     os_hooks = hooks;
 
-    for (i = 0; i < CONFIG_MAX_CPUS; i++) {
+    for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
        v3_cpu_types[i] = V3_INVALID_CPU;
     }
 
@@ -117,17 +115,13 @@ void Init_V3(struct v3_os_hooks * hooks, int num_cpus) {
     V3_init_extensions();
 
 
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
     V3_init_symmod();
 #endif
 
 
-#ifdef CONFIG_VNET
-    v3_init_vnet();
-#endif
 
-
-#ifdef CONFIG_MULTITHREAD_OS
+#ifdef V3_CONFIG_MULTITHREAD_OS
     if ((hooks) && (hooks->call_on_cpu)) {
 
        for (i = 0; i < num_cpus; i++) {
@@ -151,18 +145,14 @@ void Shutdown_V3() {
 
     V3_deinit_extensions();
 
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
     V3_deinit_symmod();
 #endif
 
 
-#ifdef CONFIG_VNET
-    v3_deinit_vnet();
-#endif
-
-#ifdef CONFIG_MULTITHREAD_OS
+#ifdef V3_CONFIG_MULTITHREAD_OS
     if ((os_hooks) && (os_hooks->call_on_cpu)) {
-       for (i = 0; i < CONFIG_MAX_CPUS; i++) {
+       for (i = 0; i < V3_CONFIG_MAX_CPUS; i++) {
            if (v3_cpu_types[i] != V3_INVALID_CPU) {
                deinit_cpu((void *)(addr_t)i);
            }
@@ -203,24 +193,27 @@ struct v3_vm_info * v3_create_vm(void * cfg, void * priv_data, char * name) {
 }
 
 
+
+
 static int start_core(void * p)
 {
     struct guest_info * core = (struct guest_info *)p;
 
 
-    PrintDebug("virtual core %u: in start_core (RIP=%p)\n", 
-              core->cpu_id, (void *)(addr_t)core->rip);
+    PrintDebug("virtual core %u (on logical core %u): in start_core (RIP=%p)\n", 
+              core->vcpu_id, core->pcpu_id, (void *)(addr_t)core->rip);
 
     switch (v3_cpu_types[0]) {
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
            return v3_start_svm_guest(core);
            break;
 #endif
-#if CONFIG_VMX
+#if V3_CONFIG_VMX
        case V3_VMX_CPU:
        case V3_VMX_EPT_CPU:
+       case V3_VMX_EPT_UG_CPU:
            return v3_start_vmx_guest(core);
            break;
 #endif
@@ -234,7 +227,7 @@ static int start_core(void * p)
 
 
 // For the moment very ugly. Eventually we will shift the cpu_mask to an arbitrary sized type...
-#ifdef CONFIG_MULTITHREAD_OS
+#ifdef V3_CONFIG_MULTITHREAD_OS
 #define MAX_CORES 32
 #else
 #define MAX_CORES 1
@@ -270,7 +263,7 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
        return -1;
     }
 
-#ifdef CONFIG_MULTITHREAD_OS
+#ifdef V3_CONFIG_MULTITHREAD_OS
     // spawn off new threads, for other cores
     for (i = 0, vcore_id = 1; (i < MAX_CORES) && (vcore_id < vm->num_cores); i++) {
        int major = 0;
@@ -290,7 +283,6 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
            i--; // We reset the logical core idx. Not strictly necessary I guess... 
        } else {
 
-           /* This assumes that the core 0 thread has been mapped to physical core 0 */
            if (i == V3_Get_CPU()) {
                // We skip the local CPU because it is reserved for vcore 0
                continue;
@@ -325,6 +317,7 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
                   core_idx, start_core, core, core->exec_name);
 
        // TODO: actually manage these threads instead of just launching them
+       core->pcpu_id = core_idx;
        core_thread = V3_CREATE_THREAD_ON_CPU(core_idx, start_core, core, core->exec_name);
 
        if (core_thread == NULL) {
@@ -339,6 +332,8 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
 
     sprintf(vm->cores[0].exec_name, "%s", vm->name);
 
+    vm->cores[0].pcpu_id = V3_Get_CPU();
+
     if (start_core(&(vm->cores[0])) != 0) {
        PrintError("Error starting VM core 0\n");
        v3_stop_vm(vm);
@@ -351,6 +346,33 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) {
 }
 
 
+int v3_reset_vm_core(struct guest_info * core, addr_t rip) {
+    
+    switch (v3_cpu_types[core->pcpu_id]) {
+#ifdef V3_CONFIG_SVM
+       case V3_SVM_CPU:
+       case V3_SVM_REV3_CPU:
+           PrintDebug("Resetting SVM Guest CPU %d\n", core->vcpu_id);
+           return v3_reset_svm_vm_core(core, rip);
+#endif
+#ifdef V3_CONFIG_VMX
+       case V3_VMX_CPU:
+       case V3_VMX_EPT_CPU:
+       case V3_VMX_EPT_UG_CPU:
+           PrintDebug("Resetting VMX Guest CPU %d\n", core->vcpu_id);
+           return v3_reset_vmx_vm_core(core, rip);
+#endif
+       case V3_INVALID_CPU:
+       default:
+           PrintError("CPU has no virtualization Extensions\n");
+           break;
+    }
+
+    return -1;
+}
+
+
+
 
 
 int v3_stop_vm(struct v3_vm_info * vm) {
@@ -490,7 +512,7 @@ void v3_print_cond(const char * fmt, ...) {
 }
 
 
-#ifdef CONFIG_MULTITHREAD_OS
+#ifdef V3_CONFIG_MULTITHREAD_OS
 
 void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector) {
     extern struct v3_os_hooks * os_hooks;
@@ -505,15 +527,16 @@ void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector) {
 
 int v3_vm_enter(struct guest_info * info) {
     switch (v3_cpu_types[0]) {
-#ifdef CONFIG_SVM
+#ifdef V3_CONFIG_SVM
        case V3_SVM_CPU:
        case V3_SVM_REV3_CPU:
            return v3_svm_enter(info);
            break;
 #endif
-#if CONFIG_VMX
+#if V3_CONFIG_VMX
        case V3_VMX_CPU:
        case V3_VMX_EPT_CPU:
+       case V3_VMX_EPT_UG_CPU:
            return v3_vmx_enter(info);
            break;
 #endif
index 1115ce0..614ceca 100644 (file)
 
 
 #include <util/vmm_barrier.h>
+
+
+
+int v3_init_barrier(struct v3_barrier * barrier) {
+    memset(barrier, 0, sizeof(struct v3_barrier));
+    v3_lock_init(&(barrier->lock));
+
+    return 0;
+}
+
+
+int v3_activate_barrier(struct guest_info * core, struct v3_barrier * barrier) {
+    addr_t flag;
+    int acquired = 0;
+    
+    flag = v3_lock_irqsave(barrier->lock);
+
+    if (barrier->active == 0) {
+       barrier->active = 1;
+       acquired = 1;
+    }
+
+    v3_unlock_irqrestore(barrier->lock, flag);
+
+    if (acquired == 0) {
+       return -1;
+    }
+
+
+    // wait for barrier catch
+
+
+    return 0;
+}
+
+
+
+
+int v3_deactivate_barrier(struct v3_barrier * barrier) {
+
+}
+
+
+int v3_check_barrier(struct guest_info * core, struct v3_barrier * barrier) {
+
+    if (barrier->activated == 0) {
+       return 0;
+    }
+    
+    // set cpu bit
+
+    // wait for cpu bit to clear
+
+}
index 9be1933..b834952 100644 (file)
 
 .data
 
-#ifdef CONFIG_VMX
+#ifdef V3_CONFIG_VMX
 .globl v3_vmxassist_start
 v3_vmxassist_start:
-.incbin CONFIG_VMXASSIST_PATH
+.incbin V3_CONFIG_VMXASSIST_PATH
 .globl v3_vmxassist_end
 v3_vmxassist_end:
 #endif
@@ -32,21 +32,21 @@ v3_vmxassist_end:
 
 .globl v3_vgabios_start
 v3_vgabios_start:
-.incbin CONFIG_VGABIOS_PATH
+.incbin V3_CONFIG_VGABIOS_PATH
 .global v3_vgabios_end
 v3_vgabios_end:
 
 .globl v3_rombios_start
 v3_rombios_start:
-.incbin CONFIG_ROMBIOS_PATH
+.incbin V3_CONFIG_ROMBIOS_PATH
 .globl v3_rombios_end
 v3_rombios_end:
 
 
-#ifdef CONFIG_USE_PXE_BIOS
+#ifdef V3_CONFIG_USE_PXE_BIOS
 .globl pxebios_start
 pxebios_start:
-.incbin CONFIG_PXEBIOS_PATH
+.incbin V3_CONFIG_PXEBIOS_PATH
 .globl pxebios_end
 pxebios_end:
 #endif
index 25d8b23..8d348e6 100644 (file)
@@ -30,7 +30,6 @@
 #include <palacios/vmm_xml.h>
 #include <palacios/vmm_io.h>
 #include <palacios/vmm_msr.h>
-#include <palacios/vmm_mptable.h>
 #include <palacios/vmm_sprintf.h>
 
 
@@ -202,7 +201,7 @@ static inline uint32_t get_alignment(char * align_str) {
        }
     }
     
-#ifndef CONFIG_ALIGNED_PG_ALLOC
+#ifndef V3_CONFIG_ALIGNED_PG_ALLOC
     if (alignment != PAGE_SIZE_4KB) {
        PrintError("Aligned page allocations are not supported in this host (requested alignment=%d)\n", alignment);
        PrintError("Ignoring alignment request\n");
@@ -247,7 +246,7 @@ static int pre_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * vm_cfg) {
        return -1;
     }
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     {
        char * telemetry = v3_cfg_val(vm_cfg, "telemetry");
 
@@ -286,14 +285,15 @@ static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_
     v3_cfg_tree_t * vm_tree = info->vm_info->cfg_data->cfg;
     v3_cfg_tree_t * pg_tree = v3_cfg_subtree(vm_tree, "paging");
     char * pg_mode          = v3_cfg_val(pg_tree, "mode");
-    char * page_size        = v3_cfg_val(pg_tree, "page_size");
     
     PrintDebug("Paging mode specified as %s\n", pg_mode);
 
     if (pg_mode) {
        if ((strcasecmp(pg_mode, "nested") == 0)) {
            // we assume symmetric cores, so if core 0 has nested paging they all do
-           if (v3_cpu_types[0] == V3_SVM_REV3_CPU) {
+           if ((v3_cpu_types[0] == V3_SVM_REV3_CPU) || 
+               (v3_cpu_types[0] == V3_VMX_EPT_CPU) ||
+               (v3_cpu_types[0] == V3_VMX_EPT_UG_CPU)) {
                info->shdw_pg_mode = NESTED_PAGING;
            } else {
                PrintError("Nested paging not supported on this hardware. Defaulting to shadow paging\n");
@@ -311,24 +311,6 @@ static int determine_paging_mode(struct guest_info * info, v3_cfg_tree_t * core_
     }
 
 
-    if (info->shdw_pg_mode == NESTED_PAGING) {
-       PrintDebug("Guest Paging Mode: NESTED_PAGING\n");
-       if (strcasecmp(page_size, "4kb") == 0) { /* TODO: this may not be an ideal place for this */
-           info->vm_info->paging_size = PAGING_4KB;
-       } else if (strcasecmp(page_size, "2mb") == 0) {
-           info->vm_info->paging_size = PAGING_2MB;
-       } else {
-           PrintError("Invalid VM paging size: '%s'\n", page_size);
-           return -1;
-       }
-       PrintDebug("VM page size=%s\n", page_size);
-    } else if (info->shdw_pg_mode == SHADOW_PAGING) {
-        PrintDebug("Guest Paging Mode: SHADOW_PAGING\n");
-    } else {
-       PrintError("Guest paging mode incorrectly set.\n");
-       return -1;
-    }
-
     if (v3_cfg_val(pg_tree, "large_pages") != NULL) {
        if (strcasecmp(v3_cfg_val(pg_tree, "large_pages"), "true") == 0) {
            info->use_large_pages = 1;
@@ -370,14 +352,18 @@ static int post_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        return -1;
     }
 
-    /* 
-     * Initialize configured extensions 
-     */
-    if (setup_extensions(vm, cfg) == -1) {
-       PrintError("Failed to setup extensions\n");
+
+    if (vm->vm_class == V3_PC_VM) {
+       if (post_config_pc(vm, cfg) == -1) {
+           PrintError("PC Post configuration failure\n");
+           return -1;
+       }
+    } else {
+       PrintError("Invalid VM Class\n");
        return -1;
     }
 
+
     /* 
      * Initialize configured devices
      */
@@ -391,16 +377,17 @@ static int post_config_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     v3_print_msr_map(vm);
 
 
-    if (vm->vm_class == V3_PC_VM) {
-       if (post_config_pc(vm, cfg) == -1) {
-           PrintError("PC Post configuration failure\n");
-           return -1;
-       }
-    } else {
-       PrintError("Invalid VM Class\n");
+
+
+    /* 
+     * Initialize configured extensions 
+     */
+    if (setup_extensions(vm, cfg) == -1) {
+       PrintError("Failed to setup extensions\n");
        return -1;
     }
 
+
     return 0;
 }
 
@@ -505,7 +492,7 @@ struct v3_vm_info * v3_config_guest(void * cfg_blob, void * priv_data) {
     for (i = 0; i < vm->num_cores; i++) {
        struct guest_info * info = &(vm->cores[i]);
 
-       info->cpu_id = i;
+       info->vcpu_id = i;
        info->vm_info = vm;
        info->core_cfg_data = per_core_cfg;
 
index 0c7ef4c..3f5b238 100644 (file)
@@ -77,21 +77,6 @@ static int post_config_pc(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     }
 
 
-    if (vm->num_cores>1 && !v3_find_dev(vm,"apic")) { 
-       PrintError("palacios: VM has more than one core, but no device named \"apic\"!\n");
-       return -1;
-    } 
-    
-    if (v3_find_dev(vm,"apic")) { 
-       if (!v3_find_dev(vm,"ioapic")) { 
-           PrintError("palacios: VM cores have apics, but there is no device named \"ioapic\"!\n");
-       }
-       if (v3_inject_mptable(vm) == -1) { 
-           PrintError("Failed to inject mptable during configuration\n");
-           return -1;
-       }
-    }
-    
     return 0;
 }
 
index ce7c244..ca7ef86 100644 (file)
@@ -135,20 +135,27 @@ static int mask_hook(struct guest_info * core, uint32_t cpuid,
     v3_cpuid(cpuid, eax, ebx, ecx, edx);
 
     *eax &= ~(mask->rax_mask);
-    *eax |= mask->rax;
+    *eax |= (mask->rax & mask->rax_mask);
 
     *ebx &= ~(mask->rbx_mask);
-    *ebx |= mask->rbx;
+    *ebx |= (mask->rbx & mask->rbx_mask);
 
     *ecx &= ~(mask->rcx_mask);
-    *ecx |= mask->rcx;
+    *ecx |= (mask->rcx & mask->rcx_mask);
 
     *edx &= ~(mask->rdx_mask);
-    *edx |= mask->rdx;
+    *edx |= (mask->rdx & mask->rdx_mask);
 
     return 0;
 }
 
+
+
+/* This function allows you to reserve a set of bits in a given cpuid value 
+ * For each cpuid return register you specify which bits you want to reserve in the mask.
+ * The value of those bits is set in the reg param.
+ * The values of the reserved bits are  returned to the guest, when it reads the cpuid
+ */ 
 int v3_cpuid_add_fields(struct v3_vm_info * vm, uint32_t cpuid, 
                        uint32_t rax_mask, uint32_t rax,
                        uint32_t rbx_mask, uint32_t rbx, 
@@ -156,6 +163,14 @@ int v3_cpuid_add_fields(struct v3_vm_info * vm, uint32_t cpuid,
                        uint32_t rdx_mask, uint32_t rdx) {
     struct v3_cpuid_hook * hook = get_cpuid_hook(vm, cpuid);
 
+
+    if ((~rax_mask & rax) || (~rbx_mask & rbx) ||
+       (~rcx_mask & rcx) || (~rdx_mask & rdx)) {
+       PrintError("Invalid cpuid reg value (mask overrun)\n");
+       return -1;
+    }
+
+
     if (hook == NULL) {
        struct masked_cpuid * mask = V3_Malloc(sizeof(struct masked_cpuid));
        memset(mask, 0, sizeof(struct masked_cpuid));
@@ -192,12 +207,6 @@ int v3_cpuid_add_fields(struct v3_vm_info * vm, uint32_t cpuid,
            return -1;
        }
 
-       if ((~rax_mask & rax) || (~rbx_mask & rbx) ||
-           (~rcx_mask & rcx) || (~rdx_mask & rdx)) {
-           PrintError("Invalid cpuid reg value (mask overrun)\n");
-           return -1;
-       }
-
        mask->rax_mask |= rax_mask;
        mask->rbx_mask |= rbx_mask;
        mask->rcx_mask |= rcx_mask;
index cc1fac6..4c84e2e 100644 (file)
@@ -26,7 +26,7 @@
 #include <palacios/vmm_direct_paging.h>
 #include <palacios/svm.h>
 
-#ifndef CONFIG_DEBUG_CTRL_REGS
+#ifndef V3_CONFIG_DEBUG_CTRL_REGS
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -596,7 +596,7 @@ int v3_handle_star_read(struct guest_info * core, uint_t msr, struct v3_msr * ds
 
 int v3_handle_star_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
     
-#ifdef CONFIG_DEBUG_SYSCALL_HIJACK
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
     PrintDebug("STAR Write\n");
 #endif
     return 0;
@@ -605,7 +605,7 @@ int v3_handle_star_write(struct guest_info * core, uint_t msr, struct v3_msr src
 
 int v3_handle_lstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
 
-#ifdef CONFIG_DEBUG_SYSCALL_HIJACK
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
     PrintDebug("LSTAR Read\n");
 #endif
     return 0;
@@ -614,16 +614,19 @@ int v3_handle_lstar_read(struct guest_info * core, uint_t msr, struct v3_msr * d
 
 int v3_handle_lstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
     
-#ifdef CONFIG_DEBUG_SYSCALL_HIJACK
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
+    ulong_t entry = ((ulong_t)src.hi << 32) | (ulong_t)src.lo;
     PrintDebug("LSTAR Write\n");
+    PrintDebug("\tKernel syscall entry point: 0x%lx\n", entry);
 #endif
+    
     return 0;
 }
 
 
 int v3_handle_cstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
 
-#ifdef CONFIG_DEBUG_SYSCALL_HIJACK
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
     PrintDebug("CSTAR Read\n");
 #endif
     return 0;
@@ -632,12 +635,24 @@ int v3_handle_cstar_read(struct guest_info * core, uint_t msr, struct v3_msr * d
 
 int v3_handle_cstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
     
-#ifdef CONFIG_DEBUG_SYSCALL_HIJACK
+#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
     PrintDebug("CSTAR Write\n");
 #endif
     return 0;
 }
 
+int v3_handle_seeip_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
+    /* we don't care about reads */
+    return 0;
+}
+
+int v3_handle_seeip_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+#ifdef V3_CONFIG_DEBUG_SYSALL_HIJACK
+    PrintDebug("SYSENTER_EIP Write\n");
+#endif
+    return 0;
+}
+
 
 int v3_handle_vm_cr_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
     /* tell the guest that the BIOS disabled SVM, that way it doesn't get 
index 67e96ae..1783ca1 100644 (file)
@@ -193,7 +193,7 @@ static const ullong_t mask_8 = 0xffffffffffffffffLL;
 void v3_print_instr(struct x86_instr * instr) {
     V3_Print("Instr: %s (Len: %d)\n", op_type_to_str(instr->op_type), instr->instr_length);
 
-    V3_Print("Prefixes= %x\n", *(uint32_t *)&(instr->prefixes));
+    V3_Print("Prefixes= %x\n", instr->prefixes.val);
 
     if (instr->is_str_op) {
        V3_Print("String OP (len=%d)\n", (uint32_t)instr->str_op_length);
index 5abb57b..a6f71e5 100644 (file)
@@ -23,7 +23,7 @@
 #include <palacios/vmm_decoder.h>
 
 
-#ifndef CONFIG_DEBUG_DEV_MGR
+#ifndef V3_CONFIG_DEBUG_DEV_MGR
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -50,7 +50,7 @@ int V3_init_devices() {
     struct v3_device_info * tmp_dev =  __start__v3_devices;
     int i = 0;
 
-#ifdef CONFIG_DEBUG_DEV_MGR
+#ifdef V3_CONFIG_DEBUG_DEV_MGR
     {
        int num_devices = (__stop__v3_devices - __start__v3_devices) / sizeof(struct v3_device_info);
        PrintDebug("%d Virtual devices registered with Palacios\n", num_devices);
index 6040e81..b044b1f 100644 (file)
@@ -25,7 +25,7 @@
 #include <palacios/vm_guest.h>
 
 
-#ifndef CONFIG_DEBUG_NESTED_PAGING
+#ifndef V3_CONFIG_DEBUG_NESTED_PAGING
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -169,7 +169,12 @@ int v3_invalidate_passthrough_addr(struct guest_info * info, addr_t inv_addr) {
 
 
 int v3_invalidate_nested_addr(struct guest_info * info, addr_t inv_addr) {
+
+#ifdef __V3_64BIT__
     v3_cpu_mode_t mode = LONG;
+#else 
+    v3_cpu_mode_t mode = PROTECTED;
+#endif
 
     switch(mode) {
        case REAL:
index b211ad9..ac6f054 100644 (file)
@@ -39,7 +39,7 @@ static inline int handle_passthrough_pagefault_32(struct guest_info * info,
     int pde_index = PDE32_INDEX(fault_addr);
     int pte_index = PTE32_INDEX(fault_addr);
     
-    struct v3_mem_region * region = v3_get_mem_region(info->vm_info, info->cpu_id, fault_addr);
+    struct v3_mem_region * region = v3_get_mem_region(info->vm_info, info->vcpu_id, fault_addr);
 
     if (region == NULL) {
        PrintError("Invalid region in passthrough page fault 32, addr=%p\n", 
@@ -129,12 +129,16 @@ static inline int invalidate_addr_32(struct guest_info * info, addr_t inv_addr)
        return 0;
     } else if (pde[pde_index].large_page) {
        pde[pde_index].present = 0;
+       pde[pde_index].writable = 0;
+       pde[pde_index].user_page = 0;
        return 0;
     }
 
     pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pde[pde_index].pt_base_addr));
 
     pte[pte_index].present = 0;
+    pte[pte_index].writable = 0;
+    pte[pte_index].user_page = 0;
 
     return 0;
 }
index a2bb71d..06e5bb4 100644 (file)
@@ -40,7 +40,7 @@ static inline int handle_passthrough_pagefault_32pae(struct guest_info * info,
     int pde_index = PDE32PAE_INDEX(fault_addr);
     int pte_index = PTE32PAE_INDEX(fault_addr);
 
-    struct v3_mem_region * region =  v3_get_mem_region(info->vm_info, info->cpu_id, fault_addr);
+    struct v3_mem_region * region =  v3_get_mem_region(info->vm_info, info->vcpu_id, fault_addr);
   
     if (region == NULL) {
        PrintError("Invalid region in passthrough page fault 32PAE, addr=%p\n", 
index baae5d5..217373a 100644 (file)
@@ -42,7 +42,7 @@ static inline int handle_passthrough_pagefault_64(struct guest_info * core, addr
     int pde_index  = PDE64_INDEX(fault_addr);
     int pte_index  = PTE64_INDEX(fault_addr);
 
-    struct v3_mem_region * region =  v3_get_mem_region(core->vm_info, core->cpu_id, fault_addr);
+    struct v3_mem_region * region =  v3_get_mem_region(core->vm_info, core->vcpu_id, fault_addr);
     int page_size = PAGE_SIZE_4KB;
 
     if (region == NULL) {
@@ -218,6 +218,8 @@ static inline int invalidate_addr_64(struct guest_info * core, addr_t inv_addr)
        return 0;
     } else if (pdpe[pdpe_index].large_page == 1) { // 1GiB
        pdpe[pdpe_index].present = 0;
+       pdpe[pdpe_index].writable = 0;
+       pdpe[pdpe_index].user_page = 0;
        return 0;
     }
 
@@ -227,12 +229,16 @@ static inline int invalidate_addr_64(struct guest_info * core, addr_t inv_addr)
        return 0;
     } else if (pde[pde_index].large_page == 1) { // 2MiB
        pde[pde_index].present = 0;
+       pde[pde_index].writable = 0;
+       pde[pde_index].user_page = 0;
        return 0;
     }
 
     pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pde[pde_index].pt_base_addr));
 
     pte[pte_index].present = 0; // 4KiB
+    pte[pte_index].writable = 0;
+    pte[pte_index].user_page = 0;
 
     return 0;
 }
index c05e09d..20c6ecb 100644 (file)
@@ -24,7 +24,7 @@
 #include <palacios/vmm_instr_emulator.h>
 #include <palacios/vmm_ctrl_regs.h>
 
-#ifndef CONFIG_DEBUG_EMULATOR
+#ifndef V3_CONFIG_DEBUG_EMULATOR
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
diff --git a/palacios/src/palacios/vmm_execve_hook.c b/palacios/src/palacios/vmm_execve_hook.c
deleted file mode 100644 (file)
index e78052e..0000000
+++ /dev/null
@@ -1,94 +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, Kyle C. Hale <kh@u.norhtwestern.edu>
- * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Kyle C. Hale <kh@u.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/vm_guest.h>
-#include <palacios/vmm_string.h>
-#include <palacios/vmm_syscall_hijack.h>
-#include <palacios/vmm_hashtable.h>
-#include <palacios/vmm_execve_hook.h>
-
-
-
-static int free_hook (struct guest_info * core, struct exec_hook * hook) {
-    list_del(&(hook->hook_node));
-    V3_Free(hook);
-    return 0;
-}
-    
-static uint_t exec_hash_fn (addr_t key) {
-    return v3_hash_long(key, sizeof(void *) * 8);
-}
-
-
-static int exec_eq_fn (addr_t key1, addr_t key2) {
-    return (key1 == key2);
-}
-
-
-int v3_init_exec_hooks (struct guest_info * core) {
-    struct v3_exec_hooks * hooks = &(core->exec_hooks);
-
-    INIT_LIST_HEAD(&(hooks->hook_list));
-
-    hooks->bin_table = v3_create_htable(0, exec_hash_fn, exec_eq_fn);
-    return 0;
-}
-
-
-int v3_deinit_exec_hooks (struct guest_info * core) {
-    struct v3_exec_hooks * hooks = &(core->exec_hooks);
-    struct exec_hook * hook = NULL;
-    struct exec_hook * tmp = NULL;
-    
-    list_for_each_entry_safe(hook, tmp, &(hooks->hook_list), hook_node) {
-        free_hook(core, hook);
-    }
-
-    v3_free_htable(hooks->bin_table, 0, 0);
-
-    return 0;
-}
-
-
-int v3_hook_executable (struct guest_info * core, 
-    const uchar_t * binfile,
-    int (*handler)(struct guest_info * core, void * priv_data),
-    void * priv_data) 
-{
-    struct exec_hook * hook = V3_Malloc(sizeof(struct exec_hook));
-    struct v3_exec_hooks * hooks = &(core->exec_hooks);
-    addr_t key;
-    
-    memset(hook, 0, sizeof(struct exec_hook));
-    
-    hook->handler = handler;
-    hook->priv_data = priv_data;
-    
-    // we hash the name of the file to produce a key
-    key = v3_hash_buffer((uchar_t*)binfile, strlen(binfile));
-
-    v3_htable_insert(hooks->bin_table, key, (addr_t)hook);
-    list_add(&(hook->hook_node), &(hooks->hook_list));
-
-    return 0;
-}
-
-
index 1db9dc6..defad8f 100644 (file)
@@ -144,7 +144,7 @@ int v3_init_core_extensions(struct guest_info * core) {
        if ((ext->impl) && (ext->impl->core_init)) {
            if (ext->impl->core_init(core, ext->priv_data) == -1) {
                PrintError("Error configuring per core extension %s on core %d\n", 
-                          ext->impl->name, core->cpu_id);
+                          ext->impl->name, core->vcpu_id);
                return -1;
            }
        }
index 7970a40..fc6d3d5 100644 (file)
@@ -22,7 +22,7 @@
 #include <palacios/vmm_intr.h>
 
 
-#ifndef CONFIG_DEBUG_HALT
+#ifndef V3_CONFIG_DEBUG_HALT
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
diff --git a/palacios/src/palacios/vmm_instrument.c b/palacios/src/palacios/vmm_instrument.c
deleted file mode 100644 (file)
index 8146338..0000000
+++ /dev/null
@@ -1,135 +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) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Chang Bae <c.s.bae@u.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-
-
-#include <palacios/svm_handler.h>
-#include <palacios/vmm_instrument.h>
-
-#define NO_INSTRUMENTATION
-#include <palacios/vmm_ringbuffer.h>
-#undef NO_INSTRUMENTATION
-
-#define RING_SIZE 2000
-
-static ullong_t last = 0;
-static struct v3_ringbuf * func_ring = NULL;
-
-struct instrumented_func {
-    ullong_t time; 
-    uint_t exiting;
-    void * called_fn;
-    void * calling_fn;
-} __attribute__((packed));
-
-
-
-static void print_instrumentation()  __attribute__((__no_instrument_function__));
-
-void __cyg_profile_func_enter(void * this, void * callsite)   __attribute__((__no_instrument_function__));
-void __cyg_profile_func_exit(void * this, void * callsite)   __attribute__((__no_instrument_function__));
-
-void v3_init_instrumentation() {
-    PrintDebug("Creating Ring Buffer (unit size = %d)\n", (uint_t)sizeof(struct instrumented_func));
-    // initialize
-    func_ring = v3_create_ringbuf(sizeof(struct instrumented_func) * RING_SIZE); //dequeue at every 4095  
-}
-
-
-
-__attribute__((__no_instrument_function__))
-    void __cyg_profile_func_enter(void * this, void * callsite) {
-
-    if (func_ring != NULL) {
-
-       struct instrumented_func tmp_fn;
-       ullong_t now = 0; 
-
-       rdtscll(now);
-
-       //PrintDebug("Entering Function\n");
-
-       if (v3_ringbuf_avail_space(func_ring) < sizeof(struct instrumented_func)) {
-           print_instrumentation();
-       }
-    
-       tmp_fn.time = now - last; // current tsc
-       tmp_fn.exiting = 0; //enter to be 0
-       tmp_fn.called_fn = this; //this
-       tmp_fn.calling_fn = callsite; //callsite
-    
-       //    PrintDebug("Writing Function: fn_data=%p, size=%d\n", 
-       //       (void *)&tmp_fn, (uint_t)sizeof(struct instrumented_func));
-       v3_ringbuf_write(func_ring, (uchar_t *)&tmp_fn, sizeof(struct instrumented_func));  
-
-       rdtscll(last);
-    }
-}
-
-
-__attribute__((__no_instrument_function__))
-    void __cyg_profile_func_exit(void * this, void * callsite){
-
-    if (func_ring != NULL) {
-
-       struct instrumented_func tmp_fn;
-       ullong_t now = 0;
-
-       rdtscll(now);
-    
-       //    PrintDebug("Exiting Function\n");
-
-       if (v3_ringbuf_avail_space(func_ring) < sizeof(struct instrumented_func)) {
-           print_instrumentation();
-       }
-    
-       tmp_fn.time = now - last; // current tsc
-       tmp_fn.exiting = 1; //exit to be 0
-       tmp_fn.called_fn = this; //this
-       tmp_fn.calling_fn = callsite; //callsite
-
-       //    PrintDebug("Writing Function: fn_data=%p, size=%d\n", 
-       //       (void *)&tmp_fn, (uint_t)sizeof(struct instrumented_func));    
-       v3_ringbuf_write(func_ring, (uchar_t *)&tmp_fn, sizeof(struct instrumented_func));
-    
-       rdtscll(last);
-    }
-}
-
-
-
-static void print_instrumentation() {
-
-    struct instrumented_func tmp_fn;
-
-    //  PrintDebug("Printing Instrumentation\n");
-    while (v3_ringbuf_data_len(func_ring) >= sizeof(struct instrumented_func)) {
-    
-       v3_ringbuf_read(func_ring, (uchar_t *)&tmp_fn, sizeof(struct instrumented_func)); 
-    
-       PrintDebug("CYG_PROF: %d %p %p %p\n", 
-                  tmp_fn.exiting, 
-                  (void *)(addr_t)(tmp_fn.time), 
-                  tmp_fn.called_fn, 
-                  tmp_fn.calling_fn);
-    }
-}
-
-
-
index 46e2c70..f8dbd68 100644 (file)
@@ -28,7 +28,7 @@
 #include <palacios/vm_guest_mem.h>
 #include <palacios/vmm_decoder.h>
 
-#ifndef CONFIG_DEBUG_INTERRUPTS
+#ifndef V3_CONFIG_DEBUG_INTERRUPTS
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -333,7 +333,7 @@ int v3_handle_swintr(struct guest_info * core) {
 
     struct v3_swintr_hook * hook = core->intr_core_state.swintr_hooks[vector];
     if (hook == NULL) {
-#ifdef CONFIG_SWINTR_PASSTHROUGH
+#ifdef V3_CONFIG_SWINTR_PASSTHROUGH
         if (v3_hook_passthrough_swintr(core, vector) == -1) {
             PrintDebug("V3 SWintr Handler: Error hooking passthrough swintr\n");
             return -1;
@@ -351,9 +351,9 @@ int v3_handle_swintr(struct guest_info * core) {
         return -1;
     }
 
-    /* at some point we may need to prioritize swints 
+    /* KCH: at some point we may need to prioritize swints 
        so that they finish in time for the next
-       instruction */
+       instruction... */
     core->rip += instr.instr_length;
     return v3_signal_swintr(core, vector);
 }
@@ -515,7 +515,7 @@ intr_type_t v3_get_intr_type(struct guest_info * info) {
        }
     }
 
-#ifdef CONFIG_DEBUG_INTERRUPTS
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
     if (type == V3_INVALID_INTR) {
        PrintError("[get_intr_type] Invalid_Intr\n");
     }
index 0e099e5..3642c3a 100644 (file)
@@ -24,7 +24,7 @@
 
 
 
-#ifndef CONFIG_DEBUG_IO
+#ifndef V3_CONFIG_DEBUG_IO
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
diff --git a/palacios/src/palacios/vmm_linux_syscall_map.c b/palacios/src/palacios/vmm_linux_syscall_map.c
deleted file mode 100644 (file)
index 578450d..0000000
+++ /dev/null
@@ -1,672 +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, Kyle C. Hale <kh@u.norhtwestern.edu>
- * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Kyle C. Hale <kh@u.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_linux_syscall_map.h>
-
-
-char * get_linux_syscall_name32 (uint_t syscall_nr) { 
-
-    switch (syscall_nr) { 
-
-        case 0: return "restart_syscall"; break;
-        case 1: return "exit"; break;
-        case 2: return "fork"; break;
-        case 3: return "read"; break;
-        case 4: return "write"; break;
-        case 5: return "open"; break;
-        case 6: return "close"; break;
-        case 7: return "waitpid"; break;
-        case 8: return "creat"; break;
-        case 9: return "link"; break;
-        case 10: return "unlink"; break;
-        case 11: return "execve"; break;
-        case 12: return "chdir"; break;
-        case 13: return "time"; break;
-        case 14: return "mknod"; break;
-        case 15: return "chmod"; break;
-        case 16: return "lchown"; break;
-        case 17: return "break"; break;
-        case 18: return "oldstat"; break;
-        case 19: return "lseek"; break;
-        case 20: return "getpid"; break;
-        case 21: return "mount"; break;
-        case 22: return "umount"; break;
-        case 23: return "setuid"; break;
-        case 24: return "getuid"; break;
-        case 25: return "stime"; break;
-        case 26: return "ptrace"; break;
-        case 27: return "alarm"; break;
-        case 28: return "oldfstat"; break;
-        case 29: return "pause"; break;
-        case 30: return "utime"; break;
-        case 31: return "stty"; break;
-        case 32: return "gtty"; break;
-        case 33: return "access"; break;
-        case 34: return "nice"; break;
-        case 35: return "ftime"; break;
-        case 36: return "sync"; break;
-        case 37: return "kill"; break;
-        case 38: return "rename"; break;
-        case 39: return "mkdir"; break;
-        case 40: return "rmdir"; break;
-        case 41: return "dup"; break;
-        case 42: return "pipe"; break;
-        case 43: return "times"; break;
-        case 44: return "prof"; break;
-        case 45: return "brk"; break;
-        case 46: return "setgid"; break;
-        case 47: return "getgid"; break;
-        case 48: return "signal"; break;
-        case 49: return "geteuid"; break;
-        case 50: return "getegid"; break;
-        case 51: return "acct"; break;
-        case 52: return "umount2"; break;
-        case 53: return "lock"; break;
-        case 54: return "ioctl"; break;
-        case 55: return "fcntl"; break;
-        case 56: return "mpx"; break;
-        case 57: return "setpgid"; break;
-        case 58: return "ulimit"; break;
-        case 59: return "oldolduname"; break;
-        case 60: return "umask"; break;
-        case 61: return "chroot"; break;
-        case 62: return "ustat"; break;
-        case 63: return "dup2"; break;
-        case 64: return "getppid"; break;
-        case 65: return "getpgrp"; break;
-        case 66: return "setsid"; break;
-        case 67: return "sigaction"; break;
-        case 68: return "sgetmask"; break;
-        case 69: return "ssetmask"; break;
-        case 70: return "setreuid"; break;
-        case 71: return "setregid"; break;
-        case 72: return "sigsuspend"; break;
-        case 73: return "sigpending"; break;
-        case 74: return "sethostname"; break;
-        case 75: return "setrlimit"; break;
-        case 76: return "getrlimit"; break;
-        case 77: return "getrusage"; break;
-        case 78: return "gettimeofday"; break;
-        case 79: return "settimeofday"; break;
-        case 80: return "getgroups"; break;
-        case 81: return "setgroups"; break;
-        case 82: return "select"; break;
-        case 83: return "symlink"; break;
-        case 84: return "oldlstat"; break;
-        case 85: return "readlink"; break;
-        case 86: return "uselib"; break;
-        case 87: return "swapon"; break;
-        case 88: return "reboot"; break;
-        case 89: return "readdir"; break;
-        case 90: return "mmap"; break;
-        case 91: return "munmap"; break;
-        case 92: return "truncate"; break;
-        case 93: return "ftruncate"; break;
-        case 94: return "fchmod"; break;
-        case 95: return "fchown"; break;
-        case 96: return "getpriority"; break;
-        case 97: return "setpriority"; break;
-        case 98: return "profil"; break;
-        case 99: return "statfs"; break;
-        case 100: return "fstatfs"; break;
-        case 101: return "ioperm"; break;
-        case 102: return "socketcall"; break;
-        case 103: return "syslog"; break;
-        case 104: return "setitimer"; break;
-        case 105: return "getitimer"; break;
-        case 106: return "stat"; break;
-        case 107: return "lstat"; break;
-        case 108: return "fstat"; break;
-        case 109: return "olduname"; break;
-        case 110: return "iopl"; break;
-        case 111: return "vhangup"; break;
-        case 112: return "idle"; break;
-        case 113: return "vm86old"; break;
-        case 114: return "wait4"; break;
-        case 115: return "swapoff"; break;
-        case 116: return "sysinfo"; break;
-        case 117: return "ipc"; break;
-        case 118: return "fsync"; break;
-        case 119: return "sigreturn"; break;
-        case 120: return "clone"; break;
-        case 121: return "setdomainname"; break;
-        case 122: return "uname"; break;
-        case 123: return "modify_ldt"; break;
-        case 124: return "adjtimex"; break;
-        case 125: return "mprotect"; break;
-        case 126: return "sigprocmask"; break;
-        case 127: return "create_module"; break;
-        case 128: return "init_module"; break;
-        case 129: return "delete_module"; break;
-        case 130: return "get_kernel_syms"; break;
-        case 131: return "quotactl"; break;
-        case 132: return "getpgid"; break;
-        case 133: return "fchdir"; break;
-        case 134: return "bdflush"; break;
-        case 135: return "sysfs"; break;
-        case 136: return "personality"; break;
-        case 137: return "afs_syscall"; break;
-        case 138: return "setfsuid"; break;
-        case 139: return "setfsgid"; break;
-        case 140: return "_llseek"; break;
-        case 141: return "getdents"; break;
-        case 142: return "_newselect"; break;
-        case 143: return "flock"; break;
-        case 144: return "msync"; break;
-        case 145: return "readv"; break;
-        case 146: return "writev"; break;
-        case 147: return "getsid"; break;
-        case 148: return "fdatasync"; break;
-        case 149: return "_sysctl"; break;
-        case 150: return "mlock"; break;
-        case 151: return "munlock"; break;
-        case 152: return "mlockall"; break;
-        case 153: return "munlockall"; break;
-        case 154: return "sched_setparam"; break;
-        case 155: return "sched_getparam"; break;
-        case 156: return "sched_setscheduler"; break;
-        case 157: return "sched_getscheduler"; break;
-        case 158: return "sched_yield"; break;
-        case 159: return "sched_get_priority_max"; break;
-        case 160: return "sched_get_priority_min"; break;
-        case 161: return "sched_rr_get_interval"; break;
-        case 162: return "nanosleep"; break;
-        case 163: return "mremap"; break;
-        case 164: return "setresuid"; break;
-        case 165: return "getresuid"; break;
-        case 166: return "vm86"; break;
-        case 167: return "query_module"; break;
-        case 168: return "poll"; break;
-        case 169: return "nfsservctl"; break;
-        case 170: return "setresgid"; break;
-        case 171: return "getresgid"; break;
-        case 172: return "prctl"; break;
-        case 173: return "rt_sigreturn"; break;
-        case 174: return "rt_sigaction"; break;
-        case 175: return "rt_sigprocmask"; break;
-        case 176: return "rt_sigpending"; break;
-        case 177: return "rt_sigtimedwait"; break;
-        case 178: return "rt_sigqueueinfo"; break;
-        case 179: return "rt_sigsuspend"; break;
-        case 180: return "pread64"; break;
-        case 181: return "pwrite64"; break;
-        case 182: return "chown"; break;
-        case 183: return "getcwd"; break;
-        case 184: return "capget"; break;
-        case 185: return "capset"; break;
-        case 186: return "sigaltstack"; break;
-        case 187: return "sendfile"; break;
-        case 188: return "getpmsg"; break;
-        case 189: return "putpmsg"; break;
-        case 190: return "vfork"; break;
-        case 191: return "ugetrlimit"; break;
-        case 192: return "mmap2"; break;
-        case 193: return "truncate64"; break;
-        case 194: return "ftruncate64"; break;
-        case 195: return "stat64"; break;
-        case 196: return "lstat64"; break;
-        case 197: return "fstat64"; break;
-        case 198: return "lchown32"; break;
-        case 199: return "getuid32"; break;
-        case 200: return "getgid32"; break;
-        case 201: return "geteuid32"; break;
-        case 202: return "getegid32"; break;
-        case 203: return "setreuid32"; break;
-        case 204: return "setregid32"; break;
-        case 205: return "getgroups32"; break;
-        case 206: return "setgroups32"; break;
-        case 207: return "fchown32"; break;
-        case 208: return "setresuid32"; break;
-        case 209: return "getresuid32"; break;
-        case 210: return "setresgid32"; break;
-        case 211: return "getresgid32"; break;
-        case 212: return "chown32"; break;
-        case 213: return "setuid32"; break;
-        case 214: return "setgid32"; break;
-        case 215: return "setfsuid32"; break;
-        case 216: return "setfsgid32"; break;
-        case 217: return "pivot_root"; break;
-        case 218: return "mincore"; break;
-        case 219: return "madvise1"; break;
-        case 220: return "getdents64"; break;
-        case 221: return "fcntl64"; break;
-        case 224: return "gettid"; break;
-        case 225: return "readahead"; break;
-        case 226: return "setxattr"; break;
-        case 227: return "lsetxattr"; break;
-        case 228: return "fsetxattr"; break;
-        case 229: return "getxattr"; break;
-        case 230: return "lgetxattr"; break;
-        case 231: return "fgetxattr"; break;
-        case 232: return "listxattr"; break;
-        case 233: return "llistxattr"; break;
-        case 234: return "flistxattr"; break;
-        case 235: return "removexattr"; break;
-        case 236: return "lremovexattr"; break;
-        case 237: return "fremovexattr"; break;
-        case 238: return "tkill"; break;
-        case 239: return "sendfile64"; break;
-        case 240: return "futex"; break;
-        case 241: return "sched_setaffinity"; break;
-        case 242: return "sched_getaffinity"; break;
-        case 243: return "set_thread_area"; break;
-        case 244: return "get_thread_area"; break;
-        case 245: return "io_setup"; break;
-        case 246: return "io_destroy"; break;
-        case 247: return "io_getevents"; break;
-        case 248: return "io_submit"; break;
-        case 249: return "io_cancel"; break;
-        case 250: return "fadvise64"; break;
-        case 252: return "exit_group"; break;
-        case 253: return "lookup_dcookie"; break;
-        case 254: return "epoll_create"; break;
-        case 255: return "epoll_ctl"; break;
-        case 256: return "epoll_wait"; break;
-        case 257: return "remap_file_pages"; break;
-        case 258: return "set_tid_address"; break;
-        case 259: return "timer_create"; break;
-        case 260: return "timer_settime"; break;
-        case 261: return "timer_gettime"; break;
-        case 262: return "timer_getoverrun"; break;
-        case 263: return "timer_delete"; break;
-        case 264: return "clock_settime"; break;
-        case 265: return "clock_gettime"; break;
-        case 266: return "clock_getres"; break;
-        case 267: return "clock_nanosleep"; break;
-        case 268: return "statfs64"; break;
-        case 269: return "fstatfs64"; break;
-        case 270: return "tgkill"; break;
-        case 271: return "utimes"; break;
-        case 272: return "fadvise64_64"; break;
-        case 273: return "vserver"; break;
-        case 274: return "mbind"; break;
-        case 275: return "get_mempolicy"; break;
-        case 276: return "set_mempolicy"; break;
-        case 277: return "mq_open"; break;
-        case 278: return "mq_unlink"; break;
-        case 279: return "mq_timedsend"; break;
-        case 280: return "mq_timedreceive"; break;
-        case 281: return "mq_notify"; break;
-        case 282: return "mq_getsetattr"; break;
-        case 283: return "kexec_load"; break;
-        case 284: return "waitid"; break;
-        case 285: return "sys_setaltroot"; break;
-        case 286: return "add_key"; break;
-        case 287: return "request_key"; break;
-        case 288: return "keyctl"; break;
-        case 289: return "ioprio_set"; break;
-        case 290: return "ioprio_get"; break;
-        case 291: return "inotify_init"; break;
-        case 292: return "inotify_add_watch"; break;
-        case 293: return "inotify_rm_watch"; break;
-        case 294: return "migrate_pages"; break;
-        case 295: return "openat"; break;
-        case 296: return "mkdirat"; break;
-        case 297: return "mknodat"; break;
-        case 298: return "fchownat"; break;
-        case 299: return "futimesat"; break;
-        case 300: return "fstatat64"; break;
-        case 301: return "unlinkat"; break;
-        case 302: return "renameat"; break;
-        case 303: return "linkat"; break;
-        case 304: return "symlinkat"; break;
-        case 305: return "readlinkat"; break;
-        case 306: return "fchmodat"; break;
-        case 307: return "faccessat"; break;
-        case 308: return "pselect6"; break;
-        case 309: return "ppoll"; break;
-        case 310: return "unshare"; break;
-        case 311: return "set_robust_list"; break;
-        case 312: return "get_robust_list"; break;
-        case 313: return "splice"; break;
-        case 314: return "sync_file_range"; break;
-        case 315: return "tee"; break;
-        case 316: return "vmsplice"; break;
-        case 317: return "move_pages"; break;
-        case 318: return "getcpu"; break;
-        case 319: return "epoll_pwait"; break;
-        case 320: return "utimensat"; break;
-        case 321: return "signalfd"; break;
-        case 322: return "timerfd_create"; break;
-        case 323: return "eventfd"; break;
-        case 324: return "fallocate"; break;
-        case 325: return "timerfd_settime"; break;
-        case 326: return "timerfd_gettime"; break;
-        case 327: return "signalfd4"; break;
-        case 328: return "eventfd2"; break;
-        case 329: return "epoll_create1"; break;
-        case 330: return "dup3"; break;
-        case 331: return "pipe2"; break;
-        case 332: return "inotify_init1"; break;
-        case 333: return "preadv"; break;
-        case 334: return "pwritev"; break;
-        case 335: return "rt_tgsigqueueinfo"; break;
-        case 336: return "perf_event_open"; break;
-        default: return "UNKNOWN";  break; 
-    }
-}
-
-
-char * get_linux_syscall_name64 (uint_t syscall_nr) { 
-
-    switch (syscall_nr) { 
-
-        case 0: return "read"; break;
-        case 1: return "write"; break;
-        case 2: return "open"; break;
-        case 3: return "close"; break;
-        case 4: return "stat"; break;
-        case 5: return "fstat"; break;
-        case 6: return "lstat"; break;
-        case 7: return "poll"; break;
-        case 8: return "lseek"; break;
-        case 9: return "mmap"; break;
-        case 10: return "mprotect"; break;
-        case 11: return "munmap"; break;
-        case 12: return "brk"; break;
-        case 13: return "rt_sigaction"; break;
-        case 14: return "rt_sigprocmask"; break;
-        case 15: return "rt_sigreturn"; break;
-        case 16: return "ioctl"; break;
-        case 17: return "pread64"; break;
-        case 18: return "pwrite64"; break;
-        case 19: return "readv"; break;
-        case 20: return "writev"; break;
-        case 21: return "access"; break;
-        case 22: return "pipe"; break;
-        case 23: return "select"; break;
-        case 24: return "sched_yield"; break;
-        case 25: return "mremap"; break;
-        case 26: return "msync"; break;
-        case 27: return "mincore"; break;
-        case 28: return "madvise"; break;
-        case 29: return "shmget"; break;
-        case 30: return "shmat"; break;
-        case 31: return "shmctl"; break;
-        case 32: return "dup"; break;
-        case 33: return "dup2"; break;
-        case 34: return "pause"; break;
-        case 35: return "nanosleep"; break;
-        case 36: return "getitimer"; break;
-        case 37: return "alarm"; break;
-        case 38: return "setitimer"; break;
-        case 39: return "getpid"; break;
-        case 40: return "sendfile"; break;
-        case 41: return "socket"; break;
-        case 42: return "connect"; break;
-        case 43: return "accept"; break;
-        case 44: return "sendto"; break;
-        case 45: return "recvfrom"; break;
-        case 46: return "sendmsg"; break;
-        case 47: return "recvmsg"; break;
-        case 48: return "shutdown"; break;
-        case 49: return "bind"; break;
-        case 50: return "listen"; break;
-        case 51: return "getsockname"; break;
-        case 52: return "getpeername"; break;
-        case 53: return "socketpair"; break;
-        case 54: return "setsockopt"; break;
-        case 55: return "getsockopt"; break;
-        case 56: return "clone"; break;
-        case 57: return "fork"; break;
-        case 58: return "vfork"; break;
-        case 59: return "execve"; break;
-        case 60: return "exit"; break;
-        case 61: return "wait4"; break;
-        case 62: return "kill"; break;
-        case 63: return "uname"; break;
-        case 64: return "semget"; break;
-        case 65: return "semop"; break;
-        case 66: return "semctl"; break;
-        case 67: return "shmdt"; break;
-        case 68: return "msgget"; break;
-        case 69: return "msgsnd"; break;
-        case 70: return "msgrcv"; break;
-        case 71: return "msgctl"; break;
-        case 72: return "fcntl"; break;
-        case 73: return "flock"; break;
-        case 74: return "fsync"; break;
-        case 75: return "fdatasync"; break;
-        case 76: return "truncate"; break;
-        case 77: return "ftruncate"; break;
-        case 78: return "getdents"; break;
-        case 79: return "getcwd"; break;
-        case 80: return "chdir"; break;
-        case 81: return "fchdir"; break;
-        case 82: return "rename"; break;
-        case 83: return "mkdir"; break;
-        case 84: return "rmdir"; break;
-        case 85: return "creat"; break;
-        case 86: return "link"; break;
-        case 87: return "unlink"; break;
-        case 88: return "symlink"; break;
-        case 89: return "readlink"; break;
-        case 90: return "chmod"; break;
-        case 91: return "fchmod"; break;
-        case 92: return "chown"; break;
-        case 93: return "fchown"; break;
-        case 94: return "lchown"; break;
-        case 95: return "umask"; break;
-        case 96: return "gettimeofday"; break;
-        case 97: return "getrlimit"; break;
-        case 98: return "getrusage"; break;
-        case 99: return "sysinfo"; break;
-        case 100: return "times"; break;
-        case 101: return "ptrace"; break;
-        case 102: return "getuid"; break;
-        case 103: return "syslog"; break;
-        case 104: return "getgid"; break;
-        case 105: return "setuid"; break;
-        case 106: return "setgid"; break;
-        case 107: return "geteuid"; break;
-        case 108: return "getegid"; break;
-        case 109: return "setpgid"; break;
-        case 110: return "getppid"; break;
-        case 111: return "getpgrp"; break;
-        case 112: return "setsid"; break;
-        case 113: return "setreuid"; break;
-        case 114: return "setregid"; break;
-        case 115: return "getgroups"; break;
-        case 116: return "setgroups"; break;
-        case 117: return "setresuid"; break;
-        case 118: return "getresuid"; break;
-        case 119: return "setresgid"; break;
-        case 120: return "getresgid"; break;
-        case 121: return "getpgid"; break;
-        case 122: return "setfsuid"; break;
-        case 123: return "setfsgid"; break;
-        case 124: return "getsid"; break;
-        case 125: return "capget"; break;
-        case 126: return "capset"; break;
-        case 127: return "rt_sigpending"; break;
-        case 128: return "rt_sigtimedwait"; break;
-        case 129: return "rt_sigqueueinfo"; break;
-        case 130: return "rt_sigsuspend"; break;
-        case 131: return "sigaltstack"; break;
-        case 132: return "utime"; break;
-        case 133: return "mknod"; break;
-        case 134: return "uselib"; break;
-        case 135: return "personality"; break;
-        case 136: return "ustat"; break;
-        case 137: return "statfs"; break;
-        case 138: return "fstatfs"; break;
-        case 139: return "sysfs"; break;
-        case 140: return "getpriority"; break;
-        case 141: return "setpriority"; break;
-        case 142: return "sched_setparam"; break;
-        case 143: return "sched_getparam"; break;
-        case 144: return "sched_setscheduler"; break;
-        case 145: return "sched_getscheduler"; break;
-        case 146: return "sched_get_priority_max"; break;
-        case 147: return "sched_get_priority_min"; break;
-        case 148: return "sched_rr_get_interval"; break;
-        case 149: return "mlock"; break;
-        case 150: return "munlock"; break;
-        case 151: return "mlockall"; break;
-        case 152: return "munlockall"; break;
-        case 153: return "vhangup"; break;
-        case 154: return "modify_ldt"; break;
-        case 155: return "pivot_root"; break;
-        case 156: return "_sysctl"; break;
-        case 157: return "prctl"; break;
-        case 158: return "arch_prctl"; break;
-        case 159: return "adjtimex"; break;
-        case 160: return "setrlimit"; break;
-        case 161: return "chroot"; break;
-        case 162: return "sync"; break;
-        case 163: return "acct"; break;
-        case 164: return "settimeofday"; break;
-        case 165: return "mount"; break;
-        case 166: return "umount2"; break;
-        case 167: return "swapon"; break;
-        case 168: return "swapoff"; break;
-        case 169: return "reboot"; break;
-        case 170: return "sethostname"; break;
-        case 171: return "setdomainname"; break;
-        case 172: return "iopl"; break;
-        case 173: return "ioperm"; break;
-        case 174: return "create_module"; break;
-        case 175: return "init_module"; break;
-        case 176: return "delete_module"; break;
-        case 177: return "get_kernel_syms"; break;
-        case 178: return "query_module"; break;
-        case 179: return "quotactl"; break;
-        case 180: return "nfsservctl"; break;
-        case 181: return "getpmsg"; break;
-        case 182: return "putpmsg"; break;
-        case 183: return "afs_syscall"; break;
-        case 184: return "tuxcall"; break;
-        case 185: return "security"; break;
-        case 186: return "gettid"; break;
-        case 187: return "readahead"; break;
-        case 188: return "setxattr"; break;
-        case 189: return "lsetxattr"; break;
-        case 190: return "fsetxattr"; break;
-        case 191: return "getxattr"; break;
-        case 192: return "lgetxattr"; break;
-        case 193: return "fgetxattr"; break;
-        case 194: return "listxattr"; break;
-        case 195: return "llistxattr"; break;
-        case 196: return "flistxattr"; break;
-        case 197: return "removexattr"; break;
-        case 198: return "lremovexattr"; break;
-        case 199: return "fremovexattr"; break;
-        case 200: return "tkill"; break;
-        case 201: return "time"; break;
-        case 202: return "futex"; break;
-        case 203: return "sched_setaffinity"; break;
-        case 204: return "sched_getaffinity"; break;
-        case 205: return "set_thread_area"; break;
-        case 206: return "io_setup"; break;
-        case 207: return "io_destroy"; break;
-        case 208: return "io_getevents"; break;
-        case 209: return "io_submit"; break;
-        case 210: return "io_cancel"; break;
-        case 211: return "get_thread_area"; break;
-        case 212: return "lookup_dcookie"; break;
-        case 213: return "epoll_create"; break;
-        case 214: return "epoll_ctl_old"; break;
-        case 215: return "epoll_wait_old"; break;
-        case 216: return "remap_file_pages"; break;
-        case 217: return "getdents64"; break;
-        case 218: return "set_tid_address"; break;
-        case 219: return "restart_syscall"; break;
-        case 220: return "semtimedop"; break;
-        case 221: return "fadvise64"; break;
-        case 222: return "timer_create"; break;
-        case 223: return "timer_settime"; break;
-        case 224: return "timer_gettime"; break;
-        case 225: return "timer_getoverrun"; break;
-        case 226: return "timer_delete"; break;
-        case 227: return "clock_settime"; break;
-        case 228: return "clock_gettime"; break;
-        case 229: return "clock_getres"; break;
-        case 230: return "clock_nanosleep"; break;
-        case 231: return "exit_group"; break;
-        case 232: return "epoll_wait"; break;
-        case 233: return "epoll_ctl"; break;
-        case 234: return "tgkill"; break;
-        case 235: return "utimes"; break;
-        case 236: return "vserver"; break;
-        case 237: return "mbind"; break;
-        case 238: return "set_mempolicy"; break;
-        case 239: return "get_mempolicy"; break;
-        case 240: return "mq_open"; break;
-        case 241: return "mq_unlink"; break;
-        case 242: return "mq_timedsend"; break;
-        case 243: return "mq_timedreceive"; break;
-        case 244: return "mq_notify"; break;
-        case 245: return "mq_getsetattr"; break;
-        case 246: return "kexec_load"; break;
-        case 247: return "waitid"; break;
-        case 248: return "add_key"; break;
-        case 249: return "request_key"; break;
-        case 250: return "keyctl"; break;
-        case 251: return "ioprio_set"; break;
-        case 252: return "ioprio_get"; break;
-        case 253: return "inotify_init"; break;
-        case 254: return "inotify_add_watch"; break;
-        case 255: return "inotify_rm_watch"; break;
-        case 256: return "migrate_pages"; break;
-        case 257: return "openat"; break;
-        case 258: return "mkdirat"; break;
-        case 259: return "mknodat"; break;
-        case 260: return "fchownat"; break;
-        case 261: return "futimesat"; break;
-        case 262: return "newfstatat"; break;
-        case 263: return "unlinkat"; break;
-        case 264: return "renameat"; break;
-        case 265: return "linkat"; break;
-        case 266: return "symlinkat"; break;
-        case 267: return "readlinkat"; break;
-        case 268: return "fchmodat"; break;
-        case 269: return "faccessat"; break;
-        case 270: return "pselect6"; break;
-        case 271: return "ppoll"; break;
-        case 272: return "unshare"; break;
-        case 273: return "set_robust_list"; break;
-        case 274: return "get_robust_list"; break;
-        case 275: return "splice"; break;
-        case 276: return "tee"; break;
-        case 277: return "sync_file_range"; break;
-        case 278: return "vmsplice"; break;
-        case 279: return "move_pages"; break;
-        case 280: return "utimensat"; break;
-        case 281: return "epoll_pwait"; break;
-        case 282: return "signalfd"; break;
-        case 283: return "timerfd_create"; break;
-        case 284: return "eventfd"; break;
-        case 285: return "fallocate"; break;
-        case 286: return "timerfd_settime"; break;
-        case 287: return "timerfd_gettime"; break;
-        case 288: return "accept4"; break;
-        case 289: return "signalfd4"; break;
-        case 290: return "eventfd2"; break;
-        case 291: return "epoll_create1"; break;
-        case 292: return "dup3"; break;
-        case 293: return "pipe2"; break;
-        case 294: return "inotify_init1"; break;
-        case 295: return "preadv"; break;
-        case 296: return "pwritev"; break;
-        case 297: return "rt_tgsigqueueinfo"; break;
-        case 298: return "perf_event_open"; break;
-        default: return "UNKNOWN";  break; 
-    }
-}
index c43dcae..6bb9f5a 100644 (file)
@@ -41,7 +41,8 @@ static int mem_offset_hypercall(struct guest_info * info, uint_t hcall_id, void
 static int unhandled_err(struct guest_info * core, addr_t guest_va, addr_t guest_pa, 
                         struct v3_mem_region * reg, pf_error_t access_info) {
 
-    PrintError("Unhandled memory access error\n");
+    PrintError("Unhandled memory access error (gpa=%p, gva=%p, error_code=%d)\n",
+              (void *)guest_pa, (void *)guest_va, *(uint32_t *)&access_info);
 
     v3_print_mem_map(core->vm_info);
 
@@ -65,7 +66,7 @@ int v3_init_mem_map(struct v3_vm_info * vm) {
     map->base_region.guest_start = 0;
     map->base_region.guest_end = mem_pages * PAGE_SIZE_4KB;
 
-#ifdef CONFIG_ALIGNED_PG_ALLOC
+#ifdef V3_CONFIG_ALIGNED_PG_ALLOC
     map->base_region.host_addr = (addr_t)V3_AllocAlignedPages(mem_pages, vm->mem_align);
 #else
     map->base_region.host_addr = (addr_t)V3_AllocPages(mem_pages);
@@ -477,7 +478,7 @@ uint32_t v3_get_max_page_size(struct guest_info * core, addr_t page_addr, v3_cpu
                pg_start = PAGE_ADDR_4MB(page_addr);
                pg_end = (pg_start + PAGE_SIZE_4MB);
 
-               reg = get_overlapping_region(core->vm_info, core->cpu_id, pg_start, pg_end); 
+               reg = get_overlapping_region(core->vm_info, core->vcpu_id, pg_start, pg_end); 
 
                if ((reg) && ((reg->host_addr % PAGE_SIZE_4MB) == 0)) {
                    page_size = PAGE_SIZE_4MB;
@@ -489,7 +490,7 @@ uint32_t v3_get_max_page_size(struct guest_info * core, addr_t page_addr, v3_cpu
                pg_start = PAGE_ADDR_2MB(page_addr);
                pg_end = (pg_start + PAGE_SIZE_2MB);
 
-               reg = get_overlapping_region(core->vm_info, core->cpu_id, pg_start, pg_end);
+               reg = get_overlapping_region(core->vm_info, core->vcpu_id, pg_start, pg_end);
 
                if ((reg) && ((reg->host_addr % PAGE_SIZE_2MB) == 0)) {
                    page_size = PAGE_SIZE_2MB;
@@ -503,7 +504,7 @@ uint32_t v3_get_max_page_size(struct guest_info * core, addr_t page_addr, v3_cpu
                pg_start = PAGE_ADDR_1GB(page_addr);
                pg_end = (pg_start + PAGE_SIZE_1GB);
                
-               reg = get_overlapping_region(core->vm_info, core->cpu_id, pg_start, pg_end);
+               reg = get_overlapping_region(core->vm_info, core->vcpu_id, pg_start, pg_end);
                
                if ((reg) && ((reg->host_addr % PAGE_SIZE_1GB) == 0)) {
                    page_size = PAGE_SIZE_1GB;
@@ -515,7 +516,7 @@ uint32_t v3_get_max_page_size(struct guest_info * core, addr_t page_addr, v3_cpu
                pg_start = PAGE_ADDR_2MB(page_addr);
                pg_end = (pg_start + PAGE_SIZE_2MB);
 
-               reg = get_overlapping_region(core->vm_info, core->cpu_id, pg_start, pg_end);
+               reg = get_overlapping_region(core->vm_info, core->vcpu_id, pg_start, pg_end);
                
                if ((reg) && ((reg->host_addr % PAGE_SIZE_2MB) == 0)) {
                    page_size = PAGE_SIZE_2MB;
index aee8c33..ee632b0 100644 (file)
@@ -169,7 +169,7 @@ static int handle_mem_hook(struct guest_info * core, addr_t guest_va, addr_t gue
            src_reg = reg;
        } else {
            // Note that this should only trigger for string operations
-           src_reg = v3_get_mem_region(core->vm_info, core->cpu_id, src_mem_op_gpa);
+           src_reg = v3_get_mem_region(core->vm_info, core->vcpu_id, src_mem_op_gpa);
        }
 
        if (src_reg == NULL) {
@@ -182,7 +182,7 @@ static int handle_mem_hook(struct guest_info * core, addr_t guest_va, addr_t gue
        // We don't check whether the region is a hook here because it doesn't yet matter.
        // These hva calculations will be true regardless
        if (src_reg->flags.alloced == 0) {
-           src_mem_op_hva = (addr_t)(hooks->hook_hvas_1 + (PAGE_SIZE * core->cpu_id));
+           src_mem_op_hva = (addr_t)(hooks->hook_hvas_1 + (PAGE_SIZE * core->vcpu_id));
        } else {
            // We already have the region so we can do the conversion ourselves
            src_mem_op_hva = (addr_t)V3_VAddr((void *)((src_mem_op_gpa - src_reg->guest_start) + src_reg->host_addr));
@@ -215,7 +215,7 @@ static int handle_mem_hook(struct guest_info * core, addr_t guest_va, addr_t gue
            dst_reg = reg;
        } else {
            // Note that this should only trigger for string operations
-           dst_reg = v3_get_mem_region(core->vm_info, core->cpu_id, dst_mem_op_gpa);
+           dst_reg = v3_get_mem_region(core->vm_info, core->vcpu_id, dst_mem_op_gpa);
        }
 
        if (dst_reg == NULL) {
@@ -228,7 +228,7 @@ static int handle_mem_hook(struct guest_info * core, addr_t guest_va, addr_t gue
        // We don't check whether the region is a hook here because it doesn't yet matter.
        // These hva calculations will be true regardless
        if (dst_reg->flags.alloced == 0) {
-           dst_mem_op_hva = (addr_t)(hooks->hook_hvas_2 + (PAGE_SIZE * core->cpu_id));
+           dst_mem_op_hva = (addr_t)(hooks->hook_hvas_2 + (PAGE_SIZE * core->vcpu_id));
        } else {
            // We already have the region so we can do the conversion ourselves
            dst_mem_op_hva = (addr_t)V3_VAddr((void *)((dst_mem_op_gpa - dst_reg->guest_start) + dst_reg->host_addr));
diff --git a/palacios/src/palacios/vmm_mpi_accel.c b/palacios/src/palacios/vmm_mpi_accel.c
deleted file mode 100644 (file)
index 24326ef..0000000
+++ /dev/null
@@ -1,64 +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, Kyle C. Hale <kh@u.norhtwestern.edu>
- * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Kyle C. Hale <kh@u.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/vm_guest.h>
-#include <palacios/vmm_intr.h>
-#include <palacios/vmm_syscall_hijack.h>
-#include <palacios/vmm_mpi_accel.h>
-#include <palacios/vmm_process_environment.h>
-#include <palacios/vmm_execve_hook.h>
-
-
-int v3_init_mpi_accel (struct guest_info * core) {
-    //binfile = "./envtest";
-    //args[1] = "LD_PRELOAD=./libcwrap.so";
-
-    v3_hook_swintr(core, 0x80, v3_syscall_handler, NULL);
-    v3_hook_syscall(core, 11, v3_sysexecve_handler, NULL);
-    v3_hook_executable(core, "./envtest", v3_mpi_preload_handler, NULL);
-
-    return 0;
-}
-
-
-int v3_deinit_mpi_accel (struct guest_info * core) {
-
-    return 0;
-}
-
-
-int v3_mpi_preload_handler (struct guest_info * core, void * priv_data) {
-
-    char * a[3];
-    a[0] = "TEST=HITHERE";
-    a[1] = "TEST2=/blah/blah/blah";
-    a[2] = "LD_PRELOAD=./libcwrap.so";
-
-    int ret = v3_inject_strings(core, (const char**)NULL, (const char**)a, 0, 3);
-    if (ret == -1) {
-        PrintDebug("Error injecting strings in execve handler\n");
-        return -1;
-    }
-
-    return 0;
-}
-
-
index ec91056..972c800 100644 (file)
@@ -46,7 +46,7 @@ static pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry);
 
 
 
-#ifndef CONFIG_DEBUG_SHADOW_PAGING
+#ifndef V3_CONFIG_DEBUG_SHADOW_PAGING
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
index f39ff4d..6a592b4 100644 (file)
@@ -410,9 +410,9 @@ void PrintPTEntry(struct guest_info * info, page_type_t type, addr_t vaddr, void
 }
 
 
-void PrintHostPageTables(struct guest_info * info, addr_t cr3) {
+void PrintHostPageTables(struct guest_info * info, v3_cpu_mode_t cpu_mode, addr_t cr3) {
     PrintDebug("CR3: %p\n", (void *)cr3);
-    switch (info->cpu_mode) {
+    switch (cpu_mode) {
        case PROTECTED:
            v3_walk_host_pt_32(info, cr3, print_page_walk_cb, NULL);
            break;
@@ -434,6 +434,7 @@ void PrintHostPageTables(struct guest_info * info, addr_t cr3) {
 void PrintGuestPageTables(struct guest_info * info, addr_t cr3) {
     PrintDebug("CR3: %p\n", (void *)cr3);
     switch (info->cpu_mode) {
+       case REAL:
        case PROTECTED:
            v3_walk_guest_pt_32(info, cr3, print_page_walk_cb, NULL);
            break;
diff --git a/palacios/src/palacios/vmm_process_environment.c b/palacios/src/palacios/vmm_process_environment.c
deleted file mode 100644 (file)
index 15f04a0..0000000
+++ /dev/null
@@ -1,589 +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, Kyle C. Hale <kh@u.norhtwestern.edu>
- * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Kyle C. Hale <kh@u.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_decoder.h>
-#include <palacios/vmm_process_environment.h>
-#include <palacios/vm_guest.h>
-#include <palacios/vm_guest_mem.h>
-
-static int v3_copy_chunk_guest32(struct guest_info * core, addr_t gva, uint_t argcnt, uint_t envcnt) {
-
-    int ret = 0, i = 0;
-    addr_t hva;
-    uint32_t tmp_args[core->var_dump.argc];
-    uint32_t tmp_envs[core->var_dump.envc];
-
-    PrintDebug("Initiating copy into guest (32bit)\n");
-    
-    ret = v3_gva_to_hva(core, get_addr_linear(core, gva, &(core->segments.ds)), &hva);
-    if (ret == -1) {
-        PrintDebug("Error translating gva in v3_copy_chunk_2guest\n");
-        return -1;
-    }
-    
-    // copy the env strings (we're moving top-down through the stack)
-    char * host_cursor = (char*) hva;
-    uint32_t guest_cursor = (uint32_t) gva;
-    host_cursor -= strlen(core->var_dump.envp[i]) + 1;
-    guest_cursor -= strlen(core->var_dump.envp[i]) + 1;
-    while (i < core->var_dump.envc) {
-        //PrintDebug("Copying envvar#%d: %s\n", i, core->var_dump.envp[i]);
-        strcpy(host_cursor, core->var_dump.envp[i]);
-        tmp_envs[i] = guest_cursor;
-        i++;
-        if (i != core->var_dump.envc) { 
-            host_cursor -= strlen(core->var_dump.envp[i]) + 1;
-            guest_cursor -= strlen(core->var_dump.envp[i]) + 1;
-        }
-    }
-        
-    // then the arg strings
-    i = 0;
-    host_cursor -= strlen(core->var_dump.argv[i]) + 1;
-    guest_cursor -= strlen(core->var_dump.argv[i]) + 1;
-    while (i < core->var_dump.argc) {
-        //PrintDebug("Copying arg #%d: %s\n", i, core->var_dump.argv[i]);
-        strcpy(host_cursor, core->var_dump.argv[i]);
-        tmp_args[i] = guest_cursor;
-        i++;
-        if (i != core->var_dump.argc) {
-            host_cursor -= strlen(core->var_dump.argv[i]) + 1;
-            guest_cursor -= strlen(core->var_dump.argv[i]) + 1;
-        }
-    }
-
-    
-    // padding
-    host_cursor--;  
-    guest_cursor--;
-    while ((long)host_cursor % 4) {
-        *host_cursor = 0;
-        host_cursor--;
-        guest_cursor--;
-    }
-
-    // null ptr
-    host_cursor -= 4;
-    guest_cursor -= 4;
-    *((uint32_t*)host_cursor) = 0;
-
-    host_cursor -= 4;
-    guest_cursor -= 4;
-    for (i = 0; i < core->var_dump.envc; i++) {
-       *((uint32_t*)host_cursor) = tmp_envs[i];
-        host_cursor -= 4;
-        guest_cursor -= 4;
-    }
-
-    core->vm_regs.rdx = guest_cursor + 4;
-    
-    *((uint32_t*)host_cursor) = 0;
-    host_cursor -= 4;
-    guest_cursor -= 4;
-    for (i = 0; i < core->var_dump.argc; i++) {
-        *((uint32_t*)host_cursor) = tmp_args[i];
-        host_cursor -= 4;
-        guest_cursor -= 4;
-    }
-
-    core->vm_regs.rcx = guest_cursor + 4;
-
-    // free up our temporary storage in the VMM
-    for (i = 0; i < core->var_dump.argc; i++) {
-        V3_Free(core->var_dump.argv[i]);
-    }
-    for (i = 0; i < core->var_dump.envc; i++) {
-        V3_Free(core->var_dump.envp[i]);
-    }
-    
-    V3_Free(core->var_dump.envp);
-    V3_Free(core->var_dump.argv);
-    return 0;
-}
-
-
-static int v3_copy_chunk_vmm32(struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
-
-    addr_t envp, argv;
-    uint_t argc = 0, envc = 0, bytes = 0;
-    char * cursor;
-
-    PrintDebug("Initiating copy into vmm\n");
-
-    int ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rdx, &(core->segments.ds)), &envp);
-    if (ret == -1) {
-        PrintDebug("Error translating address in rdx\n");
-        return 0;
-    }
-
-    ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rcx, &(core->segments.ds)), &argv);
-    if (ret == -1) {
-        PrintDebug("Error translating address in rcx\n");
-        return 0;
-    }
-    
-    cursor = (char*)argv;
-    while (*((uint32_t*)cursor) != 0) {
-        addr_t argvn;
-        ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &argvn);
-        if (ret == -1) {
-            PrintDebug("Error translating address for argvn\n");
-        }
-        argc++;
-        cursor += 4;
-    } 
-
-    /* account for new args */
-    argc += argcnt;
-    core->var_dump.argv = (char**)V3_Malloc(sizeof(char*)*argc);
-    core->var_dump.argc = argc;
-    bytes += sizeof(uint32_t)*argc;
-
-    cursor = (char*)argv;
-    int i = 0;
-    while (*((uint32_t*)cursor) != 0) {
-        addr_t argvn;
-        ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &argvn);
-        if (ret == -1) {
-            PrintDebug("Error translating argvn address\n");
-        }
-    
-        /* malloc room for the string */
-        char * tmpstr = (char*)V3_Malloc(strlen((char*)argvn) + 1);
-
-        /* copy the pointer */
-        core->var_dump.argv[i] = tmpstr; 
-
-        /* copy the string */
-        strncpy(tmpstr, (char*)argvn, strlen((char*)argvn) + 1);
-        i++;
-        cursor += 4;
-        bytes += strlen((char*)argvn) + 1;
-    }
-
-    /* stick in new arg strings */
-    int j = 0;
-    while (j < argcnt) {
-        char * tmpstr = (char*)V3_Malloc(strlen(argstrs[j]) + 1);
-        strncpy(tmpstr, argstrs[i], strlen(argstrs[j]) + 1);
-        core->var_dump.argv[i] = tmpstr;
-        bytes += strlen(argstrs[j]) + 1;
-        i++; j++;
-    }
-        
-    
-    cursor = (char*)envp;
-    while (*((uint32_t*)cursor) != 0) {
-        addr_t envpn;
-        ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &envpn);
-        if (ret == -1) {
-            PrintDebug("Error translating address for envpn\n");
-        }
-        envc++;
-        cursor += 4;
-    } 
-
-    envc += envcnt;
-    core->var_dump.envp = (char**)V3_Malloc(sizeof(char*)*envc);
-    core->var_dump.envc = envc;
-    bytes += sizeof(uint32_t)*envc;
-
-    cursor = (char*)envp;
-    i = 0;
-    while (*((uint32_t*)cursor) != 0) {
-        addr_t envpn;
-        ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &envpn);
-        if (ret == -1) {
-            PrintDebug("Error translating address for envpn\n");
-        }
-        
-        /* malloc room for the string */
-        char * tmpstr = (char*)V3_Malloc(strlen((char*)envpn) + 1);
-        
-        /* copy the pointer */
-        core->var_dump.envp[i] = tmpstr;
-
-        /* deepcopy the string */
-        strncpy(tmpstr, (char*)envpn, strlen((char*)envpn) + 1);
-        i++;    
-        cursor += 4;
-        bytes += strlen((char*)envpn) + 1; 
-    }
-
-    /* put in our new env strings */
-    j = 0;
-    while (j < envcnt) {
-        char * tmpstr = (char*)V3_Malloc(strlen(envstrs[j]) + 1);
-        strncpy(tmpstr, envstrs[j], strlen(envstrs[j]) + 1);
-        core->var_dump.envp[i] = tmpstr;
-        bytes += strlen(envstrs[j]) + 1;
-        i++; j++;
-    }
-
-
-    /* account for padding for strings
-       and 2 null pointers */
-    bytes += (bytes % 4) + 8;
-    core->var_dump.bytes = bytes;
-    return bytes;
-}
-
-
-static int v3_inject_strings32 (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
-
-    addr_t inject_gva;
-    uint_t bytes_needed = 0;
-
-    /* copy out all of the arguments and the environment to the VMM */
-    if ((bytes_needed = v3_copy_chunk_vmm32(core, argstrs, envstrs, argcnt, envcnt)) == -1) {
-        PrintDebug("Error copying out environment and arguments\n");
-        return -1;
-    }
-
-    PrintDebug("environment successfully copied into VMM\n");
-    
-    inject_gva = v3_prepare_guest_stack(core, bytes_needed);
-    if (!inject_gva) {
-        PrintDebug("Not enough space on user stack\n");
-        return -1;
-    }
-
-    v3_copy_chunk_guest32(core, inject_gva, argcnt, envcnt);
-
-    return 0;
-}
-
-
-static int v3_copy_chunk_guest64(struct guest_info * core, addr_t gva, uint_t argcnt, uint_t envcnt) {
-
-    int ret = 0, i = 0;
-    addr_t hva;
-    uint64_t tmp_args[core->var_dump.argc];
-    uint64_t tmp_envs[core->var_dump.envc];
-
-    PrintDebug("Initiating copy into guest (64bit)\n");
-    
-    ret = v3_gva_to_hva(core, get_addr_linear(core, gva, &(core->segments.ds)), &hva);
-    if (ret == -1) {
-        PrintDebug("Error translating gva in v3_copy_chunk_2guest64\n");
-        return -1;
-    }
-    
-    char * host_cursor = (char*) hva;
-    uint64_t guest_cursor = (uint64_t) gva;
-    host_cursor -= strlen(core->var_dump.envp[i]) + 1;
-    guest_cursor -= strlen(core->var_dump.envp[i]) + 1;
-    while (i < core->var_dump.envc) {
-        //PrintDebug("Copying envvar#%d: %s\n", i, core->var_dump.envp[i]);
-        strcpy(host_cursor, core->var_dump.envp[i]);
-        tmp_envs[i] = guest_cursor;
-        i++;
-        if (i != core->var_dump.envc) { 
-            host_cursor -= strlen(core->var_dump.envp[i]) + 1;
-            guest_cursor -= strlen(core->var_dump.envp[i]) + 1;
-        }
-    }
-        
-    i = 0;
-    host_cursor -= strlen(core->var_dump.argv[i]) + 1;
-    guest_cursor -= strlen(core->var_dump.argv[i]) + 1;
-    while (i < core->var_dump.argc) {
-        //PrintDebug("Copying arg #%d: %s\n", i, core->var_dump.argv[i]);
-        strcpy(host_cursor, core->var_dump.argv[i]);
-        tmp_args[i] = guest_cursor;
-        i++;
-        if (i != core->var_dump.argc) {
-            host_cursor -= strlen(core->var_dump.argv[i]) + 1;
-            guest_cursor -= strlen(core->var_dump.argv[i]) + 1;
-        }
-    }
-
-    // padding
-    host_cursor--;  
-    guest_cursor--;
-    while ((long)host_cursor % 8) {
-        *host_cursor = 0;
-        host_cursor--;
-        guest_cursor--;
-    }
-
-    // one null ptr
-    host_cursor -= 8;
-    guest_cursor -= 8;
-    *((uint64_t*)host_cursor) = 0;
-
-    host_cursor -= 8;
-    guest_cursor -= 8;
-    for (i = 0; i < core->var_dump.envc; i++) {
-       *((uint64_t*)host_cursor) = tmp_envs[i];
-        host_cursor -= 8;
-        guest_cursor -= 8;
-    }
-
-    core->vm_regs.rdx = guest_cursor + 8;
-
-    *((uint64_t*)host_cursor) = 0;
-    host_cursor -= 8;
-    guest_cursor -= 8;
-    for (i = 0; i < core->var_dump.argc; i++) {
-        *((uint64_t*)host_cursor) = tmp_args[i];
-        host_cursor -= 8;
-        guest_cursor -= 8;
-    }
-
-    core->vm_regs.rcx = guest_cursor + 8;
-
-    for (i = 0; i < core->var_dump.argc; i++) {
-        V3_Free(core->var_dump.argv[i]);
-    }
-    for (i = 0; i < core->var_dump.envc; i++) {
-        V3_Free(core->var_dump.envp[i]);
-    }
-    
-    V3_Free(core->var_dump.envp);
-    V3_Free(core->var_dump.argv);
-    return 0;
-}
-
-
-static int v3_copy_chunk_vmm64(struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
-
-    addr_t envp, argv;
-    uint_t argc = 0, envc = 0, bytes = 0;
-    char * cursor;
-
-    PrintDebug("Initiating copy into vmm\n");
-
-    int ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rdx, &(core->segments.ds)), &envp);
-    if (ret == -1) {
-        PrintDebug("Error translating address in rdx\n");
-        return 0;
-    }
-
-    ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rcx, &(core->segments.ds)), &argv);
-    if (ret == -1) {
-        PrintDebug("Error translating address in rcx\n");
-        return 0;
-    }
-    
-    cursor = (char*)argv;
-    while (*((uint64_t*)cursor) != 0) {
-        addr_t argvn;
-        ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &argvn);
-        if (ret == -1) {
-            PrintDebug("Error translating address for argvn\n");
-        }
-        argc++;
-        cursor += 8;
-    } 
-    
-    /* account for new strings */
-    argc += argcnt;
-    core->var_dump.argv = (char**)V3_Malloc(sizeof(char*)*argc);
-    core->var_dump.argc = argc;
-    bytes += sizeof(char*)*argc;
-
-    cursor = (char*)argv;
-    int i = 0;
-    while (*((uint64_t*)cursor) != 0) {
-        addr_t argvn;
-        ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &argvn);
-        if (ret == -1) {
-            PrintDebug("Error translating argvn address\n");
-        }
-    
-        /* malloc room for the string */
-        char * tmpstr = (char*)V3_Malloc(strlen((char*)argvn) + 1);
-
-        /* copy the pointer */
-        core->var_dump.argv[i] = tmpstr; 
-
-        /* copy the string */
-        strncpy(tmpstr, (char*)argvn, strlen((char*)argvn) + 1);
-        i++;
-        cursor += 8;
-        bytes += strlen((char*)argvn) + 1;
-    }
-        
-    /* stick in new arg strings */
-    int j = 0;
-    while (j < argcnt) {
-        char * tmpstr = (char*)V3_Malloc(strlen(argstrs[j]) + 1);
-        strncpy(tmpstr, argstrs[j], strlen(argstrs[j]) + 1);
-        core->var_dump.argv[i] = tmpstr;
-        bytes += strlen(argstrs[j]) + 1;
-        i++; j++;
-    }
-
-
-    cursor = (char*)envp;
-    while (*((uint64_t*)cursor) != 0) {
-        addr_t envpn;
-        ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &envpn);
-        if (ret == -1) {
-            PrintDebug("Error translating address for envpn\n");
-        }
-        envc++;
-        cursor += 8;
-    } 
-
-    envc += envcnt;
-    core->var_dump.envp = (char**)V3_Malloc(sizeof(char*)*envc);
-    core->var_dump.envc = envc;
-    bytes += sizeof(uint64_t)*(envc);
-
-
-    cursor = (char*)envp;
-    i = 0;
-    while (*((uint64_t*)cursor) != 0) {
-        addr_t envpn;
-        ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &envpn);
-        if (ret == -1) {
-            PrintDebug("Error translating address for envpn\n");
-        }
-        
-        /* malloc room for the string */
-        char * tmpstr = (char*)V3_Malloc(strlen((char*)envpn) + 1);
-        
-        /* copy the pointer */
-        core->var_dump.envp[i] = tmpstr;
-
-        /* deepcopy the string */
-        strncpy(tmpstr, (char*)envpn, strlen((char*)envpn) + 1);
-        i++;    
-        cursor += 8;
-        bytes += strlen((char*)envpn) + 1; 
-    }
-
-    /* stick in new env strings */
-    j = 0;
-    while (j < envcnt) {
-        char * tmpstr = (char*)V3_Malloc(strlen(envstrs[j]) + 1);
-        strncpy(tmpstr, envstrs[i], strlen(envstrs[j]) + 1);
-        core->var_dump.envp[i] = tmpstr;
-        bytes += strlen(envstrs[j]) + 1;
-        i++; j++;
-    } 
-
-
-    /* account for padding for strings
-       and 2 null pointers */
-    bytes += (bytes % 8) + 16;
-    core->var_dump.bytes = bytes;
-    return bytes;
-}
-
-
-static int v3_inject_strings64 (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
-
-    addr_t inject_gva;
-    uint_t bytes_needed = 0;
-
-    /* copy out all of the arguments and the environment to the VMM */
-    if ((bytes_needed = v3_copy_chunk_vmm64(core, argstrs, envstrs, argcnt, envcnt)) == -1) {
-        PrintDebug("Error copying out environment and arguments\n");
-        return -1;
-    }
-
-    PrintDebug("environment successfully copied into VMM\n");
-    
-    inject_gva = v3_prepare_guest_stack(core, bytes_needed);
-    if (!inject_gva) {
-        PrintDebug("Not enough space on user stack\n");
-        return -1;
-    }
-
-    v3_copy_chunk_guest64(core, inject_gva, argcnt, envcnt);
-    return 0;
-}
-
-
-addr_t v3_prepare_guest_stack (struct guest_info * core, uint_t bytes_needed) {
-
-    /* TODO: check if we've injected a page fault to get more stack space */
-
-    // do we have enough room between esp and the next page boundary?
-    uint_t rem_bytes = 4096 - (core->vm_regs.rsp % 4096);
-
-    if (rem_bytes >= bytes_needed) {
-        return (addr_t)core->vm_regs.rsp;
-    } else {
-        // not enough room, find out how many pages we need (ceiling)
-        uint_t num_pages = (bytes_needed + 4095) / 4096;
-        
-        // check if num_pages are user & writable
-        int i = 0;
-        int pages_ok = 1;
-        addr_t gva = core->vm_regs.rsp + rem_bytes;
-        for (; i < num_pages; i++, gva -= 4096) {
-            if (!v3_gva_can_access(core, gva)) {
-                pages_ok = 0;
-            }
-        }
-
-        if (pages_ok) {
-            return (addr_t)core->vm_regs.rsp;
-        } else {
-    
-            /*
-            // inject a page fault
-            pf_error_t fault_type = {
-                .write = 1,
-                .user = 1
-            };
-
-            // hoping Linux will allocate all pages in between gva and esp 
-            v3_inject_guest_pf(core, gva - (num_pages*4096), fault_type);
-            */
-            return -1;
-        }
-    }
-}
-
-
-/* TODO: give these next to functions the ability to copy into guest stack */
-int v3_replace_arg (struct guest_info * core, uint_t argnum, const char * newval) { 
-
-    return 0;
-}
-
-
-int v3_replace_env (struct guest_info * core, const char * envname, const char * newval) {
-
-    return 0;
-}
-
-
-int v3_inject_strings (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
-    
-    if (core->cpu_mode == LONG || core->cpu_mode == LONG_32_COMPAT) {
-        if (v3_inject_strings64(core, argstrs, envstrs, argcnt, envcnt) == -1) {
-            PrintDebug("Error injecting strings into environment (64)\n");
-            return -1;
-        }
-    } else {
-        if (v3_inject_strings32(core, argstrs, envstrs, argcnt, envcnt) == -1) {
-            PrintDebug("Error injecting strings into environment (32)\n");
-            return -1;
-        }
-    }
-
-    return 0;
-}
index 03cfb6d..20fa255 100644 (file)
@@ -33,19 +33,21 @@ struct v3_queue * v3_create_queue() {
 
 void v3_enqueue(struct v3_queue * queue, addr_t entry) {
     struct v3_queue_entry * q_entry = V3_Malloc(sizeof(struct v3_queue_entry));
+    unsigned int flags = 0;
 
-    v3_lock(queue->lock);
+    flags = v3_lock_irqsave(queue->lock);
     q_entry->entry = entry;
     list_add_tail(&(q_entry->entry_list), &(queue->entries));
     queue->num_entries++;
-    v3_unlock(queue->lock);
+    v3_unlock_irqrestore(queue->lock, flags);
 }
 
 
 addr_t v3_dequeue(struct v3_queue * queue) {
     addr_t entry_val = 0;
+    unsigned int flags = 0;
 
-    v3_lock(queue->lock);
+    flags = v3_lock_irqsave(queue->lock);
     if (!list_empty(&(queue->entries))) {
        struct list_head * q_entry = queue->entries.next;
        struct v3_queue_entry * tmp_entry = list_entry(q_entry, struct v3_queue_entry, entry_list);
@@ -54,7 +56,7 @@ addr_t v3_dequeue(struct v3_queue * queue) {
        list_del(q_entry);
        V3_Free(tmp_entry);
     }
-    v3_unlock(queue->lock);
+    v3_unlock_irqrestore(queue->lock, flags);
 
     return entry_val;
 }
index b46469c..f57ddda 100644 (file)
 
 
 
-#ifdef CONFIG_SHADOW_PAGING_TELEMETRY
+#ifdef V3_CONFIG_SHADOW_PAGING_TELEMETRY
 #include <palacios/vmm_telemetry.h>
 #endif
 
-#ifdef CONFIG_SYMBIOTIC_SWAP
+#ifdef V3_CONFIG_SYMBIOTIC_SWAP
 #include <palacios/vmm_sym_swap.h>
 #endif
 
-#ifndef CONFIG_DEBUG_SHADOW_PAGING
+#ifndef V3_CONFIG_DEBUG_SHADOW_PAGING
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -107,7 +107,7 @@ int V3_deinit_shdw_paging() {
  ***/
 
 
-#ifdef CONFIG_SHADOW_PAGING_TELEMETRY
+#ifdef V3_CONFIG_SHADOW_PAGING_TELEMETRY
 static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
     int i = 0;
     for (i = 0; i < vm->num_cores; i++) {
@@ -136,7 +136,7 @@ int v3_init_shdw_pg_state(struct guest_info * core) {
     }
 
 
-#ifdef CONFIG_SHADOW_PAGING_TELEMETRY
+#ifdef V3_CONFIG_SHADOW_PAGING_TELEMETRY
     v3_add_telemetry_cb(core->vm_info, telemetry_cb, NULL);
 #endif
   
@@ -152,9 +152,6 @@ int v3_deinit_shdw_pg_state(struct guest_info * core) {
        return -1;
     }
 
-#ifdef CONFIG_SHADOW_PAGING_TELEMETRY
-    v3_remove_telemetry_cb(core->vm_info, telemetry_cb, NULL);
-#endif
 
     return 0;
 }
@@ -302,7 +299,7 @@ int v3_handle_shadow_invlpg(struct guest_info * core) {
 int v3_inject_guest_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
     core->ctrl_regs.cr2 = fault_addr;
 
-#ifdef CONFIG_SHADOW_PAGING_TELEMETRY
+#ifdef V3_CONFIG_SHADOW_PAGING_TELEMETRY
     core->shdw_pg_state.guest_faults++;
 #endif
 
index b80f3fa..6403007 100644 (file)
@@ -87,18 +87,18 @@ struct snprintf_arg {
 
 
 
-#if defined(CONFIG_BUILT_IN_STDIO) &&                \
-    ( defined(CONFIG_BUILT_IN_SPRINTF) ||            \
-      defined(CONFIG_BUILT_IN_SNPRINTF) ||           \
-      defined(CONFIG_BUILT_IN_VSPRINTF) ||           \
-      defined(CONFIG_BUILT_IN_VSNRPRINTF ))
+#if defined(V3_CONFIG_BUILT_IN_STDIO) &&                     \
+    ( defined(V3_CONFIG_BUILT_IN_SPRINTF) ||         \
+      defined(V3_CONFIG_BUILT_IN_SNPRINTF) ||        \
+      defined(V3_CONFIG_BUILT_IN_VSPRINTF) ||        \
+      defined(V3_CONFIG_BUILT_IN_VSNRPRINTF ))
 
 static char * ksprintn(char * nbuf, uint64_t num, int base, int *len, int upper);
 static void snprintf_func(int ch, void * arg);
 static int kvprintf(char const * fmt, void (*func)(int, void *), void * arg, int radix, va_list ap);
 
 
-#ifdef CONFIG_BUILT_IN_SPRINTF
+#ifdef V3_CONFIG_BUILT_IN_SPRINTF
 /*
  * Scaled down version of sprintf(3).
  */
@@ -115,7 +115,7 @@ int sprintf(char * buf, const char * cfmt, ...) {
 #endif 
 
 
-#ifdef CONFIG_BUILT_IN_VSPRINTF
+#ifdef V3_CONFIG_BUILT_IN_VSPRINTF
 /*
  * Scaled down version of vsprintf(3).
  */
@@ -129,7 +129,7 @@ int vsprintf(char * buf, const char * cfmt, va_list ap) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_SNPRINTF
+#ifdef V3_CONFIG_BUILT_IN_SNPRINTF
 /*
  * Scaled down version of snprintf(3).
  */
@@ -164,7 +164,7 @@ int vsnprintf(char * str, size_t size, const char * format, va_list ap) {
 
 
 
-#ifdef CONFIG_BUILT_IN_VSNRPRINTF
+#ifdef V3_CONFIG_BUILT_IN_VSNRPRINTF
 /*
  * Kernel version which takes radix argument vsnprintf(3).
  */
@@ -552,7 +552,7 @@ number:
 }
 
 
-#endif // CONFIG_BUILT_IN_STDIO
+#endif // V3_CONFIG_BUILT_IN_STDIO
 
 
 
index effaf32..725fa17 100644 (file)
@@ -41,7 +41,7 @@
 #include <palacios/vmm.h>
 
 
-#ifdef CONFIG_BUILT_IN_MEMSET
+#ifdef V3_CONFIG_BUILT_IN_MEMSET
 void * memset(void * s, int c, size_t n) {
     uchar_t * p = (uchar_t *) s;
 
@@ -54,7 +54,7 @@ void * memset(void * s, int c, size_t n) {
 }
 #endif
 
-#ifdef CONFIG_BUILT_IN_MEMCPY
+#ifdef V3_CONFIG_BUILT_IN_MEMCPY
 void * memcpy(void * dst, const void * src, size_t n) {
     uchar_t * d = (uchar_t *) dst;
     const uchar_t * s = (const uchar_t *)src;
@@ -68,7 +68,7 @@ void * memcpy(void * dst, const void * src, size_t n) {
 }
 #endif
 
-#ifdef CONFIG_BUILT_IN_MEMMOVE
+#ifdef V3_CONFIG_BUILT_IN_MEMMOVE
 void * memmove(void * dst, const void * src, size_t n) {
     uint8_t * tmp = (uint8_t *)V3_Malloc(n);
     
@@ -81,7 +81,7 @@ void * memmove(void * dst, const void * src, size_t n) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_MEMCMP
+#ifdef V3_CONFIG_BUILT_IN_MEMCMP
 int memcmp(const void * s1_, const void * s2_, size_t n) {
     const char * s1 = s1_;
     const char * s2 = s2_;
@@ -102,7 +102,7 @@ int memcmp(const void * s1_, const void * s2_, size_t n) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_STRLEN
+#ifdef V3_CONFIG_BUILT_IN_STRLEN
 size_t strlen(const char * s) {
     size_t len = 0;
 
@@ -116,7 +116,7 @@ size_t strlen(const char * s) {
 
 
 
-#ifdef CONFIG_BUILT_IN_STRNLEN
+#ifdef V3_CONFIG_BUILT_IN_STRNLEN
 /*
  * This it a GNU extension.
  * It is like strlen(), but it will check at most maxlen
@@ -137,7 +137,7 @@ size_t strnlen(const char * s, size_t maxlen) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_STRCMP
+#ifdef V3_CONFIG_BUILT_IN_STRCMP
 int strcmp(const char * s1, const char * s2) {
     while (1) {
        int cmp = (*s1 - *s2);
@@ -152,7 +152,7 @@ int strcmp(const char * s1, const char * s2) {
 }
 #endif
 
-#ifdef CONFIG_BUILT_IN_STRCASECMP
+#ifdef V3_CONFIG_BUILT_IN_STRCASECMP
 int strcasecmp(const char * s1, const char * s2) {
     while (1) {
        int cmp = (tolower(*s1) - tolower(*s2));
@@ -169,7 +169,7 @@ int strcasecmp(const char * s1, const char * s2) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_STRNCMP
+#ifdef V3_CONFIG_BUILT_IN_STRNCMP
 int strncmp(const char * s1, const char * s2, size_t limit) {
     size_t i = 0;
 
@@ -190,7 +190,7 @@ int strncmp(const char * s1, const char * s2, size_t limit) {
 }
 #endif
 
-#ifdef CONFIG_BUILT_IN_STRNCASECMP
+#ifdef V3_CONFIG_BUILT_IN_STRNCASECMP
 int strncasecmp(const char * s1, const char * s2, size_t limit) {
     size_t i = 0;
 
@@ -211,7 +211,7 @@ int strncasecmp(const char * s1, const char * s2, size_t limit) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_STRCAT
+#ifdef V3_CONFIG_BUILT_IN_STRCAT
 char * strcat(char * s1, const char * s2) {
     char * t1 = s1;
 
@@ -225,7 +225,7 @@ char * strcat(char * s1, const char * s2) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_STRNCAT
+#ifdef V3_CONFIG_BUILT_IN_STRNCAT
 char * strncat(char * s1, const char * s2, size_t limit) {
     size_t i = 0;
     char * t1;
@@ -247,7 +247,7 @@ char * strncat(char * s1, const char * s2, size_t limit) {
 
 
 
-#ifdef CONFIG_BUILT_IN_STRCPY
+#ifdef V3_CONFIG_BUILT_IN_STRCPY
 char * strcpy(char * dest, const char * src)
 {
     char *ret = dest;
@@ -262,7 +262,7 @@ char * strcpy(char * dest, const char * src)
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_STRNCPY
+#ifdef V3_CONFIG_BUILT_IN_STRNCPY
 char * strncpy(char * dest, const char * src, size_t limit) {
     char * ret = dest;
 
@@ -280,7 +280,7 @@ char * strncpy(char * dest, const char * src, size_t limit) {
 
 
 
-#ifdef  CONFIG_BUILT_IN_STRDUP
+#ifdef  V3_CONFIG_BUILT_IN_STRDUP
 char * strdup(const char * s1) {
     char *ret;
 
@@ -294,7 +294,7 @@ char * strdup(const char * s1) {
 
 
 
-#ifdef CONFIG_BUILT_IN_ATOI
+#ifdef V3_CONFIG_BUILT_IN_ATOI
 int atoi(const char * buf) {
     int ret = 0;
 
@@ -379,7 +379,7 @@ uint64_t strtox(const char * nptr, char ** endptr) {
 
 
 
-#ifdef CONFIG_BUILT_IN_STRCHR
+#ifdef V3_CONFIG_BUILT_IN_STRCHR
 char * strchr(const char * s, int c) {
     while (*s != '\0') {
        if (*s == c)
@@ -391,7 +391,7 @@ char * strchr(const char * s, int c) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_STRRCHR
+#ifdef V3_CONFIG_BUILT_IN_STRRCHR
 char * strrchr(const char * s, int c) {
     size_t len = strlen(s);
     const char * p = s + len;
@@ -407,7 +407,7 @@ char * strrchr(const char * s, int c) {
 }
 #endif
 
-#ifdef CONFIG_BUILT_IN_STRPBRK
+#ifdef V3_CONFIG_BUILT_IN_STRPBRK
 char * strpbrk(const char * s, const char * accept) {
     size_t setLen = strlen(accept);
 
@@ -425,7 +425,7 @@ char * strpbrk(const char * s, const char * accept) {
 }
 #endif
 
-#ifdef CONFIG_BUILT_IN_STRSPN
+#ifdef V3_CONFIG_BUILT_IN_STRSPN
 size_t strspn(const char * s, const char * accept) {
     int match = 1;
     int cnt = 0;
@@ -449,7 +449,7 @@ size_t strspn(const char * s, const char * accept) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_STRCSPN
+#ifdef V3_CONFIG_BUILT_IN_STRCSPN
 size_t strcspn(const char * s, const char * reject) {
     int match = 0;
     int cnt = 0;
@@ -471,7 +471,7 @@ size_t strcspn(const char * s, const char * reject) {
 #endif
 
 
-#ifdef CONFIG_BUILT_IN_STRSTR
+#ifdef V3_CONFIG_BUILT_IN_STRSTR
 char *strstr(const char *haystack, const char *needle)
 {
         int l1, l2;
index 32ef348..8fda86e 100644 (file)
@@ -56,14 +56,14 @@ int v3_init_symbiotic_vm(struct v3_vm_info * vm) {
        return -1;
     }
 
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
     if (v3_init_symcall_vm(vm) == -1) {
        PrintError("Error intializing global SymCall state\n");
        return -1;
     }
 #endif
 
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
     if (v3_init_symmod_vm(vm, vm->cfg_data->cfg) == -1) {
        PrintError("Error initializing global SymMod state\n");
        return -1;
@@ -77,7 +77,7 @@ int v3_init_symbiotic_vm(struct v3_vm_info * vm) {
 
 int v3_deinit_symbiotic_vm(struct v3_vm_info * vm) {
 
-#ifdef CONFIG_SYMMOD
+#ifdef V3_CONFIG_SYMMOD
     if (v3_deinit_symmod_vm(vm) == -1) {
        PrintError("Error deinitializing global SymMod state\n");
        return -1;
index 7c17c01..caf1a8c 100644 (file)
@@ -56,7 +56,7 @@ static int symspy_msr_write(struct guest_info * core, uint_t msr, struct v3_msr
 
        if (global_state->active == 1) {
            // unmap page
-           struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->cpu_id, 
+           struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->vcpu_id, 
                                                                     (addr_t)global_state->global_guest_pa);
 
            if (old_reg == NULL) {
@@ -84,7 +84,7 @@ static int symspy_msr_write(struct guest_info * core, uint_t msr, struct v3_msr
 
        if (local_state->active == 1) {
            // unmap page
-           struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->cpu_id,
+           struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->vcpu_id,
                                                                     (addr_t)local_state->local_guest_pa);
 
            if (old_reg == NULL) {
@@ -102,7 +102,7 @@ static int symspy_msr_write(struct guest_info * core, uint_t msr, struct v3_msr
        local_state->active = 1;
 
        // map page
-       v3_add_shadow_mem(core->vm_info, core->cpu_id, (addr_t)local_state->local_guest_pa, 
+       v3_add_shadow_mem(core->vm_info, core->vcpu_id, (addr_t)local_state->local_guest_pa, 
                          (addr_t)(local_state->local_guest_pa + PAGE_SIZE_4KB - 1), 
                          local_state->local_page_pa);
     } else {
@@ -136,7 +136,7 @@ int v3_init_symspy_core(struct guest_info * core, struct v3_symspy_local_state *
     state->local_page = (struct v3_symspy_local_page *)V3_VAddr((void *)state->local_page_pa);
     memset(state->local_page, 0, PAGE_SIZE_4KB);
 
-    snprintf((uint8_t *)&(state->local_page->magic), 8, "V3V.%d", core->cpu_id);
+    snprintf((uint8_t *)&(state->local_page->magic), 8, "V3V.%d", core->vcpu_id);
 
     return 0;
 }
diff --git a/palacios/src/palacios/vmm_syscall_hijack.c b/palacios/src/palacios/vmm_syscall_hijack.c
deleted file mode 100644 (file)
index ecf1fb2..0000000
+++ /dev/null
@@ -1,203 +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, Kyle C. Hale <kh@u.norhtwestern.edu>
- * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Kyle C. Hale <kh@u.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/vm_guest_mem.h>
-#include <palacios/vm_guest.h>
-#include <palacios/vmm_intr.h>
-#include <palacios/vmm_decoder.h>
-#include <palacios/vmm_string.h>
-#include <palacios/vmm_shadow_paging.h>
-#include <palacios/vmm_syscall_hijack.h>
-#include <palacios/vmm_linux_syscall_map.h>
-#include <palacios/vmm_process_environment.h>
-#include <palacios/vmm_execve_hook.h>
-
-
-#ifndef CONFIG_DEBUG_SYSCALL_HIJACK
-#undef PrintDebug
-#define PrintDebug(fmt, args...)
-#endif
-
-#define MAX_CHARS 256
-#ifndef max
-    #define max(a, b) ( ((a) > (b)) ? (a) : (b) )
-#endif
-
-
-
-static void print_arg (struct  guest_info * core, v3_reg_t reg, uint8_t argnum) {
-
-    addr_t hva;
-    int ret = 0;
-    
-    PrintDebug("\t ARG%d: INT - %ld\n", argnum, (long) reg);
-
-    if (core->mem_mode == PHYSICAL_MEM) {
-        ret = v3_gpa_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva);
-    }
-    else { 
-        ret = v3_gva_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva);
-    }
-
-    PrintDebug("\t       STR - ");
-    if (ret == -1) {
-        PrintDebug("\n");
-        return;
-    }
-        
-    uint32_t c = max(MAX_CHARS, 4096 - (hva % 4096));
-    int i = 0;
-    for (; i < c && *((char*)(hva + i)) != 0; i++) {
-        PrintDebug("%c", *((char*)(hva + i)));
-    }
-    PrintDebug("\n");
-}
-
-
-static void print_syscall (uint8_t is64, struct guest_info * core) {
-
-    if (is64) {
-        PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name64(core->vm_regs.rax));
-    } else {
-        PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name32(core->vm_regs.rax));
-    }
-
-    print_arg(core, core->vm_regs.rbx, 1);
-    print_arg(core, core->vm_regs.rcx, 2);
-    print_arg(core, core->vm_regs.rdx, 3);
-}
-
-
-int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_data) {
-    uint_t syscall_nr = (uint_t) core->vm_regs.rax;
-    int err = 0;
-
-    struct v3_syscall_hook * hook = core->sc_hook_map.syscall_hooks[syscall_nr];
-    if (hook == NULL) {
-#ifdef CONFIG_SYSCALL_PASSTHROUGH
-        if (v3_hook_passthrough_syscall(core, syscall_nr) == -1) {
-            PrintDebug("Error hooking passthrough syscall\n");
-            return -1;
-        }
-        hook = core->sc_hook_map.syscall_hooks[syscall_nr];
-#else
-        return v3_signal_swintr(core, vector);
-#endif
-    }
-    
-    err = hook->handler(core, syscall_nr, hook->priv_data);
-    if (err == -1) {
-        PrintDebug("V3 Syscall Handler: Error in syscall hook\n");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-static inline struct v3_syscall_hook * get_syscall_hook (struct guest_info * core, uint_t syscall_nr) {
-    return core->sc_hook_map.syscall_hooks[syscall_nr];
-} 
-
-
-int v3_hook_syscall (struct guest_info * core,
-    uint_t syscall_nr,
-    int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data),
-    void * priv_data) 
-{
-    struct v3_syscall_hook * hook = (struct v3_syscall_hook *)V3_Malloc(sizeof(struct v3_syscall_hook));
-
-    // TODO: ensure that software interrupts & SYSENTER are hooked
-    
-    if (hook == NULL) {
-        return -1;
-    }
-
-    if (get_syscall_hook(core, syscall_nr) != NULL) {
-        PrintError("System Call #%d already hooked\n", syscall_nr);
-        return -1;
-    }
-
-    hook->handler = handler;
-    hook->priv_data = priv_data;
-
-    core->sc_hook_map.syscall_hooks[syscall_nr] = hook;
-
-    return 0;
-}
-
-
-static int passthrough_syscall_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
-    print_syscall(0, core);
-    return 0;
-}
-
-
-int v3_hook_passthrough_syscall (struct guest_info * core, uint_t syscall_nr) {
-    
-    int rc = v3_hook_syscall(core, syscall_nr, passthrough_syscall_handler, NULL);
-
-    if (rc) {
-        PrintError("failed to hook syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core);
-        return -1;
-    } else {
-        PrintDebug("hooked syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core);
-        return 0;
-    }
-
-    /* shouldn't get here */
-    return 0;
-}
-
-
-int v3_sysopen_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
-
-    return 0;
-}
-
-
-int v3_sysmount_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
-
-    return 0;
-}
-
-int v3_sysexecve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
-    addr_t hva, key;
-    struct exec_hook * hook;
-    int ret;
-    
-    ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva);
-    if (ret == -1) {
-        PrintDebug("Error translating file path in sysexecve handler\n");
-        return -1;
-    }
-
-    key = v3_hash_buffer((uchar_t*)hva, strlen((uchar_t*)hva));
-    if ((hook = (struct exec_hook*)v3_htable_search(core->exec_hooks.bin_table, key)) != NULL) {
-       if (hook->handler(core, NULL) == -1) {
-            PrintDebug("Error handling execve hook\n");
-            return -1;
-        }
-    } 
-        
-    return 0;
-}
-
index 2fdca40..42e7822 100644 (file)
@@ -24,8 +24,8 @@
 #include <palacios/vmm_sprintf.h>
 
 
-#ifdef CONFIG_TELEMETRY_GRANULARITY
-#define DEFAULT_GRANULARITY CONFIG_TELEMETRY_GRANULARITY
+#ifdef V3_CONFIG_TELEMETRY_GRANULARITY
+#define DEFAULT_GRANULARITY V3_CONFIG_TELEMETRY_GRANULARITY
 #else 
 #define DEFAULT_GRANULARITY 50000
 #endif
@@ -252,7 +252,7 @@ void v3_print_telemetry(struct v3_vm_info * vm) {
        struct exit_event * evt = NULL;
        struct rb_node * node = v3_rb_first(&(core->core_telem.exit_root));
        
-       V3_Print("Exit information for Core %d\n", core->cpu_id);
+       V3_Print("Exit information for Core %d\n", core->vcpu_id);
 
        if (!node) { 
            V3_Print("No information yet for this core\n");
index 357bae4..fc2e37e 100644 (file)
@@ -22,7 +22,7 @@
 #include <palacios/vmm_time.h>
 #include <palacios/vm_guest.h>
 
-#ifndef CONFIG_DEBUG_TIME
+#ifndef V3_CONFIG_DEBUG_TIME
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -399,8 +399,8 @@ void v3_init_time_core(struct guest_info * info) {
 
     if (khz) {
        time_state->guest_cpu_freq = atoi(khz);
-       PrintDebug("Core %d CPU frequency requested at %d khz.\n", 
-                  info->cpu_id, time_state->guest_cpu_freq);
+       PrintDebug("Logical Core %d (vcpu=%d) CPU frequency requested at %d khz.\n", 
+                  info->pcpu_id, info->vcpu_id, time_state->guest_cpu_freq);
     } 
     
     if ( (khz == NULL) || 
@@ -410,8 +410,8 @@ void v3_init_time_core(struct guest_info * info) {
        time_state->guest_cpu_freq = time_state->host_cpu_freq;
     }
 
-    PrintDebug("Core %d CPU frequency set to %d KHz (host CPU frequency = %d KHz).\n", 
-              info->cpu_id, 
+    PrintDebug("Logical Core %d (vcpu=%d) CPU frequency set to %d KHz (host CPU frequency = %d KHz).\n", 
+              info->pcpu_id, info->vcpu_id,
               time_state->guest_cpu_freq, 
               time_state->host_cpu_freq);
 
index 50bba30..f10bed9 100644 (file)
@@ -20,7 +20,7 @@
 #include <palacios/vmm_decoder.h>
 #include <palacios/vmm_instr_decoder.h>
 
-#ifndef CONFIG_DEBUG_DECODER
+#ifndef V3_CONFIG_DEBUG_DECODER
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -75,7 +75,7 @@ int v3_decode(struct guest_info * core, addr_t instr_ptr, struct x86_instr * ins
     int length = 0;
 
 
-    V3_Print("Decoding Instruction at %p\n", (void *)instr_ptr);
+    PrintDebug("Decoding Instruction at %p\n", (void *)instr_ptr);
 
     memset(instr, 0, sizeof(struct x86_instr));
 
@@ -102,7 +102,7 @@ int v3_decode(struct guest_info * core, addr_t instr_ptr, struct x86_instr * ins
 
     form = op_code_to_form((uint8_t *)(instr_ptr + length), &length);
 
-    V3_Print("\t decoded as (%s)\n", op_form_to_str(form));
+    PrintDebug("\t decoded as (%s)\n", op_form_to_str(form));
 
     if (form == INVALID_INSTR) {
        PrintError("Could not find instruction form (%x)\n", *(uint32_t *)(instr_ptr + length));
@@ -121,7 +121,9 @@ int v3_decode(struct guest_info * core, addr_t instr_ptr, struct x86_instr * ins
 
     instr->instr_length += length;
 
+#ifdef V3_CONFIG_DEBUG_DECODER
     v3_print_instr(instr);
+#endif
 
     return 0;
 }
@@ -444,23 +446,40 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
        }
        case INVLPG: {
            uint8_t reg_code = 0;
-           
+
            ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand), &reg_code);
-           
+
            if (ret == -1) {
                PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
                return -1;
            }
-           
+
            instr_ptr += ret;
-           
+
+           instr->num_operands = 1;
+           break;
+       }
+       case LMSW: 
+       case SMSW: {
+           uint8_t reg_code = 0;
+
+           ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand), &reg_code);
+
+           if (ret == -1) {
+               PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
+               return -1;
+           }
+
+           instr_ptr += ret;
+
+           instr->dst_operand.read = 1;
+
            instr->num_operands = 1;
            break;
        }
        case CLTS: {
            // no operands. 
            break;
-           
        }
        default:
            PrintError("Invalid Instruction form: %s\n", op_form_to_str(form));
@@ -517,7 +536,6 @@ static v3_op_type_t op_form_to_type(op_form_t form) {
            return V3_OP_MOVZX;
 
 
-           
        case ADC_2MEM_8:
        case ADC_2MEM:
        case ADC_MEM2_8:
index 80fbfde..9c0fc33 100644 (file)
@@ -35,7 +35,7 @@
 
 
 
-#ifndef CONFIG_DEBUG_DECODER
+#ifndef V3_CONFIG_DEBUG_DECODER
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -342,7 +342,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins
 
     xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
 
-#ifdef CONFIG_DEBUG_DECODER
+#ifdef V3_CONFIG_DEBUG_DECODER
     xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xed_instr);
 
     PrintDebug("iform=%s, iclass=%s\n", xed_iform_enum_t2str(iform), xed_iclass_enum_t2str(iclass));
index 4b4a8f6..d6963c8 100644 (file)
@@ -62,7 +62,7 @@ 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, uint_t old_size, uint_t new_size) {
+static void * tmp_realloc(void * old_ptr, size_t old_size, size_t new_size) {
     void * new_buf = V3_Malloc(new_size);
 
     if (new_buf == NULL) {
@@ -1103,7 +1103,10 @@ static char *ampencode(const char *s, size_t len, char **dst, size_t *dlen,
     const char * e;
     
     for (e = s + len; s != e; s++) {
-        while (*dlen + 10 > *max) *dst = tmp_realloc(*dst, *max, *max += V3_XML_BUFSIZE);
+        while (*dlen + 10 > *max) {
+           *dst = tmp_realloc(*dst, *max, *max + V3_XML_BUFSIZE);
+           *max += V3_XML_BUFSIZE;
+       }
 
         switch (*s) {
         case '\0': return *dst;
@@ -1134,14 +1137,21 @@ static char *toxml_r(struct v3_xml * xml, char **s, size_t *len, size_t *max,
     // parent character content up to this tag
     *s = ampencode(txt + start, xml->off - start, s, len, max, 0);
 
-    while (*len + strlen(xml->name) + 4 > *max) // reallocate s
-        *s = tmp_realloc(*s, *max, *max += V3_XML_BUFSIZE);
+    while (*len + strlen(xml->name) + 4 > *max) {
+       // reallocate s
+        *s = tmp_realloc(*s, *max, *max + V3_XML_BUFSIZE);
+       *max += V3_XML_BUFSIZE;
+    }
+
 
     *len += sprintf(*s + *len, "<%s", xml->name); // open tag
     for (i = 0; xml->attr[i]; i += 2) { // tag attributes
         if (v3_xml_attr(xml, xml->attr[i]) != xml->attr[i + 1]) continue;
-        while (*len + strlen(xml->attr[i]) + 7 > *max) // reallocate s
-            *s = tmp_realloc(*s, *max, *max += V3_XML_BUFSIZE);
+        while (*len + strlen(xml->attr[i]) + 7 > *max) {
+           // reallocate s
+            *s = tmp_realloc(*s, *max, *max + V3_XML_BUFSIZE);
+           *max += V3_XML_BUFSIZE;
+       }
 
         *len += sprintf(*s + *len, " %s=\"", xml->attr[i]);
         ampencode(xml->attr[i + 1], -1, s, len, max, 1);
@@ -1152,8 +1162,11 @@ static char *toxml_r(struct v3_xml * xml, char **s, size_t *len, size_t *max,
     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);
+        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);
@@ -1164,8 +1177,11 @@ static char *toxml_r(struct v3_xml * xml, char **s, size_t *len, size_t *max,
     *s = (xml->child) ? toxml_r(xml->child, s, len, max, 0, attr) //child
                       : ampencode(xml->txt, -1, s, len, max, 0);  //data
     
-    while (*len + strlen(xml->name) + 4 > *max) // reallocate s
-        *s = tmp_realloc(*s, *max, *max += V3_XML_BUFSIZE);
+    while (*len + strlen(xml->name) + 4 > *max) {
+       // reallocate s
+        *s = tmp_realloc(*s, *max, *max + V3_XML_BUFSIZE);
+       *max += V3_XML_BUFSIZE;
+    }
 
     *len += sprintf(*s + *len, "</%s>", xml->name); // close tag
 
index 4326788..106239f 100644 (file)
@@ -7,13 +7,11 @@
  * and the University of New Mexico.  You can find out more at 
  * http://www.v3vee.org
  *
- * Copyright (c) 2008, Peter Dinda <pdinda@northwestern.edu> 
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <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: Peter Dinda <pdinda@northwestern.edu>
- *         Jack Lange <jarusl@cs.northwestern.edu>
+ * 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/vmx_io.h>
 #include <palacios/vmx_msr.h>
 
+#include <palacios/vmx_ept.h>
+#include <palacios/vmx_assist.h>
 #include <palacios/vmx_hw_info.h>
 
-#ifndef CONFIG_DEBUG_VMX
+#ifndef V3_CONFIG_DEBUG_VMX
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -45,9 +45,9 @@
 /* These fields contain the hardware feature sets supported by the local CPU */
 static struct vmx_hw_info hw_info;
 
+extern v3_cpu_arch_t v3_cpu_types[];
 
-static addr_t active_vmcs_ptrs[CONFIG_MAX_CPUS] = { [0 ... CONFIG_MAX_CPUS - 1] = 0};
-static addr_t host_vmcs_ptrs[CONFIG_MAX_CPUS] = { [0 ... CONFIG_MAX_CPUS - 1] = 0};
+static addr_t host_vmcs_ptrs[V3_CONFIG_MAX_CPUS] = { [0 ... V3_CONFIG_MAX_CPUS - 1] = 0};
 
 extern int v3_vmx_launch(struct v3_gprs * vm_regs, struct guest_info * info, struct v3_ctrl_regs * ctrl_regs);
 extern int v3_vmx_resume(struct v3_gprs * vm_regs, struct guest_info * info, struct v3_ctrl_regs * ctrl_regs);
@@ -97,16 +97,14 @@ static addr_t allocate_vmcs() {
 
 
 
-static int init_vmcs_bios(struct guest_info * info, struct vmx_data * vmx_state) {
+static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) {
     int vmx_ret = 0;
-    struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data);
 
     // disable global interrupts for vm state initialization
     v3_disable_ints();
 
     PrintDebug("Loading VMCS\n");
     vmx_ret = vmcs_load(vmx_state->vmcs_ptr_phys);
-    active_vmcs_ptrs[V3_Get_CPU()] = vmx_info->vmcs_ptr_phys;
     vmx_state->state = VMX_UNLAUNCHED;
 
     if (vmx_ret != VMX_SUCCESS) {
@@ -115,6 +113,19 @@ static int init_vmcs_bios(struct guest_info * info, struct vmx_data * vmx_state)
     }
 
 
+    /*** Setup default state from HW ***/
+
+    vmx_state->pin_ctrls.value = hw_info.pin_ctrls.def_val;
+    vmx_state->pri_proc_ctrls.value = hw_info.proc_ctrls.def_val;
+    vmx_state->exit_ctrls.value = hw_info.exit_ctrls.def_val;
+    vmx_state->entry_ctrls.value = hw_info.entry_ctrls.def_val;
+    vmx_state->sec_proc_ctrls.value = hw_info.sec_proc_ctrls.def_val;
+
+    /* Print Control MSRs */
+    PrintDebug("CR0 MSR: %p\n", (void *)(addr_t)hw_info.cr0.value);
+    PrintDebug("CR4 MSR: %p\n", (void *)(addr_t)hw_info.cr4.value);
+
+
 
     /******* Setup Host State **********/
 
@@ -167,205 +178,295 @@ static int init_vmcs_bios(struct guest_info * info, struct vmx_data * vmx_state)
 
     vmx_state->host_state.tr.base = tmp_seg.base;
 
-  
-
-    /********** Setup and VMX Control Fields from MSR ***********/
-    /* Setup IO map */
-
-
-    struct v3_msr tmp_msr;
 
-    v3_get_msr(VMX_PINBASED_CTLS_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
+    /********** Setup VMX Control Fields ***********/
 
     /* Add external interrupts, NMI exiting, and virtual NMI */
-    vmx_state->pin_ctrls.value =  tmp_msr.lo;
     vmx_state->pin_ctrls.nmi_exit = 1;
     vmx_state->pin_ctrls.ext_int_exit = 1;
 
-    v3_get_msr(VMX_PROCBASED_CTLS_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
 
-    vmx_state->pri_proc_ctrls.value = tmp_msr.lo;
-    vmx_state->pri_proc_ctrls.use_io_bitmap = 1;
     vmx_state->pri_proc_ctrls.hlt_exit = 1;
-    vmx_state->pri_proc_ctrls.invlpg_exit = 1;
-    vmx_state->pri_proc_ctrls.use_msr_bitmap = 1;
-    vmx_state->pri_proc_ctrls.pause_exit = 1;
+
+
+    vmx_state->pri_proc_ctrls.pause_exit = 0;
     vmx_state->pri_proc_ctrls.tsc_offset = 1;
-#ifdef CONFIG_TIME_VIRTUALIZE_TSC
+#ifdef V3_CONFIG_TIME_VIRTUALIZE_TSC
     vmx_state->pri_proc_ctrls.rdtsc_exit = 1;
 #endif
 
-    vmx_ret |= check_vmcs_write(VMCS_IO_BITMAP_A_ADDR, (addr_t)V3_PAddr(info->vm_info->io_map.arch_data));
+    /* Setup IO map */
+    vmx_state->pri_proc_ctrls.use_io_bitmap = 1;
+    vmx_ret |= check_vmcs_write(VMCS_IO_BITMAP_A_ADDR, (addr_t)V3_PAddr(core->vm_info->io_map.arch_data));
     vmx_ret |= check_vmcs_write(VMCS_IO_BITMAP_B_ADDR, 
-            (addr_t)V3_PAddr(info->vm_info->io_map.arch_data) + PAGE_SIZE_4KB);
-
+            (addr_t)V3_PAddr(core->vm_info->io_map.arch_data) + PAGE_SIZE_4KB);
 
-    vmx_ret |= check_vmcs_write(VMCS_MSR_BITMAP, (addr_t)V3_PAddr(info->vm_info->msr_map.arch_data));
 
-    v3_get_msr(VMX_EXIT_CTLS_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
-    vmx_state->exit_ctrls.value = tmp_msr.lo;
-    vmx_state->exit_ctrls.host_64_on = 1;
+    vmx_state->pri_proc_ctrls.use_msr_bitmap = 1;
+    vmx_ret |= check_vmcs_write(VMCS_MSR_BITMAP, (addr_t)V3_PAddr(core->vm_info->msr_map.arch_data));
 
-    if ((vmx_state->exit_ctrls.save_efer == 1) || (vmx_state->exit_ctrls.ld_efer == 1)) {
-        vmx_state->ia32e_avail = 1;
-    }
 
-    v3_get_msr(VMX_ENTRY_CTLS_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
-    vmx_state->entry_ctrls.value = tmp_msr.lo;
 
-    {
-       struct vmx_exception_bitmap excp_bmap;
-       excp_bmap.value = 0;
-       
-       excp_bmap.pf = 1;
     
-       vmx_ret |= check_vmcs_write(VMCS_EXCP_BITMAP, excp_bmap.value);
-    }
-    /******* Setup VMXAssist guest state ***********/
 
-    info->rip = 0xd0000;
-    info->vm_regs.rsp = 0x80000;
 
-    struct rflags * flags = (struct rflags *)&(info->ctrl_regs.rflags);
-    flags->rsvd1 = 1;
 
-    /* Print Control MSRs */
-    v3_get_msr(VMX_CR0_FIXED0_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
-    PrintDebug("CR0 MSR: %p\n", (void *)(addr_t)tmp_msr.value);
+#ifdef __V3_64BIT__
+    vmx_state->exit_ctrls.host_64_on = 1;
+#endif
+
+
+    /* Not sure how exactly to handle this... */
+    v3_hook_msr(core->vm_info, EFER_MSR, 
+               &v3_handle_efer_read,
+               &v3_handle_efer_write, 
+               core);
 
-    v3_get_msr(VMX_CR4_FIXED0_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
-    PrintDebug("CR4 MSR: %p\n", (void *)(addr_t)tmp_msr.value);
+    // Or is it this??? 
+    vmx_state->entry_ctrls.ld_efer = 1;
+    vmx_state->exit_ctrls.ld_efer = 1;
+    vmx_state->exit_ctrls.save_efer = 1;
+    /*   ***   */
 
+    vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, CR4_VMXE);
 
-#define GUEST_CR0 0x80000031
-#define GUEST_CR4 0x00002000
-    info->ctrl_regs.cr0 = GUEST_CR0;
-    info->ctrl_regs.cr4 = GUEST_CR4;
 
-    ((struct cr0_32 *)&(info->shdw_pg_state.guest_cr0))->pe = 1;
-   
     /* Setup paging */
-    if (info->shdw_pg_mode == SHADOW_PAGING) {
+    if (core->shdw_pg_mode == SHADOW_PAGING) {
         PrintDebug("Creating initial shadow page table\n");
 
-        if (v3_init_passthrough_pts(info) == -1) {
+        if (v3_init_passthrough_pts(core) == -1) {
             PrintError("Could not initialize passthrough page tables\n");
             return -1;
         }
         
 #define CR0_PE 0x00000001
 #define CR0_PG 0x80000000
+#define CR0_WP 0x00010000 // To ensure mem hooks work
+        vmx_ret |= check_vmcs_write(VMCS_CR0_MASK, (CR0_PE | CR0_PG | CR0_WP));
 
-
-        vmx_ret |= check_vmcs_write(VMCS_CR0_MASK, (CR0_PE | CR0_PG) );
-        vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, CR4_VMXE);
-
-        info->ctrl_regs.cr3 = info->direct_map_pt;
+        core->ctrl_regs.cr3 = core->direct_map_pt;
 
         // vmx_state->pinbased_ctrls |= NMI_EXIT;
 
         /* Add CR exits */
         vmx_state->pri_proc_ctrls.cr3_ld_exit = 1;
         vmx_state->pri_proc_ctrls.cr3_str_exit = 1;
-    }
+       
+       vmx_state->pri_proc_ctrls.invlpg_exit = 1;
+       
+       /* Add page fault exits */
+       vmx_state->excp_bmap.pf = 1;
 
-    // Setup segment registers
-    {
-       struct v3_segment * seg_reg = (struct v3_segment *)&(info->segments);
+       // Setup VMX Assist
+       v3_vmxassist_init(core, vmx_state);
 
-       int i;
+    } else if ((core->shdw_pg_mode == NESTED_PAGING) && 
+              (v3_cpu_types[core->pcpu_id] == V3_VMX_EPT_CPU)) {
 
-       for (i = 0; i < 10; i++) {
-           seg_reg[i].selector = 3 << 3;
-           seg_reg[i].limit = 0xffff;
-           seg_reg[i].base = 0x0;
+#define CR0_PE 0x00000001
+#define CR0_PG 0x80000000
+#define CR0_WP 0x00010000 // To ensure mem hooks work
+        vmx_ret |= check_vmcs_write(VMCS_CR0_MASK, (CR0_PE | CR0_PG | CR0_WP));
+
+        // vmx_state->pinbased_ctrls |= NMI_EXIT;
+
+        /* Disable CR exits */
+       vmx_state->pri_proc_ctrls.cr3_ld_exit = 0;
+       vmx_state->pri_proc_ctrls.cr3_str_exit = 0;
+
+       vmx_state->pri_proc_ctrls.invlpg_exit = 0;
+
+       /* Add page fault exits */
+       //      vmx_state->excp_bmap.pf = 1; // This should never happen..., enabled to catch bugs
+       
+       // Setup VMX Assist
+       v3_vmxassist_init(core, vmx_state);
+
+       /* Enable EPT */
+       vmx_state->pri_proc_ctrls.sec_ctrls = 1; // Enable secondary proc controls
+       vmx_state->sec_proc_ctrls.enable_ept = 1; // enable EPT paging
+
+
+
+       if (v3_init_ept(core, &hw_info) == -1) {
+           PrintError("Error initializing EPT\n");
+           return -1;
        }
 
-       info->segments.cs.selector = 2<<3;
-
-       /* Set only the segment registers */
-       for (i = 0; i < 6; i++) {
-           seg_reg[i].limit = 0xfffff;
-           seg_reg[i].granularity = 1;
-           seg_reg[i].type = 3;
-           seg_reg[i].system = 1;
-           seg_reg[i].dpl = 0;
-           seg_reg[i].present = 1;
-           seg_reg[i].db = 1;
+    } else if ((core->shdw_pg_mode == NESTED_PAGING) && 
+              (v3_cpu_types[core->pcpu_id] == V3_VMX_EPT_UG_CPU)) {
+       int i = 0;
+       // For now we will assume that unrestricted guest mode is assured w/ EPT
+
+
+       core->vm_regs.rsp = 0x00;
+       core->rip = 0xfff0;
+       core->vm_regs.rdx = 0x00000f00;
+       core->ctrl_regs.rflags = 0x00000002; // The reserved bit is always 1
+       core->ctrl_regs.cr0 = 0x60010010; // Set the WP flag so the memory hooks work in real-mode
+
+
+       core->segments.cs.selector = 0xf000;
+       core->segments.cs.limit = 0xffff;
+       core->segments.cs.base = 0x0000000f0000LL;
+
+       // (raw attributes = 0xf3)
+       core->segments.cs.type = 0xb;
+       core->segments.cs.system = 0x1;
+       core->segments.cs.dpl = 0x0;
+       core->segments.cs.present = 1;
+
+
+
+       struct v3_segment * segregs [] = {&(core->segments.ss), &(core->segments.ds), 
+                                         &(core->segments.es), &(core->segments.fs), 
+                                         &(core->segments.gs), NULL};
+
+       for ( i = 0; segregs[i] != NULL; i++) {
+           struct v3_segment * seg = segregs[i];
+       
+           seg->selector = 0x0000;
+           //    seg->base = seg->selector << 4;
+           seg->base = 0x00000000;
+           seg->limit = 0xffff;
+
+
+           seg->type = 0x3;
+           seg->system = 0x1;
+           seg->dpl = 0x0;
+           seg->present = 1;
+           //    seg->granularity = 1;
+
        }
 
-       info->segments.cs.type = 0xb;
 
-       info->segments.ldtr.selector = 0x20;
-       info->segments.ldtr.type = 2;
-       info->segments.ldtr.system = 0;
-       info->segments.ldtr.present = 1;
-       info->segments.ldtr.granularity = 0;
+       core->segments.gdtr.limit = 0x0000ffff;
+       core->segments.gdtr.base = 0x0000000000000000LL;
 
-    
-       /************* Map in GDT and vmxassist *************/
-
-       uint64_t  gdt[] __attribute__ ((aligned(32))) = {
-           0x0000000000000000ULL,              /* 0x00: reserved */
-           0x0000830000000000ULL,              /* 0x08: 32-bit TSS */
-           //0x0000890000000000ULL,            /* 0x08: 32-bit TSS */
-           0x00CF9b000000FFFFULL,              /* 0x10: CS 32-bit */
-           0x00CF93000000FFFFULL,              /* 0x18: DS 32-bit */
-           0x000082000000FFFFULL,              /* 0x20: LDTR 32-bit */
-       };
-
-#define VMXASSIST_GDT   0x10000
-       addr_t vmxassist_gdt = 0;
-
-       if (v3_gpa_to_hva(info, VMXASSIST_GDT, &vmxassist_gdt) == -1) {
-           PrintError("Could not find VMXASSIST GDT destination\n");
+       core->segments.idtr.limit = 0x0000ffff;
+       core->segments.idtr.base = 0x0000000000000000LL;
+
+       core->segments.ldtr.selector = 0x0000;
+       core->segments.ldtr.limit = 0x0000ffff;
+       core->segments.ldtr.base = 0x0000000000000000LL;
+       core->segments.ldtr.type = 2;
+       core->segments.ldtr.present = 1;
+
+       core->segments.tr.selector = 0x0000;
+       core->segments.tr.limit = 0x0000ffff;
+       core->segments.tr.base = 0x0000000000000000LL;
+       core->segments.tr.type = 0xb;
+       core->segments.tr.present = 1;
+
+       //      core->dbg_regs.dr6 = 0x00000000ffff0ff0LL;
+       core->dbg_regs.dr7 = 0x0000000000000400LL;
+
+       /* Enable EPT */
+       vmx_state->pri_proc_ctrls.sec_ctrls = 1; // Enable secondary proc controls
+       vmx_state->sec_proc_ctrls.enable_ept = 1; // enable EPT paging
+       vmx_state->sec_proc_ctrls.unrstrct_guest = 1; // enable unrestricted guest operation
+
+
+       /* Disable shadow paging stuff */
+       vmx_state->pri_proc_ctrls.cr3_ld_exit = 0;
+       vmx_state->pri_proc_ctrls.cr3_str_exit = 0;
+
+       vmx_state->pri_proc_ctrls.invlpg_exit = 0;
+
+
+       if (v3_init_ept(core, &hw_info) == -1) {
+           PrintError("Error initializing EPT\n");
            return -1;
        }
 
-       memcpy((void *)vmxassist_gdt, gdt, sizeof(uint64_t) * 5);
-        
-       info->segments.gdtr.base = VMXASSIST_GDT;
-
-#define VMXASSIST_TSS   0x40000
-       uint64_t vmxassist_tss = VMXASSIST_TSS;
-       gdt[0x08 / sizeof(gdt[0])] |=
-           ((vmxassist_tss & 0xFF000000) << (56 - 24)) |
-           ((vmxassist_tss & 0x00FF0000) << (32 - 16)) |
-           ((vmxassist_tss & 0x0000FFFF) << (16)) |
-           (8392 - 1);
-
-       info->segments.tr.selector = 0x08;
-       info->segments.tr.base = vmxassist_tss;
-
-       //info->segments.tr.type = 0x9; 
-       info->segments.tr.type = 0x3;
-       info->segments.tr.system = 0;
-       info->segments.tr.present = 1;
-       info->segments.tr.granularity = 0;
+    } else {
+       PrintError("Invalid Virtual paging mode\n");
+       return -1;
     }
-    // setup VMXASSIST
-    { 
-#define VMXASSIST_START 0x000d0000
-       extern uint8_t v3_vmxassist_start[];
-       extern uint8_t v3_vmxassist_end[];
-       addr_t vmxassist_dst = 0;
-
-       if (v3_gpa_to_hva(info, VMXASSIST_START, &vmxassist_dst) == -1) {
-           PrintError("Could not find VMXASSIST destination\n");
+
+
+    // hook vmx msrs
+
+    // Setup SYSCALL/SYSENTER MSRs in load/store area
+    
+    // save STAR, LSTAR, FMASK, KERNEL_GS_BASE MSRs in MSR load/store area
+    {
+#define IA32_STAR 0xc0000081
+#define IA32_LSTAR 0xc0000082
+#define IA32_FMASK 0xc0000084
+#define IA32_KERN_GS_BASE 0xc0000102
+
+#define IA32_CSTAR 0xc0000083 // Compatibility mode STAR (ignored for now... hopefully its not that important...)
+
+       int msr_ret = 0;
+
+       struct vmcs_msr_entry * exit_store_msrs = NULL;
+       struct vmcs_msr_entry * exit_load_msrs = NULL;
+       struct vmcs_msr_entry * entry_load_msrs = NULL;;
+       int max_msrs = (hw_info.misc_info.max_msr_cache_size + 1) * 4;
+
+       V3_Print("Setting up MSR load/store areas (max_msr_count=%d)\n", max_msrs);
+
+       if (max_msrs < 4) {
+           PrintError("Max MSR cache size is too small (%d)\n", max_msrs);
            return -1;
        }
 
-       memcpy((void *)vmxassist_dst, v3_vmxassist_start, v3_vmxassist_end - v3_vmxassist_start);
+       vmx_state->msr_area = V3_VAddr(V3_AllocPages(1));
+
+       if (vmx_state->msr_area == NULL) {
+           PrintError("could not allocate msr load/store area\n");
+           return -1;
+       }
+
+       msr_ret |= check_vmcs_write(VMCS_EXIT_MSR_STORE_CNT, 4);
+       msr_ret |= check_vmcs_write(VMCS_EXIT_MSR_LOAD_CNT, 4);
+       msr_ret |= check_vmcs_write(VMCS_ENTRY_MSR_LOAD_CNT, 4);
+       
+       
+       exit_store_msrs = (struct vmcs_msr_entry *)(vmx_state->msr_area);
+       exit_load_msrs = (struct vmcs_msr_entry *)(vmx_state->msr_area + (sizeof(struct vmcs_msr_entry) * 4));
+       entry_load_msrs = (struct vmcs_msr_entry *)(vmx_state->msr_area + (sizeof(struct vmcs_msr_entry) * 8));
+
+
+       exit_store_msrs[0].index = IA32_STAR;
+       exit_store_msrs[1].index = IA32_LSTAR;
+       exit_store_msrs[2].index = IA32_FMASK;
+       exit_store_msrs[3].index = IA32_KERN_GS_BASE;
+       
+       memcpy(exit_store_msrs, exit_load_msrs, sizeof(struct vmcs_msr_entry) * 4);
+       memcpy(exit_store_msrs, entry_load_msrs, sizeof(struct vmcs_msr_entry) * 4);
+
+       
+       v3_get_msr(IA32_STAR, &(exit_load_msrs[0].hi), &(exit_load_msrs[0].lo));
+       v3_get_msr(IA32_LSTAR, &(exit_load_msrs[1].hi), &(exit_load_msrs[1].lo));
+       v3_get_msr(IA32_FMASK, &(exit_load_msrs[2].hi), &(exit_load_msrs[2].lo));
+       v3_get_msr(IA32_KERN_GS_BASE, &(exit_load_msrs[3].hi), &(exit_load_msrs[3].lo));
+
+       msr_ret |= check_vmcs_write(VMCS_EXIT_MSR_STORE_ADDR, (addr_t)V3_PAddr(exit_store_msrs));
+       msr_ret |= check_vmcs_write(VMCS_EXIT_MSR_LOAD_ADDR, (addr_t)V3_PAddr(exit_load_msrs));
+       msr_ret |= check_vmcs_write(VMCS_ENTRY_MSR_LOAD_ADDR, (addr_t)V3_PAddr(entry_load_msrs));
+
     }    
 
-    /*** Write all the info to the VMCS ***/
+    /* Sanity check ctrl/reg fields against hw_defaults */
+
 
-#define DEBUGCTL_MSR 0x1d9
-    v3_get_msr(DEBUGCTL_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
-    vmx_ret |= check_vmcs_write(VMCS_GUEST_DBG_CTL, tmp_msr.value);
 
-    info->dbg_regs.dr7 = 0x400;
+
+    /*** Write all the info to the VMCS ***/
+  
+    /*
+    {
+       // IS THIS NECESSARY???
+#define DEBUGCTL_MSR 0x1d9
+       struct v3_msr tmp_msr;
+       v3_get_msr(DEBUGCTL_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
+       vmx_ret |= check_vmcs_write(VMCS_GUEST_DBG_CTL, tmp_msr.value);
+       core->dbg_regs.dr7 = 0x400;
+    }
+    */
 
 #ifdef __V3_64BIT__
     vmx_ret |= check_vmcs_write(VMCS_LINK_PTR, (addr_t)0xffffffffffffffffULL);
@@ -374,19 +475,19 @@ static int init_vmcs_bios(struct guest_info * info, struct vmx_data * vmx_state)
     vmx_ret |= check_vmcs_write(VMCS_LINK_PTR_HIGH, (addr_t)0xffffffffUL);
 #endif
 
-    if (v3_update_vmcs_ctrl_fields(info)) {
+
+
+    if (v3_update_vmcs_ctrl_fields(core)) {
         PrintError("Could not write control fields!\n");
         return -1;
     }
     
-    if (v3_update_vmcs_host_state(info)) {
+    if (v3_update_vmcs_host_state(core)) {
         PrintError("Could not write host state\n");
         return -1;
     }
 
-
-    vmx_state->assist_state = VMXASSIST_DISABLED;
-
     // reenable global interrupts for vm state initialization now
     // that the vm state is initialized. If another VM kicks us off, 
     // it'll update our vmx state so that we know to reload ourself
@@ -395,11 +496,12 @@ static int init_vmcs_bios(struct guest_info * info, struct vmx_data * vmx_state)
     return 0;
 }
 
-int v3_init_vmx_vmcs(struct guest_info * info, v3_vm_class_t vm_class) {
+int v3_init_vmx_vmcs(struct guest_info * core, v3_vm_class_t vm_class) {
     struct vmx_data * vmx_state = NULL;
     int vmx_ret = 0;
     
     vmx_state = (struct vmx_data *)V3_Malloc(sizeof(struct vmx_data));
+    memset(vmx_state, 0, sizeof(struct vmx_data));
 
     PrintDebug("vmx_data pointer: %p\n", (void *)vmx_state);
 
@@ -408,10 +510,10 @@ int v3_init_vmx_vmcs(struct guest_info * info, v3_vm_class_t vm_class) {
 
     PrintDebug("VMCS pointer: %p\n", (void *)(vmx_state->vmcs_ptr_phys));
 
-    info->vmm_data = vmx_state;
+    core->vmm_data = vmx_state;
     vmx_state->state = VMX_UNLAUNCHED;
 
-    PrintDebug("Initializing VMCS (addr=%p)\n", info->vmm_data);
+    PrintDebug("Initializing VMCS (addr=%p)\n", core->vmm_data);
     
     // TODO: Fix vmcs fields so they're 32-bit
 
@@ -425,12 +527,18 @@ int v3_init_vmx_vmcs(struct guest_info * info, v3_vm_class_t vm_class) {
 
     if (vm_class == V3_PC_VM) {
        PrintDebug("Initializing VMCS\n");
-       init_vmcs_bios(info, vmx_state);
+       if (init_vmcs_bios(core, vmx_state) == -1) {
+           PrintError("Error initializing VMCS to BIOS state\n");
+           return -1;
+       }
     } else {
        PrintError("Invalid VM Class\n");
        return -1;
     }
 
+    PrintDebug("Serializing VMCS: %p\n", (void *)vmx_state->vmcs_ptr_phys);
+    vmx_ret = vmcs_clear(vmx_state->vmcs_ptr_phys);
+
     return 0;
 }
 
@@ -439,6 +547,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_Free(vmx_state);
 
@@ -452,8 +561,8 @@ static int update_irq_exit_state(struct guest_info * info) {
     check_vmcs_read(VMCS_IDT_VECTOR_INFO, &(idt_vec_info.value));
 
     if ((info->intr_core_state.irq_started == 1) && (idt_vec_info.valid == 0)) {
-#ifdef CONFIG_DEBUG_INTERRUPTS
-        PrintDebug("Calling v3_injecting_intr\n");
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
+        V3_Print("Calling v3_injecting_intr\n");
 #endif
         info->intr_core_state.irq_started = 0;
         v3_injecting_intr(info, info->intr_core_state.irq_vector, V3_EXTERNAL_IRQ);
@@ -484,15 +593,15 @@ static int update_irq_entry_state(struct guest_info * info) {
             check_vmcs_write(VMCS_ENTRY_EXCP_ERR, info->excp_state.excp_error_code);
             int_info.error_code = 1;
 
-#ifdef CONFIG_DEBUG_INTERRUPTS
-            PrintDebug("Injecting exception %d with error code %x\n", 
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
+            V3_Print("Injecting exception %d with error code %x\n", 
                     int_info.vector, info->excp_state.excp_error_code);
 #endif
         }
 
         int_info.valid = 1;
-#ifdef CONFIG_DEBUG_INTERRUPTS
-        PrintDebug("Injecting exception %d (EIP=%p)\n", int_info.vector, (void *)(addr_t)info->rip);
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
+        V3_Print("Injecting exception %d (EIP=%p)\n", int_info.vector, (void *)(addr_t)info->rip);
 #endif
         check_vmcs_write(VMCS_ENTRY_INT_INFO, int_info.value);
 
@@ -503,8 +612,8 @@ static int update_irq_entry_state(struct guest_info * info) {
        
         if ((info->intr_core_state.irq_started == 1) && (idt_vec_info.valid == 1)) {
 
-#ifdef CONFIG_DEBUG_INTERRUPTS
-            PrintDebug("IRQ pending from previous injection\n");
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
+            V3_Print("IRQ pending from previous injection\n");
 #endif
 
             // Copy the IDT vectoring info over to reinject the old interrupt
@@ -530,8 +639,8 @@ static int update_irq_entry_state(struct guest_info * info) {
                     ent_int.error_code = 0;
                     ent_int.valid = 1;
 
-#ifdef CONFIG_DEBUG_INTERRUPTS
-                    PrintDebug("Injecting Interrupt %d at exit %u(EIP=%p)\n", 
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
+                    V3_Print("Injecting Interrupt %d at exit %u(EIP=%p)\n", 
                               info->intr_core_state.irq_vector, 
                               (uint32_t)info->num_exits, 
                               (void *)(addr_t)info->rip);
@@ -575,8 +684,8 @@ static int update_irq_entry_state(struct guest_info * info) {
 
         check_vmcs_read(VMCS_EXIT_INSTR_LEN, &instr_len);
 
-#ifdef CONFIG_DEBUG_INTERRUPTS
-        PrintDebug("Enabling Interrupt-Window exiting: %d\n", instr_len);
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
+        V3_Print("Enabling Interrupt-Window exiting: %d\n", instr_len);
 #endif
 
         vmx_info->pri_proc_ctrls.int_wndw_exit = 1;
@@ -644,16 +753,15 @@ int v3_vmx_enter(struct guest_info * info) {
     v3_disable_ints();
 
 
-    if (active_vmcs_ptrs[V3_Get_CPU()] != vmx_info->vmcs_ptr_phys) {
+    if (vmcs_store() != vmx_info->vmcs_ptr_phys) {
        vmcs_load(vmx_info->vmcs_ptr_phys);
-       active_vmcs_ptrs[V3_Get_CPU()] = vmx_info->vmcs_ptr_phys;
     }
 
 
     v3_vmx_restore_vmcs(info);
 
 
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
     if (info->sym_core_state.symcall_state.sym_call_active == 0) {
        update_irq_entry_state(info);
     }
@@ -675,6 +783,12 @@ int v3_vmx_enter(struct guest_info * info) {
     check_vmcs_write(VMCS_TSC_OFFSET_HIGH, tsc_offset_high);
     check_vmcs_write(VMCS_TSC_OFFSET, tsc_offset_low);
 
+    if (v3_update_vmcs_host_state(info)) {
+       v3_enable_ints();
+        PrintError("Could not write host state\n");
+        return -1;
+    }
+
 
     if (vmx_info->state == VMX_UNLAUNCHED) {
        vmx_info->state = VMX_LAUNCHED;
@@ -691,8 +805,10 @@ int v3_vmx_enter(struct guest_info * info) {
        uint32_t error = 0;
 
         vmcs_read(VMCS_INSTR_ERR, &error);
-        PrintError("VMENTRY Error: %d\n", error);
 
+       v3_enable_ints();
+
+        PrintError("VMENTRY Error: %d\n", error);
        return -1;
     }
 
@@ -718,12 +834,16 @@ int v3_vmx_enter(struct guest_info * info) {
     check_vmcs_read(VMCS_EXIT_INT_ERR, &(exit_info.int_err));
     check_vmcs_read(VMCS_GUEST_LINEAR_ADDR, &(exit_info.guest_linear_addr));
 
+    if (info->shdw_pg_mode == NESTED_PAGING) {
+       check_vmcs_read(VMCS_GUEST_PHYS_ADDR, &(exit_info.ept_fault_addr));
+    }
+
     //PrintDebug("VMX Exit taken, id-qual: %u-%lu\n", exit_info.exit_reason, exit_info.exit_qual);
 
     exit_log[info->num_exits % 10] = exit_info;
 
 
-#ifdef CONFIG_SYMCALL
+#ifdef V3_CONFIG_SYMCALL
     if (info->sym_core_state.symcall_state.sym_call_active == 0) {
        update_irq_exit_state(info);
     }
@@ -737,8 +857,8 @@ int v3_vmx_enter(struct guest_info * info) {
         vmx_info->pri_proc_ctrls.int_wndw_exit = 0;
         vmcs_write(VMCS_PROC_CTRLS, vmx_info->pri_proc_ctrls.value);
 
-#ifdef CONFIG_DEBUG_INTERRUPTS
-        PrintDebug("Interrupts available again! (RIP=%llx)\n", info->rip);
+#ifdef V3_CONFIG_DEBUG_INTERRUPTS
+       V3_Print("Interrupts available again! (RIP=%llx)\n", info->rip);
 #endif
     }
 
@@ -759,30 +879,30 @@ int v3_vmx_enter(struct guest_info * info) {
 
 int v3_start_vmx_guest(struct guest_info * info) {
 
-    PrintDebug("Starting VMX core %u\n", info->cpu_id);
+    PrintDebug("Starting VMX core %u\n", info->vcpu_id);
 
-    if (info->cpu_id == 0) {
+    if (info->vcpu_id == 0) {
        info->core_run_state = CORE_RUNNING;
        info->vm_info->run_state = VM_RUNNING;
     } else {
 
-        PrintDebug("VMX core %u: Waiting for core initialization\n", info->cpu_id);
+        PrintDebug("VMX core %u: Waiting for core initialization\n", info->vcpu_id);
 
         while (info->core_run_state == CORE_STOPPED) {
             v3_yield(info);
-            //PrintDebug("VMX core %u: still waiting for INIT\n",info->cpu_id);
+            //PrintDebug("VMX core %u: still waiting for INIT\n",info->vcpu_id);
         }
        
-       PrintDebug("VMX core %u initialized\n", info->cpu_id);
+       PrintDebug("VMX core %u initialized\n", info->vcpu_id);
     }
 
 
     PrintDebug("VMX core %u: I am starting at CS=0x%x (base=0x%p, limit=0x%x),  RIP=0x%p\n",
-               info->cpu_id, info->segments.cs.selector, (void *)(info->segments.cs.base),
+               info->vcpu_id, info->segments.cs.selector, (void *)(info->segments.cs.base),
                info->segments.cs.limit, (void *)(info->rip));
 
 
-    PrintDebug("VMX core %u: Launching VMX VM\n", info->cpu_id);
+    PrintDebug("VMX core %u: Launching VMX VM on logical core %u\n", info->vcpu_id, info->pcpu_id);
 
     v3_start_time(info);
 
@@ -850,12 +970,27 @@ int v3_is_vmx_capable() {
 }
 
 
+int v3_reset_vmx_vm_core(struct guest_info * core, addr_t rip) {
+    // init vmcs bios
+    
+    if ((core->shdw_pg_mode == NESTED_PAGING) && 
+       (v3_cpu_types[core->pcpu_id] == V3_VMX_EPT_UG_CPU)) {
+       // easy 
+        core->rip = 0;
+       core->segments.cs.selector = rip << 8;
+       core->segments.cs.limit = 0xffff;
+       core->segments.cs.base = rip << 12;
+    } else {
+       core->vm_regs.rdx = core->vcpu_id;
+       core->vm_regs.rbx = rip;
+    }
 
+    return 0;
+}
 
 
 
 void v3_init_vmx_cpu(int cpu_id) {
-    extern v3_cpu_arch_t v3_cpu_types[];
 
     if (cpu_id == 0) {
        if (v3_init_vmx_hw(&hw_info) == -1) {
@@ -864,7 +999,6 @@ void v3_init_vmx_cpu(int cpu_id) {
        }
     }
 
-
     enable_vmx();
 
 
@@ -874,16 +1008,28 @@ void v3_init_vmx_cpu(int cpu_id) {
     PrintDebug("VMXON pointer: 0x%p\n", (void *)host_vmcs_ptrs[cpu_id]);
 
     if (vmx_on(host_vmcs_ptrs[cpu_id]) == VMX_SUCCESS) {
-        PrintDebug("VMX Enabled\n");
+        V3_Print("VMX Enabled\n");
     } else {
         PrintError("VMX initialization failure\n");
         return;
     }
     
 
-    v3_cpu_types[cpu_id] = V3_VMX_CPU;
-
-
+    {
+       struct vmx_sec_proc_ctrls sec_proc_ctrls;
+       sec_proc_ctrls.value = v3_vmx_get_ctrl_features(&(hw_info.sec_proc_ctrls));
+       
+       if (sec_proc_ctrls.enable_ept == 0) {
+           V3_Print("VMX EPT (Nested) Paging not supported\n");
+           v3_cpu_types[cpu_id] = V3_VMX_CPU;
+       } else if (sec_proc_ctrls.unrstrct_guest == 0) {
+           V3_Print("VMX EPT (Nested) Paging supported\n");
+           v3_cpu_types[cpu_id] = V3_VMX_EPT_CPU;
+       } else {
+           V3_Print("VMX EPT (Nested) Paging + Unrestricted guest supported\n");
+           v3_cpu_types[cpu_id] = V3_VMX_EPT_UG_CPU;
+       }
+    }
 }
 
 
index d59ed0d..cd2c2b9 100644 (file)
 #include <palacios/vmx_lowlevel.h>
 #include <palacios/vm_guest_mem.h>
 #include <palacios/vmx.h>
+#include <palacios/vmm_ctrl_regs.h>
 
-#ifndef CONFIG_DEBUG_VMX
+#ifndef V3_CONFIG_DEBUG_VMX
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
 
+
+
+
+#define VMXASSIST_MAGIC        0x17101966
+
+
+struct vmx_assist_header {
+    uint64_t rsvd; // 8 bytes of nothing
+    uint32_t magic;
+    uint32_t new_ctx_gpa;
+    uint32_t old_ctx_gpa;
+} __attribute__((packed));
+
+
+union vmcs_arbytes {
+    struct arbyte_fields {
+        unsigned int seg_type : 4,
+            s         : 1,
+            dpl       : 2,
+            p         : 1,
+            reserved0 : 4,
+            avl       : 1,
+            reserved1 : 1,
+            default_ops_size: 1,
+            g         : 1,
+            null_bit  : 1,
+            reserved2 : 15;
+    } __attribute__((packed)) fields;
+    unsigned int bytes;
+} __attribute__((packed));
+
+struct vmx_assist_segment {
+    uint32_t sel;
+    uint32_t limit;
+    uint32_t base;
+    union vmcs_arbytes arbytes;
+} __attribute__((packed));
+
+
+/*
+ * World switch state
+ */
+struct vmx_assist_context {
+    uint32_t  eip;        /* execution pointer */
+    uint32_t  esp;        /* stack pointer */
+    uint32_t  eflags;     /* flags register */
+    uint32_t  cr0;
+    uint32_t  cr3;        /* page table directory */
+    uint32_t  cr4;
+
+    uint32_t  idtr_limit; /* idt */
+    uint32_t  idtr_base;
+
+    uint32_t  gdtr_limit; /* gdt */
+    uint32_t  gdtr_base;
+
+    struct vmx_assist_segment cs;
+    struct vmx_assist_segment ds;
+    struct vmx_assist_segment es;
+    struct vmx_assist_segment ss;
+    struct vmx_assist_segment fs;
+    struct vmx_assist_segment gs;
+    struct vmx_assist_segment tr;
+    struct vmx_assist_segment ldtr;
+
+
+    unsigned char rm_irqbase[2];
+} __attribute__((packed));
+
+
+
 static void vmx_save_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx);
 static void vmx_restore_world_ctx(struct guest_info * info, struct vmx_assist_context * ctx);
 
@@ -38,7 +110,7 @@ int v3_vmxassist_ctx_switch(struct guest_info * info) {
  
 
 
-    if (v3_gpa_to_hva(info, VMXASSIST_BASE, (addr_t *)&hdr) == -1) {
+    if (v3_gpa_to_hva(info, VMXASSIST_START, (addr_t *)&hdr) == -1) {
         PrintError("Could not translate address for vmxassist header\n");
         return -1;
     }
@@ -170,3 +242,142 @@ static void vmx_restore_world_ctx(struct guest_info * info, struct vmx_assist_co
 }
 
 
+int v3_vmxassist_init(struct guest_info * core, struct vmx_data * vmx_state) {
+
+    core->rip = 0xd0000;
+    core->vm_regs.rsp = 0x80000;
+    ((struct rflags *)&(core->ctrl_regs.rflags))->rsvd1 = 1;
+
+#define GUEST_CR0 0x80010031
+#define GUEST_CR4 0x00002010
+    core->ctrl_regs.cr0 = GUEST_CR0;
+    core->ctrl_regs.cr4 = GUEST_CR4;
+
+    ((struct cr0_32 *)&(core->shdw_pg_state.guest_cr0))->pe = 1;
+    ((struct cr0_32 *)&(core->shdw_pg_state.guest_cr0))->wp = 1;
+   
+
+    // Setup segment registers
+    {
+       struct v3_segment * seg_reg = (struct v3_segment *)&(core->segments);
+
+       int i;
+
+       for (i = 0; i < 10; i++) {
+           seg_reg[i].selector = 3 << 3;
+           seg_reg[i].limit = 0xffff;
+           seg_reg[i].base = 0x0;
+       }
+
+       core->segments.cs.selector = 2 << 3;
+
+       /* Set only the segment registers */
+       for (i = 0; i < 6; i++) {
+           seg_reg[i].limit = 0xfffff;
+           seg_reg[i].granularity = 1;
+           seg_reg[i].type = 3;
+           seg_reg[i].system = 1;
+           seg_reg[i].dpl = 0;
+           seg_reg[i].present = 1;
+           seg_reg[i].db = 1;
+       }
+
+       core->segments.cs.type = 0xb;
+
+       core->segments.ldtr.selector = 0x20;
+       core->segments.ldtr.type = 2;
+       core->segments.ldtr.system = 0;
+       core->segments.ldtr.present = 1;
+       core->segments.ldtr.granularity = 0;
+
+    
+       /************* Map in GDT and vmxassist *************/
+
+       uint64_t  gdt[] __attribute__ ((aligned(32))) = {
+           0x0000000000000000ULL,              /* 0x00: reserved */
+           0x0000830000000000ULL,              /* 0x08: 32-bit TSS */
+           //0x0000890000000000ULL,            /* 0x08: 32-bit TSS */
+           0x00CF9b000000FFFFULL,              /* 0x10: CS 32-bit */
+           0x00CF93000000FFFFULL,              /* 0x18: DS 32-bit */
+           0x000082000000FFFFULL,              /* 0x20: LDTR 32-bit */
+       };
+
+
+       addr_t vmxassist_gdt = 0;
+
+       if (v3_gpa_to_hva(core, VMXASSIST_GDT, &vmxassist_gdt) == -1) {
+           PrintError("Could not find VMXASSIST GDT destination\n");
+           return -1;
+       }
+
+       memcpy((void *)vmxassist_gdt, gdt, sizeof(uint64_t) * 5);
+        
+       core->segments.gdtr.base = VMXASSIST_GDT;
+
+
+       uint64_t vmxassist_tss = VMXASSIST_TSS;
+       gdt[0x08 / sizeof(gdt[0])] |=
+           ((vmxassist_tss & 0xFF000000) << (56 - 24)) |
+           ((vmxassist_tss & 0x00FF0000) << (32 - 16)) |
+           ((vmxassist_tss & 0x0000FFFF) << (16)) |
+           (8392 - 1);
+
+       core->segments.tr.selector = 0x08;
+       core->segments.tr.base = vmxassist_tss;
+
+       //core->segments.tr.type = 0x9; 
+       core->segments.tr.type = 0x3;
+       core->segments.tr.system = 0;
+       core->segments.tr.present = 1;
+       core->segments.tr.granularity = 0;
+    }
+    if (core->shdw_pg_mode == NESTED_PAGING) {
+       // setup 1to1 page table internally.
+       int i = 0;
+       pde32_4MB_t * pde = NULL;
+
+       PrintError("Setting up internal VMXASSIST page tables\n");
+
+       if (v3_gpa_to_hva(core, VMXASSIST_1to1_PT, (addr_t *)(&pde)) == -1) {
+           PrintError("Could not find VMXASSIST 1to1 PT destination\n");
+           return -1;
+       }
+
+       memset(pde, 0, PAGE_SIZE);
+
+       for (i = 0; i < 1024; i++) {
+           pde[i].present = 1;
+           pde[i].writable = 1;
+           pde[i].user_page = 1;
+           pde[i].large_page = 1;
+           pde[i].page_base_addr = PAGE_BASE_ADDR_4MB(i * PAGE_SIZE_4MB);
+
+           //      PrintError("PDE %d: %x\n", i, *(uint32_t *)&(pde[i]));
+       }
+
+       core->ctrl_regs.cr3 = VMXASSIST_1to1_PT;
+
+    }
+
+    // setup VMXASSIST
+    { 
+
+       extern uint8_t v3_vmxassist_start[];
+       extern uint8_t v3_vmxassist_end[];
+       addr_t vmxassist_dst = 0;
+
+       if (v3_gpa_to_hva(core, VMXASSIST_START, &vmxassist_dst) == -1) {
+           PrintError("Could not find VMXASSIST destination\n");
+           return -1;
+       }
+
+       memcpy((void *)vmxassist_dst, v3_vmxassist_start, v3_vmxassist_end - v3_vmxassist_start);
+
+
+       vmx_state->assist_state = VMXASSIST_DISABLED;
+    }
+
+
+    return 0;
+}
index 685de90..6bbde36 100644 (file)
@@ -27,7 +27,7 @@
 #include <palacios/vmm_direct_paging.h>
 #include <palacios/vmm_ctrl_regs.h>
 
-#ifndef CONFIG_DEBUG_VMX
+#ifndef V3_CONFIG_DEBUG_VMX
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -192,7 +192,7 @@ static int handle_mov_to_cr0(struct guest_info * info, v3_reg_t * new_cr0, struc
        guest_cr0->pg = 1;
        guest_cr0->ne = 1;
        
-       if (paging_transition) {
+       if ((paging_transition)) {
            // Paging transition
            
            if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) {
@@ -209,14 +209,24 @@ static int handle_mov_to_cr0(struct guest_info * info, v3_reg_t * new_cr0, struc
                
                //            PrintDebug("Activating Shadow Page tables\n");
                
-               if (v3_activate_shadow_pt(info) == -1) {
-                   PrintError("Failed to activate shadow page tables\n");
-                   return -1;
+               if (info->shdw_pg_mode == SHADOW_PAGING) {
+                   if (v3_activate_shadow_pt(info) == -1) {
+                       PrintError("Failed to activate shadow page tables\n");
+                       return -1;
+                   }
                }
                
-           } else if (v3_activate_passthrough_pt(info) == -1) {
-               PrintError("Failed to activate passthrough page tables\n");
-               return -1;
+           } else {
+
+               if (info->shdw_pg_mode == SHADOW_PAGING) {
+                   if (v3_activate_passthrough_pt(info) == -1) {
+                       PrintError("Failed to activate passthrough page tables\n");
+                       return -1;
+                   }
+               } else {
+                   // This is hideous... Let's hope that the 1to1 page table has not been nuked...
+                   info->ctrl_regs.cr3 = VMXASSIST_1to1_PT;
+               }
            }
        }
     }
index 42ca942..a66ad6b 100644 (file)
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
+#include <palacios/vmm.h>
+#include <palacios/vmx_ept.h>
+#include <palacios/vmx_lowlevel.h>
+#include <palacios/vmm_paging.h>
+#include <palacios/vm_guest_mem.h>
 
+
+static struct vmx_ept_msr * ept_info = NULL;
+
+
+static addr_t create_ept_page() {
+    void * page = 0;
+    page = V3_VAddr(V3_AllocPages(1));
+    memset(page, 0, PAGE_SIZE);
+
+    return (addr_t)page;
+}
+
+
+
+
+int v3_init_ept(struct guest_info * core, struct vmx_hw_info * hw_info) {
+    addr_t ept_pa = (addr_t)V3_PAddr((void *)create_ept_page());    
+    vmx_eptp_t * ept_ptr = (vmx_eptp_t *)&(core->direct_map_pt);
+
+
+    ept_info = &(hw_info->ept_info);
+
+    /* TODO: Should we set this to WB?? */
+    ept_ptr->psmt = 0;
+
+    if (ept_info->pg_walk_len4) {
+       ept_ptr->pwl1 = 3;
+    } else {
+       PrintError("Unsupported EPT Table depth\n");
+       return -1;
+    }
+
+    ept_ptr->pml_base_addr = PAGE_BASE_ADDR(ept_pa);
+
+
+    return 0;
+}
+
+
+/* We can use the default paging macros, since the formats are close enough to allow it */
+
+int v3_handle_ept_fault(struct guest_info * core, addr_t fault_addr, struct ept_exit_qual * ept_qual) {
+    ept_pml4_t    * pml     = NULL;
+    //    ept_pdp_1GB_t * pdpe1gb = NULL;
+    ept_pdp_t     * pdpe    = NULL;
+    ept_pde_2MB_t * pde2mb  = NULL;
+    ept_pde_t     * pde     = NULL;
+    ept_pte_t     * pte     = NULL;
+    addr_t host_addr     = 0;
+
+    int pml_index  = PML4E64_INDEX(fault_addr);
+    int pdpe_index = PDPE64_INDEX(fault_addr);
+    int pde_index  = PDE64_INDEX(fault_addr);
+    int pte_index  = PTE64_INDEX(fault_addr);
+
+    struct v3_mem_region * region = v3_get_mem_region(core->vm_info, core->vcpu_id, fault_addr);
+    int page_size = PAGE_SIZE_4KB;
+
+
+
+    pf_error_t error_code = {0};
+    error_code.present = ept_qual->present;
+    error_code.write = ept_qual->write;
+    
+    if (region == NULL) {
+       PrintError("invalid region, addr=%p\n", (void *)fault_addr);
+       return -1;
+    }
+
+    if ((core->use_large_pages == 1) || (core->use_giant_pages == 1)) {
+       page_size = v3_get_max_page_size(core, fault_addr, LONG);
+    }
+
+
+
+    pml = (ept_pml4_t *)CR3_TO_PML4E64_VA(core->direct_map_pt);
+
+
+
+    //Fix up the PML entry
+    if (pml[pml_index].read == 0) { 
+       pdpe = (ept_pdp_t *)create_ept_page();
+       
+       // Set default PML Flags...
+       pml[pml_index].read = 1;
+       pml[pml_index].write = 1;
+       pml[pml_index].exec = 1;
+
+       pml[pml_index].pdp_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pdpe));
+    } else {
+       pdpe = V3_VAddr((void *)BASE_TO_PAGE_ADDR_4KB(pml[pml_index].pdp_base_addr));
+    }
+
+
+    // Fix up the PDPE entry
+    if (pdpe[pdpe_index].read == 0) {
+       pde = (ept_pde_t *)create_ept_page();
+
+       // Set default PDPE Flags...
+       pdpe[pdpe_index].read = 1;
+       pdpe[pdpe_index].write = 1;
+       pdpe[pdpe_index].exec = 1;
+
+       pdpe[pdpe_index].pd_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pde));
+    } else {
+       pde = V3_VAddr((void *)BASE_TO_PAGE_ADDR_4KB(pdpe[pdpe_index].pd_base_addr));
+    }
+
+
+
+    // Fix up the 2MiB PDE and exit here
+    if (page_size == PAGE_SIZE_2MB) {
+       pde2mb = (ept_pde_2MB_t *)pde; // all but these two lines are the same for PTE
+       pde2mb[pde_index].large_page = 1;
+
+       if (pde2mb[pde_index].read == 0) {
+
+           if ( (region->flags.alloced == 1) && 
+                (region->flags.read == 1)) {
+               // Full access
+               pde2mb[pde_index].read = 1;
+               pde2mb[pde_index].exec = 1;
+              
+               if (region->flags.write == 1) {
+                   pde2mb[pde_index].write = 1;
+               } else {
+                   pde2mb[pde_index].write = 0;
+               }
+
+               if (v3_gpa_to_hpa(core, fault_addr, &host_addr) == -1) {
+                   PrintError("Error: Could not translate fault addr (%p)\n", (void *)fault_addr);
+                   return -1;
+               }
+
+               pde2mb[pde_index].page_base_addr = PAGE_BASE_ADDR_2MB(host_addr);
+           } else {
+               return region->unhandled(core, fault_addr, fault_addr, region, error_code);
+           }
+       } else {
+           // We fix all permissions on the first pass, 
+           // so we only get here if its an unhandled exception
+
+           return region->unhandled(core, fault_addr, fault_addr, region, error_code);
+       }
+
+       return 0;
+    }
+
+    // Continue with the 4KiB page heirarchy
+    
+
+    // Fix up the PDE entry
+    if (pde[pde_index].read == 0) {
+       pte = (ept_pte_t *)create_ept_page();
+       
+       pde[pde_index].read = 1;
+       pde[pde_index].write = 1;
+       pde[pde_index].exec = 1;
+
+       pde[pde_index].pt_base_addr = PAGE_BASE_ADDR_4KB((addr_t)V3_PAddr(pte));
+    } else {
+       pte = V3_VAddr((void *)BASE_TO_PAGE_ADDR_4KB(pde[pde_index].pt_base_addr));
+    }
+
+
+
+
+    // Fix up the PTE entry
+    if (pte[pte_index].read == 0) {
+
+       if ( (region->flags.alloced == 1) && 
+            (region->flags.read == 1)) {
+           // Full access
+           pte[pte_index].read = 1;
+           pte[pte_index].exec = 1;
+
+           if (region->flags.write == 1) {
+               pte[pte_index].write = 1;
+           } else {
+               pte[pte_index].write = 0;
+           }
+
+           if (v3_gpa_to_hpa(core, fault_addr, &host_addr) == -1) {
+               PrintError("Error Could not translate fault addr (%p)\n", (void *)fault_addr);
+               return -1;
+           }
+
+
+           pte[pte_index].page_base_addr = PAGE_BASE_ADDR_4KB(host_addr);
+       } else {
+           return region->unhandled(core, fault_addr, fault_addr, region, error_code);
+       }
+    } else {
+       // We fix all permissions on the first pass, 
+       // so we only get here if its an unhandled exception
+
+       return region->unhandled(core, fault_addr, fault_addr, region, error_code);
+    }
+
+
+    return 0;
+}
index e5da762..71c1eab 100644 (file)
 #include <palacios/vmx_ctrl_regs.h>
 #include <palacios/vmx_assist.h>
 #include <palacios/vmm_halt.h>
+#include <palacios/vmx_ept.h>
 
-#ifndef CONFIG_DEBUG_VMX
+#ifndef V3_CONFIG_DEBUG_VMX
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
 #include <palacios/vmm_telemetry.h>
 #endif
 
 /* At this point the GPRs are already copied into the guest_info state */
 int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_info) {
+    struct vmx_basic_exit_info * basic_info = (struct vmx_basic_exit_info *)&(exit_info->exit_reason);
+
     /*
       PrintError("Handling VMEXIT: %s (%u), %lu (0x%lx)\n", 
       v3_vmx_exit_code_to_str(exit_info->exit_reason),
@@ -52,20 +55,40 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf
       v3_print_vmcs();
     */
 
-#ifdef CONFIG_TELEMETRY
+
+    if (basic_info->entry_error == 1) {
+       switch (basic_info->reason) {
+           case VMEXIT_INVALID_GUEST_STATE:
+               PrintError("VM Entry failed due to invalid guest state\n");
+               PrintError("Printing VMCS: (NOTE: This VMCS may not belong to the correct guest)\n");
+               v3_print_vmcs();
+               break;
+           case VMEXIT_INVALID_MSR_LOAD:
+               PrintError("VM Entry failed due to error loading MSRs\n");
+               break;
+           default:
+               PrintError("Entry failed for unknown reason (%d)\n", basic_info->reason);
+               break;
+       }
+       
+       return -1;
+    }
+
+
+#ifdef V3_CONFIG_TELEMETRY
     if (info->vm_info->enable_telemetry) {
        v3_telemetry_start_exit(info);
     }
 #endif
 
-    switch (exit_info->exit_reason) {
+    switch (basic_info->reason) {
         case VMEXIT_INFO_EXCEPTION_OR_NMI: {
             pf_error_t error_code = *(pf_error_t *)&(exit_info->int_err);
 
 
             // JRL: Change "0x0e" to a macro value
-            if ((uint8_t)exit_info->int_info == 0x0e) {
-#ifdef CONFIG_DEBUG_SHADOW_PAGING
+            if ((uint8_t)exit_info->int_info == 14) {
+#ifdef V3_CONFIG_DEBUG_SHADOW_PAGING
                 PrintDebug("Page Fault at %p error_code=%x\n", (void *)exit_info->exit_qual, *(uint32_t *)&error_code);
 #endif
 
@@ -74,6 +97,7 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf
                         PrintError("Error handling shadow page fault\n");
                         return -1;
                     }
+           
                 } else {
                     PrintError("Page fault in unimplemented paging mode\n");
                     return -1;
@@ -86,6 +110,16 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf
             break;
         }
 
+       case VMEXIT_EPT_VIOLATION: {
+           struct ept_exit_qual * ept_qual = (struct ept_exit_qual *)&(exit_info->exit_qual);
+
+           if (v3_handle_ept_fault(info, exit_info->ept_fault_addr, ept_qual) == -1) {
+               PrintError("Error handling EPT fault\n");
+               return -1;
+           }
+
+           break;
+       }
         case VMEXIT_INVLPG:
             if (info->shdw_pg_mode == SHADOW_PAGING) {
                 if (v3_handle_shadow_invlpg(info) == -1) {
@@ -97,7 +131,7 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf
             break;
 
         case VMEXIT_RDTSC:
-#ifdef CONFIG_DEBUG_TIME
+#ifdef V3_CONFIG_DEBUG_TIME
            PrintDebug("RDTSC\n");
 #endif 
            if (v3_handle_rdtsc(info) == -1) {
@@ -208,6 +242,9 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf
             }
 
             break;
+
+
+
         case VMEXIT_PAUSE:
             // Handled as NOP
             info->rip += 2;
@@ -220,16 +257,18 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf
            // This is handled in the atomic part of the vmx code,
            // not in the generic (interruptable) vmx handler
             break;
+
+           
         default:
             PrintError("Unhandled VMEXIT: %s (%u), %lu (0x%lx)\n", 
-                      v3_vmx_exit_code_to_str(exit_info->exit_reason),
-                      exit_info->exit_reason, 
+                      v3_vmx_exit_code_to_str(basic_info->reason),
+                      basic_info->reason, 
                       exit_info->exit_qual, exit_info->exit_qual);
             return -1;
     }
 
 
-#ifdef CONFIG_TELEMETRY
+#ifdef V3_CONFIG_TELEMETRY
     if (info->vm_info->enable_telemetry) {
         v3_telemetry_end_exit(info, exit_info->exit_reason);
     }
@@ -271,12 +310,12 @@ static const char VMEXIT_MOV_DR_STR[] = "VMEXIT_MOV_DR";
 static const char VMEXIT_IO_INSTR_STR[] = "VMEXIT_IO_INSTR";
 static const char VMEXIT_RDMSR_STR[] = "VMEXIT_RDMSR";
 static const char VMEXIT_WRMSR_STR[] = "VMEXIT_WRMSR";
-static const char VMEXIT_ENTRY_FAIL_INVALID_GUEST_STATE_STR[] = "VMEXIT_ENTRY_FAIL_INVALID_GUEST_STATE";
-static const char VMEXIT_ENTRY_FAIL_MSR_LOAD_STR[] = "VMEXIT_ENTRY_FAIL_MSR_LOAD";
+static const char VMEXIT_INVALID_GUEST_STATE_STR[] = "VMEXIT_INVALID_GUEST_STATE";
+static const char VMEXIT_INVALID_MSR_LOAD_STR[] = "VMEXIT_INVALID_MSR_LOAD";
 static const char VMEXIT_MWAIT_STR[] = "VMEXIT_MWAIT";
 static const char VMEXIT_MONITOR_STR[] = "VMEXIT_MONITOR";
 static const char VMEXIT_PAUSE_STR[] = "VMEXIT_PAUSE";
-static const char VMEXIT_ENTRY_FAILURE_MACHINE_CHECK_STR[] = "VMEXIT_ENTRY_FAILURE_MACHINE_CHECK";
+static const char VMEXIT_INVALID_MACHINE_CHECK_STR[] = "VMEXIT_INVALIDE_MACHINE_CHECK";
 static const char VMEXIT_TPR_BELOW_THRESHOLD_STR[] = "VMEXIT_TPR_BELOW_THRESHOLD";
 static const char VMEXIT_APIC_STR[] = "VMEXIT_APIC";
 static const char VMEXIT_GDTR_IDTR_STR[] = "VMEXIT_GDTR_IDTR";
@@ -357,18 +396,18 @@ const char * v3_vmx_exit_code_to_str(vmx_exit_t exit)
             return VMEXIT_RDMSR_STR;
         case VMEXIT_WRMSR:
             return VMEXIT_WRMSR_STR;
-        case VMEXIT_ENTRY_FAIL_INVALID_GUEST_STATE:
-            return VMEXIT_ENTRY_FAIL_INVALID_GUEST_STATE_STR;
-        case VMEXIT_ENTRY_FAIL_MSR_LOAD:
-            return VMEXIT_ENTRY_FAIL_MSR_LOAD_STR;
+        case VMEXIT_INVALID_GUEST_STATE:
+            return VMEXIT_INVALID_GUEST_STATE_STR;
+        case VMEXIT_INVALID_MSR_LOAD:
+            return VMEXIT_INVALID_MSR_LOAD_STR;
         case VMEXIT_MWAIT:
             return VMEXIT_MWAIT_STR;
         case VMEXIT_MONITOR:
             return VMEXIT_MONITOR_STR;
         case VMEXIT_PAUSE:
             return VMEXIT_PAUSE_STR;
-        case VMEXIT_ENTRY_FAILURE_MACHINE_CHECK:
-            return VMEXIT_ENTRY_FAILURE_MACHINE_CHECK_STR;
+        case VMEXIT_INVALID_MACHINE_CHECK:
+            return VMEXIT_INVALID_MACHINE_CHECK_STR;
         case VMEXIT_TPR_BELOW_THRESHOLD:
             return VMEXIT_TPR_BELOW_THRESHOLD_STR;
         case VMEXIT_APIC:
index 3220e52..478bfbc 100644 (file)
 // Intel VMX Feature MSRs
 
 
+uint32_t v3_vmx_get_ctrl_features(struct vmx_ctrl_field * fields) {
+    // features are available if they are hardwired to 1, or the mask is 0 (they can be changed)
+    uint32_t features = 0;
+   
+    features = fields->req_val;
+    features |= ~(fields->req_mask);
+
+    return features;
+}
+
 
 static int get_ex_ctrl_caps(struct vmx_hw_info * hw_info, struct vmx_ctrl_field * field, 
-                 uint32_t old_msr, uint32_t true_msr) {
+                           uint32_t old_msr, uint32_t true_msr) {
     uint32_t old_0;  /* Bit is 1 => MB1 */
     uint32_t old_1;  /* Bit is 0 => MBZ */
     uint32_t true_0; /* Bit is 1 => MB1 */
@@ -103,7 +113,7 @@ int v3_init_vmx_hw(struct vmx_hw_info * hw_info) {
     /* Intel Manual 3B. Sect. G.3.3 */
     if ( ((hw_info->proc_ctrls.req_mask & 0x80000000) == 0) || 
         ((hw_info->proc_ctrls.req_val & 0x80000000) == 1) ) {
-       get_ctrl_caps(&(hw_info->proc_ctrls_2), VMX_PROCBASED_CTLS2_MSR);
+       get_ctrl_caps(&(hw_info->sec_proc_ctrls), VMX_PROCBASED_CTLS2_MSR);
     }
     
     get_cr_fields(&(hw_info->cr0), VMX_CR0_FIXED1_MSR, VMX_CR0_FIXED0_MSR);
index 411eb1a..d69787a 100644 (file)
@@ -25,7 +25,7 @@
 #include <palacios/vm_guest_mem.h>
 #include <palacios/vmm_decoder.h>
 
-#ifndef CONFIG_DEBUG_IO
+#ifndef V3_CONFIG_DEBUG_IO
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
diff --git a/palacios/src/vnet/Makefile b/palacios/src/vnet/Makefile
new file mode 100644 (file)
index 0000000..2b8f357
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(V3_CONFIG_VNET) +=  vnet_core.o vnet_host.o vnet_hashtable.o
+obj-y += null.o
+
diff --git a/palacios/src/vnet/null.c b/palacios/src/vnet/null.c
new file mode 100644 (file)
index 0000000..1828c44
--- /dev/null
@@ -0,0 +1,6 @@
+/** \file
+ * Do nothing module.
+ *
+ * This file only exists to appease the kbuild gods.
+ */
+
similarity index 68%
rename from palacios/src/palacios/vmm_vnet_core.c
rename to palacios/src/vnet/vnet_core.c
index 4b54d71..8cf2364 100644 (file)
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
  
-#include <palacios/vmm_vnet.h>
-#include <palacios/vm_guest_mem.h>
-#include <palacios/vmm_lock.h>
-#include <palacios/vmm_queue.h>
-#include <palacios/vmm_sprintf.h>
-#include <palacios/vmm_ethernet.h>
-
-#ifndef CONFIG_DEBUG_VNET
-#undef PrintDebug
-#define PrintDebug(fmt, args...)
+#include <vnet/vnet.h>
+#include <vnet/vnet_hashtable.h>
+#include <vnet/vnet_host.h>
+#include <vnet/vnet_vmm.h>
+
+#ifndef V3_CONFIG_DEBUG_VNET
+#undef Vnet_Debug
+#define Vnet_Debug(fmt, args...)
 #endif
 
-int v3_net_debug = 0;
+int net_debug = 0;
 
 struct eth_hdr {
     uint8_t dst_mac[ETH_ALEN];
@@ -68,6 +66,8 @@ struct vnet_route_info {
     struct vnet_dev * dst_dev;
     struct vnet_dev * src_dev;
 
+    uint32_t idx;
+
     struct list_head node;
     struct list_head match_node; // used for route matching
 };
@@ -84,30 +84,33 @@ struct route_list {
 struct queue_entry{
     uint8_t use;
     struct v3_vnet_pkt pkt;
-    uint8_t data[ETHERNET_PACKET_LEN];
+    uint8_t * data;
+    uint32_t size_alloc;
 };
 
-#define VNET_QUEUE_SIZE 10240
+#define VNET_QUEUE_SIZE 1024
 struct vnet_queue {
-       struct queue_entry buf[VNET_QUEUE_SIZE];
-       int head, tail;
-       int count;
-       v3_lock_t lock;
+    struct queue_entry buf[VNET_QUEUE_SIZE];
+    int head, tail;
+    int count;
+    vnet_lock_t lock;
 };
 
 static struct {
     struct list_head routes;
     struct list_head devs;
     
-    int num_routes;
-    int num_devs;
+    uint32_t num_routes;
+    uint32_t route_idx;
+    uint32_t num_devs;
+    uint32_t dev_idx;
 
     struct vnet_brg_dev * bridge;
 
-    v3_lock_t lock;
+    vnet_lock_t lock;
     struct vnet_stat stats;
 
-    void * pkt_flush_thread;
+    struct vnet_thread * pkt_flush_thread;
 
     struct vnet_queue pkt_q;
 
@@ -115,8 +118,8 @@ static struct {
 } vnet_state;
        
 
-#ifdef CONFIG_DEBUG_VNET
-static inline void mac_to_string(uint8_t * mac, char * buf) {
+#ifdef V3_CONFIG_DEBUG_VNET
+static inline void mac2str(uint8_t * mac, char * buf) {
     snprintf(buf, 100, "%2x:%2x:%2x:%2x:%2x:%2x", 
             mac[0], mac[1], mac[2],
             mac[3], mac[4], mac[5]);
@@ -125,16 +128,16 @@ static inline void mac_to_string(uint8_t * mac, char * buf) {
 static void print_route(struct v3_vnet_route * route){
     char str[50];
 
-    mac_to_string(route->src_mac, str);
-    PrintDebug("Src Mac (%s),  src_qual (%d)\n", 
+    mac2str(route->src_mac, str);
+    Vnet_Debug("Src Mac (%s),  src_qual (%d)\n", 
               str, route->src_mac_qual);
-    mac_to_string(route->dst_mac, str);
-    PrintDebug("Dst Mac (%s),  dst_qual (%d)\n", 
+    mac2str(route->dst_mac, str);
+    Vnet_Debug("Dst Mac (%s),  dst_qual (%d)\n", 
               str, route->dst_mac_qual);
-    PrintDebug("Src dev id (%d), src type (%d)", 
+    Vnet_Debug("Src dev id (%d), src type (%d)", 
               route->src_id, 
               route->src_type);
-    PrintDebug("Dst dev id (%d), dst type (%d)\n", 
+    Vnet_Debug("Dst dev id (%d), dst type (%d)\n", 
               route->dst_id, 
               route->dst_type);
 }
@@ -143,13 +146,13 @@ static void dump_routes(){
     struct vnet_route_info *route;
 
     int i = 0;
-    PrintDebug("\n========Dump routes starts ============\n");
+    Vnet_Debug("\n========Dump routes starts ============\n");
     list_for_each_entry(route, &(vnet_state.routes), node) {
-       PrintDebug("\nroute %d:\n", i++);
+       Vnet_Debug("\nroute %d:\n", i++);
                
        print_route(&(route->route_def));
        if (route->route_def.dst_type == LINK_INTERFACE) {
-           PrintDebug("dst_dev (%p), dst_dev_id (%d), dst_dev_ops(%p), dst_dev_data (%p)\n",
+           Vnet_Debug("dst_dev (%p), dst_dev_id (%d), dst_dev_ops(%p), dst_dev_data (%p)\n",
                route->dst_dev,
                route->dst_dev->dev_id,
                (void *)&(route->dst_dev->dev_ops),
@@ -157,7 +160,7 @@ static void dump_routes(){
        }
     }
 
-    PrintDebug("\n========Dump routes end ============\n");
+    Vnet_Debug("\n========Dump routes end ============\n");
 }
 
 #endif
@@ -170,7 +173,7 @@ static void dump_routes(){
 static inline uint_t hash_fn(addr_t hdr_ptr) {    
     uint8_t * hdr_buf = (uint8_t *)hdr_ptr;
 
-    return v3_hash_buffer(hdr_buf, VNET_HASH_SIZE);
+    return vnet_hash_buffer(hdr_buf, VNET_HASH_SIZE);
 }
 
 static inline int hash_eq(addr_t key1, addr_t key2) {  
@@ -180,7 +183,7 @@ static inline int hash_eq(addr_t key1, addr_t key2) {
 static int add_route_to_cache(const struct v3_vnet_pkt * pkt, struct route_list * routes) {
     memcpy(routes->hash_buf, pkt->hash_buf, VNET_HASH_SIZE);    
 
-    if (v3_htable_insert(vnet_state.route_cache, (addr_t)routes->hash_buf, (addr_t)routes) == 0) {
+    if (vnet_htable_insert(vnet_state.route_cache, (addr_t)routes->hash_buf, (addr_t)routes) == 0) {
        PrintError("VNET/P Core: Failed to insert new route entry to the cache\n");
        return -1;
     }
@@ -189,15 +192,15 @@ static int add_route_to_cache(const struct v3_vnet_pkt * pkt, struct route_list
 }
 
 static int clear_hash_cache() {
-    v3_free_htable(vnet_state.route_cache, 1, 1);
-    vnet_state.route_cache = v3_create_htable(0, &hash_fn, &hash_eq);
+    vnet_free_htable(vnet_state.route_cache, 1, 1);
+    vnet_state.route_cache = vnet_create_htable(0, &hash_fn, &hash_eq);
 
     return 0;
 }
 
 static int look_into_cache(const struct v3_vnet_pkt * pkt, 
                           struct route_list ** routes) {
-    *routes = (struct route_list *)v3_htable_search(vnet_state.route_cache, (addr_t)(pkt->hash_buf));
+    *routes = (struct route_list *)vnet_htable_search(vnet_state.route_cache, (addr_t)(pkt->hash_buf));
    
     return 0;
 }
@@ -246,11 +249,11 @@ int v3_vnet_add_route(struct v3_vnet_route route) {
     struct vnet_route_info * new_route = NULL;
     unsigned long flags; 
 
-    new_route = (struct vnet_route_info *)V3_Malloc(sizeof(struct vnet_route_info));
+    new_route = (struct vnet_route_info *)Vnet_Malloc(sizeof(struct vnet_route_info));
     memset(new_route, 0, sizeof(struct vnet_route_info));
 
-#ifdef CONFIG_DEBUG_VNET
-    PrintDebug("VNET/P Core: add_route_entry:\n");
+#ifdef V3_CONFIG_DEBUG_VNET
+    Vnet_Debug("VNET/P Core: add_route_entry:\n");
     print_route(&route);
 #endif
     
@@ -272,19 +275,39 @@ int v3_vnet_add_route(struct v3_vnet_route route) {
     }
 
 
-    flags = v3_lock_irqsave(vnet_state.lock);
+    flags = vnet_lock_irqsave(vnet_state.lock);
 
     list_add(&(new_route->node), &(vnet_state.routes));
-    clear_hash_cache();
+    new_route->idx = ++ vnet_state.route_idx;
+    vnet_state.num_routes ++;
+       
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
 
-    v3_unlock_irqrestore(vnet_state.lock, flags);
-   
+    clear_hash_cache();
 
-#ifdef CONFIG_DEBUG_VNET
+#ifdef V3_CONFIG_DEBUG_VNET
     dump_routes();
 #endif
 
-    return 0;
+    return new_route->idx;
+}
+
+
+void v3_vnet_del_route(uint32_t route_idx){
+    struct vnet_route_info * route = NULL;
+    unsigned long flags; 
+
+    flags = vnet_lock_irqsave(vnet_state.lock);
+
+    list_for_each_entry(route, &(vnet_state.routes), node) {
+       if(route->idx == route_idx){
+           list_del(&(route->node));
+           list_del(&(route->match_node));
+           Vnet_Free(route);    
+       }
+    }
+
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
 }
 
 
@@ -293,7 +316,7 @@ static void inline del_routes_by_dev(int dev_id){
     struct vnet_route_info * route = NULL;
     unsigned long flags; 
 
-    flags = v3_lock_irqsave(vnet_state.lock);
+    flags = vnet_lock_irqsave(vnet_state.lock);
 
     list_for_each_entry(route, &(vnet_state.routes), node) {
        if((route->route_def.dst_type == LINK_INTERFACE &&
@@ -303,11 +326,11 @@ static void inline del_routes_by_dev(int dev_id){
              
            list_del(&(route->node));
            list_del(&(route->match_node));
-           V3_Free(route);    
+           Vnet_Free(route);    
        }
     }
 
-    v3_unlock_irqrestore(vnet_state.lock, flags);
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
 }
 
 /* At the end allocate a route_list
@@ -320,17 +343,17 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt) {
     int max_rank = 0;
     struct list_head match_list;
     struct eth_hdr * hdr = (struct eth_hdr *)(pkt->data);
-    //    uint8_t src_type = pkt->src_type;
+    //  uint8_t src_type = pkt->src_type;
     //  uint32_t src_link = pkt->src_id;
 
-#ifdef CONFIG_DEBUG_VNET
+#ifdef V3_CONFIG_DEBUG_VNET
     {
        char dst_str[100];
        char src_str[100];
 
-       mac_to_string(hdr->src_mac, src_str);  
-       mac_to_string(hdr->dst_mac, dst_str);
-       PrintDebug("VNET/P Core: match_route. pkt: SRC(%s), DEST(%s)\n", src_str, dst_str);
+       mac2str(hdr->src_mac, src_str);  
+       mac2str(hdr->dst_mac, dst_str);
+       Vnet_Debug("VNET/P Core: match_route. pkt: SRC(%s), DEST(%s)\n", src_str, dst_str);
     }
 #endif
 
@@ -417,14 +440,14 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt) {
        }
     }
 
-    PrintDebug("VNET/P Core: match_route: Matches=%d\n", num_matches);
+    Vnet_Debug("VNET/P Core: match_route: Matches=%d\n", num_matches);
 
     if (num_matches == 0) {
        return NULL;
     }
 
-    matches = (struct route_list *)V3_Malloc(sizeof(struct route_list) + 
-                               (sizeof(struct vnet_route_info *) * num_matches));
+    matches = (struct route_list *)Vnet_Malloc(sizeof(struct route_list) + 
+                                              (sizeof(struct vnet_route_info *) * num_matches));
 
     matches->num_routes = num_matches;
 
@@ -445,36 +468,36 @@ int vnet_tx_one_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
     int i;
 
     int cpu = V3_Get_CPU();
-    V3_Net_Print(2, "VNET/P Core: cpu %d: pkt (size %d, src_id:%d, src_type: %d, dst_id: %d, dst_type: %d)\n",
+    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);
-    if(v3_net_debug >= 4){
+    if(net_debug >= 4){
            v3_hexdump(pkt->data, pkt->size, NULL, 0);
     }
 
-    flags = v3_lock_irqsave(vnet_state.lock);
+    flags = vnet_lock_irqsave(vnet_state.lock);
 
     vnet_state.stats.rx_bytes += pkt->size;
     vnet_state.stats.rx_pkts++;
 
     look_into_cache(pkt, &matched_routes);
     if (matched_routes == NULL) {  
-       PrintDebug("VNET/P Core: send pkt Looking into routing table\n");
+       Vnet_Debug("VNET/P Core: send pkt Looking into routing table\n");
        
        matched_routes = match_route(pkt);
        
        if (matched_routes) {
            add_route_to_cache(pkt, matched_routes);
        } else {
-           PrintDebug("VNET/P Core: Could not find route for packet... discards packet\n");
-           v3_unlock_irqrestore(vnet_state.lock, flags);
+           Vnet_Debug("VNET/P Core: Could not find route for packet... discards packet\n");
+           vnet_unlock_irqrestore(vnet_state.lock, flags);
            return 0; /* do we return -1 here?*/
        }
     }
 
-    v3_unlock_irqrestore(vnet_state.lock, flags);
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
 
-    PrintDebug("VNET/P Core: send pkt route matches %d\n", matched_routes->num_routes);
+    Vnet_Debug("VNET/P Core: send pkt route matches %d\n", matched_routes->num_routes);
 
     for (i = 0; i < matched_routes->num_routes; i++) {
        struct vnet_route_info * route = matched_routes->routes[i];
@@ -485,30 +508,30 @@ int vnet_tx_one_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
            pkt->dst_id = route->route_def.dst_id;
 
            if (bridge == NULL) {
-               V3_Net_Print(2, "VNET/P Core: No active bridge to sent data to\n");
-                continue;
+               Vnet_Print(2, "VNET/P Core: No active bridge to sent data to\n");
+               continue;
            }
 
            if(bridge->brg_ops.input(bridge->vm, pkt, bridge->private_data) < 0){
-                V3_Net_Print(2, "VNET/P Core: Packet not sent properly to bridge\n");
+                Vnet_Print(2, "VNET/P Core: Packet not sent properly to bridge\n");
                 continue;
            }         
            vnet_state.stats.tx_bytes += pkt->size;
            vnet_state.stats.tx_pkts ++;
         } else if (route->route_def.dst_type == LINK_INTERFACE) {
             if (route->dst_dev == NULL){
-                 V3_Net_Print(2, "VNET/P Core: No active device to sent data to\n");
+                 Vnet_Print(2, "VNET/P Core: No active device to sent data to\n");
                continue;
             }
 
            if(route->dst_dev->dev_ops.input(route->dst_dev->vm, pkt, route->dst_dev->private_data) < 0) {
-                V3_Net_Print(2, "VNET/P Core: Packet not sent properly\n");
+                Vnet_Print(2, "VNET/P Core: Packet not sent properly\n");
                 continue;
            }
            vnet_state.stats.tx_bytes += pkt->size;
            vnet_state.stats.tx_pkts ++;
         } else {
-            PrintError("VNET/P Core: Wrong dst type\n");
+            Vnet_Print(0, "VNET/P Core: Wrong dst type\n");
         }
     }
     
@@ -520,12 +543,13 @@ 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 = v3_lock_irqsave(q->lock);
+    flags = vnet_lock_irqsave(q->lock);
 
     if (q->count >= VNET_QUEUE_SIZE){
-       V3_Net_Print(1, "VNET Queue overflow!\n");
-       v3_unlock_irqrestore(q->lock, flags);
+       Vnet_Print(1, "VNET Queue overflow!\n");
+       vnet_unlock_irqrestore(q->lock, flags);
        return -1;
     }
        
@@ -533,11 +557,25 @@ static int vnet_pkt_enqueue(struct v3_vnet_pkt * pkt){
     entry = &(q->buf[q->tail++]);
     q->tail %= VNET_QUEUE_SIZE;
        
-    v3_unlock_irqrestore(q->lock, flags);
+    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);
@@ -553,7 +591,7 @@ int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data, int synchron
        vnet_tx_one_pkt(pkt, NULL);
     }else {
        vnet_pkt_enqueue(pkt);
-       V3_Net_Print(2, "VNET/P Core: Put pkt into Queue: pkt size %d\n", pkt->size);
+       Vnet_Print(2, "VNET/P Core: Put pkt into Queue: pkt size %d\n", pkt->size);
     }
        
     return 0;
@@ -565,10 +603,10 @@ int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac,
     struct vnet_dev * new_dev = NULL;
     unsigned long flags;
 
-    new_dev = (struct vnet_dev *)V3_Malloc(sizeof(struct vnet_dev)); 
+    new_dev = (struct vnet_dev *)Vnet_Malloc(sizeof(struct vnet_dev)); 
 
     if (new_dev == NULL) {
-       PrintError("Malloc fails\n");
+       Vnet_Print(0, "Malloc fails\n");
        return -1;
     }
    
@@ -578,22 +616,23 @@ int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac,
     new_dev->vm = vm;
     new_dev->dev_id = 0;
 
-    flags = v3_lock_irqsave(vnet_state.lock);
+    flags = vnet_lock_irqsave(vnet_state.lock);
 
     if (dev_by_mac(mac) == NULL) {
        list_add(&(new_dev->node), &(vnet_state.devs));
-       new_dev->dev_id = ++vnet_state.num_devs;
+       new_dev->dev_id = ++ vnet_state.dev_idx;
+       vnet_state.num_devs ++;
     }
 
-    v3_unlock_irqrestore(vnet_state.lock, flags);
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
 
     /* if the device was found previosly the id should still be 0 */
     if (new_dev->dev_id == 0) {
-       PrintError("VNET/P Core: Device Already exists\n");
+       Vnet_Print(0, "VNET/P Core: Device Already exists\n");
        return -1;
     }
 
-    PrintDebug("VNET/P Core: Add Device: dev_id %d\n", new_dev->dev_id);
+    Vnet_Debug("VNET/P Core: Add Device: dev_id %d\n", new_dev->dev_id);
 
     return new_dev->dev_id;
 }
@@ -603,26 +642,26 @@ int v3_vnet_del_dev(int dev_id){
     struct vnet_dev * dev = NULL;
     unsigned long flags;
 
-    flags = v3_lock_irqsave(vnet_state.lock);
+    flags = vnet_lock_irqsave(vnet_state.lock);
        
     dev = dev_by_id(dev_id);
     if (dev != NULL){
        list_del(&(dev->node));
-       del_routes_by_dev(dev_id);
+       //del_routes_by_dev(dev_id);
+       vnet_state.num_devs --;
     }
        
-    v3_unlock_irqrestore(vnet_state.lock, flags);
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
 
-    V3_Free(dev);
+    Vnet_Free(dev);
 
-    PrintDebug("VNET/P Core: Remove Device: dev_id %d\n", dev_id);
+    Vnet_Debug("VNET/P Core: Remove Device: dev_id %d\n", dev_id);
 
     return 0;
 }
 
 
 int v3_vnet_stat(struct vnet_stat * stats){
-       
     stats->rx_bytes = vnet_state.stats.rx_bytes;
     stats->rx_pkts = vnet_state.stats.rx_pkts;
     stats->tx_bytes = vnet_state.stats.tx_bytes;
@@ -631,22 +670,22 @@ int v3_vnet_stat(struct vnet_stat * stats){
     return 0;
 }
 
-static void free_devices(){
+static void deinit_devices_list(){
     struct vnet_dev * dev = NULL; 
 
     list_for_each_entry(dev, &(vnet_state.devs), node) {
        list_del(&(dev->node));
-       V3_Free(dev);
+       Vnet_Free(dev);
     }
 }
 
-static void free_routes(){
+static void deinit_routes_list(){
     struct vnet_route_info * route = NULL; 
 
     list_for_each_entry(route, &(vnet_state.routes), node) {
        list_del(&(route->node));
        list_del(&(route->match_node));
-       V3_Free(route);
+       Vnet_Free(route);
     }
 }
 
@@ -658,19 +697,19 @@ int v3_vnet_add_bridge(struct v3_vm_info * vm,
     int bridge_free = 0;
     struct vnet_brg_dev * tmp_bridge = NULL;    
     
-    flags = v3_lock_irqsave(vnet_state.lock);
+    flags = vnet_lock_irqsave(vnet_state.lock);
     if (vnet_state.bridge == NULL) {
        bridge_free = 1;
        vnet_state.bridge = (void *)1;
     }
-    v3_unlock_irqrestore(vnet_state.lock, flags);
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
 
     if (bridge_free == 0) {
        PrintError("VNET/P Core: Bridge already set\n");
        return -1;
     }
 
-    tmp_bridge = (struct vnet_brg_dev *)V3_Malloc(sizeof(struct vnet_brg_dev));
+    tmp_bridge = (struct vnet_brg_dev *)Vnet_Malloc(sizeof(struct vnet_brg_dev));
 
     if (tmp_bridge == NULL) {
        PrintError("Malloc Fails\n");
@@ -685,45 +724,66 @@ int v3_vnet_add_bridge(struct v3_vm_info * vm,
     tmp_bridge->type = type;
        
     /* make this atomic to avoid possible race conditions */
-    flags = v3_lock_irqsave(vnet_state.lock);
+    flags = vnet_lock_irqsave(vnet_state.lock);
     vnet_state.bridge = tmp_bridge;
-    v3_unlock_irqrestore(vnet_state.lock, flags);
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
 
     return 0;
 }
 
 
+void v3_vnet_del_bridge(uint8_t type) {
+    unsigned long flags;
+    struct vnet_brg_dev * tmp_bridge = NULL;    
+    
+    flags = vnet_lock_irqsave(vnet_state.lock);
+       
+    if (vnet_state.bridge != NULL && vnet_state.bridge->type == type) {
+       tmp_bridge = vnet_state.bridge;
+       vnet_state.bridge = NULL;
+    }
+       
+    vnet_unlock_irqrestore(vnet_state.lock, flags);
+
+    if (tmp_bridge) {
+       Vnet_Free(tmp_bridge);
+    }
+}
+
+
 static int vnet_tx_flush(void *args){
     unsigned long flags;
     struct queue_entry * entry;
     struct vnet_queue * q = &(vnet_state.pkt_q);
 
-    V3_Print("VNET/P Handing Pkt Thread Starting ....\n");
+    Vnet_Print(0, "VNET/P Handing Pkt Thread Starting ....\n");
 
-    //V3_THREAD_SLEEP();
     /* we need thread sleep/wakeup in Palacios */
-    while(1){
-       flags = v3_lock_irqsave(q->lock);
+    while(!vnet_thread_should_stop()){
+       flags = vnet_lock_irqsave(q->lock);
 
        if (q->count <= 0){
-           v3_unlock_irqrestore(q->lock, flags);
-           v3_yield(NULL);
-           //V3_THREAD_SLEEP();
+           vnet_unlock_irqrestore(q->lock, flags);
+           Vnet_Yield();
        }else {
            q->count --;
            entry = &(q->buf[q->head++]);
            q->head %= VNET_QUEUE_SIZE;
 
-           v3_unlock_irqrestore(q->lock, flags);
+           vnet_unlock_irqrestore(q->lock, flags);
 
            /* 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;
 
-           V3_Net_Print(2, "vnet_tx_flush: pkt (size %d)\n", entry->pkt.size);   
+           Vnet_Print(2, "vnet_tx_flush: pkt (size %d)\n", entry->pkt.size);   
        }
     }
+
+    return 0;
 }
 
 int v3_init_vnet() {
@@ -735,21 +795,21 @@ int v3_init_vnet() {
     vnet_state.num_devs = 0;
     vnet_state.num_routes = 0;
 
-    if (v3_lock_init(&(vnet_state.lock)) == -1){
+    if (vnet_lock_init(&(vnet_state.lock)) == -1){
         PrintError("VNET/P Core: Fails to initiate lock\n");
     }
 
-    vnet_state.route_cache = v3_create_htable(0, &hash_fn, &hash_eq);
+    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");
         return -1;
     }
 
-    v3_lock_init(&(vnet_state.pkt_q.lock));
+    vnet_lock_init(&(vnet_state.pkt_q.lock));
 
-    vnet_state.pkt_flush_thread = V3_CREATE_THREAD(vnet_tx_flush, NULL, "VNET_Pkts");
+    vnet_state.pkt_flush_thread = vnet_start_thread(vnet_tx_flush, NULL, "VNET_Pkts");
 
-    PrintDebug("VNET/P Core is initiated\n");
+    Vnet_Debug("VNET/P Core is initiated\n");
 
     return 0;
 }
@@ -757,13 +817,13 @@ int v3_init_vnet() {
 
 void v3_deinit_vnet(){
 
-    v3_lock_deinit(&(vnet_state.lock));
+    vnet_lock_deinit(&(vnet_state.lock));
 
-    free_devices();
-    free_routes();
+    deinit_devices_list();
+    deinit_routes_list();
 
-    v3_free_htable(vnet_state.route_cache, 1, 1);
-    V3_Free(vnet_state.bridge);
+    vnet_free_htable(vnet_state.route_cache, 1, 1);
+    Vnet_Free(vnet_state.bridge);
 }
 
 
diff --git a/palacios/src/vnet/vnet_hashtable.c b/palacios/src/vnet/vnet_hashtable.c
new file mode 100644 (file)
index 0000000..0da81bd
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+  Copyright (c) 2002, 2004, Christopher Clark
+  All rights reserved.
+  
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+  
+  * Neither the name of the original author; nor the names of any contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+  
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/* Modifications made by Lei Xia <lxia@northwestern.edu> */
+
+#include <vnet/vnet_host.h>
+#include <vnet/vnet_vmm.h>
+#include <vnet/vnet_hashtable.h>
+
+struct hash_entry {
+    addr_t key;
+    addr_t value;
+    uint_t hash;
+    struct hash_entry * next;
+};
+
+struct hashtable {
+    uint_t table_length;
+    struct hash_entry ** table;
+    uint_t entry_count;
+    uint_t load_limit;
+    uint_t prime_index;
+    uint_t (*hash_fn) (addr_t key);
+    int (*eq_fn) (addr_t key1, addr_t key2);
+};
+
+
+
+/* HASH FUNCTIONS */
+static inline uint_t do_hash(struct hashtable * htable, addr_t key) {
+    /* Aim to protect against poor hash functions by adding logic here
+     * - logic taken from java 1.4 hashtable source */
+    uint_t i = htable->hash_fn(key);
+    i += ~(i << 9);
+    i ^=  ((i >> 14) | (i << 18)); /* >>> */
+    i +=  (i << 4);
+    i ^=  ((i >> 10) | (i << 22)); /* >>> */
+
+    return i;
+}
+
+
+/* HASH AN UNSIGNED LONG */
+/* LINUX UNSIGHED LONG HASH FUNCTION */
+#ifdef __V3_32BIT__
+/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
+#define GOLDEN_RATIO_PRIME 0x9e370001UL
+#define BITS_PER_LONG 32
+#elif  defined(__V3_64BIT__)
+/*  2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
+#define GOLDEN_RATIO_PRIME 0x9e37fffffffc0001UL
+#define BITS_PER_LONG 64
+#else
+#error Define GOLDEN_RATIO_PRIME for your wordsize.
+#endif
+
+ulong_t vnet_hash_long(ulong_t val, uint_t bits) {
+    ulong_t hash = val;
+
+#ifdef __V3_64BIT__
+    /*  Sigh, gcc can't optimise this alone like it does for 32 bits. */
+    ulong_t n = hash;
+    n <<= 18;
+    hash -= n;
+    n <<= 33;
+    hash -= n;
+    n <<= 3;
+    hash += n;
+    n <<= 3;
+    hash -= n;
+    n <<= 4;
+    hash += n;
+    n <<= 2;
+    hash += n;
+#else
+    /* On some cpus multiply is faster, on others gcc will do shifts */
+    hash *= GOLDEN_RATIO_PRIME;
+#endif
+
+    /* High bits are more random, so use them. */
+    return hash >> (BITS_PER_LONG - bits);
+}
+
+/* HASH GENERIC MEMORY BUFFER */
+/* ELF HEADER HASH FUNCTION */
+ulong_t vnet_hash_buffer(uchar_t * msg, uint_t length) {
+    ulong_t hash = 0;
+    ulong_t temp = 0;
+    uint_t i;
+
+    for (i = 0; i < length; i++) {
+       hash = (hash << 4) + *(msg + i) + i;
+       if ((temp = (hash & 0xF0000000))) {
+           hash ^= (temp >> 24);
+       }
+       hash &= ~temp;
+    }
+    return hash;
+}
+
+/* indexFor */
+static inline uint_t indexFor(uint_t table_length, uint_t hash_value) {
+    return (hash_value % table_length);
+};
+
+#define freekey(X) Vnet_Free(X)
+
+
+static void * tmp_realloc(void * old_ptr, uint_t old_size, uint_t new_size) {
+    void * new_buf = Vnet_Malloc(new_size);
+
+    if (new_buf == NULL) {
+       return NULL;
+    }
+
+    memcpy(new_buf, old_ptr, old_size);
+    Vnet_Free(old_ptr);
+
+    return new_buf;
+}
+
+
+/*
+  Credit for primes table: Aaron Krowne
+  http://br.endernet.org/~akrowne/
+  http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+*/
+static const uint_t primes[] = { 
+    53, 97, 193, 389,
+    769, 1543, 3079, 6151,
+    12289, 24593, 49157, 98317,
+    196613, 393241, 786433, 1572869,
+    3145739, 6291469, 12582917, 25165843,
+    50331653, 100663319, 201326611, 402653189,
+    805306457, 1610612741 };
+
+
+// this assumes that the max load factor is .65
+static const uint_t load_factors[] = {
+    35, 64, 126, 253,
+    500, 1003, 2002, 3999,
+    7988, 15986, 31953, 63907,
+    127799, 255607, 511182, 1022365,
+    2044731, 4089455, 8178897, 16357798,
+    32715575, 65431158, 130862298, 261724573,
+    523449198, 1046898282 };
+
+static const uint_t prime_table_length = sizeof(primes) / sizeof(primes[0]);
+
+struct hashtable * vnet_create_htable(uint_t min_size,
+                                     uint_t (*hash_fn) (addr_t),
+                                     int (*eq_fn) (addr_t, addr_t)) {
+    struct hashtable * htable;
+    uint_t prime_index;
+    uint_t size = primes[0];
+
+    /* Check requested hashtable isn't too large */
+    if (min_size > (1u << 30)) {
+       return NULL;
+    }
+
+    /* Enforce size as prime */
+    for (prime_index = 0; prime_index < prime_table_length; prime_index++) {
+        if (primes[prime_index] > min_size) { 
+           size = primes[prime_index]; 
+           break; 
+       }
+    }
+
+    htable = (struct hashtable *)Vnet_Malloc(sizeof(struct hashtable));
+
+    if (htable == NULL) {
+       return NULL; /*oom*/
+    }
+
+    htable->table = (struct hash_entry **)Vnet_Malloc(sizeof(struct hash_entry*) * size);
+
+    if (htable->table == NULL) { 
+       V3_Free(htable); 
+       return NULL;  /*oom*/
+    }
+
+    memset(htable->table, 0, size * sizeof(struct hash_entry *));
+
+    htable->table_length  = size;
+    htable->prime_index   = prime_index;
+    htable->entry_count   = 0;
+    htable->hash_fn       = hash_fn;
+    htable->eq_fn         = eq_fn;
+    htable->load_limit    = load_factors[prime_index];
+
+    return htable;
+}
+
+
+
+static int hashtable_expand(struct hashtable * htable) {
+    /* Double the size of the table to accomodate more entries */
+    struct hash_entry ** new_table;
+    struct hash_entry * tmp_entry;
+    struct hash_entry ** entry_ptr;
+    uint_t new_size;
+    uint_t i;
+    uint_t index;
+
+    /* Check we're not hitting max capacity */
+    if (htable->prime_index == (prime_table_length - 1)) {
+       return 0;
+    }
+
+    new_size = primes[++(htable->prime_index)];
+
+    new_table = (struct hash_entry **)Vnet_Malloc(sizeof(struct hash_entry*) * new_size);
+
+    if (new_table != NULL) {
+        memset(new_table, 0, new_size * sizeof(struct hash_entry *));
+        /* This algorithm is not 'stable'. ie. it reverses the list
+         * when it transfers entries between the tables */
+
+        for (i = 0; i < htable->table_length; i++) {
+
+           while ((tmp_entry = htable->table[i]) != NULL) {
+               htable->table[i] = tmp_entry->next;
+          
+               index = indexFor(new_size, tmp_entry->hash);
+           
+               tmp_entry->next = new_table[index];
+           
+               new_table[index] = tmp_entry;
+           }
+        }
+
+        Vnet_Free(htable->table);
+
+        htable->table = new_table;
+    } else {
+       /* Plan B: realloc instead */
+
+       //new_table = (struct hash_entry **)realloc(htable->table, new_size * sizeof(struct hash_entry *));
+       new_table = (struct hash_entry **)tmp_realloc(htable->table, primes[htable->prime_index - 1], 
+                                                     new_size * sizeof(struct hash_entry *));
+
+       if (new_table == NULL) {
+           (htable->prime_index)--;
+           return 0;
+       }
+
+       htable->table = new_table;
+
+       memset(new_table[htable->table_length], 0, new_size - htable->table_length);
+
+       for (i = 0; i < htable->table_length; i++) {
+
+           for (entry_ptr = &(new_table[i]), tmp_entry = *entry_ptr; 
+                tmp_entry != NULL; 
+                tmp_entry = *entry_ptr) {
+
+               index = indexFor(new_size, tmp_entry->hash);
+
+               if (i == index) {
+                   entry_ptr = &(tmp_entry->next);
+               } else {
+                   *entry_ptr = tmp_entry->next;
+                   tmp_entry->next = new_table[index];
+                   new_table[index] = tmp_entry;
+               }
+           }
+       }
+    }
+
+    htable->table_length = new_size;
+
+    htable->load_limit   = load_factors[htable->prime_index];
+
+    return -1;
+}
+
+uint_t vnet_htable_count(struct hashtable * htable) {
+    return htable->entry_count;
+}
+
+int vnet_htable_insert(struct hashtable * htable, addr_t key, addr_t value) {
+    /* This method allows duplicate keys - but they shouldn't be used */
+    uint_t index;
+    struct hash_entry * new_entry;
+
+    if (++(htable->entry_count) > htable->load_limit) {
+       /* Ignore the return value. If expand fails, we should
+        * still try cramming just this value into the existing table
+        * -- we may not have memory for a larger table, but one more
+        * element may be ok. Next time we insert, we'll try expanding again.*/
+       hashtable_expand(htable);
+    }
+
+
+    new_entry = (struct hash_entry *)Vnet_Malloc(sizeof(struct hash_entry));
+
+    if (new_entry == NULL) { 
+       (htable->entry_count)--; 
+       return 0; /*oom*/
+    }
+
+    new_entry->hash = do_hash(htable, key);
+
+    index = indexFor(htable->table_length, new_entry->hash);
+
+    new_entry->key = key;
+    new_entry->value = value;
+
+    new_entry->next = htable->table[index];
+
+    htable->table[index] = new_entry;
+
+    return -1;
+}
+
+
+/* returns value associated with key */
+addr_t vnet_htable_search(struct hashtable * htable, addr_t key) {
+    struct hash_entry * cursor;
+    uint_t hash_value;
+    uint_t index;
+  
+    hash_value = do_hash(htable, key);
+  
+    index = indexFor(htable->table_length, hash_value);
+  
+    cursor = htable->table[index];
+  
+    while (cursor != NULL) {
+       /* Check hash value to short circuit heavier comparison */
+       if ((hash_value == cursor->hash) && 
+           (htable->eq_fn(key, cursor->key))) {
+           return cursor->value;
+       }
+    
+       cursor = cursor->next;
+    }
+  
+    return (addr_t)NULL;
+}
+
+/* returns value associated with key */
+addr_t vnet_htable_remove(struct hashtable * htable, addr_t key, int free_key) {
+    /* TODO: consider compacting the table when the load factor drops enough,
+     *       or provide a 'compact' method. */
+  
+    struct hash_entry * cursor;
+    struct hash_entry ** entry_ptr;
+    addr_t value;
+    uint_t hash_value;
+    uint_t index;
+  
+    hash_value = do_hash(htable, key);
+
+    index = indexFor(htable->table_length, hash_value);
+
+    entry_ptr = &(htable->table[index]);
+    cursor = *entry_ptr;
+
+    while (cursor != NULL) {
+       /* Check hash value to short circuit heavier comparison */
+       if ((hash_value == cursor->hash) && 
+           (htable->eq_fn(key, cursor->key))) {
+     
+           *entry_ptr = cursor->next;
+           htable->entry_count--;
+           value = cursor->value;
+      
+           if (free_key) {
+               freekey((void *)(cursor->key));
+           }
+           Vnet_Free(cursor);
+      
+           return value;
+       }
+
+       entry_ptr = &(cursor->next);
+       cursor = cursor->next;
+    }
+    return (addr_t)NULL;
+}
+
+/* destroy */
+void vnet_free_htable(struct hashtable * htable, int free_values, int free_keys) {
+    uint_t i;
+    struct hash_entry * cursor;;
+    struct hash_entry **table = htable->table;
+
+    if (free_values) {
+       for (i = 0; i < htable->table_length; i++) {
+           cursor = table[i];
+      
+           while (cursor != NULL) { 
+               struct hash_entry * tmp;
+
+               tmp = cursor; 
+               cursor = cursor->next; 
+
+               if (free_keys) {
+                   freekey((void *)(tmp->key)); 
+               }
+               Vnet_Free((void *)(tmp->value)); 
+               Vnet_Free(tmp); 
+           }
+       }
+    } else {
+       for (i = 0; i < htable->table_length; i++) {
+           cursor = table[i];
+
+           while (cursor != NULL) { 
+               struct hash_entry * tmp;
+
+               tmp = cursor; 
+               cursor = cursor->next; 
+       
+               if (free_keys) {
+                   freekey((void *)(tmp->key)); 
+               }
+               Vnet_Free(tmp); 
+           }
+       }
+    }
+  
+    Vnet_Free(htable->table);
+    Vnet_Free(htable);
+}
+
+
+/*
+ * Copyright (c) 2002, Christopher Clark
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/palacios/src/vnet/vnet_host.c b/palacios/src/vnet/vnet_host.c
new file mode 100644 (file)
index 0000000..c5d366a
--- /dev/null
@@ -0,0 +1,77 @@
+/* 
+ * 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, Lei Xia <lxia@northwestern.edu> 
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Lei Xia <lxia@northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+#include <vnet/vnet_host.h>
+#include <vnet/vnet.h>
+
+struct vnet_host_hooks * host_hooks;
+
+int vnet_lock_init(vnet_lock_t * lock) {
+    if((host_hooks) && host_hooks->mutex_alloc){
+       *lock = (addr_t)(host_hooks->mutex_alloc());
+       
+       if (*lock) {
+           return 0;
+       }
+    }
+
+    return -1;
+}
+
+
+struct vnet_thread * vnet_start_thread(int (*func)(void *), void *arg, char * name){
+    if((host_hooks) && host_hooks->thread_start){
+       struct vnet_thread * thread = Vnet_Malloc(sizeof(struct vnet_thread));
+       thread->host_thread = host_hooks->thread_start(func, arg, name);
+
+       if(thread->host_thread){
+           return thread;
+       }
+       Vnet_Free(thread);
+    }
+
+    return NULL;
+}
+
+
+
+struct vnet_timer * vnet_create_timer(unsigned long interval, 
+                                     void (* timer_fun)(void * priv_data), 
+                                     void * priv_data){
+    if((host_hooks) && host_hooks->timer_create){
+       struct vnet_timer * timer = Vnet_Malloc(sizeof(struct vnet_timer));
+       timer->host_timer = host_hooks->timer_create(interval, timer_fun, priv_data);
+       return timer;
+    }
+
+    return NULL;
+ }
+
+
+void init_vnet(struct vnet_host_hooks * hooks){
+    host_hooks = hooks;
+    v3_init_vnet();
+}
+
+
+void deinit_vnet(){
+    host_hooks = NULL;
+    v3_deinit_vnet();
+}
+
index 5b559c9..ef211c8 100644 (file)
@@ -136,17 +136,17 @@ int conf_read_simple(const char *name)
                sym = NULL;
                switch (line[0]) {
                case '#':
-                       if (memcmp(line + 2, "CONFIG_", 7))
+                       if (memcmp(line + 2, "V3_CONFIG_", 10))
                                continue;
-                       p = strchr(line + 9, ' ');
+                       p = strchr(line + 12, ' ');
                        if (!p)
                                continue;
                        *p++ = 0;
                        if (strncmp(p, "is not set", 10))
                                continue;
-                       sym = sym_find(line + 9);
+                       sym = sym_find(line + 12);
                        if (!sym) {
-                               conf_warning("trying to assign nonexistent symbol %s", line + 9);
+                               conf_warning("trying to assign nonexistent symbol %s", line + 12);
                                break;
                        } else if (!(sym->flags & SYMBOL_NEW)) {
                                conf_warning("trying to reassign symbol %s", sym->name);
@@ -162,21 +162,21 @@ int conf_read_simple(const char *name)
                                ;
                        }
                        break;
-               case 'C':
-                       if (memcmp(line, "CONFIG_", 7)) {
-                               conf_warning("unexpected data");
+               case 'V':
+                       if (memcmp(line, "V3_CONFIG_", 10)) {
+                               conf_warning("unexpected data (1)");
                                continue;
                        }
-                       p = strchr(line + 7, '=');
+                       p = strchr(line + 10, '=');
                        if (!p)
                                continue;
                        *p++ = 0;
                        p2 = strchr(p, '\n');
                        if (p2)
                                *p2 = 0;
-                       sym = sym_find(line + 7);
+                       sym = sym_find(line + 10);
                        if (!sym) {
-                               conf_warning("trying to assign nonexistent symbol %s", line + 7);
+                               conf_warning("trying to assign nonexistent symbol %s", line + 10);
                                break;
                        } else if (!(sym->flags & SYMBOL_NEW)) {
                                conf_warning("trying to reassign symbol %s", sym->name);
@@ -233,7 +233,7 @@ int conf_read_simple(const char *name)
                case '\n':
                        break;
                default:
-                       conf_warning("unexpected data");
+                       conf_warning("unexpected data (2)");
                        continue;
                }
                if (sym && sym_is_choice_value(sym)) {
@@ -434,28 +434,28 @@ int conf_write(const char *name)
                        case S_TRISTATE:
                                switch (sym_get_tristate_value(sym)) {
                                case no:
-                                       fprintf(out, "# CONFIG_%s is not set\n", sym->name);
+                                       fprintf(out, "# V3_CONFIG_%s is not set\n", sym->name);
                                        if (out_h)
-                                               fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
+                                               fprintf(out_h, "#undef V3_CONFIG_%s\n", sym->name);
                                        break;
                                case mod:
-                                       fprintf(out, "CONFIG_%s=m\n", sym->name);
+                                       fprintf(out, "V3_CONFIG_%s=m\n", sym->name);
                                        if (out_h)
-                                               fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
+                                               fprintf(out_h, "#define V3_CONFIG_%s_MODULE 1\n", sym->name);
                                        break;
                                case yes:
-                                       fprintf(out, "CONFIG_%s=y\n", sym->name);
+                                       fprintf(out, "V3_CONFIG_%s=y\n", sym->name);
                                        if (out_h)
-                                               fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
+                                               fprintf(out_h, "#define V3_CONFIG_%s 1\n", sym->name);
                                        break;
                                }
                                break;
                        case S_STRING:
                                // fix me
                                str = sym_get_string_value(sym);
-                               fprintf(out, "CONFIG_%s=\"", sym->name);
+                               fprintf(out, "V3_CONFIG_%s=\"", sym->name);
                                if (out_h)
-                                       fprintf(out_h, "#define CONFIG_%s \"", sym->name);
+                                       fprintf(out_h, "#define V3_CONFIG_%s \"", sym->name);
                                do {
                                        l = strcspn(str, "\"\\");
                                        if (l) {
@@ -478,16 +478,16 @@ int conf_write(const char *name)
                        case S_HEX:
                                str = sym_get_string_value(sym);
                                if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
-                                       fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+                                       fprintf(out, "V3_CONFIG_%s=%s\n", sym->name, str);
                                        if (out_h)
-                                               fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
+                                               fprintf(out_h, "#define V3_CONFIG_%s 0x%s\n", sym->name, str);
                                        break;
                                }
                        case S_INT:
                                str = sym_get_string_value(sym);
-                               fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+                               fprintf(out, "V3_CONFIG_%s=%s\n", sym->name, str);
                                if (out_h)
-                                       fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
+                                       fprintf(out_h, "#define V3_CONFIG_%s %s\n", sym->name, str);
                                break;
                        }
                }