bool handle_ioinstr(struct Trapframe *tf, struct VmxGuestInfo *ginfo) { static int port_iortc; uint64_t qualification = vmcs_read64(VMCS_VMEXIT_QUALIFICATION); int port_number = (qualification >> 16) & 0xFFFF; bool is_in = BIT(qualification, 3); bool handled = false; // handle reading physical memory from the CMOS. if(port_number == IO_RTC) { if(!is_in) { port_iortc = tf->tf_regs.reg_rax; handled = true; } } else if (port_number == IO_RTC + 1) { if(is_in) { if(port_iortc == NVRAM_BASELO) { tf->tf_regs.reg_rax = 640 & 0xFF; handled = true; } else if (port_iortc == NVRAM_BASEHI) { tf->tf_regs.reg_rax = (640 >> 8) & 0xFF; handled = true; } else if (port_iortc == NVRAM_EXTLO) { tf->tf_regs.reg_rax = ((ginfo->phys_sz / 1024) - 1024) & 0xFF; handled = true; } else if (port_iortc == NVRAM_EXTHI) { tf->tf_regs.reg_rax = (((ginfo->phys_sz / 1024) - 1024) >> 8) & 0xFF; handled = true; }
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_eptviolation(uint64_t *eptrt, struct VmxGuestInfo *ginfo) { uint64_t gpa = vmcs_read64(VMCS_64BIT_GUEST_PHYSICAL_ADDR); int r; if(gpa < 0xA0000 || (gpa >= 0x100000 && gpa < ginfo->phys_sz)) { // Allocate a new page to the guest. struct Page *p = page_alloc(0); if(!p) return false; p->pp_ref += 1; r = ept_map_hva2gpa(eptrt, page2kva(p), (void *)ROUNDDOWN(gpa, PGSIZE), __EPTE_FULL, 0); assert(r >= 0); // cprintf("EPT violation for gpa:%x mapped KVA:%x\n", gpa, page2kva(p)); return true; } else if (gpa >= CGA_BUF && gpa < CGA_BUF + PGSIZE) { // FIXME: This give direct access to VGA MMIO region. r = ept_map_hva2gpa(eptrt, (void *)(KERNBASE + CGA_BUF), (void *)CGA_BUF, __EPTE_FULL, 0); // cprintf("EPT violation for gpa:%x mapped KVA:%x\n", gpa,(KERNBASE + CGA_BUF)); assert(r >= 0); return true; } else if (gpa >= 0xF0000 && gpa < 0xF0000 + 0x10000) { r = ept_map_hva2gpa(eptrt, (void *)(KERNBASE + gpa), (void *)gpa, __EPTE_FULL, 0); assert(r >= 0); return true; } else if (gpa >= 0xfee00000) { r = ept_map_hva2gpa(eptrt, (void *)(KERNBASE + gpa), (void *)gpa, __EPTE_FULL, 0); assert(r >= 0); return true; } return false; }