]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: SysMap uses MAP_FIXED if needed on 64-bit Linux
authorJonathan Mark <jhmark@xenops.com>
Wed, 8 Jun 2011 04:50:10 +0000 (21:50 -0700)
committerIan Lance Taylor <iant@golang.org>
Wed, 8 Jun 2011 04:50:10 +0000 (21:50 -0700)
This change was adapted from gccgo's libgo/runtime/mem.c at
Ian Taylor's suggestion.  It fixes all.bash failing with
"address space conflict: map() =" on amd64 Linux with kernel
version 2.6.32.8-grsec-2.1.14-modsign-xeon-64.
With this change, SysMap will use MAP_FIXED to allocate its desired
address space, after first calling mincore to check that there is
nothing else mapped there.

R=iant, dave, n13m3y3r, rsc
CC=golang-dev
https://golang.org/cl/4438091

src/pkg/runtime/linux/386/sys.s
src/pkg/runtime/linux/amd64/sys.s
src/pkg/runtime/linux/arm/sys.s
src/pkg/runtime/linux/mem.c
src/pkg/runtime/runtime.h

index 868a0d901a89d9e3d9e69d69bcd44ba642162e7d..e8b42332428629369c63e8976d6f864842cec4b0 100644 (file)
@@ -47,6 +47,14 @@ TEXT runtime·setitimer(SB),7,$0-24
        INT     $0x80
        RET
 
+TEXT runtime·mincore(SB),7,$0-24
+       MOVL    $218, AX                        // syscall - mincore
+       MOVL    4(SP), BX
+       MOVL    8(SP), CX
+       MOVL    12(SP), DX
+       INT     $0x80
+       RET
+
 TEXT runtime·gettime(SB), 7, $32
        MOVL    $78, AX                 // syscall - gettimeofday
        LEAL    8(SP), BX
index eadd30005880b7509cb4e96ebd743070d6f30e90..66fdab2083db2b706b0b353a806ff66a5b0ed235 100644 (file)
@@ -53,6 +53,14 @@ TEXT runtime·setitimer(SB),7,$0-24
        SYSCALL
        RET
 
+TEXT runtime·mincore(SB),7,$0-24
+       MOVQ    8(SP), DI
+       MOVQ    16(SP), SI
+       MOVQ    24(SP), DX
+       MOVL    $27, AX                 // syscall entry
+       SYSCALL
+       RET
+
 TEXT runtime·gettime(SB), 7, $32
        LEAQ    8(SP), DI
        MOVQ    $0, SI
index 2b5365bd86475b09270d54f3277b9aaadcc50dae..ab53498222ff65b37f3cc41ec6bc69f4bd9b19f6 100644 (file)
@@ -26,6 +26,7 @@
 #define SYS_exit_group (SYS_BASE + 248)
 #define SYS_munmap (SYS_BASE + 91)
 #define SYS_setitimer (SYS_BASE + 104)
+#define SYS_mincore (SYS_BASE + 219)
 #define SYS_gettid (SYS_BASE + 224)
 #define SYS_tkill (SYS_BASE + 238)
 
@@ -91,6 +92,14 @@ TEXT runtime·setitimer(SB),7,$0
        SWI     $0
        RET
 
+TEXT runtime·mincore(SB),7,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    8(FP), R2
+       MOVW    $SYS_mincore, R7
+       SWI     $0
+       RET
+
 TEXT runtime·gettime(SB),7,$32
        /* dummy version - return 0,0 */
        MOVW    $0, R1
index 02f798732fed60c4a6fbf920b0b47e6feb54fe9c..38ca7e4a0f973f60cb61b503a7246f88d8024b26 100644 (file)
@@ -3,6 +3,30 @@
 #include "os.h"
 #include "malloc.h"
 
+enum
+{
+       ENOMEM = 12,
+};
+
+static int32
+addrspace_free(void *v, uintptr n)
+{
+       uintptr page_size = 4096;
+       uintptr off;
+       int8 one_byte;
+
+       for(off = 0; off < n; off += page_size) {
+               int32 errval = runtime·mincore((int8 *)v + off, page_size, (void *)&one_byte);
+               // errval is 0 if success, or -(error_code) if error.
+               if (errval == 0 || errval != -ENOMEM)
+                       return 0;
+       }
+       USED(v);
+       USED(n);
+       return 1;
+}
+
+
 void*
 runtime·SysAlloc(uintptr n)
 {
@@ -54,11 +78,6 @@ runtime·SysReserve(void *v, uintptr n)
        return p;
 }
 
-enum
-{
-       ENOMEM = 12,
-};
-
 void
 runtime·SysMap(void *v, uintptr n)
 {
@@ -69,6 +88,11 @@ runtime·SysMap(void *v, uintptr n)
        // On 64-bit, we don't actually have v reserved, so tread carefully.
        if(sizeof(void*) == 8) {
                p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
+               if(p != v && addrspace_free(v, n)) {
+                       // On some systems, mmap ignores v without
+                       // MAP_FIXED, so retry if the address space is free.
+                       p = runtime·mmap(v, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+               }
                if(p == (void*)ENOMEM)
                        runtime·throw("runtime: out of memory");
                if(p != v) {
index 2b2b34a3ce456bfae60eb344ff4fcd37f8dd397d..f3ccff1bcd304ba519807ec743e7bc1d122055c9 100644 (file)
@@ -413,6 +413,7 @@ int32       runtime·gotraceback(void);
 void   runtime·traceback(uint8 *pc, uint8 *sp, uint8 *lr, G* gp);
 void   runtime·tracebackothers(G*);
 int32  runtime·write(int32, void*, int32);
+int32  runtime·mincore(void*, uintptr, byte*);
 bool   runtime·cas(uint32*, uint32, uint32);
 bool   runtime·casp(void**, void*, void*);
 uint32 runtime·xadd(uint32 volatile*, int32);