From: Jack Lange Date: Tue, 31 Mar 2009 20:42:42 +0000 (-0500) Subject: Merge branch 'devel' into ide X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=ee177da9b30ebf340c63fb5b9d535c729f90134d;hp=b86b717be870723228190fcc9c8233a511d95073 Merge branch 'devel' into ide Conflicts: misc/test_vm/build/Makefile palacios/build/Makefile --- diff --git a/build/Makefile b/build/Makefile index aecdd92..fb57c3e 100644 --- a/build/Makefile +++ b/build/Makefile @@ -51,6 +51,14 @@ DEBUG_SECTIONS := $(DEBUG_SECTIONS) DEBUG_SHADOW_PAGING=0 endif endif +ifeq ($(DEBUG_NESTED_PAGING),1) +DEBUG_SECTIONS := $(DEBUG_SECTIONS) DEBUG_NESTED_PAGING=1 +else +ifeq ($(DEBUG_NESTED_PAGING),0) +DEBUG_SECTIONS := $(DEBUG_SECTIONS) DEBUG_NESTED_PAGING=0 +endif +endif + ifeq ($(DEBUG_CTRL_REGS),1) DEBUG_SECTIONS := $(DEBUG_SECTIONS) DEBUG_CTRL_REGS=1 else diff --git a/misc/test_vm/build/Makefile b/misc/test_vm/build/Makefile index 47bd48e..c38b9f4 100644 --- a/misc/test_vm/build/Makefile +++ b/misc/test_vm/build/Makefile @@ -38,14 +38,15 @@ KERNEL_ENTRY = $(SYM_PFX)Main PROJECT_ROOT := .. VPATH := $(PROJECT_ROOT)/src -#when -DNDEBUG is set the kassert functions are disabled -#JRLDEBUG=-DNDEBUG + + ifeq ($(SERIAL_DEBUG), 1) JRLDEBUG= -DDEBUG_SERIAL else JRLDEBUG= endif + # Figure out if we're compiling with cygwin, http://cygwin.com SYSTEM_NAME := $(shell uname -s) ifeq ($(findstring CYGWIN,$(SYSTEM_NAME)),CYGWIN) @@ -178,6 +179,7 @@ NUMSECS := $(PERL) $(PROJECT_ROOT)/scripts/numsecs # ---------------------------------------------------------------------- # Flags used for all C source files + GENERAL_OPTS := -O -Wall $(EXTRA_C_OPTS) $(JRLDEBUG) CC_GENERAL_OPTS := $(GENERAL_OPTS) -Werror diff --git a/palacios/build/Makefile b/palacios/build/Makefile index 6d62c0b..f243949 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -62,7 +62,7 @@ endif ifeq ($(DEBUG_ALL),1) - DEBUG_SECTIONS:= $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING -DDEBUG_CTRL_REGS -DDEBUG_INTERRUPTS -DDEBUG_KEYBOARD -DDEBUG_PIC -DDEBUG_PIT -DDEBUG_NVRAM -DDEBUG_EMULATOR -DDEBUG_XED -DDEBUG_HALT -DDEBUG_DEV_MGR + DEBUG_SECTIONS:= $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING -DDEBUG_NESTED_PAGING -DDEBUG_CTRL_REGS -DDEBUG_INTERRUPTS -DDEBUG_KEYBOARD -DDEBUG_PIC -DDEBUG_PIT -DDEBUG_NVRAM -DDEBUG_EMULATOR -DDEBUG_XED -DDEBUG_HALT -DDEBUG_DEV_MGR # -DDEBUG_IO -DDEBUG_GENERIC -DDEBUG_IDE endif @@ -73,6 +73,14 @@ else ifeq ($(DEBUG_SHADOW_PAGING),0) DEBUG_SECTIONS := $(DEBUG_SECTIONS) -UDEBUG_SHADOW_PAGING endif + +endif +ifeq ($(DEBUG_NESTED_PAGING),1) +DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_NESTED_PAGING +else +ifeq ($(DEBUG_NESTED_PAGING),0) +DEBUG_SECTIONS := $(DEBUG_SECTIONS) -UDEBUG_NESTED_PAGING +endif endif ifeq ($(DEBUG_CTRL_REGS),1) @@ -263,6 +271,7 @@ VMM_OBJS := \ palacios/vmm_debug.o \ palacios/svm_io.o \ palacios/vmm_intr.o \ + palacios/vmm_excp.o \ palacios/vmm_time.o \ palacios/vmm_shadow_paging.o \ palacios/vm_guest_mem.o \ @@ -522,13 +531,7 @@ vgabios_link: ln -s -f ../src/vmboot/vgabios/VGABIOS-lgpl-latest.bin vgabios -force_rombios: rombios_link - (cd ../src/vmboot/rombios; make clean; make) - -force_vgabios: vgabios_link - (cd ../src/vmboot/vgabios; make clean; make) - -force_payload: force_rombios force_vgabios +force_payload: rombios_link vgabios_link ../scripts/make_payload.pl payload_layout.txt vm_kernel inter1: force_payload diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 23329eb..005d32b 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +136,9 @@ struct guest_info { // This structure is how we get interrupts for the guest struct v3_intr_state intr_state; + // This structure is how we get exceptions for the guest + struct v3_excp_state excp_state; + v3_io_map_t io_map; struct v3_msr_map msr_map; diff --git a/palacios/include/palacios/vmm.h b/palacios/include/palacios/vmm.h index 9e9f812..4a4ed79 100644 --- a/palacios/include/palacios/vmm.h +++ b/palacios/include/palacios/vmm.h @@ -273,6 +273,7 @@ struct v3_vm_config { int enable_profiling; + int enable_nested_paging; int use_ramdisk; void * ramdisk; diff --git a/palacios/include/palacios/vmm_direct_paging.h b/palacios/include/palacios/vmm_direct_paging.h index 3bae7e3..22843fd 100644 --- a/palacios/include/palacios/vmm_direct_paging.h +++ b/palacios/include/palacios/vmm_direct_paging.h @@ -29,6 +29,7 @@ addr_t v3_create_direct_passthrough_pts(struct guest_info * guest_info); int v3_handle_passthrough_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code); +int v3_handle_nested_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code); #endif // ! __V3VEE__ diff --git a/palacios/include/palacios/vmm_excp.h b/palacios/include/palacios/vmm_excp.h new file mode 100644 index 0000000..9e15e32 --- /dev/null +++ b/palacios/include/palacios/vmm_excp.h @@ -0,0 +1,74 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __VMM_EXCP_H__ +#define __VMM_EXCP_H__ + +#ifdef __V3VEE__ + + +#include + +#define DE_EXCEPTION 0x00 +#define DB_EXCEPTION 0x01 +#define NMI_EXCEPTION 0x02 +#define BP_EXCEPTION 0x03 +#define OF_EXCEPTION 0x04 +#define BR_EXCEPTION 0x05 +#define UD_EXCEPTION 0x06 +#define NM_EXCEPTION 0x07 +#define DF_EXCEPTION 0x08 +#define TS_EXCEPTION 0x0a +#define NP_EXCEPTION 0x0b +#define SS_EXCEPTION 0x0c +#define GPF_EXCEPTION 0x0d +#define PF_EXCEPTION 0x0e +#define MF_EXCEPTION 0x10 +#define AC_EXCEPTION 0x11 +#define MC_EXCEPTION 0x12 +#define XF_EXCEPTION 0x13 +#define SX_EXCEPTION 0x1e + + +struct guest_info; + +struct v3_excp_state { + + /* We need to rework the exception state, to handle stacking */ + uint_t excp_pending; + uint_t excp_num; + uint_t excp_error_code_valid : 1; + uint_t excp_error_code; + +}; + + +void v3_init_exception_state(struct guest_info * info); + + +int v3_raise_exception(struct guest_info * info, uint_t excp); +int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code); + +int v3_excp_pending(struct guest_info * info); +int v3_get_excp_number(struct guest_info * info); +int v3_injecting_excp(struct guest_info * info, uint_t excp); + +#endif + +#endif diff --git a/palacios/include/palacios/vmm_intr.h b/palacios/include/palacios/vmm_intr.h index be407c1..82de275 100644 --- a/palacios/include/palacios/vmm_intr.h +++ b/palacios/include/palacios/vmm_intr.h @@ -26,28 +26,9 @@ #include #include -#define DE_EXCEPTION 0x00 -#define DB_EXCEPTION 0x01 -#define NMI_EXCEPTION 0x02 -#define BP_EXCEPTION 0x03 -#define OF_EXCEPTION 0x04 -#define BR_EXCEPTION 0x05 -#define UD_EXCEPTION 0x06 -#define NM_EXCEPTION 0x07 -#define DF_EXCEPTION 0x08 -#define TS_EXCEPTION 0x0a -#define NP_EXCEPTION 0x0b -#define SS_EXCEPTION 0x0c -#define GPF_EXCEPTION 0x0d -#define PF_EXCEPTION 0x0e -#define MF_EXCEPTION 0x10 -#define AC_EXCEPTION 0x11 -#define MC_EXCEPTION 0x12 -#define XF_EXCEPTION 0x13 -#define SX_EXCEPTION 0x1e - - -typedef enum {INVALID_INTR, EXTERNAL_IRQ, NMI, EXCEPTION, SOFTWARE_INTR, VIRTUAL_INTR} intr_type_t; + + +typedef enum {INVALID_INTR, EXTERNAL_IRQ, NMI, SOFTWARE_INTR, VIRTUAL_INTR} intr_type_t; struct guest_info; struct v3_interrupt; @@ -65,15 +46,8 @@ struct v3_irq_hook { struct v3_intr_state { - /* We need to rework the exception state, to handle stacking */ - uint_t excp_pending; - uint_t excp_num; - uint_t excp_error_code_valid : 1; - uint_t excp_error_code; - struct list_head controller_list; - uint_t irq_pending; uint_t irq_vector; @@ -102,12 +76,8 @@ struct intr_ctrl_ops { - void v3_register_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * state); -int v3_raise_exception(struct guest_info * info, uint_t excp); -int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code); - int v3_intr_pending(struct guest_info * info); uint_t v3_get_intr_number(struct guest_info * info); intr_type_t v3_get_intr_type(struct guest_info * info); diff --git a/palacios/src/devices/apic.c b/palacios/src/devices/apic.c index 13ead3c..92e6683 100644 --- a/palacios/src/devices/apic.c +++ b/palacios/src/devices/apic.c @@ -168,6 +168,7 @@ struct apic_state { uint32_t tmr_init_cnt; + struct local_vec_tbl_reg ext_intr_vec_tbl[4]; uint32_t rem_rd_data; @@ -223,6 +224,7 @@ static void init_apic_state(struct apic_state * apic) { apic->lint1_vec_tbl.val = 0x00010000; apic->err_vec_tbl.val = 0x00010000; apic->tmr_div_cfg.val = 0x00000000; + //apic->ext_apic_feature.val = 0x00000007; apic->ext_apic_feature.val = 0x00040007; apic->ext_apic_ctrl.val = 0x00000000; apic->spec_eoi.val = 0x00000000; @@ -337,12 +339,12 @@ static int apic_do_eoi(struct apic_state * apic) { #ifdef CRAY_XT - if ((((i * 8) + j) == 238) || - (((i * 8) + j) == 239)) { - PrintError("Acking IRQ %d\n", ((i * 8) + j)); + if ((isr_irq == 238) || + (isr_irq == 239)) { + PrintError("Acking IRQ %d\n", isr_irq); } - if (((i * 8) + j) == 238) { + if (isr_irq == 238) { V3_ACK_IRQ(238); } #endif @@ -618,9 +620,19 @@ static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_d // Unhandled Registers case EXT_INT_LOC_VEC_TBL_OFFSET0: + val = apic->ext_intr_vec_tbl[0].val; + break; case EXT_INT_LOC_VEC_TBL_OFFSET1: + val = apic->ext_intr_vec_tbl[1].val; + break; case EXT_INT_LOC_VEC_TBL_OFFSET2: + val = apic->ext_intr_vec_tbl[2].val; + break; case EXT_INT_LOC_VEC_TBL_OFFSET3: + val = apic->ext_intr_vec_tbl[3].val; + break; + + case EXT_APIC_FEATURE_OFFSET: case EXT_APIC_CMD_OFFSET: case SEOI_OFFSET: @@ -791,7 +803,20 @@ static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_ case IER_OFFSET7: *(uint32_t *)(apic->int_en_reg + 28) = op_val; break; - + + case EXT_INT_LOC_VEC_TBL_OFFSET0: + apic->ext_intr_vec_tbl[0].val = op_val; + break; + case EXT_INT_LOC_VEC_TBL_OFFSET1: + apic->ext_intr_vec_tbl[1].val = op_val; + break; + case EXT_INT_LOC_VEC_TBL_OFFSET2: + apic->ext_intr_vec_tbl[2].val = op_val; + break; + case EXT_INT_LOC_VEC_TBL_OFFSET3: + apic->ext_intr_vec_tbl[3].val = op_val; + break; + // Action Registers case EOI_OFFSET: @@ -802,10 +827,7 @@ static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_ case INT_CMD_LO_OFFSET: case INT_CMD_HI_OFFSET: // Unhandled Registers - case EXT_INT_LOC_VEC_TBL_OFFSET0: - case EXT_INT_LOC_VEC_TBL_OFFSET1: - case EXT_INT_LOC_VEC_TBL_OFFSET2: - case EXT_INT_LOC_VEC_TBL_OFFSET3: + case EXT_APIC_CMD_OFFSET: case SEOI_OFFSET: default: diff --git a/palacios/src/devices/cdrom.c b/palacios/src/devices/cdrom.c index b46a361..43dafd8 100644 --- a/palacios/src/devices/cdrom.c +++ b/palacios/src/devices/cdrom.c @@ -77,14 +77,14 @@ static rd_bool cdrom_read_toc(void * private_data, uint8_t* buf, int* length, rd static uint32_t cdrom_capacity(void * private_data) { struct cdrom_state * cdrom = (struct cdrom_state *)private_data; - PrintDebug("[cdrom_capacity] s_ramdiskSize = %d\n", cdrom->capacity_in_bytes); + PrintDebug("[cdrom_capacity] s_ramdiskSize = %lu\n", cdrom->capacity_in_bytes); if (cdrom->lba) { if (cdrom->capacity_in_bytes % 2048) { - PrintDebug("\t\t capacity in LBA is %d\n", (cdrom->capacity_in_bytes / 2048) + 1); + PrintDebug("\t\t capacity in LBA is %lu\n", (cdrom->capacity_in_bytes / 2048) + 1); return (cdrom->capacity_in_bytes / 2048) + 1; } else { - PrintDebug("\t\t capacity in LBA is %d\n", cdrom->capacity_in_bytes / 2048); + PrintDebug("\t\t capacity in LBA is %lu\n", cdrom->capacity_in_bytes / 2048); return cdrom->capacity_in_bytes / 2048; } } else { @@ -102,7 +102,7 @@ static void cdrom_read_block(void * private_data, uint8_t * buf, int lba)/* __at V3_ASSERT(lba != 0); - PrintDebug("[cdrom_read_block] lba = %d (cdrom_image_start=%x)\n", lba, cdrom->image_addr); + PrintDebug("[cdrom_read_block] lba = %d (cdrom_image_start=%p)\n", lba, (void*)cdrom->image_addr); memcpy(buf, (uchar_t *)(cdrom->image_addr + lba * 2048), 2048); //PrintDebug("Returning from read block\n"); return; @@ -139,7 +139,7 @@ static struct cdrom_ops cd_ops = { static int cdrom_device_init(struct vm_device * dev) { struct cdrom_state * cdrom = (struct cdrom_state *)dev->private_data; PrintDebug("[cdrom_init]\n"); - PrintDebug("CDIMAGE located at: %x\n", cdrom->image_addr); + PrintDebug("CDIMAGE located at: %p\n", (void *)cdrom->image_addr); //FIXME:lba cdrom->lba = 1; diff --git a/palacios/src/devices/generic.c b/palacios/src/devices/generic.c index cc26934..cc9cc69 100644 --- a/palacios/src/devices/generic.c +++ b/palacios/src/devices/generic.c @@ -220,7 +220,7 @@ static int generic_init_device(struct vm_device * dev) { list_for_each_entry(tmp, &(state->port_list), range_link) { uint_t i = 0; - PrintDebug("generic: hooking ports 0x%x to 0x%x as %x\n", + PrintDebug("generic: hooking ports 0x%x to 0x%x as %s\n", tmp->start, tmp->end, (tmp->type == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore"); @@ -251,12 +251,12 @@ static int generic_init_device(struct vm_device * dev) { list_for_each_entry(tmp, &(state->mem_list), range_link) { - PrintDebug("generic: hooking addresses 0x%x to 0x%x\n", + PrintDebug("generic: hooking addresses 0x%p to 0x%p\n", tmp->start, tmp->end); if (v3_dev_hook_mem(dev, tmp->start, tmp->end)) { - PrintDebug("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n", + PrintDebug("generic: Can't hook addresses 0x%p to 0x%p (already hooked?)\n", tmp->start, tmp->end); } } @@ -331,11 +331,11 @@ static int generic_deinit_device(struct vm_device * dev) { list_for_each_entry_safe(cur, tmp, &(state->mem_list), range_link) { - PrintDebug("generic: unhooking addresses 0x%x to 0x%x\n", + PrintDebug("generic: unhooking addresses 0x%p to 0x%p\n", cur->start, cur->end); if (v3_dev_unhook_mem(dev, cur->start, cur->end)) { - PrintDebug("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n", + PrintDebug("generic: Can't unhook addresses 0x%p to 0x%p (already unhooked?)\n", cur->start, cur->end); } @@ -404,7 +404,7 @@ int v3_generic_add_port_range(struct vm_device * dev, uint_t start, uint_t end, range->type = type; - PrintDebug("generic: Adding Port Range: 0x%x to 0x%x as %x\n", + PrintDebug("generic: Adding Port Range: 0x%x to 0x%x as %s\n", range->start, range->end, (range->type == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore"); diff --git a/palacios/src/devices/ramdisk.c b/palacios/src/devices/ramdisk.c index c7668de..04602f7 100644 --- a/palacios/src/devices/ramdisk.c +++ b/palacios/src/devices/ramdisk.c @@ -2438,29 +2438,8 @@ static void rd_print_state(struct ramdisk_t * ramdisk) { memset((char *)(channels + channel), 0, sizeof(struct channel_t)); } */ - PrintDebug("sizeof(*channels) = %d\n", sizeof(*channels)); - PrintDebug("sizeof(channles->drives[0].controller) = %d\n", sizeof((channels->drives[0].controller))); - PrintDebug("sizeof(channles->drives[0].cdrom) = %d\n", sizeof((channels->drives[0].cdrom))); - PrintDebug("sizeof(channles->drives[0].sense) = %d\n", sizeof((channels->drives[0].sense))); - PrintDebug("sizeof(channles->drives[0].atapi) = %d\n", sizeof((channels->drives[0].atapi))); - PrintDebug("sizeof(channles->drives[0].controller.status) = %d\n", - sizeof((channels->drives[0].controller.status))); - PrintDebug("sizeof(channles->drives[0].controller.sector_count) = %d\n", - sizeof((channels->drives[0].controller.sector_count))); - PrintDebug("sizeof(channles->drives[0].controller.interrupt_reason) = %d\n", - sizeof((channels->drives[0].controller.interrupt_reason))); - - PrintDebug("sizeof(channles->drives[0].controller.cylinder_no) = %d\n", - sizeof((channels->drives[0].controller.cylinder_no))); - PrintDebug("sizeof(channles->drives[0].controller.byte_count) = %d\n", - sizeof((channels->drives[0].controller.byte_count))); - - - PrintDebug("sizeof(channles->drives[0].controller.control) = %d\n", - sizeof((channels->drives[0].controller.control))); - for (channel = 0; channel < MAX_ATA_CHANNEL; channel++){ diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index d578a17..7325bdf 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -72,11 +72,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { guest_state->cpl = 0; - //ctrl_area->instrs.instrs.CR0 = 1; - ctrl_area->cr_reads.cr0 = 1; - ctrl_area->cr_writes.cr0 = 1; - //ctrl_area->cr_reads.cr4 = 1; - ctrl_area->cr_writes.cr4 = 1; + /* Set up the efer to enable 64 bit page tables */ @@ -90,15 +86,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { cr4->pae = 1; } */ - guest_state->efer |= EFER_MSR_svm_enable; - vm_info->guest_efer.value = 0x0LL; - - v3_hook_msr(vm_info, EFER_MSR, - &v3_handle_efer_read, - &v3_handle_efer_write, - vm_info); - guest_state->rflags = 0x00000002; // The reserved bit is always 1 @@ -115,11 +103,12 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { ctrl_area->svm_instrs.MONITOR = 1; ctrl_area->svm_instrs.MWAIT_always = 1; ctrl_area->svm_instrs.MWAIT_if_armed = 1; + ctrl_area->instrs.INVLPGA = 1; ctrl_area->instrs.HLT = 1; // guest_state->cr0 = 0x00000001; // PE - ctrl_area->guest_ASID = 1; + /* @@ -235,28 +224,33 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { if (vm_info->shdw_pg_mode == SHADOW_PAGING) { PrintDebug("Creating initial shadow page table\n"); + ctrl_area->guest_ASID = 1; - - /* Testing 64 bit page tables for long paged real mode guests */ - // vm_info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(vm_info)); vm_info->direct_map_pt = (addr_t)V3_PAddr((void *)v3_create_direct_passthrough_pts(vm_info)); - /* End Test */ vm_info->shdw_pg_state.guest_cr0 = 0x0000000000000010LL; PrintDebug("Created\n"); - guest_state->cr3 = vm_info->direct_map_pt; - - //PrintDebugPageTables((pde32_t*)(vm_info->shdw_pg_state.shadow_cr3.e_reg.low)); - + ctrl_area->cr_reads.cr0 = 1; + ctrl_area->cr_writes.cr0 = 1; + //ctrl_area->cr_reads.cr4 = 1; + ctrl_area->cr_writes.cr4 = 1; ctrl_area->cr_reads.cr3 = 1; ctrl_area->cr_writes.cr3 = 1; + vm_info->guest_efer.value = 0x0LL; + + v3_hook_msr(vm_info, EFER_MSR, + &v3_handle_efer_read, + &v3_handle_efer_write, + vm_info); + + ctrl_area->instrs.INVLPG = 1; - ctrl_area->instrs.INVLPGA = 1; + ctrl_area->exceptions.pf = 1; @@ -264,7 +258,6 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { /* We need to fix this */ ctrl_area->TLB_CONTROL = 1; - guest_state->g_pat = 0x7040600070406ULL; guest_state->cr0 |= 0x80000000; @@ -272,6 +265,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { } else if (vm_info->shdw_pg_mode == NESTED_PAGING) { // Flush the TLB on entries/exits ctrl_area->TLB_CONTROL = 1; + ctrl_area->guest_ASID = 1; // Enable Nested Paging ctrl_area->NP_ENABLE = 1; @@ -279,7 +273,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { PrintDebug("NP_Enable at 0x%p\n", (void *)&(ctrl_area->NP_ENABLE)); // Set the Nested Page Table pointer - vm_info->direct_map_pt = ((addr_t)v3_create_direct_passthrough_pts(vm_info) & ~0xfff); + vm_info->direct_map_pt = (addr_t)V3_PAddr((void *)v3_create_direct_passthrough_pts(vm_info)); ctrl_area->N_CR3 = vm_info->direct_map_pt; // ctrl_area->N_CR3 = Get_CR3(); @@ -370,8 +364,8 @@ static int start_svm_guest(struct guest_info *info) { struct v3_msr host_gs_base; struct v3_msr host_kerngs_base; - v3_enable_ints(); - v3_clgi(); +/* v3_enable_ints(); */ +/* v3_clgi(); */ /* @@ -413,7 +407,7 @@ static int start_svm_guest(struct guest_info *info) { //PrintDebug("Turning on global interrupts\n"); v3_stgi(); - + v3_clgi(); if ((num_exits % 5000) == 0) { PrintDebug("SVM Exit number %d\n", num_exits); @@ -557,6 +551,7 @@ static int has_svm_nested_paging() { void v3_init_SVM(struct v3_ctrl_ops * vmm_ops) { reg_ex_t msr; void * host_state; + extern v3_cpu_arch_t v3_cpu_type; // Enable SVM on the CPU v3_get_msr(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low)); @@ -578,7 +573,11 @@ void v3_init_SVM(struct v3_ctrl_ops * vmm_ops) { PrintDebug("Host State being saved at %p\n", (void *)(addr_t)host_state); v3_set_msr(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low); - + if (has_svm_nested_paging() == 1) { + v3_cpu_type = V3_SVM_REV3_CPU; + } else { + v3_cpu_type = V3_SVM_CPU; + } // Setup the SVM specific vmm operations vmm_ops->init_guest = &init_svm_guest; diff --git a/palacios/src/palacios/svm_handler.c b/palacios/src/palacios/svm_handler.c index 5afadae..931bb99 100644 --- a/palacios/src/palacios/svm_handler.c +++ b/palacios/src/palacios/svm_handler.c @@ -32,7 +32,7 @@ #include #include #include - +#include @@ -74,12 +74,15 @@ int v3_handle_svm_exit(struct guest_info * info) { if ((info->intr_state.irq_pending == 1) && (guest_ctrl->guest_ctrl.V_IRQ == 0)) { // Interrupt was taken in the guest #ifdef DEBUG_INTERRUPTS - if ((info->intr_state.irq_vector == 238) || - (info->intr_state.irq_vector == 239)) { - PrintDebug("Interrupt %d taken by guest\n", info->intr_state.irq_vector); - } + PrintDebug("Interrupt %d taken by guest\n", info->intr_state.irq_vector); +#endif + if (!guest_ctrl->exit_int_info.valid) { + v3_injecting_intr(info, info->intr_state.irq_vector, EXTERNAL_IRQ); + } else { +#ifdef DEBUG_INTERRUPTS + PrintDebug("EXIT INT INFO is set (vec=%d)\n", guest_ctrl->exit_int_info.vector); #endif - v3_injecting_intr(info, info->intr_state.irq_vector, EXTERNAL_IRQ); + } } info->intr_state.irq_pending = 0; @@ -244,12 +247,20 @@ int v3_handle_svm_exit(struct guest_info * info) { } break; } - case VMEXIT_NPF: + case VMEXIT_NPF: { + addr_t fault_addr = guest_ctrl->exit_info2; + pf_error_t * error_code = (pf_error_t *)&(guest_ctrl->exit_info1); - PrintError("Currently unhandled Nested Page Fault\n"); - return -1; - + if (info->shdw_pg_mode == NESTED_PAGING) { + if (v3_handle_nested_pagefault(info, fault_addr, *error_code) == -1) { + return -1; + } + } else { + PrintError("Currently unhandled Nested Page Fault\n"); + return -1; + } break; + } case VMEXIT_INVLPG: if (info->shdw_pg_mode == SHADOW_PAGING) { #ifdef DEBUG_SHADOW_PAGING @@ -350,7 +361,29 @@ int v3_handle_svm_exit(struct guest_info * info) { // Update the low level state - if (v3_intr_pending(info)) { + if (v3_excp_pending(info)) { + uint_t excp = v3_get_excp_number(info); + + guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION; + + if (info->excp_state.excp_error_code_valid) { + guest_ctrl->EVENTINJ.error_code = info->excp_state.excp_error_code; + guest_ctrl->EVENTINJ.ev = 1; +#ifdef DEBUG_INTERRUPTS + PrintDebug("Injecting exception %d with error code %x\n", excp, guest_ctrl->EVENTINJ.error_code); +#endif + } + + guest_ctrl->EVENTINJ.vector = excp; + + guest_ctrl->EVENTINJ.valid = 1; +#ifdef DEBUG_INTERRUPTS + PrintDebug("Injecting Exception %d (EIP=%p)\n", + guest_ctrl->EVENTINJ.vector, + (void *)(addr_t)info->rip); +#endif + v3_injecting_excp(info, excp); + } else if (v3_intr_pending(info)) { switch (v3_get_intr_type(info)) { case EXTERNAL_IRQ: { @@ -358,11 +391,6 @@ int v3_handle_svm_exit(struct guest_info * info) { // check to see if ==-1 (non exists) - /* - guest_ctrl->EVENTINJ.vector = irq; - guest_ctrl->EVENTINJ.valid = 1; - guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXTERNAL_INTR; - */ guest_ctrl->guest_ctrl.V_IRQ = 1; guest_ctrl->guest_ctrl.V_INTR_VECTOR = irq; @@ -370,11 +398,9 @@ int v3_handle_svm_exit(struct guest_info * info) { guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf; #ifdef DEBUG_INTERRUPTS - if ((irq == 238) || (irq == 239)) { - PrintDebug("Injecting Interrupt %d (EIP=%p)\n", - guest_ctrl->guest_ctrl.V_INTR_VECTOR, - (void *)(addr_t)info->rip); - } + PrintDebug("Injecting Interrupt %d (EIP=%p)\n", + guest_ctrl->guest_ctrl.V_INTR_VECTOR, + (void *)(addr_t)info->rip); #endif info->intr_state.irq_pending = 1; @@ -385,32 +411,6 @@ int v3_handle_svm_exit(struct guest_info * info) { case NMI: guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI; break; - case EXCEPTION: { - uint_t excp = v3_get_intr_number(info); - - guest_ctrl->EVENTINJ.type = SVM_INJECTION_EXCEPTION; - - if (info->intr_state.excp_error_code_valid) { //PAD - guest_ctrl->EVENTINJ.error_code = info->intr_state.excp_error_code; - guest_ctrl->EVENTINJ.ev = 1; -#ifdef DEBUG_INTERRUPTS - // PrintDebug("Injecting exception %d with error code %x\n", excp, guest_ctrl->EVENTINJ.error_code); -#endif - } - - guest_ctrl->EVENTINJ.vector = excp; - - guest_ctrl->EVENTINJ.valid = 1; -#ifdef DEBUG_INTERRUPTS - /* - PrintDebug("Injecting Exception %d (EIP=%p)\n", - guest_ctrl->EVENTINJ.vector, - (void *)(addr_t)info->rip); - */ -#endif - v3_injecting_intr(info, excp, EXCEPTION); - break; - } case SOFTWARE_INTR: guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR; break; diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c index 87a1ae6..c981a3c 100644 --- a/palacios/src/palacios/vm_guest.c +++ b/palacios/src/palacios/vm_guest.c @@ -28,14 +28,17 @@ v3_vm_cpu_mode_t v3_get_cpu_mode(struct guest_info * info) { struct cr0_32 * cr0; + struct efer_64 * efer; struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4); - struct efer_64 * efer = (struct efer_64 *)&(info->guest_efer); struct v3_segment * cs = &(info->segments.cs); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); if (info->shdw_pg_mode == SHADOW_PAGING) { cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); + efer = (struct efer_64 *)&(info->guest_efer); } else if (info->shdw_pg_mode == NESTED_PAGING) { cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0); + efer = (struct efer_64 *)&(guest_state->efer); } else { PrintError("Invalid Paging Mode...\n"); V3_ASSERT(0); @@ -60,13 +63,16 @@ v3_vm_cpu_mode_t v3_get_cpu_mode(struct guest_info * info) { uint_t v3_get_addr_width(struct guest_info * info) { struct cr0_32 * cr0; struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4); - struct efer_64 * efer = (struct efer_64 *)&(info->guest_efer); + struct efer_64 * efer; struct v3_segment * cs = &(info->segments.cs); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); if (info->shdw_pg_mode == SHADOW_PAGING) { cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); + efer = (struct efer_64 *)&(info->guest_efer); } else if (info->shdw_pg_mode == NESTED_PAGING) { cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0); + efer = (struct efer_64 *)&(guest_state->efer); } else { PrintError("Invalid Paging Mode...\n"); V3_ASSERT(0); diff --git a/palacios/src/palacios/vm_guest_mem.c b/palacios/src/palacios/vm_guest_mem.c index b17dd76..c88ecd2 100644 --- a/palacios/src/palacios/vm_guest_mem.c +++ b/palacios/src/palacios/vm_guest_mem.c @@ -68,15 +68,20 @@ int host_pa_to_host_va(addr_t host_pa, addr_t * host_va) { int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_pa) { struct v3_shadow_region * shdw_reg = v3_get_shadow_region(guest_info, guest_pa); - *host_pa = v3_get_shadow_addr(shdw_reg, guest_pa); - - if ((shdw_reg == NULL) || - (shdw_reg->host_type == SHDW_REGION_INVALID) || - (shdw_reg->host_type == SHDW_REGION_FULL_HOOK)){ + if (shdw_reg == NULL) { + PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (NULL REGION)\n", + (void *)guest_pa); + return -1; + } + + if ((shdw_reg->host_type == SHDW_REGION_INVALID) || + (shdw_reg->host_type == SHDW_REGION_FULL_HOOK)) { PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (reg_type=%s)\n", (void *)guest_pa, v3_shdw_region_type_to_str(shdw_reg->host_type)); return -1; } + + *host_pa = v3_get_shadow_addr(shdw_reg, guest_pa); return 0; } diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index a5ec77e..be73f33 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -88,10 +88,12 @@ int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) v3_init_hypercall_map(info); - - if (v3_cpu_type == V3_SVM_REV3_CPU) { + if ((v3_cpu_type == V3_SVM_REV3_CPU) && + (config_ptr->enable_nested_paging == 1)) { + PrintDebug("Guest Page Mode: NESTED_PAGING\n"); info->shdw_pg_mode = NESTED_PAGING; } else { + PrintDebug("Guest Page Mode: SHADOW_PAGING\n"); v3_init_shadow_page_state(info); info->shdw_pg_mode = SHADOW_PAGING; } diff --git a/palacios/src/palacios/vmm_ctrl_regs.c b/palacios/src/palacios/vmm_ctrl_regs.c index 75d11f0..9bbcf5b 100644 --- a/palacios/src/palacios/vmm_ctrl_regs.c +++ b/palacios/src/palacios/vmm_ctrl_regs.c @@ -243,7 +243,7 @@ int v3_handle_cr0_read(struct guest_info * info) { *dst_reg = *shadow_cr0; } - PrintDebug("returned CR0: %p\n", (void *)*dst_reg); + PrintDebug("returned CR0: %p\n", (void *)*(addr_t *)dst_reg); } else { struct cr0_32 * dst_reg = (struct cr0_32 *)(dec_instr.dst_operand.operand); diff --git a/palacios/src/palacios/vmm_direct_paging.c b/palacios/src/palacios/vmm_direct_paging.c index 783f696..9884620 100644 --- a/palacios/src/palacios/vmm_direct_paging.c +++ b/palacios/src/palacios/vmm_direct_paging.c @@ -24,6 +24,13 @@ #include #include + +#ifndef DEBUG_NESTED_PAGING +#undef PrintDebug +#define PrintDebug(fmt, args...) +#endif + + static addr_t create_generic_pt_page() { void * page = 0; page = V3_VAddr(V3_AllocPages(1)); @@ -44,7 +51,7 @@ addr_t v3_create_direct_passthrough_pts(struct guest_info * info) { int v3_handle_passthrough_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { v3_vm_cpu_mode_t mode = v3_get_cpu_mode(info); - + switch(mode) { case REAL: case PROTECTED: @@ -62,3 +69,32 @@ int v3_handle_passthrough_pagefault(struct guest_info * info, addr_t fault_addr, } return -1; } + + + +int v3_handle_nested_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { + // THIS IS VERY BAD + v3_vm_cpu_mode_t mode = LONG; + + + PrintDebug("Nested PageFault: fault_addr=%p, error_code=%u\n",(void*)fault_addr, *(uint_t *)&error_code); + + switch(mode) { + case REAL: + case PROTECTED: + return handle_passthrough_pagefault_32(info, fault_addr, error_code); + + case PROTECTED_PAE: + return handle_passthrough_pagefault_32pae(info, fault_addr, error_code); + + case LONG: + case LONG_32_COMPAT: + return handle_passthrough_pagefault_64(info, fault_addr, error_code); + + default: + PrintError("Unknown CPU Mode\n"); + break; + } + return -1; +} + diff --git a/palacios/src/palacios/vmm_direct_paging_32.h b/palacios/src/palacios/vmm_direct_paging_32.h index 4df18a9..6645f86 100644 --- a/palacios/src/palacios/vmm_direct_paging_32.h +++ b/palacios/src/palacios/vmm_direct_paging_32.h @@ -33,7 +33,7 @@ static inline int handle_passthrough_pagefault_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { // Check to see if pde and pte exist (create them if not) - pde32_t * pde = CR3_TO_PDE32_VA(info->ctrl_regs.cr3); + pde32_t * pde = NULL; pte32_t * pte = NULL; addr_t host_addr = 0; @@ -51,6 +51,14 @@ static inline int handle_passthrough_pagefault_32(struct guest_info * info, host_addr = v3_get_shadow_addr(region, fault_addr); + // Lookup the correct PDE address based on the PAGING MODE + if (info->shdw_pg_mode == SHADOW_PAGING) { + pde = CR3_TO_PDE32_VA(info->ctrl_regs.cr3); + } else { + pde = CR3_TO_PDE32_VA(info->direct_map_pt); + } + + // Fix up the PDE entry if (pde[pde_index].present == 0) { pte = (pte32_t *)create_generic_pt_page(); diff --git a/palacios/src/palacios/vmm_direct_paging_32pae.h b/palacios/src/palacios/vmm_direct_paging_32pae.h index 033c69d..27cc9b3 100644 --- a/palacios/src/palacios/vmm_direct_paging_32pae.h +++ b/palacios/src/palacios/vmm_direct_paging_32pae.h @@ -31,7 +31,7 @@ static inline int handle_passthrough_pagefault_32pae(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { - pdpe32pae_t * pdpe = CR3_TO_PDPE32PAE_VA(info->ctrl_regs.cr3); + pdpe32pae_t * pdpe = NULL; pde32pae_t * pde = NULL; pte32pae_t * pte = NULL; addr_t host_addr = 0; @@ -51,6 +51,13 @@ static inline int handle_passthrough_pagefault_32pae(struct guest_info * info, host_addr = v3_get_shadow_addr(region, fault_addr); + // Lookup the correct PDPE address based on the PAGING MODE + if (info->shdw_pg_mode == SHADOW_PAGING) { + pdpe = CR3_TO_PDPE32PAE_VA(info->ctrl_regs.cr3); + } else { + pdpe = CR3_TO_PDPE32PAE_VA(info->direct_map_pt); + } + // Fix up the PDPE entry if (pdpe[pdpe_index].present == 0) { pde = (pde32pae_t *)create_generic_pt_page(); diff --git a/palacios/src/palacios/vmm_direct_paging_64.h b/palacios/src/palacios/vmm_direct_paging_64.h index a840c2b..ab82c9a 100644 --- a/palacios/src/palacios/vmm_direct_paging_64.h +++ b/palacios/src/palacios/vmm_direct_paging_64.h @@ -28,102 +28,120 @@ #include + static inline int handle_passthrough_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { - pml4e64_t * pml = CR3_TO_PML4E64_VA(info->ctrl_regs.cr3); - pdpe64_t * pdpe = NULL; - pde64_t * pde = NULL; - pte64_t * pte = NULL; - addr_t host_addr = 0; - - int pml_index = PML4E64_INDEX(fault_addr); - int pdpe_index = PDPE64_INDEX(fault_addr); - int pde_index = PDE64_INDEX(fault_addr); - int pte_index = PTE64_INDEX(fault_addr); - - struct v3_shadow_region * region = v3_get_shadow_region(info, fault_addr); - - if ((region == NULL) || - (region->host_type == SHDW_REGION_INVALID)) { - PrintError("Invalid region in passthrough page fault 64, addr=%p\n", - (void *)fault_addr); - return -1; - } - - host_addr = v3_get_shadow_addr(region, fault_addr); - - //Fix up the PML entry - if (pml[pml_index].present == 0) { - pdpe = (pdpe64_t *)create_generic_pt_page(); - - pml[pml_index].present = 1; - // Set default PML Flags... - pml[pml_index].pdp_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pdpe)); - } else { - pdpe = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pml[pml_index].pdp_base_addr)); - } - - // Fix up the PDPE entry - if (pdpe[pdpe_index].present == 0) { - pde = (pde64_t *)create_generic_pt_page(); - - pdpe[pdpe_index].present = 1; - // Set default PDPE Flags... - pdpe[pdpe_index].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde)); - } else { - pde = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pdpe[pdpe_index].pd_base_addr)); - } + pml4e64_t * pml = NULL; + pdpe64_t * pdpe = NULL; + pde64_t * pde = NULL; + pte64_t * pte = NULL; + addr_t host_addr = 0; + int pml_index = PML4E64_INDEX(fault_addr); + int pdpe_index = PDPE64_INDEX(fault_addr); + int pde_index = PDE64_INDEX(fault_addr); + int pte_index = PTE64_INDEX(fault_addr); - // Fix up the PDE entry - if (pde[pde_index].present == 0) { - pte = (pte64_t *)create_generic_pt_page(); - pde[pde_index].present = 1; - pde[pde_index].writable = 1; - pde[pde_index].user_page = 1; + - pde[pde_index].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte)); - } else { - pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pde[pde_index].pt_base_addr)); - } + struct v3_shadow_region * region = v3_get_shadow_region(info, fault_addr); + + if ((region == NULL) || + (region->host_type == SHDW_REGION_INVALID)) { + PrintError("Invalid region in passthrough page fault 64, addr=%p\n", + (void *)fault_addr); + return -1; + } + host_addr = v3_get_shadow_addr(region, fault_addr); + // - // Fix up the PTE entry - if (pte[pte_index].present == 0) { - pte[pte_index].user_page = 1; + // Lookup the correct PML address based on the PAGING MODE + if (info->shdw_pg_mode == SHADOW_PAGING) { + pml = CR3_TO_PML4E64_VA(info->ctrl_regs.cr3); + } else { + pml = CR3_TO_PML4E64_VA(info->direct_map_pt); + } - if (region->host_type == SHDW_REGION_ALLOCATED) { - // Full access - pte[pte_index].present = 1; - pte[pte_index].writable = 1; + //Fix up the PML entry + if (pml[pml_index].present == 0) { + pdpe = (pdpe64_t *)create_generic_pt_page(); + + // Set default PML Flags... + pml[pml_index].present = 1; + pml[pml_index].writable = 1; + pml[pml_index].user_page = 1; - pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); + pml[pml_index].pdp_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pdpe)); + } else { + pdpe = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pml[pml_index].pdp_base_addr)); + } - } else if (region->host_type == SHDW_REGION_WRITE_HOOK) { - // Only trap writes - pte[pte_index].present = 1; - pte[pte_index].writable = 0; + // Fix up the PDPE entry + if (pdpe[pdpe_index].present == 0) { + pde = (pde64_t *)create_generic_pt_page(); + + // Set default PDPE Flags... + pdpe[pdpe_index].present = 1; + pdpe[pdpe_index].writable = 1; + pdpe[pdpe_index].user_page = 1; - pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); + pdpe[pdpe_index].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde)); + } else { + pde = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pdpe[pdpe_index].pd_base_addr)); + } - } else if (region->host_type == SHDW_REGION_FULL_HOOK) { - // trap all accesses - return v3_handle_mem_full_hook(info, fault_addr, fault_addr, region, error_code); + // Fix up the PDE entry + if (pde[pde_index].present == 0) { + pte = (pte64_t *)create_generic_pt_page(); + + pde[pde_index].present = 1; + pde[pde_index].writable = 1; + pde[pde_index].user_page = 1; + + pde[pde_index].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte)); } else { - PrintError("Unknown Region Type...\n"); - return -1; + pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pde[pde_index].pt_base_addr)); + } + + + // Fix up the PTE entry + if (pte[pte_index].present == 0) { + pte[pte_index].user_page = 1; + + if (region->host_type == SHDW_REGION_ALLOCATED) { + // Full access + pte[pte_index].present = 1; + pte[pte_index].writable = 1; + + pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); + + } else if (region->host_type == SHDW_REGION_WRITE_HOOK) { + // Only trap writes + pte[pte_index].present = 1; + pte[pte_index].writable = 0; + + pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); + + } else if (region->host_type == SHDW_REGION_FULL_HOOK) { + // trap all accesses + return v3_handle_mem_full_hook(info, fault_addr, fault_addr, region, error_code); + + } else { + PrintError("Unknown Region Type...\n"); + return -1; + } } - } - if ( (region->host_type == SHDW_REGION_WRITE_HOOK) && - (error_code.write == 1) ) { - return v3_handle_mem_wr_hook(info, fault_addr, fault_addr, region, error_code); - } + if ( (region->host_type == SHDW_REGION_WRITE_HOOK) && + (error_code.write == 1) ) { + return v3_handle_mem_wr_hook(info, fault_addr, fault_addr, region, error_code); + } - return 0; + return 0; } diff --git a/palacios/src/palacios/vmm_emulator.c b/palacios/src/palacios/vmm_emulator.c index e6adab1..2df0469 100644 --- a/palacios/src/palacios/vmm_emulator.c +++ b/palacios/src/palacios/vmm_emulator.c @@ -150,12 +150,14 @@ static int emulate_xchg_write_op(struct guest_info * info, struct x86_instr * de PrintDebug("Emulating XCHG write\n"); if (dec_instr->src_operand.type == MEM_OPERAND) { - if (dec_instr->src_operand.operand != write_gva) { - PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr->src_operand.operand, (void *)write_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if (dec_instr->src_operand.operand != write_gva) { + PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", + (void *)dec_instr->src_operand.operand, (void *)write_gva); + return -1; + } } - + src_addr = dst_addr; } else if (dec_instr->src_operand.type == REG_OPERAND) { src_addr = dec_instr->src_operand.operand; @@ -166,41 +168,45 @@ static int emulate_xchg_write_op(struct guest_info * info, struct x86_instr * de if (dec_instr->dst_operand.type == MEM_OPERAND) { - if (dec_instr->dst_operand.operand != write_gva) { - PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr->dst_operand.operand, (void *)write_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if (dec_instr->dst_operand.operand != write_gva) { + PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", + (void *)dec_instr->dst_operand.operand, (void *)write_gva); + return -1; + } + } else { + //check that the operand (GVA) maps to the the faulting GPA } - + em_dst_addr = dst_addr; } else if (dec_instr->src_operand.type == REG_OPERAND) { em_dst_addr = dec_instr->src_operand.operand; } else { em_dst_addr = (addr_t)&(dec_instr->src_operand.operand); } - + dst_op_len = dec_instr->dst_operand.size; src_op_len = dec_instr->src_operand.size; - + PrintDebug("Dst_Addr = %p, SRC operand = %p\n", (void *)dst_addr, (void *)src_addr); - - + + if (run_op(info, dec_instr->op_type, src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) { PrintError("Instruction Emulation Failed\n"); return -1; } - + if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) { PrintError("Did not fully write hooked data\n"); return -1; } - + info->rip += dec_instr->instr_length; - + return dst_op_len; } - + static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec_instr, @@ -232,12 +238,16 @@ static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec if (dec_instr->dst_operand.type == MEM_OPERAND) { - if (dec_instr->dst_operand.operand != read_gva) { - PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr->dst_operand.operand, (void *)read_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if (dec_instr->dst_operand.operand != read_gva) { + PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", + (void *)dec_instr->dst_operand.operand, (void *)read_gva); + return -1; + } + } else { + //check that the operand (GVA) maps to the the faulting GPA } - + em_dst_addr = src_addr; } else if (dec_instr->src_operand.type == REG_OPERAND) { em_dst_addr = dec_instr->src_operand.operand; @@ -314,12 +324,15 @@ int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write } - - if ((dec_instr.dst_operand.type != MEM_OPERAND) || - (dec_instr.dst_operand.operand != write_gva)) { - PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr.dst_operand.operand, (void *)write_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if ((dec_instr.dst_operand.type != MEM_OPERAND) || + (dec_instr.dst_operand.operand != write_gva)) { + PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", + (void *)dec_instr.dst_operand.operand, (void *)write_gva); + return -1; + } + } else { + //check that the operand (GVA) maps to the the faulting GPA } @@ -401,15 +414,17 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp return emulate_xchg_read_op(info, &dec_instr, read_gva, read_gpa, src_addr, read_fn, write_fn, priv_data); } - - if ((dec_instr.src_operand.type != MEM_OPERAND) || - (dec_instr.src_operand.operand != read_gva)) { - PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr.src_operand.operand, (void *)read_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if ((dec_instr.src_operand.type != MEM_OPERAND) || + (dec_instr.src_operand.operand != read_gva)) { + PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", + (void *)dec_instr.src_operand.operand, (void *)read_gva); + return -1; + } + } else { + //check that the operand (GVA) maps to the the faulting GPA } - if (dec_instr.dst_operand.type == MEM_OPERAND) { if (info->mem_mode == PHYSICAL_MEM) { if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) { diff --git a/palacios/src/palacios/vmm_excp.c b/palacios/src/palacios/vmm_excp.c new file mode 100644 index 0000000..ea6cdc5 --- /dev/null +++ b/palacios/src/palacios/vmm_excp.c @@ -0,0 +1,98 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include + +void v3_init_exception_state(struct guest_info * info) { + info->excp_state.excp_pending = 0; + info->excp_state.excp_num = 0; + info->excp_state.excp_error_code = 0; + +} + + + +int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code) { + struct v3_excp_state * excp_state = &(info->excp_state); + + if (excp_state->excp_pending == 0) { + excp_state->excp_pending = 1; + excp_state->excp_num = excp; + excp_state->excp_error_code = error_code; + excp_state->excp_error_code_valid = 1; + // PrintDebug("[v3_raise_exception_with_error] error code: %x\n", error_code); + } else { + PrintError("exception already pending, currently not implemented\n"); + return -1; + } + + return 0; +} + +int v3_raise_exception(struct guest_info * info, uint_t excp) { + struct v3_excp_state * excp_state = &(info->excp_state); + //PrintDebug("[v3_raise_exception]\n"); + if (excp_state->excp_pending == 0) { + excp_state->excp_pending = 1; + excp_state->excp_num = excp; + excp_state->excp_error_code = 0; + excp_state->excp_error_code_valid = 0; + } else { + PrintError("exception already pending, currently not implemented\n"); + return -1; + } + + return 0; +} + + +int v3_excp_pending(struct guest_info * info) { + struct v3_excp_state * excp_state = &(info->excp_state); + + if (excp_state->excp_pending == 1) { + return 1; + } + + return 0; +} + + +int v3_get_excp_number(struct guest_info * info) { + struct v3_excp_state * excp_state = &(info->excp_state); + + if (excp_state->excp_pending == 1) { + return excp_state->excp_num; + } + + return 0; +} + + +int v3_injecting_excp(struct guest_info * info, uint_t excp) { + struct v3_excp_state * excp_state = &(info->excp_state); + + excp_state->excp_pending = 0; + excp_state->excp_num = 0; + excp_state->excp_error_code = 0; + excp_state->excp_error_code_valid = 0; + + return 0; +} diff --git a/palacios/src/palacios/vmm_intr.c b/palacios/src/palacios/vmm_intr.c index ce21ff3..953df0e 100644 --- a/palacios/src/palacios/vmm_intr.c +++ b/palacios/src/palacios/vmm_intr.c @@ -40,14 +40,10 @@ struct intr_controller { void v3_init_interrupt_state(struct guest_info * info) { - info->intr_state.excp_pending = 0; - info->intr_state.excp_num = 0; - info->intr_state.excp_error_code = 0; info->intr_state.irq_pending = 0; info->intr_state.irq_vector = 0; - INIT_LIST_HEAD(&(info->intr_state.controller_list)); memset((uchar_t *)(info->intr_state.hooks), 0, sizeof(struct v3_irq_hook *) * 256); @@ -147,39 +143,6 @@ int v3_deliver_irq(struct guest_info * info, struct v3_interrupt * intr) { -int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code) { - struct v3_intr_state * intr_state = &(info->intr_state); - - if (intr_state->excp_pending == 0) { - intr_state->excp_pending = 1; - intr_state->excp_num = excp; - intr_state->excp_error_code = error_code; - intr_state->excp_error_code_valid = 1; - // PrintDebug("[v3_raise_exception_with_error] error code: %x\n", error_code); - } else { - PrintError("exception already pending, currently not implemented\n"); - return -1; - } - - return 0; -} - -int v3_raise_exception(struct guest_info * info, uint_t excp) { - struct v3_intr_state * intr_state = &(info->intr_state); - //PrintDebug("[v3_raise_exception]\n"); - if (intr_state->excp_pending == 0) { - intr_state->excp_pending = 1; - intr_state->excp_num = excp; - intr_state->excp_error_code = 0; - intr_state->excp_error_code_valid = 0; - } else { - PrintError("exception already pending, currently not implemented\n"); - return -1; - } - - return 0; -} - int v3_lower_irq(struct guest_info * info, int irq) { struct intr_controller * ctrl = NULL; @@ -211,61 +174,45 @@ int v3_raise_irq(struct guest_info * info, int irq) { int v3_intr_pending(struct guest_info * info) { struct v3_intr_state * intr_state = &(info->intr_state); - + struct intr_controller * ctrl = NULL; // PrintDebug("[intr_pending]\n"); - if (intr_state->excp_pending == 1) { - return 1; - } else { - struct intr_controller * ctrl = NULL; - list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) { - if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data) == 1) { - return 1; - } + list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) { + if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data) == 1) { + return 1; } } + return 0; } uint_t v3_get_intr_number(struct guest_info * info) { struct v3_intr_state * intr_state = &(info->intr_state); + struct intr_controller * ctrl = NULL; - if (intr_state->excp_pending == 1) { - return intr_state->excp_num; - } else { - struct intr_controller * ctrl = NULL; - - list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) { - if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data)) { - uint_t intr_num = ctrl->ctrl_ops->get_intr_number(ctrl->priv_data); - - // PrintDebug("[get_intr_number] intr_number = %d\n", intr_num); - - return intr_num; - } + list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) { + if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data)) { + uint_t intr_num = ctrl->ctrl_ops->get_intr_number(ctrl->priv_data); + + // PrintDebug("[get_intr_number] intr_number = %d\n", intr_num); + + return intr_num; } } - return 0; } intr_type_t v3_get_intr_type(struct guest_info * info) { struct v3_intr_state * intr_state = &(info->intr_state); + struct intr_controller * ctrl = NULL; - if (intr_state->excp_pending) { - // PrintDebug("[get_intr_type] Exception\n"); - return EXCEPTION; - } else { - struct intr_controller * ctrl = NULL; - - list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) { - if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data) == 1) { - //PrintDebug("[get_intr_type] External_irq\n"); - return EXTERNAL_IRQ; - } + list_for_each_entry(ctrl, &(intr_state->controller_list), ctrl_node) { + if (ctrl->ctrl_ops->intr_pending(ctrl->priv_data) == 1) { + //PrintDebug("[get_intr_type] External_irq\n"); + return EXTERNAL_IRQ; } } @@ -281,14 +228,7 @@ intr_type_t v3_get_intr_type(struct guest_info * info) { int v3_injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) { struct v3_intr_state * intr_state = &(info->intr_state); - if (type == EXCEPTION) { - // PrintDebug("[injecting_intr] Exception\n"); - intr_state->excp_pending = 0; - intr_state->excp_num = 0; - intr_state->excp_error_code = 0; - intr_state->excp_error_code_valid = 0; - - } else if (type == EXTERNAL_IRQ) { + if (type == EXTERNAL_IRQ) { struct intr_controller * ctrl = NULL; // PrintDebug("[injecting_intr] External_Irq with intr_num = %x\n", intr_num); diff --git a/palacios/src/palacios/vmm_mem.c b/palacios/src/palacios/vmm_mem.c index 38eb602..c244793 100644 --- a/palacios/src/palacios/vmm_mem.c +++ b/palacios/src/palacios/vmm_mem.c @@ -264,7 +264,7 @@ addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr) { (reg->host_type != SHDW_REGION_INVALID) ) { return (guest_addr - reg->guest_start) + reg->host_addr; } else { - PrintError("MEM Region Invalid\n"); + PrintDebug("MEM Region Invalid\n"); return 0; } } diff --git a/palacios/src/palacios/vmm_profiler.c b/palacios/src/palacios/vmm_profiler.c index f7bc878..567f652 100644 --- a/palacios/src/palacios/vmm_profiler.c +++ b/palacios/src/palacios/vmm_profiler.c @@ -120,9 +120,10 @@ void v3_profile_exit(struct guest_info * info, uint_t exit_code) { insert_event(info, evt); } + - evt->handler_time = (evt->handler_time * .99) + (time * .01); + evt->handler_time = (evt->handler_time * 127ull + time) / 128; evt->exit_count++; diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index 2e7d853..25ca076 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -568,7 +568,7 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe int addr_width = v3_get_addr_width(info);; // struct v3_segment * seg_reg; - PrintDebug("Xen mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state))); + PrintDebug("Xed mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state))); PrintDebug("Address width: %s\n", xed_address_width_enum_t2str(xed_state_get_address_width(info->decoder_state))); PrintDebug("Stack Address width: %s\n", diff --git a/palacios/src/vmboot/rombios/BIOS-bochs-latest b/palacios/src/vmboot/rombios/BIOS-bochs-latest new file mode 100644 index 0000000..ea9a1ec Binary files /dev/null and b/palacios/src/vmboot/rombios/BIOS-bochs-latest differ diff --git a/palacios/src/vmboot/vgabios/VGABIOS-lgpl-latest.bin b/palacios/src/vmboot/vgabios/VGABIOS-lgpl-latest.bin new file mode 100644 index 0000000..dc6785d Binary files /dev/null and b/palacios/src/vmboot/vgabios/VGABIOS-lgpl-latest.bin differ