VMMCP: Virtualized APIC is now working(sort of)
authorGan Shun Lim <ganshun@gmail.com>
Tue, 8 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)
Cleared SVI to acknowledge the delivery of the virtual interrupt. Enabled debug prints and added APIC memory dump.

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

index 8cb1b9c..8972863 100644 (file)
@@ -646,6 +646,7 @@ void sysenter_callwrapper(struct syscall *sysc, unsigned long count,
 void send_ipi(uint32_t os_coreid, uint8_t vector)
 {
        int hw_coreid = get_hw_coreid(os_coreid);
+       printk("Sending IPI with core: %d, interrupt: %d", os_coreid, vector);
        if (hw_coreid == -1) {
                panic("Unmapped OS coreid (OS %d)!\n", os_coreid);
                return;
index 38ff63d..83f353a 100644 (file)
@@ -60,6 +60,7 @@
 #define I_SMP_CALL3                            (I_SMP_CALL0 + 3)
 #define I_SMP_CALL4                            (I_SMP_CALL0 + 4)
 #define I_SMP_CALL_LAST                        I_SMP_CALL4
+#define I_VMMCP_POSTED                         (I_SMP_CALL_LAST + 1)
 #define I_TESTING                              237     /* Testing IPI (used in testing.c) */
 #define I_POKE_CORE                            238
 #define I_KERNEL_MSG                   239
index 386cf17..3572010 100644 (file)
@@ -312,7 +312,7 @@ IRQ_HANDLER(IRQ193, I_SMP_CALL1)
 IRQ_HANDLER(IRQ194, I_SMP_CALL2)
 IRQ_HANDLER(IRQ195, I_SMP_CALL3)
 IRQ_HANDLER(IRQ196, I_SMP_CALL4)
-IRQ_HANDLER(IRQ197, 229)
+IRQ_HANDLER(IRQ197, I_VMMCP_POSTED)
 IRQ_HANDLER(IRQ198, 230)
 IRQ_HANDLER(IRQ199, 231)
 IRQ_HANDLER(IRQ200, 232)
index 31e37bc..700a96e 100644 (file)
 
 #include "cpufeature.h"
 
+#include <trap.h>
+
+#include <smp.h>
+
 #define currentcpu (&per_cpu_info[core_id()])
 
 /* debug stuff == remove later. It's not even multivm safe. */
@@ -332,6 +336,8 @@ vmcs_write64(unsigned long field, uint64_t value)
        vmcs_writel(field, value);
 }
 
+void vapic_status_dump_kernel(void *vapic);
+
 /*
  * A note on Things You Can't Make Up.
  * or
@@ -506,10 +512,10 @@ static const struct vmxec pbec = {
 
        .must_be_1 = (PIN_BASED_EXT_INTR_MASK |
                     PIN_BASED_NMI_EXITING |
-                    PIN_BASED_VIRTUAL_NMIS),
-
-       .must_be_0 = (PIN_BASED_VMX_PREEMPTION_TIMER |
+                    PIN_BASED_VIRTUAL_NMIS |
                     PIN_BASED_POSTED_INTR),
+
+       .must_be_0 = (PIN_BASED_VMX_PREEMPTION_TIMER),
 };
 
 static const struct vmxec cbec = {
@@ -517,7 +523,7 @@ static const struct vmxec cbec = {
        .msr = MSR_IA32_VMX_PROCBASED_CTLS,
        .truemsr = MSR_IA32_VMX_TRUE_PROCBASED_CTLS,
 
-       .must_be_1 = (CPU_BASED_MWAIT_EXITING |
+       .must_be_1 = (//CPU_BASED_MWAIT_EXITING |
                        CPU_BASED_HLT_EXITING |
                     CPU_BASED_TPR_SHADOW |
                     CPU_BASED_RDPMC_EXITING |
@@ -528,6 +534,7 @@ static const struct vmxec cbec = {
                     CPU_BASED_ACTIVATE_SECONDARY_CONTROLS),
 
        .must_be_0 = (
+                       CPU_BASED_MWAIT_EXITING |
                        CPU_BASED_VIRTUAL_INTR_PENDING |
                     CPU_BASED_INVLPG_EXITING |
                     CPU_BASED_USE_TSC_OFFSETING |
@@ -599,12 +606,16 @@ static const struct vmxec vmexit = {
        .truemsr = MSR_IA32_VMX_TRUE_EXIT_CTLS,
 
        .must_be_1 = (VM_EXIT_SAVE_DEBUG_CONTROLS |     /* can't set to 0 */
-                                VM_EXIT_SAVE_IA32_EFER | VM_EXIT_LOAD_IA32_EFER | VM_EXIT_HOST_ADDR_SPACE_SIZE),       /* 64 bit */
+                                VM_EXIT_ACK_INTR_ON_EXIT |
+                                VM_EXIT_SAVE_IA32_EFER | 
+                               VM_EXIT_LOAD_IA32_EFER | 
+                               VM_EXIT_HOST_ADDR_SPACE_SIZE),  /* 64 bit */
 
        .must_be_0 = (VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |
-                                VM_EXIT_ACK_INTR_ON_EXIT |
+                               // VM_EXIT_ACK_INTR_ON_EXIT |
                                 VM_EXIT_SAVE_IA32_PAT |
-                                VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_VMX_PREEMPTION_TIMER),
+                                VM_EXIT_LOAD_IA32_PAT | 
+                               VM_EXIT_SAVE_VMX_PREEMPTION_TIMER),
 };
 
 static void
