X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fsvm.c;h=c3bce64f05c9140ced4da9132c05d3bb8beed90d;hb=cf780b903a02efc700d51dbadcc90115f016256c;hp=52d32011016a3f38b30e3ee68fee7110c8ebfc8e;hpb=3676fa947d261206ceff968e4f6b5956900ed277;p=palacios.releases.git diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 52d3201..c3bce64 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -35,6 +35,8 @@ #include #include +#include + #include @@ -80,6 +82,25 @@ static vmcb_t * Allocate_VMCB() { } +static int v3_svm_handle_efer_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) +{ + int status; + + // Call arch-independent handler + if ((status = v3_handle_efer_write(core, msr, src, priv_data)) != 0) { + return status; + } + + // SVM-specific code + { + // Ensure that hardware visible EFER.SVME bit is set (SVM Enable) + struct efer_64 * hw_efer = (struct efer_64 *)&(core->ctrl_regs.efer); + hw_efer->svme = 1; + } + + return 0; +} + static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); @@ -220,7 +241,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { v3_hook_msr(core->vm_info, EFER_MSR, &v3_handle_efer_read, - &v3_handle_efer_write, + &v3_svm_handle_efer_write, core); if (core->shdw_pg_mode == SHADOW_PAGING) { @@ -424,6 +445,18 @@ static int update_irq_entry_state(struct guest_info * info) { break; case V3_SOFTWARE_INTR: guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR; + +#ifdef V3_CONFIG_DEBUG_INTERRUPTS + PrintDebug("Injecting software interrupt -- type: %d, vector: %d\n", + SVM_INJECTION_SOFT_INTR, info->intr_core_state.swintr_vector); +#endif + guest_ctrl->EVENTINJ.vector = info->intr_core_state.swintr_vector; + guest_ctrl->EVENTINJ.valid = 1; + + /* reset swintr state */ + info->intr_core_state.swintr_posted = 0; + info->intr_core_state.swintr_vector = 0; + break; case V3_VIRTUAL_IRQ: guest_ctrl->EVENTINJ.type = SVM_INJECTION_IRQ; @@ -462,9 +495,9 @@ int v3_svm_enter(struct guest_info * info) { // disable global interrupts for vm state transition v3_clgi(); - // Update timer devices right before entering the VM. Doing it - // here makes sure the guest sees any timers that fired while - // it was in the VMM + // Update timer devices after being in the VM, with interupts + // disabled, but before doing IRQ updates, so that any interrupts they + //raise get seen immediately. v3_update_timers(info); // Synchronize the guest state to the VMCB @@ -549,13 +582,11 @@ int v3_svm_enter(struct guest_info * info) { info->mem_mode = v3_get_vm_mem_mode(info); /* ** */ - // save exit info here exit_code = guest_ctrl->exit_code; exit_info1 = guest_ctrl->exit_info1; exit_info2 = guest_ctrl->exit_info2; - #ifdef V3_CONFIG_SYMCALL if (info->sym_core_state.symcall_state.sym_call_active == 0) { update_irq_exit_state(info); @@ -564,20 +595,20 @@ int v3_svm_enter(struct guest_info * info) { update_irq_exit_state(info); #endif - // reenable global interrupts after vm exit v3_stgi(); - // Conditionally yield the CPU if the timeslice has expired v3_yield_cond(info); - - - if (v3_handle_svm_exit(info, exit_code, exit_info1, exit_info2) != 0) { - PrintError("Error in SVM exit handler\n"); - PrintError(" last exit was %d\n", v3_last_exit); - return -1; + { + int ret = v3_handle_svm_exit(info, exit_code, exit_info1, exit_info2); + + if (ret != 0) { + PrintError("Error in SVM exit handler (ret=%d)\n", ret); + PrintError(" last Exit was %d (exit code=0x%llx)\n", v3_last_exit, (uint64_t) exit_code); + return -1; + } } @@ -662,6 +693,8 @@ int v3_start_svm_guest(struct guest_info * info) { break; } + v3_wait_at_barrier(info); + if (info->vm_info->run_state == VM_STOPPED) { info->core_run_state = CORE_STOPPED; @@ -670,11 +703,12 @@ int v3_start_svm_guest(struct guest_info * info) { - if ((info->num_exits % 5000) == 0) { +/* + if ((info->num_exits % 50000) == 0) { V3_Print("SVM Exit number %d\n", (uint32_t)info->num_exits); v3_print_guest_state(info); } - +*/ } @@ -686,6 +720,31 @@ int v3_start_svm_guest(struct guest_info * info) { +int v3_reset_svm_vm_core(struct guest_info * core, addr_t rip) { + // init vmcb_bios + + // Write the RIP, CS, and descriptor + // assume the rest is already good to go + // + // vector VV -> rip at 0 + // CS = VV00 + // This means we start executing at linear address VV000 + // + // So the selector needs to be VV00 + // and the base needs to be VV000 + // + core->rip = 0; + core->segments.cs.selector = rip << 8; + core->segments.cs.limit = 0xffff; + core->segments.cs.base = rip << 12; + + return 0; +} + + + + + /* Checks machine SVM capability */ /* Implemented from: AMD Arch Manual 3, sect 15.4 */ @@ -735,11 +794,11 @@ int v3_is_svm_capable() { static int has_svm_nested_paging() { uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; - + v3_cpuid(CPUID_SVM_REV_AND_FEATURE_IDS, &eax, &ebx, &ecx, &edx); - + //PrintDebug("CPUID_EXT_FEATURE_IDS_edx=0x%x\n", edx); - + if ((edx & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) { V3_Print("SVM Nested Paging not supported\n"); return 0; @@ -747,7 +806,8 @@ static int has_svm_nested_paging() { V3_Print("SVM Nested Paging supported\n"); return 1; } -} + } + void v3_init_svm_cpu(int cpu_id) {