aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/arm
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2011-06-19 23:36:03 -0400
committerNicolas Pitre <nico@fluxnic.net>2011-06-28 15:47:47 -0400
commit40fb79c8a88625504857d44de1bc89dc0341e618 (patch)
tree1f0e417a1f1c80fcaa79729f1a4b29e96f01fed2 /Documentation/arm
parent37b8304642c7f91df54888955c373ae89b577fcc (diff)
ARM: add a kuser_cmpxchg64 user space helper
Some user space applications are designed around the ability to perform atomic operations on 64 bit values. Since this is natively possible only with ARMv6k and above, let's provide a new kuser helper to perform the operation with kernel supervision on pre ARMv6k hardware. Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> Tested-by: Dave Martin <dave.martin@linaro.org>
Diffstat (limited to 'Documentation/arm')
-rw-r--r--Documentation/arm/kernel_user_helpers.txt64
1 files changed, 64 insertions, 0 deletions
diff --git a/Documentation/arm/kernel_user_helpers.txt b/Documentation/arm/kernel_user_helpers.txt
index 0c33f72d187..a17df9f91d1 100644
--- a/Documentation/arm/kernel_user_helpers.txt
+++ b/Documentation/arm/kernel_user_helpers.txt
@@ -201,3 +201,67 @@ typedef void (__kuser_dmb_t)(void);
201Notes: 201Notes:
202 202
203 - Valid only if __kuser_helper_version >= 3 (from kernel version 2.6.15). 203 - Valid only if __kuser_helper_version >= 3 (from kernel version 2.6.15).
204
205kuser_cmpxchg64
206---------------
207
208Location: 0xffff0f60
209
210Reference prototype:
211
212 int __kuser_cmpxchg64(const int64_t *oldval,
213 const int64_t *newval,
214 volatile int64_t *ptr);
215
216Input:
217
218 r0 = pointer to oldval
219 r1 = pointer to newval
220 r2 = pointer to target value
221 lr = return address
222
223Output:
224
225 r0 = success code (zero or non-zero)
226 C flag = set if r0 == 0, clear if r0 != 0
227
228Clobbered registers:
229
230 r3, lr, flags
231
232Definition:
233
234 Atomically store the 64-bit value pointed by *newval in *ptr only if *ptr
235 is equal to the 64-bit value pointed by *oldval. Return zero if *ptr was
236 changed or non-zero if no exchange happened.
237
238 The C flag is also set if *ptr was changed to allow for assembly
239 optimization in the calling code.
240
241Usage example:
242
243typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
244 const int64_t *newval,
245 volatile int64_t *ptr);
246#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
247
248int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
249{
250 int64_t old, new;
251
252 do {
253 old = *ptr;
254 new = old + val;
255 } while(__kuser_cmpxchg64(&old, &new, ptr));
256
257 return new;
258}
259
260Notes:
261
262 - This routine already includes memory barriers as needed.
263
264 - Due to the length of this sequence, this spans 2 conventional kuser
265 "slots", therefore 0xffff0f80 is not used as a valid entry point.
266
267 - Valid only if __kuser_helper_version >= 5 (from kernel version 3.1).