Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

possible non-387 instructions in a GO386=387 build #12970

Closed
sbinet opened this issue Oct 17, 2015 · 9 comments
Closed

possible non-387 instructions in a GO386=387 build #12970

sbinet opened this issue Oct 17, 2015 · 9 comments

Comments

@sbinet
Copy link
Member

sbinet commented Oct 17, 2015

hi,

I tried to cross-compile this simple program:

package main
func main() { println("hello") }

from a linux-64b host to a PC/104 target.
I had rebuilt the go-1.5.1 from sources, exporting GO386=387.

running on the host:

$ go build -o hello-1.5 ./hello.go

and then copying on the target, running under gdb, I get:

$ gdb ./hello-1.5
(gdb) r
Starting program: /root/hello-1.5

Program received signal SIGILL, Illegal instruction.
runtime.prefetcht0 () at /root/dev/go/src/runtime/asm_386.s:1669
warning: Source file is more recent than executable.
1669 PREFETCHT0 (AX)
(gdb) bt
#0  runtime.prefetcht0 () at /root/dev/go/src/runtime/asm_386.s:1669
#1  0x0807370e in runtime.testAtomic64 () at /root/dev/go/src/runtime/runtime1.go:98
#2  0x08073ef5 in runtime.check () at /root/dev/go/src/runtime/runtime1.go:290
#3  0x08088fba in runtime.rt0_go () at /root/dev/go/src/runtime/asm_386.s:105
#4  0x00000000 in ?? ()
(gdb) lis
1664 // traceback from goexit1 must hit code range of goexit
1665 BYTE $0x90 // NOP
1666
1667 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-4
1668 MOVL addr+0(FP), AX
1669 PREFETCHT0 (AX)
1670 RET
1671
1672 TEXT runtime·prefetcht1(SB),NOSPLIT,$0-4
1673 MOVL addr+0(FP), AX

doing the same dance with go-1.4.3, I get instead:

$ gdb ./hello-1.4
(gdb) r
Starting program: /root/hello-1.4

Program received signal SIGILL, Illegal instruction.
runtime.atomicload64 () at /root/go1.4/src/runtime/asm_386.s:575
575 BYTE $0x0f; BYTE $0x6f; BYTE $0x00
(gdb) bt
#0  runtime.atomicload64 () at /root/go1.4/src/runtime/asm_386.s:575
#1  0x080cd15c in TestAtomic64 () at /root/go1.4/src/runtime/runtime.c:158
#2  0x080cd5d7 in runtime.check () at /root/go1.4/src/runtime/runtime.c:263
#3  0x080badbb in runtime.rt0_go () at /root/go1.4/src/runtime/asm_386.s:91
#4  0x00000000 in ?? ()
(gdb) lis
570 // uint64 atomicload64(uint64 volatile* addr);
571 TEXT runtime·atomicload64(SB), NOSPLIT, $0-12
572 MOVL ptr+0(FP), AX
573 LEAL ret_lo+4(FP), BX
574 // MOVQ (%EAX), %MM0
575 BYTE $0x0f; BYTE $0x6f; BYTE $0x00
576 // MOVQ %MM0, 0(%EBX)
577 BYTE $0x0f; BYTE $0x7f; BYTE $0x03
578 // EMMS
579 BYTE $0x0F; BYTE $0x77

Taru Karttunen on golang-nuts says:

The issue is the 64bit atomics using MMX. If they are 64-bit aligned
then using FISTP/FILD instead when GO386=387 should probably fix this.

additional informations:

the linux 64b host is running the latest archlinux.
the pc/104 target is running a debian-8.2 (jessie):

$ uname -a
Linux pc104box 3.16.0-4-586 #1 Debian 3.16.7-ckt11-1+deb8u5
(2015-10-09) i586 GNU/Linux

$ cat /proc/cpuinfo | grep flags
flags : fpu tsc cx8

here are the complete specs for my pc/104 box:
http://pc104.org/hardware-specifications/pc104/

@bradfitz
Copy link
Contributor

For what it's worth, we have a linux-386-387 builder, but it's running on Haswell, so we don't actually trap on MMX, etc. It's mostly there to catch that the resulting code still compiles & runs.

