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"
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
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
#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
-
-
-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 <palacios/vmm_sym_iface.h>
+#include <palacios/vmm_symbiotic.h>
+struct v3_sym_core_state;
#endif
#include <palacios/vmm_config.h>
-struct shadow_page_state;
+
struct v3_intr_state;
struct v3_sym_swap_state;
#endif
-#ifdef CONFIG_SYMBIOTIC
-struct v3_sym_state;
-#endif
+
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
#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
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_REGS_H__
+#define __VMM_REGS_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm.h>
+
+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
+++ /dev/null
-/*
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National
- * Science Foundation and the Department of Energy.
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico. You can find out more at
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software. You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-
-#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 <palacios/vm_guest.h>
-
-
-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
#define __VMM_SYM_SWAP_H__
#ifdef __V3VEE__
-#ifdef CONFIG_SYMBIOTIC_SWAP
#include <palacios/vmm_types.h>
#include <palacios/vmm_paging.h>
int v3_swap_flush(struct v3_vm_info * vm);
-#endif
+
#endif
#endif
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __VMM_SYMBIOTIC_H__
+#define __VMM_SYMBIOTIC_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm.h>
+
+#include <palacios/vmm_symspy.h>
+
+#ifdef CONFIG_SYMCALL
+#include <palacios/vmm_symcall.h>
+#endif
+
+#ifdef CONFIG_SYMMOD
+#include <palacios/vmm_symmod.h>
+#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
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_SYMCALL_H__
+#define __VMM_SYMCALL_H__
+
+#ifdef __V3VEE__
+
+
+#include <palacios/vmm_regs.h>
+
+
+
+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
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_SYMSPY_H__
+#define __VMM_SYMSPY_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm.h>
+
+
+
+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
obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o
obj-$(CONFIG_PASSTHROUGH_PCI) += pci_passthrough.o
+
+obj-$(CONFIG_SYMBIOTIC_MODULES) += lnx_virtio_symmod.o
#include <palacios/vmm_sprintf.h>
#include <palacios/vmm_lowlevel.h>
#include <palacios/vm_guest.h> // must include this to avoid dependency issue
-#include <palacios/vmm_sym_iface.h>
+#include <palacios/vmm_symspy.h>
#include <devices/pci.h>
#include <devices/pci_types.h>
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
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
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
(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");
}
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
#ifdef CONFIG_SYMBIOTIC
- v3_init_sym_iface(vm);
+ v3_init_symbiotic_vm(vm);
#endif
v3_init_dev_mgr(vm);
#ifdef CONFIG_SYMBIOTIC
- v3_init_sym_core(core);
+ v3_init_symbiotic_core(core);
#endif
// init SVM/VMX
#include <palacios/vmm_msr.h>
-#ifdef CONFIG_SYMBIOTIC
-#include <palacios/vmm_sym_iface.h>
-#ifdef CONFIG_SYMBIOTIC_SWAP
-#include <palacios/vmm_sym_swap.h>
-#endif
-
-#endif
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;
}
#include <palacios/vm_guest.h>
#include <palacios/vm_guest_mem.h>
+
+#ifndef CONFIG_DEBUG_SHDW_PG_VTLB
+#undef PrintDebug
+#define PrintDebug(fmt, ...)
+#endif
+
+
struct shadow_page_data {
v3_reg_t cr3;
addr_t page_pa;
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;
}
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;
+++ /dev/null
-/*
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National
- * Science Foundation and the Department of Energy.
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico. You can find out more at
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software. You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-
-#include <palacios/vmm.h>
-#include <palacios/vmm_msr.h>
-#include <palacios/vmm_mem.h>
-#include <palacios/vmm_hypercall.h>
-#include <palacios/vm_guest.h>
-#include <palacios/vmm_sprintf.h>
-
-
-#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;
-}
-
-
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#include <palacios/vmm_symbiotic.h>
+#include <palacios/vm_guest.h>
+
+
+#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;
+}
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vm_guest.h>
+#include <palacios/vmm_symcall.h>
+#include <palacios/vmm_symspy.h>
+#include <palacios/vmm_msr.h>
+
+// 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;
+}
+
+
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm_symspy.h>
+#include <palacios/vmm.h>
+#include <palacios/vmm_msr.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vmm_sprintf.h>
+
+#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;
+}
#ifdef CONFIG_TELEMETRY_GRANULARITY
#define DEFAULT_GRANULARITY CONFIG_TELEMETRY_GRANULARITY
#else
-#define DEFAULT_GRANULARITY 500
+#define DEFAULT_GRANULARITY 50000
#endif
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
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