huangcm
2025-09-01 53d8e046ac1bf2ebe94f671983e3d3be059df91a
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/*
 * Macros for accessing system registers with older binutils.
 *
 * Copyright (C) 2014 ARM Ltd.
 * Author: Catalin Marinas <catalin.marinas@arm.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
#ifndef __ASM_SYSREG_H
#define __ASM_SYSREG_H
 
#include <linux/stringify.h>
 
#include <asm/opcodes.h>
 
/*
 * ARMv8 ARM reserves the following encoding for system registers:
 * (Ref: ARMv8 ARM, Section: "System instruction class encoding overview",
 *  C5.2, version:ARM DDI 0487A.f)
 *    [20-19] : Op0
 *    [18-16] : Op1
 *    [15-12] : CRn
 *    [11-8]  : CRm
 *    [7-5]   : Op2
 */
#define sys_reg(op0, op1, crn, crm, op2) \
   ((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))
 
#define SYS_MIDR_EL1            sys_reg(3, 0, 0, 0, 0)
#define SYS_MPIDR_EL1            sys_reg(3, 0, 0, 0, 5)
#define SYS_REVIDR_EL1            sys_reg(3, 0, 0, 0, 6)
 
#define SYS_ID_PFR0_EL1            sys_reg(3, 0, 0, 1, 0)
#define SYS_ID_PFR1_EL1            sys_reg(3, 0, 0, 1, 1)
#define SYS_ID_DFR0_EL1            sys_reg(3, 0, 0, 1, 2)
#define SYS_ID_MMFR0_EL1        sys_reg(3, 0, 0, 1, 4)
#define SYS_ID_MMFR1_EL1        sys_reg(3, 0, 0, 1, 5)
#define SYS_ID_MMFR2_EL1        sys_reg(3, 0, 0, 1, 6)
#define SYS_ID_MMFR3_EL1        sys_reg(3, 0, 0, 1, 7)
 
#define SYS_ID_ISAR0_EL1        sys_reg(3, 0, 0, 2, 0)
#define SYS_ID_ISAR1_EL1        sys_reg(3, 0, 0, 2, 1)
#define SYS_ID_ISAR2_EL1        sys_reg(3, 0, 0, 2, 2)
#define SYS_ID_ISAR3_EL1        sys_reg(3, 0, 0, 2, 3)
#define SYS_ID_ISAR4_EL1        sys_reg(3, 0, 0, 2, 4)
#define SYS_ID_ISAR5_EL1        sys_reg(3, 0, 0, 2, 5)
#define SYS_ID_MMFR4_EL1        sys_reg(3, 0, 0, 2, 6)
 
#define SYS_MVFR0_EL1            sys_reg(3, 0, 0, 3, 0)
#define SYS_MVFR1_EL1            sys_reg(3, 0, 0, 3, 1)
#define SYS_MVFR2_EL1            sys_reg(3, 0, 0, 3, 2)
 
#define SYS_ID_AA64PFR0_EL1        sys_reg(3, 0, 0, 4, 0)
#define SYS_ID_AA64PFR1_EL1        sys_reg(3, 0, 0, 4, 1)
 
#define SYS_ID_AA64DFR0_EL1        sys_reg(3, 0, 0, 5, 0)
#define SYS_ID_AA64DFR1_EL1        sys_reg(3, 0, 0, 5, 1)
 
#define SYS_ID_AA64ISAR0_EL1        sys_reg(3, 0, 0, 6, 0)
#define SYS_ID_AA64ISAR1_EL1        sys_reg(3, 0, 0, 6, 1)
 
#define SYS_ID_AA64MMFR0_EL1        sys_reg(3, 0, 0, 7, 0)
#define SYS_ID_AA64MMFR1_EL1        sys_reg(3, 0, 0, 7, 1)
#define SYS_ID_AA64MMFR2_EL1        sys_reg(3, 0, 0, 7, 2)
 
#define SYS_CNTFRQ_EL0            sys_reg(3, 3, 14, 0, 0)
#define SYS_CTR_EL0            sys_reg(3, 3, 0, 0, 1)
#define SYS_DCZID_EL0            sys_reg(3, 3, 0, 0, 7)
 