Perhaps we can add a binary verifier step to that builder, scanning for bogus instructions, ala the Nacl verifier? We don't support/require self-modifying code anymore, so maybe it's actually verifiable? @minux, @randall77, ... ?

@randall77
Copy link
Contributor

GO386=387: use x87 for floating point operations; should support all x86 chips (Pentium MMX or later).

I don't think we support non-MMX chips. We could probably drop prefetching from 386, but we still need atomic 64-bit loads. How would you propose to do them?

@minux
Copy link
Member

minux commented Oct 17, 2015 via email

@bradfitz
Copy link
Contributor

Maybe we can detect that at start-up in the runtime and fail early with a useful error message.

@randall77
Copy link
Contributor

We do detect it at startup, that's what the traces above show. We fail with an "illegal instruction" trap. It's not quite "Go do not support this processor because it is missing MMX instructions" but people playing with pre-MMX chips aren't neophytes - they should know what that error means.

@minux
Copy link
Member

minux commented Oct 17, 2015 via email

@gopherbot
Copy link

CL https://golang.org/cl/15998 mentions this issue.

@gopherbot
Copy link

CL https://golang.org/cl/15999 mentions this issue.

@jeffallen
Copy link
Contributor

I really like minux's proposal because i really hate leaving older x86 embedded systems without go support.

minux added a commit that referenced this issue Nov 13, 2015
It doesn't seem to help on modern processors and it makes Go impossible to run
on Pentium MMX (which is the documented minimum hardware requirement.)

Old is with prefetch, new is w/o. Both are compiled with GO386=sse2.
Benchmarking is done on Intel(R) Core(TM) i5-3570K CPU @ 3.40GHz.

name                     old time/op    new time/op    delta
BinaryTree17-4              2.89s ± 2%     2.87s ± 0%    ~     (p=0.061 n=11+10)
Fannkuch11-4                3.65s ± 0%     3.65s ± 0%    ~     (p=0.365 n=11+11)
FmtFprintfEmpty-4          52.1ns ± 0%    52.1ns ± 0%    ~      (p=0.065 n=10+9)
FmtFprintfString-4          168ns ± 0%     167ns ± 0%  -0.48%   (p=0.000 n=8+10)
FmtFprintfInt-4             167ns ± 0%     167ns ± 1%    ~      (p=0.591 n=9+10)
FmtFprintfIntInt-4          295ns ± 0%     292ns ± 0%  -0.99%   (p=0.000 n=9+10)
FmtFprintfPrefixedInt-4     327ns ± 0%     326ns ± 0%  -0.24%  (p=0.007 n=10+10)
FmtFprintfFloat-4           431ns ± 0%     431ns ± 0%  -0.07%  (p=0.000 n=10+11)
FmtManyArgs-4              1.13µs ± 0%    1.13µs ± 0%  -0.37%  (p=0.009 n=11+11)
GobDecode-4                9.36ms ± 1%    9.33ms ± 0%  -0.31%  (p=0.006 n=11+10)
GobEncode-4                7.38ms ± 1%    7.38ms ± 1%    ~     (p=0.797 n=11+11)
Gzip-4                      394ms ± 0%     395ms ± 1%    ~     (p=0.519 n=11+11)
Gunzip-4                   65.4ms ± 0%    65.4ms ± 0%    ~     (p=0.739 n=10+10)
HTTPClientServer-4         52.4µs ± 1%    52.5µs ± 1%    ~     (p=0.748 n=11+11)
JSONEncode-4               19.0ms ± 0%    19.0ms ± 0%    ~      (p=0.780 n=9+10)
JSONDecode-4               59.6ms ± 0%    59.6ms ± 0%    ~      (p=0.720 n=9+10)
Mandelbrot200-4            4.09ms ± 0%    4.09ms ± 0%    ~      (p=0.295 n=11+9)
GoParse-4                  3.45ms ± 1%    3.43ms ± 1%  -0.35%  (p=0.040 n=11+11)
RegexpMatchEasy0_32-4       101ns ± 1%     101ns ± 1%    ~     (p=1.000 n=11+11)
RegexpMatchEasy0_1K-4       796ns ± 0%     796ns ± 0%    ~      (p=0.954 n=10+8)
RegexpMatchEasy1_32-4       110ns ± 0%     110ns ± 1%    ~      (p=0.289 n=9+11)
RegexpMatchEasy1_1K-4       991ns ± 0%     991ns ± 0%    ~      (p=0.784 n=10+8)
RegexpMatchMedium_32-4      131ns ± 0%     130ns ± 0%  -0.42%   (p=0.004 n=11+9)
RegexpMatchMedium_1K-4     41.9µs ± 1%    41.6µs ± 0%    ~      (p=0.067 n=11+9)
RegexpMatchHard_32-4       2.34µs ± 0%    2.34µs ± 0%    ~     (p=0.208 n=11+11)
RegexpMatchHard_1K-4       70.9µs ± 0%    71.0µs ± 0%    ~      (p=0.968 n=9+10)
Revcomp-4                   819ms ± 0%     818ms ± 0%    ~     (p=0.251 n=10+11)
Template-4                 73.9ms ± 0%    73.8ms ± 0%  -0.25%  (p=0.013 n=10+11)
TimeParse-4                 414ns ± 0%     414ns ± 0%    ~     (p=0.809 n=11+10)
TimeFormat-4                485ns ± 0%     485ns ± 0%    ~      (p=0.404 n=11+7)

