1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#ifndef __ASM_ARM_COMPILER_H
#define __ASM_ARM_COMPILER_H
/*
* This is used to ensure the compiler did actually allocate the register we
* asked it for some inline assembly sequences. Apparently we can't trust
* the compiler from one version to another so a bit of paranoia won't hurt.
* This string is meant to be concatenated with the inline asm string and
* will cause compilation to stop on mismatch.
* (for details, see gcc PR 15089)
*/
#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
#if defined(CONFIG_SMP) && !defined(CONFIG_CPU_V6)
/*
* Read TPIDRPRW.
* GCC requires a workaround as it does not treat a "memory" clobber on a
* non-volatile asm block as a side-effect.
* We want to allow caching the value, so for GCC avoid using volatile and
* instead use a fake stack read to hazard against barrier().
*/
#if defined(__clang__)
static inline unsigned long read_TPIDRPRW(void)
{
unsigned long off;
/*
* Read TPIDRPRW.
*/
asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : : "memory");
return off;
}
#else
static inline unsigned long read_TPIDRPRW(void)
{
unsigned long off;
register unsigned long *sp asm ("sp");
asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : "Q" (*sp));
return off;
}
#endif
#endif
#endif /* __ASM_ARM_COMPILER_H */
|