EOI virtualization and virtual APIC success.
authorGanShun <ganshun@gmail.com>
Tue, 22 Sep 2015 22:20:20 +0000 (15:20 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 2 Nov 2015 23:53:51 +0000 (18:53 -0500)
Reenabled APIC emulation for APIC reads that are not automatically virtualized by the hardware.
We are now able to inject multiple interrupts into the guest.

Signed-off-by: GanShun <ganshun@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/vmm/intel/vmx.c
kern/include/ros/vmx.h
tests/vmm/vmrunkernel.c
user/vmm/apic.c

index c63508b..74ea41b 100644 (file)
@@ -1814,7 +1814,7 @@ int vmx_launch(struct vmctl *v) {
 
                vmcs_writel(POSTED_INTR_DESC_ADDR, pir_physical);
                vmcs_writel(POSTED_INTR_DESC_ADDR_HIGH, pir_physical>>32);
-               printk("POSTED_INTR_DESC_ADDR_HIGH %ld", vmcs_readl(POSTED_INTR_DESC_ADDR_HIGH));
+               printk("POSTED_INTR_DESC_ADDR_HIGH %ld\n", vmcs_readl(POSTED_INTR_DESC_ADDR_HIGH));
                if (pir_physical & 0xfff) {
                        printk("Low order 12 bits of pir address is not 0, value: %p\n", pir_physical);
                }
@@ -1837,14 +1837,14 @@ int vmx_launch(struct vmctl *v) {
                vmcs_writel(APIC_ACCESS_ADDR_HIGH, apic_physical>>32);
 
                // Clear the EOI exit bitmap(Gan)
-               vmcs_writel(EOI_EXIT_BITMAP0, 0xFFFFFFFF);
-               vmcs_writel(EOI_EXIT_BITMAP0_HIGH, 0xFFFFFFFF);
-               vmcs_writel(EOI_EXIT_BITMAP1, 0xFFFFFFFF);
-               vmcs_writel(EOI_EXIT_BITMAP1_HIGH, 0xFFFFFFFF);
-               vmcs_writel(EOI_EXIT_BITMAP2, 0xFFFFFFFF);
-               vmcs_writel(EOI_EXIT_BITMAP2_HIGH, 0xFFFFFFFF);
-               vmcs_writel(EOI_EXIT_BITMAP3, 0xFFFFFFFF);
-               vmcs_writel(EOI_EXIT_BITMAP3_HIGH, 0xFFFFFFFF);
+               vmcs_writel(EOI_EXIT_BITMAP0, 0);
+               vmcs_writel(EOI_EXIT_BITMAP0_HIGH, 0);
+               vmcs_writel(EOI_EXIT_BITMAP1, 0);
+               vmcs_writel(EOI_EXIT_BITMAP1_HIGH, 0);
+               vmcs_writel(EOI_EXIT_BITMAP2, 0);
+               vmcs_writel(EOI_EXIT_BITMAP2_HIGH, 0);
+               vmcs_writel(EOI_EXIT_BITMAP3, 0);
+               vmcs_writel(EOI_EXIT_BITMAP3_HIGH, 0);
 
                printk("v->apic %p v->pir %p\n", (void *)v->vapic, (void *)v->pir);
                // fallthrough
@@ -1965,6 +1965,12 @@ int vmx_launch(struct vmctl *v) {
                        advance = 2;
                } else if (ret == EXIT_REASON_IO_INSTRUCTION) {
                        vcpu->shutdown = SHUTDOWN_UNHANDLED_EXIT_REASON;
+               } else if (ret == EXIT_REASON_APIC_WRITE) {
+                       printk("BEGIN APIC WRITE EXIT DUMP\n");
+                       vmx_dump_cpu(vcpu);
+                       printk("END APIC WRITE EXIT DUMP\n");
+               //} else if (ret == EXIT_REASON_APIC_ACCESS) {
+                       //vmx_dump_cpu(vcpu);
                } else {
                        printk("unhandled exit: reason 0x%x, exit qualification 0x%x\n",
                               ret, vmcs_read32(EXIT_QUALIFICATION));
index 674f6de..f7cd365 100644 (file)
@@ -326,6 +326,7 @@ enum vmcs_field {
 #define EXIT_REASON_EPT_MISCONFIG       49
 #define EXIT_REASON_WBINVD              54
 #define EXIT_REASON_XSETBV              55
+#define EXIT_REASON_APIC_WRITE         56
 #define EXIT_REASON_INVPCID             58
 
 #define VMX_EXIT_REASONS \
index a169f59..6046cb0 100644 (file)
@@ -280,6 +280,7 @@ void *consin(void *arg)
 
                // Send spurious for testing (Gan)
                set_posted_interrupt(0xE5);
+               virtio_mmio_set_vring_irq();
        }
        fprintf(stderr, "All done\n");
        return NULL;
@@ -341,7 +342,7 @@ static void pir_dump()
        unsigned long *pir_ptr = (unsigned long *)vmctl.pir;
        int i;
        fprintf(stderr, "-------Begin PIR dump-------\n");
-       for (i = 0; i < 16; i++){
+       for (i = 0; i < 8; i++){
                fprintf(stderr, "Byte %d: 0x%016x\n", i, pir_ptr[i]);
        }
        fprintf(stderr, "-------End PIR dump-------\n");
@@ -358,26 +359,16 @@ static void set_posted_interrupt(int vector)
        bit_offset = vector%(sizeof(unsigned long)*8);
        fprintf(stderr, "%s: Pre set PIR dump", __func__);
        pir_dump();
+       vapic_status_dump(stderr, (void *)vmctl.vapic);
        fprintf(stderr, "%s: Setting pir bit offset %d at 0x%p", __func__,
                        bit_offset, bit_vec);
        test_and_set_bit(bit_offset, bit_vec);
 
        // Set outstanding notification bit
-       bit_vec = pir + 4;
+       /*bit_vec = pir + 4;
        fprintf(stderr, "%s: Setting pir bit offset 0 at 0x%p", __func__,
                        bit_vec);
-       test_and_set_bit(0, bit_vec);
-
-       //bit_vec = pir + 7;
-       //fprintf(stderr, "%s: Setting pir bit offset 31 at 0x%p", __func__,
-       //              bit_vec);
-       //test_and_set_bit(31, bit_vec);
-
-       //for (i = 2; i < 3; i++){
-       //      for (j = 0; j < 1; j++){
-//                     test_and_set_bit(j, pir+i);
-//             }
-//     }
+       test_and_set_bit(0, bit_vec);*/
 
        pir_dump();
 }
@@ -707,8 +698,8 @@ fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
                                if (debug) fprintf(stderr, "REGP IS %16x:\n", *regp);
                        } else if ((gpa & 0xfee00000) == 0xfee00000) {
                                // until we fix our include mess, just put the proto here.
-                               int apic(struct vmctl *v, uint64_t gpa, int destreg, uint64_t *regp, int store);
-                               apic(&vmctl, gpa, regx, regp, store);
+                               //int apic(struct vmctl *v, uint64_t gpa, int destreg, uint64_t *regp, int store);
+                               //apic(&vmctl, gpa, regx, regp, store);
                        } else if ((gpa & 0xfec00000) == 0xfec00000) {
                                // until we fix our include mess, just put the proto here.
                                int do_ioapic(struct vmctl *v, uint64_t gpa, int destreg, uint64_t *regp, int store);
@@ -805,6 +796,31 @@ fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
                                //fprintf(stderr, "RIP %p, shutdown 0x%x\n", vmctl.regs.tf_rip, vmctl.shutdown);
                                //showstatus(stderr, &vmctl);
                                break;
+                       case EXIT_REASON_APIC_ACCESS:                           
+                               if (1 || debug)fprintf(stderr, "APIC READ EXIT\n");
+                               
+                               uint64_t gpa, *regp, val;
+                               uint8_t regx;
+                               int store, size;
+                               int advance;
+                               if (decode(&vmctl, &gpa, &regx, &regp, &store, &size, &advance)) {
+                                       fprintf(stderr, "RIP %p, shutdown 0x%x\n", vmctl.regs.tf_rip, vmctl.shutdown);
+                                       showstatus(stderr, &vmctl);
+                                       quit = 1;
+                                       break;
+                               }
+
+                               int apic(struct vmctl *v, uint64_t gpa, int destreg, uint64_t *regp, int store);
+                               apic(&vmctl, gpa, regx, regp, store);
+                               vmctl.regs.tf_rip += advance;
+                               if (debug) fprintf(stderr, "Advance rip by %d bytes to %p\n", advance, vmctl.regs.tf_rip);
+                               vmctl.shutdown = 0;
+                               vmctl.gpa = 0;
+                               vmctl.command = REG_ALL;
+                               break;
+                       case EXIT_REASON_APIC_WRITE:
+                               if (1 || debug)fprintf(stderr, "APIC WRITE EXIT\n");
+                               break;
                        default:
                                fprintf(stderr, "Don't know how to handle exit %d\n", vmctl.ret_code);
                                fprintf(stderr, "RIP %p, shutdown 0x%x\n", vmctl.regs.tf_rip, vmctl.shutdown);
index 6ec53e1..d189dc3 100644 (file)
@@ -168,6 +168,10 @@ int apic(struct vmctl *v, uint64_t gpa, int destreg, uint64_t *regp, int store)
        uint32_t offset = gpa & 0xfffff;
        /* basic sanity tests. */
        // TODO: Should be minus the base but FIXME
+
+       //fprintf(stderr, "WE SHOULD NEVER BE HERE: user/vmm/apic.c");
+       //exit(1);
+
        offset = gpa & 0xfffff;
        if (offset & 0xf) {
                DPRINTF("bad register offset; low nibl is non-zero\n");