1
0
mirror of https://github.com/golang/go synced 2024-11-20 06:24:40 -07:00
go/src/runtime/sys_netbsd_arm.s
Austin Clements f5d494bbdf runtime: ensure GC sees type-safe memory on weak machines
Currently its possible for the garbage collector to observe
uninitialized memory or stale heap bitmap bits on weakly ordered
architectures such as ARM and PPC. On such architectures, the stores
that zero newly allocated memory and initialize its heap bitmap may
move after a store in user code that makes the allocated object
observable by the garbage collector.

To fix this, add a "publication barrier" (also known as an "export
barrier") before returning from mallocgc. This is a store/store
barrier that ensures any write done by user code that makes the
returned object observable to the garbage collector will be ordered
after the initialization performed by mallocgc. No barrier is
necessary on the reading side because of the data dependency between
loading the pointer and loading the contents of the object.

Fixes one of the issues raised in #9984.

Change-Id: Ia3d96ad9c5fc7f4d342f5e05ec0ceae700cd17c8
Reviewed-on: https://go-review.googlesource.com/11083
Reviewed-by: Rick Hudson <rlh@golang.org>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Reviewed-by: Minux Ma <minux@golang.org>
Reviewed-by: Martin Capitanio <capnm9@gmail.com>
Reviewed-by: Russ Cox <rsc@golang.org>
2015-06-19 15:29:50 +00:00

361 lines
8.5 KiB
ArmAsm

// Copyright 2013 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.
//
// System calls and other sys.stuff for ARM, NetBSD
// /usr/src/sys/kern/syscalls.master for syscall numbers.
//
#include "go_asm.h"
#include "go_tls.h"
#include "textflag.h"
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$-4
MOVW code+0(FP), R0 // arg 1 exit status
SWI $0xa00001
MOVW.CS $0, R8 // crash on syscall failure
MOVW.CS R8, (R8)
RET
TEXT runtime·exit1(SB),NOSPLIT,$-4
SWI $0xa00136 // sys__lwp_exit
MOVW $1, R8 // crash
MOVW R8, (R8)
RET
TEXT runtime·open(SB),NOSPLIT,$-8
MOVW name+0(FP), R0
MOVW mode+4(FP), R1
MOVW perm+8(FP), R2
SWI $0xa00005
MOVW.CS $-1, R0
MOVW R0, ret+12(FP)
RET
TEXT runtime·closefd(SB),NOSPLIT,$-8
MOVW fd+0(FP), R0
SWI $0xa00006
MOVW.CS $-1, R0
MOVW R0, ret+4(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$-8
MOVW fd+0(FP), R0
MOVW p+4(FP), R1
MOVW n+8(FP), R2
SWI $0xa00003
MOVW.CS $-1, R0
MOVW R0, ret+12(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$-4
MOVW fd+0(FP), R0 // arg 1 - fd
MOVW p+4(FP), R1 // arg 2 - buf
MOVW n+8(FP), R2 // arg 3 - nbyte
SWI $0xa00004 // sys_write
MOVW.CS $-1, R0
MOVW R0, ret+12(FP)
RET
// int32 lwp_create(void *context, uintptr flags, void *lwpid)
TEXT runtime·lwp_create(SB),NOSPLIT,$0
MOVW ctxt+0(FP), R0
MOVW flags+4(FP), R1
MOVW lwpid+8(FP), R2
SWI $0xa00135 // sys__lwp_create
MOVW R0, ret+12(FP)
RET
TEXT runtime·osyield(SB),NOSPLIT,$0
SWI $0xa0015e // sys_sched_yield
RET
TEXT runtime·lwp_park(SB),NOSPLIT,$0
MOVW abstime+0(FP), R0 // arg 1 - abstime
MOVW unpark+4(FP), R1 // arg 2 - unpark
MOVW hint+8(FP), R2 // arg 3 - hint
MOVW unparkhint+12(FP), R3 // arg 4 - unparkhint
SWI $0xa001b2 // sys__lwp_park
MOVW R0, ret+16(FP)
RET
TEXT runtime·lwp_unpark(SB),NOSPLIT,$0
MOVW lwp+0(FP), R0 // arg 1 - lwp
MOVW hint+4(FP), R1 // arg 2 - hint
SWI $0xa00141 // sys__lwp_unpark
MOVW R0, ret+8(FP)
RET
TEXT runtime·lwp_self(SB),NOSPLIT,$0
SWI $0xa00137 // sys__lwp_self
MOVW R0, ret+0(FP)
RET
TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
MOVW R0, g_m(R1)
MOVW R1, g
BL runtime·emptyfunc(SB) // fault if stack check is wrong
BL (R2)
MOVW $2, R8 // crash (not reached)
MOVW R8, (R8)
RET
TEXT runtime·usleep(SB),NOSPLIT,$16
MOVW usec+0(FP), R0
MOVW R0, R2
MOVW $1000000, R1
DIV R1, R0
// 0(R13) is the saved LR, don't use it
MOVW R0, 4(R13) // tv_sec.low
MOVW $0, R0
MOVW R0, 8(R13) // tv_sec.high
MOD R1, R2
MOVW $1000, R1
MUL R1, R2
MOVW R2, 12(R13) // tv_nsec
MOVW $4(R13), R0 // arg 1 - rqtp
MOVW $0, R1 // arg 2 - rmtp
SWI $0xa001ae // sys_nanosleep
RET
TEXT runtime·raise(SB),NOSPLIT,$16
SWI $0xa00137 // sys__lwp_self, the returned R0 is arg 1
MOVW sig+0(FP), R1 // arg 2 - signal
SWI $0xa0013e // sys__lwp_kill
RET
TEXT runtime·setitimer(SB),NOSPLIT,$-4
MOVW mode+0(FP), R0 // arg 1 - which
MOVW new+4(FP), R1 // arg 2 - itv
MOVW old+8(FP), R2 // arg 3 - oitv
SWI $0xa001a9 // sys_setitimer
RET
// func now() (sec int64, nsec int32)
TEXT time·now(SB), NOSPLIT, $32
MOVW $0, R0 // CLOCK_REALTIME
MOVW $8(R13), R1
SWI $0xa001ab // clock_gettime
MOVW 8(R13), R0 // sec.low
MOVW 12(R13), R1 // sec.high
MOVW 16(R13), R2 // nsec
MOVW R0, sec_lo+0(FP)
MOVW R1, sec_hi+4(FP)
MOVW R2, nsec+8(FP)
RET
// int64 nanotime(void) so really
// void nanotime(int64 *nsec)
TEXT runtime·nanotime(SB), NOSPLIT, $32
MOVW $0, R0 // CLOCK_REALTIME
MOVW $8(R13), R1
SWI $0xa001ab // clock_gettime
MOVW 8(R13), R0 // sec.low
MOVW 12(R13), R4 // sec.high
MOVW 16(R13), R2 // nsec
MOVW $1000000000, R3
MULLU R0, R3, (R1, R0)
MUL R3, R4
ADD.S R2, R0
ADC R4, R1
MOVW R0, ret_lo+0(FP)
MOVW R1, ret_hi+4(FP)
RET
TEXT runtime·getcontext(SB),NOSPLIT,$-4
MOVW ctxt+0(FP), R0 // arg 1 - context
SWI $0xa00133 // sys_getcontext
MOVW.CS $0, R8 // crash on syscall failure
MOVW.CS R8, (R8)
RET
TEXT runtime·sigprocmask(SB),NOSPLIT,$0
MOVW mode+0(FP), R0 // arg 1 - how
MOVW new+4(FP), R1 // arg 2 - set
MOVW old+8(FP), R2 // arg 3 - oset
SWI $0xa00125 // sys_sigprocmask
MOVW.CS $0, R8 // crash on syscall failure
MOVW.CS R8, (R8)
RET
TEXT runtime·sigreturn_tramp(SB),NOSPLIT,$-4
// on entry, SP points to siginfo, we add sizeof(ucontext)
// to SP to get a pointer to ucontext.
ADD $0x80, R13, R0 // 0x80 == sizeof(UcontextT)
SWI $0xa00134 // sys_setcontext
// something failed, we have to exit
MOVW $0x4242, R0 // magic return number
SWI $0xa00001 // sys_exit
B -2(PC) // continue exit
TEXT runtime·sigaction(SB),NOSPLIT,$4
MOVW sig+0(FP), R0 // arg 1 - signum
MOVW new+4(FP), R1 // arg 2 - nsa
MOVW old+8(FP), R2 // arg 3 - osa
MOVW $runtime·sigreturn_tramp(SB), R3 // arg 4 - tramp
MOVW $2, R4 // arg 5 - vers
MOVW R4, 4(R13)
ADD $4, R13 // pass arg 5 on stack
SWI $0xa00154 // sys___sigaction_sigtramp
SUB $4, R13
MOVW.CS $3, R8 // crash on syscall failure
MOVW.CS R8, (R8)
RET
TEXT runtime·sigtramp(SB),NOSPLIT,$24
// this might be called in external code context,
// where g is not set.
// first save R0, because runtime·load_g will clobber it
MOVW R0, 4(R13) // signum
MOVB runtime·iscgo(SB), R0
CMP $0, R0
BL.NE runtime·load_g(SB)
CMP $0, g
BNE 4(PC)
// signal number is already prepared in 4(R13)
MOVW $runtime·badsignal(SB), R11
BL (R11)
RET
// save g
MOVW g, R4
MOVW g, 20(R13)
// g = m->signal
MOVW g_m(g), R8
MOVW m_gsignal(R8), g
// R0 is already saved
MOVW R1, 8(R13) // info
MOVW R2, 12(R13) // context
MOVW R4, 16(R13) // gp
BL runtime·sighandler(SB)
// restore g
MOVW 20(R13), g
RET
TEXT runtime·mmap(SB),NOSPLIT,$12
MOVW addr+0(FP), R0 // arg 1 - addr
MOVW n+4(FP), R1 // arg 2 - len
MOVW prot+8(FP), R2 // arg 3 - prot
MOVW flags+12(FP), R3 // arg 4 - flags
// arg 5 (fid) and arg6 (offset_lo, offset_hi) are passed on stack
// note the C runtime only passes the 32-bit offset_lo to us
MOVW fd+16(FP), R4 // arg 5
MOVW R4, 4(R13)
MOVW off+20(FP), R5 // arg 6 lower 32-bit
MOVW R5, 8(R13)
MOVW $0, R6 // higher 32-bit for arg 6
MOVW R6, 12(R13)
ADD $4, R13 // pass arg 5 and arg 6 on stack
SWI $0xa000c5 // sys_mmap
SUB $4, R13
MOVW R0, ret+24(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0
MOVW addr+0(FP), R0 // arg 1 - addr
MOVW n+4(FP), R1 // arg 2 - len
SWI $0xa00049 // sys_munmap
MOVW.CS $0, R8 // crash on syscall failure
MOVW.CS R8, (R8)
RET
TEXT runtime·madvise(SB),NOSPLIT,$0
MOVW addr+0(FP), R0 // arg 1 - addr
MOVW n+4(FP), R1 // arg 2 - len
MOVW flags+8(FP), R2 // arg 3 - behav
SWI $0xa0004b // sys_madvise
// ignore failure - maybe pages are locked
RET
TEXT runtime·sigaltstack(SB),NOSPLIT,$-4
MOVW new+0(FP), R0 // arg 1 - nss
MOVW old+4(FP), R1 // arg 2 - oss
SWI $0xa00119 // sys___sigaltstack14
MOVW.CS $0, R8 // crash on syscall failure
MOVW.CS R8, (R8)
RET
TEXT runtime·sysctl(SB),NOSPLIT,$8
MOVW mib+0(FP), R0 // arg 1 - name
MOVW miblen+4(FP), R1 // arg 2 - namelen
MOVW out+8(FP), R2 // arg 3 - oldp
MOVW size+12(FP), R3 // arg 4 - oldlenp
MOVW dst+16(FP), R4 // arg 5 - newp
MOVW R4, 4(R13)
MOVW ndst+20(FP), R4 // arg 6 - newlen
MOVW R4, 8(R13)
ADD $4, R13 // pass arg 5 and 6 on stack
SWI $0xa000ca // sys___sysctl
SUB $4, R13
MOVW R0, ret+24(FP)
RET
// int32 runtime·kqueue(void)
TEXT runtime·kqueue(SB),NOSPLIT,$0
SWI $0xa00158 // sys_kqueue
RSB.CS $0, R0
MOVW R0, ret+0(FP)
RET
// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout)
TEXT runtime·kevent(SB),NOSPLIT,$8
MOVW kq+0(FP), R0 // kq
MOVW ch+4(FP), R1 // changelist
MOVW nch+8(FP), R2 // nchanges
MOVW ev+12(FP), R3 // eventlist
MOVW nev+16(FP), R4 // nevents
MOVW R4, 4(R13)
MOVW ts+20(FP), R4 // timeout
MOVW R4, 8(R13)
ADD $4, R13 // pass arg 5 and 6 on stack
SWI $0xa001b3 // sys___kevent50
RSB.CS $0, R0
SUB $4, R13
MOVW R0, ret+24(FP)
RET
// void runtime·closeonexec(int32 fd)
TEXT runtime·closeonexec(SB),NOSPLIT,$0
MOVW fd+0(FP), R0 // fd
MOVW $2, R1 // F_SETFD
MOVW $1, R2 // FD_CLOEXEC
SWI $0xa0005c // sys_fcntl
RET
TEXT runtime·casp1(SB),NOSPLIT,$0
B runtime·cas(SB)
// TODO(minux): this is only valid for ARMv6+
// bool armcas(int32 *val, int32 old, int32 new)
// Atomically:
// if(*val == old){
// *val = new;
// return 1;
// }else
// return 0;
TEXT runtime·cas(SB),NOSPLIT,$0
B runtime·armcas(SB)
// TODO: this is only valid for ARMv7+
TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
B runtime·armPublicationBarrier(SB)
TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4
MOVM.WP [R1, R2, R3, R12], (R13)
SWI $0x00a0013c // _lwp_getprivate
MOVM.IAW (R13), [R1, R2, R3, R12]
RET