From: Jack Lange Date: Sat, 6 Feb 2010 21:55:55 +0000 (-0600) Subject: reorganization of the symbiotic infrastructure X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=ee1279646a778613b23a42350b903ebb57c068f8;p=palacios.git reorganization of the symbiotic infrastructure --- diff --git a/Kconfig b/Kconfig index adf2abf..a9cc6ac 100644 --- a/Kconfig +++ b/Kconfig @@ -73,13 +73,6 @@ config SHADOW_PAGING_TELEMETRY help Enable telemetry information for shadow paging -config SYMBIOTIC_SWAP_TELEMETRY - bool "Enable Symbiotic Swap Telemetry" - default n - depends on TELEMETRY && SYMBIOTIC_SWAP - help - Enable the telemetry information for the symbiotic swap subsystem - config PASSTHROUGH_VIDEO bool "Enable Passthrough Video" @@ -138,6 +131,14 @@ config SHADOW_PAGING_VTLB help Enables Virtual TLB implemenation for shadow paging + +config DEBUG_SHDW_PG_VTLB + bool "Enable VTLB debugging" + default n + depends on SHADOW_PAGING_VTLB + help + Enables debugging messages for VTLB implementation + endmenu @@ -150,13 +151,37 @@ config SYMBIOTIC Enable Symbiotic components of the VMM + +config SYMCALL + bool "Symbiotic upcalls" + default n + depends on SYMBIOTIC && EXPERIMENTAL + help + Enables the Symbiotic upcall interface + +config SYMMOD + bool "Symbiotic Modules" + default n + depends on SYMBIOTIC && EXPERIMENTAL + help + Enable Symbiotic module loading + + config SYMBIOTIC_SWAP bool "Symbiotic Swap" default n - depends on SYMBIOTIC && EXPERIMENTAL + depends on SYMBIOTIC && SYMCALL && EXPERIMENTAL help This enables the symbiotic swap architecture +config SYMBIOTIC_SWAP_TELEMETRY + bool "Enable Symbiotic Swap Telemetry" + default n + depends on TELEMETRY && SYMBIOTIC_SWAP + help + Enable the telemetry information for the symbiotic swap subsystem + + endmenu diff --git a/palacios/include/devices/lnx_virtio_pci.h b/palacios/include/devices/lnx_virtio_pci.h index 1131feb..67c6a8b 100644 --- a/palacios/include/devices/lnx_virtio_pci.h +++ b/palacios/include/devices/lnx_virtio_pci.h @@ -35,11 +35,13 @@ #define VIRTIO_BALLOON_DEV_ID 0x1002 #define VIRTIO_CONSOLE_DEV_ID 0x1003 #define VIRTIO_SYMBIOTIC_DEV_ID 0x100a +#define VIRTIO_SYMMOD_DEV_ID 0x100b #define VIRTIO_NET_SUBDEVICE_ID 1 #define VIRTIO_BLOCK_SUBDEVICE_ID 2 #define VIRTIO_BALLOON_SUBDEVICE_ID 5 #define VIRTIO_SYMBIOTIC_SUBDEVICE_ID 10 +#define VIRTIO_SYMMOD_SUBDEVICE_ID 11 #define HOST_FEATURES_PORT 0 diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 37ae5b8..ec4569e 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -48,88 +48,14 @@ - - -struct v3_gprs { - v3_reg_t rdi; - v3_reg_t rsi; - v3_reg_t rbp; - v3_reg_t rsp; - v3_reg_t rbx; - v3_reg_t rdx; - v3_reg_t rcx; - v3_reg_t rax; - - v3_reg_t r8; - v3_reg_t r9; - v3_reg_t r10; - v3_reg_t r11; - v3_reg_t r12; - v3_reg_t r13; - v3_reg_t r14; - v3_reg_t r15; - -} __attribute__((packed)); - - -struct v3_ctrl_regs { - v3_reg_t cr0; - v3_reg_t cr2; - v3_reg_t cr3; - v3_reg_t cr4; - v3_reg_t cr8; - v3_reg_t rflags; - v3_reg_t efer; -}; - - - -struct v3_dbg_regs { - v3_reg_t dr0; - v3_reg_t dr1; - v3_reg_t dr2; - v3_reg_t dr3; - v3_reg_t dr6; - v3_reg_t dr7; -}; - -struct v3_segment { - uint16_t selector; - uint_t limit; - uint64_t base; - uint_t type : 4; - uint_t system : 1; - uint_t dpl : 2; - uint_t present : 1; - uint_t avail : 1; - uint_t long_mode : 1; - uint_t db : 1; - uint_t granularity : 1; - uint_t unusable : 1; -} __attribute__((packed)); - - -struct v3_segments { - struct v3_segment cs; - struct v3_segment ds; - struct v3_segment es; - struct v3_segment fs; - struct v3_segment gs; - struct v3_segment ss; - struct v3_segment ldtr; - struct v3_segment gdtr; - struct v3_segment idtr; - struct v3_segment tr; -}; - - #ifdef CONFIG_SYMBIOTIC -#include +#include +struct v3_sym_core_state; #endif #include -struct shadow_page_state; + struct v3_intr_state; @@ -137,9 +63,7 @@ struct v3_intr_state; struct v3_sym_swap_state; #endif -#ifdef CONFIG_SYMBIOTIC -struct v3_sym_state; -#endif + struct guest_info { @@ -188,7 +112,7 @@ struct guest_info { #ifdef CONFIG_SYMBIOTIC // Symbiotic state - struct v3_sym_local_state sym_local_state; + struct v3_sym_core_state sym_core_state; #endif @@ -228,7 +152,7 @@ struct v3_vm_info { #ifdef CONFIG_SYMBIOTIC // Symbiotic state - struct v3_sym_global_state sym_global_state; + struct v3_sym_vm_state sym_vm_state; #ifdef CONFIG_SYMBIOTIC_SWAP struct v3_sym_swap_state swap_state; #endif diff --git a/palacios/include/palacios/vmm_regs.h b/palacios/include/palacios/vmm_regs.h new file mode 100644 index 0000000..e8ed725 --- /dev/null +++ b/palacios/include/palacios/vmm_regs.h @@ -0,0 +1,102 @@ +/* + * 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_REGS_H__ +#define __VMM_REGS_H__ + +#ifdef __V3VEE__ + +#include + +struct v3_gprs { + v3_reg_t rdi; + v3_reg_t rsi; + v3_reg_t rbp; + v3_reg_t rsp; + v3_reg_t rbx; + v3_reg_t rdx; + v3_reg_t rcx; + v3_reg_t rax; + + v3_reg_t r8; + v3_reg_t r9; + v3_reg_t r10; + v3_reg_t r11; + v3_reg_t r12; + v3_reg_t r13; + v3_reg_t r14; + v3_reg_t r15; + +} __attribute__((packed)); + + +struct v3_ctrl_regs { + v3_reg_t cr0; + v3_reg_t cr2; + v3_reg_t cr3; + v3_reg_t cr4; + v3_reg_t cr8; + v3_reg_t rflags; + v3_reg_t efer; +}; + + + +struct v3_dbg_regs { + v3_reg_t dr0; + v3_reg_t dr1; + v3_reg_t dr2; + v3_reg_t dr3; + v3_reg_t dr6; + v3_reg_t dr7; +}; + +struct v3_segment { + uint16_t selector; + uint_t limit; + uint64_t base; + uint_t type : 4; + uint_t system : 1; + uint_t dpl : 2; + uint_t present : 1; + uint_t avail : 1; + uint_t long_mode : 1; + uint_t db : 1; + uint_t granularity : 1; + uint_t unusable : 1; +} __attribute__((packed)); + + +struct v3_segments { + struct v3_segment cs; + struct v3_segment ds; + struct v3_segment es; + struct v3_segment fs; + struct v3_segment gs; + struct v3_segment ss; + struct v3_segment ldtr; + struct v3_segment gdtr; + struct v3_segment idtr; + struct v3_segment tr; +}; + + +#endif + +#endif diff --git a/palacios/include/palacios/vmm_sym_iface.h b/palacios/include/palacios/vmm_sym_iface.h deleted file mode 100644 index ddda447..0000000 --- a/palacios/include/palacios/vmm_sym_iface.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * This file is part of the Palacios Virtual Machine Monitor developed - * by the V3VEE Project with funding from the United States National - * Science Foundation and the Department of Energy. - * - * The V3VEE Project is a joint project between Northwestern University - * and the University of New Mexico. You can find out more at - * http://www.v3vee.org - * - * Copyright (c) 2008, Jack Lange - * 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_SYM_IFACE_H__ -#define __VMM_SYM_IFACE_H__ - -#ifdef __V3VEE__ - - - - -struct v3_sym_global_page { - uint64_t magic; - - union { - uint32_t feature_flags; - struct { - uint_t pci_map_valid : 1; - } __attribute__((packed)); - } __attribute__((packed)); - - uint8_t pci_pt_map[(4 * 256) / 8]; // we're hardcoding this: (4 busses, 256 max devs) - -} __attribute__((packed)); - -struct v3_sym_local_page { - uint64_t magic; - - union { - uint32_t state_flags; - struct { - uint32_t sym_call_active : 1; - uint32_t sym_call_enabled : 1; - } __attribute__((packed)); - } __attribute__((packed)); -} __attribute__((packed)); - - -#include - - -struct v3_sym_cpu_context { - struct v3_gprs vm_regs; - struct v3_segment cs; - struct v3_segment ss; - uint64_t gs_base; - uint64_t fs_base; - uint64_t rip; - uint64_t flags; - uint8_t cpl; -}; - -struct v3_symcall_state { - struct { - uint_t sym_call_active : 1; - uint_t sym_call_returned : 1; - uint_t sym_call_error : 1; - } __attribute__((packed)); - - struct v3_sym_cpu_context old_ctx; - - int sym_call_errno; - - uint64_t sym_call_rip; - uint64_t sym_call_cs; - uint64_t sym_call_rsp; - uint64_t sym_call_gs; - uint64_t sym_call_fs; -}; - -struct v3_sym_global_state { - struct v3_sym_global_page * sym_page; - - addr_t global_page_pa; - uint64_t global_guest_pa; - - int active; // activated when symbiotic page MSR is written -}; - - -struct v3_sym_local_state { - struct v3_sym_local_page * local_page; - - addr_t local_page_pa; - uint64_t local_guest_pa; - - struct v3_symcall_state symcall_state; - - int active; // activated when symbiotic page MSR is written -}; - - - - - -int v3_init_sym_iface(struct v3_vm_info * vm); -int v3_init_sym_core(struct guest_info * core); - -typedef uint64_t sym_arg_t; - -#define v3_sym_call0(info, call_num) \ - v3_sym_call(info, call_num, 0, 0, 0, 0, 0) -#define v3_sym_call1(info, call_num, arg1) \ - v3_sym_call(info, call_num, arg1, 0, 0, 0, 0) -#define v3_sym_call2(info, call_num, arg1, arg2) \ - v3_sym_call(info, call_num, arg1, arg2, 0, 0, 0) -#define v3_sym_call3(info, call_num, arg1, arg2, arg3) \ - v3_sym_call(info, call_num, arg1, arg2, arg3, 0, 0) -#define v3_sym_call4(info, call_num, arg1, arg2, arg3, arg4) \ - v3_sym_call(info, call_num, arg1, arg2, arg3, arg4, 0) -#define v3_sym_call5(info, call_num, arg1, arg2, arg3, arg4, arg5) \ - v3_sym_call(info, call_num, arg1, arg2, arg3, arg4, arg5) - - - - -int v3_sym_map_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn); -int v3_sym_unmap_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn); - - -/* Symcall numbers */ -#define SYMCALL_TEST 1 -#define SYMCALL_MEM_LOOKUP 10 -/* ** */ - -int v3_sym_call(struct guest_info * info, - uint64_t call_num, sym_arg_t * arg0, - sym_arg_t * arg1, sym_arg_t * arg2, - sym_arg_t * arg3, sym_arg_t * arg4); - - -#endif - -#endif diff --git a/palacios/include/palacios/vmm_sym_swap.h b/palacios/include/palacios/vmm_sym_swap.h index 00f053b..6bd531c 100644 --- a/palacios/include/palacios/vmm_sym_swap.h +++ b/palacios/include/palacios/vmm_sym_swap.h @@ -21,7 +21,6 @@ #define __VMM_SYM_SWAP_H__ #ifdef __V3VEE__ -#ifdef CONFIG_SYMBIOTIC_SWAP #include #include @@ -80,6 +79,6 @@ addr_t v3_map_swp_page(struct v3_vm_info * vm, pte32_t * shadow_pte, pte32_t * g int v3_swap_flush(struct v3_vm_info * vm); -#endif + #endif #endif diff --git a/palacios/include/palacios/vmm_symbiotic.h b/palacios/include/palacios/vmm_symbiotic.h new file mode 100644 index 0000000..60bbb8f --- /dev/null +++ b/palacios/include/palacios/vmm_symbiotic.h @@ -0,0 +1,68 @@ +/* + * 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_SYMBIOTIC_H__ +#define __VMM_SYMBIOTIC_H__ + +#ifdef __V3VEE__ + +#include + +#include + +#ifdef CONFIG_SYMCALL +#include +#endif + +#ifdef CONFIG_SYMMOD +#include +#endif + + + +struct v3_sym_vm_state { + struct v3_symspy_global_state symspy_state; + +#ifdef CONFIG_SYMMOD + struct v3_symmod_global_state symmod_state; +#endif +}; + + +struct v3_sym_core_state { + struct v3_symspy_local_state symspy_state; + +#ifdef CONFIG_SYMCALL + struct v3_symcall_state symcall_state; +#endif + +#ifdef CONFIG_SYMMOD + struct v3_symmod_local_state symmod_state; +#endif +}; + + +int v3_init_symbiotic_vm(struct v3_vm_info * vm); +int v3_init_symbiotic_core(struct guest_info * core); + + +#endif + +#endif diff --git a/palacios/include/palacios/vmm_symcall.h b/palacios/include/palacios/vmm_symcall.h new file mode 100644 index 0000000..6ab2bf1 --- /dev/null +++ b/palacios/include/palacios/vmm_symcall.h @@ -0,0 +1,94 @@ +/* + * 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_SYMCALL_H__ +#define __VMM_SYMCALL_H__ + +#ifdef __V3VEE__ + + +#include + + + +struct v3_sym_cpu_context { + struct v3_gprs vm_regs; + struct v3_segment cs; + struct v3_segment ss; + uint64_t gs_base; + uint64_t fs_base; + uint64_t rip; + uint64_t flags; + uint8_t cpl; +}; + +struct v3_symcall_state { + struct { + uint_t sym_call_active : 1; + uint_t sym_call_returned : 1; + uint_t sym_call_error : 1; + } __attribute__((packed)); + + struct v3_sym_cpu_context old_ctx; + + int sym_call_errno; + + uint64_t sym_call_rip; + uint64_t sym_call_cs; + uint64_t sym_call_rsp; + uint64_t sym_call_gs; + uint64_t sym_call_fs; +}; + + +typedef uint64_t sym_arg_t; + +#define v3_sym_call0(info, call_num) \ + v3_sym_call(info, call_num, 0, 0, 0, 0, 0) +#define v3_sym_call1(info, call_num, arg1) \ + v3_sym_call(info, call_num, arg1, 0, 0, 0, 0) +#define v3_sym_call2(info, call_num, arg1, arg2) \ + v3_sym_call(info, call_num, arg1, arg2, 0, 0, 0) +#define v3_sym_call3(info, call_num, arg1, arg2, arg3) \ + v3_sym_call(info, call_num, arg1, arg2, arg3, 0, 0) +#define v3_sym_call4(info, call_num, arg1, arg2, arg3, arg4) \ + v3_sym_call(info, call_num, arg1, arg2, arg3, arg4, 0) +#define v3_sym_call5(info, call_num, arg1, arg2, arg3, arg4, arg5) \ + v3_sym_call(info, call_num, arg1, arg2, arg3, arg4, arg5) + + + + +/* Symcall numbers */ +#define SYMCALL_TEST 1 +#define SYMCALL_MEM_LOOKUP 10 +/* ** */ + +int v3_sym_call(struct guest_info * info, + uint64_t call_num, sym_arg_t * arg0, + sym_arg_t * arg1, sym_arg_t * arg2, + sym_arg_t * arg3, sym_arg_t * arg4); + + + +int v3_init_symcall_vm(struct v3_vm_info * vm); + +#endif + +#endif diff --git a/palacios/include/palacios/vmm_symspy.h b/palacios/include/palacios/vmm_symspy.h new file mode 100644 index 0000000..5b17b39 --- /dev/null +++ b/palacios/include/palacios/vmm_symspy.h @@ -0,0 +1,93 @@ +/* + * 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_SYMSPY_H__ +#define __VMM_SYMSPY_H__ + +#ifdef __V3VEE__ + +#include + + + +struct v3_symspy_global_page { + uint64_t magic; + + union { + uint32_t feature_flags; + struct { + uint_t pci_map_valid : 1; + } __attribute__((packed)); + } __attribute__((packed)); + + uint8_t pci_pt_map[(4 * 256) / 8]; // we're hardcoding this: (4 busses, 256 max devs) + +} __attribute__((packed)); + +struct v3_symspy_local_page { + uint64_t magic; + + union { + uint32_t symcall_flags; + struct { + uint32_t sym_call_active : 1; + uint32_t sym_call_enabled : 1; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + + +struct v3_symspy_global_state { + struct v3_symspy_global_page * sym_page; + + addr_t global_page_pa; + uint64_t global_guest_pa; + + int active; // activated when symbiotic page MSR is written +}; + + +struct v3_symspy_local_state { + struct v3_symspy_local_page * local_page; + + addr_t local_page_pa; + uint64_t local_guest_pa; + + int active; // activated when symbiotic page MSR is written +}; + + + + +int v3_init_symspy_vm(struct v3_vm_info * vm, struct v3_symspy_global_state * state); +int v3_init_symspy_core(struct guest_info * core, struct v3_symspy_local_state * state); + + + +int v3_sym_map_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn); +int v3_sym_unmap_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn); + + + + + +#endif + +#endif diff --git a/palacios/src/devices/Makefile b/palacios/src/devices/Makefile index 88c5706..fd2b694 100644 --- a/palacios/src/devices/Makefile +++ b/palacios/src/devices/Makefile @@ -31,3 +31,5 @@ obj-$(CONFIG_CGA) += cga.o obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o obj-$(CONFIG_PASSTHROUGH_PCI) += pci_passthrough.o + +obj-$(CONFIG_SYMBIOTIC_MODULES) += lnx_virtio_symmod.o diff --git a/palacios/src/devices/pci_passthrough.c b/palacios/src/devices/pci_passthrough.c index d574eee..2506d77 100644 --- a/palacios/src/devices/pci_passthrough.c +++ b/palacios/src/devices/pci_passthrough.c @@ -36,7 +36,7 @@ #include #include #include // must include this to avoid dependency issue -#include +#include #include #include diff --git a/palacios/src/palacios/Makefile b/palacios/src/palacios/Makefile index b03a7eb..76d62e9 100644 --- a/palacios/src/palacios/Makefile +++ b/palacios/src/palacios/Makefile @@ -53,7 +53,6 @@ obj-$(CONFIG_VMX) += vmx.o \ obj-$(CONFIG_SHADOW_PAGING_VTLB) += vmm_shdw_pg_tlb.o -obj-$(CONFIG_SYMBIOTIC_SWAP) += vmm_shdw_pg_swapbypass.o obj-$(CONFIG_INSTRUMENT_VMM) += vmm_instrument.o @@ -61,6 +60,8 @@ obj-$(CONFIG_TELEMETRY) += vmm_telemetry.o obj-$(CONFIG_SOCKET) += vmm_socket.o obj-$(CONFIG_VNET) += vmm_vnet.o -obj-$(CONFIG_SYMBIOTIC) += vmm_sym_iface.o +obj-$(CONFIG_SYMBIOTIC) += vmm_symbiotic.o vmm_symspy.o +obj-$(CONFIG_SYMCALL) += vmm_symcall.o +obj-$(CONFIG_SYMMOD) += vmm_symmod.o -obj-$(CONFIG_SYMBIOTIC_SWAP) += vmm_sym_swap.o +obj-$(CONFIG_SYMBIOTIC_SWAP) += vmm_sym_swap.o vmm_shdw_pg_swapbypass.o diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 75ba3a0..d4a6fd7 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -441,8 +441,8 @@ int v3_svm_enter(struct guest_info * info) { guest_state->rip = info->rip; guest_state->rsp = info->vm_regs.rsp; -#ifdef CONFIG_SYMBIOTIC - if (info->sym_local_state.symcall_state.sym_call_active == 0) { +#ifdef CONFIG_SYMCALL + if (info->sym_core_state.symcall_state.sym_call_active == 0) { update_irq_entry_state(info); } #else @@ -458,8 +458,8 @@ int v3_svm_enter(struct guest_info * info) { (void *)(addr_t)info->rip); */ -#ifdef CONFIG_SYMBIOTIC - if (info->sym_local_state.symcall_state.sym_call_active == 1) { +#ifdef CONFIG_SYMCALL + if (info->sym_core_state.symcall_state.sym_call_active == 1) { if (guest_ctrl->guest_ctrl.V_IRQ == 1) { V3_Print("!!! Injecting Interrupt during Sym call !!!\n"); } @@ -517,8 +517,8 @@ int v3_svm_enter(struct guest_info * info) { exit_info2 = guest_ctrl->exit_info2; -#ifdef CONFIG_SYMBIOTIC - if (info->sym_local_state.symcall_state.sym_call_active == 0) { +#ifdef CONFIG_SYMCALL + if (info->sym_core_state.symcall_state.sym_call_active == 0) { update_irq_exit_state(info); } #else diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c index 87f4f31..d0a8fb8 100644 --- a/palacios/src/palacios/vm_guest.c +++ b/palacios/src/palacios/vm_guest.c @@ -430,7 +430,7 @@ int v3_init_vm(struct v3_vm_info * vm) { #ifdef CONFIG_SYMBIOTIC - v3_init_sym_iface(vm); + v3_init_symbiotic_vm(vm); #endif v3_init_dev_mgr(vm); @@ -494,7 +494,7 @@ int v3_init_core(struct guest_info * core) { #ifdef CONFIG_SYMBIOTIC - v3_init_sym_core(core); + v3_init_symbiotic_core(core); #endif // init SVM/VMX diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index b622295..39c4d49 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -32,14 +32,7 @@ #include -#ifdef CONFIG_SYMBIOTIC -#include -#ifdef CONFIG_SYMBIOTIC_SWAP -#include -#endif - -#endif diff --git a/palacios/src/palacios/vmm_shdw_pg_swapbypass_32.h b/palacios/src/palacios/vmm_shdw_pg_swapbypass_32.h index 15523ff..e3d2460 100644 --- a/palacios/src/palacios/vmm_shdw_pg_swapbypass_32.h +++ b/palacios/src/palacios/vmm_shdw_pg_swapbypass_32.h @@ -33,9 +33,8 @@ static inline int activate_shadow_pt_32(struct guest_info * info) { shadow_cr3->pwt = guest_cr3->pwt; shadow_cr3->pcd = guest_cr3->pcd; -#ifdef CONFIG_SYMBIOTIC_SWAP + v3_swap_flush(info->vm_info); -#endif return 0; } diff --git a/palacios/src/palacios/vmm_shdw_pg_tlb.c b/palacios/src/palacios/vmm_shdw_pg_tlb.c index 4477786..050d6e7 100644 --- a/palacios/src/palacios/vmm_shdw_pg_tlb.c +++ b/palacios/src/palacios/vmm_shdw_pg_tlb.c @@ -23,6 +23,13 @@ #include #include + +#ifndef CONFIG_DEBUG_SHDW_PG_VTLB +#undef PrintDebug +#define PrintDebug(fmt, ...) +#endif + + struct shadow_page_data { v3_reg_t cr3; addr_t page_pa; diff --git a/palacios/src/palacios/vmm_shdw_pg_tlb_32.h b/palacios/src/palacios/vmm_shdw_pg_tlb_32.h index 15d92ac..3958250 100644 --- a/palacios/src/palacios/vmm_shdw_pg_tlb_32.h +++ b/palacios/src/palacios/vmm_shdw_pg_tlb_32.h @@ -32,10 +32,6 @@ static inline int activate_shadow_pt_32(struct guest_info * core) { shadow_cr3->pwt = guest_cr3->pwt; shadow_cr3->pcd = guest_cr3->pcd; - -#ifdef CONFIG_SYMBIOTIC_SWAP - v3_swap_flush(core->vm_info); -#endif return 0; } @@ -228,95 +224,8 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault PrintDebug("Access error injecting pf to guest (guest access error=%d) (pf error code=%d)\n", guest_pte_access, *(uint_t*)&error_code); -#ifdef CONFIG_SYMBIOTIC_SWAP - if (is_swapped_pte32(guest_pte)) { - - pf_error_t swap_perms; - - - /* - int sym_ret = v3_get_vaddr_perms(info, fault_addr, guest_pte, &swap_perms); - sym_ret = 0; - */ - addr_t swp_pg_addr = 0; - - -#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY - if (error_code.write == 0) { - info->vm_info->swap_state.read_faults++; - } else { - info->vm_info->swap_state.write_faults++; - } -#endif - - - swp_pg_addr = v3_get_swapped_pg_addr(info->vm_info, guest_pte); - - if (swp_pg_addr != 0) { - PrintDebug("Swapped page address=%p\n", (void *)swp_pg_addr); - - /* - if (info->cpl == 0) { - PrintError("Swapped Page fault in kernel mode.... bad...\n"); - goto inject; - } - */ - - int sym_ret = v3_get_vaddr_perms(info, fault_addr, guest_pte, &swap_perms); - - if (sym_ret == -1) { - PrintError("Symcall error...\n"); - return -1; - } else if (sym_ret == 0) { - - - if (swap_perms.present == 0) { - PrintError("Nonpresent swapped page\n"); - } - - // swap_perms.write ==1 || error_code.write == 0 - // swap_perms.user == 0 || error_code.user == 1 - - // This checks for permissions violations that require a guest PF injection - if ( (swap_perms.present == 1) && - ( (swap_perms.write == 1) || - (error_code.write == 0) ) && - ( (swap_perms.user == 1) || - (error_code.user == 0) ) ) { - addr_t swp_pg_pa = 0; - - swp_pg_pa = v3_map_swp_page(info->vm_info, shadow_pte, guest_pte, (void *)swp_pg_addr); - - PrintDebug("Page fault on swapped out page (vaddr=%p) (pte=%x) (error_code=%x)\n", - (void *)fault_addr, *(uint32_t *)guest_pte, *(uint32_t *)&error_code); - - shadow_pte->writable = swap_perms.write; - shadow_pte->user_page = swap_perms.user; - - shadow_pte->write_through = 0; - shadow_pte->cache_disable = 0; - shadow_pte->global_page = 0; - - shadow_pte->present = 1; - - shadow_pte->page_base_addr = swp_pg_pa; - -#ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY - info->vm_info->swap_state.mapped_pages++; -#endif - // PrintError("Swap fault handled\n"); - return 0; - } - } - } else { - PrintDebug("Not a sym swappable page\n"); - } - - } -#endif // inject: - if (v3_inject_guest_pf(info, fault_addr, error_code) == -1) { PrintError("Could not inject guest page fault for vaddr %p\n", (void *)fault_addr); return -1; diff --git a/palacios/src/palacios/vmm_sym_iface.c b/palacios/src/palacios/vmm_sym_iface.c deleted file mode 100644 index 9b3a090..0000000 --- a/palacios/src/palacios/vmm_sym_iface.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * This file is part of the Palacios Virtual Machine Monitor developed - * by the V3VEE Project with funding from the United States National - * Science Foundation and the Department of Energy. - * - * The V3VEE Project is a joint project between Northwestern University - * and the University of New Mexico. You can find out more at - * http://www.v3vee.org - * - * Copyright (c) 2008, Jack Lange - * 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 -#include -#include -#include - - -#define SYMSPY_GLOBAL_MSR 0x534 -#define SYMSPY_LOCAL_MSR 0x535 - -#define SYM_CPUID_NUM 0x90000000 - -// A succesfull symcall returns via the RET_HCALL, with the return values in registers -// A symcall error returns via the ERR_HCALL with the error code in rbx - - -/* Notes: We use a combination of SYSCALL and SYSENTER Semantics - * SYSCALL just sets an EIP, CS/SS seg, and GS seg via swapgs - * the RSP is loaded via the structure pointed to by GS - * This is safe because it assumes that system calls are guaranteed to be made with an empty kernel stack. - * We cannot make that assumption with a symcall, so we have to have our own stack area somewhere. - * SYSTENTER does not really use the GS base MSRs, but we do to map to 64 bit kernels - */ - -#define SYMCALL_RIP_MSR 0x536 -#define SYMCALL_RSP_MSR 0x537 -#define SYMCALL_CS_MSR 0x538 -#define SYMCALL_GS_MSR 0x539 -#define SYMCALL_FS_MSR 0x540 - -static int symspy_msr_read(struct guest_info * core, uint_t msr, - struct v3_msr * dst, void * priv_data) { - struct v3_sym_global_state * global_state = &(core->vm_info->sym_global_state); - struct v3_sym_local_state * local_state = &(core->sym_local_state); - - switch (msr) { - case SYMSPY_GLOBAL_MSR: - dst->value = global_state->global_guest_pa; - break; - case SYMSPY_LOCAL_MSR: - dst->value = local_state->local_guest_pa; - break; - default: - return -1; - } - - return 0; -} - -static int symcall_msr_read(struct guest_info * core, uint_t msr, - struct v3_msr * dst, void * priv_data) { - struct v3_symcall_state * state = &(core->sym_local_state.symcall_state); - - switch (msr) { - case SYMCALL_RIP_MSR: - dst->value = state->sym_call_rip; - break; - case SYMCALL_RSP_MSR: - dst->value = state->sym_call_rsp; - break; - case SYMCALL_CS_MSR: - dst->value = state->sym_call_cs; - break; - case SYMCALL_GS_MSR: - dst->value = state->sym_call_gs; - break; - case SYMCALL_FS_MSR: - dst->value = state->sym_call_fs; - break; - default: - return -1; - } - - return 0; -} - -static int symspy_msr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { - - if (msr == SYMSPY_GLOBAL_MSR) { - struct v3_sym_global_state * global_state = &(core->vm_info->sym_global_state); - - PrintDebug("Symbiotic Glbal MSR write for page %p\n", (void *)(addr_t)src.value); - - if (global_state->active == 1) { - // unmap page - struct v3_shadow_region * old_reg = v3_get_shadow_region(core->vm_info, core->cpu_id, - (addr_t)global_state->global_guest_pa); - - if (old_reg == NULL) { - PrintError("Could not find previously active symbiotic page (%p)\n", - (void *)(addr_t)global_state->global_guest_pa); - return -1; - } - - v3_delete_shadow_region(core->vm_info, old_reg); - } - - global_state->global_guest_pa = src.value; - global_state->global_guest_pa &= ~0xfffLL; - - global_state->active = 1; - - // map page - v3_add_shadow_mem(core->vm_info, V3_MEM_CORE_ANY, (addr_t)global_state->global_guest_pa, - (addr_t)(global_state->global_guest_pa + PAGE_SIZE_4KB - 1), - global_state->global_page_pa); - } else if (msr == SYMSPY_LOCAL_MSR) { - struct v3_sym_local_state * local_state = &(core->sym_local_state); - - PrintDebug("Symbiotic Local MSR write for page %p\n", (void *)(addr_t)src.value); - - if (local_state->active == 1) { - // unmap page - struct v3_shadow_region * old_reg = v3_get_shadow_region(core->vm_info, core->cpu_id, - (addr_t)local_state->local_guest_pa); - - if (old_reg == NULL) { - PrintError("Could not find previously active symbiotic page (%p)\n", - (void *)(addr_t)local_state->local_guest_pa); - return -1; - } - - v3_delete_shadow_region(core->vm_info, old_reg); - } - - local_state->local_guest_pa = src.value; - local_state->local_guest_pa &= ~0xfffLL; - - local_state->active = 1; - - // map page - v3_add_shadow_mem(core->vm_info, core->cpu_id, (addr_t)local_state->local_guest_pa, - (addr_t)(local_state->local_guest_pa + PAGE_SIZE_4KB - 1), - local_state->local_page_pa); - } else { - PrintError("Invalid Symbiotic MSR write (0x%x)\n", msr); - return -1; - } - - return 0; -} - - -static int symcall_msr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { - struct v3_symcall_state * state = &(core->sym_local_state.symcall_state); - - switch (msr) { - case SYMCALL_RIP_MSR: - state->sym_call_rip = src.value; - break; - case SYMCALL_RSP_MSR: - state->sym_call_rsp = src.value; - break; - case SYMCALL_CS_MSR: - state->sym_call_cs = src.value; - break; - case SYMCALL_GS_MSR: - state->sym_call_gs = src.value; - break; - case SYMCALL_FS_MSR: - state->sym_call_fs = src.value; - break; - default: - PrintError("Invalid Symbiotic MSR write (0x%x)\n", msr); - return -1; - } - return 0; -} - -static int cpuid_fn(struct guest_info * core, uint32_t cpuid, - uint32_t * eax, uint32_t * ebx, - uint32_t * ecx, uint32_t * edx, - void * private_data) { - extern v3_cpu_arch_t v3_cpu_types[]; - - *eax = *(uint32_t *)"V3V"; - - if ((v3_cpu_types[core->cpu_id] == V3_SVM_CPU) || - (v3_cpu_types[core->cpu_id] == V3_SVM_REV3_CPU)) { - *ebx = *(uint32_t *)"SVM"; - } else if ((v3_cpu_types[core->cpu_id] == V3_VMX_CPU) || - (v3_cpu_types[core->cpu_id] == V3_VMX_EPT_CPU)) { - *ebx = *(uint32_t *)"VMX"; - } - - - return 0; -} - - -static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * private_data); -static int sym_call_err(struct guest_info * info, uint_t hcall_id, void * private_data); - - - -int v3_init_sym_iface(struct v3_vm_info * vm) { - struct v3_sym_global_state * global_state = &(vm->sym_global_state); - memset(global_state, 0, sizeof(struct v3_sym_global_state)); - - global_state->global_page_pa = (addr_t)V3_AllocPages(1); - global_state->sym_page = (struct v3_sym_global_page *)V3_VAddr((void *)global_state->global_page_pa); - memset(global_state->sym_page, 0, PAGE_SIZE_4KB); - - memcpy(&(global_state->sym_page->magic), "V3V", 3); - - v3_hook_msr(vm, SYMSPY_LOCAL_MSR, symspy_msr_read, symspy_msr_write, NULL); - v3_hook_msr(vm, SYMSPY_GLOBAL_MSR, symspy_msr_read, symspy_msr_write, NULL); - - v3_hook_cpuid(vm, SYM_CPUID_NUM, cpuid_fn, NULL); - - v3_hook_msr(vm, SYMCALL_RIP_MSR, symcall_msr_read, symcall_msr_write, NULL); - v3_hook_msr(vm, SYMCALL_RSP_MSR, symcall_msr_read, symcall_msr_write, NULL); - v3_hook_msr(vm, SYMCALL_CS_MSR, symcall_msr_read, symcall_msr_write, NULL); - v3_hook_msr(vm, SYMCALL_GS_MSR, symcall_msr_read, symcall_msr_write, NULL); - v3_hook_msr(vm, SYMCALL_FS_MSR, symcall_msr_read, symcall_msr_write, NULL); - - v3_register_hypercall(vm, SYMCALL_RET_HCALL, sym_call_ret, NULL); - v3_register_hypercall(vm, SYMCALL_ERR_HCALL, sym_call_err, NULL); - - return 0; -} - - -int v3_init_sym_core(struct guest_info * core) { - struct v3_sym_local_state * local_state = &(core->sym_local_state); - memset(local_state, 0, sizeof(struct v3_sym_local_state)); - - local_state->local_page_pa = (addr_t)V3_AllocPages(1); - local_state->local_page = (struct v3_sym_local_page *)V3_VAddr((void *)local_state->local_page_pa); - memset(local_state->local_page, 0, PAGE_SIZE_4KB); - - snprintf((uint8_t *)&(local_state->local_page->magic), 8, "V3V.%d", core->cpu_id); - - return 0; -} - - -int v3_sym_map_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn) { - struct v3_sym_global_state * global_state = &(vm->sym_global_state); - uint_t dev_index = (bus << 8) + (dev << 3) + fn; - uint_t major = dev_index / 8; - uint_t minor = dev_index % 8; - - if (bus > 3) { - PrintError("Invalid PCI bus %d\n", bus); - return -1; - } - - PrintDebug("Setting passthrough pci map for index=%d\n", dev_index); - - global_state->sym_page->pci_pt_map[major] |= 0x1 << minor; - - PrintDebug("pt_map entry=%x\n", global_state->sym_page->pci_pt_map[major]); - - PrintDebug("pt map vmm addr=%p\n", global_state->sym_page->pci_pt_map); - - return 0; -} - -int v3_sym_unmap_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn) { - struct v3_sym_global_state * global_state = &(vm->sym_global_state); - uint_t dev_index = (bus << 8) + (dev << 3) + fn; - uint_t major = dev_index / 8; - uint_t minor = dev_index % 8; - - if (bus > 3) { - PrintError("Invalid PCI bus %d\n", bus); - return -1; - } - - global_state->sym_page->pci_pt_map[major] &= ~(0x1 << minor); - - return 0; -} - - -static int sym_call_err(struct guest_info * core, uint_t hcall_id, void * private_data) { - struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_local_state.symcall_state); - - PrintError("sym call error\n"); - - state->sym_call_errno = (int)core->vm_regs.rbx; - v3_print_guest_state(core); - v3_print_mem_map(core->vm_info); - - // clear sym flags - state->sym_call_error = 1; - state->sym_call_returned = 1; - - return -1; -} - -static int sym_call_ret(struct guest_info * core, uint_t hcall_id, void * private_data) { - struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_local_state.symcall_state); - - // PrintError("Return from sym call (ID=%x)\n", hcall_id); - // v3_print_guest_state(info); - - state->sym_call_returned = 1; - - return 0; -} - -static int execute_symcall(struct guest_info * core) { - struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_local_state.symcall_state); - - while (state->sym_call_returned == 0) { - if (v3_vm_enter(core) == -1) { - PrintError("Error in Sym call\n"); - return -1; - } - } - - return 0; -} - - -int v3_sym_call(struct guest_info * core, - uint64_t call_num, sym_arg_t * arg0, - sym_arg_t * arg1, sym_arg_t * arg2, - sym_arg_t * arg3, sym_arg_t * arg4) { - struct v3_sym_local_state * sym_state = (struct v3_sym_local_state *)&(core->sym_local_state); - struct v3_symcall_state * state = (struct v3_symcall_state *)&(sym_state->symcall_state); - struct v3_sym_cpu_context * old_ctx = (struct v3_sym_cpu_context *)&(state->old_ctx); - struct v3_segment sym_cs; - struct v3_segment sym_ss; - uint64_t trash_args[5] = { [0 ... 4] = 0 }; - - // PrintDebug("Making Sym call\n"); - // v3_print_guest_state(info); - - if ((sym_state->local_page->sym_call_enabled == 0) || - (state->sym_call_active == 1)) { - return -1; - } - - if (!arg0) arg0 = &trash_args[0]; - if (!arg1) arg1 = &trash_args[1]; - if (!arg2) arg2 = &trash_args[2]; - if (!arg3) arg3 = &trash_args[3]; - if (!arg4) arg4 = &trash_args[4]; - - // Save the old context - memcpy(&(old_ctx->vm_regs), &(core->vm_regs), sizeof(struct v3_gprs)); - memcpy(&(old_ctx->cs), &(core->segments.cs), sizeof(struct v3_segment)); - memcpy(&(old_ctx->ss), &(core->segments.ss), sizeof(struct v3_segment)); - old_ctx->gs_base = core->segments.gs.base; - old_ctx->fs_base = core->segments.fs.base; - old_ctx->rip = core->rip; - old_ctx->cpl = core->cpl; - old_ctx->flags = core->ctrl_regs.rflags; - - // Setup the sym call context - core->rip = state->sym_call_rip; - core->vm_regs.rsp = state->sym_call_rsp; // old contest rsp is saved in vm_regs - - v3_translate_segment(core, state->sym_call_cs, &sym_cs); - memcpy(&(core->segments.cs), &sym_cs, sizeof(struct v3_segment)); - - v3_translate_segment(core, state->sym_call_cs + 8, &sym_ss); - memcpy(&(core->segments.ss), &sym_ss, sizeof(struct v3_segment)); - - core->segments.gs.base = state->sym_call_gs; - core->segments.fs.base = state->sym_call_fs; - core->cpl = 0; - - core->vm_regs.rax = call_num; - core->vm_regs.rbx = *arg0; - core->vm_regs.rcx = *arg1; - core->vm_regs.rdx = *arg2; - core->vm_regs.rsi = *arg3; - core->vm_regs.rdi = *arg4; - - // Mark sym call as active - state->sym_call_active = 1; - state->sym_call_returned = 0; - - // PrintDebug("Sym state\n"); - // v3_print_guest_state(core); - - // Do the sym call entry - if (execute_symcall(core) == -1) { - PrintError("SYMCALL error\n"); - return -1; - } - - // clear sym flags - state->sym_call_active = 0; - - *arg0 = core->vm_regs.rbx; - *arg1 = core->vm_regs.rcx; - *arg2 = core->vm_regs.rdx; - *arg3 = core->vm_regs.rsi; - *arg4 = core->vm_regs.rdi; - - // restore guest state - memcpy(&(core->vm_regs), &(old_ctx->vm_regs), sizeof(struct v3_gprs)); - memcpy(&(core->segments.cs), &(old_ctx->cs), sizeof(struct v3_segment)); - memcpy(&(core->segments.ss), &(old_ctx->ss), sizeof(struct v3_segment)); - core->segments.gs.base = old_ctx->gs_base; - core->segments.fs.base = old_ctx->fs_base; - core->rip = old_ctx->rip; - core->cpl = old_ctx->cpl; - core->ctrl_regs.rflags = old_ctx->flags; - - - - // PrintError("restoring guest state\n"); - // v3_print_guest_state(core); - - return 0; -} - - diff --git a/palacios/src/palacios/vmm_symbiotic.c b/palacios/src/palacios/vmm_symbiotic.c new file mode 100644 index 0000000..c8943f0 --- /dev/null +++ b/palacios/src/palacios/vmm_symbiotic.c @@ -0,0 +1,87 @@ +/* + * 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 + + +#define SYM_CPUID_NUM 0x90000000 + +static int cpuid_fn(struct guest_info * core, uint32_t cpuid, + uint32_t * eax, uint32_t * ebx, + uint32_t * ecx, uint32_t * edx, + void * private_data) { + extern v3_cpu_arch_t v3_cpu_types[]; + + *eax = *(uint32_t *)"V3V"; + + if ((v3_cpu_types[core->cpu_id] == V3_SVM_CPU) || + (v3_cpu_types[core->cpu_id] == V3_SVM_REV3_CPU)) { + *ebx = *(uint32_t *)"SVM"; + } else if ((v3_cpu_types[core->cpu_id] == V3_VMX_CPU) || + (v3_cpu_types[core->cpu_id] == V3_VMX_EPT_CPU)) { + *ebx = *(uint32_t *)"VMX"; + } + + + return 0; +} + + +int v3_init_symbiotic_vm(struct v3_vm_info * vm) { + struct v3_sym_vm_state * vm_state = &(vm->sym_vm_state); + memset(vm_state, 0, sizeof(struct v3_sym_vm_state)); + + v3_hook_cpuid(vm, SYM_CPUID_NUM, cpuid_fn, NULL); + + if (v3_init_symspy_vm(vm, &(vm_state->symspy_state)) == -1) { + PrintError("Error initializing global SymSpy state\n"); + return -1; + } + +#ifdef CONFIG_SYMCALL + if (v3_init_symcall_vm(vm) == -1) { + PrintError("Error intializing global SymCall state\n"); + return -1; + } +#endif + +#ifdef CONFIG_SYMMOD + +#endif + + + return 0; +} + + + +int v3_init_symbiotic_core(struct guest_info * core) { + struct v3_sym_core_state * core_state = &(core->sym_core_state); + memset(core_state, 0, sizeof(struct v3_sym_core_state)); + + + if (v3_init_symspy_core(core, &(core_state->symspy_state)) == -1) { + PrintError("Error intializing local SymSpy state\n"); + return -1; + } + + return 0; +} diff --git a/palacios/src/palacios/vmm_symcall.c b/palacios/src/palacios/vmm_symcall.c new file mode 100644 index 0000000..c78fe88 --- /dev/null +++ b/palacios/src/palacios/vmm_symcall.c @@ -0,0 +1,260 @@ +/* + * 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 +#include + +// A succesfull symcall returns via the RET_HCALL, with the return values in registers +// A symcall error returns via the ERR_HCALL with the error code in rbx + + +/* Notes: We use a combination of SYSCALL and SYSENTER Semantics + * SYSCALL just sets an EIP, CS/SS seg, and GS seg via swapgs + * the RSP is loaded via the structure pointed to by GS + * This is safe because it assumes that system calls are guaranteed to be made with an empty kernel stack. + * We cannot make that assumption with a symcall, so we have to have our own stack area somewhere. + * SYSTENTER does not really use the GS base MSRs, but we do to map to 64 bit kernels + */ + +#define SYMCALL_RIP_MSR 0x536 +#define SYMCALL_RSP_MSR 0x537 +#define SYMCALL_CS_MSR 0x538 +#define SYMCALL_GS_MSR 0x539 +#define SYMCALL_FS_MSR 0x540 + + +static int symcall_msr_read(struct guest_info * core, uint_t msr, + struct v3_msr * dst, void * priv_data) { + struct v3_symcall_state * state = &(core->sym_core_state.symcall_state); + + switch (msr) { + case SYMCALL_RIP_MSR: + dst->value = state->sym_call_rip; + break; + case SYMCALL_RSP_MSR: + dst->value = state->sym_call_rsp; + break; + case SYMCALL_CS_MSR: + dst->value = state->sym_call_cs; + break; + case SYMCALL_GS_MSR: + dst->value = state->sym_call_gs; + break; + case SYMCALL_FS_MSR: + dst->value = state->sym_call_fs; + break; + default: + return -1; + } + + return 0; +} + +static int symcall_msr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { + struct v3_symcall_state * state = &(core->sym_core_state.symcall_state); + + switch (msr) { + case SYMCALL_RIP_MSR: + state->sym_call_rip = src.value; + break; + case SYMCALL_RSP_MSR: + state->sym_call_rsp = src.value; + break; + case SYMCALL_CS_MSR: + state->sym_call_cs = src.value; + break; + case SYMCALL_GS_MSR: + state->sym_call_gs = src.value; + break; + case SYMCALL_FS_MSR: + state->sym_call_fs = src.value; + break; + default: + PrintError("Invalid Symbiotic MSR write (0x%x)\n", msr); + return -1; + } + return 0; +} + + +static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * private_data); +static int sym_call_err(struct guest_info * info, uint_t hcall_id, void * private_data); + + + + +int v3_init_symcall_vm(struct v3_vm_info * vm) { + + v3_hook_msr(vm, SYMCALL_RIP_MSR, symcall_msr_read, symcall_msr_write, NULL); + v3_hook_msr(vm, SYMCALL_RSP_MSR, symcall_msr_read, symcall_msr_write, NULL); + v3_hook_msr(vm, SYMCALL_CS_MSR, symcall_msr_read, symcall_msr_write, NULL); + v3_hook_msr(vm, SYMCALL_GS_MSR, symcall_msr_read, symcall_msr_write, NULL); + v3_hook_msr(vm, SYMCALL_FS_MSR, symcall_msr_read, symcall_msr_write, NULL); + + v3_register_hypercall(vm, SYMCALL_RET_HCALL, sym_call_ret, NULL); + v3_register_hypercall(vm, SYMCALL_ERR_HCALL, sym_call_err, NULL); + + + return 0; +} + + + + + +static int sym_call_err(struct guest_info * core, uint_t hcall_id, void * private_data) { + struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state); + + PrintError("sym call error\n"); + + state->sym_call_errno = (int)core->vm_regs.rbx; + v3_print_guest_state(core); + v3_print_mem_map(core->vm_info); + + // clear sym flags + state->sym_call_error = 1; + state->sym_call_returned = 1; + + return -1; +} + +static int sym_call_ret(struct guest_info * core, uint_t hcall_id, void * private_data) { + struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state); + + // PrintError("Return from sym call (ID=%x)\n", hcall_id); + // v3_print_guest_state(info); + + state->sym_call_returned = 1; + + return 0; +} + +static int execute_symcall(struct guest_info * core) { + struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state); + + while (state->sym_call_returned == 0) { + if (v3_vm_enter(core) == -1) { + PrintError("Error in Sym call\n"); + return -1; + } + } + + return 0; +} + + +int v3_sym_call(struct guest_info * core, + uint64_t call_num, sym_arg_t * arg0, + sym_arg_t * arg1, sym_arg_t * arg2, + sym_arg_t * arg3, sym_arg_t * arg4) { + struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state); + struct v3_symspy_local_state * symspy_state = (struct v3_symspy_local_state *)&(core->sym_core_state.symspy_state); + struct v3_sym_cpu_context * old_ctx = (struct v3_sym_cpu_context *)&(state->old_ctx); + struct v3_segment sym_cs; + struct v3_segment sym_ss; + uint64_t trash_args[5] = { [0 ... 4] = 0 }; + + // PrintDebug("Making Sym call\n"); + // v3_print_guest_state(info); + + if ((symspy_state->local_page->sym_call_enabled == 0) || + (symspy_state->local_page->sym_call_active == 1)) { + return -1; + } + + if (!arg0) arg0 = &trash_args[0]; + if (!arg1) arg1 = &trash_args[1]; + if (!arg2) arg2 = &trash_args[2]; + if (!arg3) arg3 = &trash_args[3]; + if (!arg4) arg4 = &trash_args[4]; + + // Save the old context + memcpy(&(old_ctx->vm_regs), &(core->vm_regs), sizeof(struct v3_gprs)); + memcpy(&(old_ctx->cs), &(core->segments.cs), sizeof(struct v3_segment)); + memcpy(&(old_ctx->ss), &(core->segments.ss), sizeof(struct v3_segment)); + old_ctx->gs_base = core->segments.gs.base; + old_ctx->fs_base = core->segments.fs.base; + old_ctx->rip = core->rip; + old_ctx->cpl = core->cpl; + old_ctx->flags = core->ctrl_regs.rflags; + + // Setup the sym call context + core->rip = state->sym_call_rip; + core->vm_regs.rsp = state->sym_call_rsp; // old contest rsp is saved in vm_regs + + v3_translate_segment(core, state->sym_call_cs, &sym_cs); + memcpy(&(core->segments.cs), &sym_cs, sizeof(struct v3_segment)); + + v3_translate_segment(core, state->sym_call_cs + 8, &sym_ss); + memcpy(&(core->segments.ss), &sym_ss, sizeof(struct v3_segment)); + + core->segments.gs.base = state->sym_call_gs; + core->segments.fs.base = state->sym_call_fs; + core->cpl = 0; + + core->vm_regs.rax = call_num; + core->vm_regs.rbx = *arg0; + core->vm_regs.rcx = *arg1; + core->vm_regs.rdx = *arg2; + core->vm_regs.rsi = *arg3; + core->vm_regs.rdi = *arg4; + + // Mark sym call as active + state->sym_call_active = 1; + state->sym_call_returned = 0; + + // PrintDebug("Sym state\n"); + // v3_print_guest_state(core); + + // Do the sym call entry + if (execute_symcall(core) == -1) { + PrintError("SYMCALL error\n"); + return -1; + } + + // clear sym flags + state->sym_call_active = 0; + + *arg0 = core->vm_regs.rbx; + *arg1 = core->vm_regs.rcx; + *arg2 = core->vm_regs.rdx; + *arg3 = core->vm_regs.rsi; + *arg4 = core->vm_regs.rdi; + + // restore guest state + memcpy(&(core->vm_regs), &(old_ctx->vm_regs), sizeof(struct v3_gprs)); + memcpy(&(core->segments.cs), &(old_ctx->cs), sizeof(struct v3_segment)); + memcpy(&(core->segments.ss), &(old_ctx->ss), sizeof(struct v3_segment)); + core->segments.gs.base = old_ctx->gs_base; + core->segments.fs.base = old_ctx->fs_base; + core->rip = old_ctx->rip; + core->cpl = old_ctx->cpl; + core->ctrl_regs.rflags = old_ctx->flags; + + + + // PrintError("restoring guest state\n"); + // v3_print_guest_state(core); + + return 0; +} + + diff --git a/palacios/src/palacios/vmm_symspy.c b/palacios/src/palacios/vmm_symspy.c new file mode 100644 index 0000000..53f3e89 --- /dev/null +++ b/palacios/src/palacios/vmm_symspy.c @@ -0,0 +1,182 @@ +/* + * 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 +#include +#include + +#define SYMSPY_GLOBAL_MSR 0x534 +#define SYMSPY_LOCAL_MSR 0x535 + + +static int symspy_msr_read(struct guest_info * core, uint_t msr, + struct v3_msr * dst, void * priv_data) { + struct v3_symspy_global_state * global_state = &(core->vm_info->sym_vm_state.symspy_state); + struct v3_symspy_local_state * local_state = &(core->sym_core_state.symspy_state); + + switch (msr) { + case SYMSPY_GLOBAL_MSR: + dst->value = global_state->global_guest_pa; + break; + case SYMSPY_LOCAL_MSR: + dst->value = local_state->local_guest_pa; + break; + default: + return -1; + } + + return 0; +} + + +static int symspy_msr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { + + if (msr == SYMSPY_GLOBAL_MSR) { + struct v3_symspy_global_state * global_state = &(core->vm_info->sym_vm_state.symspy_state); + + PrintDebug("Symbiotic Glbal MSR write for page %p\n", (void *)(addr_t)src.value); + + if (global_state->active == 1) { + // unmap page + struct v3_shadow_region * old_reg = v3_get_shadow_region(core->vm_info, core->cpu_id, + (addr_t)global_state->global_guest_pa); + + if (old_reg == NULL) { + PrintError("Could not find previously active symbiotic page (%p)\n", + (void *)(addr_t)global_state->global_guest_pa); + return -1; + } + + v3_delete_shadow_region(core->vm_info, old_reg); + } + + global_state->global_guest_pa = src.value; + global_state->global_guest_pa &= ~0xfffLL; + + global_state->active = 1; + + // map page + v3_add_shadow_mem(core->vm_info, V3_MEM_CORE_ANY, (addr_t)global_state->global_guest_pa, + (addr_t)(global_state->global_guest_pa + PAGE_SIZE_4KB - 1), + global_state->global_page_pa); + } else if (msr == SYMSPY_LOCAL_MSR) { + struct v3_symspy_local_state * local_state = &(core->sym_core_state.symspy_state); + + PrintDebug("Symbiotic Local MSR write for page %p\n", (void *)(addr_t)src.value); + + if (local_state->active == 1) { + // unmap page + struct v3_shadow_region * old_reg = v3_get_shadow_region(core->vm_info, core->cpu_id, + (addr_t)local_state->local_guest_pa); + + if (old_reg == NULL) { + PrintError("Could not find previously active symbiotic page (%p)\n", + (void *)(addr_t)local_state->local_guest_pa); + return -1; + } + + v3_delete_shadow_region(core->vm_info, old_reg); + } + + local_state->local_guest_pa = src.value; + local_state->local_guest_pa &= ~0xfffLL; + + local_state->active = 1; + + // map page + v3_add_shadow_mem(core->vm_info, core->cpu_id, (addr_t)local_state->local_guest_pa, + (addr_t)(local_state->local_guest_pa + PAGE_SIZE_4KB - 1), + local_state->local_page_pa); + } else { + PrintError("Invalid Symbiotic MSR write (0x%x)\n", msr); + return -1; + } + + return 0; +} + + + +int v3_init_symspy_vm(struct v3_vm_info * vm, struct v3_symspy_global_state * state) { + + state->global_page_pa = (addr_t)V3_AllocPages(1); + state->sym_page = (struct v3_symspy_global_page *)V3_VAddr((void *)state->global_page_pa); + memset(state->sym_page, 0, PAGE_SIZE_4KB); + + memcpy(&(state->sym_page->magic), "V3V", 3); + + v3_hook_msr(vm, SYMSPY_LOCAL_MSR, symspy_msr_read, symspy_msr_write, NULL); + v3_hook_msr(vm, SYMSPY_GLOBAL_MSR, symspy_msr_read, symspy_msr_write, NULL); + + return 0; +} + + + +int v3_init_symspy_core(struct guest_info * core, struct v3_symspy_local_state * state) { + state->local_page_pa = (addr_t)V3_AllocPages(1); + state->local_page = (struct v3_symspy_local_page *)V3_VAddr((void *)state->local_page_pa); + memset(state->local_page, 0, PAGE_SIZE_4KB); + + snprintf((uint8_t *)&(state->local_page->magic), 8, "V3V.%d", core->cpu_id); + + return 0; +} + + + +int v3_sym_map_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn) { + struct v3_symspy_global_state * global_state = &(vm->sym_vm_state.symspy_state); + uint_t dev_index = (bus << 8) + (dev << 3) + fn; + uint_t major = dev_index / 8; + uint_t minor = dev_index % 8; + + if (bus > 3) { + PrintError("Invalid PCI bus %d\n", bus); + return -1; + } + + PrintDebug("Setting passthrough pci map for index=%d\n", dev_index); + + global_state->sym_page->pci_pt_map[major] |= 0x1 << minor; + + PrintDebug("pt_map entry=%x\n", global_state->sym_page->pci_pt_map[major]); + + PrintDebug("pt map vmm addr=%p\n", global_state->sym_page->pci_pt_map); + + return 0; +} + +int v3_sym_unmap_pci_passthrough(struct v3_vm_info * vm, uint_t bus, uint_t dev, uint_t fn) { + struct v3_symspy_global_state * global_state = &(vm->sym_vm_state.symspy_state); + uint_t dev_index = (bus << 8) + (dev << 3) + fn; + uint_t major = dev_index / 8; + uint_t minor = dev_index % 8; + + if (bus > 3) { + PrintError("Invalid PCI bus %d\n", bus); + return -1; + } + + global_state->sym_page->pci_pt_map[major] &= ~(0x1 << minor); + + return 0; +} diff --git a/palacios/src/palacios/vmm_telemetry.c b/palacios/src/palacios/vmm_telemetry.c index 8d94db0..16088a2 100644 --- a/palacios/src/palacios/vmm_telemetry.c +++ b/palacios/src/palacios/vmm_telemetry.c @@ -27,7 +27,7 @@ #ifdef CONFIG_TELEMETRY_GRANULARITY #define DEFAULT_GRANULARITY CONFIG_TELEMETRY_GRANULARITY #else -#define DEFAULT_GRANULARITY 500 +#define DEFAULT_GRANULARITY 50000 #endif diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index 4722fb5..4c37ddf 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -644,8 +644,8 @@ int v3_vmx_enter(struct guest_info * info) { v3_vmx_restore_vmcs(info); -#ifdef CONFIG_SYMBIOTIC - if (info->sym_local_state.symcall_state.sym_call_active == 0) { +#ifdef CONFIG_SYMCALL + if (info->sym_core_state.symcall_state.sym_call_active == 0) { update_irq_entry_state(info); } #else @@ -706,8 +706,8 @@ int v3_vmx_enter(struct guest_info * info) { exit_log[info->num_exits % 10] = exit_info; -#ifdef CONFIG_SYMBIOTIC - if (info->sym_local_state.symcall_state.sym_call_active == 0) { +#ifdef CONFIG_SYMCALL + if (info->sym_core_state.symcall_state.sym_call_active == 0) { update_irq_exit_state(info); } #else