#__clone(func, stack, flags, arg, ptid, tls, ctid) # a0, a1, a2, a3, a4, a5, a6 # sys_clone3(struct clone_args *cl_args, size_t size) # a0 a1 .global __clone .hidden __clone .type __clone,@function __clone: # Save function pointer and argument pointer on new thread stack addi.d $a1, $a1, -16 st.d $a0, $a1, 0 # save function pointer st.d $a3, $a1, 8 # save argument pointer li.d $t0, ~0x004000ff # mask CSIGNAL and CLONE_DETACHED and $t1, $a2, $t0 # cl_args.flags li.d $t0, 0x000000ff # CSIGNAL and $t2, $a2, $t0 # cl_args.exit_signal bstrins.d $sp, $zero, 2, 0 # align stack to 8 bytes addi.d $sp, $sp, -88 # struct clone_args st.d $t1, $sp, 0 # flags st.d $a4, $sp, 8 # pidfd st.d $a6, $sp, 16 # child_tid st.d $a4, $sp, 24 # parent_tid st.d $t2, $sp, 32 # exit_signal st.d $a1, $sp, 40 # stack st.d $zero, $sp, 48 # stack_size st.d $a5, $sp, 56 # tls st.d $zero, $sp, 64 # set_tid st.d $zero, $sp, 72 # set_tid_size st.d $zero, $sp, 80 # cgroup move $a0, $sp li.d $a1, 88 li.d $a7, 435 # __NR_clone3 syscall 0 # call clone3 beqz $a0, 1f # whether child process addi.d $sp, $sp, 88 jirl $zero, $ra, 0 # parent process return 1: ld.d $t8, $sp, 0 # function pointer ld.d $a0, $sp, 8 # argument pointer jirl $ra, $t8, 0 # call the user's function li.d $a7, 93 syscall 0 # child process exit