vmm: Attempt to backtrace the guest on error
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 5 Oct 2017 15:49:03 +0000 (11:49 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 5 Oct 2017 15:49:03 +0000 (11:49 -0400)
Build the guest with CONFIG_FRAME_POINTER.

You can backtrace it with the usual bt-akaros.sh.  You'll need to point
bt-akaros's BIN_PATH to your vmlinux.  Here's what I do:

BIN_PREFIX=PATH_TO_THE_REPO/linux-guest/ ~/scripts/bt-akaros.sh

e.g.

echo '#01 Addr 0xffffffff81480cda is in vmlinux at offset 0xffffffff81480cda
 #02 Addr 0xffffffff81480d0f is in vmlinux at offset 0xffffffff81480d0f
 #03 Addr 0xffffffff813f8e37 is in vmlinux at offset 0xffffffff813f8e37'
 | BIN_PREFIX=../linux-guest/ ~/scripts/bt-akaros.sh

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/vmm/include/vmm/util.h
user/vmm/util.c
user/vmm/vmx.c

index ccd1f8a..901bd51 100644 (file)
@@ -6,6 +6,9 @@
 
 #pragma once
 
+#include <vmm/sched.h>
+#include <stdio.h>
+
 /* Test for alignment, e.g. 2^6 */
 #define ALIGNED(p, a)  (!(((uintptr_t)(p)) & ((a)-1)))
 /* Aligns x up to the mask, e.g. (2^6 - 1) (round up if any mask bits are set)*/
@@ -21,3 +24,4 @@
 #define IS_PWR2(x) ((x) && !((x) & (x - 1)))
 
 ssize_t cat(char *file, void *where, size_t size);
+void backtrace_guest_thread(FILE *f, struct guest_thread *vm_thread);
index d63936c..eead7cb 100644 (file)
@@ -4,6 +4,7 @@
  * Utility functions. */
 
 #include <stdio.h>
+#include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
@@ -11,6 +12,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <vmm/util.h>
+#include <vmm/vmm.h>
 
 ssize_t cat(char *filename, void *where, size_t memsize)
 {
@@ -54,3 +56,29 @@ ssize_t cat(char *filename, void *where, size_t memsize)
        close(fd);
        return tot;
 }
+
+void backtrace_guest_thread(FILE *f, struct guest_thread *vm_thread)
+{
+       struct vm_trapframe *vm_tf = gth_to_vmtf(vm_thread);
+       uintptr_t guest_pc, guest_fp, host_fp;
+       uintptr_t frame[2];
+
+       guest_pc = vm_tf->tf_rip;
+       guest_fp = vm_tf->tf_rbp;
+
+       /* The BT should work for any code using frame pointers.  Most of the time,
+        * this will be vmlinux, and calling it that helps our backtrace.  This
+        * spits out the format that is parsed by bt-akaros.sh. */
+       fprintf(f, "Backtracing guest, vmlinux is assumed, but check addrs\n");
+       for (int i = 1; i < 30; i++) {
+               fprintf(f, "#%02d Addr %p is in vmlinux at offset %p\n", i, guest_pc,
+                       guest_pc);
+               if (!guest_fp)
+                       break;
+               if (gvatogpa(vm_thread, guest_fp, &host_fp))
+                       break;
+               memcpy(frame, (void*)host_fp, 2 * sizeof(uintptr_t));
+               guest_pc = frame[1];
+               guest_fp = frame[0];
+       }
+}
index c4d6452..afc0ee0 100644 (file)
@@ -19,6 +19,7 @@
 #include <vmm/virtio_ids.h>
 #include <ros/arch/vmx.h>
 #include <vmm/sched.h>
+#include <vmm/util.h>
 #include <ros/arch/mmu.h>
 #include <ros/arch/trapframe.h>
 
@@ -28,7 +29,7 @@ char *vmxexit[] = {
 
 void showstatus(FILE *f, struct guest_thread *vm_thread)
 {
-       struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);
+       struct vm_trapframe *vm_tf = gth_to_vmtf(vm_thread);
        int shutdown = vm_tf->tf_exit_reason;
        char *when = shutdown & VMX_EXIT_REASONS_FAILED_VMENTRY ? "entry" : "exit";
        shutdown &= ~VMX_EXIT_REASONS_FAILED_VMENTRY;
@@ -39,6 +40,7 @@ void showstatus(FILE *f, struct guest_thread *vm_thread)
                vm_tf->tf_guest_pcoreid, when, reason, shutdown,
                        vm_tf->tf_exit_reason);
        fprintf_vm_tf(f, vm_tf);
+       backtrace_guest_thread(f, vm_thread);
 }
 
 /* Convert a kernel guest virtual address to physical address.