@@ -913,6 +924,7 @@ vmx_dump_cpu(struct vmx_vcpu *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));
        printk("EXIT_QUALIFICATION 0x%08x\n", vmcs_read32(EXIT_QUALIFICATION));
+       printk("VM_EXIT_REASON 0x%08x\n", vmcs_read32(VM_EXIT_REASON));
        vcpu->regs.tf_rip = vmcs_readl(GUEST_RIP);
        vcpu->regs.tf_rsp = vmcs_readl(GUEST_RSP);
        flags = vmcs_readl(GUEST_RFLAGS);
@@ -1044,6 +1056,9 @@ vmx_setup_initial_guest_state(void)
        vmcs_write32(GUEST_PENDING_DBG_EXCEPTIONS, 0);
        vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);      /* 22.2.1 */
+
+       /* Initialize posted interrupt notification vector */
+       vmcs_write16(POSTED_NOTIFICATION_VEC, I_VMMCP_POSTED);
        }
 
 static void __vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
@@ -1685,15 +1700,40 @@ static void vmx_set_rvi(int vector)
        uint8_t old;
 
        status = vmcs_read16(GUEST_INTR_STATUS);
+       printk("%s: Status is %04x", __func__, status);
        old = (uint8_t)status & 0xff;
        if ((uint8_t)vector != old) {
                status &= ~0xff;
                status |= (uint8_t)vector;
                printk("%s: SET 0x%x\n", __func__, status);
+
+               // Clear SVI
+               status &= 0xff;
                vmcs_write16(GUEST_INTR_STATUS, status);
        }
+       printk("%s: Status is %04x after RVI", __func__,
+                       vmcs_read16(GUEST_INTR_STATUS));
 }
 
+/*
+static void vmx_set_posted_interrupt(int vector)
+{
+       unsigned long *bit_vec;
+       unsigned long *pir = vmcs_readl(POSTED_INTR_DESC_ADDR_HIGH);
+       pir = pir << 32;
+       pir |= vmcs_readl(POSTED_INTR_DESC_ADDR);
+
+       // Move to the correct location to set our bit.
+       bit_vec = pir + vector/32;
+       test_and_set_bit(vector%32, bit_vec);
+
+       // Set outstanding notification bit
+       bit_vec = pir + 8;
+       test_and_set_bit(0, bit_vec);
+}
+
+*/
+
 /**
  * vmx_launch - the main loop for a VMX Dune process
  * @conf: the launch configuration
@@ -1704,6 +1744,9 @@ int vmx_launch(struct vmctl *v) {
        int errors = 0;
        int advance;
        int interrupting = 0;
+       uintptr_t pir_kva, vapic_kva;
+       uint64_t pir_physical, vapic_physical;
+       struct proc * current_proc = current;
 
        /* TODO: dirty hack til we have VMM contexts */
        vcpu = current->vmm.guest_pcores[0];
