runtime/internal/syscall, syscall: replace RawSyscall6 with runtime implementation on linux

For #51087

Change-Id: I75a1bdeb5089454595f5ca04765a9c6e45cf9bd5
Reviewed-on: https://go-review.googlesource.com/c/go/+/388475
Run-TryBot: Michael Pratt <mpratt@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/src/runtime/internal/syscall/syscall_linux.go b/src/runtime/internal/syscall/syscall_linux.go
index 06d5f21..7f268e8 100644
--- a/src/runtime/internal/syscall/syscall_linux.go
+++ b/src/runtime/internal/syscall/syscall_linux.go
@@ -5,8 +5,35 @@
 // Package syscall provides the syscall primitives required for the runtime.
 package syscall
 
+import (
+	_ "unsafe" // for go:linkname
+)
+
 // TODO(https://go.dev/issue/51087): This package is incomplete and currently
 // only contains very minimal support for Linux.
 
 // Syscall6 calls system call number 'num' with arguments a1-6.
 func Syscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr)
+
+// syscall_RawSyscall6 is a push linkname to export Syscall6 as
+// syscall.RawSyscall6.
+//
+// //go:uintptrkeepalive because the uintptr argument may be converted pointers
+// that need to be kept alive in the caller (this is implied for Syscall6 since
+// it has no body).
+//
+// //go:nosplit because stack copying does not account for uintptrkeepalive, so
+// the stack must not grow. Stack copying cannot blindly assume that all
+// uintptr arguments are pointers, because some values may look like pointers,
+// but not really be pointers, and adjusting their value would break the call.
+//
+// This is a separate wrapper because we can't export one function as two
+// names. The assembly implementations name themselves Syscall6 would not be
+// affected by a linkname.
+//
+//go:uintptrkeepalive
+//go:nosplit
+//go:linkname syscall_RawSyscall6 syscall.RawSyscall6
+func syscall_RawSyscall6(num, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, errno uintptr) {
+	return Syscall6(num, a1, a2, a3, a4, a5, a6)
+}
diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s
index 1c69083..a2b5efb 100644
--- a/src/syscall/asm_linux_386.s
+++ b/src/syscall/asm_linux_386.s
@@ -87,29 +87,6 @@
 	MOVL	$0, err+24(FP)
 	RET
 
-// func RawSyscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
-TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
-	MOVL	trap+0(FP), AX	// syscall entry
-	MOVL	a1+4(FP), BX
-	MOVL	a2+8(FP), CX
-	MOVL	a3+12(FP), DX
-	MOVL	a4+16(FP), SI
-	MOVL	a5+20(FP), DI
-	MOVL	a6+24(FP), BP
-	INVOKE_SYSCALL
-	CMPL	AX, $0xfffff001
-	JLS	ok2
-	MOVL	$-1, r1+28(FP)
-	MOVL	$0, r2+32(FP)
-	NEGL	AX
-	MOVL	AX, err+36(FP)
-	RET
-ok2:
-	MOVL	AX, r1+28(FP)
-	MOVL	DX, r2+32(FP)
-	MOVL	$0, err+36(FP)
-	RET
-
 // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
 TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16
 	MOVL	trap+0(FP), AX	// syscall entry
diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s
index 0b55a30..a981259 100644
--- a/src/syscall/asm_linux_amd64.s
+++ b/src/syscall/asm_linux_amd64.s
@@ -84,29 +84,6 @@
 	MOVQ	$0, err+48(FP)
 	RET
 
-// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
-TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
-	MOVQ	a1+8(FP), DI
-	MOVQ	a2+16(FP), SI
-	MOVQ	a3+24(FP), DX
-	MOVQ	a4+32(FP), R10
-	MOVQ	a5+40(FP), R8
-	MOVQ	a6+48(FP), R9
-	MOVQ	trap+0(FP), AX	// syscall entry
-	SYSCALL
-	CMPQ	AX, $0xfffffffffffff001
-	JLS	ok2
-	MOVQ	$-1, r1+56(FP)
-	MOVQ	$0, r2+64(FP)
-	NEGQ	AX
-	MOVQ	AX, err+72(FP)
-	RET
-ok2:
-	MOVQ	AX, r1+56(FP)
-	MOVQ	DX, r2+64(FP)
-	MOVQ	$0, err+72(FP)
-	RET
-
 // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
 TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32
 	MOVQ	a1+8(FP), DI
diff --git a/src/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s
index 6bb4df8..5010317 100644
--- a/src/syscall/asm_linux_arm.s
+++ b/src/syscall/asm_linux_arm.s
@@ -70,34 +70,6 @@
 	BL	runtime·exitsyscall(SB)
 	RET
 
