diff options
Diffstat (limited to 'src/runtime/sys_linux_riscv64.s')
-rw-r--r-- | src/runtime/sys_linux_riscv64.s | 660 |
1 files changed, 660 insertions, 0 deletions
diff --git a/src/runtime/sys_linux_riscv64.s b/src/runtime/sys_linux_riscv64.s new file mode 100644 index 0000000..8b1b26b --- /dev/null +++ b/src/runtime/sys_linux_riscv64.s @@ -0,0 +1,660 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +// System calls and other sys.stuff for riscv64, Linux +// + +#include "textflag.h" +#include "go_asm.h" + +#define AT_FDCWD -100 +#define CLOCK_REALTIME 0 +#define CLOCK_MONOTONIC 1 + +#define SYS_brk 214 +#define SYS_clock_gettime 113 +#define SYS_clone 220 +#define SYS_close 57 +#define SYS_connect 203 +#define SYS_epoll_create1 20 +#define SYS_epoll_ctl 21 +#define SYS_epoll_pwait 22 +#define SYS_exit 93 +#define SYS_exit_group 94 +#define SYS_faccessat 48 +#define SYS_fcntl 25 +#define SYS_futex 98 +#define SYS_getpid 172 +#define SYS_gettid 178 +#define SYS_gettimeofday 169 +#define SYS_kill 129 +#define SYS_madvise 233 +#define SYS_mincore 232 +#define SYS_mmap 222 +#define SYS_munmap 215 +#define SYS_nanosleep 101 +#define SYS_openat 56 +#define SYS_pipe2 59 +#define SYS_pselect6 72 +#define SYS_read 63 +#define SYS_rt_sigaction 134 +#define SYS_rt_sigprocmask 135 +#define SYS_rt_sigreturn 139 +#define SYS_sched_getaffinity 123 +#define SYS_sched_yield 124 +#define SYS_setitimer 103 +#define SYS_sigaltstack 132 +#define SYS_socket 198 +#define SYS_tgkill 131 +#define SYS_timer_create 107 +#define SYS_timer_delete 111 +#define SYS_timer_settime 110 +#define SYS_tkill 130 +#define SYS_write 64 + +// func exit(code int32) +TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 + MOVW code+0(FP), A0 + MOV $SYS_exit_group, A7 + ECALL + RET + +// func exitThread(wait *atomic.Uint32) +TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 + MOV wait+0(FP), A0 + // We're done using the stack. + FENCE + MOVW ZERO, (A0) + FENCE + MOV $0, A0 // exit code + MOV $SYS_exit, A7 + ECALL + JMP 0(PC) + +// func open(name *byte, mode, perm int32) int32 +TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20 + MOV $AT_FDCWD, A0 + MOV name+0(FP), A1 + MOVW mode+8(FP), A2 + MOVW perm+12(FP), A3 + MOV $SYS_openat, A7 + ECALL + MOV $-4096, T0 + BGEU T0, A0, 2(PC) + MOV $-1, A0 + MOVW A0, ret+16(FP) + RET + +// func closefd(fd int32) int32 +TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12 + MOVW fd+0(FP), A0 + MOV $SYS_close, A7 + ECALL + MOV $-4096, T0 + BGEU T0, A0, 2(PC) + MOV $-1, A0 + MOVW A0, ret+8(FP) + RET + +// func write1(fd uintptr, p unsafe.Pointer, n int32) int32 +TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28 + MOV fd+0(FP), A0 + MOV p+8(FP), A1 + MOVW n+16(FP), A2 + MOV $SYS_write, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func read(fd int32, p unsafe.Pointer, n int32) int32 +TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28 + MOVW fd+0(FP), A0 + MOV p+8(FP), A1 + MOVW n+16(FP), A2 + MOV $SYS_read, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func pipe() (r, w int32, errno int32) +TEXT runtime·pipe(SB),NOSPLIT|NOFRAME,$0-12 + MOV $r+0(FP), A0 + MOV ZERO, A1 + MOV $SYS_pipe2, A7 + ECALL + MOVW A0, errno+8(FP) + RET + +// func pipe2(flags int32) (r, w int32, errno int32) +TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20 + MOV $r+8(FP), A0 + MOVW flags+0(FP), A1 + MOV $SYS_pipe2, A7 + ECALL + MOVW A0, errno+16(FP) + RET + +// func usleep(usec uint32) +TEXT runtime·usleep(SB),NOSPLIT,$24-4 + MOVWU usec+0(FP), A0 + MOV $1000, A1 + MUL A1, A0, A0 + MOV $1000000000, A1 + DIV A1, A0, A2 + MOV A2, 8(X2) + REM A1, A0, A3 + MOV A3, 16(X2) + ADD $8, X2, A0 + MOV ZERO, A1 + MOV $SYS_nanosleep, A7 + ECALL + RET + +// func gettid() uint32 +TEXT runtime·gettid(SB),NOSPLIT,$0-4 + MOV $SYS_gettid, A7 + ECALL + MOVW A0, ret+0(FP) + RET + +// func raise(sig uint32) +TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0 + MOV $SYS_gettid, A7 + ECALL + // arg 1 tid - already in A0 + MOVW sig+0(FP), A1 // arg 2 + MOV $SYS_tkill, A7 + ECALL + RET + +// func raiseproc(sig uint32) +TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0 + MOV $SYS_getpid, A7 + ECALL + // arg 1 pid - already in A0 + MOVW sig+0(FP), A1 // arg 2 + MOV $SYS_kill, A7 + ECALL + RET + +// func getpid() int +TEXT ·getpid(SB),NOSPLIT|NOFRAME,$0-8 + MOV $SYS_getpid, A7 + ECALL + MOV A0, ret+0(FP) + RET + +// func tgkill(tgid, tid, sig int) +TEXT ·tgkill(SB),NOSPLIT|NOFRAME,$0-24 + MOV tgid+0(FP), A0 + MOV tid+8(FP), A1 + MOV sig+16(FP), A2 + MOV $SYS_tgkill, A7 + ECALL + RET + +// func setitimer(mode int32, new, old *itimerval) +TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24 + MOVW mode+0(FP), A0 + MOV new+8(FP), A1 + MOV old+16(FP), A2 + MOV $SYS_setitimer, A7 + ECALL + RET + +// func timer_create(clockid int32, sevp *sigevent, timerid *int32) int32 +TEXT runtime·timer_create(SB),NOSPLIT,$0-28 + MOVW clockid+0(FP), A0 + MOV sevp+8(FP), A1 + MOV timerid+16(FP), A2 + MOV $SYS_timer_create, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func timer_settime(timerid int32, flags int32, new, old *itimerspec) int32 +TEXT runtime·timer_settime(SB),NOSPLIT,$0-28 + MOVW timerid+0(FP), A0 + MOVW flags+4(FP), A1 + MOV new+8(FP), A2 + MOV old+16(FP), A3 + MOV $SYS_timer_settime, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func timer_delete(timerid int32) int32 +TEXT runtime·timer_delete(SB),NOSPLIT,$0-12 + MOVW timerid+0(FP), A0 + MOV $SYS_timer_delete, A7 + ECALL + MOVW A0, ret+8(FP) + RET + +// func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32 +TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 + MOV addr+0(FP), A0 + MOV n+8(FP), A1 + MOV dst+16(FP), A2 + MOV $SYS_mincore, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func walltime() (sec int64, nsec int32) +TEXT runtime·walltime(SB),NOSPLIT,$40-12 + MOV $CLOCK_REALTIME, A0 + + MOV runtime·vdsoClockgettimeSym(SB), A7 + BEQZ A7, fallback + MOV X2, S2 // S2,S3,S4 is unchanged by C code + MOV g_m(g), S3 // S3 = m + + // Save the old values on stack for reentrant + MOV m_vdsoPC(S3), T0 + MOV T0, 24(X2) + MOV m_vdsoSP(S3), T0 + MOV T0, 32(X2) + + MOV RA, m_vdsoPC(S3) + MOV $ret-8(FP), T1 // caller's SP + MOV T1, m_vdsoSP(S3) + + MOV m_curg(S3), T1 + BNE g, T1, noswitch + + MOV m_g0(S3), T1 + MOV (g_sched+gobuf_sp)(T1), X2 + +noswitch: + ADDI $-24, X2 // Space for result + ANDI $~7, X2 // Align for C code + MOV $8(X2), A1 + + // Store g on gsignal's stack, see sys_linux_arm64.s for detail + MOVBU runtime·iscgo(SB), S4 + BNEZ S4, nosaveg + MOV m_gsignal(S3), S4 // g.m.gsignal + BEQZ S4, nosaveg + BEQ g, S4, nosaveg + MOV (g_stack+stack_lo)(S4), S4 // g.m.gsignal.stack.lo + MOV g, (S4) + + JALR RA, A7 + + MOV ZERO, (S4) + JMP finish + +nosaveg: + JALR RA, A7 + +finish: + MOV 8(X2), T0 // sec + MOV 16(X2), T1 // nsec + + MOV S2, X2 // restore stack + MOV 24(X2), A2 + MOV A2, m_vdsoPC(S3) + + MOV 32(X2), A3 + MOV A3, m_vdsoSP(S3) + + MOV T0, sec+0(FP) + MOVW T1, nsec+8(FP) + RET + +fallback: + MOV $8(X2), A1 + MOV $SYS_clock_gettime, A7 + ECALL + MOV 8(X2), T0 // sec + MOV 16(X2), T1 // nsec + MOV T0, sec+0(FP) + MOVW T1, nsec+8(FP) + RET + +// func nanotime1() int64 +TEXT runtime·nanotime1(SB),NOSPLIT,$40-8 + MOV $CLOCK_MONOTONIC, A0 + + MOV runtime·vdsoClockgettimeSym(SB), A7 + BEQZ A7, fallback + + MOV X2, S2 // S2 = RSP, S2 is unchanged by C code + MOV g_m(g), S3 // S3 = m + // Save the old values on stack for reentrant + MOV m_vdsoPC(S3), T0 + MOV T0, 24(X2) + MOV m_vdsoSP(S3), T0 + MOV T0, 32(X2) + + MOV RA, m_vdsoPC(S3) + MOV $ret-8(FP), T0 // caller's SP + MOV T0, m_vdsoSP(S3) + + MOV m_curg(S3), T1 + BNE g, T1, noswitch + + MOV m_g0(S3), T1 + MOV (g_sched+gobuf_sp)(T1), X2 + +noswitch: + ADDI $-24, X2 // Space for result + ANDI $~7, X2 // Align for C code + MOV $8(X2), A1 + + // Store g on gsignal's stack, see sys_linux_arm64.s for detail + MOVBU runtime·iscgo(SB), S4 + BNEZ S4, nosaveg + MOV m_gsignal(S3), S4 // g.m.gsignal + BEQZ S4, nosaveg + BEQ g, S4, nosaveg + MOV (g_stack+stack_lo)(S4), S4 // g.m.gsignal.stack.lo + MOV g, (S4) + + JALR RA, A7 + + MOV ZERO, (S4) + JMP finish + +nosaveg: + JALR RA, A7 + +finish: + MOV 8(X2), T0 // sec + MOV 16(X2), T1 // nsec + // restore stack + MOV S2, X2 + MOV 24(X2), T2 + MOV T2, m_vdsoPC(S3) + + MOV 32(X2), T2 + MOV T2, m_vdsoSP(S3) + // sec is in T0, nsec in T1 + // return nsec in T0 + MOV $1000000000, T2 + MUL T2, T0 + ADD T1, T0 + MOV T0, ret+0(FP) + RET + +fallback: + MOV $8(X2), A1 + MOV $SYS_clock_gettime, A7 + ECALL + MOV 8(X2), T0 // sec + MOV 16(X2), T1 // nsec + MOV $1000000000, T2 + MUL T2, T0 + ADD T1, T0 + MOV T0, ret+0(FP) + RET + +// func rtsigprocmask(how int32, new, old *sigset, size int32) +TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28 + MOVW how+0(FP), A0 + MOV new+8(FP), A1 + MOV old+16(FP), A2 + MOVW size+24(FP), A3 + MOV $SYS_rt_sigprocmask, A7 + ECALL + MOV $-4096, T0 + BLTU A0, T0, 2(PC) + WORD $0 // crash + RET + +// func rt_sigaction(sig uintptr, new, old *sigactiont, size uintptr) int32 +TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36 + MOV sig+0(FP), A0 + MOV new+8(FP), A1 + MOV old+16(FP), A2 + MOV size+24(FP), A3 + MOV $SYS_rt_sigaction, A7 + ECALL + MOVW A0, ret+32(FP) + RET + +// func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer) +TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 + MOVW sig+8(FP), A0 + MOV info+16(FP), A1 + MOV ctx+24(FP), A2 + MOV fn+0(FP), T1 + JALR RA, T1 + RET + +// func sigtramp(signo, ureg, ctxt unsafe.Pointer) +TEXT runtime·sigtramp(SB),NOSPLIT,$64 + MOVW A0, 8(X2) + MOV A1, 16(X2) + MOV A2, 24(X2) + + // this might be called in external code context, + // where g is not set. + MOVBU runtime·iscgo(SB), A0 + BEQ A0, ZERO, 2(PC) + CALL runtime·load_g(SB) + + MOV $runtime·sigtrampgo(SB), A0 + JALR RA, A0 + RET + +// func cgoSigtramp() +TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 + MOV $runtime·sigtramp(SB), T1 + JALR ZERO, T1 + +// func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (p unsafe.Pointer, err int) +TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0 + MOV addr+0(FP), A0 + MOV n+8(FP), A1 + MOVW prot+16(FP), A2 + MOVW flags+20(FP), A3 + MOVW fd+24(FP), A4 + MOVW off+28(FP), A5 + MOV $SYS_mmap, A7 + ECALL + MOV $-4096, T0 + BGEU T0, A0, 5(PC) + SUB A0, ZERO, A0 + MOV ZERO, p+32(FP) + MOV A0, err+40(FP) + RET +ok: + MOV A0, p+32(FP) + MOV ZERO, err+40(FP) + RET + +// func munmap(addr unsafe.Pointer, n uintptr) +TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0 + MOV addr+0(FP), A0 + MOV n+8(FP), A1 + MOV $SYS_munmap, A7 + ECALL + MOV $-4096, T0 + BLTU A0, T0, 2(PC) + WORD $0 // crash + RET + +// func madvise(addr unsafe.Pointer, n uintptr, flags int32) +TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0 + MOV addr+0(FP), A0 + MOV n+8(FP), A1 + MOVW flags+16(FP), A2 + MOV $SYS_madvise, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32 +TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0 + MOV addr+0(FP), A0 + MOVW op+8(FP), A1 + MOVW val+12(FP), A2 + MOV ts+16(FP), A3 + MOV addr2+24(FP), A4 + MOVW val3+32(FP), A5 + MOV $SYS_futex, A7 + ECALL + MOVW A0, ret+40(FP) + RET + +// func clone(flags int32, stk, mp, gp, fn unsafe.Pointer) int32 +TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0 + MOVW flags+0(FP), A0 + MOV stk+8(FP), A1 + + // Copy mp, gp, fn off parent stack for use by child. + MOV mp+16(FP), T0 + MOV gp+24(FP), T1 + MOV fn+32(FP), T2 + + MOV T0, -8(A1) + MOV T1, -16(A1) + MOV T2, -24(A1) + MOV $1234, T0 + MOV T0, -32(A1) + + MOV $SYS_clone, A7 + ECALL + + // In parent, return. + BEQ ZERO, A0, child + MOVW ZERO, ret+40(FP) + RET + +child: + // In child, on new stack. + MOV -32(X2), T0 + MOV $1234, A0 + BEQ A0, T0, good + WORD $0 // crash + +good: + // Initialize m->procid to Linux tid + MOV $SYS_gettid, A7 + ECALL + + MOV -24(X2), T2 // fn + MOV -16(X2), T1 // g + MOV -8(X2), T0 // m + + BEQ ZERO, T0, nog + BEQ ZERO, T1, nog + + MOV A0, m_procid(T0) + + // In child, set up new stack + MOV T0, g_m(T1) + MOV T1, g + +nog: + // Call fn + JALR RA, T2 + + // It shouldn't return. If it does, exit this thread. + MOV $111, A0 + MOV $SYS_exit, A7 + ECALL + JMP -3(PC) // keep exiting + +// func sigaltstack(new, old *stackt) +TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0 + MOV new+0(FP), A0 + MOV old+8(FP), A1 + MOV $SYS_sigaltstack, A7 + ECALL + MOV $-4096, T0 + BLTU A0, T0, 2(PC) + WORD $0 // crash + RET + +// func osyield() +TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0 + MOV $SYS_sched_yield, A7 + ECALL + RET + +// func sched_getaffinity(pid, len uintptr, buf *uintptr) int32 +TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0 + MOV pid+0(FP), A0 + MOV len+8(FP), A1 + MOV buf+16(FP), A2 + MOV $SYS_sched_getaffinity, A7 + ECALL + MOV A0, ret+24(FP) + RET + +// func epollcreate(size int32) int32 +TEXT runtime·epollcreate(SB),NOSPLIT|NOFRAME,$0 + MOV $0, A0 + MOV $SYS_epoll_create1, A7 + ECALL + MOVW A0, ret+8(FP) + RET + +// func epollcreate1(flags int32) int32 +TEXT runtime·epollcreate1(SB),NOSPLIT|NOFRAME,$0 + MOVW flags+0(FP), A0 + MOV $SYS_epoll_create1, A7 + ECALL + MOVW A0, ret+8(FP) + RET + +// func epollctl(epfd, op, fd int32, ev *epollevent) int32 +TEXT runtime·epollctl(SB),NOSPLIT|NOFRAME,$0 + MOVW epfd+0(FP), A0 + MOVW op+4(FP), A1 + MOVW fd+8(FP), A2 + MOV ev+16(FP), A3 + MOV $SYS_epoll_ctl, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32 +TEXT runtime·epollwait(SB),NOSPLIT|NOFRAME,$0 + MOVW epfd+0(FP), A0 + MOV ev+8(FP), A1 + MOVW nev+16(FP), A2 + MOVW timeout+20(FP), A3 + MOV $0, A4 + MOV $SYS_epoll_pwait, A7 + ECALL + MOVW A0, ret+24(FP) + RET + +// func closeonexec(int32) +TEXT runtime·closeonexec(SB),NOSPLIT|NOFRAME,$0 + MOVW fd+0(FP), A0 // fd + MOV $2, A1 // F_SETFD + MOV $1, A2 // FD_CLOEXEC + MOV $SYS_fcntl, A7 + ECALL + RET + +// func runtime·setNonblock(int32 fd) +TEXT runtime·setNonblock(SB),NOSPLIT|NOFRAME,$0-4 + MOVW fd+0(FP), A0 // fd + MOV $3, A1 // F_GETFL + MOV $0, A2 + MOV $SYS_fcntl, A7 + ECALL + MOV $0x800, A2 // O_NONBLOCK + OR A0, A2 + MOVW fd+0(FP), A0 // fd + MOV $4, A1 // F_SETFL + MOV $SYS_fcntl, A7 + ECALL + RET + +// func sbrk0() uintptr +TEXT runtime·sbrk0(SB),NOSPLIT,$0-8 + // Implemented as brk(NULL). + MOV $0, A0 + MOV $SYS_brk, A7 + ECALL + MOVW A0, ret+0(FP) + RET |