#include <palacios/vmm_msr.h>
#include <palacios/vmm_hypercall.h>
#include <palacios/vmm_cpuid.h>
-#include <palacios/vmm_sym_iface.h>
+
#ifdef CONFIG_TELEMETRY
#include <palacios/vmm_telemetry.h>
#endif
+
+
+
struct v3_gprs {
v3_reg_t rdi;
v3_reg_t rsi;
struct v3_segment tr;
};
+
+#ifdef CONFIG_SYMBIOTIC
+#include <palacios/vmm_sym_iface.h>
+#endif
+
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 {
uint64_t rip;
struct v3_cpuid_map cpuid_map;
+#ifdef CONFIG_SYMBIOTIC
// Symbiotic state
struct v3_sym_state sym_state;
-
+#endif
v3_hypercall_map_t hcall_map;
const uchar_t * v3_cpu_mode_to_str(v3_cpu_mode_t mode);
const uchar_t * v3_mem_mode_to_str(v3_mem_mode_t mode);
+int v3_translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg);
+
void v3_print_guest_state(struct guest_info * info);
#define CPUID_FEATURE_IDS 0x00000001
#define CPUID_EXT_FEATURE_IDS 0x80000001
+struct seg_selector {
+ union {
+ uint16_t value;
+ struct {
+ uint8_t rpl : 2;
+ uint8_t ti : 1;
+ uint16_t si : 13;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+struct gen_segment {
+ uint16_t limit_lo;
+ uint32_t base_lo : 24;
+ uint8_t type : 4;
+ uint8_t system : 1;
+ uint8_t dpl : 2;
+ uint8_t present : 1;
+ uint8_t limit_hi : 4;
+ uint8_t avail : 1;
+ uint8_t long_mode : 1;
+ uint8_t db : 1;
+ uint8_t granularity : 1;
+ uint8_t base_hi : 8;
+} __attribute__((packed));
+
+struct sys_segment64 {
+ uint16_t limit_lo;
+ uint32_t base_lo : 24;
+ uint8_t type : 4;
+ uint8_t rsvd0 : 1;
+ uint8_t dpl : 2;
+ uint8_t present : 1;
+ uint8_t limit_hi : 4;
+ uint8_t avail : 1;
+ uint8_t rsvd1 : 3;
+ uint8_t granularity : 1;
+ uint64_t base_hi : 40;
+ uint32_t rsvd2;
+} __attribute__((packed));
+
static void __inline__ v3_cpuid(uint32_t target,
#ifdef __V3VEE__
-
+#include <palacios/vm_guest.h>
union {
uint32_t feature_flags;
struct {
- uint_t cur_proc_valid : 1;
- uint_t proc_list_valid : 1;
+ uint_t pci_map_valid : 1;
+ uint32_t sym_call_enabled : 1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+
+ union {
+ uint32_t state_flags;
+ struct {
+ uint32_t sym_call_active : 1;
} __attribute__((packed));
} __attribute__((packed));
- addr_t current_proc;
- addr_t proc_list;
+ uint64_t current_proc;
+ uint64_t proc_list;
+
+ uint8_t pci_pt_map[(4 * 256) / 8]; // we're hardcoding this: (4 busses, 256 max devs)
+
+
+ uint64_t sym_call_rip;
+ uint64_t sym_call_cs;
+ uint64_t sym_call_rsp;
+ uint64_t sym_call_gs;
+ uint64_t sym_call_ret_fn;
- uint8_t pci_pt_map[256 / 8];
} __attribute__((packed));
+
+
+struct v3_sym_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;
+ uint8_t cpl;
+};
+
+
+
struct v3_sym_state {
struct v3_sym_interface * sym_page;
addr_t sym_page_pa;
- uint_t active;
uint64_t guest_pg_addr;
+ struct {
+ uint_t active : 1;
+ uint_t call_pending : 1;
+ uint_t call_active : 1;
+ } __attribute__((packed));
+
+ struct v3_sym_context old_ctx;
+ uint64_t args[6];
+ int (*notifier)(struct guest_info * info, void * private_data);
+
+ void * private_data;
+
};
int v3_init_sym_iface(struct guest_info * info);
+
+#define v3_sym_call0(info, call_num, cb, priv) \
+ v3_sym_call(info, call_num, 0, 0, 0, 0, 0, cb, priv)
+#define v3_sym_call1(info, call_num, arg1, cb, priv) \
+ v3_sym_call(info, call_num, arg1, 0, 0, 0, 0, cb, priv)
+#define v3_sym_call2(info, call_num, arg1, arg2, cb, priv) \
+ v3_sym_call(info, call_num, arg1, arg2, 0, 0, 0, cb, priv)
+#define v3_sym_call3(info, call_num, arg1, arg2, arg3, cb, priv) \
+ v3_sym_call(info, call_num, arg1, arg2, arg3, 0, 0, cb, priv)
+#define v3_sym_call4(info, call_num, arg1, arg2, arg3, arg4, cb, priv) \
+ v3_sym_call(info, call_num, arg1, arg2, arg3, arg4, 0, cb, priv)
+#define v3_sym_call5(info, call_num, arg1, arg2, arg3, arg4, arg5, cb, priv) \
+ v3_sym_call(info, call_num, arg1, arg2, arg3, arg4, arg5, cb, priv)
+
+
+
+
int v3_sym_map_pci_passthrough(struct guest_info * info, uint_t bus, uint_t dev, uint_t fn);
int v3_sym_unmap_pci_passthrough(struct guest_info * info, uint_t bus, uint_t dev, uint_t fn);
+int v3_sym_call(struct guest_info * info,
+ uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3,
+ uint64_t arg4, uint64_t arg5,
+ int (*notifier)(struct guest_info * info, void * private_data),
+ void * private_data);
+
+int v3_activate_sym_call(struct guest_info * info);
#endif
if (evt->scan_code == 0x44) { // F10 debug dump
v3_print_guest_state(info);
// PrintGuestPageTables(info, info->shdw_pg_state.guest_cr3);
+ } else if (evt->scan_code == 0x43) { // F9 Sym test
+ PrintDebug("Testing sym call\n");
+ v3_sym_call0(info, 0, NULL, NULL);
}
addr_t irq_state = v3_lock_irqsave(state->kb_lock);
int intr_pin = pci_dev->config_header.intr_pin - 1;
int irq_index = (intr_pin + pci_dev->dev_num - 1) & 0x3;
- PrintError("Raising PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
+ // PrintError("Raising PCI IRQ %d\n", piix3_cfg->pirq_rc[irq_index]);
v3_raise_irq(dev->vm, piix3_cfg->pirq_rc[irq_index]);
#include <palacios/vmm_cpuid.h>
#include <palacios/vmm_direct_paging.h>
+#ifdef CONFIG_SYMBIOTIC
+#include <palacios/vmm_sym_iface.h>
+#endif
+
#ifdef CONFIG_TELEMETRY
#include <palacios/vmm_telemetry.h>
#endif
vmcb_ctrl_t * guest_ctrl = 0;
vmcb_saved_state_t * guest_state = 0;
ulong_t exit_code = 0;
-
+
+#ifdef CONFIG_SYMBIOTIC
+ static int sym_started = 0;
+#endif
+
+
guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
exit_code = guest_ctrl->exit_code;
- // PrintDebug("SVM Exit: %s (rip=%p) (info1=%p)\n", vmexit_code_to_str(exit_code),
- // (void *)(addr_t)info->rip, (void *)(addr_t)guest_ctrl->exit_info1);
+
+
+#ifdef CONFIG_SYMBIOTIC
+ if (0) {
+ // ignore interrupt injection if we just started a symcall
+ PrintDebug("SVM Exit: %s (rip=%p) (info1=%p) (info2=%p)\n", vmexit_code_to_str(exit_code),
+ (void *)(addr_t)info->rip, (void *)(addr_t)guest_ctrl->exit_info1,
+ (void *)(addr_t)guest_ctrl->exit_info2);
+ if (exit_code == VMEXIT_EXCP14) {
+ PrintGuestPageTree(info, guest_ctrl->exit_info2, info->shdw_pg_state.guest_cr3);
+ }
+
+ }
+#endif
+
if ((info->intr_state.irq_pending == 1) && (guest_ctrl->guest_ctrl.V_IRQ == 0)) {
if (v3_handle_cr3_write(info) == -1) {
return -1;
}
+
break;
case VMEXIT_CR3_READ:
#ifdef CONFIG_DEBUG_CTRL_REGS
/*
* Hypercall
*/
-
+
+ // VMMCALL is a 3 byte op
+ // We do this early because some hypercalls can change the rip...
+ info->rip += 3;
+
if (v3_handle_hypercall(info) == -1) {
return -1;
}
-
- // VMMCALL is a 3 byte op
- info->rip += 3;
+
break;
case VMEXIT_INTR:
// handled by interrupt dispatch earlier
}
break;
case VMEXIT_PAUSE:
- //PrintDebug("Guest paused\n");
+ PrintDebug("Guest paused\n");
if (v3_handle_svm_pause(info) == -1) {
return -1;
}
#endif
+
+#ifdef CONFIG_SYMBIOTIC
+ v3_activate_sym_call(info);
+#endif
+
+ guest_state->cr0 = info->ctrl_regs.cr0;
+ guest_state->cr2 = info->ctrl_regs.cr2;
+ guest_state->cr3 = info->ctrl_regs.cr3;
+ guest_state->cr4 = info->ctrl_regs.cr4;
+ guest_state->dr6 = info->dbg_regs.dr6;
+ guest_state->dr7 = info->dbg_regs.dr7;
+ guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
+ guest_state->rflags = info->ctrl_regs.rflags;
+ guest_state->efer = info->ctrl_regs.efer;
+
+ guest_state->cpl = info->cpl;
+
+ v3_set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
+
+ guest_state->rax = info->vm_regs.rax;
+ guest_state->rip = info->rip;
+ guest_state->rsp = info->vm_regs.rsp;
+
+
+
+
if (v3_excp_pending(info)) {
uint_t excp = v3_get_excp_number(info);
guest_ctrl->EVENTINJ.vector = excp;
guest_ctrl->EVENTINJ.valid = 1;
+
+ PrintDebug("Injecting Exception %d (EIP=%p)\n",
+ guest_ctrl->EVENTINJ.vector,
+ (void *)(addr_t)info->rip);
+
+
+
#ifdef CONFIG_DEBUG_INTERRUPTS
PrintDebug("Injecting Exception %d (EIP=%p)\n",
guest_ctrl->EVENTINJ.vector,
(void *)(addr_t)info->rip);
#endif
v3_injecting_excp(info, excp);
+
+#ifdef CONFIG_SYMBIOTIC
+ } else if (info->sym_state.call_active == 1) {
+ // ignore interrupt injection if we just started a symcall
+ PrintDebug("Symcall active\n");
+ sym_started = 1;
+#endif
+
} else if (info->intr_state.irq_started == 1) {
#ifdef CONFIG_DEBUG_INTERRUPTS
PrintDebug("IRQ pending from previous injection\n");
}
- guest_state->cr0 = info->ctrl_regs.cr0;
- guest_state->cr2 = info->ctrl_regs.cr2;
- guest_state->cr3 = info->ctrl_regs.cr3;
- guest_state->cr4 = info->ctrl_regs.cr4;
- guest_state->dr6 = info->dbg_regs.dr6;
- guest_state->dr7 = info->dbg_regs.dr7;
- guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
- guest_state->rflags = info->ctrl_regs.rflags;
- guest_state->efer = info->ctrl_regs.efer;
-
- guest_state->cpl = info->cpl;
-
- guest_state->rax = info->vm_regs.rax;
- guest_state->rip = info->rip;
- guest_state->rsp = info->vm_regs.rsp;
-
-
- v3_set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
if (exit_code == VMEXIT_INTR) {
//PrintDebug("INTR ret IP = %x\n", guest_state->rip);
#include <palacios/svm_msr.h>
#include <palacios/vmm_msr.h>
-
+#include <palacios/vmm_sprintf.h>
#include <palacios/vmm_list.h>
#define AMD_7_8_GEN_MSRS_START 0xc0010000
#define AMD_7_8_GEN_MSRS_END 0xc0011fff
-#define PENTIUM_MSRS_INDEX (0x0 * 4)
-#define AMD_6_GEN_MSRS_INDEX (0x800 * 4)
-#define AMD_7_8_GEN_MSRS_INDEX (0x1000 * 4)
+#define PENTIUM_MSRS_INDEX (0)
+#define AMD_6_GEN_MSRS_INDEX (0x2000)
+#define AMD_7_8_GEN_MSRS_INDEX (0x4000)
*(bitmap + major) &= ~(mask << minor);
*(bitmap + major) |= (val << minor);
-
+
return 0;
}
#include <palacios/vmm.h>
#include <palacios/vmm_decoder.h>
#include <palacios/vmcb.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_lowlevel.h>
+#include <palacios/vmm_sprintf.h>
+
v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
seg_ptr[i].long_mode, seg_ptr[i].db);
}
+}
+
+//
+// We don't handle those fancy 64 bit system segments...
+//
+int v3_translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg) {
+ struct v3_segment * gdt = &(info->segments.gdtr);
+ addr_t gdt_addr = 0;
+ uint16_t seg_offset = (selector & ~0x7);
+ addr_t seg_addr = 0;
+ struct gen_segment * gen_seg = NULL;
+ struct seg_selector sel;
+
+ memset(seg, 0, sizeof(struct v3_segment));
+
+ sel.value = selector;
+
+ if (sel.ti == 1) {
+ PrintError("LDT translations not supported\n");
+ return -1;
+ }
+ if (guest_va_to_host_va(info, gdt->base, &gdt_addr) == -1) {
+ PrintError("Unable to translate GDT address\n");
+ return -1;
+ }
+
+ seg_addr = gdt_addr + seg_offset;
+ gen_seg = (struct gen_segment *)seg_addr;
+
+ //translate
+ seg->selector = selector;
+
+ seg->limit = gen_seg->limit_hi;
+ seg->limit <<= 16;
+ seg->limit += gen_seg->limit_lo;
+
+ seg->base = gen_seg->base_hi;
+ seg->base <<= 24;
+ seg->base += gen_seg->base_lo;
+
+ if (gen_seg->granularity == 1) {
+ seg->limit <<= 12;
+ seg->limit |= 0xfff;
+ }
+
+ seg->type = gen_seg->type;
+ seg->system = gen_seg->system;
+ seg->dpl = gen_seg->dpl;
+ seg->present = gen_seg->present;
+ seg->avail = gen_seg->avail;
+ seg->long_mode = gen_seg->long_mode;
+ seg->db = gen_seg->db;
+ seg->granularity = gen_seg->granularity;
+
+ return 0;
}
+
+
void v3_print_ctrl_regs(struct guest_info * info) {
struct v3_ctrl_regs * regs = &(info->ctrl_regs);
int i = 0;
if (config_ptr->enable_pci == 1) {
struct ide_cfg ide_config = {"PCI", "PIIX3"};
- struct pci_passthrough_cfg pci_pt_cfg = {"PCI", "E1000", 0x8086, 0x100e};
+ struct pci_passthrough_cfg pci_qemu_pt_cfg = {"PCI", "E1000", 0x8086, 0x100e};
+ struct pci_passthrough_cfg pci_hw_pt_cfg = {"PCI", "E1000", 0x8086, 0x107c};
v3_create_device(info, "PCI", NULL);
v3_create_device(info, "i440FX", "PCI");
v3_create_device(info, "IDE", &ide_config);
- v3_create_device(info, "PCI_PASSTHROUGH", &pci_pt_cfg);
+ v3_create_device(info, "PCI_PASSTHROUGH", &pci_qemu_pt_cfg);
+ v3_create_device(info, "PCI_PASSTHROUGH", &pci_hw_pt_cfg);
+
} else {
v3_create_device(info, "IDE", NULL);
uint32_t cpuid = info->vm_regs.rax;
struct v3_cpuid_hook * hook = get_cpuid_hook(info, cpuid);
+ //PrintDebug("CPUID called for 0x%x\n", cpuid);
+
if (hook == NULL) {
+ //PrintDebug("Calling passthrough handler\n");
// call the passthrough handler
v3_cpuid(cpuid,
(uint32_t *)&(info->vm_regs.rax),
(uint32_t *)&(info->vm_regs.rcx),
(uint32_t *)&(info->vm_regs.rdx));
} else {
+ // PrintDebug("Calling hook function\n");
+
if (hook->hook_fn(info, cpuid,
(uint32_t *)&(info->vm_regs.rax),
(uint32_t *)&(info->vm_regs.rbx),
}
}
+ // PrintDebug("Cleaning up register contents\n");
+
info->vm_regs.rax &= 0x00000000ffffffffLL;
info->vm_regs.rbx &= 0x00000000ffffffffLL;
info->vm_regs.rcx &= 0x00000000ffffffffLL;
struct v3_msr msr_val;
struct v3_msr_hook * hook = NULL;
+ PrintDebug("MSR write for msr 0x%x\n", msr_num);
+
hook = v3_get_msr_hook(info, msr_num);
if (!hook) {
}
list_for_each_entry(hook, &(msr_map->hook_list), link) {
+ PrintDebug("updating MSR map for msr %d\n", hook->msr);
msr_map->update_map(info, hook->msr,
(hook->read == NULL) ? 0 : 1,
(hook->write == NULL) ? 0 : 1);
struct v3_msr_hook * hook = NULL;
list_for_each_entry(hook, &(msr_map->hook_list), link) {
- PrintDebug("MSR HOOK (MSR=%d) (read=0x%p) (write=0x%p)\n",
+ V3_Print("MSR HOOK (MSR=0x%x) (read=0x%p) (write=0x%p)\n",
hook->msr, hook->read, hook->write);
}
}
if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pml4e->pdp_base_addr), (addr_t *)&guest_pdp) == -1) {
// Machine check the guest
- PrintDebug("Invalid Guest PDP Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pml4e->pdp_base_addr));
+ PrintError("Invalid Guest PDP Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pml4e->pdp_base_addr));
v3_raise_exception(info, MC_EXCEPTION);
return 0;
}
if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr), (addr_t *)&guest_pd) == -1) {
// Machine check the guest
- PrintDebug("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr));
+ PrintError("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr));
v3_raise_exception(info, MC_EXCEPTION);
return 0;
}
if (guest_pde->large_page == 0) {
if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr), (addr_t *)&guest_pt) == -1) {
// Machine check the guest
- PrintDebug("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr));
+ PrintError("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr));
v3_raise_exception(info, MC_EXCEPTION);
return 0;
}
if (shdw_reg == NULL) {
// Inject a machine check in the guest
- PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
+ PrintError("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
v3_raise_exception(info, MC_EXCEPTION);
return 0;
}
if (shdw_reg == NULL) {
// Inject a machine check in the guest
- PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
+ PrintError("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
v3_raise_exception(info, MC_EXCEPTION);
return 0;
}
#include <palacios/vmm.h>
#include <palacios/vmm_msr.h>
#include <palacios/vmm_mem.h>
+#include <palacios/vmm_hypercall.h>
-#define SYM_MSR_NUM 0x535
+#define SYM_PAGE_MSR 0x535
+#define SYM_CPUID_NUM 0x90000000
+#define SYM_CALL_RET_HCALL 0x535
static int msr_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
struct guest_info * info = (struct guest_info *)priv_data;
struct v3_sym_state * state = &(info->sym_state);
+
+ PrintDebug("Symbiotic MSR write for page %p\n", (void *)src.value);
+
if (state->active == 1) {
// unmap page
struct v3_shadow_region * old_reg = v3_get_shadow_region(info, (addr_t)state->guest_pg_addr);
return 0;
}
+static int cpuid_fn(struct guest_info * info, uint32_t cpuid,
+ uint32_t * eax, uint32_t * ebx,
+ uint32_t * ecx, uint32_t * edx,
+ void * private_data) {
+
+ memset(eax, 0, sizeof(uint32_t));
+ memcpy(eax, "V3V", 3);
+
+ return 0;
+}
+
+
+static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * private_data);
+
int v3_init_sym_iface(struct guest_info * info) {
struct v3_sym_state * state = &(info->sym_state);
-
memset(state, 0, sizeof(struct v3_sym_state));
- PrintDebug("Allocating symbiotic page\n");
state->sym_page_pa = (addr_t)V3_AllocPages(1);
state->sym_page = (struct v3_sym_interface *)V3_VAddr((void *)state->sym_page_pa);
-
- PrintDebug("Clearing symbiotic page\n");
memset(state->sym_page, 0, PAGE_SIZE_4KB);
- PrintDebug("hooking MSR\n");
- v3_hook_msr(info, SYM_MSR_NUM, msr_read, msr_write, info);
+
+ memcpy(&(state->sym_page->magic), "V3V", 3);
+
+ v3_hook_msr(info, SYM_PAGE_MSR, msr_read, msr_write, info);
+
+ v3_hook_cpuid(info, SYM_CPUID_NUM, cpuid_fn, info);
+
+
+ v3_register_hypercall(info, SYM_CALL_RET_HCALL, sym_call_ret, NULL);
- PrintDebug("Done\n");
return 0;
}
int v3_sym_map_pci_passthrough(struct guest_info * info, uint_t bus, uint_t dev, uint_t fn) {
struct v3_sym_state * state = &(info->sym_state);
- uint_t dev_index = (bus << 16) + (dev << 8) + fn;
+ 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);
+
state->sym_page->pci_pt_map[major] |= 0x1 << minor;
+ PrintDebug("pt_map entry=%x\n", state->sym_page->pci_pt_map[major]);
+
+ PrintDebug("pt map vmm addr=%p\n", state->sym_page->pci_pt_map);
+
return 0;
}
int v3_sym_unmap_pci_passthrough(struct guest_info * info, uint_t bus, uint_t dev, uint_t fn) {
struct v3_sym_state * state = &(info->sym_state);
- uint_t dev_index = (bus << 16) + (dev << 8) + fn;
+ 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;
+ }
+
state->sym_page->pci_pt_map[major] &= ~(0x1 << minor);
return 0;
}
+
+
+
+static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * private_data) {
+ struct v3_sym_state * state = (struct v3_sym_state *)&(info->sym_state);
+ struct v3_sym_context * old_ctx = (struct v3_sym_context *)&(state->old_ctx);
+
+
+ PrintError("Return from sym call\n");
+ v3_print_guest_state(info);
+ v3_print_mem_map(info);
+
+
+ if (state->notifier != NULL) {
+ if (state->notifier(info, state->private_data) == -1) {
+ PrintError("Error in return from symcall.\n");
+ return -1;
+ }
+ }
+
+
+ // restore guest state
+ memcpy(&(info->vm_regs), &(old_ctx->vm_regs), sizeof(struct v3_gprs));
+ memcpy(&(info->segments.cs), &(old_ctx->cs), sizeof(struct v3_segment));
+ memcpy(&(info->segments.ss), &(old_ctx->ss), sizeof(struct v3_segment));
+ info->segments.gs.base = old_ctx->gs_base;
+ info->segments.fs.base = old_ctx->fs_base;
+ info->rip = old_ctx->rip;
+ info->cpl = old_ctx->cpl;
+
+
+ PrintDebug("restoring guest state\n");
+ v3_print_guest_state(info);
+
+ // clear sym flags
+ state->call_active = 0;
+
+
+ return 0;
+}
+
+
+int v3_sym_call(struct guest_info * info,
+ uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3,
+ uint64_t arg4, uint64_t arg5,
+ int (*notifier)(struct guest_info * info, void * private_data),
+ void * private_data) {
+ struct v3_sym_state * state = (struct v3_sym_state *)&(info->sym_state);
+
+
+ PrintDebug("Making Sym call\n");
+
+ if ((state->sym_page->sym_call_enabled == 0) ||
+ (state->call_active == 1) ||
+ (state->call_pending == 1)) {
+ return -1;
+ }
+
+ state->args[0] = arg0;
+ state->args[1] = arg1;
+ state->args[2] = arg2;
+ state->args[3] = arg3;
+ state->args[4] = arg4;
+ state->args[5] = arg5;
+
+ state->notifier = notifier;
+ state->private_data = private_data;
+
+ state->call_pending = 1;
+
+ return 0;
+}
+
+
+
+int v3_activate_sym_call(struct guest_info * info) {
+ struct v3_sym_state * state = (struct v3_sym_state *)&(info->sym_state);
+ struct v3_sym_context * old_ctx = (struct v3_sym_context *)&(state->old_ctx);
+ struct v3_segment sym_cs;
+ struct v3_segment sym_ss;
+
+
+ if ((state->sym_page->sym_call_enabled == 0) ||
+ (state->call_pending == 0)) {
+ // Unable to make sym call or none pending
+ if (state->call_active == 1) {
+ PrintError("handled exit while in symcall\n");
+ }
+ return 0;
+ }
+
+
+ PrintDebug("Activating Symbiotic call\n");
+ v3_print_guest_state(info);
+
+
+ // Save the old context
+ memcpy(&(old_ctx->vm_regs), &(info->vm_regs), sizeof(struct v3_gprs));
+ memcpy(&(old_ctx->cs), &(info->segments.cs), sizeof(struct v3_segment));
+ memcpy(&(old_ctx->ss), &(info->segments.ss), sizeof(struct v3_segment));
+ old_ctx->gs_base = info->segments.gs.base;
+ old_ctx->fs_base = info->segments.fs.base;
+ old_ctx->rip = info->rip;
+ old_ctx->cpl = info->cpl;
+
+
+
+ // Setup the sym call context
+ info->rip = state->sym_page->sym_call_rip;
+ info->vm_regs.rsp = state->sym_page->sym_call_rsp;
+
+ v3_translate_segment(info, state->sym_page->sym_call_cs, &sym_cs);
+ memcpy(&(info->segments.cs), &sym_cs, sizeof(struct v3_segment));
+
+ v3_translate_segment(info, state->sym_page->sym_call_cs + 8, &sym_ss);
+ memcpy(&(info->segments.ss), &sym_ss, sizeof(struct v3_segment));
+
+ info->segments.gs.base = state->sym_page->sym_call_gs;
+ info->segments.fs.base = 0;
+ info->cpl = 0;
+
+ info->vm_regs.rax = state->args[0];
+ info->vm_regs.rbx = state->args[1];
+ info->vm_regs.rcx = state->args[2];
+ info->vm_regs.rdx = state->args[3];
+ info->vm_regs.rsi = state->args[4];
+ info->vm_regs.rdi = state->args[5];
+
+ // Mark sym call as active
+ state->call_pending = 0;
+ state->call_active = 1;
+
+
+ PrintDebug("Sym state\n");
+ v3_print_guest_state(info);
+
+ return 1;
+}
if (info->shdw_pg_mode == SHADOW_PAGING) {
+ /*
PrintDebug("Old Guest CR3=%p, Old Shadow CR3=%p\n",
(void *)info->ctrl_regs.cr3,
(void *)info->shdw_pg_state.guest_cr3);
-
+ */
if (info->cpu_mode == LONG) {
info->shdw_pg_state.guest_cr3 = (uint64_t)*cr3_reg;
} else {
return -1;
}
}
-
+ /*
PrintDebug("New guest CR3=%p, New shadow CR3=%p\n",
(void *)info->ctrl_regs.cr3,
(void *)info->shdw_pg_state.guest_cr3);
-
+ */
} else if (info->shdw_pg_mode == NESTED_PAGING) {
PrintError("Nested paging not available in VMX right now!\n");
return -1;
uint_t paging_transition = 0;
int instr_len = 0;
+ /*
PrintDebug("Old shadow CR0: 0x%x, New shadow CR0: 0x%x\n",
(uint32_t)info->shdw_pg_state.guest_cr0, (uint32_t)*new_cr0);
-
+ */
if (new_shdw_cr0->pe != shdw_cr0->pe) {
+ /*
PrintDebug("Guest CR0: 0x%x\n", *(uint32_t *)guest_cr0);
PrintDebug("Old shadow CR0: 0x%x\n", *(uint32_t *)shdw_cr0);
PrintDebug("New shadow CR0: 0x%x\n", *(uint32_t *)new_shdw_cr0);
-
+ */
if (v3_vmxassist_ctx_switch(info) != 0) {
PrintError("Unable to execute VMXASSIST context switch!\n");
return -1;
struct efer_64 * guest_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
if (guest_efer->lme == 1) {
- PrintDebug("Enabling long mode\n");
+ // PrintDebug("Enabling long mode\n");
guest_efer->lma = 1;
guest_efer->lme = 1;
vmx_info->entry_ctrls.guest_ia32e = 1;
}
- PrintDebug("Activating Shadow Page tables\n");
+ // PrintDebug("Activating Shadow Page tables\n");
if (v3_activate_shadow_pt(info) == -1) {
PrintError("Failed to activate shadow page tables\n");
// PrintDebug("Control register: %d\n", cr_qual->access_type);
switch(cr_qual->cr_id) {
case 0:
- PrintDebug("Handling CR0 Access\n");
+ //PrintDebug("Handling CR0 Access\n");
return v3_vmx_handle_cr0_access(info);
case 3:
- PrintDebug("Handling CR3 Access\n");
+ //PrintDebug("Handling CR3 Access\n");
return v3_vmx_handle_cr3_access(info);
default:
PrintError("Unhandled CR access: %d\n", cr_qual->cr_id);
}
break;
+ case VMEXIT_VMCALL:
+ /*
+ * Hypercall
+ */
+
+ // VMCALL is a 3 byte op
+ // We do this early because some hypercalls can change the rip...
+ info->rip += 3;
+
+ if (v3_handle_hypercall(info) == -1) {
+ return -1;
+ }
+ break;
case VMEXIT_IO_INSTR: {
struct vmx_exit_io_qual * io_qual = (struct vmx_exit_io_qual *)&exit_qual;
check_vmcs_write(VMCS_ENTRY_EXCP_ERR, info->excp_state.excp_error_code);
int_info.error_code = 1;
+#ifdef CONFIG_DEBUG_INTERRUPTS
PrintDebug("Injecting exception %d with error code %x\n",
int_info.vector, info->excp_state.excp_error_code);
+#endif
}
int_info.valid = 1;
+#ifdef CONFIG_DEBUG_INTERRUPTS
PrintDebug("Injecting exception %d (EIP=%p)\n", int_info.vector, (void *)info->rip);
+#endif
check_vmcs_write(VMCS_ENTRY_INT_INFO, int_info.value);
v3_injecting_excp(info, int_info.vector);
PrintBoth("Next: setup GDT\n");
+ {
+ uint_t addr = 0xe0000;
+ uint_t hi = 0;
+
+
+
+ // wrmsr(SYMBIOTIC_MSR, hi, addr);
+ {
+ uint_t msr_num = 0x0000001B;
+ __asm__ __volatile__ ("rdmsr" : : "c"(msr_num) : "%eax","%edx","memory");
+ }
+ {
+ uint_t msr_num = 0x0000001c;
+ __asm__ __volatile__ ("rdmsr" : : "c"(msr_num) : "%eax","%edx","memory");
+ }
+
+
+ {
+ uint_t msr_num = 0x0000001B;
+ __asm__ __volatile__ ("wrmsr" : : "c"(msr_num), "a"(hi), "d"(addr) : "memory");
+ }
+
+ {
+ uint_t msr_num = 0x535;
+ __asm__ __volatile__ ("wrmsr" : : "c"(msr_num), "a"(hi), "d"(addr) : "memory");
+ }
+
+
+ while (1) {}
+
+ }
if (TEST_PAGING) {
int i = 0;
for (i = 0; i < 1024; i++) {