From: Jack Lange Date: Sat, 5 Apr 2008 01:08:49 +0000 (+0000) Subject: code restructuring X-Git-Tag: working-cdboot-physical-but-not-qemu~36 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=a109eb919a162bd7de58d62020801bc2e633be50 code restructuring --- diff --git a/palacios/build/Makefile b/palacios/build/Makefile index fad3695..c79201e 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -1,6 +1,6 @@ # Makefile for GeekOS kernel, userspace, and tools # Copyright (c) 2004,2005 David H. Hovemeyer -# $Revision: 1.21 $ +# $Revision: 1.22 $ # This is free software. You are permitted to use, # redistribute, and modify it as specified in the file "COPYING". @@ -84,18 +84,15 @@ KERNEL_C_SRCS := idt.c int.c trap.c irq.c io.c \ bget.c malloc.c \ synch.c kthread.c \ serial.c reboot.c \ - paging.c vm_guest.c \ - svm.c svm_handler.c vmm.c vmm_util.c vmm_stubs.c svm_ctrl_regs.c \ - vmcb.c vmm_mem.c vmm_paging.c vmm_io.c vmm_debug.c svm_io.c \ - vmm_shadow_paging.c vm_guest_mem.c \ - debug.c vmx.c vmcs_gen.c vmcs.c\ + paging.c \ + debug.c vmm_stubs.c vm.c\ main.c # Kernel object files built from C source files KERNEL_C_OBJS := $(KERNEL_C_SRCS:%.c=geekos/%.o) # Kernel assembly files -KERNEL_ASM_SRCS := lowlevel.asm vmx_lowlevel.asm svm_lowlevel.asm +KERNEL_ASM_SRCS := lowlevel.asm KERNEL_GAS_SRCS := testvm.s @@ -118,6 +115,21 @@ COMMON_C_SRCS := fmtout.c string.c memmove.c # Common library object files. COMMON_C_OBJS := $(COMMON_C_SRCS:%.c=common/%.o) +VMM_ASM_SRCS := svm_lowlevel.asm \ +# vmx_lowlevel.asm + +VMM_ASM_OBJS := $(VMM_ASM_SRCS:%.asm=palacios/%.o) + + +VMM_C_SRCS := vm_guest.c \ + svm.c svm_handler.c vmm.c vmm_util.c svm_ctrl_regs.c \ + vmcb.c vmm_mem.c vmm_paging.c vmm_io.c vmm_debug.c svm_io.c \ + vmm_shadow_paging.c vm_guest_mem.c #\ +# vmx.c vmcs_gen.c vmcs.c + +VMM_C_OBJS := $(VMM_C_SRCS:%.c=palacios/%.o) + +VMM_OBJS := $(VMM_C_OBJS) $(VMM_ASM_OBJS) @@ -189,6 +201,12 @@ CC_GENERAL_OPTS := $(GENERAL_OPTS) -Werror # Flags used for kernel C source files CC_KERNEL_OPTS := -g -DGEEKOS -I$(PROJECT_ROOT)/include +# Flags used for VMM C source files +CC_VMM_OPTS := -g -I$(PROJECT_ROOT)/include + +# Flags used for VMM C ASM files +NASM_VMM_OPTS := -I$(PROJECT_ROOT)/src/palacios/ -f elf $(EXTRA_NASM_OPTS) + # Flags user for kernel assembly files NASM_KERNEL_OPTS := -I$(PROJECT_ROOT)/src/geekos/ -f elf $(EXTRA_NASM_OPTS) @@ -225,6 +243,12 @@ geekos/%.o : geekos/%.S common/%.o : common/%.c $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_USER_OPTS) $< -o common/$*.o +palacios/%.o : palacios/%.c + $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_VMM_OPTS) $< -o palacios/$*.o + +palacios/%.o : palacios/%.asm + $(NASM) $(NASM_VMM_OPTS) $< -o palacios/$*.o + # ---------------------------------------------------------------------- # Targets - # Specifies files to be built @@ -234,16 +258,16 @@ common/%.o : common/%.c all : $(ALL_TARGETS) -geekos/vmx_lowlevel.o: $(PROJECT_ROOT)/src/geekos/vmx_lowlevel.asm - $(NASM) -O99 \ - -f elf \ - -I$(PROJECT_ROOT)/src/geekos/ \ - $(PROJECT_ROOT)/src/geekos/vmx_lowlevel.asm \ - -o $@ +#geekos/vmx_lowlevel.o: $(PROJECT_ROOT)/src/geekos/vmx_lowlevel.asm +# $(NASM) -O99 \ +# -f elf \ +# -I$(PROJECT_ROOT)/src/geekos/ \ +# $(PROJECT_ROOT)/src/geekos/vmx_lowlevel.asm \ +# -o $@ -geekos/test: geekos/test.o geekos/vmcs.o geekos/vmx_lowlevel.o - $(CC) geekos/test.o geekos/vmcs.o geekos/vmx_lowlevel.o -o geekos/test +#geekos/test: geekos/test.o geekos/vmcs.o geekos/vmx_lowlevel.o +# $(CC) geekos/test.o geekos/vmcs.o geekos/vmx_lowlevel.o -o geekos/test # Standard floppy image - just boots the kernel fd.img : geekos/fd_boot.bin geekos/setup.bin geekos/kernel.bin vm_kernel @@ -285,9 +309,9 @@ geekos/kernel.bin : geekos/kernel.exe $(PAD) $@ 512 # The kernel executable and symbol map. -geekos/kernel.exe : $(KERNEL_OBJS) $(COMMON_C_OBJS) +geekos/kernel.exe : $(KERNEL_OBJS) $(COMMON_C_OBJS) $(VMM_OBJS) $(TARGET_LD) -o geekos/kernel.exe -Ttext $(KERNEL_BASE_ADDR) -e $(KERNEL_ENTRY) \ - $(KERNEL_OBJS) $(COMMON_C_OBJS) + $(KERNEL_OBJS) $(COMMON_C_OBJS) $(VMM_OBJS) $(TARGET_NM) geekos/kernel.exe > geekos/kernel.syms @@ -300,13 +324,10 @@ vm_kernel: force -vmm_mem_test: geekos/vmm_mem.c - $(HOST_CC) -m32 -o mem_test -DVMM_MEM_TEST -I../include ../src/geekos/vmm_mem.c - # Clean build directories of generated files clean : - for d in geekos common libc user tools; do \ + for d in geekos common libc user tools palacios; do \ (cd $$d && rm -f *); \ done @@ -322,6 +343,10 @@ depend : $(GENERATED_LIBC_SRCS) $(COMMON_C_SRCS:%.c=$(PROJECT_ROOT)/src/common/%.c) \ | $(PERL) -n -e 's,^(\S),common/$$1,;print' \ >> depend.mak + $(TARGET_CC) -M $(CC_GENERAL_OPTS) $(CC_KERNEL_OPTS) \ + $(VMM_C_SRCS:%.c=$(PROJECT_ROOT)/src/palacios/%.c) \ + | $(PERL) -n -e 's,^(\S),palacios/$$1,;print' \ + >> depend.mak # By default, there are no header file dependencies. depend.mak : diff --git a/palacios/build/depend.mak b/palacios/build/depend.mak index e69de29..689ab65 100644 --- a/palacios/build/depend.mak +++ b/palacios/build/depend.mak @@ -0,0 +1,442 @@ +geekos/idt.o: ../src/geekos/idt.c ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/idt.h \ + ../include/geekos/int.h ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/io.h ../include/geekos/debug.h +geekos/int.o: ../src/geekos/int.c ../include/geekos/idt.h \ + ../include/geekos/int.h ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/io.h ../include/geekos/debug.h \ + ../include/geekos/cpu.h +geekos/trap.o: ../src/geekos/trap.c ../include/geekos/idt.h \ + ../include/geekos/int.h ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/kthread.h \ + ../include/geekos/list.h ../include/geekos/trap.h \ + ../include/geekos/serial.h ../include/geekos/irq.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/io.h ../include/geekos/debug.h +geekos/irq.o: ../src/geekos/irq.c ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/idt.h ../include/geekos/int.h \ + ../include/geekos/defs.h ../include/geekos/io.h ../include/geekos/irq.h +geekos/io.o: ../src/geekos/io.c ../include/geekos/io.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h +geekos/blockdev.o: ../src/geekos/blockdev.c ../include/geekos/errno.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/malloc.h ../include/geekos/int.h \ + ../include/geekos/kassert.h ../include/geekos/defs.h \ + ../include/geekos/kthread.h ../include/geekos/list.h \ + ../include/geekos/synch.h ../include/geekos/blockdev.h \ + ../include/geekos/fileio.h +geekos/ide.o: ../src/geekos/ide.c ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/int.h \ + ../include/geekos/kassert.h ../include/geekos/screen.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/io.h ../include/geekos/errno.h \ + ../include/geekos/malloc.h ../include/geekos/timer.h \ + ../include/geekos/kthread.h ../include/geekos/list.h \ + ../include/geekos/blockdev.h ../include/geekos/fileio.h \ + ../include/geekos/ide.h +geekos/keyboard.o: ../src/geekos/keyboard.c ../include/geekos/kthread.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/list.h ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/fmtout.h \ + ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/irq.h ../include/geekos/int.h \ + ../include/geekos/defs.h ../include/geekos/io.h \ + ../include/geekos/keyboard.h +geekos/screen.o: ../src/geekos/screen.c \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/kassert.h ../include/geekos/screen.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + ../include/geekos/io.h ../include/geekos/int.h ../include/geekos/defs.h \ + ../include/geekos/debug.h ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h +geekos/timer.o: ../src/geekos/timer.c \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/limits.h \ + ../include/geekos/io.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/int.h ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/fmtout.h \ + ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/irq.h \ + ../include/geekos/kthread.h ../include/geekos/list.h \ + ../include/geekos/timer.h ../include/geekos/serial.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/debug.h +geekos/mem.o: ../src/geekos/mem.c ../include/geekos/defs.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/kassert.h ../include/geekos/screen.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/bootinfo.h ../include/geekos/gdt.h \ + ../include/geekos/int.h ../include/geekos/malloc.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/mem.h ../include/geekos/list.h \ + ../include/geekos/paging.h ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/io.h \ + ../include/geekos/debug.h +geekos/crc32.o: ../src/geekos/crc32.c ../include/geekos/crc32.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/kassert.h ../include/geekos/screen.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/serial.h ../include/geekos/irq.h \ + ../include/geekos/int.h ../include/geekos/defs.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + ../include/geekos/io.h ../include/geekos/debug.h +geekos/gdt.o: ../src/geekos/gdt.c ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/segment.h ../include/geekos/int.h \ + ../include/geekos/defs.h ../include/geekos/tss.h \ + ../include/geekos/gdt.h ../include/libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/debug.h ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h ../include/geekos/io.h +geekos/tss.o: ../src/geekos/tss.c ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/gdt.h \ + ../include/geekos/segment.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/tss.h ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/int.h ../include/geekos/io.h \ + ../include/geekos/debug.h +geekos/segment.o: ../src/geekos/segment.c ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/tss.h ../include/geekos/segment.h +geekos/bget.o: ../src/geekos/bget.c ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/kassert.h ../include/geekos/screen.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/bget.h +geekos/malloc.o: ../src/geekos/malloc.c ../include/geekos/screen.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/int.h ../include/geekos/kassert.h \ + ../include/geekos/defs.h ../include/geekos/bget.h \ + ../include/geekos/malloc.h +geekos/synch.o: ../src/geekos/synch.c ../include/geekos/kthread.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/list.h ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/fmtout.h \ + ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/int.h ../include/geekos/defs.h \ + ../include/geekos/synch.h +geekos/kthread.o: ../src/geekos/kthread.c ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/int.h \ + ../include/geekos/mem.h ../include/geekos/list.h \ + ../include/geekos/paging.h ../include/geekos/bootinfo.h \ + ../include/geekos/symbol.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/kthread.h ../include/geekos/malloc.h \ + ../include/geekos/serial.h ../include/geekos/irq.h \ + ../include/geekos/io.h ../include/geekos/debug.h +geekos/serial.o: ../src/geekos/serial.c ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/int.h \ + ../include/geekos/kassert.h ../include/geekos/screen.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/io.h ../include/geekos/reboot.h \ + ../include/geekos/gdt.h ../include/geekos/idt.h +geekos/reboot.o: ../src/geekos/reboot.c ../include/geekos/reboot.h \ + ../include/libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h +geekos/paging.o: ../src/geekos/paging.c ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/int.h ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/idt.h \ + ../include/geekos/kthread.h ../include/geekos/list.h \ + ../include/geekos/mem.h ../include/geekos/paging.h \ + ../include/geekos/bootinfo.h ../include/geekos/malloc.h \ + ../include/geekos/gdt.h ../include/geekos/segment.h \ + ../include/geekos/crc32.h ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/io.h \ + ../include/geekos/debug.h +geekos/debug.o: ../src/geekos/debug.c ../include/geekos/debug.h \ + ../include/geekos/serial.h ../include/geekos/irq.h \ + ../include/geekos/int.h ../include/geekos/kassert.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/defs.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/io.h +geekos/vmm_stubs.o: ../src/geekos/vmm_stubs.c ../include/geekos/vmm_stubs.h \ + ../include/geekos/mem.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/defs.h ../include/geekos/list.h \ + ../include/geekos/kassert.h ../include/geekos/screen.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/paging.h ../include/geekos/bootinfo.h \ + ../include/geekos/malloc.h ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/int.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/io.h +geekos/main.o: ../src/geekos/main.c ../include/geekos/bootinfo.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/screen.h ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/geekos/mem.h ../include/geekos/defs.h \ + ../include/geekos/list.h ../include/geekos/kassert.h \ + ../include/geekos/paging.h ../include/geekos/crc32.h \ + ../include/geekos/tss.h ../include/geekos/int.h \ + ../include/geekos/kthread.h ../include/geekos/trap.h \ + ../include/geekos/timer.h ../include/geekos/keyboard.h \ + ../include/geekos/io.h ../include/geekos/serial.h \ + ../include/geekos/irq.h ../include/geekos/reboot.h \ + ../include/geekos/ide.h ../include/geekos/malloc.h \ + ../include/geekos/debug.h ../include/palacios/vmm.h \ + ../include/palacios/vmm_types.h ../include/palacios/vmm_mem.h \ + ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \ + ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h ../include/geekos/gdt.h \ + ../include/geekos/vmm_stubs.h +common/fmtout.o: ../src/common/fmtout.c \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/limits.h \ + ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h +common/string.o: ../src/common/string.c ../include/libc/fmtout.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \ + ../include/libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h +common/memmove.o: ../src/common/memmove.c ../include/libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h +palacios/vm_guest.o: ../src/palacios/vm_guest.c ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vmm_types.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h +palacios/svm.o: ../src/palacios/svm.c ../include/palacios/svm.h \ + ../include/palacios/vmm_util.h ../include/palacios/vmm_types.h \ + ../include/palacios/vmm.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h ../include/palacios/vmcb.h \ + ../include/palacios/svm_handler.h ../include/palacios/vmm_debug.h \ + ../include/palacios/vm_guest_mem.h +palacios/svm_handler.o: ../src/palacios/svm_handler.c \ + ../include/palacios/svm_handler.h ../include/palacios/svm.h \ + ../include/palacios/vmm_util.h ../include/palacios/vmm_types.h \ + ../include/palacios/vmm.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h ../include/palacios/vmcb.h \ + ../include/palacios/svm_ctrl_regs.h ../include/palacios/svm_io.h +palacios/vmm.o: ../src/palacios/vmm.c ../include/palacios/vmm.h \ + ../include/palacios/vmm_types.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h ../include/palacios/svm.h \ + ../include/palacios/vmcb.h ../include/palacios/vmx.h \ + ../include/palacios/vmcs.h ../include/palacios/vmcs_gen.h +palacios/vmm_util.o: ../src/palacios/vmm_util.c ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_types.h ../include/palacios/vmm.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h +palacios/svm_ctrl_regs.o: ../src/palacios/svm_ctrl_regs.c \ + ../include/palacios/svm_ctrl_regs.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vmm_types.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h ../include/palacios/vmm.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmcb.h ../include/palacios/vmm_emulate.h \ + ../include/palacios/vm_guest_mem.h ../include/palacios/vmm_ctrl_regs.h +palacios/vmcb.o: ../src/palacios/vmcb.c ../include/palacios/vmcb.h \ + ../include/palacios/vmm_types.h ../include/palacios/vmm.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h +palacios/vmm_mem.o: ../src/palacios/vmm_mem.c ../include/palacios/vmm_mem.h \ + ../include/palacios/vmm_types.h ../include/palacios/vmm.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \ + ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h +palacios/vmm_paging.o: ../src/palacios/vmm_paging.c \ + ../include/palacios/vmm_paging.h ../include/palacios/vmm_types.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vm_guest_mem.h +palacios/vmm_io.o: ../src/palacios/vmm_io.c ../include/palacios/vmm_io.h \ + ../include/palacios/vmm_types.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h ../include/palacios/vmm_mem.h \ + ../include/palacios/vm_guest.h ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h +palacios/vmm_debug.o: ../src/palacios/vmm_debug.c ../include/palacios/vmm_debug.h \ + ../include/palacios/vmm.h ../include/palacios/vmm_types.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h +palacios/svm_io.o: ../src/palacios/svm_io.c ../include/palacios/svm_io.h \ + ../include/palacios/vm_guest.h ../include/palacios/vmm_mem.h \ + ../include/palacios/vmm_types.h ../include/palacios/vmm_io.h \ + ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h ../include/palacios/vmcb.h \ + ../include/palacios/vmm.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_ctrl_regs.h ../include/palacios/vmm_emulate.h \ + ../include/palacios/vm_guest_mem.h +palacios/vmm_shadow_paging.o: ../src/palacios/vmm_shadow_paging.c \ + ../include/palacios/vmm_shadow_paging.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_types.h ../include/palacios/vmm_paging.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vmm.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \ + ../include/palacios/vm_guest_mem.h +palacios/vm_guest_mem.o: ../src/palacios/vm_guest_mem.c \ + ../include/palacios/vm_guest_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vmm_types.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h ../include/palacios/vmm.h \ + ../include/geekos/string.h ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h +palacios/vmx.o: ../src/palacios/vmx.c ../include/geekos/cpu.h \ + ../include/geekos/io_devs.h ../include/geekos/io.h \ + ../include/geekos/ktypes.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \ + ../include/palacios/vmx.h ../include/palacios/vmm_types.h \ + ../include/palacios/vmcs.h ../include/palacios/vmcs_gen.h \ + ../include/palacios/vmm.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h ../include/palacios/vmm_string.h +palacios/vmcs_gen.o: ../src/palacios/vmcs_gen.c ../include/palacios/vmcs_gen.h \ + ../include/palacios/vmcs.h ../include/palacios/vmm_types.h \ + ../include/palacios/vmm.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h +palacios/vmcs.o: ../src/palacios/vmcs.c ../include/palacios/vmcs.h \ + ../include/palacios/vmm_types.h ../include/palacios/vmcs_gen.h \ + ../include/palacios/vmm.h ../include/geekos/string.h \ + ../include/geekos/../libc/string.h \ + /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \ + ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \ + ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \ + ../include/palacios/vmm_shadow_paging.h \ + ../include/palacios/vmm_paging.h diff --git a/palacios/include/geekos/vm.h b/palacios/include/geekos/vm.h new file mode 100644 index 0000000..57d3ec5 --- /dev/null +++ b/palacios/include/geekos/vm.h @@ -0,0 +1,8 @@ +#ifndef __VM_H +#define __VM_H + +int RunVMM(); + + +#endif + diff --git a/palacios/include/geekos/vmm_stubs.h b/palacios/include/geekos/vmm_stubs.h index 03fbfd2..06e7189 100644 --- a/palacios/include/geekos/vmm_stubs.h +++ b/palacios/include/geekos/vmm_stubs.h @@ -9,7 +9,7 @@ void * Allocate_VMM_Pages(int num_pages); void Free_VMM_Page(void * page); -void * VMM_Malloc(uint_t size); +void * VMM_Malloc(unsigned int size); void VMM_Free(void * addr); void * Identity(void *addr); diff --git a/palacios/include/geekos/svm.h b/palacios/include/palacios/svm.h similarity index 95% rename from palacios/include/geekos/svm.h rename to palacios/include/palacios/svm.h index 8b606b4..fb96a85 100644 --- a/palacios/include/geekos/svm.h +++ b/palacios/include/palacios/svm.h @@ -1,9 +1,9 @@ #ifndef __SVM_H #define __SVM_H -#include -#include -#include +#include +#include +#include #define CPUID_FEATURE_IDS 0x80000001 #define CPUID_FEATURE_IDS_ecx_svm_avail 0x00000004 diff --git a/palacios/include/geekos/svm_ctrl_regs.h b/palacios/include/palacios/svm_ctrl_regs.h similarity index 91% rename from palacios/include/geekos/svm_ctrl_regs.h rename to palacios/include/palacios/svm_ctrl_regs.h index 2ca33d3..73ce4c2 100644 --- a/palacios/include/geekos/svm_ctrl_regs.h +++ b/palacios/include/palacios/svm_ctrl_regs.h @@ -1,8 +1,8 @@ #ifndef __SVM_CTRL_REGS_H #define __SVM_CTRL_REGS_H -#include -#include +#include +#include // First opcode byte diff --git a/palacios/include/geekos/svm_handler.h b/palacios/include/palacios/svm_handler.h similarity index 98% rename from palacios/include/geekos/svm_handler.h rename to palacios/include/palacios/svm_handler.h index 21f030f..376b52f 100644 --- a/palacios/include/geekos/svm_handler.h +++ b/palacios/include/palacios/svm_handler.h @@ -1,8 +1,8 @@ #ifndef __SVM_HANDLER_H #define __SVM_HANDLER_H -#include -#include -#include +#include +#include +#include diff --git a/palacios/include/geekos/svm_io.h b/palacios/include/palacios/svm_io.h similarity index 91% rename from palacios/include/geekos/svm_io.h rename to palacios/include/palacios/svm_io.h index 361a1d9..adb220a 100644 --- a/palacios/include/geekos/svm_io.h +++ b/palacios/include/palacios/svm_io.h @@ -1,8 +1,8 @@ #ifndef __SVM_IO_H #define __SVM_IO_H -#include -#include -#include +#include +#include +#include struct svm_io_info { uint_t type : 1 PACKED; // (0=out, 1=in) diff --git a/palacios/include/geekos/vm_guest.h b/palacios/include/palacios/vm_guest.h similarity index 86% rename from palacios/include/geekos/vm_guest.h rename to palacios/include/palacios/vm_guest.h index f711b36..28dae9e 100644 --- a/palacios/include/geekos/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -1,10 +1,10 @@ #ifndef __VM_GUEST_H #define __VM_GUEST_H -#include -#include -#include -#include +#include +#include +#include +#include typedef ullong_t gpr_t; diff --git a/palacios/include/geekos/vm_guest_mem.h b/palacios/include/palacios/vm_guest_mem.h similarity index 98% rename from palacios/include/geekos/vm_guest_mem.h rename to palacios/include/palacios/vm_guest_mem.h index 24dbca8..3b7ec2e 100644 --- a/palacios/include/geekos/vm_guest_mem.h +++ b/palacios/include/palacios/vm_guest_mem.h @@ -1,8 +1,8 @@ #ifndef __VM_GUEST_MEM_H #define __VM_GUEST_MEM_H -#include -#include +#include +#include /* These functions are ordered such that they can only call the functions defined in a lower order group */ diff --git a/palacios/include/geekos/vmcb.h b/palacios/include/palacios/vmcb.h similarity index 99% rename from palacios/include/geekos/vmcb.h rename to palacios/include/palacios/vmcb.h index 801f44a..7424880 100644 --- a/palacios/include/geekos/vmcb.h +++ b/palacios/include/palacios/vmcb.h @@ -1,7 +1,7 @@ #ifndef __VMCB_H #define __VMCB_H -#include +#include #define VMCB_CTRL_AREA_OFFSET 0x0 diff --git a/palacios/include/geekos/vmcs.h b/palacios/include/palacios/vmcs.h similarity index 99% rename from palacios/include/geekos/vmcs.h rename to palacios/include/palacios/vmcs.h index f73ec3d..bf9f333 100644 --- a/palacios/include/geekos/vmcs.h +++ b/palacios/include/palacios/vmcs.h @@ -1,7 +1,7 @@ #ifndef __VMCS_H #define __VMCS_H -#include +#include /* 16 bit guest state */ @@ -576,6 +576,6 @@ extern uint_t VMCS_READ(); //uint_t VMCSRead(uint_t tag, void * val); -#include +#include #endif diff --git a/palacios/include/geekos/vmcs_gen.h b/palacios/include/palacios/vmcs_gen.h similarity index 99% rename from palacios/include/geekos/vmcs_gen.h rename to palacios/include/palacios/vmcs_gen.h index 0e10af9..5a07922 100644 --- a/palacios/include/geekos/vmcs_gen.h +++ b/palacios/include/palacios/vmcs_gen.h @@ -1,7 +1,7 @@ #ifndef vmcs_gen #define vmcs_gen -#include -#include +#include +#include void Set_VMCS_GUEST_ES_SELECTOR(uint_t val); uint_t Get_VMCS_GUEST_ES_SELECTOR(); diff --git a/palacios/include/geekos/vmm.h b/palacios/include/palacios/vmm.h similarity index 92% rename from palacios/include/geekos/vmm.h rename to palacios/include/palacios/vmm.h index 896598f..d81f4b6 100644 --- a/palacios/include/geekos/vmm.h +++ b/palacios/include/palacios/vmm.h @@ -2,13 +2,13 @@ #define __VMM_H -#include -#include +//#include +#include -#include -//#include +#include +//#include -#include +#include /* utility definitions */ #define PrintDebug(fmt, args...) \ @@ -84,7 +84,7 @@ struct vmm_os_hooks { void *(*allocate_pages)(int numPages); void (*free_page)(void * page); - void *(*malloc)(uint_t size); + void *(*malloc)(unsigned int size); void (*free)(void * addr); void *(*paddr_to_vaddr)(void *addr); diff --git a/palacios/include/geekos/vmm_ctrl_regs.h b/palacios/include/palacios/vmm_ctrl_regs.h similarity index 100% rename from palacios/include/geekos/vmm_ctrl_regs.h rename to palacios/include/palacios/vmm_ctrl_regs.h diff --git a/palacios/include/geekos/vmm_debug.h b/palacios/include/palacios/vmm_debug.h similarity index 100% rename from palacios/include/geekos/vmm_debug.h rename to palacios/include/palacios/vmm_debug.h diff --git a/palacios/include/geekos/vmm_emulate.h b/palacios/include/palacios/vmm_emulate.h similarity index 99% rename from palacios/include/geekos/vmm_emulate.h rename to palacios/include/palacios/vmm_emulate.h index 572cc98..ea24d25 100644 --- a/palacios/include/geekos/vmm_emulate.h +++ b/palacios/include/palacios/vmm_emulate.h @@ -1,6 +1,6 @@ #ifndef __VMM_EMULATE_H #define __VMM_EMULATE_H -#include +#include /* diff --git a/palacios/include/geekos/vmm_io.h b/palacios/include/palacios/vmm_io.h similarity index 94% rename from palacios/include/geekos/vmm_io.h rename to palacios/include/palacios/vmm_io.h index 556be88..f13eee8 100644 --- a/palacios/include/geekos/vmm_io.h +++ b/palacios/include/palacios/vmm_io.h @@ -1,9 +1,9 @@ #ifndef __VMM_IO_H #define __VMM_IO_H -#include +#include -#include +#include // FOREACH_IO_HOOK(vmm_io_map_t * io_map, vmm_io_hook_t * io_hook) #define FOREACH_IO_HOOK(io_map, io_hook) for (io_hook = (io_map).head; io_hook != NULL; io_hook = (io_hook)->next) diff --git a/palacios/include/geekos/vmm_mem.h b/palacios/include/palacios/vmm_mem.h similarity index 99% rename from palacios/include/geekos/vmm_mem.h rename to palacios/include/palacios/vmm_mem.h index e52ae7c..7a6a81c 100644 --- a/palacios/include/geekos/vmm_mem.h +++ b/palacios/include/palacios/vmm_mem.h @@ -2,7 +2,7 @@ #define __VMM_MEM_H -#include +#include typedef ulong_t addr_t; diff --git a/palacios/include/geekos/vmm_paging.h b/palacios/include/palacios/vmm_paging.h similarity index 98% rename from palacios/include/geekos/vmm_paging.h rename to palacios/include/palacios/vmm_paging.h index ec08fd5..1217513 100644 --- a/palacios/include/geekos/vmm_paging.h +++ b/palacios/include/palacios/vmm_paging.h @@ -2,12 +2,12 @@ #define __VMM_PAGING_H -#include +#include -#include -#include +#include +#include /* diff --git a/palacios/include/geekos/vmm_shadow_paging.h b/palacios/include/palacios/vmm_shadow_paging.h similarity index 92% rename from palacios/include/geekos/vmm_shadow_paging.h rename to palacios/include/palacios/vmm_shadow_paging.h index 1817800..7799e06 100644 --- a/palacios/include/geekos/vmm_shadow_paging.h +++ b/palacios/include/palacios/vmm_shadow_paging.h @@ -3,11 +3,11 @@ -#include +#include -#include +#include struct shadow_page_state { diff --git a/palacios/include/palacios/vmm_string.h b/palacios/include/palacios/vmm_string.h new file mode 100644 index 0000000..46ecef5 --- /dev/null +++ b/palacios/include/palacios/vmm_string.h @@ -0,0 +1,34 @@ +/* + * String library + * Copyright (c) 2001,2004 David H. Hovemeyer + * $Revision: 1.1 $ + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "COPYING". + */ + +#ifndef STRING_H +#define STRING_H + +#include + +void* memset(void* s, int c, size_t n); +void* memcpy(void *dst, const void* src, size_t n); +//void *memmove(void *dst, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +size_t strlen(const char* s); +size_t strnlen(const char *s, size_t maxlen); +int strcmp(const char* s1, const char* s2); +int strncmp(const char* s1, const char* s2, size_t limit); +char *strcat(char *s1, const char *s2); +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t limit); +char *strdup(const char *s1); +int atoi(const char *buf); +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); +char *strpbrk(const char *s, const char *accept); + + + +#endif /* STRING_H */ diff --git a/palacios/include/geekos/vmm_types.h b/palacios/include/palacios/vmm_types.h similarity index 50% rename from palacios/include/geekos/vmm_types.h rename to palacios/include/palacios/vmm_types.h index 2d0a6fe..f885bf2 100644 --- a/palacios/include/geekos/vmm_types.h +++ b/palacios/include/palacios/vmm_types.h @@ -1,21 +1,25 @@ #ifndef __VMM_TYPES_H #define __VMM_TYPES_H +#include +/* typedef signed char s8; -typedef unsigned char u8; +typedef unsigned char uchar_t; typedef signed short s16; -typedef unsigned short u16; +typedef unsigned short ushort_t; typedef signed int s32; -typedef unsigned int u32; +typedef unsigned int uint_t; typedef signed long long s64; -typedef unsigned long long u64; +typedef unsigned long long ullong_t; -typedef unsigned long size_t; +typedef unsigned long ulong_t; +typedef unsigned long size_t; +*/ #endif diff --git a/palacios/include/geekos/vmm_util.h b/palacios/include/palacios/vmm_util.h similarity index 94% rename from palacios/include/geekos/vmm_util.h rename to palacios/include/palacios/vmm_util.h index 25994c3..323b977 100644 --- a/palacios/include/geekos/vmm_util.h +++ b/palacios/include/palacios/vmm_util.h @@ -1,7 +1,7 @@ #ifndef __VMM_UTIL_H #define __VMM_UTIL_H -#include +#include #ifndef PAGE_SIZE diff --git a/palacios/include/geekos/vmx.h b/palacios/include/palacios/vmx.h similarity index 97% rename from palacios/include/geekos/vmx.h rename to palacios/include/palacios/vmx.h index 4a8ae25..d713b1f 100644 --- a/palacios/include/geekos/vmx.h +++ b/palacios/include/palacios/vmx.h @@ -1,8 +1,8 @@ #ifndef __VMX_H #define __VMX_H -#include -#include +#include +#include #define IA32_FEATURE_CONTROL_MSR ((unsigned int)0x3a) #define IA32_VMX_BASIC_MSR ((unsigned int)0x480) diff --git a/palacios/src/geekos/main.c b/palacios/src/geekos/main.c index ea43291..ab7dd1f 100644 --- a/palacios/src/geekos/main.c +++ b/palacios/src/geekos/main.c @@ -3,7 +3,7 @@ * Copyright (c) 2001,2003,2004 David H. Hovemeyer * Copyright (c) 2003, Jeffrey K. Hollingsworth * Copyright (c) 2004, Iulian Neamtiu - * $Revision: 1.30 $ + * $Revision: 1.31 $ * * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". @@ -29,18 +29,18 @@ #include #include -#include +#include #include -#include #define SPEAKER_PORT 0x61 + void Buzz(unsigned delay, unsigned num) { volatile int x; @@ -88,89 +88,6 @@ inline uchar_t MyIn_Byte(ushort_t port) -int IO_Read(ushort_t port, void * dst, uint_t length) { - uchar_t * iter = dst; - uint_t i; - - for (i = 0; i < length; i++) { - *iter = MyIn_Byte(port); - iter++; - } - - return 0; -} - - - -int IO_Write(ushort_t port, void * src, uint_t length) { - uchar_t * iter = src; - uint_t i; - - - for (i = 0; i < length; i++) { - MyOut_Byte(port, *iter); - iter++; - } - - return 0; -} - - - -int IO_Write_to_Serial(ushort_t port, void * src, uint_t length) { - PrintBoth("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length); - switch (length) { - - case 1: - PrintBoth(">0x%.2x\n", *(char*)src); - break; - case 2: - PrintBoth(">0x%.4x\n", *(ushort_t*)src); - break; - case 4: - PrintBoth(">0x%.8x\n", *(uint_t*)src); - break; - default: - break; - } - - // SerialMemDump(src, length); - return length; -} - - -void BuzzVM() -{ - int x; - int j; - unsigned char init; - -#if 0 - __asm__ __volatile__ ( - "popf" - ); - -#endif - - PrintBoth("Starting To Buzz\n"); - - init=MyIn_Byte(SPEAKER_PORT); - - while (1) { - MyOut_Byte(SPEAKER_PORT, init|0x2); - for (j=0;j<1000000;j++) { - x+=j; - } - MyOut_Byte(SPEAKER_PORT, init); - for (j=0;j<1000000;j++) { - x+=j; - } - } -} - - - - @@ -307,81 +224,7 @@ void Main(struct Boot_Info* bootInfo) #endif { - struct vmm_os_hooks os_hooks; - struct vmm_ctrl_ops vmm_ops; - struct guest_info vm_info; - addr_t rsp; - addr_t rip; - - memset(&os_hooks, 0, sizeof(struct vmm_os_hooks)); - memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops)); - memset(&vm_info, 0, sizeof(struct guest_info)); - - os_hooks.print_debug = &PrintBoth; - os_hooks.print_info = &Print; - os_hooks.print_trace = &SerialPrint; - os_hooks.allocate_pages = &Allocate_VMM_Pages; - os_hooks.free_page = &Free_VMM_Page; - os_hooks.malloc = &VMM_Malloc; - os_hooks.free = &VMM_Free; - os_hooks.vaddr_to_paddr = &Identity; - os_hooks.paddr_to_vaddr = &Identity; - - - // DumpGDT(); - Init_VMM(&os_hooks, &vmm_ops); - - init_shadow_map(&(vm_info.mem_map)); - init_shadow_page_state(&(vm_info.shdw_pg_state)); - vm_info.page_mode = SHADOW_PAGING; - - vm_info.cpu_mode = REAL; - - init_vmm_io_map(&(vm_info.io_map)); - - - if (0) { - - // add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000); - // add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0); - - rip = (ulong_t)(void*)&BuzzVM; - // rip -= 0x10000; - // rip = (addr_t)(void*)&exit_test; - // rip -= 0x2000; - vm_info.rip = rip; - rsp = (addr_t)Alloc_Page(); - - vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000; - - - } else { - //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000); - // add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0); - - shadow_region_t *ent = Malloc(sizeof(shadow_region_t));; - init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY, - 0x100000, HOST_REGION_PHYSICAL_MEMORY); - add_shadow_region(&(vm_info.mem_map),ent); - - hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write); - hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial); - - /* - vm_info.cr0 = 0; - vm_info.cs.base=0xf000; - vm_info.cs.limit=0xffff; - */ - //vm_info.rip = 0xfff0; - - vm_info.rip = 0; - vm_info.vm_regs.rsp = 0x0; - } - - PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp); - (vmm_ops).init_guest(&vm_info); - PrintBoth("Starting Guest\n"); - (vmm_ops).start_guest(&vm_info); + RunVMM(); } diff --git a/palacios/src/geekos/symbol.asm b/palacios/src/geekos/symbol.asm index 0bb1584..df9abf2 100644 --- a/palacios/src/geekos/symbol.asm +++ b/palacios/src/geekos/symbol.asm @@ -1,6 +1,6 @@ ; Symbol mangling macros ; Copyright (c) 2001, David H. Hovemeyer -; $Revision: 1.1 $ +; $Revision: 1.2 $ ; This file defines macros for dealing with externally-visible ; symbols that must be mangled for some object file formats. @@ -13,8 +13,8 @@ ; Thanks to Christopher Giese for providing the NASM macros ; (thus saving me hours of frustration). -%ifndef SYMBOL_ASM -%define SYMBOL_ASM +%ifndef __VMM_SYMBOL_ASM +%define __VMM_SYMBOL_ASM %ifdef NEED_UNDERSCORE diff --git a/palacios/src/geekos/vm.c b/palacios/src/geekos/vm.c new file mode 100644 index 0000000..72940ed --- /dev/null +++ b/palacios/src/geekos/vm.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include + + +#define SPEAKER_PORT 0x61 + + + + +inline void VM_Out_Byte(ushort_t port, uchar_t value) +{ + __asm__ __volatile__ ( + "outb %b0, %w1" + : + : "a" (value), "Nd" (port) + ); +} + +/* + * Read a byte from an I/O port. + */ +inline uchar_t VM_In_Byte(ushort_t port) +{ + uchar_t value; + + __asm__ __volatile__ ( + "inb %w1, %b0" + : "=a" (value) + : "Nd" (port) + ); + + return value; +} + + + +int IO_Read(ushort_t port, void * dst, uint_t length) { + uchar_t * iter = dst; + uint_t i; + + for (i = 0; i < length; i++) { + *iter = VM_In_Byte(port); + iter++; + } + + return 0; +} + + + +int IO_Write(ushort_t port, void * src, uint_t length) { + uchar_t * iter = src; + uint_t i; + + + for (i = 0; i < length; i++) { + VM_Out_Byte(port, *iter); + iter++; + } + + return 0; +} + + + +int IO_Write_to_Serial(ushort_t port, void * src, uint_t length) { + PrintBoth("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length); + switch (length) { + + case 1: + PrintBoth(">0x%.2x\n", *(char*)src); + break; + case 2: + PrintBoth(">0x%.4x\n", *(ushort_t*)src); + break; + case 4: + PrintBoth(">0x%.8x\n", *(uint_t*)src); + break; + default: + break; + } + + // SerialMemDump(src, length); + return length; +} + + + +void BuzzVM() +{ + int x; + int j; + unsigned char init; + +#if 0 + __asm__ __volatile__ ( + "popf" + ); + +#endif + + PrintBoth("Starting To Buzz\n"); + + init=VM_In_Byte(SPEAKER_PORT); + + while (1) { + VM_Out_Byte(SPEAKER_PORT, init|0x2); + for (j=0;j<1000000;j++) { + x+=j; + } + VM_Out_Byte(SPEAKER_PORT, init); + for (j=0;j<1000000;j++) { + x+=j; + } + } +} + + + + + + +int RunVMM() { + + struct vmm_os_hooks os_hooks; + struct vmm_ctrl_ops vmm_ops; + struct guest_info vm_info; + addr_t rsp; + addr_t rip; + + memset(&os_hooks, 0, sizeof(struct vmm_os_hooks)); + memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops)); + memset(&vm_info, 0, sizeof(struct guest_info)); + + os_hooks.print_debug = &PrintBoth; + os_hooks.print_info = &Print; + os_hooks.print_trace = &SerialPrint; + os_hooks.allocate_pages = &Allocate_VMM_Pages; + os_hooks.free_page = &Free_VMM_Page; + os_hooks.malloc = &VMM_Malloc; + os_hooks.free = &VMM_Free; + os_hooks.vaddr_to_paddr = &Identity; + os_hooks.paddr_to_vaddr = &Identity; + + + // DumpGDT(); + Init_VMM(&os_hooks, &vmm_ops); + + init_shadow_map(&(vm_info.mem_map)); + init_shadow_page_state(&(vm_info.shdw_pg_state)); + vm_info.page_mode = SHADOW_PAGING; + + vm_info.cpu_mode = REAL; + + init_vmm_io_map(&(vm_info.io_map)); + + + if (0) { + + // add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000); + // add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0); + + rip = (ulong_t)(void*)&BuzzVM; + // rip -= 0x10000; + // rip = (addr_t)(void*)&exit_test; + // rip -= 0x2000; + vm_info.rip = rip; + rsp = (addr_t)Alloc_Page(); + + vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000; + + + } else { + //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000); + // add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0); + + shadow_region_t *ent = Malloc(sizeof(shadow_region_t));; + init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY, + 0x100000, HOST_REGION_PHYSICAL_MEMORY); + add_shadow_region(&(vm_info.mem_map),ent); + + hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write); + hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial); + + /* + vm_info.cr0 = 0; + vm_info.cs.base=0xf000; + vm_info.cs.limit=0xffff; + */ + //vm_info.rip = 0xfff0; + + vm_info.rip = 0; + vm_info.vm_regs.rsp = 0x0; + } + + PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp); + (vmm_ops).init_guest(&vm_info); + PrintBoth("Starting Guest\n"); + (vmm_ops).start_guest(&vm_info); + + return 0; + +} diff --git a/palacios/src/geekos/vmm_stubs.c b/palacios/src/geekos/vmm_stubs.c index 4c37033..0bc48e3 100644 --- a/palacios/src/geekos/vmm_stubs.c +++ b/palacios/src/geekos/vmm_stubs.c @@ -36,8 +36,8 @@ void Free_VMM_Page(void * page) { } -void * VMM_Malloc(uint_t size) { - return Malloc((ulong_t) size); +void * VMM_Malloc(unsigned int size) { + return Malloc((unsigned long) size); } diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c new file mode 100644 index 0000000..5b2e0c8 --- /dev/null +++ b/palacios/src/palacios/svm.c @@ -0,0 +1,588 @@ +#include +#include + +#include +#include +#include +#include + +#include +#include + + +/* TEMPORARY BECAUSE SVM IS WEIRD */ +//#include +/* ** */ + +extern struct vmm_os_hooks * os_hooks; + +extern uint_t cpuid_ecx(uint_t op); +extern uint_t cpuid_edx(uint_t op); +extern void Get_MSR(uint_t MSR, uint_t * high_byte, uint_t * low_byte); +extern void Set_MSR(uint_t MSR, uint_t high_byte, uint_t low_byte); +extern uint_t launch_svm(vmcb_t * vmcb_addr); +extern void safe_svm_launch(vmcb_t * vmcb_addr, struct guest_gprs * gprs); + +extern uint_t Get_CR3(); + +extern void GetGDTR(void * gdt); +extern void GetIDTR(void * idt); + +extern void DisableInts(); + +/* Checks machine SVM capability */ +/* Implemented from: AMD Arch Manual 3, sect 15.4 */ +int is_svm_capable() { + uint_t ret = cpuid_ecx(CPUID_FEATURE_IDS); + uint_t vm_cr_low = 0, vm_cr_high = 0; + + + if ((ret & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) { + PrintDebug("SVM Not Available\n"); + return 0; + } + + Get_MSR(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low); + + if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) { + PrintDebug("Nested Paging not supported\n"); + } + + if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) { + return 1; + } + + ret = cpuid_edx(CPUID_SVM_REV_AND_FEATURE_IDS); + + if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) { + PrintDebug("SVM BIOS Disabled, not unlockable\n"); + } else { + PrintDebug("SVM is locked with a key\n"); + } + + return 0; +} + + + +void Init_SVM(struct vmm_ctrl_ops * vmm_ops) { + reg_ex_t msr; + void * host_state; + + + // Enable SVM on the CPU + Get_MSR(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low)); + msr.e_reg.low |= EFER_MSR_svm_enable; + Set_MSR(EFER_MSR, 0, msr.e_reg.low); + + PrintDebug("SVM Enabled\n"); + + + // Setup the host state save area + host_state = os_hooks->allocate_pages(4); + + msr.e_reg.high = 0; + msr.e_reg.low = (uint_t)host_state; + + + PrintDebug("Host State being saved at %x\n", (uint_t)host_state); + Set_MSR(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low); + + + + // Setup the SVM specific vmm operations + vmm_ops->init_guest = &init_svm_guest; + vmm_ops->start_guest = &start_svm_guest; + + + return; +} + + +int init_svm_guest(struct guest_info *info) { + + PrintDebug("Allocating VMCB\n"); + info->vmm_data = (void*)Allocate_VMCB(); + + + //PrintDebug("Generating Guest nested page tables\n"); + // info->page_tables = NULL; + //info->page_tables = generate_guest_page_tables_64(&(info->mem_layout), &(info->mem_list)); + //info->page_tables = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list)); + //PrintDebugPageTables(info->page_tables); + + + PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data); + Init_VMCB((vmcb_t*)(info->vmm_data), *info); + + // info->rip = 0; + + info->vm_regs.rdi = 0; + info->vm_regs.rsi = 0; + info->vm_regs.rbp = 0; + info->vm_regs.rsp = 0; + info->vm_regs.rbx = 0; + info->vm_regs.rdx = 0; + info->vm_regs.rcx = 0; + info->vm_regs.rax = 0; + + return 0; +} + + +// can we start a kernel thread here... +int start_svm_guest(struct guest_info *info) { + + + + PrintDebug("Launching SVM VM (vmcb=%x)\n", info->vmm_data); + //PrintDebugVMCB((vmcb_t*)(info->vmm_data)); + + while (1) { + + PrintDebug("SVM Launch Args (vmcb=%x), (info=%x), (vm_regs=%x)\n", info->vmm_data, &(info->vm_regs)); + PrintDebug("Launching to RIP: %x\n", info->rip); + safe_svm_launch((vmcb_t*)(info->vmm_data), &(info->vm_regs)); + //launch_svm((vmcb_t*)(info->vmm_data)); + PrintDebug("SVM Returned\n"); + + if (handle_svm_exit(info) != 0) { + // handle exit code.... + break; + } + } + return 0; +} + + + +vmcb_t * Allocate_VMCB() { + vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1); + + + memset(vmcb_page, 0, 4096); + + return vmcb_page; +} + + +void Init_VMCB_Real(vmcb_t * vmcb, struct guest_info vm_info) { + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb); + uint_t i; + + + guest_state->rsp = vm_info.vm_regs.rsp; + guest_state->rip = vm_info.rip; + + + guest_state->efer |= EFER_MSR_svm_enable; + guest_state->rflags = 0x00000002; // The reserved bit is always 1 + ctrl_area->svm_instrs.instrs.VMRUN = 1; + ctrl_area->guest_ASID = 1; + guest_state->cr0 = 0x60000010; + + + ctrl_area->exceptions.ex_names.de = 1; + ctrl_area->exceptions.ex_names.df = 1; + ctrl_area->exceptions.ex_names.pf = 1; + ctrl_area->exceptions.ex_names.ts = 1; + ctrl_area->exceptions.ex_names.ss = 1; + ctrl_area->exceptions.ex_names.ac = 1; + ctrl_area->exceptions.ex_names.mc = 1; + ctrl_area->exceptions.ex_names.gp = 1; + ctrl_area->exceptions.ex_names.ud = 1; + ctrl_area->exceptions.ex_names.np = 1; + ctrl_area->exceptions.ex_names.of = 1; + ctrl_area->exceptions.ex_names.nmi = 1; + + guest_state->cs.selector = 0xf000; + guest_state->cs.limit=0xffff; + guest_state->cs.base = 0xffff0000; + guest_state->cs.attrib.raw = 0x9a; + + + struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL}; + for ( i = 0; segregs[i] != NULL; i++) { + struct vmcb_selector * seg = segregs[i]; + + seg->selector = 0x0000; + seg->base = 0xffff0000; + seg->attrib.raw = 0x9b; + seg->limit = 0xffff; + } + + /* Set GPRs */ + /* + EDX == 0xfxx + EAX, EBX, ECX, ESI, EDI, EBP, ESP == 0x0 + */ + + guest_state->gdtr.base = 0; + guest_state->gdtr.limit = 0xffff; + guest_state->gdtr.attrib.raw = 0x0; + + guest_state->idtr.base = 0; + guest_state->idtr.limit = 0xffff; + guest_state->idtr.attrib.raw = 0x0; + + guest_state->ldtr.base = 0; + guest_state->ldtr.limit = 0xffff; + guest_state->ldtr.attrib.raw = 0x82; + + guest_state->tr.base = 0; + guest_state->tr.limit = 0xffff; + guest_state->tr.attrib.raw = 0x83; + + + + + if (vm_info.io_map.num_ports > 0) { + vmm_io_hook_t * iter; + addr_t io_port_bitmap; + + io_port_bitmap = (addr_t)os_hooks->allocate_pages(3); + memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3); + + ctrl_area->IOPM_BASE_PA = io_port_bitmap; + + //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap); + + FOREACH_IO_HOOK(vm_info.io_map, iter) { + ushort_t port = iter->port; + uchar_t * bitmap = (uchar_t *)io_port_bitmap; + + bitmap += (port / 8); + PrintDebug("Setting Bit in block %x\n", bitmap); + *bitmap |= 1 << (port % 8); + } + + ctrl_area->instrs.instrs.IOIO_PROT = 1; + } + + ctrl_area->instrs.instrs.INTR = 1; + + // also determine if CPU supports nested paging + + if (vm_info.page_mode == SHADOW_PAGING) { + PrintDebug("Creating initial shadow page table\n"); + vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff); + PrintDebug("Created\n"); + + guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg; + + ctrl_area->cr_reads.crs.cr3 = 1; + ctrl_area->cr_writes.crs.cr3 = 1; + ctrl_area->cr_reads.crs.cr0 = 1; + ctrl_area->cr_writes.crs.cr0 = 1; + + ctrl_area->instrs.instrs.INVLPG = 1; + ctrl_area->instrs.instrs.INVLPGA = 1; + + + guest_state->g_pat = 0x7040600070406ULL; + + vm_info.shdw_pg_state.guest_cr0.e_reg.low = guest_state->cr0; + guest_state->cr0 |= 0x80000000; + } else if (vm_info.page_mode == NESTED_PAGING) { + // Flush the TLB on entries/exits + //ctrl_area->TLB_CONTROL = 1; + + // Enable Nested Paging + //ctrl_area->NP_ENABLE = 1; + + //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE)); + + // Set the Nested Page Table pointer + // ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables); + // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables); + + // ctrl_area->N_CR3 = Get_CR3(); + // guest_state->cr3 |= (Get_CR3() & 0xfffff000); + + // guest_state->g_pat = 0x7040600070406ULL; + } + +} + + +void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) { + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb); + uint_t i; + + + guest_state->rsp = vm_info.vm_regs.rsp; + guest_state->rip = vm_info.rip; + + + //ctrl_area->instrs.instrs.CR0 = 1; + ctrl_area->cr_reads.crs.cr0 = 1; + ctrl_area->cr_writes.crs.cr0 = 1; + + guest_state->efer |= EFER_MSR_svm_enable; + guest_state->rflags = 0x00000002; // The reserved bit is always 1 + ctrl_area->svm_instrs.instrs.VMRUN = 1; + // guest_state->cr0 = 0x00000001; // PE + ctrl_area->guest_ASID = 1; + + + ctrl_area->exceptions.ex_names.de = 1; + ctrl_area->exceptions.ex_names.df = 1; + ctrl_area->exceptions.ex_names.pf = 1; + ctrl_area->exceptions.ex_names.ts = 1; + ctrl_area->exceptions.ex_names.ss = 1; + ctrl_area->exceptions.ex_names.ac = 1; + ctrl_area->exceptions.ex_names.mc = 1; + ctrl_area->exceptions.ex_names.gp = 1; + ctrl_area->exceptions.ex_names.ud = 1; + ctrl_area->exceptions.ex_names.np = 1; + ctrl_area->exceptions.ex_names.of = 1; + ctrl_area->exceptions.ex_names.nmi = 1; + + guest_state->cs.selector = 0x0000; + guest_state->cs.limit=~0u; + guest_state->cs.base = guest_state->cs.selector<<4; + guest_state->cs.attrib.raw = 0xf3; + + + struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL}; + for ( i = 0; segregs[i] != NULL; i++) { + struct vmcb_selector * seg = segregs[i]; + + seg->selector = 0x0000; + seg->base = seg->selector << 4; + seg->attrib.raw = 0xf3; + seg->limit = ~0u; + } + + if (vm_info.io_map.num_ports > 0) { + vmm_io_hook_t * iter; + addr_t io_port_bitmap; + + io_port_bitmap = (addr_t)os_hooks->allocate_pages(3); + memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3); + + ctrl_area->IOPM_BASE_PA = io_port_bitmap; + + //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap); + + FOREACH_IO_HOOK(vm_info.io_map, iter) { + ushort_t port = iter->port; + uchar_t * bitmap = (uchar_t *)io_port_bitmap; + + bitmap += (port / 8); + PrintDebug("Setting Bit in block %x\n", bitmap); + *bitmap |= 1 << (port % 8); + } + + + //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2); + + ctrl_area->instrs.instrs.IOIO_PROT = 1; + } + + ctrl_area->instrs.instrs.INTR = 1; + + + + if (vm_info.page_mode == SHADOW_PAGING) { + PrintDebug("Creating initial shadow page table\n"); + vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff); + PrintDebug("Created\n"); + + guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg; + + ctrl_area->cr_reads.crs.cr3 = 1; + ctrl_area->cr_writes.crs.cr3 = 1; + + + ctrl_area->instrs.instrs.INVLPG = 1; + ctrl_area->instrs.instrs.INVLPGA = 1; + + guest_state->g_pat = 0x7040600070406ULL; + + guest_state->cr0 |= 0x80000000; + } else if (vm_info.page_mode == NESTED_PAGING) { + // Flush the TLB on entries/exits + //ctrl_area->TLB_CONTROL = 1; + + // Enable Nested Paging + //ctrl_area->NP_ENABLE = 1; + + //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE)); + + // Set the Nested Page Table pointer + // ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables); + // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables); + + // ctrl_area->N_CR3 = Get_CR3(); + // guest_state->cr3 |= (Get_CR3() & 0xfffff000); + + // guest_state->g_pat = 0x7040600070406ULL; + } + + + +} + +void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) { + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb); + uint_t i = 0; + + + guest_state->rsp = vm_info.vm_regs.rsp; + guest_state->rip = vm_info.rip; + + + /* I pretty much just gutted this from TVMM */ + /* Note: That means its probably wrong */ + + // set the segment registers to mirror ours + guest_state->cs.selector = 1<<3; + guest_state->cs.attrib.fields.type = 0xa; // Code segment+read + guest_state->cs.attrib.fields.S = 1; + guest_state->cs.attrib.fields.P = 1; + guest_state->cs.attrib.fields.db = 1; + guest_state->cs.attrib.fields.G = 1; + guest_state->cs.limit = 0xfffff; + guest_state->cs.base = 0; + + struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL}; + for ( i = 0; segregs[i] != NULL; i++) { + struct vmcb_selector * seg = segregs[i]; + + seg->selector = 2<<3; + seg->attrib.fields.type = 0x2; // Data Segment+read/write + seg->attrib.fields.S = 1; + seg->attrib.fields.P = 1; + seg->attrib.fields.db = 1; + seg->attrib.fields.G = 1; + seg->limit = 0xfffff; + seg->base = 0; + } + + + { + /* JRL THIS HAS TO GO */ + + // guest_state->tr.selector = GetTR_Selector(); + guest_state->tr.attrib.fields.type = 0x9; + guest_state->tr.attrib.fields.P = 1; + // guest_state->tr.limit = GetTR_Limit(); + //guest_state->tr.base = GetTR_Base();// - 0x2000; + /* ** */ + } + + + /* ** */ + + + guest_state->efer |= EFER_MSR_svm_enable; + guest_state->rflags = 0x00000002; // The reserved bit is always 1 + ctrl_area->svm_instrs.instrs.VMRUN = 1; + guest_state->cr0 = 0x00000001; // PE + ctrl_area->guest_ASID = 1; + + + // guest_state->cpl = 0; + + + + // Setup exits + + ctrl_area->cr_writes.crs.cr4 = 1; + + ctrl_area->exceptions.ex_names.de = 1; + ctrl_area->exceptions.ex_names.df = 1; + ctrl_area->exceptions.ex_names.pf = 1; + ctrl_area->exceptions.ex_names.ts = 1; + ctrl_area->exceptions.ex_names.ss = 1; + ctrl_area->exceptions.ex_names.ac = 1; + ctrl_area->exceptions.ex_names.mc = 1; + ctrl_area->exceptions.ex_names.gp = 1; + ctrl_area->exceptions.ex_names.ud = 1; + ctrl_area->exceptions.ex_names.np = 1; + ctrl_area->exceptions.ex_names.of = 1; + ctrl_area->exceptions.ex_names.nmi = 1; + + + + ctrl_area->instrs.instrs.IOIO_PROT = 1; + ctrl_area->IOPM_BASE_PA = (uint_t)os_hooks->allocate_pages(3); + + { + reg_ex_t tmp_reg; + tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA; + memset((void*)(tmp_reg.e_reg.low), 0xffffffff, PAGE_SIZE * 2); + } + + ctrl_area->instrs.instrs.INTR = 1; + + + { + char gdt_buf[6]; + char idt_buf[6]; + + memset(gdt_buf, 0, 6); + memset(idt_buf, 0, 6); + + + uint_t gdt_base, idt_base; + ushort_t gdt_limit, idt_limit; + + GetGDTR(gdt_buf); + gdt_base = *(ulong_t*)((uchar_t*)gdt_buf + 2) & 0xffffffff; + gdt_limit = *(ushort_t*)(gdt_buf) & 0xffff; + PrintDebug("GDT: base: %x, limit: %x\n", gdt_base, gdt_limit); + + GetIDTR(idt_buf); + idt_base = *(ulong_t*)(idt_buf + 2) & 0xffffffff; + idt_limit = *(ushort_t*)(idt_buf) & 0xffff; + PrintDebug("IDT: base: %x, limit: %x\n",idt_base, idt_limit); + + + // gdt_base -= 0x2000; + //idt_base -= 0x2000; + + guest_state->gdtr.base = gdt_base; + guest_state->gdtr.limit = gdt_limit; + guest_state->idtr.base = idt_base; + guest_state->idtr.limit = idt_limit; + + + } + + + // also determine if CPU supports nested paging + /* + if (vm_info.page_tables) { + // if (0) { + // Flush the TLB on entries/exits + ctrl_area->TLB_CONTROL = 1; + + // Enable Nested Paging + ctrl_area->NP_ENABLE = 1; + + PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE)); + + // Set the Nested Page Table pointer + ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000); + + + // ctrl_area->N_CR3 = Get_CR3(); + // guest_state->cr3 |= (Get_CR3() & 0xfffff000); + + guest_state->g_pat = 0x7040600070406ULL; + + PrintDebug("Set Nested CR3: lo: 0x%x hi: 0x%x\n", (uint_t)*(&(ctrl_area->N_CR3)), (uint_t)*((unsigned char *)&(ctrl_area->N_CR3) + 4)); + PrintDebug("Set Guest CR3: lo: 0x%x hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*((unsigned char *)&(guest_state->cr3) + 4)); + // Enable Paging + // guest_state->cr0 |= 0x80000000; + } + */ + +} + + diff --git a/palacios/src/palacios/svm_ctrl_regs.c b/palacios/src/palacios/svm_ctrl_regs.c new file mode 100644 index 0000000..18333b4 --- /dev/null +++ b/palacios/src/palacios/svm_ctrl_regs.c @@ -0,0 +1,276 @@ +#include +#include +#include +#include +#include +#include +#include + + +/* Segmentation is a problem here... + * + * When we get a memory operand, presumably we use the default segment (which is?) + * unless an alternate segment was specfied in the prefix... + */ + + +int handle_cr0_write(struct guest_info * info) { + //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data)); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); + char instr[15]; + + + if (info->cpu_mode == REAL) { + int index = 0; + int ret; + + // The real rip address is actually a combination of the rip + CS base + ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.base), 15, instr); + if (ret != 15) { + // I think we should inject a GPF into the guest + PrintDebug("Could not read instruction (ret=%d)\n", ret); + return -1; + } + + while (is_prefix_byte(instr[index])) { + index++; + } + + if ((instr[index] == cr_access_byte) && + (instr[index + 1] == lmsw_byte) && + (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) { + + addr_t first_operand; + addr_t second_operand; + struct cr0_real *old_cr0; + struct cr0_real *new_cr0; + operand_type_t addr_type; + char new_cr0_val = 0; + // LMSW + // decode mod/RM + index += 2; + + old_cr0 = (struct cr0_real*)&(guest_state->cr0); + + + addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16); + + + if (addr_type == REG_OPERAND) { + new_cr0 = (struct cr0_real *)first_operand; + } else if (addr_type == MEM_OPERAND) { + addr_t host_addr; + + if (guest_pa_to_host_va(info, first_operand + (guest_state->ds.base << 4), &host_addr) == -1) { + // gpf the guest + return -1; + } + + new_cr0 = (struct cr0_real *)host_addr; + } else { + // error... don't know what to do + return -1; + } + + if ((new_cr0->pe == 1) && (old_cr0->pe == 0)) { + info->cpu_mode = PROTECTED; + } else if ((new_cr0->pe == 0) && (old_cr0->pe == 1)) { + info->cpu_mode = REAL; + } + + new_cr0_val = *(char*)(new_cr0) & 0x0f; + + + if (info->page_mode == SHADOW_PAGING) { + struct cr0_real * virt_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0); + + /* struct cr0_real is only 4 bits wide, + * so we can overwrite the old_cr0 without worrying about the shadow fields + */ + *(char*)old_cr0 &= 0xf0; + *(char*)old_cr0 |= new_cr0_val; + + *(char*)virt_cr0 &= 0xf0; + *(char*)virt_cr0 |= new_cr0_val; + } else { + // for now we just pass through.... + *(char*)old_cr0 &= 0xf0; + *(char*)old_cr0 |= new_cr0_val; + } + + PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip)); + info->rip += index; + PrintDebug("new_rip = %x\n", (ulong_t)(info->rip)); + } else if ((instr[index] == cr_access_byte) && + (instr[index + 1] == clts_byte)) { + // CLTS + } else { + // unsupported instruction, UD the guest + return -1; + } + + + } else if (info->cpu_mode == PROTECTED) { + int index = 0; + int ret; + + PrintDebug("Protected Mode write to CR0\n"); + + // The real rip address is actually a combination of the rip + CS base + ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.base), 15, instr); + if (ret != 0) { + // I think we should inject a GPF into the guest + PrintDebug("Could not read instruction (ret=%d)\n", ret); + return -1; + } + + while (is_prefix_byte(instr[index])) { + index++; + } + + + /* CHECK IF MOV_TO_CR CAN TAKE MEMORY OPERANDS... */ + if ((instr[index] == cr_access_byte) && + (instr[index + 1] == mov_to_cr_byte)) { + + addr_t first_operand; + addr_t second_operand; + struct cr0_32 *old_cr0; + struct cr0_32 *new_cr0; + operand_type_t addr_type; + + index += 2; + + old_cr0 = (struct cr0_32*)&(guest_state->cr0); + + addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32); + + + if (addr_type == REG_OPERAND) { + new_cr0 = (struct cr0_32 *)first_operand; + } else if (addr_type == MEM_OPERAND) { + addr_t host_addr; + + if (guest_pa_to_host_va(info, first_operand + guest_state->ds.base, &host_addr) == -1) { + // gpf the guest + return -1; + } + + new_cr0 = (struct cr0_32 *)host_addr; + } else { + // error... don't know what to do + return -1; + } + + + if (info->page_mode == SHADOW_PAGING) { + struct cr0_32 * virt_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); + + if ((new_cr0->pg == 1) && (virt_cr0->pg == 0)){ + info->cpu_mode = PROTECTED_PG; + + // Activate Shadow Paging + } + + *virt_cr0 = *new_cr0; + *old_cr0 = *new_cr0; + } else { + // fill in + } + + info->rip += index; + + } + + } else { + PrintDebug("Unknown Mode write to CR0\n"); + while(1); + } + return 0; +} + + +int handle_cr0_read(struct guest_info * info) { + //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data)); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); + char instr[15]; + + if (info->cpu_mode == REAL) { + int index = 0; + int ret; + + // The real rip address is actually a combination of the rip + CS base + ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.base), 15, instr); + if (ret != 15) { + // I think we should inject a GPF into the guest + PrintDebug("Could not read instruction (ret=%d)\n", ret); + return -1; + } + + while (is_prefix_byte(instr[index])) { + index++; + } + + if ((instr[index] == cr_access_byte) && + (instr[index + 1] == smsw_byte) && + (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) { + + addr_t first_operand; + addr_t second_operand; + struct cr0_real *cr0; + operand_type_t addr_type; + char cr0_val = 0; + + index += 2; + + cr0 = (struct cr0_real*)&(guest_state->cr0); + + + addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16); + + if (addr_type == MEM_OPERAND) { + addr_t host_addr; + + if (guest_pa_to_host_va(info, first_operand + (guest_state->ds.base << 4), &host_addr) == -1) { + // gpf the guest + return -1; + } + + first_operand = host_addr; + } else { + // error... don't know what to do + return -1; + } + + cr0_val = *(char*)cr0 & 0x0f; + + + *(char *)first_operand &= 0xf0; + *(char *)first_operand |= cr0_val; + + info->rip += index; + + } + + } else if (info->cpu_mode == PROTECTED) { + int index = 0; + int ret; + + // The real rip address is actually a combination of the rip + CS base + ret = read_guest_pa_memory(info, get_addr_linear(info, guest_state->rip, guest_state->cs.base), 15, instr); + if (ret != 15) { + // I think we should inject a GPF into the guest + PrintDebug("Could not read instruction (ret=%d)\n", ret); + return -1; + } + + while (is_prefix_byte(instr[index])) { + index++; + } + + + } + + + return 0; +} diff --git a/palacios/src/palacios/svm_handler.c b/palacios/src/palacios/svm_handler.c new file mode 100644 index 0000000..fed7b79 --- /dev/null +++ b/palacios/src/palacios/svm_handler.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include + +extern struct vmm_os_hooks * os_hooks; + + +int handle_svm_exit(struct guest_info * info) { + vmcb_ctrl_t * guest_ctrl = 0; + vmcb_saved_state_t * guest_state = 0; + ulong_t exit_code = 0; + + guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); + guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); + + + // Update the high level state + info->rip = guest_state->rip; + info->vm_regs.rsp = guest_state->rsp; + info->vm_regs.rax = guest_state->rax; + info->vm_regs.rsp = guest_state->rsp; + + + PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); + PrintDebug("RIP: %x\n", guest_state->rip); + + + + exit_code = guest_ctrl->exit_code; + + // PrintDebugVMCB((vmcb_t*)(info->vmm_data)); + PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); + + PrintDebug("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1)); + PrintDebug("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4)); + + PrintDebug("io_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2)); + PrintDebug("io_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4)); + + + if (exit_code == VMEXIT_IOIO) { + struct svm_io_info * io_info = (struct svm_io_info *)&(guest_ctrl->exit_info1); + + if (io_info->type == 0) { + if (io_info->str) { + handle_svm_io_outs(info); + } else { + handle_svm_io_out(info); + } + } else { + if (io_info->str) { + handle_svm_io_ins(info); + } else { + handle_svm_io_in(info); + } + } + } else if (exit_code == VMEXIT_CR0_WRITE) { + PrintDebug("CR0 Write\n"); + + if (handle_cr0_write(info) == -1) { + return -1; + } + + } else if (( (exit_code == VMEXIT_CR3_READ) || + (exit_code == VMEXIT_CR3_WRITE) || + (exit_code == VMEXIT_INVLPG) || + (exit_code == VMEXIT_INVLPGA) || + (exit_code == VMEXIT_EXCP14)) && + (info->page_mode == SHADOW_PAGING)) { + handle_shadow_paging(info); + } + + + // Update the low level state + guest_state->rax = info->vm_regs.rax; + guest_state->rip = info->rip; + guest_state->rsp = info->vm_regs.rsp; + + return 0; +} + + + + +int handle_shadow_paging(struct guest_info * info) { + vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); + // vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); + + if (guest_ctrl->exit_code == VMEXIT_CR3_READ) { + + } + + return 0; +} + + + diff --git a/palacios/src/palacios/svm_io.c b/palacios/src/palacios/svm_io.c new file mode 100644 index 0000000..8249362 --- /dev/null +++ b/palacios/src/palacios/svm_io.c @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include + + +// This should package up an IO request and call vmm_handle_io +int handle_svm_io_in(struct guest_info * info) { + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data)); + // vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); + struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1); + + vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port); + uint_t read_size = 0; + + if (hook == NULL) { + // error, we should not have exited on this port + return -1; + } + + PrintDebug("IN on port %d (0x%x)\n", io_info->port, io_info->port); + + if (io_info->sz8) { + read_size = 1; + } else if (io_info->sz16) { + read_size = 2; + } else if (io_info->sz32) { + read_size = 4; + } + + + if (hook->read(io_info->port, &(info->vm_regs.rax), read_size) != read_size) { + // not sure how we handle errors..... + return -1; + } + + info->rip = ctrl_area->exit_info2; + + return 0; +} + + + + + +/* We might not handle wrap around of the RDI register correctly... + * In that if we do wrap around the effect will manifest in the higher bits of the register + */ +int handle_svm_io_ins(struct guest_info * info) { + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data)); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); + + struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1); + + vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port); + uint_t read_size = 0; + addr_t base_addr = guest_state->es.base ; + addr_t dst_addr = 0; + uint_t rep_num = 1; + ullong_t mask = 0; + + + + // This is kind of hacky... + // direction can equal either 1 or -1 + // We will multiply the final added offset by this value to go the correct direction + int direction = 1; + struct rflags * flags = (struct rflags *)&(guest_state->rflags); + if (flags->df) { + direction = -1; + } + + + if (hook == NULL) { + // error, we should not have exited on this port + return -1; + } + + PrintDebug("INS on port %d (0x%x)\n", io_info->port, io_info->port); + + if (io_info->sz8) { + read_size = 1; + } else if (io_info->sz16) { + read_size = 2; + } else if (io_info->sz32) { + read_size = 4; + } + + + if (io_info->addr16) { + mask = 0xffff; + } else if (io_info->addr32) { + mask = 0xffffffff; + } else if (io_info->addr64) { + mask = 0xffffffffffffffffLL; + } else { + // should never happen + return -1; + } + + if (io_info->rep) { + rep_num = info->vm_regs.rcx & mask; + } + + + + while (rep_num > 0) { + addr_t host_addr; + dst_addr = get_addr_linear(info, info->vm_regs.rdi & mask, base_addr); + + if (guest_va_to_host_va(info, dst_addr, &host_addr) == -1) { + // either page fault or gpf... + } + + if (hook->read(io_info->port, (char*)host_addr, read_size) != read_size) { + // not sure how we handle errors..... + return -1; + } + + info->vm_regs.rdi += read_size * direction; + + if (io_info->rep) + info->vm_regs.rcx--; + + rep_num--; + } + + + info->rip = ctrl_area->exit_info2; + + return 0; +} + +int handle_svm_io_out(struct guest_info * info) { + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data)); + // vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); + struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1); + + vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port); + uint_t write_size = 0; + + if (hook == NULL) { + // error, we should not have exited on this port + return -1; + } + + PrintDebug("OUT on port %d (0x%x)\n", io_info->port, io_info->port); + + if (io_info->sz8) { + write_size = 1; + } else if (io_info->sz16) { + write_size = 2; + } else if (io_info->sz32) { + write_size = 4; + } + + + if (hook->write(io_info->port, &(info->vm_regs.rax), write_size) != write_size) { + // not sure how we handle errors..... + return -1; + } + + info->rip = ctrl_area->exit_info2; + + return 0; +} + + +/* We might not handle wrap around of the RSI register correctly... + * In that if we do wrap around the effect will manifest in the higher bits of the register + */ + +int handle_svm_io_outs(struct guest_info * info) { + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data)); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); + + struct svm_io_info * io_info = (struct svm_io_info *)&(ctrl_area->exit_info1); + + vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port); + uint_t write_size = 0; + addr_t base_addr = guest_state->ds.base; + addr_t dst_addr = 0; + uint_t rep_num = 1; + ullong_t mask = 0; + + + + // This is kind of hacky... + // direction can equal either 1 or -1 + // We will multiply the final added offset by this value to go the correct direction + int direction = 1; + struct rflags * flags = (struct rflags *)&(guest_state->rflags); + if (flags->df) { + direction = -1; + } + + + if (hook == NULL) { + // error, we should not have exited on this port + return -1; + } + + PrintDebug("OUTS on port %d (0x%x)\n", io_info->port, io_info->port); + + if (io_info->sz8) { + write_size = 1; + } else if (io_info->sz16) { + write_size = 2; + } else if (io_info->sz32) { + write_size = 4; + } + + + if (io_info->addr16) { + mask = 0xffff; + } else if (io_info->addr32) { + mask = 0xffffffff; + } else if (io_info->addr64) { + mask = 0xffffffffffffffffLL; + } else { + // should never happen + return -1; + } + + if (io_info->rep) { + rep_num = info->vm_regs.rcx & mask; + } + + + while (rep_num > 0) { + addr_t host_addr; + dst_addr = get_addr_linear(info, (info->vm_regs.rsi & mask), base_addr); + + if (guest_va_to_host_va(info, dst_addr, &host_addr) == -1) { + // either page fault or gpf... + } + + if (hook->write(io_info->port, (char*)host_addr, write_size) != write_size) { + // not sure how we handle errors..... + return -1; + } + + info->vm_regs.rsi += write_size * direction; + + if (io_info->rep) + info->vm_regs.rcx--; + + rep_num--; + } + + + info->rip = ctrl_area->exit_info2; + + + return 0; +} diff --git a/palacios/src/palacios/svm_lowlevel.asm b/palacios/src/palacios/svm_lowlevel.asm new file mode 100644 index 0000000..4731571 --- /dev/null +++ b/palacios/src/palacios/svm_lowlevel.asm @@ -0,0 +1,199 @@ +; -*- fundamental -*- + + +%ifndef SVM_ASM +%define SVM_ASM + +;%include "defs.asm" +%include "vmm_symbol.asm" + +SVM_ERROR equ 0xFFFFFFFF +SVM_SUCCESS equ 0x00000000 + +EXPORT DisableInts + +EXPORT GetGDTR +EXPORT GetIDTR +EXPORT GetTR + +EXPORT exit_test + +EXTERN handle_svm_exit + +EXPORT launch_svm +EXPORT safe_svm_launch + + + + +;; These need to be kept similar with the svm return values in svm.h +SVM_HANDLER_SUCCESS equ 0x00 +SVM_HANDLER_ERROR equ 0x1 +SVM_HANDLER_HALT equ 0x2 + +[BITS 32] + + +; Save and restore registers needed by SVM +%macro Save_SVM_Registers 1 + push eax + mov eax, dword %1 + mov [eax], edi + mov [eax + 8], esi + mov [eax + 16], ebp + mov [eax + 24], dword 0 ;; esp + mov [eax + 32], ebx + mov [eax + 40], edx + mov [eax + 48], ecx + + push ebx + mov ebx, [esp + 4] + mov [eax + 56], ebx ;; eax + pop ebx + + pop eax +%endmacro + + +%macro Restore_SVM_Registers 1 + push eax + mov eax, dword %1 + mov edi, [eax] + mov esi, [eax + 8] + mov ebp, [eax + 16] +;; mov esp, [eax + 24] + mov ebx, [eax + 32] + mov edx, [eax + 40] + mov ecx, [eax + 48] +;; mov eax, [eax + 56] + pop eax +%endmacro + +%macro vmrun 0 + db 00fh, 001h, 0d8h +%endmacro + +%macro vmsave 0 + db 00fh, 001h, 0dbh +%endmacro + +%macro vmload 0 + db 00fh, 001h, 0dah +%endmacro + +;VMRUN equ db 0Fh, 01h, D8h +;VMLOAD equ db 0x0F,0x01,0xDA +;VMSAVE equ db 0x0F,0x01,0xDB +;STGI equ db 0x0F,0x01,0xDC +;CLGI equ db 0x0F,0x01,0xDD + + +align 8 +DisableInts: + cli + ret + + +align 8 +GetGDTR: + push ebp + mov ebp, esp + pusha + mov ebx, [ebp + 8] + sgdt [ebx] + + popa + pop ebp + ret + + +align 8 +GetIDTR: + push ebp + mov ebp, esp + pusha + + mov ebx, [ebp + 8] + sidt [ebx] + + popa + pop ebp + ret + + + +align 8 +GetTR: + push ebp + mov ebp, esp + pusha + mov ebx, [ebp + 8] + str [ebx] + + popa + pop ebp + ret + + + +; I think its safe to say that there are some pretty serious register issues... +align 8 +launch_svm: + push ebp + mov ebp, esp + pusha + + mov eax, [ebp + 8] + vmrun +; db 00fh, 001h, 0d8h + popa + pop ebp + ret + + + + +exit_test: + mov cr4, eax + ret + + +;; Need to check this.. +;; save_svm_launch(rax, struct guest_gprs * regs) +align 8 +safe_svm_launch: + push ebp + mov ebp, esp + pushf + pusha ;; Save Host state + + + push dword [ebp + 12] ;; pointer to the guest GPR save area + push dword [ebp + 8] ;; pointer to the VMCB pointer + +;; mov eax, [esp + 4] ;; mov guest GPR pointer to eax + + ;; this is plus 8 because we push eax in the macro + Restore_SVM_Registers [esp + 8] ;; Restore Guest GPR state + pop eax ;; pop VMCB pointer into eax + + vmload + vmrun + vmsave + +;; pop eax ;; pop Guest GPR pointer into eax + ;; this is plus 4 because we push eax in the macro NEED TO CHANGE + Save_SVM_Registers [esp+4] ;; save guest GPRs + + add esp, 4 ;; skip past the gpr ptr + + popa ;; Restore Host state + popf + pop ebp + ret + + + +%endif + + diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c new file mode 100644 index 0000000..7b727cc --- /dev/null +++ b/palacios/src/palacios/vm_guest.c @@ -0,0 +1 @@ +#include diff --git a/palacios/src/palacios/vm_guest_mem.c b/palacios/src/palacios/vm_guest_mem.c new file mode 100644 index 0000000..33cb5b2 --- /dev/null +++ b/palacios/src/palacios/vm_guest_mem.c @@ -0,0 +1,363 @@ +#include +#include +#include + +extern struct vmm_os_hooks * os_hooks; + + +/**********************************/ +/* GROUP 0 */ +/**********************************/ + +int host_va_to_host_pa(addr_t host_va, addr_t * host_pa) { + if ((os_hooks) && (os_hooks)->vaddr_to_paddr) { + + *host_pa = (addr_t)(os_hooks)->vaddr_to_paddr((void *)host_va); + + if (*host_pa == 0) { + return -1; + } + } else { + return -1; + } + return 0; +} + + +int host_pa_to_host_va(addr_t host_pa, addr_t * host_va) { + if ((os_hooks) && (os_hooks)->paddr_to_vaddr) { + + *host_va = (addr_t)(os_hooks)->paddr_to_vaddr((void *)host_pa); + + if (*host_va == 0) { + return -1; + } + } else { + return -1; + } + return 0; +} + + + +int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_pa) { + // we use the shadow map here... + if (lookup_shadow_map_addr(&(guest_info->mem_map), guest_pa, host_pa) != HOST_REGION_PHYSICAL_MEMORY) { + return -1; + } + + return 0; +} + + +/* !! Currently not implemented !! */ +// This is a scan of the shadow map +// For now we ignore it +// +int host_pa_to_guest_pa(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_pa) { + *guest_pa = 0; + + return -1; +} + + + +/**********************************/ +/* GROUP 1 */ +/**********************************/ + + +/* !! Currently not implemented !! */ +// This will return negative until we implement host_pa_to_guest_pa() +int host_va_to_guest_pa(struct guest_info * guest_info, addr_t host_va, addr_t * guest_pa) { + addr_t host_pa; + *guest_pa = 0; + + if (host_va_to_host_pa(host_va, &host_pa) != 0) { + return -1; + } + + if (host_pa_to_guest_pa(guest_info, host_pa, guest_pa) != 0) { + return -1; + } + + return 0; +} + + + + +int guest_pa_to_host_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_va) { + addr_t host_pa; + + *host_va = 0; + + if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) { + return -1; + } + + if (host_pa_to_host_va(host_pa, host_va) != 0) { + return -1; + } + + return 0; +} + + +int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * guest_pa) { + if (guest_info->page_mode == SHADOW_PAGING) { + switch (guest_info->cpu_mode) { + case REAL: + case PROTECTED: + case LONG: + case PROTECTED_PAE: + // guest virtual address is the same as the physical + *guest_pa = guest_va; + return 0; + case PROTECTED_PG: + { + addr_t tmp_pa; + pde32_t * pde; + addr_t guest_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.guest_cr3.r_reg); + + if (guest_pa_to_host_va(guest_info, guest_pde, (addr_t *)&pde) == -1) { + return -1; + } + + switch (pde32_lookup(pde, guest_va, &tmp_pa)) { + case NOT_PRESENT: + *guest_pa = 0; + return -1; + case LARGE_PAGE: + *guest_pa = tmp_pa; + return 0; + case PTE32: + { + pte32_t * pte; + + if (guest_pa_to_host_va(guest_info, tmp_pa, (addr_t*)&pte) == -1) { + return -1; + } + + if (pte32_lookup(pte, guest_va, guest_pa) != 0) { + return -1; + } + + return 0; + } + default: + return -1; + } + } + case PROTECTED_PAE_PG: + { + // Fill in + } + case LONG_PG: + { + // Fill in + } + default: + return -1; + } + } else if (guest_info->page_mode == NESTED_PAGING) { + + // Fill in + + } else { + return -1; + } + + + return 0; +} + + + +/* !! Currently not implemented !! */ +/* This will be a real pain.... its your standard page table walker in guest memory + * + * For now we ignore it... + */ +int guest_pa_to_guest_va(struct guest_info * guest_info, addr_t guest_pa, addr_t * guest_va) { + *guest_va = 0; + return -1; +} + + +/**********************************/ +/* GROUP 2 */ +/**********************************/ + + +int guest_va_to_host_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * host_pa) { + addr_t guest_pa; + + *host_pa = 0; + + if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) { + return -1; + } + + if (guest_pa_to_host_pa(guest_info, guest_pa, host_pa) != 0) { + return -1; + } + + return 0; +} + +/* !! Currently not implemented !! */ +int host_pa_to_guest_va(struct guest_info * guest_info, addr_t host_pa, addr_t * guest_va) { + addr_t guest_pa; + + *guest_va = 0; + + if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) { + return -1; + } + + if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) { + return -1; + } + + return 0; +} + + + + +int guest_va_to_host_va(struct guest_info * guest_info, addr_t guest_va, addr_t * host_va) { + addr_t guest_pa; + addr_t host_pa; + + *host_va = 0; + + if (guest_va_to_guest_pa(guest_info, guest_va, &guest_pa) != 0) { + return -1; + } + + if (guest_pa_to_host_pa(guest_info, guest_pa, &host_pa) != 0) { + return -1; + } + + if (host_pa_to_host_va(host_pa, host_va) != 0) { + return -1; + } + + return 0; +} + + +/* !! Currently not implemented !! */ +int host_va_to_guest_va(struct guest_info * guest_info, addr_t host_va, addr_t * guest_va) { + addr_t host_pa; + addr_t guest_pa; + + *guest_va = 0; + + if (host_va_to_host_pa(host_va, &host_pa) != 0) { + return -1; + } + + if (host_pa_to_guest_pa(guest_info, host_pa, &guest_pa) != 0) { + return -1; + } + + if (guest_pa_to_guest_va(guest_info, guest_pa, guest_va) != 0) { + return -1; + } + + return 0; +} + + + + + + +/* This is a straight address conversion + copy, + * except for the tiny little issue of crossing page boundries..... + */ +int read_guest_va_memory(struct guest_info * guest_info, addr_t guest_va, int count, char * dest) { + addr_t cursor = guest_va; + int bytes_read = 0; + + while (count > 0) { + int dist_to_pg_edge = (PAGE_OFFSET(cursor) + PAGE_SIZE) - cursor; + int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge; + addr_t host_addr; + + if (guest_va_to_host_va(guest_info, cursor, &host_addr) != 0) { + return bytes_read; + } + + memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy); + + bytes_read += bytes_to_copy; + count -= bytes_to_copy; + cursor += bytes_to_copy; + } + + return bytes_read; +} + + + + + + +/* This is a straight address conversion + copy, + * except for the tiny little issue of crossing page boundries..... + */ +int read_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, char * dest) { + addr_t cursor = guest_pa; + int bytes_read = 0; + + while (count > 0) { + int dist_to_pg_edge = (PAGE_OFFSET(cursor) + PAGE_SIZE) - cursor; + int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge; + addr_t host_addr; + + if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) { + return bytes_read; + } + + memcpy(dest + bytes_read, (void*)host_addr, bytes_to_copy); + + bytes_read += bytes_to_copy; + count -= bytes_to_copy; + cursor += bytes_to_copy; + } + + return bytes_read; +} + + + + +/* This is a straight address conversion + copy, + * except for the tiny little issue of crossing page boundries..... + */ +int write_guest_pa_memory(struct guest_info * guest_info, addr_t guest_pa, int count, char * src) { + addr_t cursor = guest_pa; + int bytes_written = 0; + + while (count > 0) { + int dist_to_pg_edge = (PAGE_OFFSET(cursor) + PAGE_SIZE) - cursor; + int bytes_to_copy = (dist_to_pg_edge > count) ? count : dist_to_pg_edge; + addr_t host_addr; + + if (guest_pa_to_host_va(guest_info, cursor, &host_addr) != 0) { + return bytes_written; + } + + memcpy((void*)host_addr, src + bytes_written, bytes_to_copy); + + bytes_written += bytes_to_copy; + count -= bytes_to_copy; + cursor += bytes_to_copy; + } + + return bytes_written; +} + diff --git a/palacios/src/palacios/vmcb.c b/palacios/src/palacios/vmcb.c new file mode 100644 index 0000000..3933fc1 --- /dev/null +++ b/palacios/src/palacios/vmcb.c @@ -0,0 +1,325 @@ +#include +#include +#include + + +void PrintDebugVMCB(vmcb_t * vmcb) { + reg_ex_t tmp_reg; + + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); + vmcb_saved_state_t * guest_area = GET_VMCB_SAVE_STATE_AREA(vmcb); + + PrintDebug("VMCB (0x%.8x)\n", vmcb); + + PrintDebug("--Control Area--\n"); + PrintDebug("CR Reads: %x\n", ctrl_area->cr_reads.bitmap); + PrintDebug("CR Writes: %x\n", ctrl_area->cr_writes.bitmap); + PrintDebug("DR Reads: %x\n", ctrl_area->dr_reads.bitmap); + PrintDebug("DR Writes: %x\n", ctrl_area->dr_writes.bitmap); + + PrintDebug("Exception Bitmap: %x (at 0x%.8x)\n", ctrl_area->exceptions.bitmap, &(ctrl_area->exceptions)); + PrintDebug("\tDivide-by-Zero: %d\n", ctrl_area->exceptions.ex_names.de); + PrintDebug("\tDebug: %d\n", ctrl_area->exceptions.ex_names.db); + PrintDebug("\tNon-maskable interrupts: %d\n", ctrl_area->exceptions.ex_names.nmi); + PrintDebug("\tBreakpoint: %d\n", ctrl_area->exceptions.ex_names.bp); + PrintDebug("\tOverflow: %d\n", ctrl_area->exceptions.ex_names.of); + PrintDebug("\tBound-Range: %d\n", ctrl_area->exceptions.ex_names.br); + PrintDebug("\tInvalid Opcode: %d\n", ctrl_area->exceptions.ex_names.ud); + PrintDebug("\tDevice not available: %d\n", ctrl_area->exceptions.ex_names.nm); + PrintDebug("\tDouble Fault: %d\n", ctrl_area->exceptions.ex_names.df); + PrintDebug("\tInvalid TSS: %d\n", ctrl_area->exceptions.ex_names.ts); + PrintDebug("\tSegment not present: %d\n", ctrl_area->exceptions.ex_names.np); + PrintDebug("\tStack: %d\n", ctrl_area->exceptions.ex_names.ss); + PrintDebug("\tGPF: %d\n", ctrl_area->exceptions.ex_names.gp); + PrintDebug("\tPage Fault: %d\n", ctrl_area->exceptions.ex_names.pf); + PrintDebug("\tFloating Point: %d\n", ctrl_area->exceptions.ex_names.mf); + PrintDebug("\tAlignment Check: %d\n", ctrl_area->exceptions.ex_names.ac); + PrintDebug("\tMachine Check: %d\n", ctrl_area->exceptions.ex_names.mc); + PrintDebug("\tSIMD floating point: %d\n", ctrl_area->exceptions.ex_names.xf); + PrintDebug("\tSecurity: %d\n", ctrl_area->exceptions.ex_names.sx); + + PrintDebug("Instructions bitmap: %.8x (at 0x%.8x)\n", ctrl_area->instrs.bitmap, &(ctrl_area->instrs)); + PrintDebug("\tINTR: %d\n", ctrl_area->instrs.instrs.INTR); + PrintDebug("\tNMI: %d\n", ctrl_area->instrs.instrs.NMI); + PrintDebug("\tSMI: %d\n", ctrl_area->instrs.instrs.SMI); + PrintDebug("\tINIT: %d\n", ctrl_area->instrs.instrs.INIT); + PrintDebug("\tVINTR: %d\n", ctrl_area->instrs.instrs.VINTR); + PrintDebug("\tCR0: %d\n", ctrl_area->instrs.instrs.CR0); + PrintDebug("\tRD_IDTR: %d\n", ctrl_area->instrs.instrs.RD_IDTR); + PrintDebug("\tRD_GDTR: %d\n", ctrl_area->instrs.instrs.RD_GDTR); + PrintDebug("\tRD_LDTR: %d\n", ctrl_area->instrs.instrs.RD_LDTR); + PrintDebug("\tRD_TR: %d\n", ctrl_area->instrs.instrs.RD_TR); + PrintDebug("\tWR_IDTR: %d\n", ctrl_area->instrs.instrs.WR_IDTR); + PrintDebug("\tWR_GDTR: %d\n", ctrl_area->instrs.instrs.WR_GDTR); + PrintDebug("\tWR_LDTR: %d\n", ctrl_area->instrs.instrs.WR_LDTR); + PrintDebug("\tWR_TR: %d\n", ctrl_area->instrs.instrs.WR_TR); + PrintDebug("\tRDTSC: %d\n", ctrl_area->instrs.instrs.RDTSC); + PrintDebug("\tRDPMC: %d\n", ctrl_area->instrs.instrs.RDPMC); + PrintDebug("\tPUSHF: %d\n", ctrl_area->instrs.instrs.PUSHF); + PrintDebug("\tPOPF: %d\n", ctrl_area->instrs.instrs.POPF); + PrintDebug("\tCPUID: %d\n", ctrl_area->instrs.instrs.CPUID); + PrintDebug("\tRSM: %d\n", ctrl_area->instrs.instrs.RSM); + PrintDebug("\tIRET: %d\n", ctrl_area->instrs.instrs.IRET); + PrintDebug("\tINTn: %d\n", ctrl_area->instrs.instrs.INTn); + PrintDebug("\tINVD: %d\n", ctrl_area->instrs.instrs.INVD); + PrintDebug("\tPAUSE: %d\n", ctrl_area->instrs.instrs.PAUSE); + PrintDebug("\tHLT: %d\n", ctrl_area->instrs.instrs.HLT); + PrintDebug("\tINVLPG: %d\n", ctrl_area->instrs.instrs.INVLPG); + PrintDebug("\tINVLPGA: %d\n", ctrl_area->instrs.instrs.INVLPGA); + PrintDebug("\tIOIO_PROT: %d\n", ctrl_area->instrs.instrs.IOIO_PROT); + PrintDebug("\tMSR_PROT: %d\n", ctrl_area->instrs.instrs.MSR_PROT); + PrintDebug("\ttask_switch: %d\n", ctrl_area->instrs.instrs.task_switch); + PrintDebug("\tFERR_FREEZE: %d\n", ctrl_area->instrs.instrs.FERR_FREEZE); + PrintDebug("\tshutdown_evts: %d\n", ctrl_area->instrs.instrs.shutdown_evts); + + PrintDebug("SVM Instruction Bitmap: %.8x (at 0x%.8x)\n", ctrl_area->svm_instrs.bitmap, &(ctrl_area->svm_instrs)); + PrintDebug("\tVMRUN: %d\n", ctrl_area->svm_instrs.instrs.VMRUN); + PrintDebug("\tVMMCALL: %d\n", ctrl_area->svm_instrs.instrs.VMMCALL); + PrintDebug("\tVMLOAD: %d\n", ctrl_area->svm_instrs.instrs.VMLOAD); + PrintDebug("\tVMSAVE: %d\n", ctrl_area->svm_instrs.instrs.VMSAVE); + PrintDebug("\tSTGI: %d\n", ctrl_area->svm_instrs.instrs.STGI); + PrintDebug("\tCLGI: %d\n", ctrl_area->svm_instrs.instrs.CLGI); + PrintDebug("\tSKINIT: %d\n", ctrl_area->svm_instrs.instrs.SKINIT); + PrintDebug("\tRDTSCP: %d\n", ctrl_area->svm_instrs.instrs.RDTSCP); + PrintDebug("\tICEBP: %d\n", ctrl_area->svm_instrs.instrs.ICEBP); + PrintDebug("\tWBINVD: %d\n", ctrl_area->svm_instrs.instrs.WBINVD); + PrintDebug("\tMONITOR: %d\n", ctrl_area->svm_instrs.instrs.MONITOR); + PrintDebug("\tMWAIT_always: %d\n", ctrl_area->svm_instrs.instrs.MWAIT_always); + PrintDebug("\tMWAIT_if_armed: %d\n", ctrl_area->svm_instrs.instrs.MWAIT_if_armed); + + + + tmp_reg.r_reg = ctrl_area->IOPM_BASE_PA; + PrintDebug("IOPM_BASE_PA: lo: 0x%.8x, hi: 0x%.8x\n", tmp_reg.e_reg.low, tmp_reg.e_reg.high); + tmp_reg.r_reg = ctrl_area->MSRPM_BASE_PA; + PrintDebug("MSRPM_BASE_PA: lo: 0x%.8x, hi: 0x%.8x\n", tmp_reg.e_reg.low, tmp_reg.e_reg.high); + tmp_reg.r_reg = ctrl_area->TSC_OFFSET; + PrintDebug("TSC_OFFSET: lo: 0x%.8x, hi: 0x%.8x\n", tmp_reg.e_reg.low, tmp_reg.e_reg.high); + + PrintDebug("guest_ASID: %d\n", ctrl_area->guest_ASID); + PrintDebug("TLB_CONTROL: %d\n", ctrl_area->TLB_CONTROL); + + + PrintDebug("Guest Control Bitmap: %x (at 0x%.8x)\n", ctrl_area->guest_ctrl.bitmap, &(ctrl_area->guest_ctrl)); + PrintDebug("\tV_TPR: %d\n", ctrl_area->guest_ctrl.ctrls.V_TPR); + PrintDebug("\tV_IRQ: %d\n", ctrl_area->guest_ctrl.ctrls.V_IRQ); + PrintDebug("\tV_INTR_PRIO: %d\n", ctrl_area->guest_ctrl.ctrls.V_INTR_PRIO); + PrintDebug("\tV_IGN_TPR: %d\n", ctrl_area->guest_ctrl.ctrls.V_IGN_TPR); + PrintDebug("\tV_INTR_MASKING: %d\n", ctrl_area->guest_ctrl.ctrls.V_INTR_MASKING); + PrintDebug("\tV_INTR_VECTOR: %d\n", ctrl_area->guest_ctrl.ctrls.V_INTR_VECTOR); + + PrintDebug("Interrupt_shadow: %d\n", ctrl_area->interrupt_shadow); + + + tmp_reg.r_reg = ctrl_area->exit_code; + PrintDebug("exit_code: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = ctrl_area->exit_info1; + PrintDebug("exit_info1: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = ctrl_area->exit_info2; + PrintDebug("exit_info2: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + tmp_reg.r_reg = ctrl_area->exit_int_info; + PrintDebug("exit_int_info: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + tmp_reg.r_reg = ctrl_area->NP_ENABLE; + PrintDebug("NP_ENABLE: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + tmp_reg.r_reg = ctrl_area->EVENTINJ; + PrintDebug("EVENTINJ: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + tmp_reg.r_reg = ctrl_area->N_CR3; + PrintDebug("N_CR3: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + PrintDebug("LBR_VIRTUALIZATION_ENABLE: %d\n", ctrl_area->LBR_VIRTUALIZATION_ENABLE); + + + PrintDebug("\n--Guest Saved State--\n"); + + PrintDebug("es Selector (at 0x%.8x): \n", &(guest_area->es)); + PrintDebug("\tSelector: %d\n", guest_area->es.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->es.attrib.fields.type, guest_area->es.attrib.fields.S, + guest_area->es.attrib.fields.dpl, guest_area->es.attrib.fields.P, + guest_area->es.attrib.fields.avl, guest_area->es.attrib.fields.L, + guest_area->es.attrib.fields.db, guest_area->es.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->es.limit); + tmp_reg.r_reg = guest_area->es.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("cs Selector (at 0x%.8x): \n", &(guest_area->cs)); + PrintDebug("\tSelector: %d\n", guest_area->cs.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->cs.attrib.fields.type, guest_area->cs.attrib.fields.S, + guest_area->cs.attrib.fields.dpl, guest_area->cs.attrib.fields.P, + guest_area->cs.attrib.fields.avl, guest_area->cs.attrib.fields.L, + guest_area->cs.attrib.fields.db, guest_area->cs.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->cs.limit); + tmp_reg.r_reg = guest_area->cs.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("ss Selector (at 0x%.8x): \n", &(guest_area->ss)); + PrintDebug("\tSelector: %d\n", guest_area->ss.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->ss.attrib.fields.type, guest_area->ss.attrib.fields.S, + guest_area->ss.attrib.fields.dpl, guest_area->ss.attrib.fields.P, + guest_area->ss.attrib.fields.avl, guest_area->ss.attrib.fields.L, + guest_area->ss.attrib.fields.db, guest_area->ss.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->ss.limit); + tmp_reg.r_reg = guest_area->ss.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("ds Selector (at 0x%.8x): \n", &(guest_area->ds)); + PrintDebug("\tSelector: %d\n", guest_area->ds.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->ds.attrib.fields.type, guest_area->ds.attrib.fields.S, + guest_area->ds.attrib.fields.dpl, guest_area->ds.attrib.fields.P, + guest_area->ds.attrib.fields.avl, guest_area->ds.attrib.fields.L, + guest_area->ds.attrib.fields.db, guest_area->ds.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->ds.limit); + tmp_reg.r_reg = guest_area->ds.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("fs Selector (at 0x%.8x): \n", &(guest_area->fs)); + PrintDebug("\tSelector: %d\n", guest_area->fs.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->fs.attrib.fields.type, guest_area->fs.attrib.fields.S, + guest_area->fs.attrib.fields.dpl, guest_area->fs.attrib.fields.P, + guest_area->fs.attrib.fields.avl, guest_area->fs.attrib.fields.L, + guest_area->fs.attrib.fields.db, guest_area->fs.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->fs.limit); + tmp_reg.r_reg = guest_area->fs.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("gs Selector (at 0x%.8x): \n", &(guest_area->gs)); + PrintDebug("\tSelector: %d\n", guest_area->gs.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->gs.attrib.fields.type, guest_area->gs.attrib.fields.S, + guest_area->gs.attrib.fields.dpl, guest_area->gs.attrib.fields.P, + guest_area->gs.attrib.fields.avl, guest_area->gs.attrib.fields.L, + guest_area->gs.attrib.fields.db, guest_area->gs.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->gs.limit); + tmp_reg.r_reg = guest_area->gs.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("gdtr Selector (at 0x%.8x): \n", &(guest_area->gdtr)); + PrintDebug("\tSelector: %d\n", guest_area->gdtr.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->gdtr.attrib.fields.type, guest_area->gdtr.attrib.fields.S, + guest_area->gdtr.attrib.fields.dpl, guest_area->gdtr.attrib.fields.P, + guest_area->gdtr.attrib.fields.avl, guest_area->gdtr.attrib.fields.L, + guest_area->gdtr.attrib.fields.db, guest_area->gdtr.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->gdtr.limit); + tmp_reg.r_reg = guest_area->gdtr.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("ldtr Selector (at 0x%.8x): \n", &(guest_area->ldtr)); + PrintDebug("\tSelector: %d\n", guest_area->ldtr.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->ldtr.attrib.fields.type, guest_area->ldtr.attrib.fields.S, + guest_area->ldtr.attrib.fields.dpl, guest_area->ldtr.attrib.fields.P, + guest_area->ldtr.attrib.fields.avl, guest_area->ldtr.attrib.fields.L, + guest_area->ldtr.attrib.fields.db, guest_area->ldtr.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->ldtr.limit); + tmp_reg.r_reg = guest_area->ldtr.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("idtr Selector (at 0x%.8x): \n", &(guest_area->idtr)); + PrintDebug("\tSelector: %d\n", guest_area->idtr.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->idtr.attrib.fields.type, guest_area->idtr.attrib.fields.S, + guest_area->idtr.attrib.fields.dpl, guest_area->idtr.attrib.fields.P, + guest_area->idtr.attrib.fields.avl, guest_area->idtr.attrib.fields.L, + guest_area->idtr.attrib.fields.db, guest_area->idtr.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->idtr.limit); + tmp_reg.r_reg = guest_area->idtr.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("tr Selector (at 0x%.8x): \n", &(guest_area->tr)); + PrintDebug("\tSelector: %d\n", guest_area->tr.selector); + PrintDebug("\t(type=%x), (S=%d), (dpl=%d), (P=%d), (avl=%d), (L=%d), (db=%d), (G=%d)\n", + guest_area->tr.attrib.fields.type, guest_area->tr.attrib.fields.S, + guest_area->tr.attrib.fields.dpl, guest_area->tr.attrib.fields.P, + guest_area->tr.attrib.fields.avl, guest_area->tr.attrib.fields.L, + guest_area->tr.attrib.fields.db, guest_area->tr.attrib.fields.G); + PrintDebug("\tlimit: %lu\n", guest_area->tr.limit); + tmp_reg.r_reg = guest_area->tr.base; + PrintDebug("\tBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + PrintDebug("cpl: %d\n", guest_area->cpl); + + + tmp_reg.r_reg = guest_area->efer; + PrintDebug("EFER: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + tmp_reg.r_reg = guest_area->cr4; + PrintDebug("CR4: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->cr3; + PrintDebug("CR3: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->cr0; + PrintDebug("CR0: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->dr7; + PrintDebug("DR7: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->dr6; + PrintDebug("DR6: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->rflags; + PrintDebug("RFLAGS: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->rip; + PrintDebug("RIP: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + tmp_reg.r_reg = guest_area->rsp; + PrintDebug("RSP: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + tmp_reg.r_reg = guest_area->rax; + PrintDebug("RAX: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->star; + PrintDebug("STAR: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->lstar; + PrintDebug("LSTAR: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->cstar; + PrintDebug("CSTAR: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->sfmask; + PrintDebug("SFMASK: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->KernelGsBase; + PrintDebug("KernelGsBase: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->sysenter_cs; + PrintDebug("sysenter_cs: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->sysenter_esp; + PrintDebug("sysenter_esp: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->sysenter_eip; + PrintDebug("sysenter_eip: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->cr2; + PrintDebug("CR2: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + tmp_reg.r_reg = guest_area->g_pat; + PrintDebug("g_pat: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->dbgctl; + PrintDebug("dbgctl: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->br_from; + PrintDebug("br_from: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->br_to; + PrintDebug("br_to: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->lastexcpfrom; + PrintDebug("lastexcpfrom: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + tmp_reg.r_reg = guest_area->lastexcpto; + PrintDebug("lastexcpto: hi: 0x%.8x, lo: 0x%.8x\n", tmp_reg.e_reg.high, tmp_reg.e_reg.low); + + + + + + +} diff --git a/palacios/src/palacios/vmcs.c b/palacios/src/palacios/vmcs.c new file mode 100644 index 0000000..99850a8 --- /dev/null +++ b/palacios/src/palacios/vmcs.c @@ -0,0 +1,521 @@ +#include + + + + + + +//extern char * exception_names; +// +// Ignores "HIGH" addresses - 32 bit only for now +// + + +#define CHK_VMCS_READ(tag, val) {if (VMCS_READ(tag, val) != 0) return -1;} +#define CHK_VMCS_WRITE(tag, val) {if (VMCS_WRITE(tag, val) != 0) return -1;} + + + +int CopyOutVMCSGuestStateArea(struct VMCSGuestStateArea *p) { + CHK_VMCS_READ(GUEST_CR0, &(p->cr0)); + CHK_VMCS_READ(GUEST_CR3, &(p->cr3)); + CHK_VMCS_READ(GUEST_CR4, &(p->cr4)); + CHK_VMCS_READ(GUEST_DR7, &(p->dr7)); + CHK_VMCS_READ(GUEST_RSP, &(p->rsp)); + CHK_VMCS_READ(GUEST_RIP, &(p->rip)); + CHK_VMCS_READ(GUEST_RFLAGS, &(p->rflags)); + CHK_VMCS_READ(VMCS_GUEST_CS_SELECTOR, &(p->cs.selector)); + CHK_VMCS_READ(VMCS_GUEST_SS_SELECTOR, &(p->ss.selector)); + CHK_VMCS_READ(VMCS_GUEST_DS_SELECTOR, &(p->ds.selector)); + CHK_VMCS_READ(VMCS_GUEST_ES_SELECTOR, &(p->es.selector)); + CHK_VMCS_READ(VMCS_GUEST_FS_SELECTOR, &(p->fs.selector)); + CHK_VMCS_READ(VMCS_GUEST_GS_SELECTOR, &(p->gs.selector)); + CHK_VMCS_READ(VMCS_GUEST_LDTR_SELECTOR, &(p->ldtr.selector)); + CHK_VMCS_READ(VMCS_GUEST_TR_SELECTOR, &(p->tr.selector)); + CHK_VMCS_READ(GUEST_CS_BASE, &(p->cs.baseAddr)); + CHK_VMCS_READ(GUEST_SS_BASE, &(p->ss.baseAddr)); + CHK_VMCS_READ(GUEST_DS_BASE, &(p->ds.baseAddr)); + CHK_VMCS_READ(GUEST_ES_BASE, &(p->es.baseAddr)); + CHK_VMCS_READ(GUEST_FS_BASE, &(p->fs.baseAddr)); + CHK_VMCS_READ(GUEST_GS_BASE, &(p->gs.baseAddr)); + CHK_VMCS_READ(GUEST_LDTR_BASE, &(p->ldtr.baseAddr)); + CHK_VMCS_READ(GUEST_TR_BASE, &(p->tr.baseAddr)); + CHK_VMCS_READ(GUEST_CS_LIMIT, &(p->cs.limit)); + CHK_VMCS_READ(GUEST_SS_LIMIT, &(p->ss.limit)); + CHK_VMCS_READ(GUEST_DS_LIMIT, &(p->ds.limit)); + CHK_VMCS_READ(GUEST_ES_LIMIT, &(p->es.limit)); + CHK_VMCS_READ(GUEST_FS_LIMIT, &(p->fs.limit)); + CHK_VMCS_READ(GUEST_GS_LIMIT, &(p->gs.limit)); + CHK_VMCS_READ(GUEST_LDTR_LIMIT, &(p->ldtr.limit)); + CHK_VMCS_READ(GUEST_TR_LIMIT, &(p->tr.limit)); + CHK_VMCS_READ(GUEST_CS_ACCESS, &(p->cs.access)); + CHK_VMCS_READ(GUEST_SS_ACCESS, &(p->ss.access)); + CHK_VMCS_READ(GUEST_DS_ACCESS, &(p->ds.access)); + CHK_VMCS_READ(GUEST_ES_ACCESS, &(p->es.access)); + CHK_VMCS_READ(GUEST_FS_ACCESS, &(p->fs.access)); + CHK_VMCS_READ(GUEST_GS_ACCESS, &(p->gs.access)); + CHK_VMCS_READ(GUEST_LDTR_ACCESS, &(p->ldtr.access)); + CHK_VMCS_READ(GUEST_TR_ACCESS, &(p->tr.access)); + CHK_VMCS_READ(GUEST_GDTR_BASE, &(p->gdtr.baseAddr)); + CHK_VMCS_READ(GUEST_IDTR_BASE, &(p->idtr.baseAddr)); + CHK_VMCS_READ(GUEST_GDTR_LIMIT, &(p->gdtr.limit)); + CHK_VMCS_READ(GUEST_IDTR_LIMIT, &(p->idtr.limit)); + CHK_VMCS_READ(GUEST_IA32_DEBUGCTL, &(p->dbg_ctrl)); + CHK_VMCS_READ(GUEST_IA32_DEBUGCTL_HIGH, ((char *)&(p->dbg_ctrl)) + 4); + CHK_VMCS_READ(GUEST_IA32_SYSENTER_CS, &(p->sysenter_cs)); + CHK_VMCS_READ(GUEST_IA32_SYSENTER_ESP, &(p->sysenter_esp)); + CHK_VMCS_READ(GUEST_IA32_SYSENTER_EIP, &(p->sysenter_eip)); + CHK_VMCS_READ(GUEST_SMBASE, &(p->smbase)); + + CHK_VMCS_READ(GUEST_ACTIVITY_STATE, &(p->activity)); + CHK_VMCS_READ(GUEST_INT_STATE, &(p->interrupt_state)); + CHK_VMCS_READ(GUEST_PENDING_DEBUG_EXCS, &(p->pending_dbg_exceptions)); + CHK_VMCS_READ(VMCS_LINK_PTR, &(p->vmcs_link)); + CHK_VMCS_READ(VMCS_LINK_PTR_HIGH, ((char *)&(p->vmcs_link)) + 4); + return 0; +} + + +int CopyInVMCSGuestStateArea(struct VMCSGuestStateArea *p) { + CHK_VMCS_WRITE(GUEST_CR0, &(p->cr0)); + CHK_VMCS_WRITE(GUEST_CR3, &(p->cr3)); + CHK_VMCS_WRITE(GUEST_CR4, &(p->cr4)); + CHK_VMCS_WRITE(GUEST_DR7, &(p->dr7)); + CHK_VMCS_WRITE(GUEST_RSP, &(p->rsp)); + CHK_VMCS_WRITE(GUEST_RIP, &(p->rip)); + CHK_VMCS_WRITE(GUEST_RFLAGS, &(p->rflags)); + CHK_VMCS_WRITE(VMCS_GUEST_CS_SELECTOR, &(p->cs.selector)); + CHK_VMCS_WRITE(VMCS_GUEST_SS_SELECTOR, &(p->ss.selector)); + CHK_VMCS_WRITE(VMCS_GUEST_DS_SELECTOR, &(p->ds.selector)); + CHK_VMCS_WRITE(VMCS_GUEST_ES_SELECTOR, &(p->es.selector)); + CHK_VMCS_WRITE(VMCS_GUEST_FS_SELECTOR, &(p->fs.selector)); + CHK_VMCS_WRITE(VMCS_GUEST_GS_SELECTOR, &(p->gs.selector)); + CHK_VMCS_WRITE(VMCS_GUEST_LDTR_SELECTOR, &(p->ldtr.selector)); + CHK_VMCS_WRITE(VMCS_GUEST_TR_SELECTOR, &(p->tr.selector)); + CHK_VMCS_WRITE(GUEST_CS_BASE, &(p->cs.baseAddr)); + CHK_VMCS_WRITE(GUEST_SS_BASE, &(p->ss.baseAddr)); + CHK_VMCS_WRITE(GUEST_DS_BASE, &(p->ds.baseAddr)); + CHK_VMCS_WRITE(GUEST_ES_BASE, &(p->es.baseAddr)); + CHK_VMCS_WRITE(GUEST_FS_BASE, &(p->fs.baseAddr)); + CHK_VMCS_WRITE(GUEST_GS_BASE, &(p->gs.baseAddr)); + CHK_VMCS_WRITE(GUEST_LDTR_BASE, &(p->ldtr.baseAddr)); + CHK_VMCS_WRITE(GUEST_TR_BASE, &(p->tr.baseAddr)); + CHK_VMCS_WRITE(GUEST_CS_LIMIT, &(p->cs.limit)); + CHK_VMCS_WRITE(GUEST_SS_LIMIT, &(p->ss.limit)); + CHK_VMCS_WRITE(GUEST_DS_LIMIT, &(p->ds.limit)); + CHK_VMCS_WRITE(GUEST_ES_LIMIT, &(p->es.limit)); + CHK_VMCS_WRITE(GUEST_FS_LIMIT, &(p->fs.limit)); + CHK_VMCS_WRITE(GUEST_GS_LIMIT, &(p->gs.limit)); + CHK_VMCS_WRITE(GUEST_LDTR_LIMIT, &(p->ldtr.limit)); + CHK_VMCS_WRITE(GUEST_TR_LIMIT, &(p->tr.limit)); + CHK_VMCS_WRITE(GUEST_CS_ACCESS, &(p->cs.access)); + CHK_VMCS_WRITE(GUEST_SS_ACCESS, &(p->ss.access)); + CHK_VMCS_WRITE(GUEST_DS_ACCESS, &(p->ds.access)); + CHK_VMCS_WRITE(GUEST_ES_ACCESS, &(p->es.access)); + CHK_VMCS_WRITE(GUEST_FS_ACCESS, &(p->fs.access)); + CHK_VMCS_WRITE(GUEST_GS_ACCESS, &(p->gs.access)); + CHK_VMCS_WRITE(GUEST_LDTR_ACCESS, &(p->ldtr.access)); + CHK_VMCS_WRITE(GUEST_TR_ACCESS, &(p->tr.access)); + CHK_VMCS_WRITE(GUEST_GDTR_BASE, &(p->gdtr.baseAddr)); + CHK_VMCS_WRITE(GUEST_IDTR_BASE, &(p->idtr.baseAddr)); + CHK_VMCS_WRITE(GUEST_GDTR_LIMIT, &(p->gdtr.limit)); + CHK_VMCS_WRITE(GUEST_IDTR_LIMIT, &(p->idtr.limit)); + CHK_VMCS_WRITE(GUEST_IA32_DEBUGCTL, &(p->dbg_ctrl)); + CHK_VMCS_WRITE(GUEST_IA32_DEBUGCTL_HIGH, ((char *)&(p->dbg_ctrl)) + 4); + CHK_VMCS_WRITE(GUEST_IA32_SYSENTER_CS, &(p->sysenter_cs)); + CHK_VMCS_WRITE(GUEST_IA32_SYSENTER_ESP, &(p->sysenter_esp)); + CHK_VMCS_WRITE(GUEST_IA32_SYSENTER_EIP, &(p->sysenter_eip)); + CHK_VMCS_WRITE(GUEST_SMBASE, &(p->smbase)); + + CHK_VMCS_WRITE(GUEST_ACTIVITY_STATE, &(p->activity)); + CHK_VMCS_WRITE(GUEST_INT_STATE, &(p->interrupt_state)); + CHK_VMCS_WRITE(GUEST_PENDING_DEBUG_EXCS, &(p->pending_dbg_exceptions)); + CHK_VMCS_WRITE(VMCS_LINK_PTR, &(p->vmcs_link)); + CHK_VMCS_WRITE(VMCS_LINK_PTR_HIGH, ((char *)&(p->vmcs_link)) + 4); + return 0; +} + + + +int CopyOutVMCSHostStateArea(struct VMCSHostStateArea *p) { + CHK_VMCS_READ(HOST_CR0, &(p->cr0)); + CHK_VMCS_READ(HOST_CR3, &(p->cr3)); + CHK_VMCS_READ(HOST_CR4, &(p->cr4)); + CHK_VMCS_READ(HOST_RSP, &(p->rsp)); + CHK_VMCS_READ(HOST_RIP, &(p->rip)); + CHK_VMCS_READ(VMCS_HOST_CS_SELECTOR, &(p->csSelector)); + CHK_VMCS_READ(VMCS_HOST_SS_SELECTOR, &(p->ssSelector)); + CHK_VMCS_READ(VMCS_HOST_DS_SELECTOR, &(p->dsSelector)); + CHK_VMCS_READ(VMCS_HOST_ES_SELECTOR, &(p->esSelector)); + CHK_VMCS_READ(VMCS_HOST_FS_SELECTOR, &(p->fsSelector)); + CHK_VMCS_READ(VMCS_HOST_GS_SELECTOR, &(p->gsSelector)); + CHK_VMCS_READ(VMCS_HOST_TR_SELECTOR, &(p->trSelector)); + CHK_VMCS_READ(HOST_FS_BASE, &(p->fsBaseAddr)); + CHK_VMCS_READ(HOST_GS_BASE, &(p->gsBaseAddr)); + CHK_VMCS_READ(HOST_TR_BASE, &(p->trBaseAddr)); + CHK_VMCS_READ(HOST_GDTR_BASE, &(p->gdtrBaseAddr)); + CHK_VMCS_READ(HOST_IDTR_BASE, &(p->idtrBaseAddr)); + CHK_VMCS_READ(HOST_IA32_SYSENTER_CS, &(p->sysenter_cs)); + CHK_VMCS_READ(HOST_IA32_SYSENTER_ESP, &(p->sysenter_esp)); + CHK_VMCS_READ(HOST_IA32_SYSENTER_EIP, &(p->sysenter_eip)); + return 0; +} + + + +int CopyInVMCSHostStateArea(struct VMCSHostStateArea *p) { + CHK_VMCS_WRITE(HOST_CR0, &(p->cr0)); + CHK_VMCS_WRITE(HOST_CR3, &(p->cr3)); + CHK_VMCS_WRITE(HOST_CR4, &(p->cr4)); + CHK_VMCS_WRITE(HOST_RSP, &(p->rsp)); + CHK_VMCS_WRITE(HOST_RIP, &(p->rip)); + CHK_VMCS_WRITE(VMCS_HOST_CS_SELECTOR, &(p->csSelector)); + CHK_VMCS_WRITE(VMCS_HOST_SS_SELECTOR, &(p->ssSelector)); + CHK_VMCS_WRITE(VMCS_HOST_DS_SELECTOR, &(p->dsSelector)); + CHK_VMCS_WRITE(VMCS_HOST_ES_SELECTOR, &(p->esSelector)); + CHK_VMCS_WRITE(VMCS_HOST_FS_SELECTOR, &(p->fsSelector)); + CHK_VMCS_WRITE(VMCS_HOST_GS_SELECTOR, &(p->gsSelector)); + CHK_VMCS_WRITE(VMCS_HOST_TR_SELECTOR, &(p->trSelector)); + CHK_VMCS_WRITE(HOST_FS_BASE, &(p->fsBaseAddr)); + CHK_VMCS_WRITE(HOST_GS_BASE, &(p->gsBaseAddr)); + CHK_VMCS_WRITE(HOST_TR_BASE, &(p->trBaseAddr)); + CHK_VMCS_WRITE(HOST_GDTR_BASE, &(p->gdtrBaseAddr)); + CHK_VMCS_WRITE(HOST_IDTR_BASE, &(p->idtrBaseAddr)); + CHK_VMCS_WRITE(HOST_IA32_SYSENTER_CS, &(p->sysenter_cs)); + CHK_VMCS_WRITE(HOST_IA32_SYSENTER_ESP, &(p->sysenter_esp)); + CHK_VMCS_WRITE(HOST_IA32_SYSENTER_EIP, &(p->sysenter_eip)); + return 0; +} + + +int CopyOutVMCSExitCtrlFields(struct VMCSExitCtrlFields *p) +{ + CHK_VMCS_READ(VM_EXIT_CTRLS,&(p->exitCtrls)); + CHK_VMCS_READ(VM_EXIT_MSR_STORE_COUNT,&(p->msrStoreCount)); + CHK_VMCS_READ(VM_EXIT_MSR_STORE_ADDR,&(p->msrStoreAddr)); + CHK_VMCS_READ(VM_EXIT_MSR_LOAD_COUNT,&(p->msrLoadCount)); + CHK_VMCS_READ(VM_EXIT_MSR_LOAD_ADDR,&(p->msrLoadAddr)); + return 0; +} + +int CopyInVMCSExitCtrlFields(struct VMCSExitCtrlFields *p) +{ + CHK_VMCS_WRITE(VM_EXIT_CTRLS,&(p->exitCtrls)); + CHK_VMCS_WRITE(VM_EXIT_MSR_STORE_COUNT,&(p->msrStoreCount)); + CHK_VMCS_WRITE(VM_EXIT_MSR_STORE_ADDR,&(p->msrStoreAddr)); + CHK_VMCS_WRITE(VM_EXIT_MSR_LOAD_COUNT,&(p->msrLoadCount)); + CHK_VMCS_WRITE(VM_EXIT_MSR_LOAD_ADDR,&(p->msrLoadAddr)); + return 0; +} + + +int CopyOutVMCSEntryCtrlFields(struct VMCSEntryCtrlFields *p) +{ + CHK_VMCS_READ(VM_ENTRY_CTRLS,&(p->entryCtrls)); + CHK_VMCS_READ(VM_ENTRY_MSR_LOAD_COUNT,&(p->msrLoadCount)); + CHK_VMCS_READ(VM_ENTRY_MSR_LOAD_ADDR,&(p->msrLoadAddr)); + CHK_VMCS_READ(VM_ENTRY_INT_INFO_FIELD,&(p->intInfo)); + CHK_VMCS_READ(VM_ENTRY_EXCEPTION_ERROR,&(p->exceptionErrorCode)); + CHK_VMCS_READ(VM_ENTRY_INSTR_LENGTH,&(p->instrLength)); + return 0; +} + +int CopyInVMCSEntryCtrlFields(struct VMCSEntryCtrlFields *p) +{ + CHK_VMCS_WRITE(VM_ENTRY_CTRLS,&(p->entryCtrls)); + CHK_VMCS_WRITE(VM_ENTRY_MSR_LOAD_COUNT,&(p->msrLoadCount)); + CHK_VMCS_WRITE(VM_ENTRY_MSR_LOAD_ADDR,&(p->msrLoadAddr)); + CHK_VMCS_WRITE(VM_ENTRY_INT_INFO_FIELD,&(p->intInfo)); + CHK_VMCS_WRITE(VM_ENTRY_EXCEPTION_ERROR,&(p->exceptionErrorCode)); + CHK_VMCS_WRITE(VM_ENTRY_INSTR_LENGTH,&(p->instrLength)); + return 0; +} + +int CopyOutVMCSExitInfoFields(struct VMCSExitInfoFields *p) { + CHK_VMCS_READ(EXIT_REASON,&(p->reason)); + CHK_VMCS_READ(EXIT_QUALIFICATION,&(p->qualification)); + CHK_VMCS_READ(VM_EXIT_INT_INFO,&(p->intInfo)); + CHK_VMCS_READ(VM_EXIT_INT_ERROR,&(p->intErrorCode)); + CHK_VMCS_READ(IDT_VECTOR_INFO,&(p->idtVectorInfo)); + CHK_VMCS_READ(IDT_VECTOR_ERROR,&(p->idtVectorErrorCode)); + CHK_VMCS_READ(VM_EXIT_INSTR_LENGTH,&(p->instrLength)); + CHK_VMCS_READ(GUEST_LINEAR_ADDR,&(p->guestLinearAddr)); + CHK_VMCS_READ(VMX_INSTR_INFO,&(p->instrInfo)); + CHK_VMCS_READ(IO_RCX,&(p->ioRCX)); + CHK_VMCS_READ(IO_RSI,&(p->ioRSI)); + CHK_VMCS_READ(IO_RDI,&(p->ioRDI)); + CHK_VMCS_READ(IO_RIP,&(p->ioRIP)); + CHK_VMCS_READ(VM_INSTR_ERROR,&(p->instrErrorField)); + return 0; +} + + +int CopyOutVMCSExecCtrlFields(struct VMCSExecCtrlFields *p) +{ + CHK_VMCS_READ(PIN_VM_EXEC_CTRLS,&(p->pinCtrls)); + CHK_VMCS_READ(PROC_VM_EXEC_CTRLS,&(p->procCtrls)); + CHK_VMCS_READ(EXCEPTION_BITMAP,&(p->execBitmap)); + CHK_VMCS_READ(PAGE_FAULT_ERROR_MASK,&(p->pageFaultErrorMask)); + CHK_VMCS_READ(PAGE_FAULT_ERROR_MATCH,&(p->pageFaultErrorMatch)); + CHK_VMCS_READ(IO_BITMAP_A_ADDR,&(p->ioBitmapA)); + CHK_VMCS_READ(IO_BITMAP_B_ADDR,&(p->ioBitmapB)); + CHK_VMCS_READ(TSC_OFFSET,&(p->tscOffset)); + CHK_VMCS_READ(CR0_GUEST_HOST_MASK,&(p->cr0GuestHostMask)); + CHK_VMCS_READ(CR0_READ_SHADOW,&(p->cr0ReadShadow)); + CHK_VMCS_READ(CR4_GUEST_HOST_MASK,&(p->cr4GuestHostMask)); + CHK_VMCS_READ(CR4_READ_SHADOW,&(p->cr4ReadShadow)); + CHK_VMCS_READ(CR3_TARGET_COUNT, &(p->cr3TargetCount)); + CHK_VMCS_READ(CR3_TARGET_VALUE_0, &(p->cr3TargetValue0)); + CHK_VMCS_READ(CR3_TARGET_VALUE_1, &(p->cr3TargetValue1)); + CHK_VMCS_READ(CR3_TARGET_VALUE_2, &(p->cr3TargetValue2)); + CHK_VMCS_READ(CR3_TARGET_VALUE_3, &(p->cr3TargetValue3)); + CHK_VMCS_READ(VIRT_APIC_PAGE_ADDR, &(p->virtApicPageAddr)); + CHK_VMCS_READ(TPR_THRESHOLD, &(p->tprThreshold)); + CHK_VMCS_READ(MSR_BITMAPS, &(p->MSRBitmapsBaseAddr)); + CHK_VMCS_READ(VMCS_EXEC_PTR,&(p->vmcsExecPtr)); + return 0; +} + + +int CopyInVMCSExecCtrlFields(struct VMCSExecCtrlFields *p) +{ + CHK_VMCS_WRITE(PIN_VM_EXEC_CTRLS,&(p->pinCtrls)); + CHK_VMCS_WRITE(PROC_VM_EXEC_CTRLS,&(p->procCtrls)); + CHK_VMCS_WRITE(EXCEPTION_BITMAP,&(p->execBitmap)); + CHK_VMCS_WRITE(PAGE_FAULT_ERROR_MASK,&(p->pageFaultErrorMask)); + CHK_VMCS_WRITE(PAGE_FAULT_ERROR_MATCH,&(p->pageFaultErrorMatch)); + CHK_VMCS_WRITE(IO_BITMAP_A_ADDR,&(p->ioBitmapA)); + CHK_VMCS_WRITE(IO_BITMAP_B_ADDR,&(p->ioBitmapB)); + CHK_VMCS_WRITE(TSC_OFFSET,&(p->tscOffset)); + CHK_VMCS_WRITE(CR0_GUEST_HOST_MASK,&(p->cr0GuestHostMask)); + CHK_VMCS_WRITE(CR0_READ_SHADOW,&(p->cr0ReadShadow)); + CHK_VMCS_WRITE(CR4_GUEST_HOST_MASK,&(p->cr4GuestHostMask)); + CHK_VMCS_WRITE(CR4_READ_SHADOW,&(p->cr4ReadShadow)); + CHK_VMCS_WRITE(CR3_TARGET_COUNT, &(p->cr3TargetCount)); + CHK_VMCS_WRITE(CR3_TARGET_VALUE_0, &(p->cr3TargetValue0)); + CHK_VMCS_WRITE(CR3_TARGET_VALUE_1, &(p->cr3TargetValue1)); + CHK_VMCS_WRITE(CR3_TARGET_VALUE_2, &(p->cr3TargetValue2)); + CHK_VMCS_WRITE(CR3_TARGET_VALUE_3, &(p->cr3TargetValue3)); + CHK_VMCS_WRITE(VIRT_APIC_PAGE_ADDR, &(p->virtApicPageAddr)); + CHK_VMCS_WRITE(TPR_THRESHOLD, &(p->tprThreshold)); + CHK_VMCS_WRITE(MSR_BITMAPS, &(p->MSRBitmapsBaseAddr)); + CHK_VMCS_WRITE(VMCS_EXEC_PTR,&(p->vmcsExecPtr)); + return 0; +} + + +int CopyOutVMCSData(struct VMCSData *p) { + if (CopyOutVMCSGuestStateArea(&(p->guestStateArea)) != 0) { + return -1; + } + if (CopyOutVMCSHostStateArea(&(p->hostStateArea)) != 0) { + return -1; + } + if (CopyOutVMCSExecCtrlFields(&(p->execCtrlFields)) != 0) { + return -1; + } + if (CopyOutVMCSExitCtrlFields(&(p->exitCtrlFields)) != 0) { + return -1; + } + if (CopyOutVMCSEntryCtrlFields(&(p->entryCtrlFields)) != 0) { + return -1; + } + if (CopyOutVMCSExitInfoFields(&(p->exitInfoFields)) != 0) { + return -1; + } + return 0; +} + + +int CopyInVMCSData(struct VMCSData *p) { + if (CopyInVMCSGuestStateArea(&(p->guestStateArea)) != 0) { + return -1; + } + if (CopyInVMCSHostStateArea(&(p->hostStateArea)) != 0) { + return -1; + } + if (CopyInVMCSExecCtrlFields(&(p->execCtrlFields)) != 0) { + return -1; + } + if (CopyInVMCSExitCtrlFields(&(p->exitCtrlFields)) != 0) { + return -1; + } + if (CopyInVMCSEntryCtrlFields(&(p->entryCtrlFields)) != 0) { + return -1; + } + return 0; +} + + +void PrintTrace_VMX_Regs(struct VMXRegs * regs) { + PrintTrace("==>VMX Register values:\n"); + PrintTrace("EAX: %x\n", regs->eax); + PrintTrace("ECX: %x\n", regs->ecx); + PrintTrace("EDX: %x\n", regs->edx); + PrintTrace("EBX: %x\n", regs->ebx); + PrintTrace("ESP: %x\n", regs->esp); + PrintTrace("EBP: %x\n", regs->ebp); + PrintTrace("ESI: %x\n", regs->esi); + PrintTrace("EDI: %x\n", regs->edi); + PrintTrace("\n"); +} + + +void PrintTrace_VMCSSegment(char * segname, struct VMCSSegment * seg, int abbr) { + PrintTrace("Segment: %s\n", segname); + if (abbr == 0) { + PrintTrace("\tSelector: %x\n", (uint_t)seg->selector); + PrintTrace("\tAccess: %x\n", *(uint_t*)&(seg->access)); + } + PrintTrace("\tBase Addr: %x\n", (uint_t)seg->baseAddr); + PrintTrace("\tLimit: %x\n", (uint_t)seg->limit); + +} + + +void PrintTrace_VMCSGuestStateArea(struct VMCSGuestStateArea * guestState) { + PrintTrace("==>Guest State Area\n"); + PrintTrace("==>==> Guest Register State\n"); + PrintTrace("GUEST_CR0: %x\n",(uint_t) guestState->cr0); + PrintTrace("GUEST_CR3: %x\n",(uint_t)guestState->cr3); + PrintTrace("GUEST_CR4: %x\n",(uint_t)guestState->cr4); + PrintTrace("GUEST_DR7: %x\n",(uint_t)guestState->dr7); + PrintTrace("GUEST_RSP: %x\n",(uint_t)guestState->rsp); + PrintTrace("GUEST_RIP: %x\n",(uint_t)guestState->rip); + PrintTrace("GUEST_RFLAGS: %x\n",(uint_t)guestState->rflags); + + PrintTrace_VMCSSegment("Guest CS", &(guestState->cs), 0); + PrintTrace_VMCSSegment("Guest SS", &(guestState->ss), 0); + PrintTrace_VMCSSegment("Guest DS",&(guestState->ds), 0); + PrintTrace_VMCSSegment("Guest ES", &(guestState->es), 0); + PrintTrace_VMCSSegment("Guest FS", &(guestState->fs), 0); + PrintTrace_VMCSSegment("Guest GS", &(guestState->gs), 0); + PrintTrace_VMCSSegment("Guest LDTR", &(guestState->ldtr), 0); + PrintTrace_VMCSSegment("Guest TR", &(guestState->tr), 0); + PrintTrace_VMCSSegment("Guest GDTR", &(guestState->gdtr), 1); + PrintTrace_VMCSSegment("Guest IDTR", &(guestState->idtr), 1); + + + PrintTrace("GUEST_IA32_DEBUGCTL: %x\n",(uint_t)(guestState->dbg_ctrl & 0xffffffff)); + PrintTrace("GUEST_IA32_DEBUGCTL_HIGH: %x\n",(uint_t)(guestState->dbg_ctrl >> 32) & 0xffffffff); + PrintTrace("GUEST_IA32_SYSENTER_CS: %x\n",guestState->sysenter_cs); + PrintTrace("GUEST_IA32_SYSENTER_ESP: %x\n",(uint_t)guestState->sysenter_esp); + PrintTrace("GUEST_IA32_SYSENTER_EIP: %x\n",(uint_t)guestState->sysenter_eip); + PrintTrace("GUEST_SMBASE: %x\n", (uint_t)guestState->smbase); + + PrintTrace("==>==> Guest Non-Register State\n"); + PrintTrace("GUEST_ACTIVITY_STATE: %x\n", (uint_t)guestState->activity); + PrintTrace("GUEST_INT_STATE: %x\n", (uint_t)guestState->interrupt_state); + PrintTrace("GUEST_PENDING_DEBUG_EXCS: %x\n", (uint_t)guestState->pending_dbg_exceptions); + PrintTrace("VMCS_LINK_PTR: %x\n", (uint_t)guestState->vmcs_link & 0xffffffff); + PrintTrace("VMCS_LINK_PTR_HIGH: %x\n", (uint_t)(guestState->vmcs_link >> 32) & 0xffffffff); +} + + +void PrintTrace_VMCSHostStateArea(struct VMCSHostStateArea * hostState) { + PrintTrace("\n==> Host State Area\n"); + PrintTrace("HOST_CR0: %x\n", (uint_t)hostState->cr0); + PrintTrace("HOST_CR3: %x\n", (uint_t)hostState->cr3); + PrintTrace("HOST_CR4: %x\n", (uint_t)hostState->cr4); + PrintTrace("HOST_RSP: %x\n", (uint_t)hostState->rsp); + PrintTrace("HOST_RIP: %x\n", (uint_t)hostState->rip); + PrintTrace("VMCS_HOST_CS_SELECTOR: %x\n", (uint_t)hostState->csSelector); + PrintTrace("VMCS_HOST_SS_SELECTOR: %x\n", (uint_t)hostState->ssSelector); + PrintTrace("VMCS_HOST_DS_SELECTOR: %x\n", (uint_t)hostState->dsSelector); + PrintTrace("VMCS_HOST_ES_SELECTOR: %x\n", (uint_t)hostState->esSelector); + PrintTrace("VMCS_HOST_FS_SELECTOR: %x\n", (uint_t)hostState->fsSelector); + PrintTrace("VMCS_HOST_GS_SELECTOR: %x\n", (uint_t)hostState->gsSelector); + PrintTrace("VMCS_HOST_TR_SELECTOR: %x\n", (uint_t)hostState->trSelector); + PrintTrace("HOST_FS_BASE: %x\n", (uint_t)hostState->fsBaseAddr); + PrintTrace("HOST_GS_BASE: %x\n", (uint_t)hostState->gsBaseAddr); + PrintTrace("HOST_TR_BASE: %x\n", (uint_t)hostState->trBaseAddr); + PrintTrace("HOST_GDTR_BASE: %x\n", (uint_t)hostState->gdtrBaseAddr); + PrintTrace("HOST_IDTR_BASE: %x\n", (uint_t)hostState->idtrBaseAddr); + PrintTrace("HOST_IA32_SYSENTER_CS: %x\n", (uint_t)hostState->sysenter_cs); + PrintTrace("HOST_IA32_SYSENTER_ESP: %x\n", (uint_t)hostState->sysenter_esp); + PrintTrace("HOST_IA32_SYSENTER_EIP: %x\n", (uint_t)hostState->sysenter_eip); +} + +void PrintTrace_VMCSExecCtrlFields(struct VMCSExecCtrlFields * execCtrls) { + PrintTrace("\n==> VM-Execution Controls:\n"); + PrintTrace("PIN_VM_EXEC_CTRLS: %x\n", (uint_t) execCtrls->pinCtrls); + PrintTrace("PROC_VM_EXEC_CTRLS: %x\n", (uint_t) execCtrls->procCtrls); + PrintTrace("EXCEPTION_BITMAP: %x\n", (uint_t) execCtrls->execBitmap); + PrintTrace("PAGE_FAULT_ERROR_MASK: %x\n", (uint_t) execCtrls->pageFaultErrorMask); + PrintTrace("PAGE_FAULT_ERROR_MATCH: %x\n", (uint_t) execCtrls->pageFaultErrorMatch); + PrintTrace("IO_BITMAP_A_ADDR: %x\n", (uint_t) execCtrls->ioBitmapA); + // PrintTrace("IO_BITMAP_A_ADDR_HIGH: %x\n", (uint_t) execCtrls->); + PrintTrace("IO_BITMAP_B_ADDR: %x\n", (uint_t) execCtrls->ioBitmapB); + // PrintTrace("IO_BITMAP_B_ADDR_HIGH: %x\n", (uint_t) execCtrls->); + PrintTrace("TSC_OFFSET: %x\n", (uint_t) execCtrls->tscOffset & 0xffffffff); + PrintTrace("TSC_OFFSET_HIGH: %x\n", (uint_t) (execCtrls->tscOffset >> 32) & 0xffffffff); + PrintTrace("CR0_GUEST_HOST_MASK: %x\n", (uint_t) execCtrls->cr0GuestHostMask); + PrintTrace("CR0_READ_SHADOW: %x\n", (uint_t) execCtrls->cr0ReadShadow); + PrintTrace("CR4_GUEST_HOST_MASK: %x\n", (uint_t) execCtrls->cr4GuestHostMask); + PrintTrace("CR4_READ_SHADOW: %x\n", (uint_t) execCtrls->cr4ReadShadow); + PrintTrace("CR3_TARGET_COUNT: %x\n", (uint_t) execCtrls->cr3TargetCount); + PrintTrace("CR3_TARGET_VALUE_0: %x\n", (uint_t) execCtrls->cr3TargetValue0); + PrintTrace("CR3_TARGET_VALUE_1: %x\n", (uint_t) execCtrls->cr3TargetValue1); + PrintTrace("CR3_TARGET_VALUE_2: %x\n", (uint_t) execCtrls->cr3TargetValue2); + PrintTrace("CR3_TARGET_VALUE_3: %x\n", (uint_t) execCtrls->cr3TargetValue3); + PrintTrace("VIRT_APIC_PAGE_ADDR: %x\n", (uint_t) execCtrls->virtApicPageAddr & 0xffffffff); + PrintTrace("VIRT_APIC_PAGE_ADDR_HIGH: %x\n", (uint_t) (execCtrls->virtApicPageAddr >> 32) & 0xffffffff); + PrintTrace("TPR_THRESHOLD: %x\n", (uint_t) execCtrls->tprThreshold); + PrintTrace("MSR_BITMAPS: %x\n", (uint_t) execCtrls->MSRBitmapsBaseAddr & 0xffffffff); + PrintTrace("MSR_BITMAPS_HIGH: %x\n", (uint_t) (execCtrls->MSRBitmapsBaseAddr >> 32) & 0xffffffff); + PrintTrace("VMCS_EXEC_PTR: %x\n", (uint_t) execCtrls->vmcsExecPtr & 0xffffffff); + PrintTrace("VMCS_EXEC_PTR_HIGH: %x\n", (uint_t) (execCtrls->vmcsExecPtr >> 32) & 0xffffffff); +} + +void PrintTrace_VMCSExitCtrlFields(struct VMCSExitCtrlFields * exitCtrls) { + PrintTrace("\n==> VM Exit Controls\n"); + PrintTrace("VM_EXIT_CTRLS: %x\n", (uint_t) exitCtrls->exitCtrls); + PrintTrace("VM_EXIT_MSR_STORE_COUNT: %x\n", (uint_t) exitCtrls->msrStoreCount); + PrintTrace("VM_EXIT_MSR_STORE_ADDR: %x\n", (uint_t) exitCtrls->msrStoreAddr & 0xffffffff); + PrintTrace("VM_EXIT_MSR_STORE_ADDR_HIGH: %x\n", (uint_t) (exitCtrls->msrStoreAddr >> 32) & 0xffffffff); + PrintTrace("VM_EXIT_MSR_LOAD_COUNT: %x\n", (uint_t) exitCtrls->msrLoadCount); + PrintTrace("VM_EXIT_MSR_LOAD_ADDR: %x\n", (uint_t) exitCtrls->msrLoadAddr & 0xffffffff); + PrintTrace("VM_EXIT_MSR_LOAD_ADDR_HIGH: %x\n", (uint_t) (exitCtrls->msrLoadAddr >> 32) & 0xffffffff); +} + +void PrintTrace_VMCSEntryCtrlFields(struct VMCSEntryCtrlFields * entryCtrls) { + PrintTrace("\n==> VM Entry Controls\n"); + PrintTrace("VM_ENTRY_CTRLS: %x\n", (uint_t) entryCtrls->entryCtrls); + PrintTrace("VM_ENTRY_MSR_LOAD_COUNT: %x\n", (uint_t) entryCtrls->msrLoadCount); + PrintTrace("VM_ENTRY_MSR_LOAD_ADDR: %x\n", (uint_t) entryCtrls->msrLoadAddr & 0xffffffff); + PrintTrace("VM_ENTRY_MSR_LOAD_ADDR_HIGH: %x\n", (uint_t) (entryCtrls->msrLoadAddr >> 32) & 0xffffffff); + PrintTrace("VM_ENTRY_INT_INFO_FIELD: %x\n", (uint_t) entryCtrls->intInfo); + PrintTrace("VM_ENTRY_EXCEPTION_ERROR: %x\n", (uint_t) entryCtrls->exceptionErrorCode); + PrintTrace("VM_ENTRY_INSTR_LENGTH: %x\n", (uint_t) entryCtrls->instrLength); +} + +void PrintTrace_VMCSExitInfoFields(struct VMCSExitInfoFields * exitInfo) { + PrintTrace("\n==> VM Exit Info\n"); + PrintTrace("EXIT_REASON: %x\n", (uint_t) exitInfo->reason); + PrintTrace("EXIT_QUALIFICATION: %x\n", (uint_t) exitInfo->qualification); + PrintTrace("VM_EXIT_INT_INFO: %x\n", (uint_t) exitInfo->intInfo); + PrintTrace("VM_EXIT_INT_ERROR: %x\n", (uint_t) exitInfo->intErrorCode); + PrintTrace("IDT_VECTOR_INFO: %x\n", (uint_t) exitInfo->idtVectorInfo); + PrintTrace("IDT_VECTOR_ERROR: %x\n", (uint_t) exitInfo->idtVectorErrorCode); + PrintTrace("VM_EXIT_INSTR_LENGTH: %x\n", (uint_t) exitInfo->instrLength); + PrintTrace("GUEST_LINEAR_ADDR: %x\n", (uint_t) exitInfo->guestLinearAddr); + PrintTrace("VMX_INSTR_INFO: %x\n", (uint_t) exitInfo->instrInfo); + PrintTrace("IO_RCX: %x\n", (uint_t) exitInfo->ioRCX); + PrintTrace("IO_RSI: %x\n", (uint_t) exitInfo->ioRSI); + PrintTrace("IO_RDI: %x\n", (uint_t) exitInfo->ioRDI); + PrintTrace("IO_RIP: %x\n", (uint_t) exitInfo->ioRIP); + PrintTrace("VM_INSTR_ERROR: %x\n", (uint_t) exitInfo->instrErrorField); +} + + +void PrintTrace_VMCSData(struct VMCSData * vmcs) { + PrintTrace("VMCSData Structure\n"); + + PrintTrace_VMCSGuestStateArea(&(vmcs->guestStateArea)); + PrintTrace_VMCSHostStateArea(&(vmcs->hostStateArea)); + PrintTrace_VMCSExecCtrlFields(&(vmcs->execCtrlFields)); + PrintTrace_VMCSExitCtrlFields(&(vmcs->exitCtrlFields)); + PrintTrace_VMCSEntryCtrlFields(&(vmcs->entryCtrlFields)); + PrintTrace_VMCSExitInfoFields(&(vmcs->exitInfoFields)); + PrintTrace("\n"); +} diff --git a/palacios/src/palacios/vmcs_fields.asm b/palacios/src/palacios/vmcs_fields.asm new file mode 100644 index 0000000..f354cf1 --- /dev/null +++ b/palacios/src/palacios/vmcs_fields.asm @@ -0,0 +1,135 @@ +%ifndef VMCS_FIELDS_ASM +%define VMCS_FIELDS_ASM + +VMCS_GUEST_ES_SELECTOR equ 0x00000800 +VMCS_GUEST_CS_SELECTOR equ 0x00000802 +VMCS_GUEST_SS_SELECTOR equ 0x00000804 +VMCS_GUEST_DS_SELECTOR equ 0x00000806 +VMCS_GUEST_FS_SELECTOR equ 0x00000808 +VMCS_GUEST_GS_SELECTOR equ 0x0000080A +VMCS_GUEST_LDTR_SELECTOR equ 0x0000080C +VMCS_GUEST_TR_SELECTOR equ 0x0000080E +VMCS_HOST_ES_SELECTOR equ 0x00000C00 +VMCS_HOST_CS_SELECTOR equ 0x00000C02 +VMCS_HOST_SS_SELECTOR equ 0x00000C04 +VMCS_HOST_DS_SELECTOR equ 0x00000C06 +VMCS_HOST_FS_SELECTOR equ 0x00000C08 +VMCS_HOST_GS_SELECTOR equ 0x00000C0A +VMCS_HOST_TR_SELECTOR equ 0x00000C0C +IO_BITMAP_A_ADDR equ 0x00002000 +IO_BITMAP_A_ADDR_HIGH equ 0x00002001 +IO_BITMAP_B_ADDR equ 0x00002002 +IO_BITMAP_B_ADDR_HIGH equ 0x00002003 +MSR_BITMAPS equ 0x00002004 +MSR_BITMAPS_HIGH equ 0x00002005 +VM_EXIT_MSR_STORE_ADDR equ 0x00002006 +VM_EXIT_MSR_STORE_ADDR_HIGH equ 0x00002007 +VM_EXIT_MSR_LOAD_ADDR equ 0x00002008 +VM_EXIT_MSR_LOAD_ADDR_HIGH equ 0x00002009 +VM_ENTRY_MSR_LOAD_ADDR equ 0x0000200A +VM_ENTRY_MSR_LOAD_ADDR_HIGH equ 0x0000200B +VMCS_EXEC_PTR equ 0x0000200C +VMCS_EXEC_PTR_HIGH equ 0x0000200D +TSC_OFFSET equ 0x00002010 +TSC_OFFSET_HIGH equ 0x00002011 +VIRT_APIC_PAGE_ADDR equ 0x00002012 +VIRT_APIC_PAGE_ADDR_HIGH equ 0x00002013 +VMCS_LINK_PTR equ 0x00002800 +VMCS_LINK_PTR_HIGH equ 0x00002801 +GUEST_IA32_DEBUGCTL equ 0x00002802 +GUEST_IA32_DEBUGCTL_HIGH equ 0x00002803 +PIN_VM_EXEC_CTRLS equ 0x00004000 +PROC_VM_EXEC_CTRLS equ 0x00004002 +EXCEPTION_BITMAP equ 0x00004004 +PAGE_FAULT_ERROR_MASK equ 0x00004006 +PAGE_FAULT_ERROR_MATCH equ 0x00004008 +CR3_TARGET_COUNT equ 0x0000400A +VM_EXIT_CTRLS equ 0x0000400C +VM_EXIT_MSR_STORE_COUNT equ 0x0000400E +VM_EXIT_MSR_LOAD_COUNT equ 0x00004010 +VM_ENTRY_CTRLS equ 0x00004012 +VM_ENTRY_MSR_LOAD_COUNT equ 0x00004014 +VM_ENTRY_INT_INFO_FIELD equ 0x00004016 +VM_ENTRY_EXCEPTION_ERROR equ 0x00004018 +VM_ENTRY_INSTR_LENGTH equ 0x0000401A +TPR_THRESHOLD equ 0x0000401C +VM_INSTR_ERROR equ 0x00004400 +EXIT_REASON equ 0x00004402 +VM_EXIT_INT_INFO equ 0x00004404 +VM_EXIT_INT_ERROR equ 0x00004406 +IDT_VECTOR_INFO equ 0x00004408 +IDT_VECTOR_ERROR equ 0x0000440A +VM_EXIT_INSTR_LENGTH equ 0x0000440C +VMX_INSTR_INFO equ 0x0000440E +GUEST_ES_LIMIT equ 0x00004800 +GUEST_CS_LIMIT equ 0x00004802 +GUEST_SS_LIMIT equ 0x00004804 +GUEST_DS_LIMIT equ 0x00004806 +GUEST_FS_LIMIT equ 0x00004808 +GUEST_GS_LIMIT equ 0x0000480A +GUEST_LDTR_LIMIT equ 0x0000480C +GUEST_TR_LIMIT equ 0x0000480E +GUEST_GDTR_LIMIT equ 0x00004810 +GUEST_IDTR_LIMIT equ 0x00004812 +GUEST_ES_ACCESS equ 0x00004814 +GUEST_CS_ACCESS equ 0x00004816 +GUEST_SS_ACCESS equ 0x00004818 +GUEST_DS_ACCESS equ 0x0000481A +GUEST_FS_ACCESS equ 0x0000481C +GUEST_GS_ACCESS equ 0x0000481E +GUEST_LDTR_ACCESS equ 0x00004820 +GUEST_TR_ACCESS equ 0x00004822 +GUEST_INT_STATE equ 0x00004824 +GUEST_ACTIVITY_STATE equ 0x00004826 +GUEST_SMBASE equ 0x00004828 +GUEST_IA32_SYSENTER_CS equ 0x0000482A +HOST_IA32_SYSENTER_CS equ 0x00004C00 +CR0_GUEST_HOST_MASK equ 0x00006000 +CR4_GUEST_HOST_MASK equ 0x00006002 +CR0_READ_SHADOW equ 0x00006004 +CR4_READ_SHADOW equ 0x00006006 +CR3_TARGET_VALUE_0 equ 0x00006008 +CR3_TARGET_VALUE_1 equ 0x0000600A +CR3_TARGET_VALUE_2 equ 0x0000600C +CR3_TARGET_VALUE_3 equ 0x0000600E +EXIT_QUALIFICATION equ 0x00006400 +IO_RCX equ 0x00006402 +IO_RSI equ 0x00006404 +IO_RDI equ 0x00006406 +IO_RIP equ 0x00006408 +GUEST_LINEAR_ADDR equ 0x0000640A +GUEST_CR0 equ 0x00006800 +GUEST_CR3 equ 0x00006802 +GUEST_CR4 equ 0x00006804 +GUEST_ES_BASE equ 0x00006806 +GUEST_CS_BASE equ 0x00006808 +GUEST_SS_BASE equ 0x0000680A +GUEST_DS_BASE equ 0x0000680C +GUEST_FS_BASE equ 0x0000680E +GUEST_GS_BASE equ 0x00006810 +GUEST_LDTR_BASE equ 0x00006812 +GUEST_TR_BASE equ 0x00006814 +GUEST_GDTR_BASE equ 0x00006816 +GUEST_IDTR_BASE equ 0x00006818 +GUEST_DR7 equ 0x0000681A +GUEST_RSP equ 0x0000681C +GUEST_RIP equ 0x0000681E +GUEST_RFLAGS equ 0x00006820 +GUEST_PENDING_DEBUG_EXCS equ 0x00006822 +GUEST_IA32_SYSENTER_ESP equ 0x00006824 +GUEST_IA32_SYSENTER_EIP equ 0x00006826 +HOST_CR0 equ 0x00006C00 +HOST_CR3 equ 0x00006C02 +HOST_CR4 equ 0x00006C04 +HOST_FS_BASE equ 0x00006C06 +HOST_GS_BASE equ 0x00006C08 +HOST_TR_BASE equ 0x00006C0A +HOST_GDTR_BASE equ 0x00006C0C +HOST_IDTR_BASE equ 0x00006C0E +HOST_IA32_SYSENTER_ESP equ 0x00006C10 +HOST_IA32_SYSENTER_EIP equ 0x00006C12 +HOST_RSP equ 0x00006C14 +HOST_RIP equ 0x00006C16 + +%endif + diff --git a/palacios/src/palacios/vmcs_gen.c b/palacios/src/palacios/vmcs_gen.c new file mode 100644 index 0000000..cc7ad8f --- /dev/null +++ b/palacios/src/palacios/vmcs_gen.c @@ -0,0 +1,926 @@ +#include + + + + +void Set_VMCS_GUEST_ES_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_GUEST_ES_SELECTOR,val); } +uint_t Get_VMCS_GUEST_ES_SELECTOR() { uint_t rc; VMCS_READ(VMCS_GUEST_ES_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_GUEST_ES_SELECTOR() { PrintTrace("VMCS_GUEST_ES_SELECTOR = %x\n", Get_VMCS_GUEST_ES_SELECTOR()); } + + +void Set_VMCS_GUEST_CS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_GUEST_CS_SELECTOR,val); } +uint_t Get_VMCS_GUEST_CS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_GUEST_CS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_GUEST_CS_SELECTOR() { PrintTrace("VMCS_GUEST_CS_SELECTOR = %x\n", Get_VMCS_GUEST_CS_SELECTOR()); } + + +void Set_VMCS_GUEST_SS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_GUEST_SS_SELECTOR,val); } +uint_t Get_VMCS_GUEST_SS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_GUEST_SS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_GUEST_SS_SELECTOR() { PrintTrace("VMCS_GUEST_SS_SELECTOR = %x\n", Get_VMCS_GUEST_SS_SELECTOR()); } + + +void Set_VMCS_GUEST_DS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_GUEST_DS_SELECTOR,val); } +uint_t Get_VMCS_GUEST_DS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_GUEST_DS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_GUEST_DS_SELECTOR() { PrintTrace("VMCS_GUEST_DS_SELECTOR = %x\n", Get_VMCS_GUEST_DS_SELECTOR()); } + + +void Set_VMCS_GUEST_FS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_GUEST_FS_SELECTOR,val); } +uint_t Get_VMCS_GUEST_FS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_GUEST_FS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_GUEST_FS_SELECTOR() { PrintTrace("VMCS_GUEST_FS_SELECTOR = %x\n", Get_VMCS_GUEST_FS_SELECTOR()); } + + +void Set_VMCS_GUEST_GS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_GUEST_GS_SELECTOR,val); } +uint_t Get_VMCS_GUEST_GS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_GUEST_GS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_GUEST_GS_SELECTOR() { PrintTrace("VMCS_GUEST_GS_SELECTOR = %x\n", Get_VMCS_GUEST_GS_SELECTOR()); } + + +void Set_VMCS_GUEST_LDTR_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_GUEST_LDTR_SELECTOR,val); } +uint_t Get_VMCS_GUEST_LDTR_SELECTOR() { uint_t rc; VMCS_READ(VMCS_GUEST_LDTR_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_GUEST_LDTR_SELECTOR() { PrintTrace("VMCS_GUEST_LDTR_SELECTOR = %x\n", Get_VMCS_GUEST_LDTR_SELECTOR()); } + + +void Set_VMCS_GUEST_TR_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_GUEST_TR_SELECTOR,val); } +uint_t Get_VMCS_GUEST_TR_SELECTOR() { uint_t rc; VMCS_READ(VMCS_GUEST_TR_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_GUEST_TR_SELECTOR() { PrintTrace("VMCS_GUEST_TR_SELECTOR = %x\n", Get_VMCS_GUEST_TR_SELECTOR()); } + + +void Set_VMCS_HOST_ES_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_HOST_ES_SELECTOR,val); } +uint_t Get_VMCS_HOST_ES_SELECTOR() { uint_t rc; VMCS_READ(VMCS_HOST_ES_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_HOST_ES_SELECTOR() { PrintTrace("VMCS_HOST_ES_SELECTOR = %x\n", Get_VMCS_HOST_ES_SELECTOR()); } + + +void Set_VMCS_HOST_CS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_HOST_CS_SELECTOR,val); } +uint_t Get_VMCS_HOST_CS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_HOST_CS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_HOST_CS_SELECTOR() { PrintTrace("VMCS_HOST_CS_SELECTOR = %x\n", Get_VMCS_HOST_CS_SELECTOR()); } + + +void Set_VMCS_HOST_SS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_HOST_SS_SELECTOR,val); } +uint_t Get_VMCS_HOST_SS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_HOST_SS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_HOST_SS_SELECTOR() { PrintTrace("VMCS_HOST_SS_SELECTOR = %x\n", Get_VMCS_HOST_SS_SELECTOR()); } + + +void Set_VMCS_HOST_DS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_HOST_DS_SELECTOR,val); } +uint_t Get_VMCS_HOST_DS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_HOST_DS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_HOST_DS_SELECTOR() { PrintTrace("VMCS_HOST_DS_SELECTOR = %x\n", Get_VMCS_HOST_DS_SELECTOR()); } + + +void Set_VMCS_HOST_FS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_HOST_FS_SELECTOR,val); } +uint_t Get_VMCS_HOST_FS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_HOST_FS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_HOST_FS_SELECTOR() { PrintTrace("VMCS_HOST_FS_SELECTOR = %x\n", Get_VMCS_HOST_FS_SELECTOR()); } + + +void Set_VMCS_HOST_GS_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_HOST_GS_SELECTOR,val); } +uint_t Get_VMCS_HOST_GS_SELECTOR() { uint_t rc; VMCS_READ(VMCS_HOST_GS_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_HOST_GS_SELECTOR() { PrintTrace("VMCS_HOST_GS_SELECTOR = %x\n", Get_VMCS_HOST_GS_SELECTOR()); } + + +void Set_VMCS_HOST_TR_SELECTOR(uint_t val) { VMCS_WRITE(VMCS_HOST_TR_SELECTOR,val); } +uint_t Get_VMCS_HOST_TR_SELECTOR() { uint_t rc; VMCS_READ(VMCS_HOST_TR_SELECTOR,&rc); return rc; } + +void PrintTrace_VMCS_HOST_TR_SELECTOR() { PrintTrace("VMCS_HOST_TR_SELECTOR = %x\n", Get_VMCS_HOST_TR_SELECTOR()); } + + +void Set_IO_BITMAP_A_ADDR(uint_t val) { VMCS_WRITE(IO_BITMAP_A_ADDR,val); } +uint_t Get_IO_BITMAP_A_ADDR() { uint_t rc; VMCS_READ(IO_BITMAP_A_ADDR,&rc); return rc; } + +void PrintTrace_IO_BITMAP_A_ADDR() { PrintTrace("IO_BITMAP_A_ADDR = %x\n", Get_IO_BITMAP_A_ADDR()); } + + +void Set_IO_BITMAP_A_ADDR_HIGH(uint_t val) { VMCS_WRITE(IO_BITMAP_A_ADDR_HIGH,val); } +uint_t Get_IO_BITMAP_A_ADDR_HIGH() { uint_t rc; VMCS_READ(IO_BITMAP_A_ADDR_HIGH,&rc); return rc; } + +void PrintTrace_IO_BITMAP_A_ADDR_HIGH() { PrintTrace("IO_BITMAP_A_ADDR_HIGH = %x\n", Get_IO_BITMAP_A_ADDR_HIGH()); } + + +void Set_IO_BITMAP_B_ADDR(uint_t val) { VMCS_WRITE(IO_BITMAP_B_ADDR,val); } +uint_t Get_IO_BITMAP_B_ADDR() { uint_t rc; VMCS_READ(IO_BITMAP_B_ADDR,&rc); return rc; } + +void PrintTrace_IO_BITMAP_B_ADDR() { PrintTrace("IO_BITMAP_B_ADDR = %x\n", Get_IO_BITMAP_B_ADDR()); } + + +void Set_IO_BITMAP_B_ADDR_HIGH(uint_t val) { VMCS_WRITE(IO_BITMAP_B_ADDR_HIGH,val); } +uint_t Get_IO_BITMAP_B_ADDR_HIGH() { uint_t rc; VMCS_READ(IO_BITMAP_B_ADDR_HIGH,&rc); return rc; } + +void PrintTrace_IO_BITMAP_B_ADDR_HIGH() { PrintTrace("IO_BITMAP_B_ADDR_HIGH = %x\n", Get_IO_BITMAP_B_ADDR_HIGH()); } + + +void Set_MSR_BITMAPS(uint_t val) { VMCS_WRITE(MSR_BITMAPS,val); } +uint_t Get_MSR_BITMAPS() { uint_t rc; VMCS_READ(MSR_BITMAPS,&rc); return rc; } + +void PrintTrace_MSR_BITMAPS() { PrintTrace("MSR_BITMAPS = %x\n", Get_MSR_BITMAPS()); } + + +void Set_MSR_BITMAPS_HIGH(uint_t val) { VMCS_WRITE(MSR_BITMAPS_HIGH,val); } +uint_t Get_MSR_BITMAPS_HIGH() { uint_t rc; VMCS_READ(MSR_BITMAPS_HIGH,&rc); return rc; } + +void PrintTrace_MSR_BITMAPS_HIGH() { PrintTrace("MSR_BITMAPS_HIGH = %x\n", Get_MSR_BITMAPS_HIGH()); } + + +void Set_VM_EXIT_MSR_STORE_ADDR(uint_t val) { VMCS_WRITE(VM_EXIT_MSR_STORE_ADDR,val); } +uint_t Get_VM_EXIT_MSR_STORE_ADDR() { uint_t rc; VMCS_READ(VM_EXIT_MSR_STORE_ADDR,&rc); return rc; } + +void PrintTrace_VM_EXIT_MSR_STORE_ADDR() { PrintTrace("VM_EXIT_MSR_STORE_ADDR = %x\n", Get_VM_EXIT_MSR_STORE_ADDR()); } + + +void Set_VM_EXIT_MSR_STORE_ADDR_HIGH(uint_t val) { VMCS_WRITE(VM_EXIT_MSR_STORE_ADDR_HIGH,val); } +uint_t Get_VM_EXIT_MSR_STORE_ADDR_HIGH() { uint_t rc; VMCS_READ(VM_EXIT_MSR_STORE_ADDR_HIGH,&rc); return rc; } + +void PrintTrace_VM_EXIT_MSR_STORE_ADDR_HIGH() { PrintTrace("VM_EXIT_MSR_STORE_ADDR_HIGH = %x\n", Get_VM_EXIT_MSR_STORE_ADDR_HIGH()); } + + +void Set_VM_EXIT_MSR_LOAD_ADDR(uint_t val) { VMCS_WRITE(VM_EXIT_MSR_LOAD_ADDR,val); } +uint_t Get_VM_EXIT_MSR_LOAD_ADDR() { uint_t rc; VMCS_READ(VM_EXIT_MSR_LOAD_ADDR,&rc); return rc; } + +void PrintTrace_VM_EXIT_MSR_LOAD_ADDR() { PrintTrace("VM_EXIT_MSR_LOAD_ADDR = %x\n", Get_VM_EXIT_MSR_LOAD_ADDR()); } + + +void Set_VM_EXIT_MSR_LOAD_ADDR_HIGH(uint_t val) { VMCS_WRITE(VM_EXIT_MSR_LOAD_ADDR_HIGH,val); } +uint_t Get_VM_EXIT_MSR_LOAD_ADDR_HIGH() { uint_t rc; VMCS_READ(VM_EXIT_MSR_LOAD_ADDR_HIGH,&rc); return rc; } + +void PrintTrace_VM_EXIT_MSR_LOAD_ADDR_HIGH() { PrintTrace("VM_EXIT_MSR_LOAD_ADDR_HIGH = %x\n", Get_VM_EXIT_MSR_LOAD_ADDR_HIGH()); } + + +void Set_VM_ENTRY_MSR_LOAD_ADDR(uint_t val) { VMCS_WRITE(VM_ENTRY_MSR_LOAD_ADDR,val); } +uint_t Get_VM_ENTRY_MSR_LOAD_ADDR() { uint_t rc; VMCS_READ(VM_ENTRY_MSR_LOAD_ADDR,&rc); return rc; } + +void PrintTrace_VM_ENTRY_MSR_LOAD_ADDR() { PrintTrace("VM_ENTRY_MSR_LOAD_ADDR = %x\n", Get_VM_ENTRY_MSR_LOAD_ADDR()); } + + +void Set_VM_ENTRY_MSR_LOAD_ADDR_HIGH(uint_t val) { VMCS_WRITE(VM_ENTRY_MSR_LOAD_ADDR_HIGH,val); } +uint_t Get_VM_ENTRY_MSR_LOAD_ADDR_HIGH() { uint_t rc; VMCS_READ(VM_ENTRY_MSR_LOAD_ADDR_HIGH,&rc); return rc; } + +void PrintTrace_VM_ENTRY_MSR_LOAD_ADDR_HIGH() { PrintTrace("VM_ENTRY_MSR_LOAD_ADDR_HIGH = %x\n", Get_VM_ENTRY_MSR_LOAD_ADDR_HIGH()); } + + +void Set_VMCS_EXEC_PTR(uint_t val) { VMCS_WRITE(VMCS_EXEC_PTR,val); } +uint_t Get_VMCS_EXEC_PTR() { uint_t rc; VMCS_READ(VMCS_EXEC_PTR,&rc); return rc; } + +void PrintTrace_VMCS_EXEC_PTR() { PrintTrace("VMCS_EXEC_PTR = %x\n", Get_VMCS_EXEC_PTR()); } + + +void Set_VMCS_EXEC_PTR_HIGH(uint_t val) { VMCS_WRITE(VMCS_EXEC_PTR_HIGH,val); } +uint_t Get_VMCS_EXEC_PTR_HIGH() { uint_t rc; VMCS_READ(VMCS_EXEC_PTR_HIGH,&rc); return rc; } + +void PrintTrace_VMCS_EXEC_PTR_HIGH() { PrintTrace("VMCS_EXEC_PTR_HIGH = %x\n", Get_VMCS_EXEC_PTR_HIGH()); } + + +void Set_TSC_OFFSET(uint_t val) { VMCS_WRITE(TSC_OFFSET,val); } +uint_t Get_TSC_OFFSET() { uint_t rc; VMCS_READ(TSC_OFFSET,&rc); return rc; } + +void PrintTrace_TSC_OFFSET() { PrintTrace("TSC_OFFSET = %x\n", Get_TSC_OFFSET()); } + + +void Set_TSC_OFFSET_HIGH(uint_t val) { VMCS_WRITE(TSC_OFFSET_HIGH,val); } +uint_t Get_TSC_OFFSET_HIGH() { uint_t rc; VMCS_READ(TSC_OFFSET_HIGH,&rc); return rc; } + +void PrintTrace_TSC_OFFSET_HIGH() { PrintTrace("TSC_OFFSET_HIGH = %x\n", Get_TSC_OFFSET_HIGH()); } + + +void Set_VIRT_APIC_PAGE_ADDR(uint_t val) { VMCS_WRITE(VIRT_APIC_PAGE_ADDR,val); } +uint_t Get_VIRT_APIC_PAGE_ADDR() { uint_t rc; VMCS_READ(VIRT_APIC_PAGE_ADDR,&rc); return rc; } + +void PrintTrace_VIRT_APIC_PAGE_ADDR() { PrintTrace("VIRT_APIC_PAGE_ADDR = %x\n", Get_VIRT_APIC_PAGE_ADDR()); } + + +void Set_VIRT_APIC_PAGE_ADDR_HIGH(uint_t val) { VMCS_WRITE(VIRT_APIC_PAGE_ADDR_HIGH,val); } +uint_t Get_VIRT_APIC_PAGE_ADDR_HIGH() { uint_t rc; VMCS_READ(VIRT_APIC_PAGE_ADDR_HIGH,&rc); return rc; } + +void PrintTrace_VIRT_APIC_PAGE_ADDR_HIGH() { PrintTrace("VIRT_APIC_PAGE_ADDR_HIGH = %x\n", Get_VIRT_APIC_PAGE_ADDR_HIGH()); } + + +void Set_VMCS_LINK_PTR(uint_t val) { VMCS_WRITE(VMCS_LINK_PTR,val); } +uint_t Get_VMCS_LINK_PTR() { uint_t rc; VMCS_READ(VMCS_LINK_PTR,&rc); return rc; } + +void PrintTrace_VMCS_LINK_PTR() { PrintTrace("VMCS_LINK_PTR = %x\n", Get_VMCS_LINK_PTR()); } + + +void Set_VMCS_LINK_PTR_HIGH(uint_t val) { VMCS_WRITE(VMCS_LINK_PTR_HIGH,val); } +uint_t Get_VMCS_LINK_PTR_HIGH() { uint_t rc; VMCS_READ(VMCS_LINK_PTR_HIGH,&rc); return rc; } + +void PrintTrace_VMCS_LINK_PTR_HIGH() { PrintTrace("VMCS_LINK_PTR_HIGH = %x\n", Get_VMCS_LINK_PTR_HIGH()); } + + +void Set_GUEST_IA32_DEBUGCTL(uint_t val) { VMCS_WRITE(GUEST_IA32_DEBUGCTL,val); } +uint_t Get_GUEST_IA32_DEBUGCTL() { uint_t rc; VMCS_READ(GUEST_IA32_DEBUGCTL,&rc); return rc; } + +void PrintTrace_GUEST_IA32_DEBUGCTL() { PrintTrace("GUEST_IA32_DEBUGCTL = %x\n", Get_GUEST_IA32_DEBUGCTL()); } + + +void Set_GUEST_IA32_DEBUGCTL_HIGH(uint_t val) { VMCS_WRITE(GUEST_IA32_DEBUGCTL_HIGH,val); } +uint_t Get_GUEST_IA32_DEBUGCTL_HIGH() { uint_t rc; VMCS_READ(GUEST_IA32_DEBUGCTL_HIGH,&rc); return rc; } + +void PrintTrace_GUEST_IA32_DEBUGCTL_HIGH() { PrintTrace("GUEST_IA32_DEBUGCTL_HIGH = %x\n", Get_GUEST_IA32_DEBUGCTL_HIGH()); } + + +void Set_PIN_VM_EXEC_CTRLS(uint_t val) { VMCS_WRITE(PIN_VM_EXEC_CTRLS,val); } +uint_t Get_PIN_VM_EXEC_CTRLS() { uint_t rc; VMCS_READ(PIN_VM_EXEC_CTRLS,&rc); return rc; } + +void PrintTrace_PIN_VM_EXEC_CTRLS() { PrintTrace("PIN_VM_EXEC_CTRLS = %x\n", Get_PIN_VM_EXEC_CTRLS()); } + + +void Set_PROC_VM_EXEC_CTRLS(uint_t val) { VMCS_WRITE(PROC_VM_EXEC_CTRLS,val); } +uint_t Get_PROC_VM_EXEC_CTRLS() { uint_t rc; VMCS_READ(PROC_VM_EXEC_CTRLS,&rc); return rc; } + +void PrintTrace_PROC_VM_EXEC_CTRLS() { PrintTrace("PROC_VM_EXEC_CTRLS = %x\n", Get_PROC_VM_EXEC_CTRLS()); } + + +void Set_EXCEPTION_BITMAP(uint_t val) { VMCS_WRITE(EXCEPTION_BITMAP,val); } +uint_t Get_EXCEPTION_BITMAP() { uint_t rc; VMCS_READ(EXCEPTION_BITMAP,&rc); return rc; } + +void PrintTrace_EXCEPTION_BITMAP() { PrintTrace("EXCEPTION_BITMAP = %x\n", Get_EXCEPTION_BITMAP()); } + + +void Set_PAGE_FAULT_ERROR_MASK(uint_t val) { VMCS_WRITE(PAGE_FAULT_ERROR_MASK,val); } +uint_t Get_PAGE_FAULT_ERROR_MASK() { uint_t rc; VMCS_READ(PAGE_FAULT_ERROR_MASK,&rc); return rc; } + +void PrintTrace_PAGE_FAULT_ERROR_MASK() { PrintTrace("PAGE_FAULT_ERROR_MASK = %x\n", Get_PAGE_FAULT_ERROR_MASK()); } + + +void Set_PAGE_FAULT_ERROR_MATCH(uint_t val) { VMCS_WRITE(PAGE_FAULT_ERROR_MATCH,val); } +uint_t Get_PAGE_FAULT_ERROR_MATCH() { uint_t rc; VMCS_READ(PAGE_FAULT_ERROR_MATCH,&rc); return rc; } + +void PrintTrace_PAGE_FAULT_ERROR_MATCH() { PrintTrace("PAGE_FAULT_ERROR_MATCH = %x\n", Get_PAGE_FAULT_ERROR_MATCH()); } + + +void Set_CR3_TARGET_COUNT(uint_t val) { VMCS_WRITE(CR3_TARGET_COUNT,val); } +uint_t Get_CR3_TARGET_COUNT() { uint_t rc; VMCS_READ(CR3_TARGET_COUNT,&rc); return rc; } + +void PrintTrace_CR3_TARGET_COUNT() { PrintTrace("CR3_TARGET_COUNT = %x\n", Get_CR3_TARGET_COUNT()); } + + +void Set_VM_EXIT_CTRLS(uint_t val) { VMCS_WRITE(VM_EXIT_CTRLS,val); } +uint_t Get_VM_EXIT_CTRLS() { uint_t rc; VMCS_READ(VM_EXIT_CTRLS,&rc); return rc; } + +void PrintTrace_VM_EXIT_CTRLS() { PrintTrace("VM_EXIT_CTRLS = %x\n", Get_VM_EXIT_CTRLS()); } + + +void Set_VM_EXIT_MSR_STORE_COUNT(uint_t val) { VMCS_WRITE(VM_EXIT_MSR_STORE_COUNT,val); } +uint_t Get_VM_EXIT_MSR_STORE_COUNT() { uint_t rc; VMCS_READ(VM_EXIT_MSR_STORE_COUNT,&rc); return rc; } + +void PrintTrace_VM_EXIT_MSR_STORE_COUNT() { PrintTrace("VM_EXIT_MSR_STORE_COUNT = %x\n", Get_VM_EXIT_MSR_STORE_COUNT()); } + + +void Set_VM_EXIT_MSR_LOAD_COUNT(uint_t val) { VMCS_WRITE(VM_EXIT_MSR_LOAD_COUNT,val); } +uint_t Get_VM_EXIT_MSR_LOAD_COUNT() { uint_t rc; VMCS_READ(VM_EXIT_MSR_LOAD_COUNT,&rc); return rc; } + +void PrintTrace_VM_EXIT_MSR_LOAD_COUNT() { PrintTrace("VM_EXIT_MSR_LOAD_COUNT = %x\n", Get_VM_EXIT_MSR_LOAD_COUNT()); } + + +void Set_VM_ENTRY_CTRLS(uint_t val) { VMCS_WRITE(VM_ENTRY_CTRLS,val); } +uint_t Get_VM_ENTRY_CTRLS() { uint_t rc; VMCS_READ(VM_ENTRY_CTRLS,&rc); return rc; } + +void PrintTrace_VM_ENTRY_CTRLS() { PrintTrace("VM_ENTRY_CTRLS = %x\n", Get_VM_ENTRY_CTRLS()); } + + +void Set_VM_ENTRY_MSR_LOAD_COUNT(uint_t val) { VMCS_WRITE(VM_ENTRY_MSR_LOAD_COUNT,val); } +uint_t Get_VM_ENTRY_MSR_LOAD_COUNT() { uint_t rc; VMCS_READ(VM_ENTRY_MSR_LOAD_COUNT,&rc); return rc; } + +void PrintTrace_VM_ENTRY_MSR_LOAD_COUNT() { PrintTrace("VM_ENTRY_MSR_LOAD_COUNT = %x\n", Get_VM_ENTRY_MSR_LOAD_COUNT()); } + + +void Set_VM_ENTRY_INT_INFO_FIELD(uint_t val) { VMCS_WRITE(VM_ENTRY_INT_INFO_FIELD,val); } +uint_t Get_VM_ENTRY_INT_INFO_FIELD() { uint_t rc; VMCS_READ(VM_ENTRY_INT_INFO_FIELD,&rc); return rc; } + +void PrintTrace_VM_ENTRY_INT_INFO_FIELD() { PrintTrace("VM_ENTRY_INT_INFO_FIELD = %x\n", Get_VM_ENTRY_INT_INFO_FIELD()); } + + +void Set_VM_ENTRY_EXCEPTION_ERROR(uint_t val) { VMCS_WRITE(VM_ENTRY_EXCEPTION_ERROR,val); } +uint_t Get_VM_ENTRY_EXCEPTION_ERROR() { uint_t rc; VMCS_READ(VM_ENTRY_EXCEPTION_ERROR,&rc); return rc; } + +void PrintTrace_VM_ENTRY_EXCEPTION_ERROR() { PrintTrace("VM_ENTRY_EXCEPTION_ERROR = %x\n", Get_VM_ENTRY_EXCEPTION_ERROR()); } + + +void Set_VM_ENTRY_INSTR_LENGTH(uint_t val) { VMCS_WRITE(VM_ENTRY_INSTR_LENGTH,val); } +uint_t Get_VM_ENTRY_INSTR_LENGTH() { uint_t rc; VMCS_READ(VM_ENTRY_INSTR_LENGTH,&rc); return rc; } + +void PrintTrace_VM_ENTRY_INSTR_LENGTH() { PrintTrace("VM_ENTRY_INSTR_LENGTH = %x\n", Get_VM_ENTRY_INSTR_LENGTH()); } + + +void Set_TPR_THRESHOLD(uint_t val) { VMCS_WRITE(TPR_THRESHOLD,val); } +uint_t Get_TPR_THRESHOLD() { uint_t rc; VMCS_READ(TPR_THRESHOLD,&rc); return rc; } + +void PrintTrace_TPR_THRESHOLD() { PrintTrace("TPR_THRESHOLD = %x\n", Get_TPR_THRESHOLD()); } + + +void Set_VM_INSTR_ERROR(uint_t val) { VMCS_WRITE(VM_INSTR_ERROR,val); } +uint_t Get_VM_INSTR_ERROR() { uint_t rc; VMCS_READ(VM_INSTR_ERROR,&rc); return rc; } + +void PrintTrace_VM_INSTR_ERROR() { PrintTrace("VM_INSTR_ERROR = %x\n", Get_VM_INSTR_ERROR()); } + + +void Set_EXIT_REASON(uint_t val) { VMCS_WRITE(EXIT_REASON,val); } +uint_t Get_EXIT_REASON() { uint_t rc; VMCS_READ(EXIT_REASON,&rc); return rc; } + +void PrintTrace_EXIT_REASON() { PrintTrace("EXIT_REASON = %x\n", Get_EXIT_REASON()); } + + +void Set_VM_EXIT_INT_INFO(uint_t val) { VMCS_WRITE(VM_EXIT_INT_INFO,val); } +uint_t Get_VM_EXIT_INT_INFO() { uint_t rc; VMCS_READ(VM_EXIT_INT_INFO,&rc); return rc; } + +void PrintTrace_VM_EXIT_INT_INFO() { PrintTrace("VM_EXIT_INT_INFO = %x\n", Get_VM_EXIT_INT_INFO()); } + + +void Set_VM_EXIT_INT_ERROR(uint_t val) { VMCS_WRITE(VM_EXIT_INT_ERROR,val); } +uint_t Get_VM_EXIT_INT_ERROR() { uint_t rc; VMCS_READ(VM_EXIT_INT_ERROR,&rc); return rc; } + +void PrintTrace_VM_EXIT_INT_ERROR() { PrintTrace("VM_EXIT_INT_ERROR = %x\n", Get_VM_EXIT_INT_ERROR()); } + + +void Set_IDT_VECTOR_INFO(uint_t val) { VMCS_WRITE(IDT_VECTOR_INFO,val); } +uint_t Get_IDT_VECTOR_INFO() { uint_t rc; VMCS_READ(IDT_VECTOR_INFO,&rc); return rc; } + +void PrintTrace_IDT_VECTOR_INFO() { PrintTrace("IDT_VECTOR_INFO = %x\n", Get_IDT_VECTOR_INFO()); } + + +void Set_IDT_VECTOR_ERROR(uint_t val) { VMCS_WRITE(IDT_VECTOR_ERROR,val); } +uint_t Get_IDT_VECTOR_ERROR() { uint_t rc; VMCS_READ(IDT_VECTOR_ERROR,&rc); return rc; } + +void PrintTrace_IDT_VECTOR_ERROR() { PrintTrace("IDT_VECTOR_ERROR = %x\n", Get_IDT_VECTOR_ERROR()); } + + +void Set_VM_EXIT_INSTR_LENGTH(uint_t val) { VMCS_WRITE(VM_EXIT_INSTR_LENGTH,val); } +uint_t Get_VM_EXIT_INSTR_LENGTH() { uint_t rc; VMCS_READ(VM_EXIT_INSTR_LENGTH,&rc); return rc; } + +void PrintTrace_VM_EXIT_INSTR_LENGTH() { PrintTrace("VM_EXIT_INSTR_LENGTH = %x\n", Get_VM_EXIT_INSTR_LENGTH()); } + + +void Set_VMX_INSTR_INFO(uint_t val) { VMCS_WRITE(VMX_INSTR_INFO,val); } +uint_t Get_VMX_INSTR_INFO() { uint_t rc; VMCS_READ(VMX_INSTR_INFO,&rc); return rc; } + +void PrintTrace_VMX_INSTR_INFO() { PrintTrace("VMX_INSTR_INFO = %x\n", Get_VMX_INSTR_INFO()); } + + +void Set_GUEST_ES_LIMIT(uint_t val) { VMCS_WRITE(GUEST_ES_LIMIT,val); } +uint_t Get_GUEST_ES_LIMIT() { uint_t rc; VMCS_READ(GUEST_ES_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_ES_LIMIT() { PrintTrace("GUEST_ES_LIMIT = %x\n", Get_GUEST_ES_LIMIT()); } + + +void Set_GUEST_CS_LIMIT(uint_t val) { VMCS_WRITE(GUEST_CS_LIMIT,val); } +uint_t Get_GUEST_CS_LIMIT() { uint_t rc; VMCS_READ(GUEST_CS_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_CS_LIMIT() { PrintTrace("GUEST_CS_LIMIT = %x\n", Get_GUEST_CS_LIMIT()); } + + +void Set_GUEST_SS_LIMIT(uint_t val) { VMCS_WRITE(GUEST_SS_LIMIT,val); } +uint_t Get_GUEST_SS_LIMIT() { uint_t rc; VMCS_READ(GUEST_SS_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_SS_LIMIT() { PrintTrace("GUEST_SS_LIMIT = %x\n", Get_GUEST_SS_LIMIT()); } + + +void Set_GUEST_DS_LIMIT(uint_t val) { VMCS_WRITE(GUEST_DS_LIMIT,val); } +uint_t Get_GUEST_DS_LIMIT() { uint_t rc; VMCS_READ(GUEST_DS_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_DS_LIMIT() { PrintTrace("GUEST_DS_LIMIT = %x\n", Get_GUEST_DS_LIMIT()); } + + +void Set_GUEST_FS_LIMIT(uint_t val) { VMCS_WRITE(GUEST_FS_LIMIT,val); } +uint_t Get_GUEST_FS_LIMIT() { uint_t rc; VMCS_READ(GUEST_FS_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_FS_LIMIT() { PrintTrace("GUEST_FS_LIMIT = %x\n", Get_GUEST_FS_LIMIT()); } + + +void Set_GUEST_GS_LIMIT(uint_t val) { VMCS_WRITE(GUEST_GS_LIMIT,val); } +uint_t Get_GUEST_GS_LIMIT() { uint_t rc; VMCS_READ(GUEST_GS_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_GS_LIMIT() { PrintTrace("GUEST_GS_LIMIT = %x\n", Get_GUEST_GS_LIMIT()); } + + +void Set_GUEST_LDTR_LIMIT(uint_t val) { VMCS_WRITE(GUEST_LDTR_LIMIT,val); } +uint_t Get_GUEST_LDTR_LIMIT() { uint_t rc; VMCS_READ(GUEST_LDTR_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_LDTR_LIMIT() { PrintTrace("GUEST_LDTR_LIMIT = %x\n", Get_GUEST_LDTR_LIMIT()); } + + +void Set_GUEST_TR_LIMIT(uint_t val) { VMCS_WRITE(GUEST_TR_LIMIT,val); } +uint_t Get_GUEST_TR_LIMIT() { uint_t rc; VMCS_READ(GUEST_TR_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_TR_LIMIT() { PrintTrace("GUEST_TR_LIMIT = %x\n", Get_GUEST_TR_LIMIT()); } + + +void Set_GUEST_GDTR_LIMIT(uint_t val) { VMCS_WRITE(GUEST_GDTR_LIMIT,val); } +uint_t Get_GUEST_GDTR_LIMIT() { uint_t rc; VMCS_READ(GUEST_GDTR_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_GDTR_LIMIT() { PrintTrace("GUEST_GDTR_LIMIT = %x\n", Get_GUEST_GDTR_LIMIT()); } + + +void Set_GUEST_IDTR_LIMIT(uint_t val) { VMCS_WRITE(GUEST_IDTR_LIMIT,val); } +uint_t Get_GUEST_IDTR_LIMIT() { uint_t rc; VMCS_READ(GUEST_IDTR_LIMIT,&rc); return rc; } + +void PrintTrace_GUEST_IDTR_LIMIT() { PrintTrace("GUEST_IDTR_LIMIT = %x\n", Get_GUEST_IDTR_LIMIT()); } + + +void Set_GUEST_ES_ACCESS(uint_t val) { VMCS_WRITE(GUEST_ES_ACCESS,val); } +uint_t Get_GUEST_ES_ACCESS() { uint_t rc; VMCS_READ(GUEST_ES_ACCESS,&rc); return rc; } + +void PrintTrace_GUEST_ES_ACCESS() { PrintTrace("GUEST_ES_ACCESS = %x\n", Get_GUEST_ES_ACCESS()); } + + +void Set_GUEST_CS_ACCESS(uint_t val) { VMCS_WRITE(GUEST_CS_ACCESS,val); } +uint_t Get_GUEST_CS_ACCESS() { uint_t rc; VMCS_READ(GUEST_CS_ACCESS,&rc); return rc; } + +void PrintTrace_GUEST_CS_ACCESS() { PrintTrace("GUEST_CS_ACCESS = %x\n", Get_GUEST_CS_ACCESS()); } + + +void Set_GUEST_SS_ACCESS(uint_t val) { VMCS_WRITE(GUEST_SS_ACCESS,val); } +uint_t Get_GUEST_SS_ACCESS() { uint_t rc; VMCS_READ(GUEST_SS_ACCESS,&rc); return rc; } + +void PrintTrace_GUEST_SS_ACCESS() { PrintTrace("GUEST_SS_ACCESS = %x\n", Get_GUEST_SS_ACCESS()); } + + +void Set_GUEST_DS_ACCESS(uint_t val) { VMCS_WRITE(GUEST_DS_ACCESS,val); } +uint_t Get_GUEST_DS_ACCESS() { uint_t rc; VMCS_READ(GUEST_DS_ACCESS,&rc); return rc; } + +void PrintTrace_GUEST_DS_ACCESS() { PrintTrace("GUEST_DS_ACCESS = %x\n", Get_GUEST_DS_ACCESS()); } + + +void Set_GUEST_FS_ACCESS(uint_t val) { VMCS_WRITE(GUEST_FS_ACCESS,val); } +uint_t Get_GUEST_FS_ACCESS() { uint_t rc; VMCS_READ(GUEST_FS_ACCESS,&rc); return rc; } + +void PrintTrace_GUEST_FS_ACCESS() { PrintTrace("GUEST_FS_ACCESS = %x\n", Get_GUEST_FS_ACCESS()); } + + +void Set_GUEST_GS_ACCESS(uint_t val) { VMCS_WRITE(GUEST_GS_ACCESS,val); } +uint_t Get_GUEST_GS_ACCESS() { uint_t rc; VMCS_READ(GUEST_GS_ACCESS,&rc); return rc; } + +void PrintTrace_GUEST_GS_ACCESS() { PrintTrace("GUEST_GS_ACCESS = %x\n", Get_GUEST_GS_ACCESS()); } + + +void Set_GUEST_LDTR_ACCESS(uint_t val) { VMCS_WRITE(GUEST_LDTR_ACCESS,val); } +uint_t Get_GUEST_LDTR_ACCESS() { uint_t rc; VMCS_READ(GUEST_LDTR_ACCESS,&rc); return rc; } + +void PrintTrace_GUEST_LDTR_ACCESS() { PrintTrace("GUEST_LDTR_ACCESS = %x\n", Get_GUEST_LDTR_ACCESS()); } + + +void Set_GUEST_TR_ACCESS(uint_t val) { VMCS_WRITE(GUEST_TR_ACCESS,val); } +uint_t Get_GUEST_TR_ACCESS() { uint_t rc; VMCS_READ(GUEST_TR_ACCESS,&rc); return rc; } + +void PrintTrace_GUEST_TR_ACCESS() { PrintTrace("GUEST_TR_ACCESS = %x\n", Get_GUEST_TR_ACCESS()); } + + +void Set_GUEST_INT_STATE(uint_t val) { VMCS_WRITE(GUEST_INT_STATE,val); } +uint_t Get_GUEST_INT_STATE() { uint_t rc; VMCS_READ(GUEST_INT_STATE,&rc); return rc; } + +void PrintTrace_GUEST_INT_STATE() { PrintTrace("GUEST_INT_STATE = %x\n", Get_GUEST_INT_STATE()); } + + +void Set_GUEST_ACTIVITY_STATE(uint_t val) { VMCS_WRITE(GUEST_ACTIVITY_STATE,val); } +uint_t Get_GUEST_ACTIVITY_STATE() { uint_t rc; VMCS_READ(GUEST_ACTIVITY_STATE,&rc); return rc; } + +void PrintTrace_GUEST_ACTIVITY_STATE() { PrintTrace("GUEST_ACTIVITY_STATE = %x\n", Get_GUEST_ACTIVITY_STATE()); } + + +void Set_GUEST_SMBASE(uint_t val) { VMCS_WRITE(GUEST_SMBASE,val); } +uint_t Get_GUEST_SMBASE() { uint_t rc; VMCS_READ(GUEST_SMBASE,&rc); return rc; } + +void PrintTrace_GUEST_SMBASE() { PrintTrace("GUEST_SMBASE = %x\n", Get_GUEST_SMBASE()); } + + +void Set_GUEST_IA32_SYSENTER_CS(uint_t val) { VMCS_WRITE(GUEST_IA32_SYSENTER_CS,val); } +uint_t Get_GUEST_IA32_SYSENTER_CS() { uint_t rc; VMCS_READ(GUEST_IA32_SYSENTER_CS,&rc); return rc; } + +void PrintTrace_GUEST_IA32_SYSENTER_CS() { PrintTrace("GUEST_IA32_SYSENTER_CS = %x\n", Get_GUEST_IA32_SYSENTER_CS()); } + + +void Set_HOST_IA32_SYSENTER_CS(uint_t val) { VMCS_WRITE(HOST_IA32_SYSENTER_CS,val); } +uint_t Get_HOST_IA32_SYSENTER_CS() { uint_t rc; VMCS_READ(HOST_IA32_SYSENTER_CS,&rc); return rc; } + +void PrintTrace_HOST_IA32_SYSENTER_CS() { PrintTrace("HOST_IA32_SYSENTER_CS = %x\n", Get_HOST_IA32_SYSENTER_CS()); } + + +void Set_CR0_GUEST_HOST_MASK(uint_t val) { VMCS_WRITE(CR0_GUEST_HOST_MASK,val); } +uint_t Get_CR0_GUEST_HOST_MASK() { uint_t rc; VMCS_READ(CR0_GUEST_HOST_MASK,&rc); return rc; } + +void PrintTrace_CR0_GUEST_HOST_MASK() { PrintTrace("CR0_GUEST_HOST_MASK = %x\n", Get_CR0_GUEST_HOST_MASK()); } + + +void Set_CR4_GUEST_HOST_MASK(uint_t val) { VMCS_WRITE(CR4_GUEST_HOST_MASK,val); } +uint_t Get_CR4_GUEST_HOST_MASK() { uint_t rc; VMCS_READ(CR4_GUEST_HOST_MASK,&rc); return rc; } + +void PrintTrace_CR4_GUEST_HOST_MASK() { PrintTrace("CR4_GUEST_HOST_MASK = %x\n", Get_CR4_GUEST_HOST_MASK()); } + + +void Set_CR0_READ_SHADOW(uint_t val) { VMCS_WRITE(CR0_READ_SHADOW,val); } +uint_t Get_CR0_READ_SHADOW() { uint_t rc; VMCS_READ(CR0_READ_SHADOW,&rc); return rc; } + +void PrintTrace_CR0_READ_SHADOW() { PrintTrace("CR0_READ_SHADOW = %x\n", Get_CR0_READ_SHADOW()); } + + +void Set_CR4_READ_SHADOW(uint_t val) { VMCS_WRITE(CR4_READ_SHADOW,val); } +uint_t Get_CR4_READ_SHADOW() { uint_t rc; VMCS_READ(CR4_READ_SHADOW,&rc); return rc; } + +void PrintTrace_CR4_READ_SHADOW() { PrintTrace("CR4_READ_SHADOW = %x\n", Get_CR4_READ_SHADOW()); } + + +void Set_CR3_TARGET_VALUE_0(uint_t val) { VMCS_WRITE(CR3_TARGET_VALUE_0,val); } +uint_t Get_CR3_TARGET_VALUE_0() { uint_t rc; VMCS_READ(CR3_TARGET_VALUE_0,&rc); return rc; } + +void PrintTrace_CR3_TARGET_VALUE_0() { PrintTrace("CR3_TARGET_VALUE_0 = %x\n", Get_CR3_TARGET_VALUE_0()); } + + +void Set_CR3_TARGET_VALUE_1(uint_t val) { VMCS_WRITE(CR3_TARGET_VALUE_1,val); } +uint_t Get_CR3_TARGET_VALUE_1() { uint_t rc; VMCS_READ(CR3_TARGET_VALUE_1,&rc); return rc; } + +void PrintTrace_CR3_TARGET_VALUE_1() { PrintTrace("CR3_TARGET_VALUE_1 = %x\n", Get_CR3_TARGET_VALUE_1()); } + + +void Set_CR3_TARGET_VALUE_2(uint_t val) { VMCS_WRITE(CR3_TARGET_VALUE_2,val); } +uint_t Get_CR3_TARGET_VALUE_2() { uint_t rc; VMCS_READ(CR3_TARGET_VALUE_2,&rc); return rc; } + +void PrintTrace_CR3_TARGET_VALUE_2() { PrintTrace("CR3_TARGET_VALUE_2 = %x\n", Get_CR3_TARGET_VALUE_2()); } + + +void Set_CR3_TARGET_VALUE_3(uint_t val) { VMCS_WRITE(CR3_TARGET_VALUE_3,val); } +uint_t Get_CR3_TARGET_VALUE_3() { uint_t rc; VMCS_READ(CR3_TARGET_VALUE_3,&rc); return rc; } + +void PrintTrace_CR3_TARGET_VALUE_3() { PrintTrace("CR3_TARGET_VALUE_3 = %x\n", Get_CR3_TARGET_VALUE_3()); } + + +void Set_EXIT_QUALIFICATION(uint_t val) { VMCS_WRITE(EXIT_QUALIFICATION,val); } +uint_t Get_EXIT_QUALIFICATION() { uint_t rc; VMCS_READ(EXIT_QUALIFICATION,&rc); return rc; } + +void PrintTrace_EXIT_QUALIFICATION() { PrintTrace("EXIT_QUALIFICATION = %x\n", Get_EXIT_QUALIFICATION()); } + + +void Set_IO_RCX(uint_t val) { VMCS_WRITE(IO_RCX,val); } +uint_t Get_IO_RCX() { uint_t rc; VMCS_READ(IO_RCX,&rc); return rc; } + +void PrintTrace_IO_RCX() { PrintTrace("IO_RCX = %x\n", Get_IO_RCX()); } + + +void Set_IO_RSI(uint_t val) { VMCS_WRITE(IO_RSI,val); } +uint_t Get_IO_RSI() { uint_t rc; VMCS_READ(IO_RSI,&rc); return rc; } + +void PrintTrace_IO_RSI() { PrintTrace("IO_RSI = %x\n", Get_IO_RSI()); } + + +void Set_IO_RDI(uint_t val) { VMCS_WRITE(IO_RDI,val); } +uint_t Get_IO_RDI() { uint_t rc; VMCS_READ(IO_RDI,&rc); return rc; } + +void PrintTrace_IO_RDI() { PrintTrace("IO_RDI = %x\n", Get_IO_RDI()); } + + +void Set_IO_RIP(uint_t val) { VMCS_WRITE(IO_RIP,val); } +uint_t Get_IO_RIP() { uint_t rc; VMCS_READ(IO_RIP,&rc); return rc; } + +void PrintTrace_IO_RIP() { PrintTrace("IO_RIP = %x\n", Get_IO_RIP()); } + + +void Set_GUEST_LINEAR_ADDR(uint_t val) { VMCS_WRITE(GUEST_LINEAR_ADDR,val); } +uint_t Get_GUEST_LINEAR_ADDR() { uint_t rc; VMCS_READ(GUEST_LINEAR_ADDR,&rc); return rc; } + +void PrintTrace_GUEST_LINEAR_ADDR() { PrintTrace("GUEST_LINEAR_ADDR = %x\n", Get_GUEST_LINEAR_ADDR()); } + + +void Set_GUEST_CR0(uint_t val) { VMCS_WRITE(GUEST_CR0,val); } +uint_t Get_GUEST_CR0() { uint_t rc; VMCS_READ(GUEST_CR0,&rc); return rc; } + +void PrintTrace_GUEST_CR0() { PrintTrace("GUEST_CR0 = %x\n", Get_GUEST_CR0()); } + + +void Set_GUEST_CR3(uint_t val) { VMCS_WRITE(GUEST_CR3,val); } +uint_t Get_GUEST_CR3() { uint_t rc; VMCS_READ(GUEST_CR3,&rc); return rc; } + +void PrintTrace_GUEST_CR3() { PrintTrace("GUEST_CR3 = %x\n", Get_GUEST_CR3()); } + + +void Set_GUEST_CR4(uint_t val) { VMCS_WRITE(GUEST_CR4,val); } +uint_t Get_GUEST_CR4() { uint_t rc; VMCS_READ(GUEST_CR4,&rc); return rc; } + +void PrintTrace_GUEST_CR4() { PrintTrace("GUEST_CR4 = %x\n", Get_GUEST_CR4()); } + + +void Set_GUEST_ES_BASE(uint_t val) { VMCS_WRITE(GUEST_ES_BASE,val); } +uint_t Get_GUEST_ES_BASE() { uint_t rc; VMCS_READ(GUEST_ES_BASE,&rc); return rc; } + +void PrintTrace_GUEST_ES_BASE() { PrintTrace("GUEST_ES_BASE = %x\n", Get_GUEST_ES_BASE()); } + + +void Set_GUEST_CS_BASE(uint_t val) { VMCS_WRITE(GUEST_CS_BASE,val); } +uint_t Get_GUEST_CS_BASE() { uint_t rc; VMCS_READ(GUEST_CS_BASE,&rc); return rc; } + +void PrintTrace_GUEST_CS_BASE() { PrintTrace("GUEST_CS_BASE = %x\n", Get_GUEST_CS_BASE()); } + + +void Set_GUEST_SS_BASE(uint_t val) { VMCS_WRITE(GUEST_SS_BASE,val); } +uint_t Get_GUEST_SS_BASE() { uint_t rc; VMCS_READ(GUEST_SS_BASE,&rc); return rc; } + +void PrintTrace_GUEST_SS_BASE() { PrintTrace("GUEST_SS_BASE = %x\n", Get_GUEST_SS_BASE()); } + + +void Set_GUEST_DS_BASE(uint_t val) { VMCS_WRITE(GUEST_DS_BASE,val); } +uint_t Get_GUEST_DS_BASE() { uint_t rc; VMCS_READ(GUEST_DS_BASE,&rc); return rc; } + +void PrintTrace_GUEST_DS_BASE() { PrintTrace("GUEST_DS_BASE = %x\n", Get_GUEST_DS_BASE()); } + + +void Set_GUEST_FS_BASE(uint_t val) { VMCS_WRITE(GUEST_FS_BASE,val); } +uint_t Get_GUEST_FS_BASE() { uint_t rc; VMCS_READ(GUEST_FS_BASE,&rc); return rc; } + +void PrintTrace_GUEST_FS_BASE() { PrintTrace("GUEST_FS_BASE = %x\n", Get_GUEST_FS_BASE()); } + + +void Set_GUEST_GS_BASE(uint_t val) { VMCS_WRITE(GUEST_GS_BASE,val); } +uint_t Get_GUEST_GS_BASE() { uint_t rc; VMCS_READ(GUEST_GS_BASE,&rc); return rc; } + +void PrintTrace_GUEST_GS_BASE() { PrintTrace("GUEST_GS_BASE = %x\n", Get_GUEST_GS_BASE()); } + + +void Set_GUEST_LDTR_BASE(uint_t val) { VMCS_WRITE(GUEST_LDTR_BASE,val); } +uint_t Get_GUEST_LDTR_BASE() { uint_t rc; VMCS_READ(GUEST_LDTR_BASE,&rc); return rc; } + +void PrintTrace_GUEST_LDTR_BASE() { PrintTrace("GUEST_LDTR_BASE = %x\n", Get_GUEST_LDTR_BASE()); } + + +void Set_GUEST_TR_BASE(uint_t val) { VMCS_WRITE(GUEST_TR_BASE,val); } +uint_t Get_GUEST_TR_BASE() { uint_t rc; VMCS_READ(GUEST_TR_BASE,&rc); return rc; } + +void PrintTrace_GUEST_TR_BASE() { PrintTrace("GUEST_TR_BASE = %x\n", Get_GUEST_TR_BASE()); } + + +void Set_GUEST_GDTR_BASE(uint_t val) { VMCS_WRITE(GUEST_GDTR_BASE,val); } +uint_t Get_GUEST_GDTR_BASE() { uint_t rc; VMCS_READ(GUEST_GDTR_BASE,&rc); return rc; } + +void PrintTrace_GUEST_GDTR_BASE() { PrintTrace("GUEST_GDTR_BASE = %x\n", Get_GUEST_GDTR_BASE()); } + + +void Set_GUEST_IDTR_BASE(uint_t val) { VMCS_WRITE(GUEST_IDTR_BASE,val); } +uint_t Get_GUEST_IDTR_BASE() { uint_t rc; VMCS_READ(GUEST_IDTR_BASE,&rc); return rc; } + +void PrintTrace_GUEST_IDTR_BASE() { PrintTrace("GUEST_IDTR_BASE = %x\n", Get_GUEST_IDTR_BASE()); } + + +void Set_GUEST_DR7(uint_t val) { VMCS_WRITE(GUEST_DR7,val); } +uint_t Get_GUEST_DR7() { uint_t rc; VMCS_READ(GUEST_DR7,&rc); return rc; } + +void PrintTrace_GUEST_DR7() { PrintTrace("GUEST_DR7 = %x\n", Get_GUEST_DR7()); } + + +void Set_GUEST_RSP(uint_t val) { VMCS_WRITE(GUEST_RSP,val); } +uint_t Get_GUEST_RSP() { uint_t rc; VMCS_READ(GUEST_RSP,&rc); return rc; } + +void PrintTrace_GUEST_RSP() { PrintTrace("GUEST_RSP = %x\n", Get_GUEST_RSP()); } + + +void Set_GUEST_RIP(uint_t val) { VMCS_WRITE(GUEST_RIP,val); } +uint_t Get_GUEST_RIP() { uint_t rc; VMCS_READ(GUEST_RIP,&rc); return rc; } + +void PrintTrace_GUEST_RIP() { PrintTrace("GUEST_RIP = %x\n", Get_GUEST_RIP()); } + + +void Set_GUEST_RFLAGS(uint_t val) { VMCS_WRITE(GUEST_RFLAGS,val); } +uint_t Get_GUEST_RFLAGS() { uint_t rc; VMCS_READ(GUEST_RFLAGS,&rc); return rc; } + +void PrintTrace_GUEST_RFLAGS() { PrintTrace("GUEST_RFLAGS = %x\n", Get_GUEST_RFLAGS()); } + + +void Set_GUEST_PENDING_DEBUG_EXCS(uint_t val) { VMCS_WRITE(GUEST_PENDING_DEBUG_EXCS,val); } +uint_t Get_GUEST_PENDING_DEBUG_EXCS() { uint_t rc; VMCS_READ(GUEST_PENDING_DEBUG_EXCS,&rc); return rc; } + +void PrintTrace_GUEST_PENDING_DEBUG_EXCS() { PrintTrace("GUEST_PENDING_DEBUG_EXCS = %x\n", Get_GUEST_PENDING_DEBUG_EXCS()); } + + +void Set_GUEST_IA32_SYSENTER_ESP(uint_t val) { VMCS_WRITE(GUEST_IA32_SYSENTER_ESP,val); } +uint_t Get_GUEST_IA32_SYSENTER_ESP() { uint_t rc; VMCS_READ(GUEST_IA32_SYSENTER_ESP,&rc); return rc; } + +void PrintTrace_GUEST_IA32_SYSENTER_ESP() { PrintTrace("GUEST_IA32_SYSENTER_ESP = %x\n", Get_GUEST_IA32_SYSENTER_ESP()); } + + +void Set_GUEST_IA32_SYSENTER_EIP(uint_t val) { VMCS_WRITE(GUEST_IA32_SYSENTER_EIP,val); } +uint_t Get_GUEST_IA32_SYSENTER_EIP() { uint_t rc; VMCS_READ(GUEST_IA32_SYSENTER_EIP,&rc); return rc; } + +void PrintTrace_GUEST_IA32_SYSENTER_EIP() { PrintTrace("GUEST_IA32_SYSENTER_EIP = %x\n", Get_GUEST_IA32_SYSENTER_EIP()); } + + +void Set_HOST_CR0(uint_t val) { VMCS_WRITE(HOST_CR0,val); } +uint_t Get_HOST_CR0() { uint_t rc; VMCS_READ(HOST_CR0,&rc); return rc; } + +void PrintTrace_HOST_CR0() { PrintTrace("HOST_CR0 = %x\n", Get_HOST_CR0()); } + + +void Set_HOST_CR3(uint_t val) { VMCS_WRITE(HOST_CR3,val); } +uint_t Get_HOST_CR3() { uint_t rc; VMCS_READ(HOST_CR3,&rc); return rc; } + +void PrintTrace_HOST_CR3() { PrintTrace("HOST_CR3 = %x\n", Get_HOST_CR3()); } + + +void Set_HOST_CR4(uint_t val) { VMCS_WRITE(HOST_CR4,val); } +uint_t Get_HOST_CR4() { uint_t rc; VMCS_READ(HOST_CR4,&rc); return rc; } + +void PrintTrace_HOST_CR4() { PrintTrace("HOST_CR4 = %x\n", Get_HOST_CR4()); } + + +void Set_HOST_FS_BASE(uint_t val) { VMCS_WRITE(HOST_FS_BASE,val); } +uint_t Get_HOST_FS_BASE() { uint_t rc; VMCS_READ(HOST_FS_BASE,&rc); return rc; } + +void PrintTrace_HOST_FS_BASE() { PrintTrace("HOST_FS_BASE = %x\n", Get_HOST_FS_BASE()); } + + +void Set_HOST_GS_BASE(uint_t val) { VMCS_WRITE(HOST_GS_BASE,val); } +uint_t Get_HOST_GS_BASE() { uint_t rc; VMCS_READ(HOST_GS_BASE,&rc); return rc; } + +void PrintTrace_HOST_GS_BASE() { PrintTrace("HOST_GS_BASE = %x\n", Get_HOST_GS_BASE()); } + + +void Set_HOST_TR_BASE(uint_t val) { VMCS_WRITE(HOST_TR_BASE,val); } +uint_t Get_HOST_TR_BASE() { uint_t rc; VMCS_READ(HOST_TR_BASE,&rc); return rc; } + +void PrintTrace_HOST_TR_BASE() { PrintTrace("HOST_TR_BASE = %x\n", Get_HOST_TR_BASE()); } + + +void Set_HOST_GDTR_BASE(uint_t val) { VMCS_WRITE(HOST_GDTR_BASE,val); } +uint_t Get_HOST_GDTR_BASE() { uint_t rc; VMCS_READ(HOST_GDTR_BASE,&rc); return rc; } + +void PrintTrace_HOST_GDTR_BASE() { PrintTrace("HOST_GDTR_BASE = %x\n", Get_HOST_GDTR_BASE()); } + + +void Set_HOST_IDTR_BASE(uint_t val) { VMCS_WRITE(HOST_IDTR_BASE,val); } +uint_t Get_HOST_IDTR_BASE() { uint_t rc; VMCS_READ(HOST_IDTR_BASE,&rc); return rc; } + +void PrintTrace_HOST_IDTR_BASE() { PrintTrace("HOST_IDTR_BASE = %x\n", Get_HOST_IDTR_BASE()); } + + +void Set_HOST_IA32_SYSENTER_ESP(uint_t val) { VMCS_WRITE(HOST_IA32_SYSENTER_ESP,val); } +uint_t Get_HOST_IA32_SYSENTER_ESP() { uint_t rc; VMCS_READ(HOST_IA32_SYSENTER_ESP,&rc); return rc; } + +void PrintTrace_HOST_IA32_SYSENTER_ESP() { PrintTrace("HOST_IA32_SYSENTER_ESP = %x\n", Get_HOST_IA32_SYSENTER_ESP()); } + + +void Set_HOST_IA32_SYSENTER_EIP(uint_t val) { VMCS_WRITE(HOST_IA32_SYSENTER_EIP,val); } +uint_t Get_HOST_IA32_SYSENTER_EIP() { uint_t rc; VMCS_READ(HOST_IA32_SYSENTER_EIP,&rc); return rc; } + +void PrintTrace_HOST_IA32_SYSENTER_EIP() { PrintTrace("HOST_IA32_SYSENTER_EIP = %x\n", Get_HOST_IA32_SYSENTER_EIP()); } + + +void Set_HOST_RSP(uint_t val) { VMCS_WRITE(HOST_RSP,val); } +uint_t Get_HOST_RSP() { uint_t rc; VMCS_READ(HOST_RSP,&rc); return rc; } + +void PrintTrace_HOST_RSP() { PrintTrace("HOST_RSP = %x\n", Get_HOST_RSP()); } + + +void Set_HOST_RIP(uint_t val) { VMCS_WRITE(HOST_RIP,val); } +uint_t Get_HOST_RIP() { uint_t rc; VMCS_READ(HOST_RIP,&rc); return rc; } + +void PrintTrace_HOST_RIP() { PrintTrace("HOST_RIP = %x\n", Get_HOST_RIP()); } + +void PrintTrace_VMCS_ALL() { + + PrintTrace("==>Guest State Area\n"); + PrintTrace("==>==> Guest Register State\n"); + PrintTrace_GUEST_CR0(); + PrintTrace_GUEST_CR3(); + PrintTrace_GUEST_CR4(); + PrintTrace_GUEST_DR7(); + PrintTrace_GUEST_RSP(); + PrintTrace_GUEST_RIP(); + PrintTrace_GUEST_RFLAGS(); + PrintTrace_VMCS_GUEST_CS_SELECTOR(); + PrintTrace_VMCS_GUEST_SS_SELECTOR(); + PrintTrace_VMCS_GUEST_DS_SELECTOR(); + PrintTrace_VMCS_GUEST_ES_SELECTOR(); + PrintTrace_VMCS_GUEST_FS_SELECTOR(); + PrintTrace_VMCS_GUEST_GS_SELECTOR(); + PrintTrace_VMCS_GUEST_LDTR_SELECTOR(); + PrintTrace_VMCS_GUEST_TR_SELECTOR(); + PrintTrace_GUEST_CS_BASE(); + PrintTrace_GUEST_SS_BASE(); + PrintTrace_GUEST_DS_BASE(); + PrintTrace_GUEST_ES_BASE(); + PrintTrace_GUEST_FS_BASE(); + PrintTrace_GUEST_GS_BASE(); + PrintTrace_GUEST_LDTR_BASE(); + PrintTrace_GUEST_TR_BASE(); + PrintTrace_GUEST_CS_LIMIT(); + PrintTrace_GUEST_SS_LIMIT(); + PrintTrace_GUEST_DS_LIMIT(); + PrintTrace_GUEST_ES_LIMIT(); + PrintTrace_GUEST_FS_LIMIT(); + PrintTrace_GUEST_GS_LIMIT(); + PrintTrace_GUEST_LDTR_LIMIT(); + PrintTrace_GUEST_TR_LIMIT(); + PrintTrace_GUEST_ES_ACCESS(); + PrintTrace_GUEST_CS_ACCESS(); + PrintTrace_GUEST_SS_ACCESS(); + PrintTrace_GUEST_DS_ACCESS(); + PrintTrace_GUEST_FS_ACCESS(); + PrintTrace_GUEST_GS_ACCESS(); + PrintTrace_GUEST_LDTR_ACCESS(); + PrintTrace_GUEST_TR_ACCESS(); + PrintTrace_GUEST_GDTR_BASE(); + PrintTrace_GUEST_IDTR_BASE(); + PrintTrace_GUEST_GDTR_LIMIT(); + PrintTrace_GUEST_IDTR_LIMIT(); + PrintTrace_GUEST_IA32_DEBUGCTL(); + PrintTrace_GUEST_IA32_DEBUGCTL_HIGH(); + PrintTrace_GUEST_IA32_SYSENTER_CS(); + PrintTrace_GUEST_IA32_SYSENTER_ESP(); + PrintTrace_GUEST_IA32_SYSENTER_EIP(); + PrintTrace_GUEST_SMBASE(); + + PrintTrace("==>==> Guest Non-Register State\n"); + PrintTrace_GUEST_ACTIVITY_STATE(); + PrintTrace_GUEST_INT_STATE(); + PrintTrace_GUEST_PENDING_DEBUG_EXCS(); + PrintTrace_VMCS_LINK_PTR(); + PrintTrace_VMCS_LINK_PTR_HIGH(); + + PrintTrace("\n==> Host State Area\n"); + PrintTrace_HOST_CR0(); + PrintTrace_HOST_CR3(); + PrintTrace_HOST_CR4(); + PrintTrace_HOST_RSP(); + PrintTrace_HOST_RIP(); + PrintTrace_VMCS_HOST_CS_SELECTOR(); + PrintTrace_VMCS_HOST_SS_SELECTOR(); + PrintTrace_VMCS_HOST_DS_SELECTOR(); + PrintTrace_VMCS_HOST_ES_SELECTOR(); + PrintTrace_VMCS_HOST_FS_SELECTOR(); + PrintTrace_VMCS_HOST_GS_SELECTOR(); + PrintTrace_VMCS_HOST_TR_SELECTOR(); + PrintTrace_HOST_FS_BASE(); + PrintTrace_HOST_GS_BASE(); + PrintTrace_HOST_TR_BASE(); + PrintTrace_HOST_GDTR_BASE(); + PrintTrace_HOST_IDTR_BASE(); + PrintTrace_HOST_IA32_SYSENTER_CS(); + PrintTrace_HOST_IA32_SYSENTER_ESP(); + PrintTrace_HOST_IA32_SYSENTER_EIP(); + + + PrintTrace("\n==> VM-Execution Controls:\n"); + PrintTrace_PIN_VM_EXEC_CTRLS(); + PrintTrace_PROC_VM_EXEC_CTRLS(); + PrintTrace_EXCEPTION_BITMAP(); + PrintTrace_PAGE_FAULT_ERROR_MASK(); + PrintTrace_PAGE_FAULT_ERROR_MATCH(); + PrintTrace_IO_BITMAP_A_ADDR(); + PrintTrace_IO_BITMAP_A_ADDR_HIGH(); + PrintTrace_IO_BITMAP_B_ADDR(); + PrintTrace_IO_BITMAP_B_ADDR_HIGH(); + PrintTrace_TSC_OFFSET(); + PrintTrace_TSC_OFFSET_HIGH(); + PrintTrace_CR0_GUEST_HOST_MASK(); + PrintTrace_CR0_READ_SHADOW(); + PrintTrace_CR4_GUEST_HOST_MASK(); + PrintTrace_CR4_READ_SHADOW(); + PrintTrace_CR3_TARGET_COUNT(); + PrintTrace_CR3_TARGET_VALUE_0(); + PrintTrace_CR3_TARGET_VALUE_1(); + PrintTrace_CR3_TARGET_VALUE_2(); + PrintTrace_CR3_TARGET_VALUE_3(); + PrintTrace_VIRT_APIC_PAGE_ADDR(); + PrintTrace_VIRT_APIC_PAGE_ADDR_HIGH(); + PrintTrace_TPR_THRESHOLD(); + PrintTrace_MSR_BITMAPS(); + PrintTrace_MSR_BITMAPS_HIGH(); + PrintTrace_VMCS_EXEC_PTR(); + PrintTrace_VMCS_EXEC_PTR_HIGH(); + + PrintTrace("\n==> VM Exit Controls\n"); + PrintTrace_VM_EXIT_CTRLS(); + PrintTrace_VM_EXIT_MSR_STORE_COUNT(); + PrintTrace_VM_EXIT_MSR_STORE_ADDR(); + PrintTrace_VM_EXIT_MSR_STORE_ADDR_HIGH(); + PrintTrace_VM_EXIT_MSR_LOAD_COUNT(); + PrintTrace_VM_EXIT_MSR_LOAD_ADDR(); + PrintTrace_VM_EXIT_MSR_LOAD_ADDR_HIGH(); + + PrintTrace("\n==> VM Entry Controls\n"); + PrintTrace_VM_ENTRY_CTRLS(); + PrintTrace_VM_ENTRY_MSR_LOAD_COUNT(); + PrintTrace_VM_ENTRY_MSR_LOAD_ADDR(); + PrintTrace_VM_ENTRY_MSR_LOAD_ADDR_HIGH(); + PrintTrace_VM_ENTRY_INT_INFO_FIELD(); + PrintTrace_VM_ENTRY_EXCEPTION_ERROR(); + PrintTrace_VM_ENTRY_INSTR_LENGTH(); + + PrintTrace("\n==> VM Exit Info\n"); + PrintTrace_EXIT_REASON(); + PrintTrace_EXIT_QUALIFICATION(); + PrintTrace_VM_EXIT_INT_INFO(); + PrintTrace_VM_EXIT_INT_ERROR(); + PrintTrace_IDT_VECTOR_INFO(); + PrintTrace_IDT_VECTOR_ERROR(); + PrintTrace_VM_EXIT_INSTR_LENGTH(); + PrintTrace_GUEST_LINEAR_ADDR(); + PrintTrace_VMX_INSTR_INFO(); + PrintTrace_IO_RCX(); + PrintTrace_IO_RSI(); + PrintTrace_IO_RDI(); + PrintTrace_IO_RIP(); + PrintTrace_VM_INSTR_ERROR(); + PrintTrace("\n"); +} diff --git a/palacios/src/palacios/vmm.c b/palacios/src/palacios/vmm.c new file mode 100644 index 0000000..5a3eb04 --- /dev/null +++ b/palacios/src/palacios/vmm.c @@ -0,0 +1,36 @@ +#include +#include +#include + + +uint_t vmm_cpu_type; + + + + +struct vmm_os_hooks * os_hooks = NULL; + + + +void Init_VMM(struct vmm_os_hooks * hooks, struct vmm_ctrl_ops * vmm_ops) { + vmm_cpu_type = VMM_INVALID_CPU; + + os_hooks = hooks; + + + + if (is_svm_capable()) { + vmm_cpu_type = VMM_SVM_CPU; + PrintDebug("Machine is SVM Capable\n"); + + Init_SVM(vmm_ops); + + /* + } else if (is_vmx_capable()) { + vmm_cpu_type = VMM_VMX_CPU; + PrintDebug("Machine is VMX Capable\n"); + //Init_VMX();*/ + } else { + PrintDebug("CPU has no virtualization Extensions\n"); + } +} diff --git a/palacios/src/palacios/vmm_debug.c b/palacios/src/palacios/vmm_debug.c new file mode 100644 index 0000000..d5520c3 --- /dev/null +++ b/palacios/src/palacios/vmm_debug.c @@ -0,0 +1,34 @@ +#include +#include + + +void PrintDebugHex(unsigned char x) +{ + unsigned char z; + + z = (x>>4) & 0xf ; + PrintDebug("%x", z); + z = x & 0xf; + PrintDebug("%x", z); +} + +void PrintDebugMemDump(unsigned char *start, int n) +{ + int i, j; + + for (i=0;i=32) && (start[j]<=126)) ? start[j] : '.'); + } + PrintDebug("\n"); + } +} diff --git a/palacios/src/palacios/vmm_io.c b/palacios/src/palacios/vmm_io.c new file mode 100644 index 0000000..4f58d04 --- /dev/null +++ b/palacios/src/palacios/vmm_io.c @@ -0,0 +1,91 @@ +#include +#include +#include + +extern struct vmm_os_hooks * os_hooks; + +void init_vmm_io_map(vmm_io_map_t * io_map) { + io_map->num_ports = 0; + io_map->head = NULL; +} + + + +void add_io_hook(vmm_io_map_t * io_map, vmm_io_hook_t * io_hook) { + vmm_io_hook_t * tmp_hook = io_map->head; + + if (!tmp_hook) { + io_map->head = io_hook; + io_map->num_ports = 1; + return; + } else { + while ((tmp_hook->next) && + (tmp_hook->next->port <= io_hook->port)) { + tmp_hook = tmp_hook->next; + } + + if (tmp_hook->port == io_hook->port) { + tmp_hook->read = io_hook->read; + tmp_hook->write = io_hook->write; + + VMMFree(io_hook); + return; + } else if (!tmp_hook->next) { + tmp_hook->next = io_hook; + io_hook->prev = tmp_hook; + io_map->num_ports++; + + return; + } else { + io_hook->next = tmp_hook->next; + io_hook->prev = tmp_hook; + + tmp_hook->next = io_hook; + if (io_hook->next) { + io_hook->next->prev = io_hook; + } + + io_map->num_ports++; + return; + } + } +} + +void hook_io_port(vmm_io_map_t * io_map, uint_t port, + int (*read)(ushort_t port, void * dst, uint_t length), + int (*write)(ushort_t port, void * src, uint_t length)) { + vmm_io_hook_t * io_hook = os_hooks->malloc(sizeof(vmm_io_hook_t)); + + io_hook->port = port; + io_hook->read = read; + io_hook->write = write; + io_hook->next = NULL; + io_hook->prev = NULL; + + add_io_hook(io_map, io_hook); + + return; +} + + +vmm_io_hook_t * get_io_hook(vmm_io_map_t * io_map, uint_t port) { + vmm_io_hook_t * tmp_hook; + FOREACH_IO_HOOK(*io_map, tmp_hook) { + if (tmp_hook->port == port) { + return tmp_hook; + } + } + return NULL; +} + + + +void PrintDebugIOMap(vmm_io_map_t * io_map) { + vmm_io_hook_t * iter = io_map->head; + + PrintDebug("VMM IO Map (Entries=%d)\n", io_map->num_ports); + + while (iter) { + PrintDebug("IO Port: %hu (Read=%x) (Write=%x)\n", iter->port, iter->read, iter->write); + } +} diff --git a/palacios/src/palacios/vmm_mem.c b/palacios/src/palacios/vmm_mem.c new file mode 100644 index 0000000..013ea0b --- /dev/null +++ b/palacios/src/palacios/vmm_mem.c @@ -0,0 +1,368 @@ +#include +#include +#include + +extern struct vmm_os_hooks * os_hooks; + + +void init_shadow_region(shadow_region_t * entry, + addr_t guest_addr_start, + addr_t guest_addr_end, + guest_region_type_t guest_region_type, + host_region_type_t host_region_type) +{ + entry->guest_type = guest_region_type; + entry->guest_start = guest_addr_start; + entry->guest_end = guest_addr_end; + entry->host_type = host_region_type; + entry->next=entry->prev = NULL; +} + +void init_shadow_region_physical(shadow_region_t * entry, + addr_t guest_addr_start, + addr_t guest_addr_end, + guest_region_type_t guest_region_type, + addr_t host_addr_start, + host_region_type_t host_region_type) +{ + init_shadow_region(entry, guest_addr_start, guest_addr_end, guest_region_type, host_region_type); + entry->host_addr.phys_addr.host_start = host_addr_start; + +} + + +void init_shadow_map(shadow_map_t * map) { + map->num_regions = 0; + + map->head = NULL; +} + + +void free_shadow_map(shadow_map_t * map) { + shadow_region_t * cursor = map->head; + shadow_region_t * tmp = NULL; + + while(cursor) { + tmp = cursor; + cursor = cursor->next; + VMMFree(tmp); + } + + VMMFree(map); +} + + + +/* This is slightly different semantically from the mem list, in that + * we don't allow overlaps we could probably allow overlappig regions + * of the same type... but I'll let someone else deal with that + */ +int add_shadow_region(shadow_map_t * map, + shadow_region_t * region) +{ + shadow_region_t * cursor = map->head; + + if ((!cursor) || (cursor->guest_start >= region->guest_end)) { + region->prev = NULL; + region->next = cursor; + map->num_regions++; + map->head = region; + return 0; + } + + while (cursor) { + // Check if it overlaps with the current cursor + if ((cursor->guest_end > region->guest_start) && (cursor->guest_start < region->guest_start)) { + // overlaps not allowed + return -1; + } + + if (!(cursor->next)) { + // add to the end of the list + cursor->next = region; + region->prev = cursor; + region->next = NULL; + map->num_regions++; + return 0; + } else if (cursor->next->guest_start >= region->guest_end) { + // add here + region->next = cursor->next; + region->prev = cursor; + + cursor->next->prev = region; + cursor->next = region; + + map->num_regions++; + + return 0; + } else if (cursor->next->guest_end < region->guest_start) { + cursor = cursor->next; + } else { + // This cannot happen! + // we should panic here + return -1; + } + } + + // This cannot happen + // We should panic here + return -1; +} + + +int delete_shadow_region(shadow_map_t * map, + addr_t guest_start, + addr_t guest_end) { + return -1; +} + + + +shadow_region_t *get_shadow_region_by_index(shadow_map_t * map, + uint_t index) { + shadow_region_t * reg = map->head; + uint_t i = 0; + + while (reg) { + if (i == index) { + return reg; + } + reg = reg->next; + i++; + } + return NULL; +} + + +shadow_region_t * get_shadow_region_by_addr(shadow_map_t * map, + addr_t addr) { + shadow_region_t * reg = map->head; + + while (reg) { + if ((reg->guest_start <= addr) && (reg->guest_end > addr)) { + return reg; + } else if (reg->guest_start > addr) { + return NULL; + } else { + reg = reg->next; + } + } + return NULL; +} + + + +host_region_type_t lookup_shadow_map_addr(shadow_map_t * map, addr_t guest_addr, addr_t * host_addr) { + shadow_region_t * reg = get_shadow_region_by_addr(map, guest_addr); + + if (!reg) { + // No mapping exists + return HOST_REGION_INVALID; + } else { + switch (reg->host_type) { + case HOST_REGION_PHYSICAL_MEMORY: + *host_addr = (guest_addr - reg->guest_start) + reg->host_addr.phys_addr.host_start; + return reg->host_type; + case HOST_REGION_MEMORY_MAPPED_DEVICE: + case HOST_REGION_UNALLOCATED: + // ... + default: + *host_addr = 0; + return reg->host_type; + } + } +} + + +void print_shadow_map(shadow_map_t * map) { + shadow_region_t * cur = map->head; + int i = 0; + + PrintDebug("Memory Layout (regions: %d) \n", map->num_regions); + + while (cur) { + PrintDebug("%d: 0x%x - 0x%x (%s) -> ", i, cur->guest_start, cur->guest_end - 1, + cur->guest_type == GUEST_REGION_PHYSICAL_MEMORY ? "GUEST_REGION_PHYSICAL_MEMORY" : + cur->guest_type == GUEST_REGION_NOTHING ? "GUEST_REGION_NOTHING" : + cur->guest_type == GUEST_REGION_MEMORY_MAPPED_DEVICE ? "GUEST_REGION_MEMORY_MAPPED_DEVICE" : + "UNKNOWN"); + if (cur->host_type == HOST_REGION_PHYSICAL_MEMORY || + cur->host_type == HOST_REGION_UNALLOCATED || + cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) { + PrintDebug("0x%x", cur->host_addr.phys_addr.host_start); + } + PrintDebug("(%s)\n", + cur->host_type == HOST_REGION_PHYSICAL_MEMORY ? "HOST_REGION_PHYSICAL_MEMORY" : + cur->host_type == HOST_REGION_UNALLOCATED ? "HOST_REGION_UNALLOACTED" : + cur->host_type == HOST_REGION_NOTHING ? "HOST_REGION_NOTHING" : + cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE ? "HOST_REGION_MEMORY_MAPPED_DEVICE" : + cur->host_type == HOST_REGION_REMOTE ? "HOST_REGION_REMOTE" : + cur->host_type == HOST_REGION_SWAPPED ? "HOST_REGION_SWAPPED" : + "UNKNOWN"); + cur = cur->next; + i++; + } +} + + + + + + + + + + +#ifdef VMM_MEM_TEST + + +#include +#include +#include + + + + + +struct vmm_os_hooks * os_hooks; + +void * TestMalloc(uint_t size) { + return malloc(size); +} + +void * TestAllocatePages(int size) { + return malloc(4096 * size); +} + + +void TestPrint(const char * fmt, ...) { + va_list args; + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} + +int mem_list_add_test_1( vmm_mem_list_t * list) { + + uint_t offset = 0; + + PrintDebug("\n\nTesting Memory List\n"); + + init_mem_list(list); + + offset = PAGE_SIZE * 6; + PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10)); + add_mem_list_pages(list, offset, 10); + print_mem_list(list); + + + offset = 0; + PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4); + add_mem_list_pages(list, offset, 4); + print_mem_list(list); + + offset = PAGE_SIZE * 20; + PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1)); + add_mem_list_pages(list, offset, 1); + print_mem_list(list); + + offset = PAGE_SIZE * 21; + PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 3)); + add_mem_list_pages(list, offset, 3); + print_mem_list(list); + + + offset = PAGE_SIZE * 10; + PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 30)); + add_mem_list_pages(list, offset, 30); + print_mem_list(list); + + + offset = PAGE_SIZE * 5; + PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1)); + add_mem_list_pages(list, offset, 1); + print_mem_list(list); + + + + return 0; +} + + +int mem_layout_add_test_1(vmm_mem_layout_t * layout) { + + + uint_t start = 0; + uint_t end = 0; + + PrintDebug("\n\nTesting Memory Layout\n"); + + init_mem_layout(layout); + + start = 0x6000; + end = 0x10000;; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); + print_mem_layout(layout); + + + start = 0x1000; + end = 0x3000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); + print_mem_layout(layout); + + start = 0x2000; + end = 0x6000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); + print_mem_layout(layout); + + start = 0x4000; + end = 0x5000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); + print_mem_layout(layout); + + + start = 0x5000; + end = 0x7000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); + print_mem_layout(layout); + + + + + return 0; +} + + + +int main(int argc, char ** argv) { + struct vmm_os_hooks dummy_hooks; + os_hooks = &dummy_hooks; + + vmm_mem_layout_t layout; + vmm_mem_list_t list; + + os_hooks->malloc = &TestMalloc; + os_hooks->free = &free; + os_hooks->print_debug = &TestPrint; + os_hooks->allocate_pages = &TestAllocatePages; + + + + printf("mem_list_add_test_1: %d\n", mem_list_add_test_1(&list)); + printf("layout_add_test_1: %d\n", mem_layout_add_test_1(&layout)); + + return 0; +} +#endif + + + + + + diff --git a/palacios/src/palacios/vmm_paging.c b/palacios/src/palacios/vmm_paging.c new file mode 100644 index 0000000..8ae430d --- /dev/null +++ b/palacios/src/palacios/vmm_paging.c @@ -0,0 +1,242 @@ +#include + +#include + +#include + + +extern struct vmm_os_hooks * os_hooks; + +void delete_page_tables_pde32(pde32_t * pde) { + int i, j; + + if (pde == NULL) { + return; + } + + for (i = 0; (i < MAX_PDE32_ENTRIES); i++) { + if (pde[i].present) { + pte32_t * pte = (pte32_t *)(pde[i].pt_base_addr << PAGE_POWER); + + for (j = 0; (j < MAX_PTE32_ENTRIES); j++) { + if ((pte[j].present)) { + os_hooks->free_page((void *)(pte[j].page_base_addr << PAGE_POWER)); + } + } + + os_hooks->free_page(pte); + } + } + + os_hooks->free_page(pde); +} + + + + + + + +/* We can't do a full lookup because we don't know what context the page tables are in... + * The entry addresses could be pointing to either guest physical memory or host physical memory + * Instead we just return the entry address, and a flag to show if it points to a pte or a large page... + */ +pde32_entry_type_t pde32_lookup(pde32_t * pde, addr_t addr, addr_t * entry) { + pde32_t * pde_entry = &(pde[PDE32_INDEX(addr)]); + + if (!pde_entry->present) { + *entry = 0; + return NOT_PRESENT; + } else { + *entry = PAGE_ADDR(pde_entry->pt_base_addr); + + if (pde_entry->large_pages) { + *entry += PAGE_OFFSET(addr); + return LARGE_PAGE; + } else { + return PTE32; + } + } + return NOT_PRESENT; +} + + +int pte32_lookup(pte32_t * pte, addr_t addr, addr_t * entry) { + pte32_t * pte_entry = &(pte[PTE32_INDEX(addr)]); + + if (!pte_entry->present) { + *entry = 0; + return -1; + } else { + *entry = PAGE_ADDR(pte_entry->page_base_addr); + *entry += PAGE_OFFSET(addr); + return 0; + } + + return -1; +} + + + + + + + + +/* We generate a page table to correspond to a given memory layout + * pulling pages from the mem_list when necessary + * If there are any gaps in the layout, we add them as unmapped pages + */ +pde32_t * create_passthrough_pde32_pts(struct guest_info * guest_info) { + ullong_t current_page_addr = 0; + int i, j; + shadow_map_t * map = &(guest_info->mem_map); + + + pde32_t * pde = os_hooks->allocate_pages(1); + + for (i = 0; i < MAX_PDE32_ENTRIES; i++) { + int pte_present = 0; + pte32_t * pte = os_hooks->allocate_pages(1); + + + for (j = 0; j < MAX_PTE32_ENTRIES; j++) { + shadow_region_t * region = get_shadow_region_by_addr(map, current_page_addr); + + if (!region || + (region->host_type == HOST_REGION_NOTHING) || + (region->host_type == HOST_REGION_UNALLOCATED) || + (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || + (region->host_type == HOST_REGION_REMOTE) || + (region->host_type == HOST_REGION_SWAPPED)) { + pte[j].present = 0; + pte[j].flags = 0; + pte[j].accessed = 0; + pte[j].dirty = 0; + pte[j].pte_attr = 0; + pte[j].global_page = 0; + pte[j].vmm_info = 0; + pte[j].page_base_addr = 0; + } else { + addr_t host_addr; + pte[j].present = 1; + pte[j].flags = VM_READ | VM_WRITE | VM_EXEC | VM_USER; + + pte[j].accessed = 0; + pte[j].dirty = 0; + pte[j].pte_attr = 0; + pte[j].global_page = 0; + pte[j].vmm_info = 0; + + if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) { + // BIG ERROR + // PANIC + return NULL; + } + + pte[j].page_base_addr = host_addr >> 12; + + pte_present = 1; + } + + current_page_addr += PAGE_SIZE; + } + + if (pte_present == 0) { + os_hooks->free_page(pte); + + pde[i].present = 0; + pde[i].flags = 0; + pde[i].accessed = 0; + pde[i].reserved = 0; + pde[i].large_pages = 0; + pde[i].global_page = 0; + pde[i].vmm_info = 0; + pde[i].pt_base_addr = 0; + } else { + pde[i].present = 1; + pde[i].flags = VM_READ | VM_WRITE | VM_EXEC | VM_USER; + pde[i].accessed = 0; + pde[i].reserved = 0; + pde[i].large_pages = 0; + pde[i].global_page = 0; + pde[i].vmm_info = 0; + pde[i].pt_base_addr = PAGE_ALIGNED_ADDR(pte); + } + + } + + return pde; +} + + + + + + +void PrintPDE32(void * virtual_address, pde32_t * pde) +{ + PrintDebug("PDE %p -> %p : present=%x, flags=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n", + virtual_address, + (void *) (pde->pt_base_addr << PAGE_POWER), + pde->present, + pde->flags, + pde->accessed, + pde->reserved, + pde->large_pages, + pde->global_page, + pde->vmm_info); +} + +void PrintPTE32(void * virtual_address, pte32_t * pte) +{ + PrintDebug("PTE %p -> %p : present=%x, flags=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, vmm_info=%x\n", + virtual_address, + (void*)(pte->page_base_addr << PAGE_POWER), + pte->present, + pte->flags, + pte->accessed, + pte->dirty, + pte->pte_attr, + pte->global_page, + pte->vmm_info); +} + + + +void PrintPD32(pde32_t * pde) +{ + int i; + + PrintDebug("Page Directory at %p:\n", pde); + for (i = 0; (i < MAX_PDE32_ENTRIES) && pde[i].present; i++) { + PrintPDE32((void*)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i])); + } +} + +void PrintPT32(void * starting_address, pte32_t * pte) +{ + int i; + + PrintDebug("Page Table at %p:\n", pte); + for (i = 0; (i < MAX_PTE32_ENTRIES) && pte[i].present; i++) { + PrintPTE32(starting_address + (PAGE_SIZE * i), &(pte[i])); + } +} + + + + + +void PrintDebugPageTables(pde32_t * pde) +{ + int i; + + PrintDebug("Dumping the pages starting with the pde page at %p\n", pde); + + for (i = 0; (i < MAX_PDE32_ENTRIES) && pde[i].present; i++) { + PrintPDE32((void *)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i])); + PrintPT32((void *)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), (void *)(pde[i].pt_base_addr << PAGE_POWER)); + } +} + diff --git a/palacios/src/palacios/vmm_shadow_paging.c b/palacios/src/palacios/vmm_shadow_paging.c new file mode 100644 index 0000000..c9546e4 --- /dev/null +++ b/palacios/src/palacios/vmm_shadow_paging.c @@ -0,0 +1,209 @@ +#include + +#include +#include + +extern struct vmm_os_hooks * os_hooks; + + +int init_shadow_page_state(struct shadow_page_state * state) { + state->guest_mode = PDE32; + state->shadow_mode = PDE32; + + state->guest_cr3.r_reg = 0; + state->shadow_cr3.r_reg = 0; + + return 0; +} + + +int wholesale_update_shadow_page_state(struct guest_info * guest_info) { + unsigned i, j; + pde32_t * guest_pde; + pde32_t * shadow_pde; + + struct shadow_page_state * state = &(guest_info->shdw_pg_state); + + + // For now, we'll only work with PDE32 + if (state->guest_mode != PDE32) { + return -1; + } + + shadow_pde = (pde32_t *)(CR3_TO_PDE32(state->shadow_cr3.e_reg.low)); + + if (host_pa_to_host_va(CR3_TO_PDE32(state->guest_cr3.e_reg.low), (addr_t*)&guest_pde) != 0) { + return -1; + } + + // Delete the current page table + delete_page_tables_pde32(shadow_pde); + + shadow_pde = os_hooks->allocate_pages(1); + + state->shadow_cr3.e_reg.low = (addr_t)shadow_pde; + + state->shadow_mode = PDE32; + + for (i = 0; i < MAX_PDE32_ENTRIES; i++) { + shadow_pde[i] = guest_pde[i]; + + // The shadow can be identical to the guest if it's not present + if (!shadow_pde[i].present) { + continue; + } + + if (shadow_pde[i].large_pages) { + // large page - just map it through shadow map to generate its physical location + addr_t guest_addr = PAGE_ADDR(shadow_pde[i].pt_base_addr); + addr_t host_addr; + shadow_region_t * ent; + + ent = get_shadow_region_by_addr(&(guest_info->mem_map), guest_addr); + + if (!ent) { + // FIXME Panic here - guest is trying to map to physical memory + // it does not own in any way! + return -1; + } + + // FIXME Bounds check here to see if it's trying to trick us + + switch (ent->host_type) { + case HOST_REGION_PHYSICAL_MEMORY: + // points into currently allocated physical memory, so we just + // set up the shadow to point to the mapped location + if (guest_pa_to_host_pa(guest_info, guest_addr, &host_addr)) { + // Panic here + return -1; + } + + shadow_pde[i].pt_base_addr = PAGE_ALIGNED_ADDR(host_addr); + // FIXME set vmm_info bits here + break; + case HOST_REGION_UNALLOCATED: + // points to physical memory that is *allowed* but that we + // have not yet allocated. We mark as not present and set a + // bit to remind us to allocate it later + shadow_pde[i].present = 0; + // FIXME Set vminfo bits here so that we know that we will be + // allocating it later + break; + case HOST_REGION_NOTHING: + // points to physical memory that is NOT ALLOWED. + // We will mark it as not present and set a bit to remind + // us that it's bad later and insert a GPF then + shadow_pde[i].present = 0; + break; + case HOST_REGION_MEMORY_MAPPED_DEVICE: + case HOST_REGION_REMOTE: + case HOST_REGION_SWAPPED: + default: + // Panic. Currently unhandled + return -1; + break; + } + } else { + pte32_t * guest_pte; + pte32_t * shadow_pte; + addr_t guest_addr; + addr_t guest_pte_host_addr; + shadow_region_t * ent; + + // small page - set PDE and follow down to the child table + shadow_pde[i] = guest_pde[i]; + + guest_addr = PAGE_ADDR(guest_pde[i].pt_base_addr); + + // Allocate a new second level page table for the shadow + shadow_pte = os_hooks->allocate_pages(1); + + // make our first level page table in the shadow point to it + shadow_pde[i].pt_base_addr = PAGE_ALIGNED_ADDR(shadow_pte); + + ent = get_shadow_region_by_addr(&(guest_info->mem_map), guest_addr); + + + /* JRL: This is bad.... */ + // For now the guest Page Table must always be mapped to host physical memory + /* If we swap out a page table or if it isn't present for some reason, this turns real ugly */ + + if ((!ent) || (ent->host_type != HOST_REGION_PHYSICAL_MEMORY)) { + // FIXME Panic here - guest is trying to map to physical memory + // it does not own in any way! + return -1; + } + + // Address of the relevant second level page table in the guest + if (guest_pa_to_host_pa(guest_info, guest_addr, &guest_pte_host_addr)) { + // Panic here + return -1; + } + + + // host_addr now contains the host physical address for the guest's 2nd level page table + // Now we transform it to relevant virtual address + guest_pte = os_hooks->paddr_to_vaddr((void *)guest_pte_host_addr); + + // Now we walk through the second level guest page table + // and clone it into the shadow + for (j = 0; j < MAX_PTE32_ENTRIES; j++) { + shadow_pte[j] = guest_pte[j]; + + addr_t guest_addr = PAGE_ADDR(shadow_pte[j].page_base_addr); + + shadow_region_t * ent; + + ent = get_shadow_region_by_addr(&(guest_info->mem_map), guest_addr); + + if (!ent) { + // FIXME Panic here - guest is trying to map to physical memory + // it does not own in any way! + return -1; + } + + switch (ent->host_type) { + case HOST_REGION_PHYSICAL_MEMORY: + { + addr_t host_addr; + + // points into currently allocated physical memory, so we just + // set up the shadow to point to the mapped location + if (guest_pa_to_host_pa(guest_info, guest_addr, &host_addr)) { + // Panic here + return -1; + } + + shadow_pte[j].page_base_addr = PAGE_ALIGNED_ADDR(host_addr); + // FIXME set vmm_info bits here + break; + } + case HOST_REGION_UNALLOCATED: + // points to physical memory that is *allowed* but that we + // have not yet allocated. We mark as not present and set a + // bit to remind us to allocate it later + shadow_pte[j].present = 0; + // FIXME Set vminfo bits here so that we know that we will be + // allocating it later + break; + case HOST_REGION_NOTHING: + // points to physical memory that is NOT ALLOWED. + // We will mark it as not present and set a bit to remind + // us that it's bad later and insert a GPF then + shadow_pte[j].present = 0; + break; + case HOST_REGION_MEMORY_MAPPED_DEVICE: + case HOST_REGION_REMOTE: + case HOST_REGION_SWAPPED: + default: + // Panic. Currently unhandled + return -1; + break; + } + } + } + } + return 0; +} + + diff --git a/palacios/src/palacios/vmm_string.c b/palacios/src/palacios/vmm_string.c new file mode 100644 index 0000000..ecc08a8 --- /dev/null +++ b/palacios/src/palacios/vmm_string.c @@ -0,0 +1,212 @@ +/* + * String library + * Copyright (c) 2001,2004 David H. Hovemeyer + * $Revision: 1.1 $ + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "COPYING". + */ + +/* + * NOTE: + * These are slow and simple implementations of a subset of + * the standard C library string functions. + * We also have an implementation of snprintf(). + */ + + +#include + +extern void *Malloc(size_t size); + +void* memset(void* s, int c, size_t n) +{ + unsigned char* p = (unsigned char*) s; + + while (n > 0) { + *p++ = (unsigned char) c; + --n; + } + + return s; +} + +void* memcpy(void *dst, const void* src, size_t n) +{ + unsigned char* d = (unsigned char*) dst; + const unsigned char* s = (const unsigned char*) src; + + while (n > 0) { + *d++ = *s++; + --n; + } + + return dst; +} + +int memcmp(const void *s1_, const void *s2_, size_t n) +{ + const signed char *s1 = s1_, *s2 = s2_; + + while (n > 0) { + int cmp = *s1 - *s2; + if (cmp != 0) + return cmp; + ++s1; + ++s2; + } + + return 0; +} + +size_t strlen(const char* s) +{ + size_t len = 0; + while (*s++ != '\0') + ++len; + return len; +} + +/* + * This it a GNU extension. + * It is like strlen(), but it will check at most maxlen + * characters for the terminating nul character, + * returning maxlen if it doesn't find a nul. + * This is very useful for checking the length of untrusted + * strings (e.g., from user space). + */ +size_t strnlen(const char *s, size_t maxlen) +{ + size_t len = 0; + while (len < maxlen && *s++ != '\0') + ++len; + return len; +} + +int strcmp(const char* s1, const char* s2) +{ + while (1) { + int cmp = *s1 - *s2; + if (cmp != 0 || *s1 == '\0' || *s2 == '\0') + return cmp; + ++s1; + ++s2; + } +} + +int strncmp(const char* s1, const char* s2, size_t limit) +{ + size_t i = 0; + while (i < limit) { + int cmp = *s1 - *s2; + if (cmp != 0 || *s1 == '\0' || *s2 == '\0') + return cmp; + ++s1; + ++s2; + ++i; + } + + /* limit reached and equal */ + return 0; +} + +char *strcat(char *s1, const char *s2) +{ + char *t1; + + t1 = s1; + while (*s1) s1++; + while(*s2) *s1++ = *s2++; + *s1 = '\0'; + + return t1; +} + +char *strcpy(char *dest, const char *src) +{ + char *ret = dest; + + while (*src) { + *dest++ = *src++; + } + *dest = '\0'; + + return ret; +} + +char *strncpy(char *dest, const char *src, size_t limit) +{ + char *ret = dest; + + while (*src != '\0' && limit > 0) { + *dest++ = *src++; + --limit; + } + if (limit > 0) + *dest = '\0'; + + return ret; +} + +char *strdup(const char *s1) +{ + char *ret; + + ret = Malloc(strlen(s1) + 1); + strcpy(ret, s1); + + return ret; +} + +int atoi(const char *buf) +{ + int ret = 0; + + while (*buf >= '0' && *buf <= '9') { + ret *= 10; + ret += *buf - '0'; + buf++; + } + + return ret; +} + +char *strchr(const char *s, int c) +{ + while (*s != '\0') { + if (*s == c) + return (char *) s; + ++s; + } + return 0; +} + +char *strrchr(const char *s, int c) +{ + size_t len = strlen(s); + const char *p = s + len; + + while (p > s) { + --p; + if (*p == c) + return (char*) p; + } + return 0; +} + +char *strpbrk(const char *s, const char *accept) +{ + size_t setLen = strlen(accept); + + while (*s != '\0') { + size_t i; + for (i = 0; i < setLen; ++i) { + if (*s == accept[i]) + return (char *) s; + } + ++s; + } + + return 0; +} + diff --git a/palacios/src/palacios/vmm_symbol.asm b/palacios/src/palacios/vmm_symbol.asm new file mode 100644 index 0000000..cd9841e --- /dev/null +++ b/palacios/src/palacios/vmm_symbol.asm @@ -0,0 +1,43 @@ +; Symbol mangling macros +; Copyright (c) 2001, David H. Hovemeyer +; $Revision: 1.1 $ + +; This file defines macros for dealing with externally-visible +; symbols that must be mangled for some object file formats. +; For example, PECOFF requires a leading underscore, while +; ELF does not. + +; EXPORT defines a symbol as global +; IMPORT references a symbol defined in another module + +; Thanks to Christopher Giese for providing the NASM macros +; (thus saving me hours of frustration). + +%ifndef __VMM_SYMBOL_ASM +%define __VMM_SYMBOL_ASM + +%ifdef NEED_UNDERSCORE + +%macro EXPORT 1 +[GLOBAL _%1] +%define %1 _%1 +%endmacro + +%macro IMPORT 1 +[EXTERN _%1] +%define %1 _%1 +%endmacro + +%else + +%macro EXPORT 1 +[GLOBAL %1] +%endmacro + +%macro IMPORT 1 +[EXTERN %1] +%endmacro + +%endif + +%endif diff --git a/palacios/src/palacios/vmm_util.c b/palacios/src/palacios/vmm_util.c new file mode 100644 index 0000000..77440e5 --- /dev/null +++ b/palacios/src/palacios/vmm_util.c @@ -0,0 +1,40 @@ +#include + +#include + +extern struct vmm_os_hooks * os_hooks; + + +void PrintTraceHex(unsigned char x) { + unsigned char z; + + z = (x >> 4) & 0xf ; + PrintTrace("%x", z); + z = x & 0xf; + PrintTrace("%x", z); +} + + +void PrintTraceMemDump(unsigned char *start, int n) +{ + int i, j; + + for (i = 0; i < n; i += 16) { + PrintTrace("%8x", (unsigned)(start + i)); + for (j = i; (j < (i + 16)) && (j < n); j += 2) { + PrintTrace(" "); + PrintTraceHex(*((unsigned char *)(start + j))); + if ((j + 1) < n) { + PrintTraceHex(*((unsigned char *)(start + j + 1))); + } + } + PrintTrace(" "); + for (j = i; (j < (i + 16)) && (j < n); j++) { + PrintTrace("%c", ((start[j] >= 32) && (start[j] <= 126)) ? start[j] : '.'); + } + PrintTrace("\n"); + } +} + + + diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c new file mode 100644 index 0000000..e393099 --- /dev/null +++ b/palacios/src/palacios/vmx.c @@ -0,0 +1,911 @@ +/* Eventually we want to get rid of these */ + +#include +#include +#include +/* ** */ + +#include +#include +#include +#include +#include + + +extern void Get_MSR(unsigned int msr, uint_t * high, uint_t * low); +extern void Set_MSR(unsigned int msr, uint_t high, uint_t low); +extern int Enable_VMX(ullong_t regionPtr); +extern int cpuid_ecx(unsigned int op); +extern int Launch_VM(ullong_t vmcsPtr, uint_t eip); + +#define NUMPORTS 65536 + + +#define VMXASSIST_INFO_PORT 0x0e9 +#define ROMBIOS_PANIC_PORT 0x400 +#define ROMBIOS_PANIC_PORT2 0x401 +#define ROMBIOS_INFO_PORT 0x402 +#define ROMBIOS_DEBUG_PORT 0x403 + + +extern struct vmm_os_hooks * os_hooks; + + +static struct VM theVM; + +static uint_t GetLinearIP(struct VM *vm) +{ + if (vm->state==VM_VMXASSIST_V8086_BIOS || vm->state==VM_VMXASSIST_V8086) { + return vm->vmcs.guestStateArea.cs.baseAddr + vm->vmcs.guestStateArea.rip; + } else { + return vm->vmcs.guestStateArea.rip; + } +} + + +static void VMXPanic() +{ + while (1) {} +} + + +#define MAX_CODE 512 +#define INSTR_OFFSET_START 17 +#define NOP_SEQ_LEN 10 +#define INSTR_OFFSET_END (INSTR_OFFSET_START+NOP_SEQ_LEN-1) +#define TEMPLATE_CODE_LEN 35 + +uint_t oldesp=0; +uint_t myregs=0; + +// simply execute the instruction that is faulting and return +static int ExecFaultingInstructionInVMM(struct VM *vm) +{ + uint_t address = GetLinearIP(vm); + myregs = (uint_t)&(vm->registers); + + + PrintTrace("About the execute faulting instruction!\n"); + PrintTrace("Instruction is:\n"); + PrintTraceMemDump((void*)(address),vm->vmcs.exitInfoFields.instrLength); + + + PrintTrace("The template code is:\n"); + PrintTraceMemDump(&&template_code,TEMPLATE_CODE_LEN); + + // clone the template code + //memcpy(&&template_code,code,MAX_CODE); + + // clean up the nop field + memset(&&template_code+INSTR_OFFSET_START,*((uchar_t *)(&&template_code+0)),NOP_SEQ_LEN); + // overwrite the nops with the faulting instruction + memcpy(&&template_code+INSTR_OFFSET_START, (void*)(address),vm->vmcs.exitInfoFields.instrLength); + + PrintTrace("Finished modifying the template code, which now is:\n"); + PrintTraceMemDump(&&template_code,TEMPLATE_CODE_LEN); + + PrintTrace("Now entering modified template code\n"); + + + template_code: + // Template code stores current registers, + // restores registers, has a landing pad of noops + // that will be modified, restores current regs, and then returns + // + // Note that this currently ignores cr0, cr3, cr4, dr7, rsp, rip, and rflags + // it also blythly assumes it can exec the instruction in protected mode + // + __asm__ __volatile__ ("nop\n" // for cloning purposes (1 byte) + "pusha\n" // push our current regs onto the current stack (1 byte) + "movl %0, %%eax\n" // Get oldesp location (5 bytes) + "movl %%esp, (%%eax)\n" // store the current stack pointer in oldesp (2 bytes) + "movl %1, %%eax\n" // Get regs location (5 bytes) + "movl (%%eax), %%esp\n" // point esp at regs (2 bytes) + "popa\n" // now we have the VM registers restored (1 byte) + "nop\n" // now we execute the actual instruction (1 byte x 10) + "nop\n" // now we execute the actual instruction + "nop\n" // now we execute the actual instruction + "nop\n" // now we execute the actual instruction + "nop\n" // now we execute the actual instruction + "nop\n" // now we execute the actual instruction + "nop\n" // now we execute the actual instruction + "nop\n" // now we execute the actual instruction + "nop\n" // now we execute the actual instruction + "nop\n" // now we execute the actual instruction + // need to copy back to the VM registers! + "movl %0, %%eax\n" // recapture oldesp location (5 bytes) + "movl (%%eax), %%esp\n" // now we'll get our esp back from oldesp (2 bytes) + "popa\n" // and restore our GP regs and we're done (1 byte) + : "=m"(oldesp) + : "m"(myregs) + ); + + PrintTrace("Survived executing the faulting instruction and returning.\n"); + + vm->vmcs.guestStateArea.rip += vm->vmcs.exitInfoFields.instrLength; + + return 0; + +} + + +int is_vmx_capable() { + uint_t ret; + union VMX_MSR featureMSR; + + ret = cpuid_ecx(1); + if (ret & CPUID_1_ECX_VTXFLAG) { + Get_MSR(IA32_FEATURE_CONTROL_MSR, &featureMSR.regs.high, &featureMSR.regs.low); + + PrintTrace("MSRREGlow: 0x%.8x\n", featureMSR.regs.low); + + if ((featureMSR.regs.low & FEATURE_CONTROL_VALID) != FEATURE_CONTROL_VALID) { + PrintDebug("VMX is locked -- enable in the BIOS\n"); + return 0; + } + } else { + PrintDebug("VMX not supported on this cpu\n"); + return 0; + } + + return 1; + +} + + +VmxOnRegion * Init_VMX() { + uint_t ret; + VmxOnRegion * region = NULL; + + + region = CreateVmxOnRegion(); + + + ret = Enable_VMX((ullong_t)((uint_t)region)); + if (ret == 0) { + PrintDebug("VMX Enabled\n"); + } else { + PrintDebug("VMX failure (ret = %d)\n", ret); + } + + theVM.vmxonregion = region; + + return region; +} + +extern uint_t VMCS_CLEAR(); +extern uint_t VMCS_LOAD(); +extern uint_t VMCS_STORE(); +extern uint_t VMCS_LAUNCH(); +extern uint_t VMCS_RESUME(); +extern uint_t Init_VMCS_HostState(); +extern uint_t Init_VMCS_GuestState(); + +void SetCtrlBitsCorrectly(int msrno, int vmcsno) +{ + uint_t reserved =0; + union VMX_MSR msr; + + PrintTrace("SetCtrlBitsCorrectly(%x,%x)\n", msrno, vmcsno); + Get_MSR(msrno, &msr.regs.high, &msr.regs.low); + PrintTrace("MSR %x = %x : %x \n", msrno, msr.regs.high, msr.regs.low); + reserved = msr.regs.low; + reserved &= msr.regs.high; + VMCS_WRITE(vmcsno, &reserved); +} + + +void SetCRBitsCorrectly(int msr0no, int msr1no, int vmcsno) +{ + uint_t reserved =0; + union VMX_MSR msr0, msr1; + + PrintTrace("SetCRBitsCorrectly(%x,%x,%x)\n",msr0no,msr1no,vmcsno); + Get_MSR(msr0no, &msr0.regs.high, &msr0.regs.low); + Get_MSR(msr1no, &msr1.regs.high, &msr1.regs.low); + PrintTrace("MSR %x = %x, %x = %x \n", msr0no, msr0.regs.low, msr1no, msr1.regs.low); + reserved = msr0.regs.low; + reserved &= msr1.regs.low; + VMCS_WRITE(vmcsno, &reserved); +} + + +extern int Get_CR2(); +extern int vmRunning; + + +static int PanicUnhandledVMExit(struct VM *vm) +{ + PrintInfo("Panicking due to VMExit with reason %u\n", vm->vmcs.exitInfoFields.reason); + PrintTrace("Panicking due to VMExit with reason %u\n", vm->vmcs.exitInfoFields.reason); + PrintTrace_VMCS_ALL(); + PrintTrace_VMX_Regs(&(vm->registers)); + VMXPanic(); + return 0; +} + + +static int HandleVMPrintsAndPanics(struct VM *vm, uint_t port, uint_t data) +{ + if (port==VMXASSIST_INFO_PORT && + (vm->state == VM_VMXASSIST_STARTUP || + vm->state == VM_VMXASSIST_V8086_BIOS || + vm->state == VM_VMXASSIST_V8086)) { + // Communication channel from VMXAssist + PrintTrace("VMXASSIST Output Port\n"); + PrintDebug("%c",data&0xff); + return 1; + } + + if ((port==ROMBIOS_PANIC_PORT || + port==ROMBIOS_PANIC_PORT2 || + port==ROMBIOS_DEBUG_PORT || + port==ROMBIOS_INFO_PORT) && + (vm->state==VM_VMXASSIST_V8086_BIOS)) { + // rombios is communicating + PrintTrace("ROMBIOS Output Port\n"); + // PrintDebug("%c",data&0xff); + return 1; + } + + if (port==BOOT_STATE_CARD_PORT && vm->state==VM_VMXASSIST_V8086_BIOS) { + // rombios is sending something to the display card + PrintTrace("Hex Display: 0x%x\n",data&0xff); + return 1; + } + return 0; +} + +static int HandleInOutExit(struct VM *vm) +{ + uint_t address; + + struct VMCSExitInfoFields *exitinfo = &(vm->vmcs.exitInfoFields); + struct VMExitIOQual * qual = (struct VMExitIOQual *)&(vm->vmcs.exitInfoFields.qualification); + struct VMXRegs *regs = &(vm->registers); + + address=GetLinearIP(vm); + + PrintTrace("Handling Input/Output Instruction Exit\n"); + + PrintTrace_VMX_Regs(regs); + + PrintTrace("Qualifications=0x%x\n", exitinfo->qualification); + PrintTrace("Reason=0x%x\n", exitinfo->reason); + PrintTrace("IO Port: 0x%x (%d)\n", qual->port, qual->port); + PrintTrace("Instruction Info=%x\n", exitinfo->instrInfo); + PrintTrace("%x : %s %s %s instruction of length %d for %d bytes from/to port 0x%x\n", + address, + qual->dir == 0 ? "output" : "input", + qual->string ==0 ? "nonstring" : "STRING", + qual->REP == 0 ? "with no rep" : "WITH REP", + exitinfo->instrLength, + qual->accessSize==0 ? 1 : qual->accessSize==1 ? 2 : 4, + qual->port); + + if ((qual->port == PIC_MASTER_CMD_ISR_PORT) || + (qual->port == PIC_MASTER_IMR_PORT) || + (qual->port == PIC_SLAVE_CMD_ISR_PORT) || + (qual->port == PIC_SLAVE_IMR_PORT)) { + PrintTrace( "PIC Access\n"); + } + + + if ((qual->dir == 1) && (qual->REP == 0) && (qual->string == 0)) { + char byte = In_Byte(qual->port); + + vm->vmcs.guestStateArea.rip += exitinfo->instrLength; + regs->eax = (regs->eax & 0xffffff00) | byte; + PrintTrace("Returning 0x%x in eax\n", (regs->eax)); + } + + if (qual->dir==0 && qual->REP==0 && qual->string==0) { + // See if we need to handle the outb as a signal or + // print from the VM + if (HandleVMPrintsAndPanics(vm,qual->port,regs->eax)) { + } else { + // If not, just go ahead and do the outb + Out_Byte(qual->port,regs->eax); + PrintTrace("Wrote 0x%x to port\n",(regs->eax)); + } + vm->vmcs.guestStateArea.rip += exitinfo->instrLength; + } + + return 0; +} + + +static int HandleExternalIRQExit(struct VM *vm) +{ + struct VMCSExitInfoFields * exitinfo = &(vm->vmcs.exitInfoFields); + struct VMExitIntInfo * intInfo = (struct VMExitIntInfo *)&(vm->vmcs.exitInfoFields.intInfo); + + PrintTrace("External Interrupt captured\n"); + PrintTrace("IntInfo: %x\n", exitinfo->intInfo); + + + if (!intInfo->valid) { + // interrupts are off, but this interrupt is not acknoledged (still pending) + // so we turn on interrupts to deliver appropriately in the + // host + PrintTrace("External Interrupt is invald. Turning Interrupts back on\n"); + asm("sti"); + return 0; + } + + // At this point, interrupts are off and the interrupt has been + // acknowledged. We will now handle the interrupt ourselves + // and turn interrupts back on in the host + + PrintTrace("type: %d\n", intInfo->type); + PrintTrace("number: %d\n", intInfo->nr); + + PrintTrace("Interrupt %d occuring now and handled by HandleExternalIRQExit\n",intInfo->nr); + + switch (intInfo->type) { + case 0: { // ext. IRQ + // In the following, we construct an "int x" instruction + // where x is the specific interrupt number that is raised + // then we execute that instruciton + // because we are in host context, that means it is delivered as normal + // through the host IDT + + ((char*)(&&ext_int_seq_start))[1] = intInfo->nr; + + PrintTrace("Interrupt instruction setup done %x\n", *((ushort_t *)(&&ext_int_seq_start))); + +ext_int_seq_start: + asm("int $0"); + } + + break; + case 2: // NMI + PrintTrace("Type: NMI\n"); + break; + case 3: // hw exception + PrintTrace("Type: HW Exception\n"); + break; + case 4: // sw exception + PrintTrace("Type: SW Exception\n"); + break; + default: + PrintTrace("Invalid Interrupt Type\n"); + return -1; + } + + if (intInfo->valid && intInfo->errorCode) { + PrintTrace("IntError: %x\n", exitinfo->intErrorCode); + } + + + return 0; + +} + + + +void DecodeCurrentInstruction(struct VM *vm, struct Instruction *inst) +{ + // this is a gruesome hack + uint_t address = GetLinearIP(vm); + uint_t length = vm->vmcs.exitInfoFields.instrLength; + unsigned char *t = (unsigned char *) address; + + + + PrintTrace("DecodeCurrentInstruction: instruction is\n"); + PrintTraceMemDump(t,length); + + if (length==3 && t[0]==0x0f && t[1]==0x22 && t[2]==0xc0) { + // mov from eax to cr0 + // usually used to signal + inst->type=VM_MOV_TO_CR0; + inst->address=address; + inst->size=length; + inst->input1=vm->registers.eax; + inst->input2=vm->vmcs.guestStateArea.cr0; + inst->output=vm->registers.eax; + PrintTrace("MOV FROM EAX TO CR0\n"); + } else { + inst->type=VM_UNKNOWN_INST; + } +} + + +static void V8086ModeSegmentRegisterFixup(struct VM *vm) +{ + vm->vmcs.guestStateArea.cs.baseAddr=vm->vmcs.guestStateArea.cs.selector<<4; + vm->vmcs.guestStateArea.es.baseAddr=vm->vmcs.guestStateArea.es.selector<<4; + vm->vmcs.guestStateArea.ss.baseAddr=vm->vmcs.guestStateArea.ss.selector<<4; + vm->vmcs.guestStateArea.ds.baseAddr=vm->vmcs.guestStateArea.ds.selector<<4; + vm->vmcs.guestStateArea.fs.baseAddr=vm->vmcs.guestStateArea.fs.selector<<4; + vm->vmcs.guestStateArea.gs.baseAddr=vm->vmcs.guestStateArea.gs.selector<<4; +} + +static void SetupV8086ModeForBoot(struct VM *vm) +{ + vm->state = VM_VMXASSIST_V8086_BIOS; + + // Put guest into V8086 mode on return + vm->vmcs.guestStateArea.rflags |= EFLAGS_VM | EFLAGS_IOPL_HI | EFLAGS_IOPL_LO ; + + // We will start at f000:fff0 on return + // + // We want this to look as much as possible as a processor + // reset + vm->vmcs.guestStateArea.rip = 0xfff0; // note, 16 bit rip + vm->vmcs.guestStateArea.cs.selector = 0xf000; + vm->vmcs.guestStateArea.cs.limit=0xffff; + vm->vmcs.guestStateArea.cs.access.as_dword = 0xf3; + + vm->vmcs.guestStateArea.ss.selector = 0x0000; + vm->vmcs.guestStateArea.ss.limit=0xffff; + vm->vmcs.guestStateArea.ss.access.as_dword = 0xf3; + + vm->vmcs.guestStateArea.ds.selector = 0x0000; + vm->vmcs.guestStateArea.ds.limit=0xffff; + vm->vmcs.guestStateArea.ds.access.as_dword = 0xf3; + + vm->vmcs.guestStateArea.es.selector = 0x0000; + vm->vmcs.guestStateArea.es.limit=0xffff; + vm->vmcs.guestStateArea.es.access.as_dword = 0xf3; + + vm->vmcs.guestStateArea.fs.selector = 0x0000; + vm->vmcs.guestStateArea.fs.limit=0xffff; + vm->vmcs.guestStateArea.fs.access.as_dword = 0xf3; + + vm->vmcs.guestStateArea.gs.selector = 0x0000; + vm->vmcs.guestStateArea.gs.limit=0xffff; + vm->vmcs.guestStateArea.gs.access.as_dword = 0xf3; + + V8086ModeSegmentRegisterFixup(vm); + + PrintTrace_VMCSData(&(vm->vmcs)); + +} + + + +static int HandleExceptionOrNMI(struct VM *vm) +{ + struct Instruction inst; + uint_t num; + uint_t type; + uint_t errorvalid; + uint_t error; + uint_t ext=0; + uint_t idt=0; + uint_t ti=0; + uint_t selectorindex=0; + + PrintTrace("Exception or NMI occurred\n"); + + num=vm->vmcs.exitInfoFields.intInfo & 0xff; + type=(vm->vmcs.exitInfoFields.intInfo & 0x700)>>8; + errorvalid=(vm->vmcs.exitInfoFields.intInfo & 0x800)>>11; + if (errorvalid) { + error=vm->vmcs.exitInfoFields.intErrorCode; + ext=error&0x1; + idt=(error&0x2)>>1; + ti=(error&0x4)>>2; + selectorindex=(error>>3)&0xffff; + } + + PrintTrace("Exception %d now - handled by HandleExceptionOrNMI\n",num); + + PrintTrace("Exception Number %u : %s\n", num, exception_names[num]); + PrintTrace("Exception Type %u : %s\n", type, exception_type_names[type]); + if (errorvalid) { + if (ext) { + PrintTrace("External\n"); + } else { + PrintTrace("%s - Selector Index is %u\n", idt ? "IDT" : ti ? "LDT" : "GDT", selectorindex); + } + } + + DecodeCurrentInstruction(vm,&inst); + + if (inst.type==VM_MOV_TO_CR0) { + PrintTrace("MOV TO CR0, oldvalue=0x%x, newvalue=0x%x\n",inst.input2, inst.input1); + if ((inst.input2 & CR0_PE) && !(inst.input1 & CR0_PE) && vm->state==VM_VMXASSIST_STARTUP) { + // This is VMXAssist signalling for us to turn on V8086 mode and + // jump into the bios + PrintTrace("VMXAssist is signaling us for switch to V8086 mode and jump to 0xf000:fff0\n"); + SetupV8086ModeForBoot(vm); + goto leave; + } else { + PrintTrace("Instruction is a write to CR0, but we don't understand it so we'll just exec it\n"); + } + } + + + PrintTrace("Trying to execute the faulting instruction in VMM context now\n"); + ExecFaultingInstructionInVMM(vm); + + leave: + // + //PanicUnhandledVMExit(vmcs,regs); + //VMXPanic(); + return 0; +} + + +static struct VM *FindVM() +{ + return &theVM; +} + + +int Do_VMM(struct VMXRegs regs) +{ + + ullong_t vmcs_ptr = 0; + uint_t vmcs_ptr_low = 0; + int ret = 0; + uint_t vmx_abort = 0; + + + + PrintTrace("Vm Exit\n"); + ret = VMCS_STORE(&vmcs_ptr); + vmcs_ptr &= 0xffffffff; + vmcs_ptr_low += vmcs_ptr; + + + + + PrintTrace("ret=%d\n", ret); + PrintTrace("Revision: %x\n", *(uint_t *)(vmcs_ptr_low)); + vmx_abort = *(uint_t*)(((char *)vmcs_ptr_low)+4); + + struct VM *vm = FindVM(); + + if (vmx_abort != 0) { + PrintTrace("VM ABORTED w/ code: %x\n", vmx_abort); + return -1; + } + + vm->registers = regs; + + if (CopyOutVMCSData(&(vm->vmcs)) != 0) { + PrintTrace("Could not copy out VMCS\n"); + return -1; + } + + + PrintTrace("Guest esp: 0x%x (%u)\n", vm->vmcs.guestStateArea.rsp, vm->vmcs.guestStateArea.rsp); + + PrintTrace("VM Exit for reason: %d (%x)\n", + vm->vmcs.exitInfoFields.reason & 0x00000fff, + vm->vmcs.exitInfoFields.reason); + + if (vm->vmcs.exitInfoFields.reason & (0x1<<29) ) { + PrintTrace("VM Exit is from VMX root operation. Panicking\n"); + VMXPanic(); + } + + if (vm->vmcs.exitInfoFields.reason & (0x1<<31) ) { + PrintTrace("VM Exit is due to a VM entry failure. Shouldn't happen here. Panicking\n"); + PrintTrace_VMCSData(&(vm->vmcs)); + VMXPanic(); + } + + switch (vm->vmcs.exitInfoFields.reason) { + case VM_EXIT_REASON_INFO_EXCEPTION_OR_NMI: + ret = HandleExceptionOrNMI(vm); + break; + case VM_EXIT_REASON_EXTERNAL_INTR: + ret = HandleExternalIRQExit(vm); + break; + case VM_EXIT_REASON_TRIPLE_FAULT: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_INIT_SIGNAL: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_STARTUP_IPI: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_IO_SMI: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_OTHER_SMI: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_INTR_WINDOW: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_NMI_WINDOW: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_TASK_SWITCH: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_CPUID: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_INVD: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_INVLPG: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_RDPMC: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_RDTSC: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_RSM: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMCALL: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMCLEAR: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMLAUNCH: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMPTRLD: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMPTRST: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMREAD: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMRESUME: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMWRITE: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMXOFF: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_VMXON: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_CR_REG_ACCESSES: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_MOV_DR: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_IO_INSTR: + ret = HandleInOutExit(vm); + break; + case VM_EXIT_REASON_RDMSR: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_WRMSR: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_ENTRY_FAIL_INVALID_GUEST_STATE: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_ENTRY_FAIL_MSR_LOAD: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_MWAIT: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_MONITOR: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_PAUSE: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_ENTRY_FAILURE_MACHINE_CHECK: + ret = PanicUnhandledVMExit(vm); + break; + case VM_EXIT_REASON_TPR_BELOW_THRESHOLD: + ret = PanicUnhandledVMExit(vm); + break; + default: + ret = PanicUnhandledVMExit(vm); + break; + } + + + regs = vm->registers; + CopyInVMCSData(&(vm->vmcs)); + + /* + { + VMCS_CLEAR(vmcs_ptr); + } + */ + + PrintTrace("Returning from Do_VMM: %d\n", ret); + + return ret; +} + + +static void ConfigureExits(struct VM *vm) +{ + CopyOutVMCSExecCtrlFields(&(vm->vmcs.execCtrlFields)); + + vm->vmcs.execCtrlFields.pinCtrls |= 0 + // EXTERNAL_INTERRUPT_EXITING + | NMI_EXITING; + vm->vmcs.execCtrlFields.procCtrls |= 0 + // INTERRUPT_WINDOWS_EXIT + | USE_TSC_OFFSETTING + | HLT_EXITING + |INVLPG_EXITING + |MWAIT_EXITING + |RDPMC_EXITING + |RDTSC_EXITING + |MOVDR_EXITING + |UNCONDITION_IO_EXITING + |MONITOR_EXITING + |PAUSE_EXITING ; + + CopyInVMCSExecCtrlFields(&(vm->vmcs.execCtrlFields)); + + CopyOutVMCSExitCtrlFields(&(vm->vmcs.exitCtrlFields)); + + vm->vmcs.exitCtrlFields.exitCtrls |= ACK_IRQ_ON_EXIT; + + CopyInVMCSExitCtrlFields(&(vm->vmcs.exitCtrlFields)); + + +/* VMCS_READ(VM_EXIT_CTRLS, &flags); */ +/* flags |= ACK_IRQ_ON_EXIT; */ +/* VMCS_WRITE(VM_EXIT_CTRLS, &flags); */ +} + + +extern int RunVMM(); +extern int SAFE_VM_LAUNCH(); + +int MyLaunch(struct VM *vm) +{ + ullong_t vmcs = (ullong_t)((uint_t) (vm->vmcsregion)); + uint_t entry_eip = vm->descriptor.entry_ip; + uint_t exit_eip = vm->descriptor.exit_eip; + uint_t guest_esp = vm->descriptor.guest_esp; + uint_t f = 0xffffffff; + uint_t tmpReg = 0; + int ret; + int vmm_ret = 0; + + PrintTrace("Guest ESP: 0x%x (%u)\n", guest_esp, guest_esp); + + exit_eip=(uint_t)RunVMM; + + PrintTrace("Clear\n"); + VMCS_CLEAR(vmcs); + PrintTrace("Load\n"); + VMCS_LOAD(vmcs); + + + PrintTrace("VMCS_LINK_PTR\n"); + VMCS_WRITE(VMCS_LINK_PTR, &f); + PrintTrace("VMCS_LINK_PTR_HIGH\n"); + VMCS_WRITE(VMCS_LINK_PTR_HIGH, &f); + + + SetCtrlBitsCorrectly(IA32_VMX_PINBASED_CTLS_MSR, PIN_VM_EXEC_CTRLS); + SetCtrlBitsCorrectly(IA32_VMX_PROCBASED_CTLS_MSR, PROC_VM_EXEC_CTRLS); + SetCtrlBitsCorrectly(IA32_VMX_EXIT_CTLS_MSR, VM_EXIT_CTRLS); + SetCtrlBitsCorrectly(IA32_VMX_ENTRY_CTLS_MSR, VM_ENTRY_CTRLS); + + // + // + //SetCtrlBitsCorrectly(IA32_something,GUEST_IA32_DEBUGCTL); + //SetCtrlBitsCorrectly(IA32_something,GUEST_IA32_DEBUGCTL_HIGH); + + + /* Host state */ + PrintTrace("Setting up host state\n"); + SetCRBitsCorrectly(IA32_VMX_CR0_FIXED0_MSR, IA32_VMX_CR0_FIXED1_MSR, HOST_CR0); + SetCRBitsCorrectly(IA32_VMX_CR4_FIXED0_MSR, IA32_VMX_CR4_FIXED1_MSR, HOST_CR4); + ret = Init_VMCS_HostState(); + + if (ret != VMX_SUCCESS) { + if (ret == VMX_FAIL_VALID) { + PrintTrace("Init Host state: VMCS FAILED WITH ERROR\n"); + } else { + PrintTrace("Init Host state: Invalid VMCS\n"); + } + return ret; + } + + // PrintTrace("HOST_RIP: %x (%u)\n", exit_eip, exit_eip); + VMCS_WRITE(HOST_RIP, &exit_eip); + + /* Guest state */ + PrintTrace("Setting up guest state\n"); + PrintTrace("GUEST_RIP: %x (%u)\n", entry_eip, entry_eip); + VMCS_WRITE(GUEST_RIP,&entry_eip); + + SetCRBitsCorrectly(IA32_VMX_CR0_FIXED0_MSR, IA32_VMX_CR0_FIXED1_MSR, GUEST_CR0); + SetCRBitsCorrectly(IA32_VMX_CR4_FIXED0_MSR, IA32_VMX_CR4_FIXED1_MSR, GUEST_CR4); + ret = Init_VMCS_GuestState(); + + PrintTrace("InitGuestState returned\n"); + if (ret != VMX_SUCCESS) { + if (ret == VMX_FAIL_VALID) { + PrintTrace("Init Guest state: VMCS FAILED WITH ERROR\n"); + } else { + PrintTrace("Init Guest state: Invalid VMCS\n"); + } + return ret; + } + PrintTrace("GUEST_RSP: %x (%u)\n", guest_esp, (uint_t)guest_esp); + VMCS_WRITE(GUEST_RSP,&guest_esp); + + // tmpReg = 0x4100; + tmpReg = 0xffffffff; + if (VMCS_WRITE(EXCEPTION_BITMAP,&tmpReg ) != VMX_SUCCESS) { + PrintInfo("Bitmap error\n"); + } + + ConfigureExits(vm); + + PrintTrace("VMCS_LAUNCH\n"); + + vm->state=VM_VMXASSIST_STARTUP; + + vmm_ret = SAFE_VM_LAUNCH(); + + PrintTrace("VMM error %d\n", vmm_ret); + + return vmm_ret; +} + + + + +int VMLaunch(struct VMDescriptor *vm) +{ + VMCS * vmcs = CreateVMCS(); + int rc; + + ullong_t vmcs_ptr = (ullong_t)((uint_t)vmcs); + uint_t top = (vmcs_ptr>>32)&0xffffffff; + uint_t bottom = (vmcs_ptr)&0xffffffff; + + theVM.vmcsregion = vmcs; + theVM.descriptor = *vm; + + PrintTrace("vmcs_ptr_top=%x vmcs_ptr_bottom=%x, eip=%x\n", top, bottom, vm->entry_ip); + rc=MyLaunch(&theVM); // vmcs_ptr, vm->entry_ip, vm->exit_eip, vm->guest_esp); + PrintTrace("Returned from MyLaunch();\n"); + return rc; +} + + +VmxOnRegion * CreateVmxOnRegion() { + union VMX_MSR basicMSR; + VmxOnRegion * region = (VmxOnRegion *)(os_hooks)->allocate_pages(1); + + Get_MSR(IA32_VMX_BASIC_MSR, &basicMSR.regs.high, &basicMSR.regs.low); + // memcpy(region, &basicMSR.vmxBasic.revision, sizeof(uint_t)); + + *(ulong_t*)region = basicMSR.vmxBasic.revision; + + PrintInfo("VMX revision: 0x%lu\n", *(ulong_t *)region); + + return region; +} + +VMCS * CreateVMCS() { + union VMX_MSR basicMSR; + VMCS * vmcs = (VMCS *)(os_hooks)->allocate_pages(1); + + Get_MSR(IA32_VMX_BASIC_MSR, &basicMSR.regs.high, &basicMSR.regs.low); + *(ulong_t *)vmcs = basicMSR.vmxBasic.revision; + *(ulong_t *)((char*)vmcs + 4) = 0; + + PrintTrace("VMCS Region size: %u\n", basicMSR.vmxBasic.regionSize); + PrintTrace("VMCS Abort: %x\n",*(uint_t *)(((char*)vmcs)+4)); + + return vmcs; +} diff --git a/palacios/src/palacios/vmx_lowlevel.asm b/palacios/src/palacios/vmx_lowlevel.asm new file mode 100644 index 0000000..05257c9 --- /dev/null +++ b/palacios/src/palacios/vmx_lowlevel.asm @@ -0,0 +1,936 @@ +; -*- fundamental -*- + +%ifndef VMX_ASM +%define VMX_ASM + + +%include "defs.asm" +%include "symbol.asm" + + +%include "vmcs_fields.asm" + +VMX_SUCCESS equ 0x00000000 +VMX_FAIL_INVALID equ 0x00000001 +VMX_FAIL_VALID equ 0x00000002 +VMM_ERROR equ 0x00000003 + +[BITS 32] + +IMPORT Do_VMM + + +; VMX Functions +EXPORT VMCS_READ +EXPORT VMCS_WRITE +EXPORT VMCS_CLEAR +EXPORT VMCS_LOAD +EXPORT VMCS_STORE +EXPORT Enable_VMX +EXPORT Disable_VMX +EXPORT Launch_VM +EXPORT VMCS_LAUNCH +EXPORT VMCS_RESUME +EXPORT RunVMM +EXPORT SAFE_VM_LAUNCH +EXPORT Init_VMCS_HostState +EXPORT Init_VMCS_GuestState + +; +; Enable_VMX - Turn on VMX +; +align 8 +Enable_VMX: + push ebp + mov ebp, esp + push ebx + mov ebx, cr4 + or ebx, dword 0x00002000 + mov cr4, ebx + mov ebx, cr0 + or ebx, dword 0x80000021 + mov cr0, ebx + vmxon [ebp+8] + pop ebx + pop ebp + mov eax, VMX_SUCCESS + jnc .return + mov eax, VMX_FAIL_INVALID +.return + ret + + +; +; VMREAD - read a value from a VMCS +; +align 8 +VMCS_READ: + push ebp + mov ebp, esp + push ecx + push ebx + + mov ecx, [ebp + 8] + mov ebx,[ebp + 12] +; lea ebx, ebp + vmread [ebx], ecx + + pop ebx + pop ecx + pop ebp + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + ret + +; +; VMWRITE - write a value to a VMCS +align 8 +VMCS_WRITE: + push ebp + mov ebp, esp + push ebx + + mov eax, [ebp + 8] + mov ebx, [ebp + 12] + vmwrite eax, [ebx] + + pop ebx + pop ebp + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + ret + +; +; VMCLEAR - Initializes a VMCS +; +align 8 +VMCS_CLEAR: + vmclear [esp+4] + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + ret + + + +; +; VMCS_LOAD - load a VMCS +; +align 8 +VMCS_LOAD: + vmptrld [esp+4] + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + ret + + + +; +; VMCS_STORE - Store a VMCS +; +align 8 +VMCS_STORE: + mov eax, [esp+4] + vmptrst [eax] + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + ret + + +; +; VMCS_LAUNCH +; +align 8 +VMCS_LAUNCH: + vmlaunch + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + ret + + + +; +; VMCS_RESUME +; +align 8 +VMCS_RESUME: + vmresume + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + ret + +align 8 +SAFE_VM_LAUNCH: + pushf + pusha + mov eax, HOST_RSP + vmwrite eax, esp + jz .esp_err + jc .esp_err + jmp .vm_cont + +.esp_err + popa + jz .error_code + jc .error +.vm_cont + vmlaunch + popa + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + popf + ret + + +; +; RunVMM +; +align 8 +RunVMM: + pusha + call Do_VMM + and eax, eax + jnz .vmm_error + jmp .vm_cont + +.vmm_error + popa + popa + mov eax, VMM_ERROR + jmp .return + +.vm_cont + popa + vmresume + popa ; we only get here if there is an error in the vmresume + ; we restore the host state and return an error code + + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + popf + ret + + + + +; +; Setup_VMCS_GuestState +; Copy all of the Guest registers into the guest state of a vmcs +; + +align 8 +InitGuestSelectors: + push ebp + mov ebp, esp + push ebx + push ebx + + mov ebx, VMCS_GUEST_ES_SELECTOR + mov eax, es + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_GUEST_CS_SELECTOR + mov eax, cs + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_GUEST_SS_SELECTOR + mov eax, ss + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_GUEST_DS_SELECTOR + mov eax, ds + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_GUEST_FS_SELECTOR + mov eax, fs + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_GUEST_GS_SELECTOR + mov eax, gs + vmwrite ebx, eax + jz .error_code + jc .error + + str [esp] + mov eax, [esp] + mov ebx, VMCS_GUEST_TR_SELECTOR + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + pop ebx + pop ebx + pop ebp + ret +ret + +align 8 +InitGuestDescRegs: + push ebp + mov ebp, esp + push ebx + sub esp, 6 + + + sgdt [esp] + mov eax, [esp] + and eax, 0xffff + mov ebx, GUEST_GDTR_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, [esp+2] + mov ebx, GUEST_GDTR_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + + sidt [esp] + mov eax, [esp] + and eax, 0xffff + mov ebx, GUEST_IDTR_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, [esp+2] + mov ebx, GUEST_IDTR_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + + sldt [esp] + mov eax, [esp] + mov ebx, GUEST_LDTR_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + + mov eax, 0x00000000 + mov ebx, GUEST_LDTR_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + + add esp, 6 + pop ebx + pop ebp + ret + + + + + +align 8 +InitGuestSegBases: + push ebp + mov ebp, esp + push ebx + + + mov eax, dword 0 + mov ebx, GUEST_ES_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, dword 0 + mov ebx, GUEST_CS_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, dword 0 + mov ebx, GUEST_SS_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, dword 0 + mov ebx, GUEST_DS_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, dword 0 + mov ebx, GUEST_FS_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, dword 0 + mov ebx, GUEST_GS_BASE + vmwrite ebx, eax + jz .error_code + jc .error + +; mov eax, dword 0 + mov eax, 0x000220a0 + mov ebx, GUEST_TR_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + + pop ebx + pop ebp + ret + +align 8 +InitGuestSegsAccess: + push ebp + mov ebp, esp + push ebx + + mov eax, 1100000010010011b + mov ebx, GUEST_ES_ACCESS + vmwrite ebx, eax + jz .error_code + jc .error + + + + mov eax, 1100000010011001b +; mov eax, 0x0000c099 + mov ebx, GUEST_CS_ACCESS + vmwrite ebx, eax + jz .error_code + jc .error + +; mov eax, 1100000010010111b + mov eax, 1100000010010011b + mov ebx, GUEST_SS_ACCESS + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, 1100000010010011b + mov ebx, GUEST_DS_ACCESS + vmwrite ebx, eax + jz .error_code + jc .error + + + mov eax, 1100000010010011b + mov ebx, GUEST_FS_ACCESS + vmwrite ebx, eax + jz .error_code + jc .error + + + mov eax, 1100000010010011b + mov ebx, GUEST_GS_ACCESS + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, 0x10000 + mov ebx, GUEST_LDTR_ACCESS + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, 01000000010001011b + mov ebx, GUEST_TR_ACCESS + vmwrite ebx, eax + jz .error_code + jc .error + +; + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + pop ebx + pop ebp + ret + +;; Do seg limit +align 8 +InitGuestSegsLimits: + push ebp + mov ebp, esp + push ebx + + +; mov eax, 0xffffffff + mov eax, 0xffffffff + mov ebx, GUEST_ES_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + +; mov eax, 0xffffffff + mov eax, 0xffffffff + mov ebx, GUEST_CS_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + +; mov eax, 0xffffffff + mov eax, 0xffffffff + mov ebx, GUEST_SS_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + +; mov eax, 0xffffffff + mov eax, 0xffffffff + mov ebx, GUEST_DS_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + +; mov eax, 0xffffffff + mov eax, 0xffffffff + mov ebx, GUEST_FS_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + +; mov eax, 0xffffffff + mov eax, 0xffffffff + mov ebx, GUEST_GS_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + +; mov eax, 0xffffffff + mov eax, 0x68fff + mov ebx, GUEST_TR_LIMIT + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + pop ebx + pop ebp + ret + + +align 8 +Init_VMCS_GuestState: + push ebp + mov ebp, esp + push ebx + + mov ebx, GUEST_CR3 + mov eax, cr3 + vmwrite ebx, eax + jz .error_code + jc .error + + call InitGuestSelectors + and eax, 0xffffffff + jz .selDone + jmp .return +.selDone + + call InitGuestDescRegs + and eax, 0xffffffff + jz .descRegsDone + jmp .return +.descRegsDone + + call InitGuestSegBases + and eax, 0xffffffff + jz .descSegBasesDone + jmp .return +.descSegBasesDone + + + call InitGuestSegsLimits + and eax, 0xffffffff + jz .segsLimitsDone + jmp .return +.segsLimitsDone + + call InitGuestSegsAccess + and eax, 0xffffffff + jz .segsAccessDone + jmp .return +.segsAccessDone + + mov ebx, GUEST_RSP + mov eax, esp + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, GUEST_RFLAGS + mov eax, dword 0x00000002 + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, GUEST_DR7 + mov eax, dword 0x00000400 + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + pop ebx + pop ebp + ret + +; +; Setup_VMCS_HostState +; Copy all of the host registers into the host state of a vmcs +; + +align 8 +InitHostSelectors: + push ebp + mov ebp, esp + push ebx + push ebx + + mov ebx, VMCS_HOST_ES_SELECTOR + mov eax, es + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_HOST_CS_SELECTOR + mov eax, cs + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_HOST_SS_SELECTOR + mov eax, ss + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_HOST_DS_SELECTOR + mov eax, ds + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_HOST_FS_SELECTOR + mov eax, fs + vmwrite ebx, eax + jz .error_code + jc .error + + mov ebx, VMCS_HOST_GS_SELECTOR + mov eax, gs + vmwrite ebx, eax + jz .error_code + jc .error + + str [esp] + mov eax, [esp] + mov ebx, VMCS_HOST_TR_SELECTOR + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + pop ebx + pop ebx + pop ebp + ret +ret + + + + + +align 8 +InitHostBaseRegs: + push ebp + mov ebp, esp + push ebx + sub esp, 6 + + sgdt [esp] + mov eax, [esp+2] + mov ebx, HOST_GDTR_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + sidt [esp] + mov eax, [esp+2] + mov ebx, HOST_IDTR_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + + mov eax, dword 0 + mov ebx, HOST_FS_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, dword 0 + mov ebx, HOST_GS_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, dword 0 + mov ebx, HOST_TR_BASE + vmwrite ebx, eax + jz .error_code + jc .error + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + + add esp, 6 + pop ebx + pop ebp + ret + + +align 8 +Init_VMCS_HostState: + push ebp + mov ebp, esp + push ebx + + mov ebx, HOST_CR3 + mov eax, cr3 + vmwrite ebx, eax + jz .error_code + jc .error + + + mov ebx, HOST_RSP + mov eax, esp + vmwrite ebx, eax + jz .error_code + jc .error + +; push esp + call InitHostSelectors + and eax, 0xffffffff + jz .selDone + jmp .return +.selDone +; push esp + call InitHostBaseRegs + and eax, 0xffffffff + jz .baseRegsDone + jmp .return +.baseRegsDone + + + mov eax, VMX_SUCCESS + jmp .return +.error + mov eax, VMX_FAIL_INVALID + jmp .return +.error_code + mov eax, VMX_FAIL_VALID +.return + pop ebx + pop ebp + ret + +; +; Launch_VM - inits a vmcs with an ip and launches it +; [eip = ebp + 8], [vmcs = ebp + 12] +; int Launch_VM(ullont_t VMCS, uint_t eip); +; +align 8 +Launch_VM: + push ebp + mov ebp, esp + push ebx + mov ebx, dword 0 + vmclear [ebp+8] + jz .error_code + jc .error + add ebx, dword 1 + vmptrld [ebp+8] + jz .error_code + jc .error + mov eax, dword 0x0000681E + add ebx, dword 1 + vmwrite eax, [ebp+16] + jz .error_code + jc .error + add ebx, dword 1 + vmlaunch + jz .error_code + jc .error + mov eax, VMX_SUCCESS + jmp .return +.error + shl ebx, 4 + mov eax, VMX_FAIL_INVALID + or eax, ebx + jmp .return +.error_code + shl ebx, 4 + mov eax, VMX_FAIL_VALID + or eax, ebx + mov ebx, dword 0x00004400 + vmread eax, ebx +.return + pop ebx + pop ebp + + ret + + +%endif