@@ -1730,12 +1773,39 @@ int vmx_launch(struct vmctl *v) {
                printd("REG_RSP_RIP_CR3\n");
                vmcs_writel(GUEST_RSP, v->regs.tf_rsp);
                vmcs_writel(GUEST_CR3, v->cr3);
-               vmcs_writel(POSTED_INTR_DESC_ADDR, v->pir);
-               vmcs_writel(POSTED_INTR_DESC_ADDR_HIGH, v->pir>>32);
-               vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, v->vapic);
-               vmcs_writel(VIRTUAL_APIC_PAGE_ADDR_HIGH, v->vapic>>32);
+
+               pir_kva = uva2kva(current_proc, (void *)v->pir);
+               pir_physical = (uint64_t)PADDR(pir_kva);
+
+               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));
+               if (pir_physical & 0xfff) {
+                       printk("Low order 12 bits of pir address is not 0, value: %p\n", pir_physical);
+               }
+
+               vapic_kva = uva2kva(current_proc, (void *)v->vapic);
+               vapic_physical = (uint64_t)PADDR(vapic_kva);
+
+               vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, vapic_physical);
+               vmcs_writel(VIRTUAL_APIC_PAGE_ADDR_HIGH, vapic_physical>>32);
+               if (vapic_physical & 0xfff) {
+                       printk("Low order 12 bits of vapic address is not 0, value: %p\n", vapic_physical);
+               }
+
                vmcs_writel(APIC_ACCESS_ADDR, 0xfee00000);
                vmcs_writel(APIC_ACCESS_ADDR_HIGH, 0);
+
+               // Clear the EOI exit bitmap(Gan)
+               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
        case REG_RIP:
