Skip to content

Commit

Permalink
all: add start of netbsd/arm64 support
Browse files Browse the repository at this point in the history
This works well enough to run some code natively on arm64, but not well enough for more complicated code. I've been suggested to start a pull request anyway.

Updates golang#30824

Change-Id: Ib4f63e0e8a9edfc862cf65b5f1b0fbf9a8a1628e
GitHub-Last-Rev: b01b105
GitHub-Pull-Request: golang#29398
Reviewed-on: https://go-review.googlesource.com/c/go/+/155739
Run-TryBot: Benny Siegert <bsiegert@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
  • Loading branch information
coypoop authored and bsiegert committed Apr 20, 2019
1 parent 78f0de1 commit d23cba6
Show file tree
Hide file tree
Showing 18 changed files with 4,685 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/cmd/api/goapi.go
Expand Up @@ -77,6 +77,8 @@ var contexts = []*build.Context{
{GOOS: "netbsd", GOARCH: "amd64"},
{GOOS: "netbsd", GOARCH: "arm", CgoEnabled: true},
{GOOS: "netbsd", GOARCH: "arm"},
{GOOS: "netbsd", GOARCH: "arm64", CgoEnabled: true},
{GOOS: "netbsd", GOARCH: "arm64"},
{GOOS: "openbsd", GOARCH: "386", CgoEnabled: true},
{GOOS: "openbsd", GOARCH: "386"},
{GOOS: "openbsd", GOARCH: "amd64", CgoEnabled: true},
Expand Down
1 change: 1 addition & 0 deletions src/cmd/dist/build.go
Expand Up @@ -1510,6 +1510,7 @@ var cgoEnabled = map[string]bool{
"netbsd/386": true,
"netbsd/amd64": true,
"netbsd/arm": true,
"netbsd/arm64": true,
"openbsd/386": true,
"openbsd/amd64": true,
"openbsd/arm": true,
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/link/internal/arm64/asm.go
Expand Up @@ -359,7 +359,7 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
return int64(o1)<<32 | int64(o0), true
case objabi.R_ARM64_TLS_LE:
r.Done = false
if ctxt.HeadType != objabi.Hlinux {
if ctxt.HeadType == objabi.Hdarwin {
ld.Errorf(s, "TLS reloc on unsupported OS %v", ctxt.HeadType)
}
// The TCB is two pointers. This is not documented anywhere, but is
Expand Down
5 changes: 3 additions & 2 deletions src/cmd/link/internal/arm64/obj.go
Expand Up @@ -61,7 +61,7 @@ func Init() (*sys.Arch, ld.Arch) {

Freebsddynld: "XXX",
Openbsddynld: "XXX",
Netbsddynld: "XXX",
Netbsddynld: "/libexec/ld.elf_so",
Dragonflydynld: "XXX",
Solarisdynld: "XXX",
}
Expand All @@ -84,7 +84,8 @@ func archinit(ctxt *ld.Link) {
*ld.FlagRound = 4096
}

case objabi.Hlinux: /* arm64 elf */
case objabi.Hlinux, /* arm64 elf */
objabi.Hnetbsd:
ld.Elfinit(ctxt)
ld.HEADR = ld.ELFRESERVE
if *ld.FlagTextAddr == -1 {
Expand Down
78 changes: 78 additions & 0 deletions src/runtime/cgo/gcc_netbsd_arm64.c
@@ -0,0 +1,78 @@
// Copyright 2019 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.

#include <sys/types.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include "libcgo.h"
#include "libcgo_unix.h"

static void *threadentry(void*);

static void (*setg_gcc)(void*);

void
x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;

setg_gcc = setg;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
}


void
_cgo_sys_thread_start(ThreadStart *ts)
{
pthread_attr_t attr;
sigset_t ign, oset;
pthread_t p;
size_t size;
int err;

sigfillset(&ign);
pthread_sigmask(SIG_SETMASK, &ign, &oset);

pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
// Leave stacklo=0 and set stackhi=size; mstart will do the rest.
ts->g->stackhi = size;
err = _cgo_try_pthread_create(&p, &attr, threadentry, ts);

pthread_sigmask(SIG_SETMASK, &oset, nil);

if (err != 0) {
fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
abort();
}
}

static void*
threadentry(void *v)
{
ThreadStart ts;
stack_t ss;

ts = *(ThreadStart*)v;
free(v);

// On NetBSD, a new thread inherits the signal stack of the
// creating thread. That confuses minit, so we remove that
// signal stack here before calling the regular mstart. It's
// a bit baroque to remove a signal stack here only to add one
// in minit, but it's a simple change that keeps NetBSD
// working like other OS's. At this point all signals are
// blocked, so there is no race.
memset(&ss, 0, sizeof ss);
ss.ss_flags = SS_DISABLE;
sigaltstack(&ss, nil);

crosscall1(ts.fn, setg_gcc, (void*)ts.g);
return nil;
}
195 changes: 195 additions & 0 deletions src/runtime/defs1_netbsd_arm64.go
@@ -0,0 +1,195 @@
// created by cgo -cdefs and then converted to Go
// cgo -cdefs defs_netbsd.go defs_netbsd_arm.go

package runtime

const (
_EINTR = 0x4
_EFAULT = 0xe

_PROT_NONE = 0x0
_PROT_READ = 0x1
_PROT_WRITE = 0x2
_PROT_EXEC = 0x4

_MAP_ANON = 0x1000
_MAP_PRIVATE = 0x2
_MAP_FIXED = 0x10

_MADV_FREE = 0x6

_SA_SIGINFO = 0x40
_SA_RESTART = 0x2
_SA_ONSTACK = 0x1

_SIGHUP = 0x1
_SIGINT = 0x2
_SIGQUIT = 0x3
_SIGILL = 0x4
_SIGTRAP = 0x5
_SIGABRT = 0x6
_SIGEMT = 0x7
_SIGFPE = 0x8
_SIGKILL = 0x9
_SIGBUS = 0xa
_SIGSEGV = 0xb
_SIGSYS = 0xc
_SIGPIPE = 0xd
_SIGALRM = 0xe
_SIGTERM = 0xf
_SIGURG = 0x10
_SIGSTOP = 0x11
_SIGTSTP = 0x12
_SIGCONT = 0x13
_SIGCHLD = 0x14
_SIGTTIN = 0x15
_SIGTTOU = 0x16
_SIGIO = 0x17
_SIGXCPU = 0x18
_SIGXFSZ = 0x19
_SIGVTALRM = 0x1a
_SIGPROF = 0x1b
_SIGWINCH = 0x1c
_SIGINFO = 0x1d
_SIGUSR1 = 0x1e
_SIGUSR2 = 0x1f

_FPE_INTDIV = 0x1
_FPE_INTOVF = 0x2
_FPE_FLTDIV = 0x3
_FPE_FLTOVF = 0x4
_FPE_FLTUND = 0x5
_FPE_FLTRES = 0x6
_FPE_FLTINV = 0x7
_FPE_FLTSUB = 0x8

_BUS_ADRALN = 0x1
_BUS_ADRERR = 0x2
_BUS_OBJERR = 0x3

_SEGV_MAPERR = 0x1
_SEGV_ACCERR = 0x2

_ITIMER_REAL = 0x0
_ITIMER_VIRTUAL = 0x1
_ITIMER_PROF = 0x2

_EV_ADD = 0x1
_EV_DELETE = 0x2
_EV_CLEAR = 0x20
_EV_RECEIPT = 0
_EV_ERROR = 0x4000
_EV_EOF = 0x8000
_EVFILT_READ = 0x0
_EVFILT_WRITE = 0x1
)

type sigset struct {
__bits [4]uint32
}

type siginfo struct {
_signo int32
_code int32
_errno int32
_reason uintptr
_reasonx [16]byte
}

type stackt struct {
ss_sp uintptr
ss_size uintptr
ss_flags int32
}

type timespec struct {
tv_sec int64
tv_nsec int64
}

func (ts *timespec) setNsec(ns int64) {
ts.tv_sec = ns / 1e9
ts.tv_nsec = ns % 1e9
}

type timeval struct {
tv_sec int64
tv_usec int32
_ [4]byte // EABI
}

func (tv *timeval) set_usec(x int32) {
tv.tv_usec = x
}

type itimerval struct {
it_interval timeval
it_value timeval
}

type mcontextt struct {
__gregs [35]uint64
__fregs [4160]byte // _NFREG * 128 + 32 + 32
_ [8]uint64 // future use
}

type ucontextt struct {
uc_flags uint32
uc_link *ucontextt
uc_sigmask sigset
uc_stack stackt
_ [4]byte // EABI
uc_mcontext mcontextt
__uc_pad [2]int32
}

type keventt struct {
ident uint64
filter uint32
flags uint32
fflags uint32
pad_cgo_0 [4]byte
data int64
udata *byte
}

// created by cgo -cdefs and then converted to Go
// cgo -cdefs defs_netbsd.go defs_netbsd_arm.go

const (
_REG_X0 = 0
_REG_X1 = 1
_REG_X2 = 2
_REG_X3 = 3
_REG_X4 = 4
_REG_X5 = 5
_REG_X6 = 6
_REG_X7 = 7
_REG_X8 = 8
_REG_X9 = 9
_REG_X10 = 10
_REG_X11 = 11
_REG_X12 = 12
_REG_X13 = 13
_REG_X14 = 14
_REG_X15 = 15
_REG_X16 = 16
_REG_X17 = 17
_REG_X18 = 18
_REG_X19 = 19
_REG_X20 = 20
_REG_X21 = 21
_REG_X22 = 22
_REG_X23 = 23
_REG_X24 = 24
_REG_X25 = 25
_REG_X26 = 26
_REG_X27 = 27
_REG_X28 = 28
_REG_X29 = 29
_REG_X30 = 30
_REG_X31 = 31
_REG_ELR = 32
_REG_SPSR = 33
_REG_TPIDR = 34
)
24 changes: 24 additions & 0 deletions src/runtime/os_netbsd_arm64.go
@@ -0,0 +1,24 @@
// Copyright 2019 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.

package runtime

import "unsafe"

func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) {
// Machine dependent mcontext initialisation for LWP.
mc.__gregs[_REG_ELR] = uint64(funcPC(lwp_tramp))
mc.__gregs[_REG_X31] = uint64(uintptr(stk))
mc.__gregs[_REG_X0] = uint64(uintptr(unsafe.Pointer(mp)))
mc.__gregs[_REG_X1] = uint64(uintptr(unsafe.Pointer(mp.g0)))
mc.__gregs[_REG_X2] = uint64(fn)
}

//go:nosplit
func cputicks() int64 {
// Currently cputicks() is used in blocking profiler and to seed runtime·fastrand().
// runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
// TODO: need more entropy to better seed fastrand.
return nanotime()
}

0 comments on commit d23cba6

Please sign in to comment.