-// func RawSyscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
-// Actually RawSyscall5 but the rest of the code expects it to be named RawSyscall6.
-TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
-	MOVW	trap+0(FP), R7	// syscall entry
-	MOVW	a1+4(FP), R0
-	MOVW	a2+8(FP), R1
-	MOVW	a3+12(FP), R2
-	MOVW	a4+16(FP), R3
-	MOVW	a5+20(FP), R4
-	MOVW	a6+24(FP), R5
-	SWI	$0
-	MOVW	$0xfffff001, R6
-	CMP	R6, R0
-	BLS	ok2
-	MOVW	$-1, R1
-	MOVW	R1, r1+28(FP)
-	MOVW	$0, R2
-	MOVW	R2, r2+32(FP)
-	RSB	$0, R0, R0
-	MOVW	R0, err+36(FP)
-	RET
-ok2:
-	MOVW	R0, r1+28(FP)
-	MOVW	R1, r2+32(FP)
-	MOVW	$0, R0
-	MOVW	R0, err+36(FP)
-	RET
-
 #define SYS__LLSEEK 140  /* from zsysnum_linux_arm.go */
 // func seek(fd int, offset int64, whence int) (newoffset int64, errno int)
 // Implemented in assembly to avoid allocation when
diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s
index 6c50fa9..c9c6bfa 100644
--- a/src/syscall/asm_linux_arm64.s
+++ b/src/syscall/asm_linux_arm64.s
@@ -80,29 +80,6 @@
 	MOVD	ZR, err+48(FP)	// errno
 	RET
 
-TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
-	MOVD	a1+8(FP), R0
-	MOVD	a2+16(FP), R1
-	MOVD	a3+24(FP), R2
-	MOVD	a4+32(FP), R3
-	MOVD	a5+40(FP), R4
-	MOVD	a6+48(FP), R5
-	MOVD	trap+0(FP), R8	// syscall entry
-	SVC
-	CMN	$4095, R0
-	BCC	ok
-	MOVD	$-1, R4
-	MOVD	R4, r1+56(FP)	// r1
-	MOVD	ZR, r2+64(FP)	// r2
-	NEG	R0, R0
-	MOVD	R0, err+72(FP)	// errno
-	RET
-ok:
-	MOVD	R0, r1+56(FP)	// r1
-	MOVD	R1, r2+64(FP)	// r2
-	MOVD	ZR, err+72(FP)	// errno
-	RET
-
 // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
 TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32
 	MOVD	a1+8(FP), R0
diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s
index a75d0f7..bc2f72c 100644
--- a/src/syscall/asm_linux_mips64x.s
+++ b/src/syscall/asm_linux_mips64x.s
@@ -80,27 +80,6 @@
 	MOVV	R0, err+48(FP)	// errno
 	RET
 
-TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
-	MOVV	a1+8(FP), R4
-	MOVV	a2+16(FP), R5
-	MOVV	a3+24(FP), R6
-	MOVV	a4+32(FP), R7
-	MOVV	a5+40(FP), R8
-	MOVV	a6+48(FP), R9
-	MOVV	trap+0(FP), R2	// syscall entry
-	SYSCALL
-	BEQ	R7, ok2
-	MOVV	$-1, R1
-	MOVV	R1, r1+56(FP)	// r1
-	MOVV	R0, r2+64(FP)	// r2
-	MOVV	R2, err+72(FP)	// errno
-	RET
-ok2:
-	MOVV	R2, r1+56(FP)	// r1
-	MOVV	R3, r2+64(FP)	// r2
-	MOVV	R0, err+72(FP)	// errno
-	RET
-
 // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
 TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32
 	MOVV	a1+8(FP), R4
diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s
index 04f90f6..04fad40 100644
--- a/src/syscall/asm_linux_mipsx.s
+++ b/src/syscall/asm_linux_mipsx.s
@@ -115,29 +115,6 @@
 	MOVW	R0, err+24(FP)	// errno
 	RET
 
-TEXT ·RawSyscall6(SB),NOSPLIT,$20-40
-	MOVW	a1+4(FP), R4
-	MOVW	a2+8(FP), R5
-	MOVW	a3+12(FP), R6
-	MOVW	a4+16(FP), R7
-	MOVW	a5+20(FP), R8
-	MOVW	a6+24(FP), R9
-	MOVW	R8, 16(R29)
-	MOVW	R9, 20(R29)
-	MOVW	trap+0(FP), R2	// syscall entry
-	SYSCALL
-	BEQ	R7, ok2
-	MOVW	$-1, R1
-	MOVW	R1, r1+28(FP)	// r1
-	MOVW	R0, r2+32(FP)	// r2
-	MOVW	R2, err+36(FP)	// errno
-	RET
-ok2:
-	MOVW	R2, r1+28(FP)	// r1
-	MOVW	R3, r2+32(FP)	// r2
-	MOVW	R0, err+36(FP)	// errno
-	RET
-
 // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
 TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-16
 	MOVW	a1+4(FP), R4
diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s
index bf701e5..4c9c383 100644
--- a/src/syscall/asm_linux_ppc64x.s
+++ b/src/syscall/asm_linux_ppc64x.s
@@ -80,27 +80,6 @@
 	MOVD	R0, err+48(FP)	// errno
 	RET
 
-TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
-	MOVD	a1+8(FP), R3
-	MOVD	a2+16(FP), R4
-	MOVD	a3+24(FP), R5
-	MOVD	a4+32(FP), R6
-	MOVD	a5+40(FP), R7
-	MOVD	a6+48(FP), R8
-	MOVD	trap+0(FP), R9	// syscall entry
-	SYSCALL R9
-	BVC	ok2
-	MOVD	$-1, R4
-	MOVD	R4, r1+56(FP)	// r1
-	MOVD	R0, r2+64(FP)	// r2
-	MOVD	R3, err+72(FP)	// errno
-	RET
-ok2:
-	MOVD	R3, r1+56(FP)	// r1
-	MOVD	R0, r2+64(FP)	// r2
-	MOVD	R0, err+72(FP)	// errno
-	RET
-
 // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
 TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32
 	MOVD	a1+8(FP), R3
diff --git a/src/syscall/asm_linux_riscv64.s b/src/syscall/asm_linux_riscv64.s
index f172dd3..c7e1003 100644
--- a/src/syscall/asm_linux_riscv64.s
+++ b/src/syscall/asm_linux_riscv64.s
@@ -80,30 +80,6 @@
 	MOV	A0, err+48(FP)	// errno
 	RET
 
-// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
-TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
-	MOV	a1+8(FP), A0
-	MOV	a2+16(FP), A1
-	MOV	a3+24(FP), A2
-	MOV	a4+32(FP), A3
-	MOV	a5+40(FP), A4
-	MOV	a6+48(FP), A5
-	MOV	trap+0(FP), A7	// syscall entry
-	ECALL
-	MOV	$-4096, T0
-	BLTU	T0, A0, err
-	MOV	A0, r1+56(FP)	// r1
-	MOV	A1, r2+64(FP)	// r2
-	MOV	ZERO, err+72(FP)	// errno
-	RET
-err:
-	MOV	$-1, T0
-	MOV	T0, r1+56(FP)	// r1
-	MOV	ZERO, r2+64(FP)	// r2
-	SUB	A0, ZERO, A0
-	MOV	A0, err+72(FP)	// errno
-	RET
-
 // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
 TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32
 	MOV	a1+8(FP), A0
diff --git a/src/syscall/asm_linux_s390x.s b/src/syscall/asm_linux_s390x.s
index 86a5c51..3fbda38 100644
--- a/src/syscall/asm_linux_s390x.s
+++ b/src/syscall/asm_linux_s390x.s
@@ -83,29 +83,6 @@
 	MOVD	$0, err+48(FP)	// errno
 	RET
 
-// func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
-TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
-	MOVD	a1+8(FP), R2
-	MOVD	a2+16(FP), R3
-	MOVD	a3+24(FP), R4
-	MOVD	a4+32(FP), R5
-	MOVD	a5+40(FP), R6
-	MOVD	a6+48(FP), R7
-	MOVD	trap+0(FP), R1	// syscall entry
-	SYSCALL
-	MOVD	$0xfffffffffffff001, R8
-	CMPUBLT	R2, R8, ok2
-	MOVD	$-1, r1+56(FP)
-	MOVD	$0, r2+64(FP)
-	NEG	R2, R2
-	MOVD	R2, err+72(FP)	// errno
-	RET
-ok2:
-	MOVD	R2, r1+56(FP)
-	MOVD	R3, r2+64(FP)
-	MOVD	$0, err+72(FP)	// errno
-	RET
-
 // func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr)
 TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-32
 	MOVD	$0, R2
diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go
index a10bfbb..b0e2cdb 100644
--- a/src/syscall/syscall_linux.go
+++ b/src/syscall/syscall_linux.go
@@ -19,6 +19,12 @@
 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
+
+// N.B. RawSyscall6 is provided via linkname by runtime/internal/syscall.
+//
+// Errno is uintptr and thus compatible with the runtime/internal/syscall
+// definition.
+
 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
 
 func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr)