bool handle_interrupts(struct Trapframe *tf, struct VmxGuestInfo *ginfo, uint32_t host_vector) { uint64_t rflags; uint32_t procbased_ctls_or; rflags = vmcs_read64(VMCS_GUEST_RFLAGS); if ( !(rflags & (0x1 << 9)) ) { //we have to wait the interrupt window open //get the interrupt info procbased_ctls_or = vmcs_read32( VMCS_32BIT_CONTROL_PROCESSOR_BASED_VMEXEC_CONTROLS); //disable the interrupt window exiting procbased_ctls_or |= VMCS_PROC_BASED_VMEXEC_CTL_INTRWINEXIT; vmcs_write32( VMCS_32BIT_CONTROL_PROCESSOR_BASED_VMEXEC_CONTROLS, procbased_ctls_or); } else { //revector the host vector to the guest vector vmcs_write32( VMCS_32BIT_CONTROL_VMENTRY_INTERRUPTION_INFO , host_vector); } return true; }
bool handle_wrmsr(struct Trapframe *tf, struct VmxGuestInfo *ginfo) { uint64_t msr = tf->tf_regs.reg_rcx; if(msr == EFER_MSR) { uint64_t cur_val, new_val; struct vmx_msr_entry *entry; bool r = find_msr_in_region(msr, ginfo->msr_guest_area, ginfo->msr_count, &entry); assert(r); cur_val = entry->msr_value; new_val = (tf->tf_regs.reg_rdx << 32)|tf->tf_regs.reg_rax; if(BIT(cur_val, EFER_LME) == 0 && BIT(new_val, EFER_LME) == 1) { // Long mode enable. uint32_t entry_ctls = vmcs_read32( VMCS_32BIT_CONTROL_VMENTRY_CONTROLS ); entry_ctls |= VMCS_VMENTRY_x64_GUEST; vmcs_write32( VMCS_32BIT_CONTROL_VMENTRY_CONTROLS, entry_ctls ); } entry->msr_value = new_val; tf->tf_rip += vmcs_read32(VMCS_32BIT_VMEXIT_INSTRUCTION_LENGTH); return true; } return false; }
bool handle_interrupt_window(struct Trapframe *tf, struct VmxGuestInfo *ginfo, uint32_t host_vector) { uint64_t rflags; uint32_t procbased_ctls_or; procbased_ctls_or = vmcs_read32( VMCS_32BIT_CONTROL_PROCESSOR_BASED_VMEXEC_CONTROLS ); //disable the interrupt window exiting procbased_ctls_or &= ~(VMCS_PROC_BASED_VMEXEC_CTL_INTRWINEXIT); vmcs_write32( VMCS_32BIT_CONTROL_PROCESSOR_BASED_VMEXEC_CONTROLS, procbased_ctls_or); //write back the host_vector, which can insert a virtual interrupt vmcs_write32( VMCS_32BIT_CONTROL_VMENTRY_INTERRUPTION_INFO , host_vector); return true; }