From 002cf2820d49009e6e5590d53b8ee640bfd6eb5c Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Tue, 23 Feb 2016 01:26:50 -0500 Subject: runtime, syscall: switch linux/386 to use int 0x80 Like bionic, musl also doesn't provide vsyscall helper in %gs:0x10, and as int $0x80 is as fast as calling %gs:0x10, just use int $0x80 always. Because we're no longer using vsyscall in VDSO, get rid of VDSO code for linux/386 too. Fixes #14476. Change-Id: I00ec8652060700e0a3c9b524bfe3c16a810263f6 Reviewed-on: https://go-review.googlesource.com/19833 Run-TryBot: Minux Ma Reviewed-by: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-on: https://go-review.googlesource.com/22038 Reviewed-by: Brad Fitzpatrick --- src/runtime/os_linux_386.go | 5 ----- src/runtime/rt0_linux_386.s | 8 -------- src/runtime/runtime1.go | 2 +- src/runtime/signal_386.go | 25 +------------------------ src/runtime/sys_linux_386.s | 25 ++++++++++--------------- src/syscall/asm_linux_386.s | 13 ++----------- 6 files changed, 14 insertions(+), 64 deletions(-) diff --git a/src/runtime/os_linux_386.go b/src/runtime/os_linux_386.go index 3577a2406b..0f39cade3b 100644 --- a/src/runtime/os_linux_386.go +++ b/src/runtime/os_linux_386.go @@ -15,8 +15,6 @@ const ( _AT_SYSINFO = 32 ) -var _vdso uint32 - func sysargs(argc int32, argv **byte) { // skip over argv, envv to get to auxv n := argc + 1 @@ -28,9 +26,6 @@ func sysargs(argc int32, argv **byte) { for i := 0; auxv[i] != _AT_NULL; i += 2 { switch auxv[i] { - case _AT_SYSINFO: - _vdso = auxv[i+1] - case _AT_RANDOM: startupRandomData = (*[16]byte)(unsafe.Pointer(uintptr(auxv[i+1])))[:] } diff --git a/src/runtime/rt0_linux_386.s b/src/runtime/rt0_linux_386.s index 59a30b41e8..23bfc98b10 100644 --- a/src/runtime/rt0_linux_386.s +++ b/src/runtime/rt0_linux_386.s @@ -73,11 +73,3 @@ GLOBL _rt0_386_linux_lib_argv<>(SB),NOPTR, $4 TEXT main(SB),NOSPLIT,$0 JMP runtime·rt0_go(SB) - -TEXT _fallback_vdso(SB),NOSPLIT,$0 - INT $0x80 - RET - -DATA runtime·_vdso(SB)/4, $_fallback_vdso(SB) -GLOBL runtime·_vdso(SB), NOPTR, $4 - diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index f63e09cc61..400ea296a9 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -52,7 +52,7 @@ var ( argv **byte ) -// nosplit for use in linux/386 startup linux_setup_vdso +// nosplit for use in linux startup sysargs //go:nosplit func argv_index(argv **byte, i int32) *byte { return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*sys.PtrSize)) diff --git a/src/runtime/signal_386.go b/src/runtime/signal_386.go index 0374f4a2d7..25187dad74 100644 --- a/src/runtime/signal_386.go +++ b/src/runtime/signal_386.go @@ -142,30 +142,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { level, _, docrash := gotraceback() if level > 0 { goroutineheader(gp) - - // On Linux/386, all system calls go through the vdso kernel_vsyscall routine. - // Normally we don't see those PCs, but during signals we can. - // If we see a PC in the vsyscall area (it moves around, but near the top of memory), - // assume we're blocked in the vsyscall routine, which has saved - // three words on the stack after the initial call saved the caller PC. - // Pop all four words off SP and use the saved PC. - // The check of the stack bounds here should suffice to avoid a fault - // during the actual PC pop. - // If we do load a bogus PC, not much harm done: we weren't going - // to get a decent traceback anyway. - // TODO(rsc): Make this more precise: we should do more checks on the PC, - // and we should find out whether different versions of the vdso page - // use different prologues that store different amounts on the stack. - pc := uintptr(c.eip()) - sp := uintptr(c.esp()) - if GOOS == "linux" && pc >= 0xf4000000 && gp.stack.lo <= sp && sp+16 <= gp.stack.hi { - // Assume in vsyscall page. - sp += 16 - pc = *(*uintptr)(unsafe.Pointer(sp - 4)) - print("runtime: unwind vdso kernel_vsyscall: pc=", hex(pc), " sp=", hex(sp), "\n") - } - - tracebacktrap(pc, sp, 0, gp) + tracebacktrap(uintptr(c.eip()), uintptr(c.esp()), 0, gp) if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning { // tracebackothers on original m skipped this one; trace it now. goroutineheader(_g_.m.curg) diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s index 1a3aaf0104..4a74196032 100644 --- a/src/runtime/sys_linux_386.s +++ b/src/runtime/sys_linux_386.s @@ -12,16 +12,17 @@ // Most linux systems use glibc's dynamic linker, which puts the // __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position -// independent code and setldt in this file does the same in the statically -// linked case. Android, however, uses bionic's dynamic linker, which does not -// save the helper anywhere, and so the only way to invoke a syscall from -// position independent code is boring old int $0x80 (which is also what -// bionic's syscall wrappers use). -#ifdef GOOS_android +// independent code and setldt in runtime does the same in the statically +// linked case. However, systems that use alternative libc such as Android's +// bionic and musl, do not save the helper anywhere, and so the only way to +// invoke a syscall from position independent code is boring old int $0x80 +// (which is also what syscall wrappers in bionic/musl use). +// +// The benchmarks also showed that using int $0x80 is as fast as calling +// *%gs:0x10 except on AMD Opteron. See https://golang.org/cl/19833 +// for the benchmark program and raw data. +//#define INVOKE_SYSCALL CALL 0x10(GS) // non-portable #define INVOKE_SYSCALL INT $0x80 -#else -#define INVOKE_SYSCALL CALL 0x10(GS) -#endif TEXT runtime·exit(SB),NOSPLIT,$0 MOVL $252, AX // syscall number @@ -434,12 +435,6 @@ TEXT runtime·setldt(SB),NOSPLIT,$32 */ ADDL $0x4, DX // address MOVL DX, 0(DX) - // We copy the glibc dynamic linker behaviour of storing the - // __kernel_vsyscall entry point at 0x10(GS) so that it can be invoked - // by "CALL 0x10(GS)" in all situations, not only those where the - // binary is actually dynamically linked. - MOVL runtime·_vdso(SB), AX - MOVL AX, 0x10(DX) #endif // set up user_desc diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s index c94060571b..228a542cf1 100644 --- a/src/syscall/asm_linux_386.s +++ b/src/syscall/asm_linux_386.s @@ -12,18 +12,9 @@ // func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr); // Trap # in AX, args in BX CX DX SI DI, return in AX -// Most linux systems use glibc's dynamic linker, which puts the -// __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position -// independent code and setldt in runtime does the same in the statically -// linked case. Android, however, uses bionic's dynamic linker, which does not -// save the helper anywhere, and so the only way to invoke a syscall from -// position independent code is boring old int $0x80 (which is also what -// bionic's syscall wrappers use). -#ifdef GOOS_android +// See ../runtime/sys_linux_386.s for the reason why we always use int 0x80 +// instead of the glibc-specific "CALL 0x10(GS)". #define INVOKE_SYSCALL INT $0x80 -#else -#define INVOKE_SYSCALL CALL 0x10(GS) -#endif TEXT ·Syscall(SB),NOSPLIT,$0-28 CALL runtime·entersyscall(SB) -- cgit v1.2.3-54-g00ecf