Interrupt framework
authorRonald G. Minnich <rminnich@gmail.com>
Tue, 18 Aug 2015 20:41:33 +0000 (13:41 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 2 Nov 2015 23:24:25 +0000 (18:24 -0500)
Beginnings of interrupt framework. We're not doing x2apic or anything fancy.
We're going to let the timer fire and then kick off a given interrupt
in the guest.

Note that our attempts to do a gpf fail. It just fails to enter the guest
at all.

Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/vmm/intel/vmx.c
kern/include/ros/vmm.h
tests/vmm/vmrunkernel.c

index 915c3ec..a8a9e51 100644 (file)
@@ -890,6 +890,8 @@ vmx_dump_cpu(struct vmx_vcpu *vcpu)
        unsigned long flags;
 
        vmx_get_cpu(vcpu);
+       printk("GUEST_INTERRUPTIBILITY_INFO: 0x%08x\n",  vmcs_readl(GUEST_INTERRUPTIBILITY_INFO));
+       printk("VM_ENTRY_INTR_INFO_FIELD 0x%08x\n", vmcs_readl(VM_ENTRY_INTR_INFO_FIELD));
        vcpu->regs.tf_rip = vmcs_readl(GUEST_RIP);
        vcpu->regs.tf_rsp = vmcs_readl(GUEST_RSP);
        flags = vmcs_readl(GUEST_RFLAGS);
@@ -1677,6 +1679,14 @@ int vmx_launch(struct vmctl *v) {
                vmcs_writel(GUEST_RIP, v->regs.tf_rip);
                break;
        case RESUME:
+               /* If v->interrupt is non-zero, set it in the vmcs and
+                * zero it in the vmctl. Else set RIP.
+                */
+               if (v->interrupt) {
+                       printk("Set GUEST_INTERRUPTIBILITY_INFO to 0x%x\n", v->interrupt);
+                       vmcs_writel(GUEST_INTERRUPTIBILITY_INFO, v->interrupt);
+                       v->interrupt = 0;
+               }
                printd("RESUME\n");
                break;
        default: 
@@ -1733,7 +1743,16 @@ int vmx_launch(struct vmctl *v) {
                        if (vmx_handle_nmi_exception(vcpu)) 
                                vcpu->shutdown = SHUTDOWN_NMI_EXCEPTION;
                } else if (ret == EXIT_REASON_EXTERNAL_INTERRUPT) {
-                       printd("External interrupt\n");
+                       printk("External interrupt\n");
+                       vmx_dump_cpu(vcpu);
+                       vmx_get_cpu(vcpu);
+                       v->intrinfo1 = vmcs_readl(GUEST_INTERRUPTIBILITY_INFO);
+                       v->intrinfo2 = vmcs_readl(VM_ENTRY_INTR_INFO_FIELD);
+                       vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
+                       vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
+                       vmx_put_cpu(vcpu);
+                       printk("GUEST_INTERRUPTIBILITY_INFO: 0x%08x\n",  v->intrinfo1);
+                       printk("VM_ENTRY_INTR_INFO_FIELD 0x%08x\n", v->intrinfo2);
                        vcpu->shutdown = SHUTDOWN_UNHANDLED_EXIT_REASON;
                } else if (ret == EXIT_REASON_MSR_READ) {
                        printd("msr read\n");
@@ -1753,7 +1772,10 @@ int vmx_launch(struct vmctl *v) {
                } else {
                        printk("unhandled exit: reason 0x%x, exit qualification 0x%x\n",
                               ret, vmcs_read32(EXIT_QUALIFICATION));
-                       //vmx_dump_cpu(vcpu);
+                       if (ret & 0x80000000) {
+                               printk("entry failed.\n");
+                               vmx_dump_cpu(vcpu);
+                       }
                        vcpu->shutdown = SHUTDOWN_UNHANDLED_EXIT_REASON;
                }
 
index 76b2910..3017390 100644 (file)
@@ -31,6 +31,9 @@ struct vmctl {
        uint64_t shutdown;
        uint64_t ret_code;
        uint64_t core;
+       uint32_t interrupt;
+       uint32_t intrinfo1;
+       uint32_t intrinfo2;
        struct hw_trapframe regs;
 };
 
index ffbd4c1..efaa099 100644 (file)
@@ -326,8 +326,7 @@ int main(int argc, char **argv)
                        vmctl.shutdown = 0;
                        vmctl.gpa = 0;
                        vmctl.command = REG_ALL;
-               }
-               if (vmctl.shutdown == SHUTDOWN_UNHANDLED_EXIT_REASON) {
+               } else if (vmctl.shutdown == SHUTDOWN_UNHANDLED_EXIT_REASON) {
                        switch(vmctl.ret_code){
                        case  EXIT_REASON_VMCALL:
                                byte = vmctl.regs.tf_rdi;
@@ -335,6 +334,12 @@ int main(int argc, char **argv)
                                if (byte == '\n') printf("%c", 'V');
                                vmctl.regs.tf_rip += 3;
                                break;
+                       case EXIT_REASON_EXTERNAL_INTERRUPT:
+                               fprintf(stderr, "XINT\n");
+                               // Just inject a GPF for now. See what shakes.
+                               vmctl.interrupt = 0;//x8000080d;
+                               vmctl.command = RESUME;
+                               break;
                        default:
                                fprintf(stderr, "Don't know how to handle exit %d\n", vmctl.ret_code);
                                quit = 1;