@@ -1752,7 +1822,12 @@ int vmx_launch(struct vmctl *v) {
                if (v->interrupt) {
                        printk("Set VM_ENTRY_INFTR_INFO_FIELD to 0x%x\n", v->interrupt);
                        //vmcs_writel(VM_ENTRY_INTR_INFO_FIELD, v->interrupt);
-                       vmx_set_rvi(v->interrupt);
+                       //vapic_status_dump_kernel((void *)v->vapic);
+                       
+                       //Not using this because we still need a VMExit.
+                       //vmx_set_rvi(v->interrupt);
+
+                       //vapic_status_dump_kernel((void *)v->vapic);
                        v->interrupt = 0;
                        interrupting = 1;
                }
@@ -1779,13 +1854,21 @@ int vmx_launch(struct vmctl *v) {
                disable_irq();
                //dumpmsrs();
                ret = vmx_run_vcpu(vcpu);
+               
                //dumpmsrs();
                enable_irq();
                v->intrinfo1 = vmcs_readl(GUEST_INTERRUPTIBILITY_INFO);
-               v->intrinfo2 = vmcs_readl(VM_ENTRY_INTR_INFO_FIELD);
+               v->intrinfo2 = vmcs_readl(VM_EXIT_INTR_INFO);
                vmx_put_cpu(vcpu);
+
                if (interrupting) {
-                       printk("POST INTERRUPT: ");
+                       printk("POST INTERRUPT: \n");
+                       unsigned long cr8val;
+                       asm volatile("mov %%cr8,%0" : "=r" (cr8val));
+                       printk("CR8 Value: 0x%08x", cr8val);
+                       
+                       printk("%s: Status is %04x\n", __func__,
+                                       vmcs_read16(GUEST_INTR_STATUS));
                        vmx_dump_cpu(vcpu);
                }
 
@@ -1823,9 +1906,9 @@ int vmx_launch(struct vmctl *v) {
                                vcpu->shutdown = SHUTDOWN_NMI_EXCEPTION;
                } else if (ret == EXIT_REASON_EXTERNAL_INTERRUPT) {
                        printk("External interrupt\n");
-                       //vmx_dump_cpu(vcpu);
+                       vmx_dump_cpu(vcpu);
                        printk("GUEST_INTERRUPTIBILITY_INFO: 0x%08x,",  v->intrinfo1);
-                       printk("VM_ENTRY_INTR_INFO_FIELD 0x%08x,", v->intrinfo2);
+                       printk("VM_EXIT_INFO_FIELD 0x%08x,", v->intrinfo2);
                        printk("rflags 0x%x\n", vcpu->regs.tf_rflags);
                        vcpu->shutdown = SHUTDOWN_UNHANDLED_EXIT_REASON;
                } else if (ret == EXIT_REASON_MSR_READ) {
@@ -2097,3 +2180,21 @@ int intel_vmm_pcpu_init(void) {
        vmx_enable();
        return 0;
 }
+
+
+void vapic_status_dump_kernel(void *vapic)
+{
+       uint32_t *p = (uint32_t *)vapic;
+       int i;
+       printk("-- BEGIN KERNEL APIC STATUS DUMP --\n");
+       for (i = 0x100/sizeof(*p); i < 0x180/sizeof(*p); i+=4) {
+               printk("VISR : 0x%x: 0x%08x\n", i, p[i]);
+       }
+       for (i = 0x200/sizeof(*p); i < 0x280/sizeof(*p); i+=4) {
+               printk("VIRR : 0x%x: 0x%08x\n", i, p[i]);
+       }
+       i = 0x0B0/sizeof(*p);
+       printk("EOI FIELD : 0x%x, 0x%08x\n", i, p[i]);
+
+       printk("-- END KERNEL APIC STATUS DUMP --\n");
+}
index 142fec9..6d95351 100644 (file)
 #include <ros/vmm.h>
 #include "intel/vmx.h"
 #include "vmm.h"
+#include <trap.h>
 
 /* TODO: have better cpuid info storage and checks */
 bool x86_supports_vmx = FALSE;
 
+static void vmmcp_posted_handler(struct hw_trapframe *hw_tf, void *data);
+
 /* Figure out what kind of CPU we are on, and if it supports any reasonable
  * virtualization. For now, if we're not some sort of newer intel, don't
  * bother. This does all cores. Again, note, we make these decisions at runtime,
@@ -36,6 +39,9 @@ void vmm_init(void)
        ret = intel_vmm_init();
        if (! ret) {
                printd("intel_vmm_init worked\n");
+
+               //Register I_VMMCP_POSTED IRQ
+               register_irq(I_VMMCP_POSTED, vmmcp_posted_handler, NULL, MKBUS(BusLAPIC, 0, 0, 0));
                x86_supports_vmx = TRUE;
                return;
        }
@@ -45,6 +51,11 @@ void vmm_init(void)
        return;
 }
 
+static void vmmcp_posted_handler(struct hw_trapframe *hw_tf, void *data)
+{
+       printk("%s\n", __func__);
+}
+
 void vmm_pcpu_init(void)
 {
        if (!x86_supports_vmx)
index 15034cf..674f6de 100644 (file)
 /* VMCS Encodings */
 enum vmcs_field {
        VIRTUAL_PROCESSOR_ID            = 0x00000000,
+       POSTED_NOTIFICATION_VEC         = 0x00000002,
        GUEST_ES_SELECTOR               = 0x00000800,
        GUEST_CS_SELECTOR               = 0x00000802,
        GUEST_SS_SELECTOR               = 0x00000804,
index 7f1f3e0..9630419 100644 (file)
@@ -24,6 +24,9 @@
 #include <vmm/virtio_config.h>
 
 int msrio(struct vmctl *vcpu, uint32_t opcode);
+
+struct vmctl vmctl;
+
 /* Kind of sad what a total clusterf the pc world is. By 1999, you could just scan the hardware 
  * and work it out. But 2005, that was no longer possible. How sad. 
  * so we have to fake acpi to make it all work. !@#$!@#$#.
@@ -152,6 +155,19 @@ int resumeprompt = 0;
 //             vring_new_virtqueue(0, 512, 8192, 0, inpages, NULL, NULL, "test");
 uint64_t virtio_mmio_base = 0x100000000;
 
+void vapic_status_dump(FILE *f, void *vapic);
+static void set_posted_interrupt(int vector);
+
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
+#error "Get a gcc newer than 4.4.0"
+#else
+#define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
+#endif
+
+#define LOCK_PREFIX "lock "
+#define ADDR                           BITOP_ADDR(addr)
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr);
+
 void *consout(void *arg)
 {
        char *line, *consline, *outline;
@@ -172,6 +188,7 @@ void *consout(void *arg)
        }
        
        for(num = 0;;num++) {
+               //int debug = 1;
                /* host: use any buffers we should have been sent. */
                head = wait_for_vq_desc(v, iov, &outlen, &inlen);
                if (debug)
@@ -182,6 +199,9 @@ void *consout(void *arg)
                for(i = 0; i < outlen; i++) {
                        num++;
                        int j;
+                       if (debug) {
+                               fprintf(stderr, "CCC: IOV length is %d\n", iov[i].length);
+                       }
                        for (j = 0; j < iov[i].length; j++)
                                printf("%c", ((char *)iov[i].v)[j]);
                }
@@ -242,7 +262,8 @@ void *consin(void *arg)
                        if (fgets(consline, 4096-256, stdin) == NULL) {
                                exit(0);
                        } 
-                       if (debug) fprintf(stderr, "GOT A LINE:%s:\n", consline);
+                       if (debug) fprintf(stderr, "CONSIN: GOT A LINE:%s:\n", consline);
+                       if (debug) fprintf(stderr, "CONSIN: OUTLEN:%d:\n", outlen);
                        if (strlen(consline) < 3 && consline[0] == 'q' ) {
                                quit = 1;
                                break;
@@ -256,6 +277,9 @@ void *consin(void *arg)
                add_used(v, head, outlen+inlen);
                consdata = 1;
                if (debug) fprintf(stderr, "DONE call add_used\n");
+
+               // Send spurious for testing (Gan)
+               set_posted_interrupt(0xE5);
        }
        fprintf(stderr, "All done\n");
        return NULL;
@@ -302,6 +326,62 @@ static void gencsum(uint8_t *target, void *data, int len)
        fprintf(stderr, "Cmoputed is %02x\n", *target);
 }
 
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+       int oldbit;
+
+       asm volatile(LOCK_PREFIX "bts %2,%1\n\t"
+                    "sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
+
+       return oldbit;
+}
+
+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++){
+               fprintf(stderr, "Byte %d: 0x%016x\n", i, pir_ptr[i]);
+       }
+       fprintf(stderr, "-------End PIR dump-------\n");
+}
+
+static void set_posted_interrupt(int vector)
+{
+       unsigned long *bit_vec;
+       int bit_offset;
+       int i, j;
+       unsigned long *pir = (unsigned long *)vmctl.pir;
+       // Move to the correct location to set our bit.
+       bit_vec = pir + vector/(sizeof(unsigned long)*8);
+       bit_offset = vector%(sizeof(unsigned long)*8);
+       fprintf(stderr, "%s: Pre set PIR dump", __func__);
+       pir_dump();
+       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;
+       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);
+//             }
+//     }
+
+       pir_dump();
+}
+
 int main(int argc, char **argv)
 {
        uint64_t *p64;
@@ -313,7 +393,7 @@ int main(int argc, char **argv)
        uint64_t virtiobase = 0x100000000ULL;
        // lowmem is a bump allocated pointer to 2M at the "physbase" of memory 
        void *lowmem = (void *) 0x1000000;
-       struct vmctl vmctl;
+       //struct vmctl vmctl;
        int amt;
        int vmmflags = 0; // Disabled probably forever. VMM_VMCALL_PRINTF;
        uint64_t entry = 0x1200000, kerneladdress = 0x1200000;
@@ -325,6 +405,7 @@ int main(int argc, char **argv)
        int i;
        uint8_t csum;
        void *coreboot_tables = (void *) 0x1165000;
+       void *a_page;
 fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
 
        // mmap is not working for us at present.
@@ -339,6 +420,23 @@ fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
        //low4k[0x40e] = 0;
        //low4k[0x40f] = 0xe0;
 
+       //Place mmap(Gan)
+       a_page = mmap((void *)0xfee00000, PGSIZE, PROT_READ | PROT_WRITE,
+                             MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+       fprintf(stderr, "a_page mmap pointer %p", a_page);
+
+       if (a_page == (void *) -1) {
+               perror("Could not mmap APIC");
+               exit(1);
+       }
+       if (((uint64_t)a_page & 0xfff) != 0) {
+               perror("APIC page mapping is not page aligned");
+               exit(1);
+       }
+
+       memset(a_page, 0, 4096);
+       ((uint32_t *)a_page)[0x30/4] = 0x01060015;
+
        if (fd < 0) {
                perror("#cons/sysctl");
                exit(1);
@@ -481,12 +579,16 @@ fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
 
        a = (void *)(((unsigned long)a + 0xfff) & ~0xfff);
        vmctl.pir = (uint64_t) a;
+       memset(a, 0, 4096);
        a += 4096;
-       vmctl.vapic = (uint64_t) a;
+       //vmctl.vapic = (uint64_t) a;
+       vmctl.vapic = (uint64_t) a_page;        
+       memset(a, 0, 4096);
+       //((uint32_t *)a)[0x30/4] = 0x01060015;
        p64 = a;
        // set up apic values? do we need to?
        // qemu does this.
-       ((uint8_t *)a)[4] = 1;
+       //((uint8_t *)a)[4] = 1;
        a += 4096;
 
        if (ros_syscall(SYS_setup_vmm, nr_gpcs, vmmflags, 0, 0, 0, 0) != nr_gpcs) {
@@ -556,8 +658,13 @@ fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
        }
        fprintf(stderr, "threads started\n");
        fprintf(stderr, "Writing command :%s:\n", cmd);
+       
+       vapic_status_dump(stderr, (void *)vmctl.vapic);
 
        ret = write(fd, &vmctl, sizeof(vmctl));
+
+       vapic_status_dump(stderr, (void *)vmctl.vapic);
+
        if (ret != sizeof(vmctl)) {
                perror(cmd);
        }
@@ -596,6 +703,8 @@ fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
                                if (debug) fprintf(stderr, "DO SOME VIRTIO\n");
                                // Lucky for us the various virtio ops are well-defined.
                                virtio_mmio(&vmctl, gpa, regx, regp, store);
+                               if (debug) fprintf(stderr, "store is %d:\n", store);
+                               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);
@@ -635,6 +744,7 @@ fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
                        case EXIT_REASON_EXTERNAL_INTERRUPT:
                                //debug = 1;
                                fprintf(stderr, "XINT 0x%x 0x%x\n", vmctl.intrinfo1, vmctl.intrinfo2);
+                               pir_dump();
                                vmctl.command = RESUME;
                                break;
                        case EXIT_REASON_IO_INSTRUCTION:
@@ -669,6 +779,7 @@ fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
                                while (!consdata)
                                        ;
                                //debug = 1;
+                               vapic_status_dump(stderr, (void *)vmctl.vapic);
                                if (debug)fprintf(stderr, "Resume with consdata ...\n");
                                vmctl.regs.tf_rip += 3;
                                ret = write(fd, &vmctl, sizeof(vmctl));
@@ -708,14 +819,10 @@ fprintf(stderr, "%p %p %p %p\n", PGSIZE, PGSHIFT, PML1_SHIFT, PML1_PTE_REACH);
                if (consdata) {
                        if (debug) fprintf(stderr, "inject an interrupt\n");
                        fprintf(stderr, "XINT 0x%x 0x%x\n", vmctl.intrinfo1, vmctl.intrinfo2);
-                       if (1 || (vmctl.intrinfo1 == 0) && (vmctl.regs.tf_rflags & 0x200)) {
-                               vmctl.interrupt = 0x80000000 | virtioirq;
-                               virtio_mmio_set_vring_irq();
-                               consdata = 0;
-                               //debug = 1;
-                       } else { 
-                               fprintf(stderr, "Can't inject interrupt: IF is clear\n");
-                       }
+                       vmctl.interrupt = 0x80000000 | virtioirq;
+                       virtio_mmio_set_vring_irq();
+                       consdata = 0;
+                       //debug = 1;
                        vmctl.command = RESUME;
                }
                if (debug) fprintf(stderr, "NOW DO A RESUME\n");
index ab6e33b..6ec53e1 100644 (file)
@@ -27,6 +27,7 @@
 #include <vmm/virtio_ids.h>
 #include <vmm/virtio_config.h>
 
+
 #define APIC_CONFIG 0x100
 
 int debug_apic = 1;
@@ -187,3 +188,20 @@ int apic(struct vmctl *v, uint64_t gpa, int destreg, uint64_t *regp, int store)
        }
 
 }
+
+void vapic_status_dump(FILE *f, void *vapic)
+{
+       uint32_t *p = (uint32_t *)vapic;
+       int i;
+       fprintf(f, "-- BEGIN APIC STATUS DUMP --\n");
+       for (i = 0x100/sizeof(*p); i < 0x180/sizeof(*p); i+=4) {
+               fprintf(f, "VISR : 0x%x: 0x%08x\n", i, p[i]);
+       }
+       for (i = 0x200/sizeof(*p); i < 0x280/sizeof(*p); i+=4) {
+               fprintf(f, "VIRR : 0x%x: 0x%08x\n", i, p[i]);
+       }
+       i = 0x0B0/sizeof(*p);
+       fprintf(f, "EOI FIELD : 0x%x, 0x%08x\n", i, p[i]);
+
+       fprintf(f, "-- END APIC STATUS DUMP --\n");
+}