Skip to content

Commit

Permalink
runtime: support windows/arm
Browse files Browse the repository at this point in the history
Updates #26148

Change-Id: I8f68b2c926c7b11dc86c9664ed7ff2d2f78b64b4
Reviewed-on: https://go-review.googlesource.com/128715
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
jordanrh1 authored and ianlancetaylor committed Sep 18, 2018
1 parent 37db664 commit d24ec86
Show file tree
Hide file tree
Showing 17 changed files with 4,942 additions and 21 deletions.
1 change: 0 additions & 1 deletion src/cmd/vet/all/whitelist/windows_386.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
runtime/sys_windows_386.s: [386] profileloop: use of 4(SP) points beyond argument frame
runtime/sys_windows_386.s: [386] ctrlhandler: 4(SP) should be _type+0(FP)
runtime/sys_windows_386.s: [386] setldt: function setldt missing Go declaration
runtime/zcallback_windows.s: [386] callbackasm: function callbackasm missing Go declaration
runtime/sys_windows_386.s: [386] callbackasm1+0: function callbackasm1+0 missing Go declaration
runtime/sys_windows_386.s: [386] tstart: function tstart missing Go declaration
runtime/sys_windows_386.s: [386] tstart_stdcall: RET without writing to 4-byte ret+4(FP)
Expand Down
1 change: 0 additions & 1 deletion src/cmd/vet/all/whitelist/windows_amd64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ runtime/sys_windows_amd64.s: [amd64] callbackasm1: function callbackasm1 missing
runtime/sys_windows_amd64.s: [amd64] tstart_stdcall: RET without writing to 4-byte ret+8(FP)
runtime/sys_windows_amd64.s: [amd64] settls: function settls missing Go declaration
runtime/sys_windows_amd64.s: [amd64] cannot check cross-package assembly function: now is in package time
runtime/zcallback_windows.s: [amd64] callbackasm: function callbackasm missing Go declaration
4 changes: 4 additions & 0 deletions src/runtime/asm_arm.s
Original file line number Diff line number Diff line change
Expand Up @@ -784,13 +784,17 @@ TEXT setg<>(SB),NOSPLIT|NOFRAME,$0-0
MOVW R0, g

// Save g to thread-local storage.
#ifdef GOOS_windows
B runtime·save_g(SB)
#else
MOVB runtime·iscgo(SB), R0
CMP $0, R0
B.EQ 2(PC)
B runtime·save_g(SB)

MOVW g, R0
RET
#endif

