parlib: slab: Use the modern ctor/dtor interface
[akaros.git] / user / parlib / x86 / vcore.c
index ea38099..32243d4 100644 (file)
  * enable notifs, make sure notif IPIs weren't pending, restore the work reg,
  * and then "ret".
  *
+ * However, we can't just put the extra stuff directly below the rsp.  We need
+ * to leave room for the redzone: area that is potentially being used.  (Even if
+ * you compile with -mno-red-zone, some asm code (glibc memcpy) will still use
+ * that area).
+ *
  * This is what the target uthread's stack will look like (growing down):
  *
  * Target RSP -> |   u_thread's old stuff   | the future %rsp, tf->tf_rsp
- *               |   new rip                | 0x08 below %rsp (one slot is 0x08)
+ *               |            .             | beginning of Red Zone
+ *               |            .             |
+ *               |   128 Bytes of Red Zone  |
+ *               |            .             |
+ *               |            .             | end of Red Zone
+ *               |   new rip                | 0x08 below Red (one slot is 0x08)
  *               |   rflags space           | 0x10 below
  *               |   rdi save space         | 0x18 below
  *               |   *sysc ptr to syscall   | 0x20 below
  * so that restarting *this* code won't clobber shit we need later.  The way we
  * do this is that we do any "stack jumping" before we enable interrupts/notifs.
  * These jumps are when we directly modify rsp, specifically in the down
- * direction (subtracts).  Adds would be okay.
- *
- * Another 64-bit concern is the red-zone.  The AMD64 ABI allows the use of
- * space below the stack pointer by regular programs.  If we allowed this, we
- * would clobber that space when we do our TF restarts, much like with OSs and
- * IRQ handlers.  Thus we have the cross compiler automatically disabling the
- * redzone (-mno-red-zone is a built-in option).
- *
- * When compared to the 32 bit code, notice we use rdi, instead of eax, for our
- * work.  This is because rdi is the arg0 of a syscall.  Using it saves us some
- * extra moves, since we need to pop the *sysc before saving any other
- * registers. */
+ * direction (subtracts).  Adds would be okay. */
 
 /* Helper for writing the info we need later to the u_tf's stack.  Also, note
  * this goes backwards, since memory reads up the stack. */
@@ -52,6 +51,7 @@ struct restart_helper {
        uint64_t                                        rflags;
        uint64_t                                        rip;
 };
+
 /* Static syscall, used for self-notifying.  We never wait on it, and we
  * actually might submit it multiple times in parallel on different cores!
  * While this may seem dangerous, the kernel needs to be able to handle this
@@ -74,11 +74,13 @@ struct syscall vc_entry = {
 
 static void pop_hw_tf(struct hw_trapframe *tf, uint32_t vcoreid)
 {
+       #define X86_RED_ZONE_SZ                 128
        struct restart_helper *rst;
        struct preempt_data *vcpd = &__procdata.vcore_preempt_data[vcoreid];
 
-       /* The stuff we need to write will be below the current stack of the utf */
-       rst = (struct restart_helper*)((void*)tf->tf_rsp -
+       /* The stuff we need to write will be below the current stack and red zone
+        * of the utf */
+       rst = (struct restart_helper*)((void*)tf->tf_rsp - X86_RED_ZONE_SZ -
                                       sizeof(struct restart_helper));
        /* Fill in the info we'll need later */
        rst->notif_disab_loc = &vcpd->notif_disabled;
@@ -106,6 +108,7 @@ static void pop_hw_tf(struct hw_trapframe *tf, uint32_t vcoreid)
                      "popq %%r15;           "
                      "addq $0x28, %%rsp;    " /* move to the rsp slot in the tf */
                      "popq %%rsp;           " /* change to the utf's %rsp */
+                     "subq %[red], %%rsp;   " /* jump over the redzone */
                      "subq $0x10, %%rsp;    " /* move rsp to below rdi's slot */
                      "pushq %%rdi;          " /* save rdi, will clobber soon */
                      "subq $0x18, %%rsp;    " /* move to notif_dis_loc slot */
@@ -114,7 +117,7 @@ static void pop_hw_tf(struct hw_trapframe *tf, uint32_t vcoreid)
                                  /* Need a wrmb() here so the write of enable_notif can't pass
                                   * the read of notif_pending (racing with a potential
                                   * cross-core call with proc_notify()). */
-                                 "lock addq $0, (%%rdi);" /* LOCK is a CPU mb() */
+                                 "lock addb $0, (%%rdi);" /* LOCK is a CPU mb() */
                                  /* From here down, we can get interrupted and restarted */
                      "popq %%rdi;           " /* get notif_pending status loc */
                      "testb $0x01, (%%rdi); " /* test if a notif is pending */
@@ -131,9 +134,9 @@ static void pop_hw_tf(struct hw_trapframe *tf, uint32_t vcoreid)
                                  "1: addq $0x08, %%rsp; " /* discard &sysc (on non-sc path) */
                      "2: popq %%rdi;        " /* restore tf's %rdi (both paths) */
                                  "popfq;                " /* restore utf's rflags */
-                     "ret;                  " /* return to the new PC */
+                     "ret %[red];           " /* return to the new PC, skip red */
                      :
-                     : "g"(&tf->tf_rax), "i"(T_SYSCALL)
+                     : "g"(&tf->tf_rax), "i"(T_SYSCALL), [red]"i"(X86_RED_ZONE_SZ)
                      : "memory");
 }
 
