X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fsvm.c;h=a4e9443d5140839bec83762387884fbc1c2c2267;hb=3f777ee2e04c359758b0658b04ff8f076d38f2f9;hp=b4f692cf0c23666db477db43ed8b6762ecc0ca09;hpb=a686a57429dcd9fa2f701228227dadcd096df8ed;p=palacios.git diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index b4f692c..a4e9443 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -18,6 +18,7 @@ */ + #include #include @@ -36,6 +37,9 @@ #include #include +#include + + #ifdef V3_CONFIG_CHECKPOINT #include @@ -239,7 +243,19 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { PrintDebug("Exiting on interrupts\n"); ctrl_area->guest_ctrl.V_INTR_MASKING = 1; ctrl_area->instrs.INTR = 1; + // The above also assures the TPR changes (CR8) are only virtual + + // However, we need to see TPR writes since they will + // affect the virtual apic + // we reflect out cr8 to ctrl_regs->apic_tpr + ctrl_area->cr_reads.cr8 = 1; + ctrl_area->cr_writes.cr8 = 1; + // We will do all TPR comparisons in the virtual apic + // We also do not want the V_TPR to be able to mask the PIC + ctrl_area->guest_ctrl.V_IGN_TPR = 1; + + v3_hook_msr(core->vm_info, EFER_MSR, &v3_handle_efer_read, @@ -275,7 +291,6 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { ctrl_area->cr_writes.cr3 = 1; - ctrl_area->instrs.INVLPG = 1; ctrl_area->exceptions.pf = 1; @@ -283,7 +298,6 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { guest_state->g_pat = 0x7040600070406ULL; - } else if (core->shdw_pg_mode == NESTED_PAGING) { // Flush the TLB on entries/exits ctrl_area->TLB_CONTROL = 1; @@ -368,15 +382,25 @@ int v3_deinit_svm_vmcb(struct guest_info * core) { #ifdef V3_CONFIG_CHECKPOINT int v3_svm_save_core(struct guest_info * core, void * ctx){ - v3_chkpt_save_8(ctx, "cpl", &(core->cpl)); - v3_chkpt_save(ctx, "vmcb_data", PAGE_SIZE, core->vmm_data); + if (v3_chkpt_save_8(ctx, "cpl", &(core->cpl)) == -1) { + PrintError("Could not save SVM cpl\n"); + return -1; + } + + if (v3_chkpt_save(ctx, "vmcb_data", PAGE_SIZE, core->vmm_data) == -1) { + PrintError("Could not save SVM vmcb\n"); + return -1; + } return 0; } int v3_svm_load_core(struct guest_info * core, void * ctx){ - v3_chkpt_load_8(ctx, "cpl", &(core->cpl)); + if (v3_chkpt_load_8(ctx, "cpl", &(core->cpl)) == -1) { + PrintError("Could not load SVM cpl\n"); + return -1; + } if (v3_chkpt_load(ctx, "vmcb_data", PAGE_SIZE, core->vmm_data) == -1) { return -1; @@ -463,8 +487,11 @@ static int update_irq_entry_state(struct guest_info * info) { #endif guest_ctrl->guest_ctrl.V_IRQ = 1; guest_ctrl->guest_ctrl.V_INTR_VECTOR = info->intr_core_state.irq_vector; + + // We ignore the virtual TPR on this injection + // TPR/PPR tests have already been done in the APIC. guest_ctrl->guest_ctrl.V_IGN_TPR = 1; - guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf; + guest_ctrl->guest_ctrl.V_INTR_PRIO = info->intr_core_state.irq_vector >> 4 ; // 0xf; } else { switch (v3_intr_pending(info)) { @@ -473,8 +500,11 @@ static int update_irq_entry_state(struct guest_info * info) { guest_ctrl->guest_ctrl.V_IRQ = 1; guest_ctrl->guest_ctrl.V_INTR_VECTOR = irq; + + // We ignore the virtual TPR on this injection + // TPR/PPR tests have already been done in the APIC. guest_ctrl->guest_ctrl.V_IGN_TPR = 1; - guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf; + guest_ctrl->guest_ctrl.V_INTR_PRIO = info->intr_core_state.irq_vector >> 4 ; // 0xf; #ifdef V3_CONFIG_DEBUG_INTERRUPTS PrintDebug("Injecting Interrupt %d (EIP=%p)\n", @@ -523,13 +553,19 @@ int v3_svm_config_tsc_virtualization(struct guest_info * info) { vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); - if (info->time_state.time_flags & V3_TIME_TRAP_RDTSC) { + + if (info->time_state.flags & VM_TIME_TRAP_RDTSC) { ctrl_area->instrs.RDTSC = 1; ctrl_area->svm_instrs.RDTSCP = 1; } else { ctrl_area->instrs.RDTSC = 0; ctrl_area->svm_instrs.RDTSCP = 0; - ctrl_area->TSC_OFFSET = v3_tsc_host_offset(&info->time_state); + + if (info->time_state.flags & VM_TIME_TSC_PASSTHROUGH) { + ctrl_area->TSC_OFFSET = 0; + } else { + ctrl_area->TSC_OFFSET = v3_tsc_host_offset(&info->time_state); + } } return 0; } @@ -549,17 +585,17 @@ int v3_svm_enter(struct guest_info * info) { uint64_t guest_cycles = 0; // Conditionally yield the CPU if the timeslice has expired - v3_yield_cond(info); + v3_yield_cond(info,-1); + + // Update timer devices after being in the VM before doing + // IRQ updates, so that any interrupts they raise get seen + // immediately. + v3_advance_time(info, NULL); + v3_update_timers(info); // disable global interrupts for vm state transition v3_clgi(); - // 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_advance_time(info); - v3_update_timers(info); - // Synchronize the guest state to the VMCB guest_state->cr0 = info->ctrl_regs.cr0; guest_state->cr2 = info->ctrl_regs.cr2; @@ -567,7 +603,17 @@ int v3_svm_enter(struct guest_info * info) { 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; + + // CR8 is now updated by read/writes and it contains the APIC TPR + // the V_TPR should be just the class part of that. + // This update is here just for completeness. We currently + // are ignoring V_TPR on all injections and doing the priority logivc + // in the APIC. + // guest_ctrl->guest_ctrl.V_TPR = ((info->ctrl_regs.apic_tpr) >> 4) & 0xf; + + //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; @@ -610,7 +656,6 @@ int v3_svm_enter(struct guest_info * info) { } #endif - v3_time_enter_vm(info); v3_svm_config_tsc_virtualization(info); //V3_Print("Calling v3_svm_launch\n"); @@ -632,8 +677,7 @@ int v3_svm_enter(struct guest_info * info) { v3_last_exit = (uint32_t)(guest_ctrl->exit_code); - // Immediate exit from VM time bookkeeping - v3_time_exit_vm(info, &guest_cycles); + v3_advance_time(info, &guest_cycles); info->num_exits++; @@ -650,7 +694,11 @@ int v3_svm_enter(struct guest_info * info) { info->ctrl_regs.cr4 = guest_state->cr4; info->dbg_regs.dr6 = guest_state->dr6; info->dbg_regs.dr7 = guest_state->dr7; - info->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR; + // + // We do not track this anymore + // V_TPR is ignored and we do the logic in the APIC + //info->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR; + // info->ctrl_regs.rflags = guest_state->rflags; info->ctrl_regs.efer = guest_state->efer; @@ -682,7 +730,12 @@ int v3_svm_enter(struct guest_info * info) { v3_stgi(); // Conditionally yield the CPU if the timeslice has expired - v3_yield_cond(info); + v3_yield_cond(info,-1); + + // This update timers is for time-dependent handlers + // if we're slaved to host time + v3_advance_time(info, NULL); + v3_update_timers(info); { int ret = v3_handle_svm_exit(info, exit_code, exit_info1, exit_info2); @@ -722,7 +775,7 @@ int v3_start_svm_guest(struct guest_info * info) { return 0; } - v3_yield(info); + v3_yield(info,-1); //PrintDebug("SVM core %u: still waiting for INIT\n", info->vcpu_id); } @@ -920,6 +973,11 @@ void v3_init_svm_cpu(int cpu_id) { // Setup the host state save area host_vmcbs[cpu_id] = (addr_t)V3_AllocPages(4); + if (!host_vmcbs[cpu_id]) { + PrintError("Failed to allocate VMCB\n"); + return; + } + /* 64-BIT-ISSUE */ // msr.e_reg.high = 0; //msr.e_reg.low = (uint_t)host_vmcb; @@ -1159,6 +1217,11 @@ void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) { ctrl_area->instrs.IOIO_PROT = 1; ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3); + + if (!ctrl_area->IOPM_BASE_PA) { + PrintError("Cannot allocate IO bitmap\n"); + return; + } { reg_ex_t tmp_reg;