#define REG_PSTATE_PAN_IMM        sys_reg(0, 0, 4, 0, 4)
#define REG_PSTATE_UAO_IMM        sys_reg(0, 0, 4, 0, 3)
 
#define SET_PSTATE_PAN(x) __inst_arm(0xd5000000 | REG_PSTATE_PAN_IMM |\
                    (!!x)<<8 | 0x1f)
#define SET_PSTATE_UAO(x) __inst_arm(0xd5000000 | REG_PSTATE_UAO_IMM |\
                    (!!x)<<8 | 0x1f)
 
/* Common SCTLR_ELx flags. */
#define SCTLR_ELx_EE    (1 << 25)
#define SCTLR_ELx_I    (1 << 12)
#define SCTLR_ELx_SA    (1 << 3)
#define SCTLR_ELx_C    (1 << 2)
#define SCTLR_ELx_A    (1 << 1)
#define SCTLR_ELx_M    1
 
#define SCTLR_EL2_RES1    ((1 << 4)  | (1 << 5)  | (1 << 11) | (1 << 16) | \
            (1 << 16) | (1 << 18) | (1 << 22) | (1 << 23) | \
            (1 << 28) | (1 << 29))
 
#define SCTLR_ELx_FLAGS    (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \
            SCTLR_ELx_SA | SCTLR_ELx_I)
 
/* SCTLR_EL1 specific flags. */
#define SCTLR_EL1_UCI        (1 << 26)
#define SCTLR_EL1_SPAN        (1 << 23)
#define SCTLR_EL1_UCT        (1 << 15)
#define SCTLR_EL1_SED        (1 << 8)
#define SCTLR_EL1_CP15BEN    (1 << 5)
 
/* id_aa64isar0 */
#define ID_AA64ISAR0_DP_SHIFT        44
#define ID_AA64ISAR0_SM4_SHIFT        40
#define ID_AA64ISAR0_SM3_SHIFT        36
#define ID_AA64ISAR0_SHA3_SHIFT        32
#define ID_AA64ISAR0_RDM_SHIFT        28
#define ID_AA64ISAR0_ATOMICS_SHIFT    20
#define ID_AA64ISAR0_CRC32_SHIFT    16
#define ID_AA64ISAR0_SHA2_SHIFT        12
#define ID_AA64ISAR0_SHA1_SHIFT        8
#define ID_AA64ISAR0_AES_SHIFT        4
 
/* id_aa64pfr0 */
#define ID_AA64PFR0_CSV3_SHIFT        60
#define ID_AA64PFR0_CSV2_SHIFT        56
#define ID_AA64PFR0_SVE_SHIFT        32
#define ID_AA64PFR0_GIC_SHIFT        24
#define ID_AA64PFR0_ASIMD_SHIFT        20
#define ID_AA64PFR0_FP_SHIFT        16
#define ID_AA64PFR0_EL3_SHIFT        12
#define ID_AA64PFR0_EL2_SHIFT        8
#define ID_AA64PFR0_EL1_SHIFT        4
#define ID_AA64PFR0_EL0_SHIFT        0
 
#define ID_AA64PFR0_FP_NI        0xf
#define ID_AA64PFR0_FP_SUPPORTED    0x0
#define ID_AA64PFR0_ASIMD_NI        0xf
#define ID_AA64PFR0_ASIMD_SUPPORTED    0x0
#define ID_AA64PFR0_EL1_64BIT_ONLY    0x1
#define ID_AA64PFR0_EL0_64BIT_ONLY    0x1
#define ID_AA64PFR0_EL0_32BIT_64BIT    0x2
 
/* id_aa64mmfr0 */
#define ID_AA64MMFR0_TGRAN4_SHIFT    28
#define ID_AA64MMFR0_TGRAN64_SHIFT    24
#define ID_AA64MMFR0_TGRAN16_SHIFT    20
#define ID_AA64MMFR0_BIGENDEL0_SHIFT    16
#define ID_AA64MMFR0_SNSMEM_SHIFT    12
#define ID_AA64MMFR0_BIGENDEL_SHIFT    8
#define ID_AA64MMFR0_ASID_SHIFT        4
#define ID_AA64MMFR0_PARANGE_SHIFT    0
 