@@ -170,7 +173,7 @@ static void pop_sw_tf(struct sw_trapframe *sw_tf, uint32_t vcoreid)
                      /* Need a wrmb() here so the write of enable_notif can't pass
                       * the read of notif_pending (racing with a potential
                       * cross-core call with proc_notify()). */
-                     "lock addq $0, (%2);   " /* LOCK is a CPU mb() */
+                     "lock addb $0, (%2);   " /* LOCK is a CPU mb() */
                      /* From here down, we can get interrupted and restarted */
                      "testb $0x01, (%3);    " /* test if a notif is pending */
                      "jz 1f;                " /* if not pending, skip syscall */
@@ -298,100 +301,101 @@ void pop_user_ctx_raw(struct user_context *ctx, uint32_t vcoreid)
                      : "memory");
 }
 
-void print_hw_tf(struct hw_trapframe *hw_tf)
+void fprintf_hw_tf(FILE *f, struct hw_trapframe *hw_tf)
 {
-       printf("[user] HW TRAP frame 0x%016x\n", hw_tf);
-       printf("  rax  0x%016lx\n",           hw_tf->tf_rax);
-       printf("  rbx  0x%016lx\n",           hw_tf->tf_rbx);
-       printf("  rcx  0x%016lx\n",           hw_tf->tf_rcx);
-       printf("  rdx  0x%016lx\n",           hw_tf->tf_rdx);
-       printf("  rbp  0x%016lx\n",           hw_tf->tf_rbp);
-       printf("  rsi  0x%016lx\n",           hw_tf->tf_rsi);
-       printf("  rdi  0x%016lx\n",           hw_tf->tf_rdi);
-       printf("  r8   0x%016lx\n",           hw_tf->tf_r8);
-       printf("  r9   0x%016lx\n",           hw_tf->tf_r9);
-       printf("  r10  0x%016lx\n",           hw_tf->tf_r10);
-       printf("  r11  0x%016lx\n",           hw_tf->tf_r11);
-       printf("  r12  0x%016lx\n",           hw_tf->tf_r12);
-       printf("  r13  0x%016lx\n",           hw_tf->tf_r13);
-       printf("  r14  0x%016lx\n",           hw_tf->tf_r14);
-       printf("  r15  0x%016lx\n",           hw_tf->tf_r15);
-       printf("  trap 0x%08x\n",             hw_tf->tf_trapno);
-       printf("  gsbs 0x%016lx\n",           hw_tf->tf_gsbase);
-       printf("  fsbs 0x%016lx\n",           hw_tf->tf_fsbase);
-       printf("  err  0x--------%08x\n",     hw_tf->tf_err);
-       printf("  rip  0x%016lx\n",           hw_tf->tf_rip);
-       printf("  cs   0x------------%04x\n", hw_tf->tf_cs);
-       printf("  flag 0x%016lx\n",           hw_tf->tf_rflags);
-       printf("  rsp  0x%016lx\n",           hw_tf->tf_rsp);
-       printf("  ss   0x------------%04x\n", hw_tf->tf_ss);
+       fprintf(f, "[user] HW TRAP frame 0x%016x\n", hw_tf);
+       fprintf(f, "  rax  0x%016lx\n",           hw_tf->tf_rax);
+       fprintf(f, "  rbx  0x%016lx\n",           hw_tf->tf_rbx);
+       fprintf(f, "  rcx  0x%016lx\n",           hw_tf->tf_rcx);
+       fprintf(f, "  rdx  0x%016lx\n",           hw_tf->tf_rdx);
+       fprintf(f, "  rbp  0x%016lx\n",           hw_tf->tf_rbp);
+       fprintf(f, "  rsi  0x%016lx\n",           hw_tf->tf_rsi);
+       fprintf(f, "  rdi  0x%016lx\n",           hw_tf->tf_rdi);
+       fprintf(f, "  r8   0x%016lx\n",           hw_tf->tf_r8);
+       fprintf(f, "  r9   0x%016lx\n",           hw_tf->tf_r9);
+       fprintf(f, "  r10  0x%016lx\n",           hw_tf->tf_r10);
+       fprintf(f, "  r11  0x%016lx\n",           hw_tf->tf_r11);
+       fprintf(f, "  r12  0x%016lx\n",           hw_tf->tf_r12);
+       fprintf(f, "  r13  0x%016lx\n",           hw_tf->tf_r13);
+       fprintf(f, "  r14  0x%016lx\n",           hw_tf->tf_r14);
+       fprintf(f, "  r15  0x%016lx\n",           hw_tf->tf_r15);
+       fprintf(f, "  trap 0x%08x\n",             hw_tf->tf_trapno);
+       fprintf(f, "  gsbs 0x%016lx\n",           hw_tf->tf_gsbase);
+       fprintf(f, "  fsbs 0x%016lx\n",           hw_tf->tf_fsbase);
+       fprintf(f, "  err  0x--------%08x\n",     hw_tf->tf_err);
+       fprintf(f, "  rip  0x%016lx\n",           hw_tf->tf_rip);
+       fprintf(f, "  cs   0x------------%04x\n", hw_tf->tf_cs);
+       fprintf(f, "  flag 0x%016lx\n",           hw_tf->tf_rflags);
+       fprintf(f, "  rsp  0x%016lx\n",           hw_tf->tf_rsp);
+       fprintf(f, "  ss   0x------------%04x\n", hw_tf->tf_ss);
 }
 
-void print_sw_tf(struct sw_trapframe *sw_tf)
+void fprintf_sw_tf(FILE *f, struct sw_trapframe *sw_tf)
 {
-       printf("[user] SW TRAP frame 0x%016p\n", sw_tf);
-       printf("  rbx  0x%016lx\n",           sw_tf->tf_rbx);
-       printf("  rbp  0x%016lx\n",           sw_tf->tf_rbp);
-       printf("  r12  0x%016lx\n",           sw_tf->tf_r12);
-       printf("  r13  0x%016lx\n",           sw_tf->tf_r13);
-       printf("  r14  0x%016lx\n",           sw_tf->tf_r14);
-       printf("  r15  0x%016lx\n",           sw_tf->tf_r15);
-       printf("  gsbs 0x%016lx\n",           sw_tf->tf_gsbase);
-       printf("  fsbs 0x%016lx\n",           sw_tf->tf_fsbase);
-       printf("  rip  0x%016lx\n",           sw_tf->tf_rip);
-       printf("  rsp  0x%016lx\n",           sw_tf->tf_rsp);
-       printf(" mxcsr 0x%08x\n",             sw_tf->tf_mxcsr);
-       printf(" fpucw 0x%04x\n",             sw_tf->tf_fpucw);
+       fprintf(f, "[user] SW TRAP frame 0x%016p\n", sw_tf);
+       fprintf(f, "  rbx  0x%016lx\n",           sw_tf->tf_rbx);
+       fprintf(f, "  rbp  0x%016lx\n",           sw_tf->tf_rbp);
+       fprintf(f, "  r12  0x%016lx\n",           sw_tf->tf_r12);
+       fprintf(f, "  r13  0x%016lx\n",           sw_tf->tf_r13);
+       fprintf(f, "  r14  0x%016lx\n",           sw_tf->tf_r14);
+       fprintf(f, "  r15  0x%016lx\n",           sw_tf->tf_r15);
+       fprintf(f, "  gsbs 0x%016lx\n",           sw_tf->tf_gsbase);
+       fprintf(f, "  fsbs 0x%016lx\n",           sw_tf->tf_fsbase);
+       fprintf(f, "  rip  0x%016lx\n",           sw_tf->tf_rip);
+       fprintf(f, "  rsp  0x%016lx\n",           sw_tf->tf_rsp);
+       fprintf(f, " mxcsr 0x%08x\n",             sw_tf->tf_mxcsr);
+       fprintf(f, " fpucw 0x%04x\n",             sw_tf->tf_fpucw);
 }
 
