From: Lei Xia Date: Fri, 26 Aug 2011 01:57:44 +0000 (-0500) Subject: Merge branch 'devel' of palacios@newskysaw.cs.northwestern.edu:/home/palacios/palacio... X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=5c16780e3eb5e4ef59de8e929e2528bb07fce5ec;hp=8e9c13c41b0244a8d0029e837a623591a22c5879;p=palacios.git Merge branch 'devel' of palacios@newskysaw.cs.northwestern.edu:/home/palacios/palacios into devel Conflicts: linux_usr/Makefile --- diff --git a/Kconfig b/Kconfig index 6432790..5397fec 100644 --- a/Kconfig +++ b/Kconfig @@ -76,6 +76,12 @@ config VMX Compile with support for Intel VMX +config FRAME_POINTER + bool "Compile with Frame pointers" + default n + help + Compiles the Palacios library with Frame pointers + config DEBUG_INFO bool "Compile with Debug Information" default n @@ -296,12 +302,6 @@ endmenu menu "Debug configuration" -config CONFIG_DEBUG_INFO - bool "Compile with Debug information" - default n - help - This adds the -g flag to the compilation flags - ## Is unwind information useful diff --git a/Makefile b/Makefile index 1b14317..22b56bb 100644 --- a/Makefile +++ b/Makefile @@ -298,7 +298,8 @@ V3_INCLUDE := -Ipalacios/include \ CPPFLAGS := $(V3_INCLUDE) -D__V3VEE__ -CFLAGS := -fno-stack-protector -Wall -Werror -mno-red-zone -fno-common +CFLAGS := -fno-stack-protector -Wall -Werror -mno-red-zone -fno-common \ + $(call cc-option, -Wno-unused-but-set-variable,) @@ -379,9 +380,9 @@ ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) endif ifeq ($(KBUILD_EXTMOD),) - ifneq ($(filter config %config,$(MAKECMDGOALS)),) + ifneq ($(filter %config,$(MAKECMDGOALS)),) config-targets := 1 - ifneq ($(filter-out config %config,$(MAKECMDGOALS)),) + ifneq ($(filter-out %config,$(MAKECMDGOALS)),) mixed-targets := 1 endif endif @@ -407,7 +408,7 @@ ifeq ($(config-targets),1) include $(srctree)/Makefile.$(ARCH) export KBUILD_DEFCONFIG -config %config: scripts_basic outputmakefile FORCE +%config: scripts_basic outputmakefile FORCE $(Q)mkdir -p palacios/include/config $(Q)$(MAKE) $(build)=scripts/kconfig $@ # $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease @@ -500,8 +501,6 @@ endif ifdef V3_CONFIG_DEBUG_INFO CFLAGS += -g -else -CFLAGS += -O endif @@ -942,7 +941,7 @@ target-dir = $(dir $@) $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) # Modules -/ %/: prepare scripts FORCE +%/: prepare scripts FORCE $(Q)$(MAKE) KBUILD_MODULES=$(if $(V3_CONFIG_MODULES),1) \ $(build)=$(build-dir) %.ko: prepare scripts FORCE diff --git a/linux_module/Makefile b/linux_module/Makefile index 137674c..d028d2e 100644 --- a/linux_module/Makefile +++ b/linux_module/Makefile @@ -27,6 +27,7 @@ v3vee-$(V3_CONFIG_SOCKET) += iface-socket.o v3vee-$(V3_CONFIG_KEYED_STREAMS) += iface-keyed-stream.o v3vee-$(V3_CONFIG_HOST_DEVICE) += iface-host-dev.o v3vee-$(V3_CONFIG_GRAPHICS_CONSOLE) += iface-graphics-console.o +v3vee-$(V3_CONFIG_EXT_MACH_CHECK) += mcheck.o v3vee-$(V3_CONFIG_VNET) += palacios-vnet.o \ palacios-vnet-ctrl.o \ diff --git a/linux_module/mcheck.c b/linux_module/mcheck.c new file mode 100644 index 0000000..e357e94 --- /dev/null +++ b/linux_module/mcheck.c @@ -0,0 +1,57 @@ +/* + * DebugFS interface + * (c) Patrick Bridges and Philip Soltero, 2011 + */ + +#include +#include +#include +#include + +#include + +#include "palacios.h" +#include "vm.h" +#include "linux-exts.h" + +#define SCRUBBER_MCE 0x1 +#define V3_VM_INJECT_SCRUBBER_MCE (10224+20) + +static int inject_mce(struct v3_guest * guest, unsigned int cmd, unsigned long arg, + void * priv_data) +{ + unsigned long type = (unsigned long)priv_data; + switch ( type ) { + case SCRUBBER_MCE: + return v3_mcheck_inject_scrubber_mce((struct v3_vm_info *)guest->v3_ctx, 0, arg); + break; + default: + // TODO: How to print an error in the host OS? + //PrintError("Injection of unknown machine check type %lu requested.\n", type); + return -1; + break; + } +} + +static int guest_init(struct v3_guest * guest, void ** vm_data) { + + add_guest_ctrl(guest, V3_VM_INJECT_SCRUBBER_MCE, inject_mce, (void *)SCRUBBER_MCE); + return 0; +} + +static int guest_deinit(struct v3_guest * guest, void * vm_data) { + + return 0; +} + + +struct linux_ext mcheck_ext = { + .name = "MACHINE CHECK", + .init = NULL, + .deinit = NULL, + .guest_init = guest_init, + .guest_deinit = guest_deinit +}; + + +register_extension(&mcheck_ext); diff --git a/linux_module/util-hashtable.c b/linux_module/util-hashtable.c index ebf1d1c..669bbfb 100644 --- a/linux_module/util-hashtable.c +++ b/linux_module/util-hashtable.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "util-hashtable.h" diff --git a/linux_usr/Makefile b/linux_usr/Makefile index 5392207..2a09f45 100644 --- a/linux_usr/Makefile +++ b/linux_usr/Makefile @@ -37,6 +37,8 @@ v3_user_keyed_stream_file: v3_user_keyed_stream_file.c v3_user_keyed_stream.h v3 v3_core_move : v3_core_move.c v3_ctrl.h gcc -static v3_core_move.c -o v3_core_move +v3_inject_ecc_scrubber_mce: v3_inject_ecc_scrubber_mce.c + gcc -static -I../linux_module v3_inject_ecc_scrubber_mce.c -o v3_inject_ecc_scrubber_mce clean: rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_stream v3_user_host_dev_example v3_os_debug v3_user_keyed_stream_example v3_user_keyed_stream_file v3_core_migrate diff --git a/linux_usr/v3_inject_ecc_scrubber_mce.c b/linux_usr/v3_inject_ecc_scrubber_mce.c new file mode 100644 index 0000000..ec98ba8 --- /dev/null +++ b/linux_usr/v3_inject_ecc_scrubber_mce.c @@ -0,0 +1,51 @@ +/* + * V3 ECC DRAM Scrubber MCE + * (c) Philip Soltero, 2010 + */ + +#include +#include +#include + +#define V3_VM_INJECT_SCRUBBER_MCE (10224+20) + +int main(int argc, char * argv[]) { + char * end_ptr; + char * vm_device; + unsigned int cpu; + uint64_t address; + int v3_fd = 0; + + if (argc <= 3) { + fprintf(stderr, "Usage: v3_inject_ecc_scrubber_mce \n"); + return -1; + } + + vm_device = argv[1]; + + cpu = strtol(argv[2], &end_ptr, 10); + if (strcmp(end_ptr, "\0") != 0) { + fprintf(stderr, "The specified cpu is not a valid integer '%s', in particular '%s'.\n", argv[2], end_ptr); + return -1; + } + + address = strtoll(argv[3], &end_ptr, 16); + if (strcmp(end_ptr, "\0") != 0) { + fprintf(stderr, "The specified address is not a valid integer '%s', in particular '%s'.\n", argv[3], end_ptr); + return -1; + } + + v3_fd = open(vm_device, O_RDONLY); + + if (v3_fd == -1) { + fprintf(stderr, "Error opening V3Vee control device.\n"); + return -1; + } + + ioctl(v3_fd, V3_VM_INJECT_SCRUBBER_MCE, address); + + /* Close the file descriptor. */ + close(v3_fd); + + return 0; +} diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index 7f33fde..767fe25 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -52,29 +52,31 @@ struct x86_prefixes { uint32_t val; struct { - uint_t lock : 1; // 0xF0 - uint_t repne : 1; // 0xF2 - uint_t repnz : 1; // 0xF2 - uint_t rep : 1; // 0xF3 - uint_t repe : 1; // 0xF3 - uint_t repz : 1; // 0xF3 - uint_t cs_override : 1; // 0x2E - uint_t ss_override : 1; // 0x36 - uint_t ds_override : 1; // 0x3E - uint_t es_override : 1; // 0x26 - uint_t fs_override : 1; // 0x64 - uint_t gs_override : 1; // 0x65 - uint_t br_not_taken : 1; // 0x2E - uint_t br_taken : 1; // 0x3E - uint_t op_size : 1; // 0x66 - uint_t addr_size : 1; // 0x67 - - uint_t rex : 1; + uint32_t lock : 1; // 0xF0 + uint32_t repne : 1; // 0xF2 + uint32_t repnz : 1; // 0xF2 + uint32_t rep : 1; // 0xF3 + uint32_t repe : 1; // 0xF3 + uint32_t repz : 1; // 0xF3 + uint32_t cs_override : 1; // 0x2E + uint32_t ss_override : 1; // 0x36 + uint32_t ds_override : 1; // 0x3E + uint32_t es_override : 1; // 0x26 + uint32_t fs_override : 1; // 0x64 + uint32_t gs_override : 1; // 0x65 + uint32_t br_not_taken : 1; // 0x2E + uint32_t br_taken : 1; // 0x3E + uint32_t op_size : 1; // 0x66 + uint32_t addr_size : 1; // 0x67 + + uint32_t rex : 1; - uint_t rex_rm : 1; // REX.B - uint_t rex_sib_idx : 1; // REX.X - uint_t rex_reg : 1; // REX.R - uint_t rex_op_size : 1; // REX.W + uint32_t rex_rm : 1; // REX.B + uint32_t rex_sib_idx : 1; // REX.X + uint32_t rex_reg : 1; // REX.R + uint32_t rex_op_size : 1; // REX.W + + uint32_t rsvd : 11; } __attribute__((packed)); } __attribute__((packed)); } __attribute__((packed)); diff --git a/palacios/include/palacios/vmm_instr_emulator.h b/palacios/include/palacios/vmm_instr_emulator.h index 7559f05..cbccaf1 100644 --- a/palacios/include/palacios/vmm_instr_emulator.h +++ b/palacios/include/palacios/vmm_instr_emulator.h @@ -19,11 +19,13 @@ #include +#define FLAGS_MASK 0x00000cff + #define MAKE_1OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint8_t tmp_dst = *(uint8_t *)dst; \ \ asm volatile ( \ "pushf; " \ @@ -33,16 +35,19 @@ "pushf; " \ "pop %1; " \ "popf; " \ - : "=q"(*(uint8_t *)dst),"=q"(*flags) \ - : "q"(*flags), "0"(*(uint8_t *)dst) \ + : "=&q"(tmp_dst),"=q"(guest_flags) \ + : "1"(guest_flags), "0"(tmp_dst) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ + *(uint8_t *)dst = tmp_dst; \ \ } #define MAKE_1OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint16_t tmp_dst = *(uint16_t *)dst; \ \ asm volatile ( \ "pushf; " \ @@ -52,16 +57,18 @@ "pushf; " \ "pop %1; " \ "popf; " \ - : "=q"(*(uint16_t *)dst),"=q"(*flags) \ - : "q"(*flags), "0"(*(uint16_t *)dst) \ + : "=&q"(tmp_dst),"=q"(guest_flags) \ + : "1"(guest_flags), "0"(tmp_dst) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ - \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ + *(uint16_t *)dst = tmp_dst; \ } #define MAKE_1OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint32_t tmp_dst = *(uint32_t *)dst; \ \ asm volatile ( \ "pushf; " \ @@ -71,16 +78,19 @@ "pushf; " \ "pop %1; " \ "popf; " \ - : "=q"(*(uint32_t *)dst),"=q"(*flags) \ - : "q"(*flags), "0"(*(uint32_t *)dst) \ + : "=&q"(tmp_dst),"=q"(guest_flags) \ + : "1"(guest_flags), "0"(tmp_dst) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ + *(uint32_t *)dst = tmp_dst; \ } #define MAKE_1OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint64_t tmp_dst = *(uint64_t *)dst; \ \ asm volatile ( \ "pushfq; " \ @@ -90,51 +100,66 @@ "pushfq; " \ "pop %1; " \ "popfq; " \ - : "=q"(*(uint64_t *)dst),"=q"(*flags) \ - : "q"(*flags), "0"(*(uint64_t *)dst) \ + : "=q"(tmp_dst),"=q"(guest_flags) \ + : "q"(guest_flags), "0"(tmp_dst) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ + *(uint64_t *)dst = tmp_dst; \ } #define MAKE_1OP_8_INST(iname) static inline void iname##8(addr_t * dst) { \ + uint8_t tmp_dst = *(uint8_t *)dst; \ asm volatile ( \ #iname"b %0; " \ - : "=q"(*(uint8_t *)dst) \ - : "0"(*(uint8_t *)dst) \ + : "=q"(tmp_dst) \ + : "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint8_t *)dst = tmp_dst; \ } #define MAKE_1OP_16_INST(iname) static inline void iname##16(addr_t * dst) { \ + uint16_t tmp_dst = *(uint16_t *)dst; \ asm volatile ( \ #iname"w %0; " \ - : "=q"(*(uint16_t *)dst) \ - : "0"(*(uint16_t *)dst) \ + : "=q"(tmp_dst) \ + : "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint16_t *)dst = tmp_dst; \ } #define MAKE_1OP_32_INST(iname) static inline void iname##32(addr_t * dst) { \ + uint32_t tmp_dst = *(uint32_t *)dst; \ asm volatile ( \ #iname"l %0; " \ - : "=q"(*(uint32_t *)dst) \ - : "0"(*(uint32_t *)dst) \ + : "=q"(tmp_dst) \ + : "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint32_t *)dst = tmp_dst; \ } #define MAKE_1OP_64_INST(iname) static inline void iname##64(addr_t * dst) { \ + uint64_t tmp_dst = *(uint64_t *)dst; \ asm volatile ( \ #iname"q %0; " \ - : "=q"(*(uint64_t *)dst) \ - : "0"(*(uint64_t *)dst) \ + : "=q"(tmp_dst) \ + : "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint64_t *)dst = tmp_dst; \ } #define MAKE_2OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint64_t tmp_dst = *(uint64_t *)dst; \ \ asm volatile ( \ "pushfq\r\n" \ @@ -144,19 +169,21 @@ "pushfq\r\n" \ "pop %1\r\n" \ "popfq\r\n" \ - : "=q"(*(uint64_t *)dst),"=q"(*flags) \ - : "q"(*(uint64_t *)src),"q"(*flags), "0"(*(uint64_t *)dst) \ + : "=&q"(tmp_dst),"=q"(guest_flags) \ + : "q"(*(uint64_t *)src),"1"(guest_flags), "0"(tmp_dst) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ - \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ + *(uint64_t *)dst = tmp_dst; \ } #define MAKE_2OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint32_t tmp_dst = *(uint32_t *)dst; \ \ asm volatile ( \ "pushf; " \ @@ -166,16 +193,19 @@ "pushf; " \ "pop %1; " \ "popf; " \ - : "=q"(*(uint32_t *)dst),"=q"(*flags) \ - : "q"(*(uint32_t *)src),"q"(*flags), "0"(*(uint32_t *)dst) \ + : "=&q"(tmp_dst),"=q"(guest_flags) \ + : "q"(*(uint32_t *)src),"1"(guest_flags), "0"(tmp_dst) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ + *(uint32_t *)dst = tmp_dst; \ } #define MAKE_2OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint16_t tmp_dst = *(uint16_t *)dst; \ \ asm volatile ( \ "pushf; " \ @@ -185,15 +215,18 @@ "pushf; " \ "pop %1; " \ "popf; " \ - : "=q"(*(uint16_t *)dst),"=q"(*flags) \ - : "q"(*(uint16_t *)src),"q"(*flags), "0"(*(uint16_t *)dst) \ + : "=&q"(tmp_dst),"=q"(guest_flags) \ + : "q"(*(uint16_t *)src),"1"(guest_flags), "0"(tmp_dst) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ + *(uint16_t *)dst = tmp_dst; \ } #define MAKE_2OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint8_t tmp_dst = *(uint8_t *)dst; \ \ asm volatile ( \ "pushf; " \ @@ -203,10 +236,13 @@ "pushf; " \ "pop %1; " \ "popf; " \ - : "=q"(*(uint8_t *)dst),"=q"(*flags) \ - : "q"(*(uint8_t *)src),"q"(*flags), "0"(*(uint8_t *)dst) \ + : "=q"(tmp_dst),"=q"(guest_flags) \ + : "q"(*(uint8_t *)src),"1"(guest_flags), "0"(tmp_dst) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ + *(uint8_t *)dst = tmp_dst; \ } @@ -216,65 +252,71 @@ #define MAKE_2OP_64STR_INST(iname) static inline void iname##64(addr_t * dst, \ addr_t * src, \ addr_t * ecx, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint64_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0; \ \ asm volatile ( \ "pushfq; " \ - "pushq %4; " \ + "pushq %7; " \ "popfq; " \ "rep; " \ #iname"q; " \ "pushfq; " \ "popq %0; " \ "popfq; " \ - : "=q"(*flags) \ - : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags) \ + : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \ + : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ } #define MAKE_2OP_32STR_INST(iname) static inline void iname##32(addr_t * dst, \ addr_t * src, \ addr_t * ecx, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint32_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0; \ \ asm volatile ( \ "pushf; " \ - "push %4; " \ + "push %7; " \ "popf; " \ "rep; " \ #iname"l; " \ "pushf; " \ "pop %0; " \ "popf; " \ - : "=q"(*flags) \ - : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags) \ + : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \ + : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ } #define MAKE_2OP_16STR_INST(iname) static inline void iname##16(addr_t * dst, \ addr_t * src, \ addr_t * ecx, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint16_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0; \ \ asm volatile ( \ "pushf; " \ - "push %4; " \ + "push %7; " \ "popf; " \ "rep; " \ #iname"w; " \ "pushf; " \ "pop %0; " \ "popf; " \ - : "=q"(*flags) \ - : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags) \ + : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \ + : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ } @@ -282,22 +324,24 @@ #define MAKE_2OP_8STR_INST(iname) static inline void iname##8(addr_t * dst, \ addr_t * src, \ addr_t * ecx, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint8_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0; \ \ asm volatile ( \ "pushf; " \ - "push %4; " \ + "push %7; " \ "popf; " \ "rep; " \ #iname"b; " \ "pushf; " \ "pop %0; " \ "popf; " \ - : "=q"(*flags) \ - : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags) \ + : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \ + : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ } @@ -306,66 +350,73 @@ #define MAKE_1OP_64STR_INST(iname) static inline void iname##64(addr_t * dst, \ addr_t * src, \ addr_t * ecx, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint64_t tmp_dst = 0, tmp_ecx = 0; \ \ asm volatile ( \ "pushfq; " \ - "pushq %4; " \ + "pushq %6; " \ "popfq; " \ "rep; " \ #iname"q; " \ "pushfq; " \ "popq %0; " \ "popfq; " \ - : "=q"(*flags) \ - : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags) \ + : "=&q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \ + : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags) \ + : "memory" \ ); \ \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ } #define MAKE_1OP_32STR_INST(iname) static inline void iname##32(addr_t * dst, \ addr_t * src, \ addr_t * ecx, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint32_t tmp_dst = 0, tmp_ecx = 0; \ \ asm volatile ( \ "pushf; " \ - "push %4; " \ + "push %6; " \ "popf; " \ "rep; " \ #iname"l; " \ "pushf; " \ "pop %0; " \ "popf; " \ - : "=q"(*flags) \ - : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags) \ + : "=&q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \ + : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ } #define MAKE_1OP_16STR_INST(iname) static inline void iname##16(addr_t * dst, \ addr_t * src, \ addr_t * ecx, addr_t * flags) { \ - /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & FLAGS_MASK; \ + uint16_t tmp_dst = 0, tmp_ecx = 0; \ \ asm volatile ( \ "pushf; " \ - "push %4; " \ + "push %6; " \ "popf; " \ "rep; " \ #iname"w; " \ "pushf; " \ "pop %0; " \ "popf; " \ - : "=q"(*flags) \ - : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags) \ + : "=q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \ + : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ } @@ -374,56 +425,71 @@ addr_t * src, \ addr_t * ecx, addr_t * flags) { \ /* Some of the flags values are not copied out in a pushf, we save them here */ \ - addr_t flags_rsvd = *flags & ~0xfffc7fff; \ + addr_t guest_flags = *flags & 0x00000cff; \ + uint8_t tmp_dst = 0, tmp_ecx = 0; \ \ asm volatile ( \ "pushf; " \ - "push %4; " \ + "push %6; " \ "popf; " \ "rep; " \ #iname"b; " \ "pushf; " \ "pop %0; " \ "popf; " \ - : "=q"(*flags) \ - : "D"(*dst),"a"(*src),"c"(*ecx),"q"(*flags) \ + : "=&q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \ + : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags) \ + : "memory" \ ); \ - *flags |= flags_rsvd; \ + *flags &= ~FLAGS_MASK; \ + *flags |= (guest_flags & FLAGS_MASK); \ } #define MAKE_2OP_64_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src) { \ + uint64_t tmp_dst = *(uint64_t *)dst; \ asm volatile ( \ #iname"q %1, %0; " \ - : "=q"(*(uint64_t *)dst) \ - : "q"(*(uint64_t *)src), "0"(*(uint64_t *)dst) \ + : "=&q"(tmp_dst) \ + : "q"(*(uint64_t *)src), "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint64_t *)dst = tmp_dst; \ } #define MAKE_2OP_32_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src) { \ + uint32_t tmp_dst = *(uint32_t *)dst; \ asm volatile ( \ #iname"l %1, %0; " \ - : "=q"(*(uint32_t *)dst) \ - : "q"(*(uint32_t *)src), "0"(*(uint32_t *)dst) \ + : "=&q"(tmp_dst) \ + : "q"(*(uint32_t *)src), "0"(tmp_dst) \ + : "memory" \ ); \ - } + *(uint32_t *)dst = tmp_dst; \ + } #define MAKE_2OP_16_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src) { \ + uint16_t tmp_dst = *(uint16_t *)dst; \ asm volatile ( \ #iname"w %1, %0; " \ - : "=q"(*(uint16_t *)dst) \ - : "q"(*(uint16_t *)src), "0"(*(uint16_t *)dst) \ + : "=&q"(tmp_dst) \ + : "q"(*(uint16_t *)src), "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint16_t *)dst = tmp_dst; \ } #define MAKE_2OP_8_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src) { \ + uint8_t tmp_dst = *(uint8_t *)dst; \ asm volatile ( \ #iname"b %1, %0; " \ - : "=q"(*(uint8_t *)dst) \ - : "q"(*(uint8_t *)src), "0"(*(uint8_t *)dst) \ + : "=&q"(tmp_dst) \ + : "q"(*(uint8_t *)src), "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint8_t *)dst = tmp_dst; \ } @@ -432,39 +498,54 @@ #define MAKE_2OP_8EXT_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, uint_t dst_len) { \ if (dst_len == 2) { \ + uint16_t tmp_dst = *(uint16_t *)dst; \ asm volatile ( \ #iname" %1, %0; " \ - : "=q"(*(uint16_t *)dst) \ - : "q"(*(uint8_t *)src), "0"(*(uint16_t *)dst) \ + : "=&q"(tmp_dst) \ + : "q"(*(uint8_t *)src), "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint16_t *)dst = tmp_dst; \ } else if (dst_len == 4) { \ + uint32_t tmp_dst = *(uint32_t *)dst; \ asm volatile ( \ #iname" %1, %0; " \ - : "=q"(*(uint32_t *)dst) \ - : "q"(*(uint8_t *)src), "0"(*(uint32_t *)dst) \ + : "=&q"(tmp_dst) \ + : "q"(*(uint8_t *)src), "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint32_t *)dst = tmp_dst; \ } else if (dst_len == 8) { \ + uint64_t tmp_dst = *(uint64_t *)dst; \ asm volatile ( \ #iname" %1, %0; " \ - : "=q"(*(uint64_t *)dst) \ - : "q"(*(uint8_t *)src), "0"(*(uint64_t *)dst) \ + : "=&q"(tmp_dst) \ + : "q"(*(uint8_t *)src), "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint64_t *)dst = tmp_dst; \ } \ } #define MAKE_2OP_16EXT_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, uint_t dst_len) { \ if (dst_len == 4) { \ + uint32_t tmp_dst = *(uint32_t *)dst; \ asm volatile ( \ #iname" %1, %0; " \ - : "=q"(*(uint32_t *)dst) \ - : "q"(*(uint16_t *)src), "0"(*(uint32_t *)dst) \ + : "=&q"(tmp_dst) \ + : "q"(*(uint16_t *)src), "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint32_t *)dst = tmp_dst; \ } else if (dst_len == 8) { \ + uint64_t tmp_dst = *(uint64_t *)dst; \ asm volatile ( \ #iname" %1, %0; " \ - : "=q"(*(uint64_t *)dst) \ - : "q"(*(uint16_t *)src), "0"(*(uint64_t *)dst) \ + : "=&q"(tmp_dst) \ + : "q"(*(uint16_t *)src), "0"(tmp_dst) \ + : "memory" \ ); \ + *(uint64_t *)dst = tmp_dst; \ } \ } @@ -472,35 +553,59 @@ #define MAKE_2OUT_64_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src) { \ + uint64_t tmp_dst = *(uint64_t *)dst; \ + uint64_t tmp_src = *(uint64_t *)src; \ + \ asm volatile ( \ #iname"q %1, %0; " \ - : "=q"(*(uint64_t *)dst), "=q"(*(uint64_t *)src) \ - : "0"(*(uint64_t *)dst), "1"(*(uint64_t *)src) \ + : "=&q"(tmp_dst), "=&q"(tmp_src) \ + : "0"(tmp_dst), "1"(tmp_src) \ + : "memory" \ ); \ + *(uint64_t *)src = tmp_src; \ + *(uint64_t *)dst = tmp_dst; \ } #define MAKE_2OUT_32_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src) { \ + uint32_t tmp_dst = *(uint32_t *)dst; \ + uint32_t tmp_src = *(uint32_t *)src; \ + \ asm volatile ( \ #iname"l %1, %0; " \ - : "=q"(*(uint32_t *)dst), "=q"(*(uint32_t *)src) \ - : "0"(*(uint32_t *)dst), "1"(*(uint32_t *)src) \ + : "=&q"(tmp_dst), "=&q"(tmp_src) \ + : "0"(tmp_dst), "1"(tmp_src) \ + : "memory" \ ); \ + *(uint32_t *)src = tmp_src; \ + *(uint32_t *)dst = tmp_dst; \ } #define MAKE_2OUT_16_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src) { \ + uint16_t tmp_dst = *(uint16_t *)dst; \ + uint16_t tmp_src = *(uint16_t *)src; \ + \ asm volatile ( \ #iname"w %1, %0; " \ - : "=q"(*(uint16_t *)dst), "=q"(*(uint16_t *)src) \ - : "0"(*(uint16_t *)dst), "1"(*(uint16_t *)src) \ + : "=&q"(tmp_dst), "=&q"(tmp_src) \ + : "0"(tmp_dst), "1"(tmp_src) \ + : "memory" \ ); \ + *(uint16_t *)src = tmp_src; \ + *(uint16_t *)dst = tmp_dst; \ } #define MAKE_2OUT_8_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src) { \ + uint8_t tmp_dst = *(uint8_t *)dst; \ + uint8_t tmp_src = *(uint8_t *)src; \ + \ asm volatile ( \ #iname"b %1, %0; " \ - : "=q"(*(uint8_t *)dst), "=q"(*(uint8_t *)src) \ - : "0"(*(uint8_t *)dst), "1"(*(uint8_t *)src) \ + : "=&q"(tmp_dst), "=&q"(tmp_src) \ + : "0"(tmp_dst), "1"(tmp_src) \ + : "memory" \ ); \ + *(uint8_t *)src = tmp_src; \ + *(uint8_t *)dst = tmp_dst; \ } diff --git a/palacios/include/palacios/vmm_mtrr.h b/palacios/include/palacios/vmm_mtrr.h deleted file mode 100644 index 0901781..0000000 --- a/palacios/include/palacios/vmm_mtrr.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of the Palacios Virtual Machine Monitor developed - * by the V3VEE Project with funding from the United States National - * Science Foundation and the Department of Energy. - * - * The V3VEE Project is a joint project between Northwestern University - * and the University of New Mexico. You can find out more at - * http://www.v3vee.org - * - * Copyright (c) 2011, Jack Lange - * Copyright (c) 2011, 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_MTRR_H__ -#define __VMM_MTRR_H__ - - -#ifdef __V3VEE__ - -#include - - - -#endif - -#endif diff --git a/palacios/src/devices/piix3.c b/palacios/src/devices/piix3.c index ab82bdb..8752943 100644 --- a/palacios/src/devices/piix3.c +++ b/palacios/src/devices/piix3.c @@ -361,7 +361,15 @@ static int reset_piix3(struct v3_southbridge * piix3) { } -//irq is pirq_rc[intr_pin + pci_dev_num - 1] & 0x3 +//irq is pirq_rc[intr_pin + pci_dev_num - 1] & 0xf +/* +struct pirq_rc_reg { + uint8_t irq : 4; + uint8_t rsvd : 3; + uint8_t disabled : 1; // (1=disabled, 0=enabled) +} +*/ + static int raise_pci_irq(struct pci_device * pci_dev, void * dev_data) { struct v3_southbridge * piix3 = dev_data; @@ -372,7 +380,15 @@ static int raise_pci_irq(struct pci_device * pci_dev, void * dev_data) { //PrintError("Raising PCI IRQ %d, %p\n", piix3_cfg->pirq_rc[irq_index], piix3->vm); - v3_raise_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index]); + if (piix3_cfg->pirq_rc[irq_index] < 16) { + v3_raise_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index] & 0xf); + } else { + PrintError("Tried to raise interrupt on disabled PIRQ entry (%d)\n", irq_index); + PrintError("\tpirq_rc values: 0=0x%x, 1=0x%x, 2=0x%x, 3=0x%x\n", + piix3_cfg->pirq_rc[0], piix3_cfg->pirq_rc[1], + piix3_cfg->pirq_rc[2], piix3_cfg->pirq_rc[3]); + return -1; + } return 0; } @@ -388,7 +404,15 @@ static int lower_pci_irq(struct pci_device * pci_dev, void * dev_data) { // PrintError("Lowering PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]); - v3_lower_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index]); + if (piix3_cfg->pirq_rc[irq_index] < 16) { + v3_lower_irq(piix3->vm, piix3_cfg->pirq_rc[irq_index] & 0xf); + } else { + PrintError("Tried to lower interrupt on disabled PIRQ entry (%d)\n", irq_index); + PrintError("\tpirq_rc values: 0=0x%x, 1=0x%x, 2=0x%x, 3=0x%x\n", + piix3_cfg->pirq_rc[0], piix3_cfg->pirq_rc[1], + piix3_cfg->pirq_rc[2], piix3_cfg->pirq_rc[3]); + return -1; + } return 0; } diff --git a/palacios/src/extensions/ext_mcheck.c b/palacios/src/extensions/ext_mcheck.c index 51605ae..2ab04ca 100644 --- a/palacios/src/extensions/ext_mcheck.c +++ b/palacios/src/extensions/ext_mcheck.c @@ -545,6 +545,25 @@ int v3_mcheck_inject_nb_mce(struct v3_vm_info * const vm, const uint32_t cpu, return 0; } +int v3_mcheck_inject_scrubber_mce(struct v3_vm_info *info, int cpu, uint64_t dst) +{ + struct mc4_stat_msr stat; + struct mc4_addr_msr addr; + + stat.value = 0; + stat.error_code = 0x810; + stat.error_code_ext = 0x8; + stat.uecc = 1; + stat.addr_v = 1; + stat.en = 1; + stat.uc = 1; + stat.val = 1; + + addr.addr64 = dst; + + return v3_mcheck_inject_nb_mce(info, cpu, stat, addr); +} + static struct v3_extension_impl mcheck_impl = { .name = MCHECK, .init = init_mcheck, diff --git a/palacios/src/palacios/Makefile b/palacios/src/palacios/Makefile index d067aae..63a822b 100644 --- a/palacios/src/palacios/Makefile +++ b/palacios/src/palacios/Makefile @@ -33,7 +33,6 @@ obj-y := \ vmm_xml.o \ vmm_mem_hook.o \ vmm_extensions.o \ - vmm_mtrr.o \ vmm_multitree.o \ vmm_bitmap.o \ vmm_barrier.o \ diff --git a/palacios/src/palacios/vmm_mtrr.c b/palacios/src/palacios/vmm_mtrr.c deleted file mode 100644 index 5e27afc..0000000 --- a/palacios/src/palacios/vmm_mtrr.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of the Palacios Virtual Machine Monitor developed - * by the V3VEE Project with funding from the United States National - * Science Foundation and the Department of Energy. - * - * The V3VEE Project is a joint project between Northwestern University - * and the University of New Mexico. You can find out more at - * http://www.v3vee.org - * - * Copyright (c) 2011, Jack Lange - * Copyright (c) 2011, 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 -#include -#include - - -#define MTRR_CAP_MSR 0x00fe -#define MTRR_PHYS_BASE_0 0x0200 -#define MTRR_PHYS_BASE_1 0x0202 -#define MTRR_PHYS_BASE_2 0x0204 -#define MTRR_PHYS_BASE_3 0x0206 -#define MTRR_PHYS_BASE_4 0x0208 -#define MTRR_PHYS_BASE_5 0x020a -#define MTRR_PHYS_BASE_6 0x020c -#define MTRR_PHYS_BASE_7 0x020e -#define MTRR_PHYS_MASK_0 0x0201 -#define MTRR_PHYS_MASK_1 0x0203 -#define MTRR_PHYS_MASK_2 0x0205 -#define MTRR_PHYS_MASK_3 0x0207 -#define MTRR_PHYS_MASK_4 0x0209 -#define MTRR_PHYS_MASK_5 0x020b -#define MTRR_PHYS_MASK_6 0x020d -#define MTRR_PHYS_MASK_7 0x020f -#define MTRR_FIX_64K_00000 0x0250 -#define MTRR_FIX_16K_80000 0x0258 -#define MTRR_FIX_16K_A0000 0x0259 -#define MTRR_FIX_4K_C0000 0x0268 -#define MTRR_FIX_4K_C8000 0x0269 -#define MTRR_FIX_4K_D0000 0x026a -#define MTRR_FIX_4K_D8000 0x026b -#define MTRR_FIX_4K_E0000 0x026c -#define MTRR_FIX_4K_E8000 0x026d -#define MTRR_FIX_4K_F0000 0x026e -#define MTRR_FIX_4K_F8000 0x026f - - -struct mtrr_cap { - - -}; - - -struct mtrr_state { - struct mtrr_cap cap; - -}; - - -static int mtrr_cap_read(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data) { - return 0; -} - -static int mtrr_cap_write(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data) { - - return 0; -} - - - -static int init_mtrrs(struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) { - - - V3_Print("Intializing MTRR extension\n"); - - v3_hook_msr(vm, MTRR_CAP_MSR, mtrr_cap_read, mtrr_cap_write, NULL); - - - return 0; -} - - -static struct v3_extension_impl mtrr_ext = { - .name = "MTRRS", - .init = init_mtrrs, - .deinit = NULL, - .core_init = NULL, - .core_deinit = NULL -}; - - - -register_extension(&mtrr_ext); diff --git a/palacios/src/palacios/vmx_handler.c b/palacios/src/palacios/vmx_handler.c index 5af3122..be86fe2 100644 --- a/palacios/src/palacios/vmx_handler.c +++ b/palacios/src/palacios/vmx_handler.c @@ -102,6 +102,9 @@ int v3_handle_vmx_exit(struct guest_info * info, struct vmx_exit_info * exit_inf PrintError("Page fault in unimplemented paging mode\n"); return -1; } + } else if ((uint8_t)exit_info->int_info == 2) { + // NMI. Don't do anything + V3_Print("NMI Exception Received\n"); } else { PrintError("Unknown exception: 0x%x\n", (uint8_t)exit_info->int_info); v3_print_GPRs(info);