name                     old speed      new speed      delta
GobDecode-4              82.0MB/s ± 1%  82.3MB/s ± 0%  +0.31%  (p=0.007 n=11+10)
GobEncode-4               104MB/s ± 1%   104MB/s ± 1%    ~     (p=0.797 n=11+11)
Gzip-4                   49.2MB/s ± 0%  49.1MB/s ± 1%    ~     (p=0.507 n=11+11)
Gunzip-4                  297MB/s ± 0%   297MB/s ± 0%    ~     (p=0.670 n=10+10)
JSONEncode-4              102MB/s ± 0%   102MB/s ± 0%    ~      (p=0.794 n=9+10)
JSONDecode-4             32.6MB/s ± 0%  32.6MB/s ± 0%    ~       (p=0.334 n=9+9)
GoParse-4                16.8MB/s ± 1%  16.9MB/s ± 1%    ~     (p=0.052 n=11+11)
RegexpMatchEasy0_32-4     314MB/s ± 0%   314MB/s ± 1%    ~     (p=0.618 n=11+11)
RegexpMatchEasy0_1K-4    1.29GB/s ± 0%  1.29GB/s ± 0%    ~     (p=0.315 n=10+10)
RegexpMatchEasy1_32-4     290MB/s ± 1%   290MB/s ± 1%    ~     (p=0.667 n=10+11)
RegexpMatchEasy1_1K-4    1.03GB/s ± 0%  1.03GB/s ± 0%    ~      (p=0.829 n=10+8)
RegexpMatchMedium_32-4   7.63MB/s ± 0%  7.65MB/s ± 0%    ~     (p=0.142 n=11+11)
RegexpMatchMedium_1K-4   24.4MB/s ± 1%  24.6MB/s ± 0%    ~      (p=0.063 n=11+9)
RegexpMatchHard_32-4     13.7MB/s ± 0%  13.7MB/s ± 0%    ~     (p=0.302 n=11+11)
RegexpMatchHard_1K-4     14.4MB/s ± 0%  14.4MB/s ± 0%    ~      (p=0.784 n=9+10)
Revcomp-4                 310MB/s ± 0%   311MB/s ± 0%    ~     (p=0.243 n=10+11)
Template-4               26.2MB/s ± 0%  26.3MB/s ± 0%  +0.24%  (p=0.009 n=10+11)

Update #12970.

Change-Id: Id185080687a60c229a5cb2e5220e7ca1b53910e2
Reviewed-on: https://go-review.googlesource.com/15999
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
minux added a commit that referenced this issue Dec 5, 2015
…on 386

Fixes #12970.

Change-Id: Id0026e8274e071d65d47df63d65a93110abbec5d
Reviewed-on: https://go-review.googlesource.com/15998
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
@golang golang locked and limited conversation to collaborators Oct 24, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants