0001 ============================
0002 Kernel-provided User Helpers
0003 ============================
0004
0005 These are segment of kernel provided user code reachable from user space
0006 at a fixed address in kernel memory. This is used to provide user space
0007 with some operations which require kernel help because of unimplemented
0008 native feature and/or instructions in many ARM CPUs. The idea is for this
0009 code to be executed directly in user mode for best efficiency but which is
0010 too intimate with the kernel counter part to be left to user libraries.
0011 In fact this code might even differ from one CPU to another depending on
0012 the available instruction set, or whether it is a SMP systems. In other
0013 words, the kernel reserves the right to change this code as needed without
0014 warning. Only the entry points and their results as documented here are
0015 guaranteed to be stable.
0016
0017 This is different from (but doesn't preclude) a full blown VDSO
0018 implementation, however a VDSO would prevent some assembly tricks with
0019 constants that allows for efficient branching to those code segments. And
0020 since those code segments only use a few cycles before returning to user
0021 code, the overhead of a VDSO indirect far call would add a measurable
0022 overhead to such minimalistic operations.
0023
0024 User space is expected to bypass those helpers and implement those things
0025 inline (either in the code emitted directly by the compiler, or part of
0026 the implementation of a library call) when optimizing for a recent enough
0027 processor that has the necessary native support, but only if resulting
0028 binaries are already to be incompatible with earlier ARM processors due to
0029 usage of similar native instructions for other things. In other words
0030 don't make binaries unable to run on earlier processors just for the sake
0031 of not using these kernel helpers if your compiled code is not going to
0032 use new instructions for other purpose.
0033
0034 New helpers may be added over time, so an older kernel may be missing some
0035 helpers present in a newer kernel. For this reason, programs must check
0036 the value of __kuser_helper_version (see below) before assuming that it is
0037 safe to call any particular helper. This check should ideally be
0038 performed only once at process startup time, and execution aborted early
0039 if the required helpers are not provided by the kernel version that
0040 process is running on.
0041
0042 kuser_helper_version
0043 --------------------
0044
0045 Location: 0xffff0ffc
0046
0047 Reference declaration::
0048
0049 extern int32_t __kuser_helper_version;
0050
0051 Definition:
0052
0053 This field contains the number of helpers being implemented by the
0054 running kernel. User space may read this to determine the availability
0055 of a particular helper.
0056
0057 Usage example::
0058
0059 #define __kuser_helper_version (*(int32_t *)0xffff0ffc)
0060
0061 void check_kuser_version(void)
0062 {
0063 if (__kuser_helper_version < 2) {
0064 fprintf(stderr, "can't do atomic operations, kernel too old\n");
0065 abort();
0066 }
0067 }
0068
0069 Notes:
0070
0071 User space may assume that the value of this field never changes
0072 during the lifetime of any single process. This means that this
0073 field can be read once during the initialisation of a library or
0074 startup phase of a program.
0075
0076 kuser_get_tls
0077 -------------
0078
0079 Location: 0xffff0fe0
0080
0081 Reference prototype::
0082
0083 void * __kuser_get_tls(void);
0084
0085 Input:
0086
0087 lr = return address
0088
0089 Output:
0090
0091 r0 = TLS value
0092
0093 Clobbered registers:
0094
0095 none
0096
0097 Definition:
0098
0099 Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
0100
0101 Usage example::
0102
0103 typedef void * (__kuser_get_tls_t)(void);
0104 #define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
0105
0106 void foo()
0107 {
0108 void *tls = __kuser_get_tls();
0109 printf("TLS = %p\n", tls);
0110 }
0111
0112 Notes:
0113
0114 - Valid only if __kuser_helper_version >= 1 (from kernel version 2.6.12).
0115
0116 kuser_cmpxchg
0117 -------------
0118
0119 Location: 0xffff0fc0
0120
0121 Reference prototype::
0122
0123 int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
0124
0125 Input:
0126
0127 r0 = oldval
0128 r1 = newval
0129 r2 = ptr
0130 lr = return address
0131
0132 Output:
0133
0134 r0 = success code (zero or non-zero)
0135 C flag = set if r0 == 0, clear if r0 != 0
0136
0137 Clobbered registers:
0138
0139 r3, ip, flags
0140
0141 Definition:
0142
0143 Atomically store newval in `*ptr` only if `*ptr` is equal to oldval.
0144 Return zero if `*ptr` was changed or non-zero if no exchange happened.
0145 The C flag is also set if `*ptr` was changed to allow for assembly
0146 optimization in the calling code.
0147
0148 Usage example::
0149
0150 typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
0151 #define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
0152
0153 int atomic_add(volatile int *ptr, int val)
0154 {
0155 int old, new;
0156
0157 do {
0158 old = *ptr;
0159 new = old + val;
0160 } while(__kuser_cmpxchg(old, new, ptr));
0161
0162 return new;
0163 }
0164
0165 Notes:
0166
0167 - This routine already includes memory barriers as needed.
0168
0169 - Valid only if __kuser_helper_version >= 2 (from kernel version 2.6.12).
0170
0171 kuser_memory_barrier
0172 --------------------
0173
0174 Location: 0xffff0fa0
0175
0176 Reference prototype::
0177
0178 void __kuser_memory_barrier(void);
0179
0180 Input:
0181
0182 lr = return address
0183
0184 Output:
0185
0186 none
0187
0188 Clobbered registers:
0189
0190 none
0191
0192 Definition:
0193
0194 Apply any needed memory barrier to preserve consistency with data modified
0195 manually and __kuser_cmpxchg usage.
0196
0197 Usage example::
0198
0199 typedef void (__kuser_dmb_t)(void);
0200 #define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
0201
0202 Notes:
0203
0204 - Valid only if __kuser_helper_version >= 3 (from kernel version 2.6.15).
0205
0206 kuser_cmpxchg64
0207 ---------------
0208
0209 Location: 0xffff0f60
0210
0211 Reference prototype::
0212
0213 int __kuser_cmpxchg64(const int64_t *oldval,
0214 const int64_t *newval,
0215 volatile int64_t *ptr);
0216
0217 Input:
0218
0219 r0 = pointer to oldval
0220 r1 = pointer to newval
0221 r2 = pointer to target value
0222 lr = return address
0223
0224 Output:
0225
0226 r0 = success code (zero or non-zero)
0227 C flag = set if r0 == 0, clear if r0 != 0
0228
0229 Clobbered registers:
0230
0231 r3, lr, flags
0232
0233 Definition:
0234
0235 Atomically store the 64-bit value pointed by `*newval` in `*ptr` only if `*ptr`
0236 is equal to the 64-bit value pointed by `*oldval`. Return zero if `*ptr` was
0237 changed or non-zero if no exchange happened.
0238
0239 The C flag is also set if `*ptr` was changed to allow for assembly
0240 optimization in the calling code.
0241
0242 Usage example::
0243
0244 typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
0245 const int64_t *newval,
0246 volatile int64_t *ptr);
0247 #define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
0248
0249 int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
0250 {
0251 int64_t old, new;
0252
0253 do {
0254 old = *ptr;
0255 new = old + val;
0256 } while(__kuser_cmpxchg64(&old, &new, ptr));
0257
0258 return new;
0259 }
0260
0261 Notes:
0262
0263 - This routine already includes memory barriers as needed.
0264
0265 - Due to the length of this sequence, this spans 2 conventional kuser
0266 "slots", therefore 0xffff0f80 is not used as a valid entry point.
0267
0268 - Valid only if __kuser_helper_version >= 5 (from kernel version 3.1).