1 #ifndef __ASM_ARM_ARM32_SYSREGS_H
2 #define __ASM_ARM_ARM32_SYSREGS_H
3 
4 #include <xen/stringify.h>
5 #include <asm/cpregs.h>
6 
7 /* Layout as used in assembly, with src/dest registers mixed in */
8 #define __CP32(r, coproc, opc1, crn, crm, opc2) coproc, opc1, r, crn, crm, opc2
9 #define __CP64(r1, r2, coproc, opc, crm) coproc, opc, r1, r2, crm
10 #define CP32(r, name...) __CP32(r, name)
11 #define CP64(r, name...) __CP64(r, name)
12 
13 /* Stringified for inline assembly */
14 #define LOAD_CP32(r, name...)  "mrc " __stringify(CP32(%r, name)) ";"
15 #define STORE_CP32(r, name...) "mcr " __stringify(CP32(%r, name)) ";"
16 #define LOAD_CP64(r, name...)  "mrrc " __stringify(CP64(%r, %H##r, name)) ";"
17 #define STORE_CP64(r, name...) "mcrr " __stringify(CP64(%r, %H##r, name)) ";"
18 
19 /* Issue a CP operation which takes no argument,
20  * uses r0 as a placeholder register. */
21 #define CMD_CP32(name...)      "mcr " __stringify(CP32(r0, name)) ";"
22 
23 #ifndef __ASSEMBLY__
24 
25 /* C wrappers */
26 #define READ_CP32(name...) ({                                   \
27     register uint32_t _r;                                       \
28     asm volatile(LOAD_CP32(0, name) : "=r" (_r));               \
29     _r; })
30 
31 #define WRITE_CP32(v, name...) do {                             \
32     register uint32_t _r = (v);                                 \
33     asm volatile(STORE_CP32(0, name) : : "r" (_r));             \
34 } while (0)
35 
36 #define READ_CP64(name...) ({                                   \
37     register uint64_t _r;                                       \
38     asm volatile(LOAD_CP64(0, name) : "=r" (_r));               \
39     _r; })
40 
41 #define WRITE_CP64(v, name...) do {                             \
42     register uint64_t _r = (v);                                 \
43     asm volatile(STORE_CP64(0, name) : : "r" (_r));             \
44 } while (0)
45 
46 /*
47  * C wrappers for accessing system registers.
48  *
49  * Registers come in 3 types:
50  * - those which are always 32-bit regardless of AArch32 vs AArch64
51  *   (use {READ,WRITE}_SYSREG32).
52  * - those which are always 64-bit regardless of AArch32 vs AArch64
53  *   (use {READ,WRITE}_SYSREG64).
54  * - those which vary between AArch32 and AArch64 (use {READ,WRITE}_SYSREG).
55  */
56 #define READ_SYSREG32(R...)     READ_CP32(R)
57 #define WRITE_SYSREG32(V, R...) WRITE_CP32(V, R)
58 
59 #define READ_SYSREG64(R...)     READ_CP64(R)
60 #define WRITE_SYSREG64(V, R...) WRITE_CP64(V, R)
61 
62 #define READ_SYSREG(R...)       READ_SYSREG32(R)
63 #define WRITE_SYSREG(V, R...)   WRITE_SYSREG32(V, R)
64 
65 #endif /* __ASSEMBLY__ */
66 
67 #endif /* __ASM_ARM_ARM32_SYSREGS_H */
68 /*
69  * Local variables:
70  * mode: C
71  * c-file-style: "BSD"
72  * c-basic-offset: 4
73  * indent-tabs-mode: nil
74  * End:
75  */
76