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