#define ID_AA64MMFR0_TGRAN4_NI        0xf
#define ID_AA64MMFR0_TGRAN4_SUPPORTED    0x0
#define ID_AA64MMFR0_TGRAN64_NI        0xf
#define ID_AA64MMFR0_TGRAN64_SUPPORTED    0x0
#define ID_AA64MMFR0_TGRAN16_NI        0x0
#define ID_AA64MMFR0_TGRAN16_SUPPORTED    0x1
 
/* id_aa64mmfr1 */
#define ID_AA64MMFR1_PAN_SHIFT        20
#define ID_AA64MMFR1_LOR_SHIFT        16
#define ID_AA64MMFR1_HPD_SHIFT        12
#define ID_AA64MMFR1_VHE_SHIFT        8
#define ID_AA64MMFR1_VMIDBITS_SHIFT    4
#define ID_AA64MMFR1_HADBS_SHIFT    0
 
#define ID_AA64MMFR1_VMIDBITS_8        0
#define ID_AA64MMFR1_VMIDBITS_16    2
 
/* id_aa64mmfr2 */
#define ID_AA64MMFR2_LVA_SHIFT        16
#define ID_AA64MMFR2_IESB_SHIFT        12
#define ID_AA64MMFR2_LSM_SHIFT        8
#define ID_AA64MMFR2_UAO_SHIFT        4
#define ID_AA64MMFR2_CNP_SHIFT        0
 
/* id_aa64dfr0 */
#define ID_AA64DFR0_CTX_CMPS_SHIFT    28
#define ID_AA64DFR0_WRPS_SHIFT        20
#define ID_AA64DFR0_BRPS_SHIFT        12
#define ID_AA64DFR0_PMUVER_SHIFT    8
#define ID_AA64DFR0_TRACEVER_SHIFT    4
#define ID_AA64DFR0_DEBUGVER_SHIFT    0
 
#define ID_ISAR5_RDM_SHIFT        24
#define ID_ISAR5_CRC32_SHIFT        16
#define ID_ISAR5_SHA2_SHIFT        12
#define ID_ISAR5_SHA1_SHIFT        8
#define ID_ISAR5_AES_SHIFT        4
#define ID_ISAR5_SEVL_SHIFT        0
 
#define MVFR0_FPROUND_SHIFT        28
#define MVFR0_FPSHVEC_SHIFT        24
#define MVFR0_FPSQRT_SHIFT        20
#define MVFR0_FPDIVIDE_SHIFT        16
#define MVFR0_FPTRAP_SHIFT        12
#define MVFR0_FPDP_SHIFT        8
#define MVFR0_FPSP_SHIFT        4
#define MVFR0_SIMD_SHIFT        0
 
#define MVFR1_SIMDFMAC_SHIFT        28
#define MVFR1_FPHP_SHIFT        24
#define MVFR1_SIMDHP_SHIFT        20
#define MVFR1_SIMDSP_SHIFT        16
#define MVFR1_SIMDINT_SHIFT        12
#define MVFR1_SIMDLS_SHIFT        8
#define MVFR1_FPDNAN_SHIFT        4
#define MVFR1_FPFTZ_SHIFT        0
 
 
#define ID_AA64MMFR0_TGRAN4_SHIFT    28
#define ID_AA64MMFR0_TGRAN64_SHIFT    24
#define ID_AA64MMFR0_TGRAN16_SHIFT    20
 
#define ID_AA64MMFR0_TGRAN4_NI        0xf
#define ID_AA64MMFR0_TGRAN4_SUPPORTED    0x0
#define ID_AA64MMFR0_TGRAN64_NI        0xf
#define ID_AA64MMFR0_TGRAN64_SUPPORTED    0x0
#define ID_AA64MMFR0_TGRAN16_NI        0x0
#define ID_AA64MMFR0_TGRAN16_SUPPORTED    0x1
 
