18c2ecf20Sopenharmony_ci============================
28c2ecf20Sopenharmony_ciKernel-provided User Helpers
38c2ecf20Sopenharmony_ci============================
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ciThese are segment of kernel provided user code reachable from user space
68c2ecf20Sopenharmony_ciat a fixed address in kernel memory.  This is used to provide user space
78c2ecf20Sopenharmony_ciwith some operations which require kernel help because of unimplemented
88c2ecf20Sopenharmony_cinative feature and/or instructions in many ARM CPUs. The idea is for this
98c2ecf20Sopenharmony_cicode to be executed directly in user mode for best efficiency but which is
108c2ecf20Sopenharmony_citoo intimate with the kernel counter part to be left to user libraries.
118c2ecf20Sopenharmony_ciIn fact this code might even differ from one CPU to another depending on
128c2ecf20Sopenharmony_cithe available instruction set, or whether it is a SMP systems. In other
138c2ecf20Sopenharmony_ciwords, the kernel reserves the right to change this code as needed without
148c2ecf20Sopenharmony_ciwarning. Only the entry points and their results as documented here are
158c2ecf20Sopenharmony_ciguaranteed to be stable.
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ciThis is different from (but doesn't preclude) a full blown VDSO
188c2ecf20Sopenharmony_ciimplementation, however a VDSO would prevent some assembly tricks with
198c2ecf20Sopenharmony_ciconstants that allows for efficient branching to those code segments. And
208c2ecf20Sopenharmony_cisince those code segments only use a few cycles before returning to user
218c2ecf20Sopenharmony_cicode, the overhead of a VDSO indirect far call would add a measurable
228c2ecf20Sopenharmony_cioverhead to such minimalistic operations.
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ciUser space is expected to bypass those helpers and implement those things
258c2ecf20Sopenharmony_ciinline (either in the code emitted directly by the compiler, or part of
268c2ecf20Sopenharmony_cithe implementation of a library call) when optimizing for a recent enough
278c2ecf20Sopenharmony_ciprocessor that has the necessary native support, but only if resulting
288c2ecf20Sopenharmony_cibinaries are already to be incompatible with earlier ARM processors due to
298c2ecf20Sopenharmony_ciusage of similar native instructions for other things.  In other words
308c2ecf20Sopenharmony_cidon't make binaries unable to run on earlier processors just for the sake
318c2ecf20Sopenharmony_ciof not using these kernel helpers if your compiled code is not going to
328c2ecf20Sopenharmony_ciuse new instructions for other purpose.
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ciNew helpers may be added over time, so an older kernel may be missing some
358c2ecf20Sopenharmony_cihelpers present in a newer kernel.  For this reason, programs must check
368c2ecf20Sopenharmony_cithe value of __kuser_helper_version (see below) before assuming that it is
378c2ecf20Sopenharmony_cisafe to call any particular helper.  This check should ideally be
388c2ecf20Sopenharmony_ciperformed only once at process startup time, and execution aborted early
398c2ecf20Sopenharmony_ciif the required helpers are not provided by the kernel version that
408c2ecf20Sopenharmony_ciprocess is running on.
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cikuser_helper_version
438c2ecf20Sopenharmony_ci--------------------
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ciLocation:	0xffff0ffc
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ciReference declaration::
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci  extern int32_t __kuser_helper_version;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ciDefinition:
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci  This field contains the number of helpers being implemented by the
548c2ecf20Sopenharmony_ci  running kernel.  User space may read this to determine the availability
558c2ecf20Sopenharmony_ci  of a particular helper.
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ciUsage example::
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci  #define __kuser_helper_version (*(int32_t *)0xffff0ffc)
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci  void check_kuser_version(void)
628c2ecf20Sopenharmony_ci  {
638c2ecf20Sopenharmony_ci	if (__kuser_helper_version < 2) {
648c2ecf20Sopenharmony_ci		fprintf(stderr, "can't do atomic operations, kernel too old\n");
658c2ecf20Sopenharmony_ci		abort();
668c2ecf20Sopenharmony_ci	}
678c2ecf20Sopenharmony_ci  }
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ciNotes:
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci  User space may assume that the value of this field never changes
728c2ecf20Sopenharmony_ci  during the lifetime of any single process.  This means that this
738c2ecf20Sopenharmony_ci  field can be read once during the initialisation of a library or
748c2ecf20Sopenharmony_ci  startup phase of a program.
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cikuser_get_tls
778c2ecf20Sopenharmony_ci-------------
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ciLocation:	0xffff0fe0
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ciReference prototype::
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci  void * __kuser_get_tls(void);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ciInput:
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci  lr = return address
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ciOutput:
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci  r0 = TLS value
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ciClobbered registers:
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci  none
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ciDefinition:
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci  Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciUsage example::
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci  typedef void * (__kuser_get_tls_t)(void);
1048c2ecf20Sopenharmony_ci  #define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci  void foo()
1078c2ecf20Sopenharmony_ci  {
1088c2ecf20Sopenharmony_ci	void *tls = __kuser_get_tls();
1098c2ecf20Sopenharmony_ci	printf("TLS = %p\n", tls);
1108c2ecf20Sopenharmony_ci  }
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ciNotes:
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci  - Valid only if __kuser_helper_version >= 1 (from kernel version 2.6.12).
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cikuser_cmpxchg
1178c2ecf20Sopenharmony_ci-------------
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ciLocation:	0xffff0fc0
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ciReference prototype::
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci  int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ciInput:
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci  r0 = oldval
1288c2ecf20Sopenharmony_ci  r1 = newval
1298c2ecf20Sopenharmony_ci  r2 = ptr
1308c2ecf20Sopenharmony_ci  lr = return address
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ciOutput:
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci  r0 = success code (zero or non-zero)
1358c2ecf20Sopenharmony_ci  C flag = set if r0 == 0, clear if r0 != 0
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ciClobbered registers:
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci  r3, ip, flags
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ciDefinition:
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci  Atomically store newval in `*ptr` only if `*ptr` is equal to oldval.
1448c2ecf20Sopenharmony_ci  Return zero if `*ptr` was changed or non-zero if no exchange happened.
1458c2ecf20Sopenharmony_ci  The C flag is also set if `*ptr` was changed to allow for assembly
1468c2ecf20Sopenharmony_ci  optimization in the calling code.
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ciUsage example::
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci  typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
1518c2ecf20Sopenharmony_ci  #define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci  int atomic_add(volatile int *ptr, int val)
1548c2ecf20Sopenharmony_ci  {
1558c2ecf20Sopenharmony_ci	int old, new;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	do {
1588c2ecf20Sopenharmony_ci		old = *ptr;
1598c2ecf20Sopenharmony_ci		new = old + val;
1608c2ecf20Sopenharmony_ci	} while(__kuser_cmpxchg(old, new, ptr));
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	return new;
1638c2ecf20Sopenharmony_ci  }
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ciNotes:
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci  - This routine already includes memory barriers as needed.
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci  - Valid only if __kuser_helper_version >= 2 (from kernel version 2.6.12).
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cikuser_memory_barrier
1728c2ecf20Sopenharmony_ci--------------------
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ciLocation:	0xffff0fa0
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ciReference prototype::
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci  void __kuser_memory_barrier(void);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ciInput:
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci  lr = return address
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ciOutput:
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci  none
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ciClobbered registers:
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci  none
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ciDefinition:
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci  Apply any needed memory barrier to preserve consistency with data modified
1958c2ecf20Sopenharmony_ci  manually and __kuser_cmpxchg usage.
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ciUsage example::
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci  typedef void (__kuser_dmb_t)(void);
2008c2ecf20Sopenharmony_ci  #define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ciNotes:
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci  - Valid only if __kuser_helper_version >= 3 (from kernel version 2.6.15).
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cikuser_cmpxchg64
2078c2ecf20Sopenharmony_ci---------------
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ciLocation:	0xffff0f60
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ciReference prototype::
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci  int __kuser_cmpxchg64(const int64_t *oldval,
2148c2ecf20Sopenharmony_ci                        const int64_t *newval,
2158c2ecf20Sopenharmony_ci                        volatile int64_t *ptr);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ciInput:
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci  r0 = pointer to oldval
2208c2ecf20Sopenharmony_ci  r1 = pointer to newval
2218c2ecf20Sopenharmony_ci  r2 = pointer to target value
2228c2ecf20Sopenharmony_ci  lr = return address
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ciOutput:
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci  r0 = success code (zero or non-zero)
2278c2ecf20Sopenharmony_ci  C flag = set if r0 == 0, clear if r0 != 0
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ciClobbered registers:
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci  r3, lr, flags
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ciDefinition:
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci  Atomically store the 64-bit value pointed by `*newval` in `*ptr` only if `*ptr`
2368c2ecf20Sopenharmony_ci  is equal to the 64-bit value pointed by `*oldval`.  Return zero if `*ptr` was
2378c2ecf20Sopenharmony_ci  changed or non-zero if no exchange happened.
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci  The C flag is also set if `*ptr` was changed to allow for assembly
2408c2ecf20Sopenharmony_ci  optimization in the calling code.
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ciUsage example::
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci  typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
2458c2ecf20Sopenharmony_ci                                    const int64_t *newval,
2468c2ecf20Sopenharmony_ci                                    volatile int64_t *ptr);
2478c2ecf20Sopenharmony_ci  #define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci  int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
2508c2ecf20Sopenharmony_ci  {
2518c2ecf20Sopenharmony_ci	int64_t old, new;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	do {
2548c2ecf20Sopenharmony_ci		old = *ptr;
2558c2ecf20Sopenharmony_ci		new = old + val;
2568c2ecf20Sopenharmony_ci	} while(__kuser_cmpxchg64(&old, &new, ptr));
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	return new;
2598c2ecf20Sopenharmony_ci  }
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ciNotes:
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci  - This routine already includes memory barriers as needed.
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci  - Due to the length of this sequence, this spans 2 conventional kuser
2668c2ecf20Sopenharmony_ci    "slots", therefore 0xffff0f80 is not used as a valid entry point.
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci  - Valid only if __kuser_helper_version >= 5 (from kernel version 3.1).
269