Add support for attempting returns from panic
[akaros.git] / kern / src / trap.c
index e3eabfe..5e3824d 100644 (file)
@@ -17,11 +17,22 @@ static void print_unhandled_trap(struct proc *p, struct user_context *ctx,
                                  unsigned int trap_nr, unsigned int err,
                                  unsigned long aux)
 {
+       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
+       uint32_t vcoreid = pcpui->owning_vcoreid;
+       struct preempt_data *vcpd = &p->procdata->vcore_preempt_data[vcoreid];
+       static spinlock_t print_trap_lock = SPINLOCK_INITIALIZER;
+
+       spin_lock(&print_trap_lock);
+       if (!proc_is_vcctx_ready(p))
+               printk("Unhandled user trap from early SCP\n");
+       else if (vcpd->notif_disabled)
+               printk("Unhandled user trap in vcore context from VC %d\n", vcoreid);
        print_user_ctx(ctx);
        printk("err 0x%x (for PFs: User 4, Wr 2, Rd 1), aux %p\n", err, aux);
        debug_addr_proc(p, get_user_ctx_pc(ctx));
        print_vmrs(p);
        backtrace_user_ctx(p, ctx);
+       spin_unlock(&print_trap_lock);
 }
 
 /* Traps that are considered normal operations. */
@@ -38,67 +49,49 @@ static void printx_unhandled_trap(struct proc *p, struct user_context *ctx,
                print_unhandled_trap(p, ctx, trap_nr, err, aux);
 }
 
-void reflect_unhandled_trap(unsigned int trap_nr, unsigned int err,
-                            unsigned long aux)
+/* Helper, reflects the current context back to the 2LS.  Returns 0 on success,
+ * -1 on failure. */
+int reflect_current_context(void)
 {
        uint32_t coreid = core_id();
        struct per_cpu_info *pcpui = &per_cpu_info[coreid];
        struct proc *p = pcpui->cur_proc;
        uint32_t vcoreid = pcpui->owning_vcoreid;
        struct preempt_data *vcpd = &p->procdata->vcore_preempt_data[vcoreid];
-       struct hw_trapframe *hw_tf = &pcpui->cur_ctx->tf.hw_tf;
-       assert(p);
-       assert(pcpui->cur_ctx && (pcpui->cur_ctx->type == ROS_HW_CTX));
-       if (!proc_is_vcctx_ready(p)) {
-               printk("Unhandled user trap from early SCP\n");
-               goto error_out;
-       }
-       if (vcpd->notif_disabled) {
-               printk("Unhandled user trap in vcore context from VC %d\n", vcoreid);
-               goto error_out;
-       }
-       printx_unhandled_trap(p, pcpui->cur_ctx, trap_nr, err, aux);
-       /* need to store trap_nr, err code, and aux into the tf so that it can get
-        * extracted on the other end, and we need to flag the TF in some way so we
-        * can tell it was reflected.  for example, on a PF, we need some number (14
-        * on x86), the prot violation (write, read, etc), and the virt addr (aux).
-        * parlib will know how to extract this info. */
-       __arch_reflect_trap_hwtf(hw_tf, trap_nr, err, aux);
+
+       assert(pcpui->cur_proc == pcpui->owning_proc);
+       if (!proc_is_vcctx_ready(p))
+               return -1;
+       if (vcpd->notif_disabled)
+               return -1;
        /* the guts of a __notify */
        vcpd->notif_disabled = TRUE;
        copy_current_ctx_to(&vcpd->uthread_ctx);
        memset(pcpui->cur_ctx, 0, sizeof(struct user_context));
        proc_init_ctx(pcpui->cur_ctx, vcoreid, vcpd->vcore_entry,
                      vcpd->vcore_stack, vcpd->vcore_tls_desc);
-       return;
-error_out:
-       print_unhandled_trap(p, pcpui->cur_ctx, trap_nr, err, aux);
-       proc_destroy(p);
+       return 0;
 }
 
-uintptr_t get_user_ctx_pc(struct user_context *ctx)
+void reflect_unhandled_trap(unsigned int trap_nr, unsigned int err,
+                            unsigned long aux)
 {
-       switch (ctx->type) {
-               case ROS_HW_CTX:
-                       return get_hwtf_pc(&ctx->tf.hw_tf);
-               case ROS_SW_CTX:
-                       return get_swtf_pc(&ctx->tf.sw_tf);
-               default:
-                       warn("Bad context type %d for ctx %p\n", ctx->type, ctx);
-                       return 0;
-       }
-}
+       uint32_t coreid = core_id();
+       struct per_cpu_info *pcpui = &per_cpu_info[coreid];
+       struct proc *p = pcpui->cur_proc;
 
