From: Jack Lange Date: Fri, 2 Oct 2009 20:18:02 +0000 (-0500) Subject: added symbiotic interface X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=cd012ba87f57c1c694038f1a17f249f90f9a2be8 added symbiotic interface --- diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index d8444a6..b5d481c 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -232,6 +232,8 @@ void v3_print_segments(struct guest_info * info); void v3_print_ctrl_regs(struct guest_info * info); void v3_print_GPRs(struct guest_info * info); +void v3_print_stack(struct guest_info * info); + #endif // ! __V3VEE__ #endif diff --git a/palacios/include/palacios/vmm_sym_iface.h b/palacios/include/palacios/vmm_sym_iface.h index 94b47ec..ce599b3 100644 --- a/palacios/include/palacios/vmm_sym_iface.h +++ b/palacios/include/palacios/vmm_sym_iface.h @@ -52,11 +52,7 @@ struct v3_sym_interface { 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; + } __attribute__((packed)); @@ -90,6 +86,14 @@ struct v3_sym_state { struct v3_sym_context old_ctx; uint64_t args[6]; + + 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; + uint64_t sym_call_ret_fn; + int (*notifier)(struct guest_info * info, void * private_data); void * private_data; @@ -120,10 +124,15 @@ int v3_sym_map_pci_passthrough(struct guest_info * info, uint_t bus, uint_t dev, int v3_sym_unmap_pci_passthrough(struct guest_info * info, 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 arg0, uint64_t arg1, - uint64_t arg2, uint64_t arg3, - uint64_t arg4, uint64_t arg5, + uint64_t call_num, uint64_t arg0, + uint64_t arg1, uint64_t arg2, + uint64_t arg3, uint64_t arg4, int (*notifier)(struct guest_info * info, void * private_data), void * private_data); diff --git a/palacios/src/devices/keyboard.c b/palacios/src/devices/keyboard.c index c50374a..00e497a 100644 --- a/palacios/src/devices/keyboard.c +++ b/palacios/src/devices/keyboard.c @@ -329,9 +329,14 @@ static int key_event_handler(struct guest_info * 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); + v3_sym_call5(info, SYMCALL_TEST, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, NULL, NULL); + } else if (evt->scan_code == 0x42) { // F8 Sym test2 + PrintDebug("Testing sym call\n"); + v3_sym_call1(info, SYMCALL_MEM_LOOKUP, 0, NULL, NULL); } + + addr_t irq_state = v3_lock_irqsave(state->kb_lock); if ( (state->status.enabled == 1) // onboard is enabled diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index dd2e407..7a1c737 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -42,6 +42,7 @@ #include #include +#include // This is a global pointer to the host's VMCB @@ -325,7 +326,7 @@ static int start_svm_guest(struct guest_info *info) { vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); addr_t host_addr; addr_t linear_addr = 0; - + info->run_state = VM_ERROR; PrintDebug("SVM ERROR!!\n"); @@ -353,6 +354,10 @@ static int start_svm_guest(struct guest_info *info) { PrintDebug("Instr (15 bytes) at %p:\n", (void *)host_addr); v3_dump_mem((uint8_t *)host_addr, 15); + + v3_print_stack(info); + + break; } } @@ -366,7 +371,6 @@ static int start_svm_guest(struct guest_info *info) { /* Checks machine SVM capability */ /* Implemented from: AMD Arch Manual 3, sect 15.4 */ int v3_is_svm_capable() { - // Dinda uint_t vm_cr_low = 0, vm_cr_high = 0; uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; diff --git a/palacios/src/palacios/svm_handler.c b/palacios/src/palacios/svm_handler.c index 1c64657..eeb03c8 100644 --- a/palacios/src/palacios/svm_handler.c +++ b/palacios/src/palacios/svm_handler.c @@ -83,14 +83,16 @@ int v3_handle_svm_exit(struct guest_info * info) { #ifdef CONFIG_SYMBIOTIC if (0) { + // if (sym_started == 1) { // 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); - } + /* if (exit_code == VMEXIT_EXCP14) { + PrintGuestPageTree(info, guest_ctrl->exit_info2, info->shdw_pg_state.guest_cr3); + }*/ + } #endif diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c index 94bbc7b..6b902f0 100644 --- a/palacios/src/palacios/vm_guest.c +++ b/palacios/src/palacios/vm_guest.c @@ -168,11 +168,11 @@ void v3_print_segments(struct guest_info * info) { seg_ptr=(struct v3_segment *)segs; char *seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL}; - PrintDebug("Segments\n"); + V3_Print("Segments\n"); for (i = 0; seg_names[i] != NULL; i++) { - PrintDebug("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, + V3_Print("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, (void *)(addr_t)seg_ptr[i].base, seg_ptr[i].limit, seg_ptr[i].long_mode, seg_ptr[i].db); @@ -247,13 +247,13 @@ void v3_print_ctrl_regs(struct guest_info * info) { reg_ptr = (v3_reg_t *)regs; - PrintDebug("32 bit Ctrl Regs:\n"); + V3_Print("32 bit Ctrl Regs:\n"); for (i = 0; reg_names[i] != NULL; i++) { - PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]); + V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]); } - PrintDebug("\tEFER=0x%p\n", (void*)(addr_t)(guest_state->efer)); + V3_Print("\tEFER=0x%p\n", (void*)(addr_t)(guest_state->efer)); } @@ -261,24 +261,56 @@ void v3_print_ctrl_regs(struct guest_info * info) { void v3_print_guest_state(struct guest_info * info) { addr_t linear_addr = 0; - PrintDebug("RIP: %p\n", (void *)(addr_t)(info->rip)); + V3_Print("RIP: %p\n", (void *)(addr_t)(info->rip)); linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs)); - PrintDebug("RIP Linear: %p\n", (void *)linear_addr); + V3_Print("RIP Linear: %p\n", (void *)linear_addr); v3_print_segments(info); v3_print_ctrl_regs(info); if (info->shdw_pg_mode == SHADOW_PAGING) { - PrintDebug("Shadow Paging Guest Registers:\n"); - PrintDebug("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0)); - PrintDebug("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3)); - PrintDebug("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value)); + V3_Print("Shadow Paging Guest Registers:\n"); + V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0)); + V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3)); + V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value)); // CR4 } v3_print_GPRs(info); } +void v3_print_stack(struct guest_info * info) { + addr_t linear_addr = 0; + addr_t host_addr = 0; + int i = 0; + v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info); + + + linear_addr = get_addr_linear(info, info->vm_regs.rsp, &(info->segments.ss)); + + if (info->mem_mode == PHYSICAL_MEM) { + guest_pa_to_host_va(info, linear_addr, &host_addr); + } else if (info->mem_mode == VIRTUAL_MEM) { + guest_va_to_host_va(info, linear_addr, &host_addr); + } + + V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr); + V3_Print("Stack at %p:\n", (void *)host_addr); + + // We start i at one because the current stack pointer points to an unused stack element + for (i = 0; i <= 24; i++) { + if (cpu_mode == LONG) { + V3_Print("\t%p\n", (void *)*(uint64_t *)(host_addr + (i * 8))); + } else if (cpu_mode == REAL) { + V3_Print("Don't currently handle 16 bit stacks... \n"); + } else { + // 32 bit stacks... + V3_Print("\t%.8x\n", *(uint32_t *)(host_addr + (i * 4))); + } + } + +} + #ifdef __V3_32BIT__ void v3_print_GPRs(struct guest_info * info) { @@ -289,10 +321,10 @@ void v3_print_GPRs(struct guest_info * info) { reg_ptr= (v3_reg_t *)regs; - PrintDebug("32 bit GPRs:\n"); + V3_Print("32 bit GPRs:\n"); for (i = 0; reg_names[i] != NULL; i++) { - PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]); + V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]); } } @@ -305,12 +337,12 @@ void v3_print_GPRs(struct guest_info * info) { char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \ "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL}; - reg_ptr= (v3_reg_t *)regs; + reg_ptr = (v3_reg_t *)regs; - PrintDebug("64 bit GPRs:\n"); + V3_Print("64 bit GPRs:\n"); for (i = 0; reg_names[i] != NULL; i++) { - PrintDebug("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]); + V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]); } } diff --git a/palacios/src/palacios/vmm_hypercall.c b/palacios/src/palacios/vmm_hypercall.c index f3169a7..3dc49f2 100644 --- a/palacios/src/palacios/vmm_hypercall.c +++ b/palacios/src/palacios/vmm_hypercall.c @@ -119,7 +119,8 @@ int v3_handle_hypercall(struct guest_info * info) { struct hypercall * hcall = get_hypercall(info, hypercall_id); if (!hcall) { - PrintError("Invalid Hypercall (%d not registered)\n", hypercall_id); + PrintError("Invalid Hypercall (%d(0x%x) not registered)\n", + hypercall_id, hypercall_id); return -1; } diff --git a/palacios/src/palacios/vmm_sym_iface.c b/palacios/src/palacios/vmm_sym_iface.c index 5cb4e35..ae7fcdc 100644 --- a/palacios/src/palacios/vmm_sym_iface.c +++ b/palacios/src/palacios/vmm_sym_iface.c @@ -30,11 +30,47 @@ #define SYM_CALL_RET_HCALL 0x535 +/* 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 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); - dst->value = state->guest_pg_addr; + switch (msr) { + case SYM_PAGE_MSR: + dst->value = state->guest_pg_addr; + break; + 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; } @@ -43,31 +79,47 @@ static int msr_write(uint_t msr, struct v3_msr src, void * priv_data) { struct guest_info * info = (struct guest_info *)priv_data; struct v3_sym_state * state = &(info->sym_state); + if (msr == SYM_PAGE_MSR) { + PrintDebug("Symbiotic MSR write for page %p\n", (void *)src.value); - 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); - if (state->active == 1) { - // unmap page - struct v3_shadow_region * old_reg = v3_get_shadow_region(info, (addr_t)state->guest_pg_addr); + if (old_reg == NULL) { + PrintError("Could not find previously active symbiotic page (%p)\n", (void *)state->guest_pg_addr); + return -1; + } - if (old_reg == NULL) { - PrintError("Could not find previously active symbiotic page (%p)\n", (void *)state->guest_pg_addr); - return -1; + v3_delete_shadow_region(info, old_reg); } - v3_delete_shadow_region(info, old_reg); + state->guest_pg_addr = src.value; + state->guest_pg_addr &= ~0xfffLL; + + state->active = 1; + + // map page + v3_add_shadow_mem(info, (addr_t)state->guest_pg_addr, + (addr_t)(state->guest_pg_addr + PAGE_SIZE_4KB - 1), + state->sym_page_pa); + + + } else if (msr == SYMCALL_RIP_MSR) { + state->sym_call_rip = src.value; + } else if (msr == SYMCALL_RSP_MSR) { + state->sym_call_rsp = src.value; + } else if (msr == SYMCALL_CS_MSR) { + state->sym_call_cs = src.value; + } else if (msr == SYMCALL_GS_MSR) { + state->sym_call_gs = src.value; + } else if (msr == SYMCALL_FS_MSR) { + state->sym_call_fs = src.value; + } else { + PrintError("Invalid Symbiotic MSR write (0x%x)\n", msr); + return -1; } - state->guest_pg_addr = src.value; - state->guest_pg_addr &= ~0xfffLL; - - state->active = 1; - - // map page - v3_add_shadow_mem(info, (addr_t)state->guest_pg_addr, - (addr_t)(state->guest_pg_addr + PAGE_SIZE_4KB - 1), - state->sym_page_pa); - return 0; } @@ -75,9 +127,18 @@ 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) { + extern v3_cpu_arch_t v3_cpu_types[]; + + *eax = *(uint32_t *)"V3V"; + + if ((v3_cpu_types[info->cpu_id] == V3_SVM_CPU) || + (v3_cpu_types[info->cpu_id] == V3_SVM_REV3_CPU)) { + *ebx = *(uint32_t *)"SVM"; + } else if ((v3_cpu_types[info->cpu_id] == V3_VMX_CPU) || + (v3_cpu_types[info->cpu_id] == V3_VMX_EPT_CPU)) { + *ebx = *(uint32_t *)"VMX"; + } - memset(eax, 0, sizeof(uint32_t)); - memcpy(eax, "V3V", 3); return 0; } @@ -102,6 +163,11 @@ int v3_init_sym_iface(struct guest_info * info) { v3_hook_cpuid(info, SYM_CPUID_NUM, cpuid_fn, info); + v3_hook_msr(info, SYMCALL_RIP_MSR, msr_read, msr_write, info); + v3_hook_msr(info, SYMCALL_RSP_MSR, msr_read, msr_write, info); + v3_hook_msr(info, SYMCALL_CS_MSR, msr_read, msr_write, info); + v3_hook_msr(info, SYMCALL_GS_MSR, msr_read, msr_write, info); + v3_hook_msr(info, SYMCALL_FS_MSR, msr_read, msr_write, info); v3_register_hypercall(info, SYM_CALL_RET_HCALL, sym_call_ret, NULL); @@ -188,9 +254,9 @@ static int sym_call_ret(struct guest_info * info, uint_t hcall_id, void * privat 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, + uint64_t call_num, uint64_t arg0, + uint64_t arg1, uint64_t arg2, + uint64_t arg3, uint64_t arg4, int (*notifier)(struct guest_info * info, void * private_data), void * private_data) { struct v3_sym_state * state = (struct v3_sym_state *)&(info->sym_state); @@ -204,12 +270,12 @@ int v3_sym_call(struct guest_info * info, 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->args[0] = call_num; + state->args[1] = arg0; + state->args[2] = arg1; + state->args[3] = arg2; + state->args[4] = arg3; + state->args[5] = arg4; state->notifier = notifier; state->private_data = private_data; @@ -254,17 +320,17 @@ int v3_activate_sym_call(struct guest_info * info) { // Setup the sym call context - info->rip = state->sym_page->sym_call_rip; - info->vm_regs.rsp = state->sym_page->sym_call_rsp; + info->rip = state->sym_call_rip; + info->vm_regs.rsp = state->sym_call_rsp; - v3_translate_segment(info, state->sym_page->sym_call_cs, &sym_cs); + v3_translate_segment(info, state->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); + v3_translate_segment(info, state->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->segments.gs.base = state->sym_call_gs; + info->segments.fs.base = state->sym_call_fs; info->cpl = 0; info->vm_regs.rax = state->args[0];