Text file src/runtime/internal/atomic/sys_linux_arm.s

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include "textflag.h"
     6  
     7  // Linux/ARM atomic operations.
     8  
     9  // Because there is so much variation in ARM devices,
    10  // the Linux kernel provides an appropriate compare-and-swap
    11  // implementation at address 0xffff0fc0.  Caller sets:
    12  //	R0 = old value
    13  //	R1 = new value
    14  //	R2 = addr
    15  //	LR = return address
    16  // The function returns with CS true if the swap happened.
    17  // http://lxr.linux.no/linux+v2.6.37.2/arch/arm/kernel/entry-armv.S#L850
    18  //
    19  // https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b49c0f24cf6744a3f4fd09289fe7cade349dead5
    20  //
    21  TEXT cas<>(SB),NOSPLIT,$0
    22  	MOVW	$0xffff0fc0, R15 // R15 is hardware PC.
    23  
    24  TEXT ·Cas(SB),NOSPLIT|NOFRAME,$0
    25  	MOVB	runtime·goarm(SB), R11
    26  	CMP	$7, R11
    27  	BLT	2(PC)
    28  	JMP	·armcas(SB)
    29  	JMP	kernelcas<>(SB)
    30  
    31  TEXT kernelcas<>(SB),NOSPLIT,$0
    32  	MOVW	ptr+0(FP), R2
    33  	// trigger potential paging fault here,
    34  	// because we don't know how to traceback through __kuser_cmpxchg
    35  	MOVW    (R2), R0
    36  	MOVW	old+4(FP), R0
    37  	MOVW	new+8(FP), R1
    38  	BL	cas<>(SB)
    39  	BCC	ret0
    40  	MOVW	$1, R0
    41  	MOVB	R0, ret+12(FP)
    42  	RET
    43  ret0:
    44  	MOVW	$0, R0
    45  	MOVB	R0, ret+12(FP)
    46  	RET
    47  
    48  // As for cas, memory barriers are complicated on ARM, but the kernel
    49  // provides a user helper. ARMv5 does not support SMP and has no
    50  // memory barrier instruction at all. ARMv6 added SMP support and has
    51  // a memory barrier, but it requires writing to a coprocessor
    52  // register. ARMv7 introduced the DMB instruction, but it's expensive
    53  // even on single-core devices. The kernel helper takes care of all of
    54  // this for us.
    55  
    56  // Use kernel helper version of memory_barrier, when compiled with GOARM < 7.
    57  TEXT memory_barrier<>(SB),NOSPLIT|NOFRAME,$0
    58  	MOVW	$0xffff0fa0, R15 // R15 is hardware PC.
    59  
    60  TEXT	·Load(SB),NOSPLIT,$0-8
    61  	MOVW	addr+0(FP), R0
    62  	MOVW	(R0), R1
    63  
    64  	MOVB	runtime·goarm(SB), R11
    65  	CMP	$7, R11
    66  	BGE	native_barrier
    67  	BL	memory_barrier<>(SB)
    68  	B	end
    69  native_barrier:
    70  	DMB	MB_ISH
    71  end:
    72  	MOVW	R1, ret+4(FP)
    73  	RET
    74  
    75  TEXT	·Store(SB),NOSPLIT,$0-8
    76  	MOVW	addr+0(FP), R1
    77  	MOVW	v+4(FP), R2
    78  
    79  	MOVB	runtime·goarm(SB), R8
    80  	CMP	$7, R8
    81  	BGE	native_barrier
    82  	BL	memory_barrier<>(SB)
    83  	B	store
    84  native_barrier:
    85  	DMB	MB_ISH
    86  
    87  store:
    88  	MOVW	R2, (R1)
    89  
    90  	CMP	$7, R8
    91  	BGE	native_barrier2
    92  	BL	memory_barrier<>(SB)
    93  	RET
    94  native_barrier2:
    95  	DMB	MB_ISH
    96  	RET
    97  
    98  TEXT	·Load8(SB),NOSPLIT,$0-5
    99  	MOVW	addr+0(FP), R0
   100  	MOVB	(R0), R1
   101  
   102  	MOVB	runtime·goarm(SB), R11
   103  	CMP	$7, R11
   104  	BGE	native_barrier
   105  	BL	memory_barrier<>(SB)
   106  	B	end
   107  native_barrier:
   108  	DMB	MB_ISH
   109  end:
   110  	MOVB	R1, ret+4(FP)
   111  	RET
   112  
   113  TEXT	·Store8(SB),NOSPLIT,$0-5
   114  	MOVW	addr+0(FP), R1
   115  	MOVB	v+4(FP), R2
   116  
   117  	MOVB	runtime·goarm(SB), R8
   118  	CMP	$7, R8
   119  	BGE	native_barrier
   120  	BL	memory_barrier<>(SB)
   121  	B	store
   122  native_barrier:
   123  	DMB	MB_ISH
   124  
   125  store:
   126  	MOVB	R2, (R1)
   127  
   128  	CMP	$7, R8
   129  	BGE	native_barrier2
   130  	BL	memory_barrier<>(SB)
   131  	RET
   132  native_barrier2:
   133  	DMB	MB_ISH
   134  	RET
   135  

View as plain text