~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/arch/arm/kernel_user_helpers.rst

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 ============================
  2 Kernel-provided User Helpers
  3 ============================
  4 
  5 These are segment of kernel provided user code reachable from user space
  6 at a fixed address in kernel memory.  This is used to provide user space
  7 with some operations which require kernel help because of unimplemented
  8 native feature and/or instructions in many ARM CPUs. The idea is for this
  9 code to be executed directly in user mode for best efficiency but which is
 10 too intimate with the kernel counter part to be left to user libraries.
 11 In fact this code might even differ from one CPU to another depending on
 12 the available instruction set, or whether it is a SMP systems. In other
 13 words, the kernel reserves the right to change this code as needed without
 14 warning. Only the entry points and their results as documented here are
 15 guaranteed to be stable.
 16 
 17 This is different from (but doesn't preclude) a full blown VDSO
 18 implementation, however a VDSO would prevent some assembly tricks with
 19 constants that allows for efficient branching to those code segments. And
 20 since those code segments only use a few cycles before returning to user
 21 code, the overhead of a VDSO indirect far call would add a measurable
 22 overhead to such minimalistic operations.
 23 
 24 User space is expected to bypass those helpers and implement those things
 25 inline (either in the code emitted directly by the compiler, or part of
 26 the implementation of a library call) when optimizing for a recent enough
 27 processor that has the necessary native support, but only if resulting
 28 binaries are already to be incompatible with earlier ARM processors due to
 29 usage of similar native instructions for other things.  In other words
 30 don't make binaries unable to run on earlier processors just for the sake
 31 of not using these kernel helpers if your compiled code is not going to
 32 use new instructions for other purpose.
 33 
 34 New helpers may be added over time, so an older kernel may be missing some
 35 helpers present in a newer kernel.  For this reason, programs must check
 36 the value of __kuser_helper_version (see below) before assuming that it is
 37 safe to call any particular helper.  This check should ideally be
 38 performed only once at process startup time, and execution aborted early
 39 if the required helpers are not provided by the kernel version that
 40 process is running on.
 41 
 42 kuser_helper_version
 43 --------------------
 44 
 45 Location:       0xffff0ffc
 46 
 47 Reference declaration::
 48 
 49   extern int32_t __kuser_helper_version;
 50 
 51 Definition:
 52 
 53   This field contains the number of helpers being implemented by the
 54   running kernel.  User space may read this to determine the availability
 55   of a particular helper.
 56 
 57 Usage example::
 58 
 59   #define __kuser_helper_version (*(int32_t *)0xffff0ffc)
 60 
 61   void check_kuser_version(void)
 62   {
 63         if (__kuser_helper_version < 2) {
 64                 fprintf(stderr, "can't do atomic operations, kernel too old\n");
 65                 abort();
 66         }
 67   }
 68 
 69 Notes:
 70 
 71   User space may assume that the value of this field never changes
 72   during the lifetime of any single process.  This means that this
 73   field can be read once during the initialisation of a library or
 74   startup phase of a program.
 75 
 76 kuser_get_tls
 77 -------------
 78 
 79 Location:       0xffff0fe0
 80 
 81 Reference prototype::
 82 
 83   void * __kuser_get_tls(void);
 84 
 85 Input:
 86 
 87   lr = return address
 88 
 89 Output:
 90 
 91   r0 = TLS value
 92 
 93 Clobbered registers:
 94 
 95   none
 96 
 97 Definition:
 98 
 99   Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
100 
101 Usage example::
102 
103   typedef void * (__kuser_get_tls_t)(void);
104   #define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
105 
106   void foo()
107   {
108         void *tls = __kuser_get_tls();
109         printf("TLS = %p\n", tls);
110   }
111 
112 Notes:
113 
114   - Valid only if __kuser_helper_version >= 1 (from kernel version 2.6.12).
115 
116 kuser_cmpxchg
117 -------------
118 
119 Location:       0xffff0fc0
120 
121 Reference prototype::
122 
123   int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
124 
125 Input:
126 
127   r0 = oldval
128   r1 = newval
129   r2 = ptr
130   lr = return address
131 
132 Output:
133 
134   r0 = success code (zero or non-zero)
135   C flag = set if r0 == 0, clear if r0 != 0
136 
137 Clobbered registers:
138 
139   r3, ip, flags
140 
141 Definition:
142 
143   Atomically store newval in `*ptr` only if `*ptr` is equal to oldval.
144   Return zero if `*ptr` was changed or non-zero if no exchange happened.
145   The C flag is also set if `*ptr` was changed to allow for assembly
146   optimization in the calling code.
147 
148 Usage example::
149 
150   typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
151   #define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
152 
153   int atomic_add(volatile int *ptr, int val)
154   {
155         int old, new;
156 
157         do {
158                 old = *ptr;
159                 new = old + val;
160         } while(__kuser_cmpxchg(old, new, ptr));
161 
162         return new;
163   }
164 
165 Notes:
166 
167   - This routine already includes memory barriers as needed.
168 
169   - Valid only if __kuser_helper_version >= 2 (from kernel version 2.6.12).
170 
171 kuser_memory_barrier
172 --------------------
173 
174 Location:       0xffff0fa0
175 
176 Reference prototype::
177 
178   void __kuser_memory_barrier(void);
179 
180 Input:
181 
182   lr = return address
183 
184 Output:
185 
186   none
187 
188 Clobbered registers:
189 
190   none
191 
192 Definition:
193 
194   Apply any needed memory barrier to preserve consistency with data modified
195   manually and __kuser_cmpxchg usage.
196 
197 Usage example::
198 
199   typedef void (__kuser_dmb_t)(void);
200   #define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
201 
202 Notes:
203 
204   - Valid only if __kuser_helper_version >= 3 (from kernel version 2.6.15).
205 
206 kuser_cmpxchg64
207 ---------------
208 
209 Location:       0xffff0f60
210 
211 Reference prototype::
212 
213   int __kuser_cmpxchg64(const int64_t *oldval,
214                         const int64_t *newval,
215                         volatile int64_t *ptr);
216 
217 Input:
218 
219   r0 = pointer to oldval
220   r1 = pointer to newval
221   r2 = pointer to target value
222   lr = return address
223 
224 Output:
225 
226   r0 = success code (zero or non-zero)
227   C flag = set if r0 == 0, clear if r0 != 0
228 
229 Clobbered registers:
230 
231   r3, lr, flags
232 
233 Definition:
234 
235   Atomically store the 64-bit value pointed by `*newval` in `*ptr` only if `*ptr`
236   is equal to the 64-bit value pointed by `*oldval`.  Return zero if `*ptr` was
237   changed or non-zero if no exchange happened.
238 
239   The C flag is also set if `*ptr` was changed to allow for assembly
240   optimization in the calling code.
241 
242 Usage example::
243 
244   typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
245                                     const int64_t *newval,
246                                     volatile int64_t *ptr);
247   #define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
248 
249   int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
250   {
251         int64_t old, new;
252 
253         do {
254                 old = *ptr;
255                 new = old + val;
256         } while(__kuser_cmpxchg64(&old, &new, ptr));
257 
258         return new;
259   }
260 
261 Notes:
262 
263   - This routine already includes memory barriers as needed.
264 
265   - Due to the length of this sequence, this spans 2 conventional kuser
266     "slots", therefore 0xffff0f80 is not used as a valid entry point.
267 
268   - Valid only if __kuser_helper_version >= 5 (from kernel version 3.1).

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php