-uintptr_t get_user_ctx_fp(struct user_context *ctx)
-{
-       switch (ctx->type) {
-               case ROS_HW_CTX:
-                       return get_hwtf_fp(&ctx->tf.hw_tf);
-               case ROS_SW_CTX:
-                       return get_swtf_fp(&ctx->tf.sw_tf);
-               default:
-                       warn("Bad context type %d for ctx %p\n", ctx->type, ctx);
-                       return 0;
+       assert(p);
+       assert(pcpui->cur_ctx && (pcpui->cur_ctx->type == ROS_HW_CTX));
+       /* need to store trap_nr, err code, and aux into the tf so that it can get
+        * extracted on the other end, and we need to flag the TF in some way so we
+        * can tell it was reflected.  for example, on a PF, we need some number (14
+        * on x86), the prot violation (write, read, etc), and the virt addr (aux).
+        * parlib will know how to extract this info. */
+       __arch_reflect_trap_hwtf(&pcpui->cur_ctx->tf.hw_tf, trap_nr, err, aux);
+       printx_unhandled_trap(p, pcpui->cur_ctx, trap_nr, err, aux);
+       if (reflect_current_context()) {
+               print_unhandled_trap(p, pcpui->cur_ctx, trap_nr, err, aux);
+               proc_destroy(p);
        }
 }
 
@@ -118,7 +111,8 @@ struct kmem_cache *kernel_msg_cache;
 void kernel_msg_init(void)
 {
        kernel_msg_cache = kmem_cache_create("kernel_msgs",
-                          sizeof(struct kernel_message), ARCH_CL_SIZE, 0, 0, 0);
+                                            sizeof(struct kernel_message),
+                                            ARCH_CL_SIZE, 0, NULL, 0, 0, NULL);
 }
 
 uint32_t send_kernel_message(uint32_t dst, amr_t pc, long arg0, long arg1,
@@ -273,8 +267,9 @@ void print_kmsgs(uint32_t coreid)
                struct kernel_message *kmsg_i;
                STAILQ_FOREACH(kmsg_i, list, link) {
                        fn_name = get_fn_name((long)kmsg_i->pc);
-                       printk("%s KMSG on %d from %d to run %p(%s)\n", type,
-                              kmsg_i->dstid, kmsg_i->srcid, kmsg_i->pc, fn_name); 
+                       printk("%s KMSG on %d from %d to run %p(%s)(%p, %p, %p)\n", type,
+                              kmsg_i->dstid, kmsg_i->srcid, kmsg_i->pc, fn_name,
+                              kmsg_i->arg0, kmsg_i->arg1, kmsg_i->arg2);
                        kfree(fn_name);
                }
        }
@@ -316,7 +311,7 @@ void kmsg_queue_stat(void)
                        printk("\targ1: %p\n", kmsg->arg1);
                        printk("\targ2: %p\n", kmsg->arg2);
                }
-                       
+
        }
 }
 
@@ -324,7 +319,7 @@ void print_kctx_depths(const char *str)
 {
        uint32_t coreid = core_id();
        struct per_cpu_info *pcpui = &per_cpu_info[coreid];
-       
+
        if (!str)
                str = "(none)";
        printk("%s: Core %d, irq depth %d, ktrap depth %d, irqon %d\n", str, coreid,
@@ -333,10 +328,17 @@ void print_kctx_depths(const char *str)
 
 void print_user_ctx(struct user_context *ctx)
 {
-       if (ctx->type == ROS_SW_CTX)
-               print_swtrapframe(&ctx->tf.sw_tf);
-       else if (ctx->type == ROS_HW_CTX)
+       switch (ctx->type) {
+       case ROS_HW_CTX:
                print_trapframe(&ctx->tf.hw_tf);
-       else
+               break;
+       case ROS_SW_CTX:
+               print_swtrapframe(&ctx->tf.sw_tf);
+               break;
+       case ROS_VM_CTX:
+               print_vmtrapframe(&ctx->tf.vm_tf);
+               break;
+       default:
                printk("Bad TF %p type %d!\n", ctx, ctx->type);
+       }
 }