Apic msr exit handling added with timer thread support
authorGanShun <ganshun@gmail.com>
Thu, 24 Mar 2016 17:54:05 +0000 (10:54 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 28 Mar 2016 15:04:32 +0000 (11:04 -0400)
Added emsr_apic in user/vmm/vmxmsr to write all apic msr writes to the
vapic page. Started the timer thread using the vector linux writes to the
timer msr. We ignore the initial count as long as its not 0 and we just
inject a timer interrupt at 100hz.

Signed-off-by: GanShun <ganshun@gmail.com>
[touched up function declaration formatting]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/vmm/vmm.c
tests/vmm/vmrunkernel.c
user/vmm/include/vmm/vmm.h
user/vmm/vmxmsr.c

index c5f6aaf..bdbf530 100644 (file)
@@ -285,20 +285,6 @@ 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 011aaa4..1d06723 100644 (file)
@@ -338,14 +338,19 @@ 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)
 {
+       uint8_t vector;
+       uint32_t initial_count;
        while (1) {
-               set_posted_interrupt(0xef);
-               ros_syscall(SYS_vmm_poke_guest, 0, 0, 0, 0, 0, 0);
+               vector = ((uint32_t *)gpci.vapic_addr)[0x32] & 0xff;
+               initial_count = ((uint32_t *)gpci.vapic_addr)[0x38];
+               if (vector && initial_count) {
+                       set_posted_interrupt(vector);
+                       ros_syscall(SYS_vmm_poke_guest, 0, 0, 0, 0, 0, 0);
+               }
                uthread_usleep(100000);
        }
        fprintf(stderr, "SENDING TIMER\n");
@@ -558,7 +563,7 @@ int main(int argc, char **argv)
                                    " nohlt"
                                    " init=/bin/launcher"
                                    " lapic=notscdeadline"
-                                   " lapictimerfreq=1000"
+                                   " lapictimerfreq=1000000"
                                    " pit=none";
        char *cmdline_extra = "\0";
        char *cmdline;
@@ -585,6 +590,7 @@ int main(int argc, char **argv)
        void *coreboot_tables = (void *) 0x1165000;
        void *a_page;
        struct vm_trapframe *vm_tf;
+       uint64_t tsc_freq_khz;
 
        the_ball = uth_mutex_alloc();
        uth_mutex_lock(the_ball);
@@ -793,7 +799,9 @@ int main(int argc, char **argv)
        cmdline = a;
        a += 4096;
        bp->hdr.cmd_line_ptr = (uintptr_t) cmdline;
-       sprintf(cmdline, "%s %s", cmdline_default, cmdline_extra);
+       tsc_freq_khz = get_tsc_freq()/1000;
+       sprintf(cmdline, "%s tscfreq=%lld %s", cmdline_default, tsc_freq_khz,
+               cmdline_extra);
 
 
        /* Put the e820 memory region information in the boot_params */
@@ -890,13 +898,11 @@ int main(int argc, char **argv)
        if (debug)
                vapic_status_dump(stderr, (void *)gpci.vapic_addr);
 
-       if (0 && !timer_started && mcp) {
+       if (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;
                }
        }
 
@@ -1010,7 +1016,7 @@ int main(int argc, char **argv)
                        case EXIT_REASON_MSR_WRITE:
                        case EXIT_REASON_MSR_READ:
                                fprintf(stderr, "Do an msr\n");
-                               if (msrio((struct guest_thread *)vm_thread,
+                               if (msrio((struct guest_thread *)vm_thread, &gpci,
                                          vm_tf->tf_exit_reason)) {
                                        // uh-oh, msrio failed
                                        // well, hand back a GP fault which is what Intel does
index 6d1c162..ff0f615 100644 (file)
@@ -14,7 +14,8 @@ int decode(struct guest_thread *vm_thread, uint64_t *gpa, uint8_t *destreg,
            uint64_t **regp, int *store, int *size, int *advance);
 int io(struct guest_thread *vm_thread);
 void showstatus(FILE *f, struct guest_thread *vm_thread);
-int msrio(struct guest_thread *vm_thread, uint32_t opcode);
+int msrio(struct guest_thread *vm_thread, struct vmm_gpcore_init *gpci,
+          uint32_t opcode);
 int do_ioapic(struct guest_thread *vm_thread, uint64_t gpa,
               int destreg, uint64_t *regp, int store);
 
index b1c2a2f..45ccdc5 100644 (file)
@@ -253,16 +253,50 @@ static int emsr_fakewrite(struct guest_thread *vm_thread, struct emmsr *msr,
        return 0;
 }
 
-int
-msrio(struct guest_thread *vm_thread, uint32_t opcode) {
+static int emsr_apic(struct guest_thread *vm_thread,
+                     struct vmm_gpcore_init *gpci, uint32_t opcode)
+{
+       struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);
+       int apic_offset = vm_tf->tf_rcx & 0xff;
+       uint64_t value;
+
+       if (opcode == EXIT_REASON_MSR_READ) {
+               if (vm_tf->tf_rcx != MSR_LAPIC_ICR) {
+                       vm_tf->tf_rax = ((uint32_t *)(gpci->vapic_addr))[apic_offset];
+                       vm_tf->tf_rdx = 0;
+               } else {
+                       vm_tf->tf_rax = ((uint32_t *)(gpci->vapic_addr))[apic_offset];
+                       vm_tf->tf_rdx = ((uint32_t *)(gpci->vapic_addr))[apic_offset + 1];
+               }
+       } else {
+               if (vm_tf->tf_rcx != MSR_LAPIC_ICR)
+                       ((uint32_t *)(gpci->vapic_addr))[apic_offset] =
+                                                              (uint32_t)(vm_tf->tf_rax);
+               else {
+                       ((uint32_t *)(gpci->vapic_addr))[apic_offset] =
+                                                              (uint32_t)(vm_tf->tf_rax);
+                       ((uint32_t *)(gpci->vapic_addr))[apic_offset + 1] =
+                                                              (uint32_t)(vm_tf->tf_rdx);
+               }
+       }
+       return 0;
+}
+
+int msrio(struct guest_thread *vm_thread, struct vmm_gpcore_init *gpci,
+          uint32_t opcode)
+{
        int i;
        struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);
+
+       if (vm_tf->tf_rcx >= MSR_LAPIC_ID && vm_tf->tf_rcx < MSR_LAPIC_END)
+               return emsr_apic(vm_thread, gpci, opcode);
+
        for (i = 0; i < sizeof(emmsrs)/sizeof(emmsrs[0]); i++) {
-               if (emmsrs[i].reg != vm_tf->tf_cr3)
+               if (emmsrs[i].reg != vm_tf->tf_rcx)
                        continue;
                return emmsrs[i].f(vm_thread, &emmsrs[i], opcode);
        }
-       fprintf(stderr, "msrio for 0x%lx failed\n", vm_tf->tf_cr3);
+       fprintf(stderr, "msrio for 0x%lx failed\n", vm_tf->tf_rcx);
        return SHUTDOWN_UNHANDLED_EXIT_REASON;
 }