Virtualization changes to handle X2APIC mode.
authorGanShun <ganshun@gmail.com>
Thu, 17 Dec 2015 22:43:30 +0000 (14:43 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 26 Feb 2016 23:54:48 +0000 (18:54 -0500)
These are changes to the vmm to allow it to handle the new MSR based
accesses. This includes allowing the direct msr access in vmx.c,
otherwise vmexiting will occur.

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

index 90ee085..536190a 100644 (file)
@@ -545,16 +545,16 @@ static const struct vmxec cb2ec = {
        .truemsr = MSR_IA32_VMX_PROCBASED_CTLS2,
 
        .must_be_1 = (SECONDARY_EXEC_ENABLE_EPT |
-                    SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
                     SECONDARY_EXEC_APIC_REGISTER_VIRT |
                     SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
+                    SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
                     SECONDARY_EXEC_WBINVD_EXITING),
 
        .must_be_0 = (
                     //SECONDARY_EXEC_APIC_REGISTER_VIRT |
                     //SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
                     SECONDARY_EXEC_DESCRIPTOR_EXITING |
-                    SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
+                    SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
                     SECONDARY_EXEC_ENABLE_VPID |
                     SECONDARY_EXEC_UNRESTRICTED_GUEST |
                     SECONDARY_EXEC_PAUSE_LOOP_EXITING |
@@ -1311,6 +1311,15 @@ int intel_vmm_init(void) {
        /* FIXME: do we need APIC virtualization (flexpriority?) */
 
        memset(msr_bitmap, 0xff, PAGE_SIZE);
+
+       /* The following MSRs are virtualized to the vapic page so there is no
+        * write or read from the actual MSR. */
+       memset((void *)msr_bitmap + INTEL_X2APIC_MSR_START, 0,
+              INTEL_X2APIC_MSR_LENGTH);
+       __vmx_disable_intercept_for_msr(msr_bitmap, MSR_LAPIC_EOI);
+       __vmx_disable_intercept_for_msr(msr_bitmap, MSR_LAPIC_TPR);
+       __vmx_disable_intercept_for_msr(msr_bitmap, MSR_LAPIC_SELF_IPI);
+
        memset(io_bitmap, 0xff, VMX_IO_BITMAP_SZ);
 
        /* These are the only MSRs that are not autoloaded and not intercepted */
index b305717..39371f8 100644 (file)
 
 #include <ros/arch/vmx.h>
 
+#define INTEL_MSR_WRITE_OFFSET                 2048
+
+#define INTEL_X2APIC_MSR_START                 0x100
+#define INTEL_X2APIC_MSR_LENGTH                        (0x40/8)
+
 int vmx_init(void);
 void vmx_exit(void);
 int intel_vmm_init(void);
index 808bad6..c0a1679 100644 (file)
@@ -284,6 +284,20 @@ struct emmsr emmsrs[] = {
 
        // TBD
        {MSR_IA32_TSC_DEADLINE, "MSR_IA32_TSC_DEADLINE", emsr_fakewrite},
+
+       // APIC Fakewrites. We should eventually transition this onto the vapic
+       // This will require userspace msr handling.
+       {MSR_LAPIC_INITIAL_COUNT, "MSR_LAPIC_INITIAL_COUNT", emsr_fakewrite},
+       {MSR_LAPIC_LVT_TIMER, "MSR_LAPIC_LVT_TIMER", emsr_fakewrite},
+       {MSR_LAPIC_LVT_PERFMON, "MSR_LAPIC_LVT_PERFMON", emsr_fakewrite},
+       {MSR_LAPIC_TPR, "MSR_LAPIC_TPR", emsr_fakewrite},
+       {MSR_LAPIC_SPURIOUS, "MSR_LAPIC_SPURIOUS", emsr_fakewrite},
+       {MSR_LAPIC_LVT_LINT0, "MSR_LAPIC_LVT_LINT0", emsr_fakewrite},
+       {MSR_LAPIC_LVT_LINT1, "MSR_LAPIC_LVT_LINT1", emsr_fakewrite},
+       {MSR_LAPIC_ESR, "MSR_LAPIC_ESR", emsr_fakewrite},
+       {MSR_LAPIC_LVT_ERROR_REG, "MSR_LAPIC_LVT_ERROR_REG", emsr_fakewrite},
+       {MSR_LAPIC_DIVIDE_CONFIG_REG, "MSR_LAPIC_DIVIDE_CONFIG_REG",
+        emsr_fakewrite},
 };
 
 /* this may be the only register that needs special handling.
index 07e325a..483ed97 100644 (file)
@@ -251,6 +251,15 @@ struct acpi_madt_local_apic Apic0 = {.header = {.type = ACPI_MADT_TYPE_LOCAL_API
                                     .processor_id = 0, .id = 0};
 struct acpi_madt_io_apic Apic1 = {.header = {.type = ACPI_MADT_TYPE_IO_APIC, .length = sizeof(struct acpi_madt_io_apic)},
                                  .id = 1, .address = 0xfec00000, .global_irq_base = 0};
+struct acpi_madt_local_x2apic X2Apic0 = {
+       .header = {
+               .type = ACPI_MADT_TYPE_LOCAL_X2APIC,
+               .length = sizeof(struct acpi_madt_local_x2apic)
+       },
+       .local_apic_id = 0,
+       .uid = 0
+};
+
 struct acpi_madt_interrupt_override isor[] = {
        /* I have no idea if it should be source irq 2, global 0, or global 2, source 0. Shit. */
        {.header = {.type = ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, .length = sizeof(struct acpi_madt_interrupt_override)},
@@ -333,13 +342,17 @@ static void set_posted_interrupt(int vector);
 #define ADDR                           BITOP_ADDR(addr)
 static inline int test_and_set_bit(int nr, volatile unsigned long *addr);
 
+static int timer_started;
+pthread_t timerthread_struct;
+
 void *timer_thread(void *arg)
 {
        while (1) {
                set_posted_interrupt(0xef);
                ros_syscall(SYS_vmm_poke_guest, 0, 0, 0, 0, 0, 0);
-               uthread_usleep(1);
+               uthread_usleep(100000);
        }
+       fprintf(stderr, "SENDING TIMER\n");
 }
 
 void *consout(void *arg)
@@ -418,8 +431,6 @@ void *consin(void *arg)
        int i;
        int num;
        //char c[1];
-       int timer_started = 0;
-       pthread_t timerthread_struct;
 
        if (debug) fprintf(stderr, "Spin on console being read, print num queues, halt\n");
 
@@ -462,15 +473,6 @@ void *consin(void *arg)
                virtio_mmio_set_vring_irq();
 
                ros_syscall(SYS_vmm_poke_guest, 0, 0, 0, 0, 0, 0);
-               /*if (!timer_started && mcp) {
-                       // Start up timer thread
-                       if (pthread_create(&timerthread_struct, NULL, timer_thread, NULL)) {
-                               fprintf(stderr, "pth_create failed for timer thread.");
-                               perror("pth_create");
-                       } else {
-                               timer_started = 1;
-                       }
-               }*/
        }
        fprintf(stderr, "All done\n");
        return NULL;
@@ -606,8 +608,8 @@ int main(int argc, char **argv)
        }
 
        memset(a_page, 0, 4096);
-       //((uint32_t *)a_page)[0x30/4] = 0x01060015;
-       ((uint32_t *)a_page)[0x30/4] = 0xDEADBEEF;
+       ((uint32_t *)a_page)[0x30/4] = 0x01060015;
+       //((uint32_t *)a_page)[0x30/4] = 0xDEADBEEF;
 
 
        argc--,argv++;
@@ -728,6 +730,8 @@ int main(int argc, char **argv)
        a += sizeof(Apic0);
        memmove(a, &Apic1, sizeof(Apic1));
        a += sizeof(Apic1);
+       memmove(a, &X2Apic0, sizeof(X2Apic0));
+       a += sizeof(X2Apic0);
        memmove(a, &isor, sizeof(isor));
        a += sizeof(isor);
        m->header.length = a - (void *)m;
@@ -884,6 +888,16 @@ int main(int argc, char **argv)
        if (debug)
                vapic_status_dump(stderr, (void *)gpci.vapic_addr);
 
+       if (0 && !timer_started && mcp) {
+               /* Start up timer thread */
+               if (pthread_create(&timerthread_struct, NULL, timer_thread, NULL)) {
+                       fprintf(stderr, "pth_create failed for timer thread.");
+                       perror("pth_create");
+               } else {
+                       timer_started = 1;
+               }
+       }
+
        while (1) {
 
                int c;