x86: vmm: Use a separate vector for posted IRQs
[akaros.git] / kern / src / kdebug.c
index 982fca5..8480c1e 100644 (file)
@@ -36,8 +36,7 @@ char *get_fn_name(uintptr_t pc)
        buf = kmalloc(name_len, 0);
        if (!buf)
                return 0;
-       strncpy(buf, found->name, name_len);
-       buf[name_len] = 0;
+       strlcpy(buf, found->name, name_len);
        return buf;
 }
 
@@ -111,7 +110,7 @@ static void __print_hdr(void)
                printk("IRQ       :");
        } else {
                assert(pcpui->cur_kthread);
-               if (pcpui->cur_kthread->is_ktask) {
+               if (is_ktask(pcpui->cur_kthread)) {
                        printk("%10s:", pcpui->cur_kthread->name);
                } else {
                        printk("PID %3d   :", pcpui->cur_proc ? pcpui->cur_proc->pid : 0);
@@ -202,31 +201,94 @@ void debug_addr_pid(int pid, unsigned long addr)
        proc_decref(p);
 }
 
-void backtrace_kframe(struct hw_trapframe *hw_tf)
+void print_backtrace_list(uintptr_t *pcs, size_t nr_pcs,
+                                                 void (*pfunc)(void *, const char *), void *opaque)
+{
+       char *func_name;
+       char bt_line[128];
+
+       for (size_t i = 0; i < nr_pcs; i++) {
+               func_name = get_fn_name(pcs[i]);
+               snprintf(bt_line, sizeof(bt_line), "#%02d [<%p>] in %s\n", i + 1,
+                                pcs[i], func_name);
+               pfunc(opaque, bt_line);
+               kfree(func_name);
+       }
+}
+
+static void printk_func(void *opaque, const char *str)
+{
+       printk("%s", str);
+}
+
+void backtrace(void)
+{
+       printk("Stack Backtrace on Core %d:\n", core_id());
+       gen_backtrace(&printk_func, NULL);
+}
+
+void backtrace_frame(uintptr_t eip, uintptr_t ebp)
+{
+       uintptr_t pcs[MAX_BT_DEPTH];
+       size_t nr_pcs = backtrace_list(eip, ebp, pcs, MAX_BT_DEPTH);
+
+       printk("\nBacktrace of kernel context on Core %d:\n", core_id());
+       print_backtrace_list(pcs, nr_pcs, &printk_func, NULL);
+}
+
+/* TODO: change debug_addr_proc() to allow print redirection like
+ * print_backtrace_list(). */
+void backtrace_user_frame(uintptr_t eip, uintptr_t ebp)
+{
+       uintptr_t pcs[MAX_BT_DEPTH];
+       size_t nr_pcs = backtrace_user_list(eip, ebp, pcs, MAX_BT_DEPTH);
+
+       printk("\nBacktrace of user context on Core %d:\n", core_id());
+       printk("\tOffsets only matter for shared libraries\n");
+       /* This formatting is consumed by scripts/bt-akaros.sh. */
+       for (int i = 0; i < nr_pcs; i++) {
+               printk("#%02d ", i + 1);
+               /* TODO: user backtraces all assume we're working on 'current' */
+               debug_addr_proc(current, pcs[i]);
+       }
+}
+
+void backtrace_hwtf(struct hw_trapframe *hw_tf)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
+
        pcpui->__lock_checking_enabled--;
-       printk("\nBacktrace of kernel context on Core %d:\n", core_id());
-       backtrace_frame(get_hwtf_pc(hw_tf), get_hwtf_fp(hw_tf));
+       if (in_kernel(hw_tf))
+               backtrace_frame(get_hwtf_pc(hw_tf), get_hwtf_fp(hw_tf));
+       else
+               backtrace_user_frame(get_hwtf_pc(hw_tf), get_hwtf_fp(hw_tf));
        pcpui->__lock_checking_enabled++;
 }
 
 void backtrace_user_ctx(struct proc *p, struct user_context *ctx)
 {
-       #define MAX_BT_DEPTH 20
-       uintptr_t pcs[MAX_BT_DEPTH];
-       size_t nr_pcs;
+       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
+       uintptr_t st_save;
 
        if (!ctx) {
                printk("Null user context!\n");
                return;
        }
-       nr_pcs = backtrace_list(get_user_ctx_pc(ctx), get_user_ctx_fp(ctx), pcs,
-                               MAX_BT_DEPTH);
-       printk("User context backtrace:\n");
-       printk("\tOffsets only matter for shared libraries\n");
-       for (int i = 0; i < nr_pcs; i++) {
-               printk("#%02d ", i + 1);
-               debug_addr_proc(p, pcs[i]);
-       }
+       st_save = switch_to(p);
+       pcpui->__lock_checking_enabled--;
+       backtrace_user_frame(get_user_ctx_pc(ctx), get_user_ctx_fp(ctx));
+       pcpui->__lock_checking_enabled++;
+       switch_back(p, st_save);
+}
+
+static spinlock_t __px_lock = SPINLOCK_INITIALIZER_IRQSAVE;
+void px_lock(void)
+{
+       if (printx_on)
+               spin_lock_irqsave(&__px_lock);
+}
+void px_unlock(void)
+{
+       if (printx_on)
+               spin_unlock_irqsave(&__px_lock);
 }