TEXT runtime·emptyfunc(SB),0,$0-0
RET
Expand Down
3 changes: 3 additions & 0 deletions src/runtime/defs_windows_386.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ type context struct {
func (c *context) ip() uintptr { return uintptr(c.eip) }
func (c *context) sp() uintptr { return uintptr(c.esp) }

// 386 does not have link register, so this returns 0.
func (c *context) lr() uintptr { return 0 }

func (c *context) setip(x uintptr) { c.eip = uint32(x) }
func (c *context) setsp(x uintptr) { c.esp = uint32(x) }

Expand Down
3 changes: 3 additions & 0 deletions src/runtime/defs_windows_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ type context struct {
func (c *context) ip() uintptr { return uintptr(c.rip) }
func (c *context) sp() uintptr { return uintptr(c.rsp) }

// Amd64 does not have link register, so this returns 0.
func (c *context) lr() uintptr { return 0 }

func (c *context) setip(x uintptr) { c.rip = uint64(x) }
func (c *context) setsp(x uintptr) { c.rsp = uint64(x) }

Expand Down
149 changes: 149 additions & 0 deletions src/runtime/defs_windows_arm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Copyright 2018 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

const (
_PROT_NONE = 0
_PROT_READ = 1
_PROT_WRITE = 2
_PROT_EXEC = 4

_MAP_ANON = 1
_MAP_PRIVATE = 2

_DUPLICATE_SAME_ACCESS = 0x2
_THREAD_PRIORITY_HIGHEST = 0x2

_SIGINT = 0x2
_CTRL_C_EVENT = 0x0
_CTRL_BREAK_EVENT = 0x1

_CONTEXT_CONTROL = 0x10001
_CONTEXT_FULL = 0x10007

_EXCEPTION_ACCESS_VIOLATION = 0xc0000005
_EXCEPTION_BREAKPOINT = 0x80000003
_EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d
_EXCEPTION_FLT_DIVIDE_BY_ZERO = 0xc000008e
_EXCEPTION_FLT_INEXACT_RESULT = 0xc000008f
_EXCEPTION_FLT_OVERFLOW = 0xc0000091
_EXCEPTION_FLT_UNDERFLOW = 0xc0000093
_EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094
_EXCEPTION_INT_OVERFLOW = 0xc0000095

_INFINITE = 0xffffffff
_WAIT_TIMEOUT = 0x102

_EXCEPTION_CONTINUE_EXECUTION = -0x1
_EXCEPTION_CONTINUE_SEARCH = 0x0
)

type systeminfo struct {
anon0 [4]byte
dwpagesize uint32
lpminimumapplicationaddress *byte
lpmaximumapplicationaddress *byte
dwactiveprocessormask uint32
dwnumberofprocessors uint32
dwprocessortype uint32
dwallocationgranularity uint32
wprocessorlevel uint16
wprocessorrevision uint16
}

type exceptionrecord struct {
exceptioncode uint32
exceptionflags uint32
exceptionrecord *exceptionrecord
exceptionaddress *byte
numberparameters uint32
exceptioninformation [15]uint32
}

type neon128 struct {
low uint64
high int64
}

type context struct {
contextflags uint32
r0 uint32
r1 uint32
r2 uint32
r3 uint32
r4 uint32
r5 uint32
r6 uint32
r7 uint32
r8 uint32
r9 uint32
r10 uint32
r11 uint32
r12 uint32

spr uint32
lrr uint32
pc uint32
cpsr uint32

fpscr uint32
padding uint32

floatNeon [16]neon128

bvr [8]uint32
bcr [8]uint32
wvr [1]uint32
wcr [1]uint32
padding2 [2]uint32
}

func (c *context) ip() uintptr { return uintptr(c.pc) }
func (c *context) sp() uintptr { return uintptr(c.spr) }
func (c *context) lr() uintptr { return uintptr(c.lrr) }

func (c *context) setip(x uintptr) { c.pc = uint32(x) }
func (c *context) setsp(x uintptr) { c.spr = uint32(x) }

func dumpregs(r *context) {
print("r0 ", hex(r.r0), "\n")
print("r1 ", hex(r.r1), "\n")
print("r2 ", hex(r.r2), "\n")
print("r3 ", hex(r.r3), "\n")
print("r4 ", hex(r.r4), "\n")
print("r5 ", hex(r.r5), "\n")
print("r6 ", hex(r.r6), "\n")
print("r7 ", hex(r.r7), "\n")
print("r8 ", hex(r.r8), "\n")
print("r9 ", hex(r.r9), "\n")
print("r10 ", hex(r.r10), "\n")
print("r11 ", hex(r.r11), "\n")
print("r12 ", hex(r.r12), "\n")
print("sp ", hex(r.spr), "\n")
print("lr ", hex(r.lrr), "\n")
print("pc ", hex(r.pc), "\n")
print("cpsr ", hex(r.cpsr), "\n")
}

type overlapped struct {
internal uint32
internalhigh uint32
anon0 [8]byte
hevent *byte
}

type memoryBasicInformation struct {
baseAddress uintptr
allocationBase uintptr
allocationProtect uint32
regionSize uintptr
state uint32
protect uint32
type_ uint32
}

func stackcheck() {
// TODO: not implemented on ARM
}
30 changes: 26 additions & 4 deletions src/runtime/os_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const (
//go:cgo_import_dynamic runtime._SetWaitableTimer SetWaitableTimer%6 "kernel32.dll"
//go:cgo_import_dynamic runtime._SuspendThread SuspendThread%1 "kernel32.dll"
//go:cgo_import_dynamic runtime._SwitchToThread SwitchToThread%0 "kernel32.dll"
//go:cgo_import_dynamic runtime._TlsAlloc TlsAlloc%0 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc%4 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualQuery VirtualQuery%3 "kernel32.dll"
Expand Down Expand Up @@ -91,6 +92,7 @@ var (
_SetWaitableTimer,
_SuspendThread,
_SwitchToThread,
_TlsAlloc,
_VirtualAlloc,
_VirtualFree,
_VirtualQuery,
Expand Down Expand Up @@ -860,14 +862,34 @@ func profilem(mp *m) {
var r *context
rbuf := make([]byte, unsafe.Sizeof(*r)+15)

tls := &mp.tls[0]
gp := *((**g)(unsafe.Pointer(tls)))

// align Context to 16 bytes
r = (*context)(unsafe.Pointer((uintptr(unsafe.Pointer(&rbuf[15]))) &^ 15))
r.contextflags = _CONTEXT_CONTROL
stdcall2(_GetThreadContext, mp.thread, uintptr(unsafe.Pointer(r)))
sigprof(r.ip(), r.sp(), 0, gp, mp)

var gp *g
switch GOARCH {
default:
panic("unsupported architecture")
case "arm":
// TODO(jordanrh1): this is incorrect when Go is executing
// on the system or signal stacks because curg returns
// the current user g. The true g is stored in thread
// local storage, which we cannot access from another CPU.
// We cannot pull R10 from the thread context because
// it might be executing C code, in which case R10
// would not be g.
gp = mp.curg
case "386", "amd64":
tls := &mp.tls[0]
gp = *((**g)(unsafe.Pointer(tls)))
}

if gp == nil {
sigprofNonGoPC(r.ip())
} else {
sigprof(r.ip(), r.sp(), 0, gp, mp)
}
}

func profileloop1(param uintptr) uint32 {
Expand Down
18 changes: 18 additions & 0 deletions src/runtime/os_windows_arm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2018 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

//go:nosplit
func cputicks() int64 {
return nanotime()
}

func checkgoarm() {
if goarm < 7 {
print("Need atomic synchronization instructions, coprocessor ",
"access instructions. Recompile using GOARM=7.\n")
exit(1)
}
}
12 changes: 12 additions & 0 deletions src/runtime/rt0_windows_arm.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright 2018 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 "go_asm.h"
#include "go_tls.h"
#include "textflag.h"

// This is the entry point for the program from the
// kernel for an ordinary -buildmode=exe program.
TEXT _rt0_arm_windows(SB),NOSPLIT|NOFRAME,$0
B ·rt0_go(SB)
10 changes: 8 additions & 2 deletions src/runtime/signal_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func lastcontinuetramp()

func initExceptionHandler() {
stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp))
if _AddVectoredContinueHandler == nil || unsafe.Sizeof(&_AddVectoredContinueHandler) == 4 {
if _AddVectoredContinueHandler == nil || GOARCH == "386" {
// use SetUnhandledExceptionFilter for windows-386 or
// if VectoredContinueHandler is unavailable.
// note: SetUnhandledExceptionFilter handler won't be called, if debugging.
Expand Down Expand Up @@ -177,9 +177,15 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
}
print("\n")

// TODO(jordanrh1): This may be needed for 386/AMD64 as well.
if GOARCH == "arm" {
_g_.m.throwing = 1
_g_.m.caughtsig.set(gp)
}

level, _, docrash := gotraceback()
if level > 0 {
tracebacktrap(r.ip(), r.sp(), 0, gp)
tracebacktrap(r.ip(), r.sp(), r.lr(), gp)
tracebackothers(gp)
dumpregs(r)
}
Expand Down
Loading

0 comments on commit d24ec86

Please sign in to comment.