runtime: fix errno sign for some mmap and mincore cases

The caller of mmap expects it to return a positive errno value, but the
linux-arm64 and nacl-386 system calls returned a negative errno value.
Correct them to negate the errno value.

The caller of mincore expects it to return a negative errno value (yes,
this is inconsistent), but the linux-mips64x and linux-ppc64x system
call returned a positive errno value.  Correct them to negate the errno
value.

Add a test that mmap returns errno with the correct sign.  Brad added a
test for mincore's errno value in https://golang.org/cl/19457.

Fixes #14297.

Change-Id: I2b93f32e679bd1eae1c9aef9ae7bcf0ba39521b5
Reviewed-on: https://go-review.googlesource.com/19455
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Minux Ma <minux@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/runtime/export_linux_test.go b/src/runtime/export_linux_test.go
index c8b9746..61d6ae4 100644
--- a/src/runtime/export_linux_test.go
+++ b/src/runtime/export_linux_test.go
@@ -7,3 +7,4 @@
 package runtime
 
 var NewOSProc0 = newosproc0
+var Mincore = mincore
diff --git a/src/runtime/export_mmap_test.go b/src/runtime/export_mmap_test.go
new file mode 100644
index 0000000..11ea076
--- /dev/null
+++ b/src/runtime/export_mmap_test.go
@@ -0,0 +1,15 @@
+// Copyright 2016 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+// Export guts for testing.
+
+package runtime
+
+var Mmap = mmap
+
+const ENOMEM = _ENOMEM
+const MAP_ANON = _MAP_ANON
+const MAP_PRIVATE = _MAP_PRIVATE
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index b09022b..5400c1d 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -28,8 +28,6 @@
 var LockedOSThread = lockedOSThread
 var Xadduintptr = atomic.Xadduintptr
 
-var Mincore = mincore
-
 var FuncPC = funcPC
 
 var Fastlog2 = fastlog2
diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go
index 1e388ec..c3fe610 100644
--- a/src/runtime/mem_bsd.go
+++ b/src/runtime/mem_bsd.go
@@ -59,9 +59,9 @@
 	return p
 }
 
-func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) {
-	const _ENOMEM = 12
+const _ENOMEM = 12
 
+func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) {
 	mSysStatInc(sysStat, n)
 
 	// On 64-bit, we don't actually have v reserved, so tread carefully.
diff --git a/src/runtime/os2_nacl.go b/src/runtime/os2_nacl.go
index 0c91e0f..d8c88db 100644
--- a/src/runtime/os2_nacl.go
+++ b/src/runtime/os2_nacl.go
@@ -10,18 +10,19 @@
 
 	// native_client/src/trusted/service_runtime/include/sys/errno.h
 	// The errors are mainly copied from Linux.
-	_EPERM           = 1        /* Operation not permitted */
-	_ENOENT          = 2        /* No such file or directory */
-	_ESRCH           = 3        /* No such process */
-	_EINTR           = 4        /* Interrupted system call */
-	_EIO             = 5        /* I/O error */
-	_ENXIO           = 6        /* No such device or address */
-	_E2BIG           = 7        /* Argument list too long */
-	_ENOEXEC         = 8        /* Exec format error */
-	_EBADF           = 9        /* Bad file number */
-	_ECHILD          = 10       /* No child processes */
-	_EAGAIN          = 11       /* Try again */
-	_ENOMEM          = 12       /* Out of memory */
+	_EPERM   = 1  /* Operation not permitted */
+	_ENOENT  = 2  /* No such file or directory */
+	_ESRCH   = 3  /* No such process */
+	_EINTR   = 4  /* Interrupted system call */
+	_EIO     = 5  /* I/O error */
+	_ENXIO   = 6  /* No such device or address */
+	_E2BIG   = 7  /* Argument list too long */
+	_ENOEXEC = 8  /* Exec format error */
+	_EBADF   = 9  /* Bad file number */
+	_ECHILD  = 10 /* No child processes */
+	_EAGAIN  = 11 /* Try again */
+	// _ENOMEM is defined in mem_bsd.go for nacl.
+	// _ENOMEM          = 12       /* Out of memory */
 	_EACCES          = 13       /* Permission denied */
 	_EFAULT          = 14       /* Bad address */
 	_EBUSY           = 16       /* Device or resource busy */
diff --git a/src/runtime/runtime_mmap_test.go b/src/runtime/runtime_mmap_test.go
new file mode 100644
index 0000000..ff5e733
--- /dev/null
+++ b/src/runtime/runtime_mmap_test.go
@@ -0,0 +1,30 @@
+// Copyright 2016 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package runtime_test
+
+import (
+	"runtime"
+	"runtime/internal/sys"
+	"testing"
+)
+
+// Test that the error value returned by mmap is positive, as that is
+// what the code in mem_bsd.go, mem_darwin.go, and mem_linux.go expects.
+// See the uses of ENOMEM in sysMap in those files.
+func TestMmapErrorSign(t *testing.T) {
+	p := runtime.Mmap(nil, ^uintptr(0)&^(sys.PhysPageSize-1), 0, runtime.MAP_ANON|runtime.MAP_PRIVATE, -1, 0)
+
+	// The runtime.mmap function is nosplit, but t.Errorf is not.
+	// Reset the pointer so that we don't get an "invalid stack
+	// pointer" error from t.Errorf if we call it.
+	v := uintptr(p)
+	p = nil
+
+	if v != runtime.ENOMEM {
+		t.Errorf("mmap = %v, want %v", v, runtime.ENOMEM)
+	}
+}
diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s
index ca0e07a..94c101a 100644
--- a/src/runtime/sys_linux_arm64.s
+++ b/src/runtime/sys_linux_arm64.s
@@ -269,6 +269,9 @@
 
 	MOVD	$SYS_mmap, R8
 	SVC
+	CMN	$4095, R0
+	BCC	2(PC)
+	NEG	R0,R0
 	MOVD	R0, ret+32(FP)
 	RET
 
diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s
index 6ccb38f..26437dd 100644
--- a/src/runtime/sys_linux_mips64x.s
+++ b/src/runtime/sys_linux_mips64x.s
@@ -168,6 +168,7 @@
 	MOVV	dst+16(FP), R6
 	MOVV	$SYS_mincore, R2
 	SYSCALL
+	SUBVU	R2, R0, R2	// caller expects negative errno
 	MOVW	R2, ret+24(FP)
 	RET
 
diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s
index ba410c5..d063e02 100644
--- a/src/runtime/sys_linux_ppc64x.s
+++ b/src/runtime/sys_linux_ppc64x.s
@@ -153,6 +153,7 @@
 	MOVD	n+8(FP), R4
 	MOVD	dst+16(FP), R5
 	SYSCALL	$SYS_mincore
+	NEG	R3		// caller expects negative errno
 	MOVW	R3, ret+24(FP)
 	RET
 
diff --git a/src/runtime/sys_nacl_386.s b/src/runtime/sys_nacl_386.s
index bf2d36e..e69a0b7 100644
--- a/src/runtime/sys_nacl_386.s
+++ b/src/runtime/sys_nacl_386.s
@@ -227,6 +227,9 @@
 	LEAL	24(SP), AX
 	MOVL	AX, 20(SP)
 	NACL_SYSCALL(SYS_mmap)
+	CMPL	AX, $-4095
+	JNA	2(PC)
+	NEGL	AX
 	MOVL	AX, ret+24(FP)
 	RET