-void print_vm_tf(struct vm_trapframe *vm_tf)
+void fprintf_vm_tf(FILE *f, struct vm_trapframe *vm_tf)
 {
-       printf("[user] VM Trapframe 0x%016x\n", vm_tf);
-       printf("  rax  0x%016lx\n",           vm_tf->tf_rax);
-       printf("  rbx  0x%016lx\n",           vm_tf->tf_rbx);
-       printf("  rcx  0x%016lx\n",           vm_tf->tf_rcx);
-       printf("  rdx  0x%016lx\n",           vm_tf->tf_rdx);
-       printf("  rbp  0x%016lx\n",           vm_tf->tf_rbp);
-       printf("  rsi  0x%016lx\n",           vm_tf->tf_rsi);
-       printf("  rdi  0x%016lx\n",           vm_tf->tf_rdi);
-       printf("  r8   0x%016lx\n",           vm_tf->tf_r8);
-       printf("  r9   0x%016lx\n",           vm_tf->tf_r9);
-       printf("  r10  0x%016lx\n",           vm_tf->tf_r10);
-       printf("  r11  0x%016lx\n",           vm_tf->tf_r11);
-       printf("  r12  0x%016lx\n",           vm_tf->tf_r12);
-       printf("  r13  0x%016lx\n",           vm_tf->tf_r13);
-       printf("  r14  0x%016lx\n",           vm_tf->tf_r14);
-       printf("  r15  0x%016lx\n",           vm_tf->tf_r15);
-       printf("  rip  0x%016lx\n",           vm_tf->tf_rip);
-       printf("  rflg 0x%016lx\n",           vm_tf->tf_rflags);
-       printf("  rsp  0x%016lx\n",           vm_tf->tf_rsp);
-       printf("  cr2  0x%016lx\n",           vm_tf->tf_cr2);
-       printf("  cr3  0x%016lx\n",           vm_tf->tf_cr3);
-       printf("Gpcore 0x%08x\n",             vm_tf->tf_guest_pcoreid);
-       printf("Flags  0x%08x\n",             vm_tf->tf_flags);
-       printf("Inject 0x%08x\n",             vm_tf->tf_trap_inject);
-       printf("ExitRs 0x%08x\n",             vm_tf->tf_exit_reason);
-       printf("ExitQl 0x%08x\n",             vm_tf->tf_exit_qual);
-       printf("Intr1  0x%016lx\n",           vm_tf->tf_intrinfo1);
-       printf("Intr2  0x%016lx\n",           vm_tf->tf_intrinfo2);
-       printf("GVA    0x%016lx\n",           vm_tf->tf_guest_va);
-       printf("GPA    0x%016lx\n",           vm_tf->tf_guest_pa);
+       fprintf(f, "[user] VM Trapframe 0x%016x\n", vm_tf);
+       fprintf(f, "  rax  0x%016lx\n",           vm_tf->tf_rax);
+       fprintf(f, "  rbx  0x%016lx\n",           vm_tf->tf_rbx);
+       fprintf(f, "  rcx  0x%016lx\n",           vm_tf->tf_rcx);
+       fprintf(f, "  rdx  0x%016lx\n",           vm_tf->tf_rdx);
+       fprintf(f, "  rbp  0x%016lx\n",           vm_tf->tf_rbp);
+       fprintf(f, "  rsi  0x%016lx\n",           vm_tf->tf_rsi);
+       fprintf(f, "  rdi  0x%016lx\n",           vm_tf->tf_rdi);
+       fprintf(f, "  r8   0x%016lx\n",           vm_tf->tf_r8);
+       fprintf(f, "  r9   0x%016lx\n",           vm_tf->tf_r9);
+       fprintf(f, "  r10  0x%016lx\n",           vm_tf->tf_r10);
+       fprintf(f, "  r11  0x%016lx\n",           vm_tf->tf_r11);
+       fprintf(f, "  r12  0x%016lx\n",           vm_tf->tf_r12);
+       fprintf(f, "  r13  0x%016lx\n",           vm_tf->tf_r13);
+       fprintf(f, "  r14  0x%016lx\n",           vm_tf->tf_r14);
+       fprintf(f, "  r15  0x%016lx\n",           vm_tf->tf_r15);
+       fprintf(f, "  rip  0x%016lx\n",           vm_tf->tf_rip);
+       fprintf(f, "  rflg 0x%016lx\n",           vm_tf->tf_rflags);
+       fprintf(f, "  rsp  0x%016lx\n",           vm_tf->tf_rsp);
+       fprintf(f, "  cr2  0x%016lx\n",           vm_tf->tf_cr2);
+       fprintf(f, "  cr3  0x%016lx\n",           vm_tf->tf_cr3);
+       fprintf(f, "Gpcore 0x%08x\n",             vm_tf->tf_guest_pcoreid);
+       fprintf(f, "Flags  0x%08x\n",             vm_tf->tf_flags);
+       fprintf(f, "Inject 0x%08x\n",             vm_tf->tf_trap_inject);
+       fprintf(f, "ExitRs 0x%08x\n",             vm_tf->tf_exit_reason);
+       fprintf(f, "ExitQl 0x%08x\n",             vm_tf->tf_exit_qual);
+       fprintf(f, "Intr1  0x%016lx\n",           vm_tf->tf_intrinfo1);
+       fprintf(f, "Intr2  0x%016lx\n",           vm_tf->tf_intrinfo2);
+       fprintf(f, "GIntr  0x----%04x\n",         vm_tf->tf_guest_intr_status);
+       fprintf(f, "GVA    0x%016lx\n",           vm_tf->tf_guest_va);
+       fprintf(f, "GPA    0x%016lx\n",           vm_tf->tf_guest_pa);
 }
 
 void print_user_context(struct user_context *ctx)
 {
        switch (ctx->type) {
        case ROS_HW_CTX:
-               print_hw_tf(&ctx->tf.hw_tf);
+               fprintf_hw_tf(stdout, &ctx->tf.hw_tf);
                break;
        case ROS_SW_CTX:
-               print_sw_tf(&ctx->tf.sw_tf);
+               fprintf_sw_tf(stdout, &ctx->tf.sw_tf);
                break;
        case ROS_VM_CTX:
-               print_vm_tf(&ctx->tf.vm_tf);
+               fprintf_vm_tf(stdout, &ctx->tf.vm_tf);
                break;
        default:
-               printf("Unknown context type %d\n", ctx->type);
+               fprintf(stderr, "Unknown context type %d\n", ctx->type);
        }
 }