Browse Source

[lwp/rv64] support pending POSIX signal

wangxiaoyao 2 years ago
parent
commit
d5e2f8da69
1 changed files with 48 additions and 41 deletions
  1. 48 41
      components/lwp/arch/risc-v/rv64/lwp_gcc.S

+ 48 - 41
components/lwp/arch/risc-v/rv64/lwp_gcc.S

@@ -97,38 +97,52 @@ ret_to_user_exit:
     // `RESTORE_ALL` also reset sp to user sp, and setup sscratch
     sret
 
+/**
+ * Restore user context from exception frame stroraged in ustack
+ * And handle pending signals;
+ * 
+ */
 arch_signal_quit:
     call lwp_signal_restore
     call arch_get_usp_from_uctx
     // return value is user sp
     mv sp, a0
+
+    // restore user sp before enter trap
+    addi a0, sp, CTX_REG_NR * REGBYTES 
+    csrw sscratch, a0
+
     RESTORE_ALL
-    csrw sscratch, zero
-    sret
+    SAVE_ALL
+    j arch_ret_to_user
 
+/**
+ * Prepare and enter user signal handler
+ * Move user exception frame and setup signal return
+ * routine in user stack
+ */
 user_do_signal:
-    csrw sscratch, sp
+    /** restore and backup kernel sp carefully to avoid leaking */
+    addi t0, sp, CTX_REG_NR * REGBYTES
+    csrw sscratch, t0
+
     RESTORE_ALL
-    // now sp is user sp
-    // and in interrupt close
     SAVE_ALL
 
-    // save user sp in SAVE_ALL frame
-    mv t0, sp
-    addi t0, t0, CTX_REG_NR * REGBYTES
-    STORE t0, 32 * REGBYTES(sp)
-
-    // save lwp_sigreturn in user memory
+    /**
+     * save lwp_sigreturn in user memory
+     */
     mv s0, sp
-    la t0, lwp_sigreturn//t0 = src
+    la t0, lwp_sigreturn
     la t1, lwp_sigreturn_end
-    sub t1, t1, t0//t1 = size
-    sub s0, s0, t1//s0 = dst
-
+    // t1 <- size
+    sub t1, t1, t0
+    // s0 <- dst
+    sub s0, s0, t1
 lwp_sigreturn_copy_loop:
-    addi t2, t1, -1//t2 = memory index
-    add t3, t0, t2//t3 = src addr
-    add t4, s0, t2//t4 = dst addr
+    addi t2, t1, -1
+    add t3, t0, t2
+    add t4, s0, t2
     lb t5, 0(t3)
     sb t5, 0(t4)
     mv t1, t2
@@ -147,7 +161,10 @@ lwp_sigreturn_copy_loop:
     csrrw sp, sscratch, x0
 
     /**
-     * a0: user sp
+     * backup user sp (point to saved exception frame, skip sigreturn routine)
+     * And get signal id
+
+     * a0: user sp 
      * a1: user_pc (not used)
      * a2: user_flag (not used)
      */
@@ -155,31 +172,27 @@ lwp_sigreturn_copy_loop:
     mv a2, zero
     call lwp_signal_backup
 
-    // s2 <- signal id (a0/return value)
-    mv s2, a0
     /**
-     * WARN: lwp_sighandler_get can be a exit point
-     * a0: signal id
+     * backup signal id in s2, 
+     * and get sighandler by signal id
      */
+    mv s2, a0
     call lwp_sighandler_get
-    // a0 <- signal_handler
-
-    // ra <- lwp_sigreturn
-    mv ra, s0
 
     /**
-     * restore user sp in sscratch
-     * now ready to enter user mode
+     * set regiter RA to user signal handler
+     * set sp to user sp & save kernel sp in sscratch
      */
-    csrw sscratch, s0
+    mv ra, s0
+    csrw sscratch, sp
+    mv sp, s0
 
     /**
-     * signal handler entry point may be 
-     * lwp_sigreturn or real signal handler
+     * a0 is signal_handler,
+     * s1 = s0 == NULL ? lwp_sigreturn : s0;
      */
     mv s1, s0
     beqz a0, skip_user_signal_handler
-    // a0 <- signal_handler
     mv s1, a0
 
 skip_user_signal_handler:
@@ -189,12 +202,6 @@ skip_user_signal_handler:
     li t0, SSTATUS_SPIE
     csrs sstatus, t0
 
-    /**
-     * sp <- user sp
-     * sscratch <- kernel sp
-     */
-    csrrw sp, sscratch, sp
-
     // sepc <- signal_handler
     csrw sepc, s1
     // a0 <- signal id
@@ -251,11 +258,11 @@ syscall_entry:
     andi t0, t0, 0x100
     beqz t0, __restore_sp_from_tcb
 
-__restore_sp_from_sscratch:
+__restore_sp_from_sscratch: // from kernel
     csrr t0, sscratch
     j __move_stack_context
 
-__restore_sp_from_tcb:
+__restore_sp_from_tcb: // from user
     la a0, rt_current_thread
     LOAD a0, 0(a0)
     jal get_thread_kernel_stack_top