Skip to content

runtime: go1.26 SIGILL on riscv64 with vector support #78045

@lotheac

Description

@lotheac

Go version

go version go1.26.1 linux/riscv64

Output of go env in your module/workspace:

AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='riscv64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2250152223=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='riscv64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/root/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/root/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GORISCV64='rva20u64'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/root/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_riscv64'
GOVCS=''
GOVERSION='go1.26.1'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

Since go 1.26, we are seeing SIGILLs on Alpine Linux riscv64 CI on a machine that supports vector instructions (BananaPi F3 with Spacemit X60).

I have not bisected, but these commits seem like the likely causes:
75ea2d0
3406a61
d83b16f

This CPU does support vector instructions:

$ lscpu
Architecture:           riscv64
  Byte Order:           Little Endian
CPU(s):                 8
  On-line CPU(s) list:  0-7
Vendor ID:              0x710
  Model name:           Spacemit(R) X60
    CPU family:         0x8000000058000001
    Model:              0x1000000049772200
    Thread(s) per core: 1
    Core(s) per socket: 8
    Socket(s):          1
    CPU(s) scaling MHz: 100%
    CPU max MHz:        1600.0000
    CPU min MHz:        614.4000
Caches (sum of all):
  L1d:                  256 KiB (8 instances)
  L1i:                  256 KiB (8 instances)
  L2:                   1 MiB (2 instances)
$ grep isa /proc/cpuinfo |uniq
isa		: rv64imafdcv_zicbom_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zfhmin_zca_zcd_zba_zbb_zbc_zbs_zkt_zve32f_zve32x_zve64d_zve64f_zve64x_zvfh_zvfhmin_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt

Those vector instructions work fine when compiled into a C program, but go crashes.

I can semi-reliably trigger a SIGILL on this machine on go1.26 by compiling the following program:

~/trivial # cat main.go
package main

import "fmt"

func main() {
	fmt.Printf("hello world\n");
	return
}

It's possible (although a bit less reliable) to trigger a SIGILL even when compiling a more trivial program (func main(){return}).

What did you see happen?

~/trivial # go build -o main main.go
~/trivial # go build -o main main.go
SIGILL: illegal instruction
PC=0x14c04 m=0 sigcode=1
instruction bytes: 0x7 0x4 0x5 0x2 0x57 0x40 0x86 0x62 0x57 0xa3 0x8 0x42 0x63 0x59 0x3 0x0

goroutine 0 gp=0x142df80 m=0 mp=0x1430c80 [idle]:
indexByteBig()
	internal/bytealg/indexbyte_riscv64.s:82 +0x14 fp=0x3fd86da888 sp=0x3fd86da888 pc=0x14c04
runtime.findnull(0x963da0?)
	runtime/string.go:520 +0x54 fp=0x3fd86da8c0 sp=0x3fd86da888 pc=0x73584
runtime.gostringnocopy(...)
	runtime/string.go:544
runtime.(*moduledata).funcName(0x63278?, 0x293f2700?)
	runtime/symtab.go:762 +0x42 fp=0x3fd86da8d8 sp=0x3fd86da8c0 pc=0x7415a
runtime.funcname(...)
	runtime/symtab.go:1150
runtime.isSystemGoroutine(0x7293f2700, 0x0)
	runtime/traceback.go:1437 +0xce fp=0x3fd86da8f8 sp=0x3fd86da8d8 pc=0x7c58e
runtime.newproc1(0xa54fb0, 0x7293f21c0, 0x5ab0c, 0x0, 0x0)
	runtime/proc.go:5358 +0x162 fp=0x3fd86da960 sp=0x3fd86da8f8 pc=0x634ba
runtime.newproc.func1()
	runtime/proc.go:5299 +0x2e fp=0x3fd86da988 sp=0x3fd86da960 pc=0x63326
runtime.systemstack(0x1430c80)
	runtime/asm_riscv64.s:230 +0x4a fp=0x3fd86da990 sp=0x3fd86da988 pc=0x8bcca

goroutine 1 gp=0x7293f21c0 m=0 mp=0x1430c80 [running, locked to thread]:
runtime.systemstack_switch()
	runtime/asm_riscv64.s:193 +0x8 fp=0x729446608 sp=0x729446600 pc=0x8bc70
runtime.newproc(0x6812e?)
	runtime/proc.go:5298 +0x3a fp=0x729446638 sp=0x729446608 pc=0x632ea
runtime.init.6()
	runtime/proc.go:363 +0x24 fp=0x729446648 sp=0x729446638 pc=0x5ab0c
runtime.doInit1(0x12bf9a0)
	runtime/proc.go:8103 +0xa6 fp=0x729446760 sp=0x729446648 pc=0x6812e
runtime.doInit(...)
	runtime/proc.go:8070
runtime.main()
	runtime/proc.go:203 +0xfa fp=0x7294467d8 sp=0x729446760 pc=0x5a792
runtime.goexit({})
	runtime/asm_riscv64.s:630 +0x4 fp=0x7294467d8 sp=0x7294467d8 pc=0x8d4dc

ra  0x73584	sp  0x3fd86da888
gp  0x2abfac7800	tp  0x3f9b2edd98
t0  0x100	t1  0x0
t2  0xeb7068	s0  0x45f
s1  0x56ff	a0  0xa86aa6
a1  0x55a	a2  0x0
a3  0xa86aa6	a4  0x0
a5  0x1	a6  0x0
a7  0x1	s2  0x1f0
s3  0x2	s4  0x2
s5  0x14514c0	s6  0x8
s7  0x10	s8  0x2
s9  0x10	s10 0x3fd86da8e0
s11 0x142df80	t3  0x18
t4  0xa1b907517bb8e	t5  0xffffffffffffffff
t6  0xfff	pc  0x14c04
go: error obtaining buildID for go tool compile: exit status 2

What did you expect to see?

I expected a successful compilation.

Curiously, GODEBUG=asyncpreemptoff=1 seems to work around the issue: if this is set in env for go build, the SIGILLs go away entirely; I can even recompile go itself with this set.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.compiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions