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