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