#if defined(CONFIG_ARM64_4K_PAGES)
#define ID_AA64MMFR0_TGRAN_SHIFT    ID_AA64MMFR0_TGRAN4_SHIFT
#define ID_AA64MMFR0_TGRAN_SUPPORTED    ID_AA64MMFR0_TGRAN4_SUPPORTED
#elif defined(CONFIG_ARM64_16K_PAGES)
#define ID_AA64MMFR0_TGRAN_SHIFT    ID_AA64MMFR0_TGRAN16_SHIFT
#define ID_AA64MMFR0_TGRAN_SUPPORTED    ID_AA64MMFR0_TGRAN16_SUPPORTED
#elif defined(CONFIG_ARM64_64K_PAGES)
#define ID_AA64MMFR0_TGRAN_SHIFT    ID_AA64MMFR0_TGRAN64_SHIFT
#define ID_AA64MMFR0_TGRAN_SUPPORTED    ID_AA64MMFR0_TGRAN64_SUPPORTED
#endif
 
#ifdef __ASSEMBLY__
 
   .irp    num,0,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
   .equ    .L__reg_num_x\num, \num
   .endr
   .equ    .L__reg_num_xzr, 31
 
   .macro    mrs_s, rt, sreg
   .inst    0xd5200000|(\sreg)|(.L__reg_num_\rt)
   .endm
 
   .macro    msr_s, sreg, rt
   .inst    0xd5000000|(\sreg)|(.L__reg_num_\rt)
   .endm
 
#else
 
#include <linux/types.h>
 
#define __DEFINE_MRS_MSR_S_REGNUM                \
"    .irp    num,0,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\n" \
"    .equ    .L__reg_num_x\\num, \\num\n"            \
"    .endr\n"                        \
"    .equ    .L__reg_num_xzr, 31\n"
 
#define DEFINE_MRS_S                        \
   __DEFINE_MRS_MSR_S_REGNUM                \
"    .macro    mrs_s, rt, sreg\n"                \
"    .inst 0xd5200000|(\\sreg)|(.L__reg_num_\\rt)\n"    \
"    .endm\n"
 
#define DEFINE_MSR_S                        \
   __DEFINE_MRS_MSR_S_REGNUM                \
"    .macro    msr_s, sreg, rt\n"                \
"    .inst 0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n"        \
"    .endm\n"
 
#define UNDEFINE_MRS_S                        \
"    .purgem    mrs_s\n"
 
#define UNDEFINE_MSR_S                        \
"    .purgem    msr_s\n"
 
#define __mrs_s(r, v)                        \
   DEFINE_MRS_S                        \
"    mrs_s %0, " __stringify(r) "\n"                \
   UNDEFINE_MRS_S : "=r" (v)
 
#define __msr_s(r, v)                        \
   DEFINE_MSR_S                        \
"    msr_s " __stringify(r) ", %x0\n"            \
   UNDEFINE_MSR_S : : "rZ" (v)
 
/*
 * Unlike read_cpuid, calls to read_sysreg are never expected to be
 * optimized away or replaced with synthetic values.
 */
#define read_sysreg(r) ({                    \
   u64 __val;                        \
   asm volatile("mrs %0, " __stringify(r) : "=r" (__val));    \
   __val;                            \
})
 
/*
 * The "Z" constraint normally means a zero immediate, but when combined with
 * the "%x0" template means XZR.
 */
#define write_sysreg(v, r) do {                    \
   u64 __val = (u64)v;                    \
   asm volatile("msr " __stringify(r) ", %x0"        \
            : : "rZ" (__val));                \
} while (0)
 
/*
 * For registers without architectural names, or simply unsupported by
 * GAS.
 */
#define read_sysreg_s(r) ({                    \
   u64 __val;                        \
   asm volatile(__mrs_s(r, __val));            \
   __val;                            \
})
 
#define write_sysreg_s(v, r) do {                \
   u64 __val = (u64)(v);                    \
   asm volatile(__msr_s(r, __val));            \
} while (0)
 
static inline void config_sctlr_el1(u32 clear, u32 set)
{
   u32 val;
 
   val = read_sysreg(sctlr_el1);
   val &= ~clear;
   val |= set;
   write_sysreg(val, sctlr_el1);
}
 
#endif
 
#endif    /* __ASM_SYSREG_H */