source: rtems/cpukit/score/cpu/arm/include/libcpu/arm-cp15.h @ 8e8cf72

Last change on this file since 8e8cf72 was 8e8cf72, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 13, 2017 at 7:42:34 AM

arm: Move <libcpu/arm-cp15.h> to cpukit

Update #3254.

  • Property mode set to 100644
File size: 47.1 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreCPUARMCP15
5 *
6 * @brief ARM co-processor 15 (CP15) API.
7 */
8
9/*
10 * Copyright (c) 2013 Hesham AL-Matary
11 * Copyright (c) 2009-2017 embedded brains GmbH.  All rights reserved.
12 *
13 *  embedded brains GmbH
14 *  Dornierstr. 4
15 *  82178 Puchheim
16 *  Germany
17 *  <info@embedded-brains.de>
18 *
19 * The license and distribution terms for this file may be
20 * found in the file LICENSE in this distribution or at
21 * http://www.rtems.org/license/LICENSE.
22 */
23
24#ifndef LIBCPU_SHARED_ARM_CP15_H
25#define LIBCPU_SHARED_ARM_CP15_H
26
27#include <rtems.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif /* __cplusplus */
32
33/*
34 * Allow users of this header file to optionally place the inline functions
35 * into a non-standard section.
36 */
37#ifndef ARM_CP15_TEXT_SECTION
38  #define ARM_CP15_TEXT_SECTION
39#endif
40
41#define ARM_CP15_CACHE_PREPARE_MVA(mva) \
42  ((const void *) (((uint32_t) (mva)) & ~0x1fU))
43
44#define ARM_CP15_TLB_PREPARE_MVA(mva) \
45  ((const void *) (((uint32_t) (mva)) & ~0x3fU))
46
47/**
48 * @defgroup ScoreCPUARMCP15 ARM Co-Processor 15 Support
49 *
50 * @ingroup ScoreCPUARM
51 *
52 * @brief ARM co-processor 15 (CP15) support.
53 *
54 * @{
55 */
56
57/**
58 * @name MMU Defines
59 *
60 * See section B3.8.2, "Short-descriptor format memory region attributes,
61 * without TEX remap" in the "ARM Architecture Reference Manual ARMv7-A and
62 * ARMv7-R edition".
63 *
64 * @{
65 */
66
67#define ARM_MMU_SECT_BASE_SHIFT 20
68#define ARM_MMU_SECT_BASE_MASK (0xfffU << ARM_MMU_SECT_BASE_SHIFT)
69#define ARM_MMU_SECT_NS (1U << 19)
70#define ARM_MMU_SECT_NG (1U << 17)
71#define ARM_MMU_SECT_S (1U << 16)
72#define ARM_MMU_SECT_AP_2 (1U << 15)
73#define ARM_MMU_SECT_TEX_2 (1U << 14)
74#define ARM_MMU_SECT_TEX_1 (1U << 13)
75#define ARM_MMU_SECT_TEX_0 (1U << 12)
76#define ARM_MMU_SECT_TEX_SHIFT 12
77#define ARM_MMU_SECT_TEX_MASK (0x3U << ARM_MMU_SECT_TEX_SHIFT)
78#define ARM_MMU_SECT_AP_1 (1U << 11)
79#define ARM_MMU_SECT_AP_0 (1U << 10)
80#define ARM_MMU_SECT_AP_SHIFT 10
81#define ARM_MMU_SECT_AP_MASK (0x23U << ARM_MMU_SECT_AP_SHIFT)
82#define ARM_MMU_SECT_DOMAIN_SHIFT 5
83#define ARM_MMU_SECT_DOMAIN_MASK (0xfU << ARM_MMU_SECT_DOMAIN_SHIFT)
84#define ARM_MMU_SECT_XN (1U << 4)
85#define ARM_MMU_SECT_C (1U << 3)
86#define ARM_MMU_SECT_B (1U << 2)
87#define ARM_MMU_SECT_PXN (1U << 0)
88#define ARM_MMU_SECT_DEFAULT 0x2U
89#define ARM_MMU_SECT_GET_INDEX(mva) \
90  (((uint32_t) (mva)) >> ARM_MMU_SECT_BASE_SHIFT)
91#define ARM_MMU_SECT_MVA_ALIGN_UP(mva) \
92  ((1U << ARM_MMU_SECT_BASE_SHIFT) \
93    + ((((uint32_t) (mva) - 1U)) & ~((1U << ARM_MMU_SECT_BASE_SHIFT) - 1U)))
94
95#define ARM_MMU_TRANSLATION_TABLE_ENTRY_SIZE 4U
96#define ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT 4096U
97
98#define ARM_MMU_DEFAULT_CLIENT_DOMAIN 15U
99
100#define ARMV7_MMU_READ_ONLY \
101  ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
102    | ARM_MMU_SECT_AP_0 \
103    | ARM_MMU_SECT_AP_2 \
104    | ARM_MMU_SECT_DEFAULT)
105
106#define ARMV7_MMU_READ_ONLY_CACHED \
107  (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
108
109#define ARMV7_MMU_READ_WRITE \
110  ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
111    | ARM_MMU_SECT_AP_0 \
112    | ARM_MMU_SECT_DEFAULT)
113
114#ifdef RTEMS_SMP
115  #define ARMV7_MMU_READ_WRITE_CACHED \
116    (ARMV7_MMU_READ_WRITE \
117      | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B | ARM_MMU_SECT_S)
118#else
119  #define ARMV7_MMU_READ_WRITE_CACHED \
120    (ARMV7_MMU_READ_WRITE \
121      | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
122#endif
123
124#define ARMV7_MMU_DATA_READ_ONLY \
125  (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0)
126
127#define ARMV7_MMU_DATA_READ_ONLY_CACHED \
128  ARMV7_MMU_READ_ONLY_CACHED
129
130#define ARMV7_MMU_DATA_READ_WRITE \
131  (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_TEX_0)
132
133#define ARMV7_MMU_DATA_READ_WRITE_CACHED \
134  ARMV7_MMU_READ_WRITE_CACHED
135
136#define ARMV7_MMU_CODE \
137  (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0)
138
139#define ARMV7_MMU_CODE_CACHED \
140  ARMV7_MMU_READ_ONLY_CACHED
141
142#define ARMV7_MMU_DEVICE \
143  (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_B)
144
145/** @} */
146
147/**
148 * @name Control Register Defines
149 *
150 * @{
151 */
152
153#define ARM_CP15_CTRL_TE (1U << 30)
154#define ARM_CP15_CTRL_AFE (1U << 29)
155#define ARM_CP15_CTRL_TRE (1U << 28)
156#define ARM_CP15_CTRL_NMFI (1U << 27)
157#define ARM_CP15_CTRL_EE (1U << 25)
158#define ARM_CP15_CTRL_VE (1U << 24)
159#define ARM_CP15_CTRL_XP (1U << 23)
160#define ARM_CP15_CTRL_U (1U << 22)
161#define ARM_CP15_CTRL_FI (1U << 21)
162#define ARM_CP15_CTRL_UWXN (1U << 20)
163#define ARM_CP15_CTRL_WXN (1U << 19)
164#define ARM_CP15_CTRL_HA (1U << 17)
165#define ARM_CP15_CTRL_L4 (1U << 15)
166#define ARM_CP15_CTRL_RR (1U << 14)
167#define ARM_CP15_CTRL_V (1U << 13)
168#define ARM_CP15_CTRL_I (1U << 12)
169#define ARM_CP15_CTRL_Z (1U << 11)
170#define ARM_CP15_CTRL_SW (1U << 10)
171#define ARM_CP15_CTRL_R (1U << 9)
172#define ARM_CP15_CTRL_S (1U << 8)
173#define ARM_CP15_CTRL_B (1U << 7)
174#define ARM_CP15_CTRL_CP15BEN (1U << 5)
175#define ARM_CP15_CTRL_C (1U << 2)
176#define ARM_CP15_CTRL_A (1U << 1)
177#define ARM_CP15_CTRL_M (1U << 0)
178
179/** @} */
180
181/**
182 * @name Domain Access Control Defines
183 *
184 * @{
185 */
186
187#define ARM_CP15_DAC_NO_ACCESS 0x0U
188#define ARM_CP15_DAC_CLIENT 0x1U
189#define ARM_CP15_DAC_MANAGER 0x3U
190#define ARM_CP15_DAC_DOMAIN(index, val) ((val) << (2 * index))
191
192/** @} */
193
194/**
195 * @name Fault Status Register Defines
196 *
197 * @{
198 */
199
200#define ARM_CP15_FAULT_STATUS_MASK 0x040F
201
202#define ARM_CP15_FSR_ALIGNMENT_FAULT   0x00000001
203#define ARM_CP15_FSR_BACKGROUND_FAULT  0x0000
204#define ARM_CP15_FSR_ACCESS_PERMISSION_FAULT 0x000D
205#define ARM_CP15_FSR_PRECISE_EXTERNAL_ABORT_FAULT 0x0008
206#define ARM_CP15_FSR_IMPRECISE_EXTERNAL_ABORT_FAULT 0x0406
207#define ARM_CP15_FSR_PRECISE_PARITY_ERROR_EXCEPTION 0x0006
208#define ARM_CP15_FSR_IMPRECISE_PARITY_ERROR_EXCEPTION 0x0408
209#define ARM_CP15_FSR_DEBUG_EVENT 0x0002
210
211/** @} */
212
213/**
214 * @name CTR, Cache Type Register Defines
215 *
216 * The format can be obtained from CP15 by call
217 * arm_cp15_cache_type_get_format(arm_cp15_get_cache_type());
218 *
219 * @{
220 */
221
222#define ARM_CP15_CACHE_TYPE_FORMAT_ARMV6 0
223#define ARM_CP15_CACHE_TYPE_FORMAT_ARMV7 4
224
225/** @} */
226
227/**
228 * @name CCSIDR, Cache Size ID Register Defines
229 *
230 * @{
231 */
232
233#define ARM_CP15_CACHE_CSS_ID_DATA 0
234#define ARM_CP15_CACHE_CSS_ID_INSTRUCTION 1
235#define ARM_CP15_CACHE_CSS_LEVEL(level) ((level) << 1)
236
237/** @} */
238
239ARM_CP15_TEXT_SECTION static inline uint32_t
240arm_cp15_get_id_code(void)
241{
242  ARM_SWITCH_REGISTERS;
243  uint32_t val;
244
245  __asm__ volatile (
246    ARM_SWITCH_TO_ARM
247    "mrc p15, 0, %[val], c0, c0, 0\n"
248    ARM_SWITCH_BACK
249    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
250  );
251
252  return val;
253}
254
255ARM_CP15_TEXT_SECTION static inline uint32_t
256arm_cp15_get_tcm_status(void)
257{
258  ARM_SWITCH_REGISTERS;
259  uint32_t val;
260
261  __asm__ volatile (
262    ARM_SWITCH_TO_ARM
263    "mrc p15, 0, %[val], c0, c0, 2\n"
264    ARM_SWITCH_BACK
265    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
266  );
267
268  return val;
269}
270
271ARM_CP15_TEXT_SECTION static inline uint32_t
272arm_cp15_get_control(void)
273{
274  ARM_SWITCH_REGISTERS;
275  uint32_t val;
276
277  __asm__ volatile (
278    ARM_SWITCH_TO_ARM
279    "mrc p15, 0, %[val], c1, c0, 0\n"
280    ARM_SWITCH_BACK
281    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
282  );
283
284  return val;
285}
286
287ARM_CP15_TEXT_SECTION static inline void
288arm_cp15_set_control(uint32_t val)
289{
290  ARM_SWITCH_REGISTERS;
291
292  __asm__ volatile (
293    ARM_SWITCH_TO_ARM
294    "mcr p15, 0, %[val], c1, c0, 0\n"
295    "nop\n"
296    "nop\n"
297    ARM_SWITCH_BACK
298    : ARM_SWITCH_OUTPUT
299    : [val] "r" (val)
300    : "memory"
301  );
302}
303
304/**
305 * @name MMU Functions
306 *
307 * @{
308 */
309
310/**
311 * @brief Disable the MMU.
312 *
313 * This function will clean and invalidate eight cache lines before and after
314 * the current stack pointer.
315 *
316 * @param[in] cls The data cache line size.
317 *
318 * @return The current control register value.
319 */
320ARM_CP15_TEXT_SECTION static inline uint32_t
321arm_cp15_mmu_disable(uint32_t cls)
322{
323  ARM_SWITCH_REGISTERS;
324  uint32_t ctrl;
325  uint32_t tmp_0;
326  uint32_t tmp_1;
327
328  __asm__ volatile (
329    ARM_SWITCH_TO_ARM
330    "mrc p15, 0, %[ctrl], c1, c0, 0\n"
331    "bic %[tmp_0], %[ctrl], #1\n"
332    "mcr p15, 0, %[tmp_0], c1, c0, 0\n"
333    "nop\n"
334    "nop\n"
335    "mov %[tmp_1], sp\n"
336    "rsb %[tmp_0], %[cls], #0\n"
337    "and %[tmp_0], %[tmp_0], %[tmp_1]\n"
338    "sub %[tmp_0], %[tmp_0], %[cls], asl #3\n"
339    "add %[tmp_1], %[tmp_0], %[cls], asl #4\n"
340    "1:\n"
341    "mcr p15, 0, %[tmp_0], c7, c14, 1\n"
342    "add %[tmp_0], %[tmp_0], %[cls]\n"
343    "cmp %[tmp_1], %[tmp_0]\n"
344    "bne 1b\n"
345    ARM_SWITCH_BACK
346    : [ctrl] "=&r" (ctrl),
347      [tmp_0] "=&r" (tmp_0),
348      [tmp_1] "=&r" (tmp_1)
349      ARM_SWITCH_ADDITIONAL_OUTPUT
350    : [cls] "r" (cls)
351    : "memory", "cc"
352  );
353
354  return ctrl;
355}
356
357ARM_CP15_TEXT_SECTION static inline uint32_t
358*arm_cp15_get_translation_table_base(void)
359{
360  ARM_SWITCH_REGISTERS;
361  uint32_t *base;
362
363  __asm__ volatile (
364    ARM_SWITCH_TO_ARM
365    "mrc p15, 0, %[base], c2, c0, 0\n"
366    ARM_SWITCH_BACK
367    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
368  );
369
370  return base;
371}
372
373ARM_CP15_TEXT_SECTION static inline void
374arm_cp15_set_translation_table_base(uint32_t *base)
375{
376  ARM_SWITCH_REGISTERS;
377
378  __asm__ volatile (
379    ARM_SWITCH_TO_ARM
380    "mcr p15, 0, %[base], c2, c0, 0\n"
381    ARM_SWITCH_BACK
382    : ARM_SWITCH_OUTPUT
383    : [base] "r" (base)
384  );
385}
386
387/* Translation Table Base Control Register - DDI0301H arm1176jzfs TRM 3.2.15 */
388ARM_CP15_TEXT_SECTION static inline uint32_t
389arm_cp15_get_translation_table_base_control_register(void)
390{
391  ARM_SWITCH_REGISTERS;
392  uint32_t ttb_cr;
393
394  __asm__ volatile (
395    ARM_SWITCH_TO_ARM
396    "mrc p15, 0, %[ttb_cr], c2, c0, 2\n"
397    ARM_SWITCH_BACK
398    : [ttb_cr] "=&r" (ttb_cr) ARM_SWITCH_ADDITIONAL_OUTPUT
399  );
400
401  return ttb_cr;
402}
403
404ARM_CP15_TEXT_SECTION static inline void
405arm_cp15_set_translation_table_base_control_register(uint32_t ttb_cr)
406{
407  ARM_SWITCH_REGISTERS;
408
409  __asm__ volatile (
410    ARM_SWITCH_TO_ARM
411    "mcr p15, 0, %[ttb_cr], c2, c0, 2\n"
412    ARM_SWITCH_BACK
413    : ARM_SWITCH_OUTPUT
414    : [ttb_cr] "r" (ttb_cr)
415  );
416}
417
418ARM_CP15_TEXT_SECTION static inline uint32_t
419arm_cp15_get_domain_access_control(void)
420{
421  ARM_SWITCH_REGISTERS;
422  uint32_t val;
423
424  __asm__ volatile (
425    ARM_SWITCH_TO_ARM
426    "mrc p15, 0, %[val], c3, c0, 0\n"
427    ARM_SWITCH_BACK
428    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
429  );
430
431  return val;
432}
433
434ARM_CP15_TEXT_SECTION static inline void
435arm_cp15_set_domain_access_control(uint32_t val)
436{
437  ARM_SWITCH_REGISTERS;
438
439  __asm__ volatile (
440    ARM_SWITCH_TO_ARM
441    "mcr p15, 0, %[val], c3, c0, 0\n"
442    ARM_SWITCH_BACK
443    : ARM_SWITCH_OUTPUT
444    : [val] "r" (val)
445  );
446}
447
448ARM_CP15_TEXT_SECTION static inline uint32_t
449arm_cp15_get_data_fault_status(void)
450{
451  ARM_SWITCH_REGISTERS;
452  uint32_t val;
453
454  __asm__ volatile (
455    ARM_SWITCH_TO_ARM
456    "mrc p15, 0, %[val], c5, c0, 0\n"
457    ARM_SWITCH_BACK
458    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
459  );
460
461  return val;
462}
463
464ARM_CP15_TEXT_SECTION static inline void
465arm_cp15_set_data_fault_status(uint32_t val)
466{
467  ARM_SWITCH_REGISTERS;
468
469  __asm__ volatile (
470    ARM_SWITCH_TO_ARM
471    "mcr p15, 0, %[val], c5, c0, 0\n"
472    ARM_SWITCH_BACK
473    : ARM_SWITCH_OUTPUT
474    : [val] "r" (val)
475  );
476}
477
478ARM_CP15_TEXT_SECTION static inline uint32_t
479arm_cp15_get_instruction_fault_status(void)
480{
481  ARM_SWITCH_REGISTERS;
482  uint32_t val;
483
484  __asm__ volatile (
485    ARM_SWITCH_TO_ARM
486    "mrc p15, 0, %[val], c5, c0, 1\n"
487    ARM_SWITCH_BACK
488    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
489  );
490
491  return val;
492}
493
494ARM_CP15_TEXT_SECTION static inline void
495arm_cp15_set_instruction_fault_status(uint32_t val)
496{
497  ARM_SWITCH_REGISTERS;
498
499  __asm__ volatile (
500    ARM_SWITCH_TO_ARM
501    "mcr p15, 0, %[val], c5, c0, 1\n"
502    ARM_SWITCH_BACK
503    : ARM_SWITCH_OUTPUT
504    : [val] "r" (val)
505  );
506}
507
508ARM_CP15_TEXT_SECTION static inline void
509*arm_cp15_get_fault_address(void)
510{
511  ARM_SWITCH_REGISTERS;
512  void *mva;
513
514  __asm__ volatile (
515    ARM_SWITCH_TO_ARM
516    "mrc p15, 0, %[mva], c6, c0, 0\n"
517    ARM_SWITCH_BACK
518    : [mva] "=&r" (mva) ARM_SWITCH_ADDITIONAL_OUTPUT
519  );
520
521  return mva;
522}
523
524ARM_CP15_TEXT_SECTION static inline void
525arm_cp15_set_fault_address(const void *mva)
526{
527  ARM_SWITCH_REGISTERS;
528
529  __asm__ volatile (
530    ARM_SWITCH_TO_ARM
531    "mcr p15, 0, %[mva], c6, c0, 0\n"
532    ARM_SWITCH_BACK
533    : ARM_SWITCH_OUTPUT
534    : [mva] "r" (mva)
535  );
536}
537
538ARM_CP15_TEXT_SECTION static inline void
539arm_cp15_tlb_invalidate(void)
540{
541  ARM_SWITCH_REGISTERS;
542  uint32_t sbz = 0;
543
544  __asm__ volatile (
545    ARM_SWITCH_TO_ARM
546    "mcr p15, 0, %[sbz], c8, c7, 0\n"
547    ARM_SWITCH_BACK
548    : ARM_SWITCH_OUTPUT
549    : [sbz] "r" (sbz)
550  );
551
552  /*
553   * ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, Issue C,
554   * B3.10.1 General TLB maintenance requirements.
555   */
556  _ARM_Data_synchronization_barrier();
557  _ARM_Instruction_synchronization_barrier();
558}
559
560ARM_CP15_TEXT_SECTION static inline void
561arm_cp15_tlb_invalidate_entry(const void *mva)
562{
563  ARM_SWITCH_REGISTERS;
564
565  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
566
567  __asm__ volatile (
568    ARM_SWITCH_TO_ARM
569    "mcr p15, 0, %[mva], c8, c7, 1\n"
570    ARM_SWITCH_BACK
571    : ARM_SWITCH_OUTPUT
572    : [mva] "r" (mva)
573  );
574}
575
576ARM_CP15_TEXT_SECTION static inline void
577arm_cp15_tlb_invalidate_entry_all_asids(const void *mva)
578{
579  ARM_SWITCH_REGISTERS;
580
581  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
582
583  __asm__ volatile (
584    ARM_SWITCH_TO_ARM
585    "mcr p15, 0, %[mva], c8, c7, 3\n"
586    ARM_SWITCH_BACK
587    : ARM_SWITCH_OUTPUT
588    : [mva] "r" (mva)
589  );
590}
591
592ARM_CP15_TEXT_SECTION static inline void
593arm_cp15_tlb_instruction_invalidate(void)
594{
595  ARM_SWITCH_REGISTERS;
596  uint32_t sbz = 0;
597
598  __asm__ volatile (
599    ARM_SWITCH_TO_ARM
600    "mcr p15, 0, %[sbz], c8, c5, 0\n"
601    ARM_SWITCH_BACK
602    : ARM_SWITCH_OUTPUT
603    : [sbz] "r" (sbz)
604  );
605}
606
607ARM_CP15_TEXT_SECTION static inline void
608arm_cp15_tlb_instruction_invalidate_entry(const void *mva)
609{
610  ARM_SWITCH_REGISTERS;
611
612  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
613
614  __asm__ volatile (
615    ARM_SWITCH_TO_ARM
616    "mcr p15, 0, %[mva], c8, c5, 1\n"
617    ARM_SWITCH_BACK
618    : ARM_SWITCH_OUTPUT
619    : [mva] "r" (mva)
620  );
621}
622
623ARM_CP15_TEXT_SECTION static inline void
624arm_cp15_tlb_data_invalidate(void)
625{
626  ARM_SWITCH_REGISTERS;
627  uint32_t sbz = 0;
628
629  __asm__ volatile (
630    ARM_SWITCH_TO_ARM
631    "mcr p15, 0, %[sbz], c8, c6, 0\n"
632    ARM_SWITCH_BACK
633    : ARM_SWITCH_OUTPUT
634    : [sbz] "r" (sbz)
635  );
636}
637
638ARM_CP15_TEXT_SECTION static inline void
639arm_cp15_tlb_data_invalidate_entry(const void *mva)
640{
641  ARM_SWITCH_REGISTERS;
642
643  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
644
645  __asm__ volatile (
646    ARM_SWITCH_TO_ARM
647    "mcr p15, 0, %[mva], c8, c6, 1\n"
648    ARM_SWITCH_BACK
649    : ARM_SWITCH_OUTPUT
650    : [mva] "r" (mva)
651  );
652}
653
654ARM_CP15_TEXT_SECTION static inline void
655arm_cp15_tlb_lockdown_entry(const void *mva)
656{
657  uint32_t arm_switch_reg;
658
659  __asm__ volatile (
660    ARM_SWITCH_TO_ARM
661    "add %[arm_switch_reg], pc, #16\n"
662    "mcr p15, 0, %[arm_switch_reg], c7, c13, 1\n"
663    "mcr p15, 0, %[mva], c8, c7, 1\n"
664    "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
665    "orr %[arm_switch_reg], #0x1\n"
666    "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
667    "ldr %[mva], [%[mva]]\n"
668    "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
669    "bic %[arm_switch_reg], #0x1\n"
670    "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
671    ARM_SWITCH_BACK
672    : [mva] "=r" (mva), [arm_switch_reg] "=&r" (arm_switch_reg)
673    : "[mva]" (mva)
674  );
675}
676
677/** @} */
678
679/**
680 * @name Cache Functions
681 *
682 * @{
683 */
684
685/* Read cache type register CTR */
686ARM_CP15_TEXT_SECTION static inline uint32_t
687arm_cp15_get_cache_type(void)
688{
689  ARM_SWITCH_REGISTERS;
690  uint32_t val;
691
692  __asm__ volatile (
693    ARM_SWITCH_TO_ARM
694    "mrc p15, 0, %[val], c0, c0, 1\n"
695    ARM_SWITCH_BACK
696    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
697  );
698
699  return val;
700}
701
702/* Extract format version from cache type CTR */
703ARM_CP15_TEXT_SECTION static inline int
704arm_cp15_cache_type_get_format(uint32_t ct)
705{
706  return (ct >> 29) & 0x7U;
707}
708
709/* Read size of smallest cache line of all instruction/data caches controlled by the processor */
710ARM_CP15_TEXT_SECTION static inline uint32_t
711arm_cp15_get_min_cache_line_size(void)
712{
713  uint32_t mcls = 0;
714  uint32_t ct = arm_cp15_get_cache_type();
715  uint32_t format = arm_cp15_cache_type_get_format(ct);
716
717  if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
718    /* ARMv7 format */
719    mcls = (1U << (ct & 0xf)) * 4;
720  } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
721    /* ARMv6 format */
722    uint32_t mask = (1U << 12) - 1;
723    uint32_t dcls = (ct >> 12) & mask;
724    uint32_t icls = ct & mask;
725
726    mcls = dcls <= icls ? dcls : icls;
727  }
728
729  return mcls;
730}
731
732/* Read size of smallest data cache lines */
733ARM_CP15_TEXT_SECTION static inline uint32_t
734arm_cp15_get_data_cache_line_size(void)
735{
736  uint32_t mcls = 0;
737  uint32_t ct = arm_cp15_get_cache_type();
738  uint32_t format = arm_cp15_cache_type_get_format(ct);
739
740  if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
741    /* ARMv7 format */
742    mcls = (1U << ((ct & 0xf0000) >> 16)) * 4;
743  } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
744    /* ARMv6 format */
745    uint32_t mask = (1U << 12) - 1;
746    mcls = (ct >> 12) & mask;
747  }
748
749  return mcls;
750}
751
752/* Read size of smallest instruction cache lines */
753ARM_CP15_TEXT_SECTION static inline uint32_t
754arm_cp15_get_instruction_cache_line_size(void)
755{
756  uint32_t mcls = 0;
757  uint32_t ct = arm_cp15_get_cache_type();
758  uint32_t format = arm_cp15_cache_type_get_format(ct);
759
760  if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
761    /* ARMv7 format */
762    mcls = (1U << (ct & 0x0000f)) * 4;
763  } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
764    /* ARMv6 format */
765    uint32_t mask = (1U << 12) - 1;
766    mcls = ct & mask;;
767  }
768
769  return mcls;
770}
771
772/* CCSIDR, Cache Size ID Register */
773
774ARM_CP15_TEXT_SECTION static inline uint32_t
775arm_cp15_get_cache_size_id(void)
776{
777  ARM_SWITCH_REGISTERS;
778  uint32_t val;
779
780  __asm__ volatile (
781    ARM_SWITCH_TO_ARM
782    "mrc p15, 1, %[val], c0, c0, 0\n"
783     ARM_SWITCH_BACK
784    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
785  );
786
787  return val;
788}
789
790ARM_CP15_TEXT_SECTION static inline uint32_t
791arm_ccsidr_get_line_power(uint32_t ccsidr)
792{
793  return (ccsidr & 0x7) + 4;
794}
795
796ARM_CP15_TEXT_SECTION static inline uint32_t
797arm_ccsidr_get_associativity(uint32_t ccsidr)
798{
799  return ((ccsidr >> 3) & 0x3ff) + 1;
800}
801
802ARM_CP15_TEXT_SECTION static inline uint32_t
803arm_ccsidr_get_num_sets(uint32_t ccsidr)
804{
805  return ((ccsidr >> 13) & 0x7fff) + 1;
806}
807
808/* CLIDR, Cache Level ID Register */
809
810ARM_CP15_TEXT_SECTION static inline uint32_t
811arm_cp15_get_cache_level_id(void)
812{
813  ARM_SWITCH_REGISTERS;
814  uint32_t val;
815
816  __asm__ volatile (
817    ARM_SWITCH_TO_ARM
818    "mrc p15, 1, %[val], c0, c0, 1\n"
819     ARM_SWITCH_BACK
820    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
821  );
822
823  return val;
824}
825
826ARM_CP15_TEXT_SECTION static inline uint32_t
827arm_clidr_get_level_of_coherency(uint32_t clidr)
828{
829  return (clidr >> 24) & 0x7;
830}
831
832ARM_CP15_TEXT_SECTION static inline uint32_t
833arm_clidr_get_cache_type(uint32_t clidr, uint32_t level)
834{
835  return (clidr >> (3 * level)) & 0x7;
836}
837
838/* CSSELR, Cache Size Selection Register */
839
840ARM_CP15_TEXT_SECTION static inline uint32_t
841arm_cp15_get_cache_size_selection(void)
842{
843  ARM_SWITCH_REGISTERS;
844  uint32_t val;
845
846  __asm__ volatile (
847    ARM_SWITCH_TO_ARM
848    "mrc p15, 2, %[val], c0, c0, 0\n"
849     ARM_SWITCH_BACK
850    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
851  );
852
853  return val;
854}
855
856ARM_CP15_TEXT_SECTION static inline void
857arm_cp15_set_cache_size_selection(uint32_t val)
858{
859  ARM_SWITCH_REGISTERS;
860
861  __asm__ volatile (
862    ARM_SWITCH_TO_ARM
863    "mcr p15, 2, %[val], c0, c0, 0\n"
864     ARM_SWITCH_BACK
865    : ARM_SWITCH_OUTPUT
866    : [val] "r" (val)
867    : "memory"
868  );
869}
870
871ARM_CP15_TEXT_SECTION static inline uint32_t
872arm_cp15_get_cache_size_id_for_level(uint32_t level_and_inst_dat)
873{
874  rtems_interrupt_level irq_level;
875  uint32_t ccsidr;
876
877  rtems_interrupt_local_disable(irq_level);
878  arm_cp15_set_cache_size_selection(level_and_inst_dat);
879  _ARM_Instruction_synchronization_barrier();
880  ccsidr = arm_cp15_get_cache_size_id();
881  rtems_interrupt_local_enable(irq_level);
882
883  return ccsidr;
884}
885
886ARM_CP15_TEXT_SECTION static inline void
887arm_cp15_cache_invalidate(void)
888{
889  ARM_SWITCH_REGISTERS;
890  uint32_t sbz = 0;
891
892  __asm__ volatile (
893    ARM_SWITCH_TO_ARM
894    "mcr p15, 0, %[sbz], c7, c7, 0\n"
895    ARM_SWITCH_BACK
896    : ARM_SWITCH_OUTPUT
897    : [sbz] "r" (sbz)
898    : "memory"
899  );
900}
901
902/* ICIALLUIS, Instruction Cache Invalidate All to PoU, Inner Shareable */
903
904ARM_CP15_TEXT_SECTION static inline void
905arm_cp15_instruction_cache_inner_shareable_invalidate_all(void)
906{
907  ARM_SWITCH_REGISTERS;
908  uint32_t sbz = 0;
909
910  __asm__ volatile (
911    ARM_SWITCH_TO_ARM
912    "mcr p15, 0, %[sbz], c7, c1, 0\n"
913    ARM_SWITCH_BACK
914    : ARM_SWITCH_OUTPUT
915    : [sbz] "r" (sbz)
916    : "memory"
917  );
918}
919
920/* BPIALLIS, Branch Predictor Invalidate All, Inner Shareable */
921
922ARM_CP15_TEXT_SECTION static inline void
923arm_cp15_branch_predictor_inner_shareable_invalidate_all(void)
924{
925  ARM_SWITCH_REGISTERS;
926  uint32_t sbz = 0;
927
928  __asm__ volatile (
929    ARM_SWITCH_TO_ARM
930    "mcr p15, 0, %[sbz], c7, c1, 6\n"
931    ARM_SWITCH_BACK
932    : ARM_SWITCH_OUTPUT
933    : [sbz] "r" (sbz)
934    : "memory"
935  );
936}
937
938/* BPIALL, Branch Predictor Invalidate All */
939
940ARM_CP15_TEXT_SECTION static inline void
941arm_cp15_branch_predictor_invalidate_all(void)
942{
943  ARM_SWITCH_REGISTERS;
944  uint32_t sbz = 0;
945
946  __asm__ volatile (
947    ARM_SWITCH_TO_ARM
948    "mcr p15, 0, %[sbz], c7, c5, 6\n"
949    ARM_SWITCH_BACK
950    : ARM_SWITCH_OUTPUT
951    : [sbz] "r" (sbz)
952    : "memory"
953  );
954}
955
956/* Flush Prefetch Buffer - DDI0301H arm1176jzfs TRM 3.2.22 */
957ARM_CP15_TEXT_SECTION static inline void
958arm_cp15_flush_prefetch_buffer(void)
959{
960  ARM_SWITCH_REGISTERS;
961  uint32_t sbz = 0;
962
963  __asm__ volatile (
964    ARM_SWITCH_TO_ARM
965    "mcr p15, 0, %[sbz], c7, c5, 4\n"
966    ARM_SWITCH_BACK
967    : ARM_SWITCH_OUTPUT
968    : [sbz] "r" (sbz)
969    : "memory"
970  );
971}
972
973ARM_CP15_TEXT_SECTION static inline void
974arm_cp15_instruction_cache_invalidate(void)
975{
976  ARM_SWITCH_REGISTERS;
977  uint32_t sbz = 0;
978
979  __asm__ volatile (
980    ARM_SWITCH_TO_ARM
981    "mcr p15, 0, %[sbz], c7, c5, 0\n"
982    ARM_SWITCH_BACK
983    : ARM_SWITCH_OUTPUT
984    : [sbz] "r" (sbz)
985    : "memory"
986  );
987}
988
989ARM_CP15_TEXT_SECTION static inline void
990arm_cp15_instruction_cache_invalidate_line(const void *mva)
991{
992  ARM_SWITCH_REGISTERS;
993
994  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
995
996  __asm__ volatile (
997    ARM_SWITCH_TO_ARM
998    "mcr p15, 0, %[mva], c7, c5, 1\n"
999    ARM_SWITCH_BACK
1000    : ARM_SWITCH_OUTPUT
1001    : [mva] "r" (mva)
1002    : "memory"
1003  );
1004}
1005
1006ARM_CP15_TEXT_SECTION static inline void
1007arm_cp15_instruction_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
1008{
1009  ARM_SWITCH_REGISTERS;
1010
1011  __asm__ volatile (
1012    ARM_SWITCH_TO_ARM
1013    "mcr p15, 0, %[set_and_way], c7, c5, 2\n"
1014    ARM_SWITCH_BACK
1015    : ARM_SWITCH_OUTPUT
1016    : [set_and_way] "r" (set_and_way)
1017    : "memory"
1018  );
1019}
1020
1021ARM_CP15_TEXT_SECTION static inline void
1022arm_cp15_instruction_cache_prefetch_line(const void *mva)
1023{
1024  ARM_SWITCH_REGISTERS;
1025
1026  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1027
1028  __asm__ volatile (
1029    ARM_SWITCH_TO_ARM
1030    "mcr p15, 0, %[mva], c7, c13, 1\n"
1031    ARM_SWITCH_BACK
1032    : ARM_SWITCH_OUTPUT
1033    : [mva] "r" (mva)
1034  );
1035}
1036
1037ARM_CP15_TEXT_SECTION static inline void
1038arm_cp15_data_cache_invalidate(void)
1039{
1040  ARM_SWITCH_REGISTERS;
1041  uint32_t sbz = 0;
1042
1043  __asm__ volatile (
1044    ARM_SWITCH_TO_ARM
1045    "mcr p15, 0, %[sbz], c7, c6, 0\n"
1046    ARM_SWITCH_BACK
1047    : ARM_SWITCH_OUTPUT
1048    : [sbz] "r" (sbz)
1049    : "memory"
1050  );
1051}
1052
1053ARM_CP15_TEXT_SECTION static inline void
1054arm_cp15_data_cache_invalidate_line(const void *mva)
1055{
1056  ARM_SWITCH_REGISTERS;
1057
1058  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1059
1060  __asm__ volatile (
1061    ARM_SWITCH_TO_ARM
1062    "mcr p15, 0, %[mva], c7, c6, 1\n"
1063    ARM_SWITCH_BACK
1064    : ARM_SWITCH_OUTPUT
1065    : [mva] "r" (mva)
1066    : "memory"
1067  );
1068}
1069
1070ARM_CP15_TEXT_SECTION static inline void
1071arm_cp15_data_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
1072{
1073  ARM_SWITCH_REGISTERS;
1074
1075  __asm__ volatile (
1076    ARM_SWITCH_TO_ARM
1077    "mcr p15, 0, %[set_and_way], c7, c6, 2\n"
1078    ARM_SWITCH_BACK
1079    : ARM_SWITCH_OUTPUT
1080    : [set_and_way] "r" (set_and_way)
1081    : "memory"
1082  );
1083}
1084
1085ARM_CP15_TEXT_SECTION static inline void
1086arm_cp15_cache_invalidate_level(uint32_t level, uint32_t inst_data_fl)
1087{
1088  uint32_t ccsidr;
1089  uint32_t line_power;
1090  uint32_t associativity;
1091  uint32_t way;
1092  uint32_t way_shift;
1093
1094  ccsidr = arm_cp15_get_cache_size_id_for_level((level << 1) | inst_data_fl);
1095
1096  line_power = arm_ccsidr_get_line_power(ccsidr);
1097  associativity = arm_ccsidr_get_associativity(ccsidr);
1098  way_shift = __builtin_clz(associativity - 1);
1099
1100  for (way = 0; way < associativity; ++way) {
1101    uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
1102    uint32_t set;
1103
1104    for (set = 0; set < num_sets; ++set) {
1105      uint32_t set_way = (way << way_shift)
1106        | (set << line_power)
1107        | (level << 1);
1108
1109      arm_cp15_data_cache_invalidate_line_by_set_and_way(set_way);
1110    }
1111  }
1112}
1113
1114ARM_CP15_TEXT_SECTION static inline void
1115arm_cp15_data_cache_invalidate_all_levels(void)
1116{
1117  uint32_t clidr = arm_cp15_get_cache_level_id();
1118  uint32_t loc = arm_clidr_get_level_of_coherency(clidr);
1119  uint32_t level = 0;
1120
1121  for (level = 0; level < loc; ++level) {
1122    uint32_t ctype = arm_clidr_get_cache_type(clidr, level);
1123
1124    /* Check if this level has a data cache or unified cache */
1125    if (((ctype & (0x6)) == 2) || (ctype == 4)) {
1126      arm_cp15_cache_invalidate_level(level, 0);
1127    }
1128  }
1129}
1130
1131ARM_CP15_TEXT_SECTION static inline void
1132arm_cp15_data_cache_clean_line(const void *mva)
1133{
1134  ARM_SWITCH_REGISTERS;
1135
1136  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1137
1138  __asm__ volatile (
1139    ARM_SWITCH_TO_ARM
1140    "mcr p15, 0, %[mva], c7, c10, 1\n"
1141    ARM_SWITCH_BACK
1142    : ARM_SWITCH_OUTPUT
1143    : [mva] "r" (mva)
1144    : "memory"
1145  );
1146}
1147
1148ARM_CP15_TEXT_SECTION static inline void
1149arm_cp15_data_cache_clean_line_by_set_and_way(uint32_t set_and_way)
1150{
1151  ARM_SWITCH_REGISTERS;
1152
1153  __asm__ volatile (
1154    ARM_SWITCH_TO_ARM
1155    "mcr p15, 0, %[set_and_way], c7, c10, 2\n"
1156    ARM_SWITCH_BACK
1157    : ARM_SWITCH_OUTPUT
1158    : [set_and_way] "r" (set_and_way)
1159    : "memory"
1160  );
1161}
1162
1163ARM_CP15_TEXT_SECTION static inline void
1164arm_cp15_data_cache_clean_level(uint32_t level)
1165{
1166  uint32_t ccsidr;
1167  uint32_t line_power;
1168  uint32_t associativity;
1169  uint32_t way;
1170  uint32_t way_shift;
1171
1172  ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
1173
1174  line_power = arm_ccsidr_get_line_power(ccsidr);
1175  associativity = arm_ccsidr_get_associativity(ccsidr);
1176  way_shift = __builtin_clz(associativity - 1);
1177
1178  for (way = 0; way < associativity; ++way) {
1179    uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
1180    uint32_t set;
1181
1182    for (set = 0; set < num_sets; ++set) {
1183      uint32_t set_way = (way << way_shift)
1184        | (set << line_power)
1185        | (level << 1);
1186
1187      arm_cp15_data_cache_clean_line_by_set_and_way(set_way);
1188    }
1189  }
1190}
1191
1192ARM_CP15_TEXT_SECTION static inline void
1193arm_cp15_data_cache_clean_all_levels(void)
1194{
1195  uint32_t clidr = arm_cp15_get_cache_level_id();
1196  uint32_t loc = arm_clidr_get_level_of_coherency(clidr);
1197  uint32_t level = 0;
1198
1199  for (level = 0; level < loc; ++level) {
1200    uint32_t ctype = arm_clidr_get_cache_type(clidr, level);
1201
1202    /* Check if this level has a data cache or unified cache */
1203    if (((ctype & (0x6)) == 2) || (ctype == 4)) {
1204      arm_cp15_data_cache_clean_level(level);
1205    }
1206  }
1207}
1208
1209ARM_CP15_TEXT_SECTION static inline void
1210arm_cp15_data_cache_test_and_clean(void)
1211{
1212  ARM_SWITCH_REGISTERS;
1213
1214  __asm__ volatile (
1215    ARM_SWITCH_TO_ARM
1216    "1:\n"
1217    "mrc p15, 0, r15, c7, c10, 3\n"
1218    "bne 1b\n"
1219    ARM_SWITCH_BACK
1220    : ARM_SWITCH_OUTPUT
1221    :
1222    : "memory"
1223  );
1224}
1225
1226/*      In DDI0301H_arm1176jzfs_r0p7_trm
1227 *      'MCR p15, 0, <Rd>, c7, c14, 0' means
1228 *      Clean and Invalidate Entire Data Cache
1229 */
1230ARM_CP15_TEXT_SECTION static inline void
1231arm_cp15_data_cache_clean_and_invalidate(void)
1232{
1233  ARM_SWITCH_REGISTERS;
1234
1235  uint32_t sbz = 0;
1236
1237  __asm__ volatile (
1238    ARM_SWITCH_TO_ARM
1239    "mcr p15, 0, %[sbz], c7, c14, 0\n"
1240    ARM_SWITCH_BACK
1241    : ARM_SWITCH_OUTPUT
1242    : [sbz] "r" (sbz)
1243    : "memory"
1244  );
1245}
1246
1247ARM_CP15_TEXT_SECTION static inline void
1248arm_cp15_data_cache_clean_and_invalidate_line(const void *mva)
1249{
1250  ARM_SWITCH_REGISTERS;
1251
1252  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1253
1254  __asm__ volatile (
1255    ARM_SWITCH_TO_ARM
1256    "mcr p15, 0, %[mva], c7, c14, 1\n"
1257    ARM_SWITCH_BACK
1258    : ARM_SWITCH_OUTPUT
1259    : [mva] "r" (mva)
1260    : "memory"
1261  );
1262}
1263
1264ARM_CP15_TEXT_SECTION static inline void
1265arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(uint32_t set_and_way)
1266{
1267  ARM_SWITCH_REGISTERS;
1268
1269  __asm__ volatile (
1270    ARM_SWITCH_TO_ARM
1271    "mcr p15, 0, %[set_and_way], c7, c14, 2\n"
1272    ARM_SWITCH_BACK
1273    : ARM_SWITCH_OUTPUT
1274    : [set_and_way] "r" (set_and_way)
1275    : "memory"
1276  );
1277}
1278
1279ARM_CP15_TEXT_SECTION static inline void
1280arm_cp15_data_cache_test_and_clean_and_invalidate(void)
1281{
1282  ARM_SWITCH_REGISTERS;
1283
1284  __asm__ volatile (
1285    ARM_SWITCH_TO_ARM
1286    "1:\n"
1287    "mrc p15, 0, r15, c7, c14, 3\n"
1288    "bne 1b\n"
1289    ARM_SWITCH_BACK
1290    : ARM_SWITCH_OUTPUT
1291    :
1292    : "memory"
1293  );
1294}
1295
1296/** @} */
1297
1298ARM_CP15_TEXT_SECTION static inline void
1299arm_cp15_drain_write_buffer(void)
1300{
1301  ARM_SWITCH_REGISTERS;
1302  uint32_t sbz = 0;
1303
1304  __asm__ volatile (
1305    ARM_SWITCH_TO_ARM
1306    "mcr p15, 0, %[sbz], c7, c10, 4\n"
1307    ARM_SWITCH_BACK
1308    : ARM_SWITCH_OUTPUT
1309    : [sbz] "r" (sbz)
1310    : "memory"
1311  );
1312}
1313
1314ARM_CP15_TEXT_SECTION static inline void
1315arm_cp15_wait_for_interrupt(void)
1316{
1317  ARM_SWITCH_REGISTERS;
1318  uint32_t sbz = 0;
1319
1320  __asm__ volatile (
1321    ARM_SWITCH_TO_ARM
1322    "mcr p15, 0, %[sbz], c7, c0, 4\n"
1323    ARM_SWITCH_BACK
1324    : ARM_SWITCH_OUTPUT
1325    : [sbz] "r" (sbz)
1326    : "memory"
1327  );
1328}
1329
1330ARM_CP15_TEXT_SECTION static inline uint32_t
1331arm_cp15_get_multiprocessor_affinity(void)
1332{
1333  ARM_SWITCH_REGISTERS;
1334  uint32_t mpidr;
1335
1336  __asm__ volatile (
1337    ARM_SWITCH_TO_ARM
1338          "mrc p15, 0, %[mpidr], c0, c0, 5\n"
1339    ARM_SWITCH_BACK
1340    : [mpidr] "=&r" (mpidr) ARM_SWITCH_ADDITIONAL_OUTPUT
1341  );
1342
1343  return mpidr & 0xff;
1344}
1345
1346ARM_CP15_TEXT_SECTION static inline uint32_t
1347arm_cortex_a9_get_multiprocessor_cpu_id(void)
1348{
1349  return arm_cp15_get_multiprocessor_affinity() & 0xff;
1350}
1351
1352#define ARM_CORTEX_A9_ACTL_FW (1U << 0)
1353#define ARM_CORTEX_A9_ACTL_L2_PREFETCH_HINT_ENABLE (1U << 1)
1354#define ARM_CORTEX_A9_ACTL_L1_PREFETCH_ENABLE (1U << 2)
1355#define ARM_CORTEX_A9_ACTL_WRITE_FULL_LINE_OF_ZEROS_MODE (1U << 3)
1356#define ARM_CORTEX_A9_ACTL_SMP (1U << 6)
1357#define ARM_CORTEX_A9_ACTL_EXCL (1U << 7)
1358#define ARM_CORTEX_A9_ACTL_ALLOC_IN_ONE_WAY (1U << 8)
1359#define ARM_CORTEX_A9_ACTL_PARITY_ON (1U << 9)
1360
1361ARM_CP15_TEXT_SECTION static inline uint32_t
1362arm_cp15_get_auxiliary_control(void)
1363{
1364  ARM_SWITCH_REGISTERS;
1365  uint32_t val;
1366
1367  __asm__ volatile (
1368    ARM_SWITCH_TO_ARM
1369    "mrc p15, 0, %[val], c1, c0, 1\n"
1370    ARM_SWITCH_BACK
1371    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1372  );
1373
1374  return val;
1375}
1376
1377ARM_CP15_TEXT_SECTION static inline void
1378arm_cp15_set_auxiliary_control(uint32_t val)
1379{
1380  ARM_SWITCH_REGISTERS;
1381
1382  __asm__ volatile (
1383    ARM_SWITCH_TO_ARM
1384    "mcr p15, 0, %[val], c1, c0, 1\n"
1385    ARM_SWITCH_BACK
1386    : ARM_SWITCH_OUTPUT
1387    : [val] "r" (val)
1388  );
1389}
1390
1391/* ID_PFR1, Processor Feature Register 1 */
1392
1393ARM_CP15_TEXT_SECTION static inline uint32_t
1394arm_cp15_get_processor_feature_1(void)
1395{
1396  ARM_SWITCH_REGISTERS;
1397  uint32_t val;
1398
1399  __asm__ volatile (
1400    ARM_SWITCH_TO_ARM
1401    "mrc p15, 0, %[val], c0, c1, 1\n"
1402    ARM_SWITCH_BACK
1403    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1404  );
1405
1406  return val;
1407}
1408
1409/* VBAR, Vector Base Address Register, Security Extensions */
1410
1411ARM_CP15_TEXT_SECTION static inline void
1412*arm_cp15_get_vector_base_address(void)
1413{
1414  ARM_SWITCH_REGISTERS;
1415  void *base;
1416
1417  __asm__ volatile (
1418    ARM_SWITCH_TO_ARM
1419    "mrc p15, 0, %[base], c12, c0, 0\n"
1420    ARM_SWITCH_BACK
1421    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1422  );
1423
1424  return base;
1425}
1426
1427ARM_CP15_TEXT_SECTION static inline void
1428arm_cp15_set_vector_base_address(void *base)
1429{
1430  ARM_SWITCH_REGISTERS;
1431
1432  __asm__ volatile (
1433    ARM_SWITCH_TO_ARM
1434    "mcr p15, 0, %[base], c12, c0, 0\n"
1435    ARM_SWITCH_BACK
1436    : ARM_SWITCH_OUTPUT
1437    : [base] "r" (base)
1438  );
1439}
1440
1441ARM_CP15_TEXT_SECTION static inline void
1442*arm_cp15_get_hyp_vector_base_address(void)
1443{
1444  ARM_SWITCH_REGISTERS;
1445  void *base;
1446
1447  __asm__ volatile (
1448    ARM_SWITCH_TO_ARM
1449    "mrc p15, 4, %[base], c12, c0, 0\n"
1450    ARM_SWITCH_BACK
1451    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1452  );
1453
1454  return base;
1455}
1456
1457ARM_CP15_TEXT_SECTION static inline void
1458arm_cp15_set_hyp_vector_base_address(void *base)
1459{
1460  ARM_SWITCH_REGISTERS;
1461
1462  __asm__ volatile (
1463    ARM_SWITCH_TO_ARM
1464    "mcr p15, 4, %[base], c12, c0, 0\n"
1465    ARM_SWITCH_BACK
1466    : ARM_SWITCH_OUTPUT
1467    : [base] "r" (base)
1468  );
1469}
1470
1471/* PMCCNTR */
1472ARM_CP15_TEXT_SECTION static inline uint32_t
1473arm_cp15_get_performance_monitors_cycle_count(void)
1474{
1475  ARM_SWITCH_REGISTERS;
1476  uint32_t val;
1477
1478  __asm__ volatile (
1479    ARM_SWITCH_TO_ARM
1480    "mrc p15, 0, %[val], c9, c13, 0\n"
1481    ARM_SWITCH_BACK
1482    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1483  );
1484
1485  return val;
1486}
1487
1488/* PMCCNTR */
1489ARM_CP15_TEXT_SECTION static inline void
1490arm_cp15_set_performance_monitors_cycle_count(uint32_t val)
1491{
1492  ARM_SWITCH_REGISTERS;
1493
1494  __asm__ volatile (
1495    ARM_SWITCH_TO_ARM
1496    "mcr p15, 0, %[val], c9, c13, 0\n"
1497    ARM_SWITCH_BACK
1498    : ARM_SWITCH_OUTPUT
1499    : [val] "r" (val)
1500  );
1501}
1502
1503/* PMCEID0 */
1504ARM_CP15_TEXT_SECTION static inline uint32_t
1505arm_cp15_get_performance_monitors_common_event_id_0(void)
1506{
1507  ARM_SWITCH_REGISTERS;
1508  uint32_t val;
1509
1510  __asm__ volatile (
1511    ARM_SWITCH_TO_ARM
1512    "mrc p15, 0, %[val], c9, c12, 6\n"
1513    ARM_SWITCH_BACK
1514    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1515  );
1516
1517  return val;
1518}
1519
1520/* PMCEID1 */
1521ARM_CP15_TEXT_SECTION static inline uint32_t
1522arm_cp15_get_performance_monitors_common_event_id_1(void)
1523{
1524  ARM_SWITCH_REGISTERS;
1525  uint32_t val;
1526
1527  __asm__ volatile (
1528    ARM_SWITCH_TO_ARM
1529    "mrc p15, 0, %[val], c9, c12, 7\n"
1530    ARM_SWITCH_BACK
1531    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1532  );
1533
1534  return val;
1535}
1536
1537#define ARM_CP15_PMCLRSET_CYCLE_COUNTER 0x80000000
1538
1539/* PMCCNTENCLR */
1540ARM_CP15_TEXT_SECTION static inline uint32_t
1541arm_cp15_get_performance_monitors_count_enable_clear(void)
1542{
1543  ARM_SWITCH_REGISTERS;
1544  uint32_t val;
1545
1546  __asm__ volatile (
1547    ARM_SWITCH_TO_ARM
1548    "mrc p15, 0, %[val], c9, c12, 2\n"
1549    ARM_SWITCH_BACK
1550    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1551  );
1552
1553  return val;
1554}
1555
1556/* PMCCNTENCLR */
1557ARM_CP15_TEXT_SECTION static inline void
1558arm_cp15_set_performance_monitors_count_enable_clear(uint32_t val)
1559{
1560  ARM_SWITCH_REGISTERS;
1561
1562  __asm__ volatile (
1563    ARM_SWITCH_TO_ARM
1564    "mcr p15, 0, %[val], c9, c12, 2\n"
1565    ARM_SWITCH_BACK
1566    : ARM_SWITCH_OUTPUT
1567    : [val] "r" (val)
1568  );
1569}
1570
1571/* PMCCNTENSET */
1572ARM_CP15_TEXT_SECTION static inline uint32_t
1573arm_cp15_get_performance_monitors_count_enable_set(void)
1574{
1575  ARM_SWITCH_REGISTERS;
1576  uint32_t val;
1577
1578  __asm__ volatile (
1579    ARM_SWITCH_TO_ARM
1580    "mrc p15, 0, %[val], c9, c12, 1\n"
1581    ARM_SWITCH_BACK
1582    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1583  );
1584
1585  return val;
1586}
1587
1588/* PMCCNTENSET */
1589ARM_CP15_TEXT_SECTION static inline void
1590arm_cp15_set_performance_monitors_count_enable_set(uint32_t val)
1591{
1592  ARM_SWITCH_REGISTERS;
1593
1594  __asm__ volatile (
1595    ARM_SWITCH_TO_ARM
1596    "mcr p15, 0, %[val], c9, c12, 1\n"
1597    ARM_SWITCH_BACK
1598    : ARM_SWITCH_OUTPUT
1599    : [val] "r" (val)
1600  );
1601}
1602
1603#define ARM_CP15_PMCR_IMP(x) ((x) << 24)
1604#define ARM_CP15_PMCR_IDCODE(x) ((x) << 16)
1605#define ARM_CP15_PMCR_N(x) ((x) << 11)
1606#define ARM_CP15_PMCR_DP (1U << 5)
1607#define ARM_CP15_PMCR_X (1U << 3)
1608#define ARM_CP15_PMCR_D (1U << 4)
1609#define ARM_CP15_PMCR_C (1U << 2)
1610#define ARM_CP15_PMCR_P (1U << 1)
1611#define ARM_CP15_PMCR_E (1U << 0)
1612
1613/* PMCR */
1614ARM_CP15_TEXT_SECTION static inline uint32_t
1615arm_cp15_get_performance_monitors_control(void)
1616{
1617  ARM_SWITCH_REGISTERS;
1618  uint32_t val;
1619
1620  __asm__ volatile (
1621    ARM_SWITCH_TO_ARM
1622    "mrc p15, 0, %[val], c9, c12, 0\n"
1623    ARM_SWITCH_BACK
1624    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1625  );
1626
1627  return val;
1628}
1629
1630/* PMCR */
1631ARM_CP15_TEXT_SECTION static inline void
1632arm_cp15_set_performance_monitors_control(uint32_t val)
1633{
1634  ARM_SWITCH_REGISTERS;
1635
1636  __asm__ volatile (
1637    ARM_SWITCH_TO_ARM
1638    "mcr p15, 0, %[val], c9, c12, 0\n"
1639    ARM_SWITCH_BACK
1640    : ARM_SWITCH_OUTPUT
1641    : [val] "r" (val)
1642  );
1643}
1644
1645/* PMINTENCLR */
1646ARM_CP15_TEXT_SECTION static inline uint32_t
1647arm_cp15_get_performance_monitors_interrupt_enable_clear(void)
1648{
1649  ARM_SWITCH_REGISTERS;
1650  uint32_t val;
1651
1652  __asm__ volatile (
1653    ARM_SWITCH_TO_ARM
1654    "mrc p15, 0, %[val], c9, c14, 2\n"
1655    ARM_SWITCH_BACK
1656    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1657  );
1658
1659  return val;
1660}
1661
1662/* PMINTENCLR */
1663ARM_CP15_TEXT_SECTION static inline void
1664arm_cp15_set_performance_monitors_interrupt_enable_clear(uint32_t val)
1665{
1666  ARM_SWITCH_REGISTERS;
1667
1668  __asm__ volatile (
1669    ARM_SWITCH_TO_ARM
1670    "mcr p15, 0, %[val], c9, c14, 2\n"
1671    ARM_SWITCH_BACK
1672    : ARM_SWITCH_OUTPUT
1673    : [val] "r" (val)
1674  );
1675}
1676
1677/* PMINTENSET */
1678ARM_CP15_TEXT_SECTION static inline uint32_t
1679arm_cp15_get_performance_monitors_interrupt_enable_set(void)
1680{
1681  ARM_SWITCH_REGISTERS;
1682  uint32_t val;
1683
1684  __asm__ volatile (
1685    ARM_SWITCH_TO_ARM
1686    "mrc p15, 0, %[val], c9, c14, 1\n"
1687    ARM_SWITCH_BACK
1688    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1689  );
1690
1691  return val;
1692}
1693
1694/* PMINTENSET */
1695ARM_CP15_TEXT_SECTION static inline void
1696arm_cp15_set_performance_monitors_interrupt_enable_set(uint32_t val)
1697{
1698  ARM_SWITCH_REGISTERS;
1699
1700  __asm__ volatile (
1701    ARM_SWITCH_TO_ARM
1702    "mcr p15, 0, %[val], c9, c14, 1\n"
1703    ARM_SWITCH_BACK
1704    : ARM_SWITCH_OUTPUT
1705    : [val] "r" (val)
1706  );
1707}
1708
1709/* PMOVSR */
1710ARM_CP15_TEXT_SECTION static inline uint32_t
1711arm_cp15_get_performance_monitors_overflow_flag_status(void)
1712{
1713  ARM_SWITCH_REGISTERS;
1714  uint32_t val;
1715
1716  __asm__ volatile (
1717    ARM_SWITCH_TO_ARM
1718    "mrc p15, 0, %[val], c9, c12, 3\n"
1719    ARM_SWITCH_BACK
1720    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1721  );
1722
1723  return val;
1724}
1725
1726/* PMOVSR */
1727ARM_CP15_TEXT_SECTION static inline void
1728arm_cp15_set_performance_monitors_overflow_flag_status(uint32_t val)
1729{
1730  ARM_SWITCH_REGISTERS;
1731
1732  __asm__ volatile (
1733    ARM_SWITCH_TO_ARM
1734    "mcr p15, 0, %[val], c9, c12, 3\n"
1735    ARM_SWITCH_BACK
1736    : ARM_SWITCH_OUTPUT
1737    : [val] "r" (val)
1738  );
1739}
1740
1741/* PMOVSSET */
1742ARM_CP15_TEXT_SECTION static inline uint32_t
1743arm_cp15_get_performance_monitors_overflow_flag_status_set(void)
1744{
1745  ARM_SWITCH_REGISTERS;
1746  uint32_t val;
1747
1748  __asm__ volatile (
1749    ARM_SWITCH_TO_ARM
1750    "mrc p15, 0, %[val], c9, c14, 3\n"
1751    ARM_SWITCH_BACK
1752    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1753  );
1754
1755  return val;
1756}
1757
1758/* PMOVSSET */
1759ARM_CP15_TEXT_SECTION static inline void
1760arm_cp15_set_performance_monitors_overflow_flag_status_set(uint32_t val)
1761{
1762  ARM_SWITCH_REGISTERS;
1763
1764  __asm__ volatile (
1765    ARM_SWITCH_TO_ARM
1766    "mcr p15, 0, %[val], c9, c14, 3\n"
1767    ARM_SWITCH_BACK
1768    : ARM_SWITCH_OUTPUT
1769    : [val] "r" (val)
1770  );
1771}
1772
1773/* PMSELR */
1774ARM_CP15_TEXT_SECTION static inline uint32_t
1775arm_cp15_get_performance_monitors_event_counter_selection(void)
1776{
1777  ARM_SWITCH_REGISTERS;
1778  uint32_t val;
1779
1780  __asm__ volatile (
1781    ARM_SWITCH_TO_ARM
1782    "mrc p15, 0, %[val], c9, c12, 5\n"
1783    ARM_SWITCH_BACK
1784    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1785  );
1786
1787  return val;
1788}
1789
1790/* PMSELR */
1791ARM_CP15_TEXT_SECTION static inline void
1792arm_cp15_set_performance_monitors_event_counter_selection(uint32_t val)
1793{
1794  ARM_SWITCH_REGISTERS;
1795
1796  __asm__ volatile (
1797    ARM_SWITCH_TO_ARM
1798    "mcr p15, 0, %[val], c9, c12, 5\n"
1799    ARM_SWITCH_BACK
1800    : ARM_SWITCH_OUTPUT
1801    : [val] "r" (val)
1802  );
1803}
1804
1805/* PMSWINC */
1806ARM_CP15_TEXT_SECTION static inline void
1807arm_cp15_set_performance_monitors_software_increment(uint32_t val)
1808{
1809  ARM_SWITCH_REGISTERS;
1810
1811  __asm__ volatile (
1812    ARM_SWITCH_TO_ARM
1813    "mcr p15, 0, %[val], c9, c12, 4\n"
1814    ARM_SWITCH_BACK
1815    : ARM_SWITCH_OUTPUT
1816    : [val] "r" (val)
1817  );
1818}
1819
1820/* PMUSERENR */
1821ARM_CP15_TEXT_SECTION static inline uint32_t
1822arm_cp15_get_performance_monitors_user_enable(void)
1823{
1824  ARM_SWITCH_REGISTERS;
1825  uint32_t val;
1826
1827  __asm__ volatile (
1828    ARM_SWITCH_TO_ARM
1829    "mrc p15, 0, %[val], c9, c14, 0\n"
1830    ARM_SWITCH_BACK
1831    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1832  );
1833
1834  return val;
1835}
1836
1837/* PMUSERENR */
1838ARM_CP15_TEXT_SECTION static inline void
1839arm_cp15_set_performance_monitors_user_enable(uint32_t val)
1840{
1841  ARM_SWITCH_REGISTERS;
1842
1843  __asm__ volatile (
1844    ARM_SWITCH_TO_ARM
1845    "mcr p15, 0, %[val], c9, c14, 0\n"
1846    ARM_SWITCH_BACK
1847    : ARM_SWITCH_OUTPUT
1848    : [val] "r" (val)
1849  );
1850}
1851
1852/* PMXEVCNTR */
1853ARM_CP15_TEXT_SECTION static inline uint32_t
1854arm_cp15_get_performance_monitors_event_count(void)
1855{
1856  ARM_SWITCH_REGISTERS;
1857  uint32_t val;
1858
1859  __asm__ volatile (
1860    ARM_SWITCH_TO_ARM
1861    "mrc p15, 0, %[val], c9, c13, 2\n"
1862    ARM_SWITCH_BACK
1863    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1864  );
1865
1866  return val;
1867}
1868
1869/* PMXEVCNTR */
1870ARM_CP15_TEXT_SECTION static inline void
1871arm_cp15_set_performance_monitors_event_count(uint32_t val)
1872{
1873  ARM_SWITCH_REGISTERS;
1874
1875  __asm__ volatile (
1876    ARM_SWITCH_TO_ARM
1877    "mcr p15, 0, %[val], c9, c13, 2\n"
1878    ARM_SWITCH_BACK
1879    : ARM_SWITCH_OUTPUT
1880    : [val] "r" (val)
1881  );
1882}
1883
1884/* PMXEVTYPER */
1885ARM_CP15_TEXT_SECTION static inline uint32_t
1886arm_cp15_get_performance_monitors_event_type_select(void)
1887{
1888  ARM_SWITCH_REGISTERS;
1889  uint32_t val;
1890
1891  __asm__ volatile (
1892    ARM_SWITCH_TO_ARM
1893    "mrc p15, 0, %[val], c9, c13, 1\n"
1894    ARM_SWITCH_BACK
1895    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1896  );
1897
1898  return val;
1899}
1900
1901/* PMXEVTYPER */
1902ARM_CP15_TEXT_SECTION static inline void
1903arm_cp15_set_performance_monitors_event_type_select(uint32_t val)
1904{
1905  ARM_SWITCH_REGISTERS;
1906
1907  __asm__ volatile (
1908    ARM_SWITCH_TO_ARM
1909    "mcr p15, 0, %[val], c9, c13, 1\n"
1910    ARM_SWITCH_BACK
1911    : ARM_SWITCH_OUTPUT
1912    : [val] "r" (val)
1913  );
1914}
1915
1916/* CNTFRQ */
1917ARM_CP15_TEXT_SECTION static inline uint32_t
1918arm_cp15_get_counter_frequency(void)
1919{
1920  ARM_SWITCH_REGISTERS;
1921  uint32_t val;
1922
1923  __asm__ volatile (
1924    ARM_SWITCH_TO_ARM
1925    "mrc p15, 0, %[val], c14, c0, 0\n"
1926    ARM_SWITCH_BACK
1927    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1928  );
1929
1930  return val;
1931}
1932
1933/* CNTFRQ */
1934ARM_CP15_TEXT_SECTION static inline void
1935arm_cp15_set_counter_frequency(uint32_t val)
1936{
1937  ARM_SWITCH_REGISTERS;
1938
1939  __asm__ volatile (
1940    ARM_SWITCH_TO_ARM
1941    "mcr p15, 0, %[val], c14, c0, 0\n"
1942    ARM_SWITCH_BACK
1943    : ARM_SWITCH_OUTPUT
1944    : [val] "r" (val)
1945  );
1946}
1947
1948/* CNTPCT */
1949ARM_CP15_TEXT_SECTION static inline uint64_t
1950arm_cp15_get_counter_physical_count(void)
1951{
1952  ARM_SWITCH_REGISTERS;
1953  uint64_t val;
1954
1955  __asm__ volatile (
1956    ARM_SWITCH_TO_ARM
1957    "mrrc p15, 0, %Q[val], %R[val], c14\n"
1958    ARM_SWITCH_BACK
1959    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1960  );
1961
1962  return val;
1963}
1964
1965/* CNTKCTL */
1966ARM_CP15_TEXT_SECTION static inline uint32_t
1967arm_cp15_get_counter_non_secure_pl1_control(void)
1968{
1969  ARM_SWITCH_REGISTERS;
1970  uint32_t val;
1971
1972  __asm__ volatile (
1973    ARM_SWITCH_TO_ARM
1974    "mrc p15, 0, %[val], c14, c1, 0\n"
1975    ARM_SWITCH_BACK
1976    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1977  );
1978
1979  return val;
1980}
1981
1982/* CNTKCTL */
1983ARM_CP15_TEXT_SECTION static inline void
1984arm_cp15_set_counter_non_secure_pl1_control(uint32_t val)
1985{
1986  ARM_SWITCH_REGISTERS;
1987
1988  __asm__ volatile (
1989    ARM_SWITCH_TO_ARM
1990    "mcr p15, 0, %[val], c14, c1, 0\n"
1991    ARM_SWITCH_BACK
1992    : ARM_SWITCH_OUTPUT
1993    : [val] "r" (val)
1994  );
1995}
1996
1997/* CNTP_TVAL */
1998ARM_CP15_TEXT_SECTION static inline uint32_t
1999arm_cp15_get_counter_pl1_physical_timer_value(void)
2000{
2001  ARM_SWITCH_REGISTERS;
2002  uint32_t val;
2003
2004  __asm__ volatile (
2005    ARM_SWITCH_TO_ARM
2006    "mrc p15, 0, %[val], c14, c2, 0\n"
2007    ARM_SWITCH_BACK
2008    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2009  );
2010
2011  return val;
2012}
2013
2014/* CNTP_TVAL */
2015ARM_CP15_TEXT_SECTION static inline void
2016arm_cp15_set_counter_pl1_physical_timer_value(uint32_t val)
2017{
2018  ARM_SWITCH_REGISTERS;
2019
2020  __asm__ volatile (
2021    ARM_SWITCH_TO_ARM
2022    "mcr p15, 0, %[val], c14, c2, 0\n"
2023    ARM_SWITCH_BACK
2024    : ARM_SWITCH_OUTPUT
2025    : [val] "r" (val)
2026  );
2027}
2028
2029/* CNTP_CTL */
2030ARM_CP15_TEXT_SECTION static inline uint32_t
2031arm_cp15_get_counter_pl1_physical_timer_control(void)
2032{
2033  ARM_SWITCH_REGISTERS;
2034  uint32_t val;
2035
2036  __asm__ volatile (
2037    ARM_SWITCH_TO_ARM
2038    "mrc p15, 0, %[val], c14, c2, 1\n"
2039    ARM_SWITCH_BACK
2040    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2041  );
2042
2043  return val;
2044}
2045
2046/* CNTP_CTL */
2047ARM_CP15_TEXT_SECTION static inline void
2048arm_cp15_set_counter_pl1_physical_timer_control(uint32_t val)
2049{
2050  ARM_SWITCH_REGISTERS;
2051
2052  __asm__ volatile (
2053    ARM_SWITCH_TO_ARM
2054    "mcr p15, 0, %[val], c14, c2, 1\n"
2055    ARM_SWITCH_BACK
2056    : ARM_SWITCH_OUTPUT
2057    : [val] "r" (val)
2058  );
2059}
2060
2061/* CNTV_TVAL */
2062ARM_CP15_TEXT_SECTION static inline uint32_t
2063arm_cp15_get_counter_pl1_virtual_timer_value(void)
2064{
2065  ARM_SWITCH_REGISTERS;
2066  uint32_t val;
2067
2068  __asm__ volatile (
2069    ARM_SWITCH_TO_ARM
2070    "mrc p15, 0, %[val], c14, c2, 0\n"
2071    ARM_SWITCH_BACK
2072    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2073  );
2074
2075  return val;
2076}
2077
2078/* CNTV_TVAL */
2079ARM_CP15_TEXT_SECTION static inline void
2080arm_cp15_set_counter_pl1_virtual_timer_value(uint32_t val)
2081{
2082  ARM_SWITCH_REGISTERS;
2083
2084  __asm__ volatile (
2085    ARM_SWITCH_TO_ARM
2086    "mcr p15, 0, %[val], c14, c3, 0\n"
2087    ARM_SWITCH_BACK
2088    : ARM_SWITCH_OUTPUT
2089    : [val] "r" (val)
2090  );
2091}
2092
2093/* CNTV_CTL */
2094ARM_CP15_TEXT_SECTION static inline uint32_t
2095arm_cp15_get_counter_pl1_virtual_timer_control(void)
2096{
2097  ARM_SWITCH_REGISTERS;
2098  uint32_t val;
2099
2100  __asm__ volatile (
2101    ARM_SWITCH_TO_ARM
2102    "mrc p15, 0, %[val], c14, c3, 1\n"
2103    ARM_SWITCH_BACK
2104    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2105  );
2106
2107  return val;
2108}
2109
2110/* CNTV_CTL */
2111ARM_CP15_TEXT_SECTION static inline void
2112arm_cp15_set_counter_pl1_virtual_timer_control(uint32_t val)
2113{
2114  ARM_SWITCH_REGISTERS;
2115
2116  __asm__ volatile (
2117    ARM_SWITCH_TO_ARM
2118    "mcr p15, 0, %[val], c14, c3, 1\n"
2119    ARM_SWITCH_BACK
2120    : ARM_SWITCH_OUTPUT
2121    : [val] "r" (val)
2122  );
2123}
2124
2125/* CNTVCT */
2126ARM_CP15_TEXT_SECTION static inline uint64_t
2127arm_cp15_get_counter_virtual_count(void)
2128{
2129  ARM_SWITCH_REGISTERS;
2130  uint64_t val;
2131
2132  __asm__ volatile (
2133    ARM_SWITCH_TO_ARM
2134    "mrrc p15, 1, %Q[val], %R[val], c14\n"
2135    ARM_SWITCH_BACK
2136    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2137  );
2138
2139  return val;
2140}
2141
2142/* CNTP_CVAL */
2143ARM_CP15_TEXT_SECTION static inline uint64_t
2144arm_cp15_get_counter_pl1_physical_compare_value(void)
2145{
2146  ARM_SWITCH_REGISTERS;
2147  uint64_t val;
2148
2149  __asm__ volatile (
2150    ARM_SWITCH_TO_ARM
2151    "mrrc p15, 2, %Q[val], %R[val], c14\n"
2152    ARM_SWITCH_BACK
2153    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2154  );
2155
2156  return val;
2157}
2158
2159/* CNTP_CVAL */
2160ARM_CP15_TEXT_SECTION static inline void
2161arm_cp15_set_counter_pl1_physical_compare_value(uint64_t val)
2162{
2163  ARM_SWITCH_REGISTERS;
2164
2165  __asm__ volatile (
2166    ARM_SWITCH_TO_ARM
2167    "mcrr p15, 2, %Q[val], %R[val], c14\n"
2168    ARM_SWITCH_BACK
2169    : ARM_SWITCH_OUTPUT
2170    : [val] "r" (val)
2171  );
2172}
2173
2174/* CNTV_CVAL */
2175ARM_CP15_TEXT_SECTION static inline uint64_t
2176arm_cp15_get_counter_pl1_virtual_compare_value(void)
2177{
2178  ARM_SWITCH_REGISTERS;
2179  uint64_t val;
2180
2181  __asm__ volatile (
2182    ARM_SWITCH_TO_ARM
2183    "mrrc p15, 3, %Q[val], %R[val], c14\n"
2184    ARM_SWITCH_BACK
2185    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2186  );
2187
2188  return val;
2189}
2190
2191/* CNTV_CVAL */
2192ARM_CP15_TEXT_SECTION static inline void
2193arm_cp15_set_counter_pl1_virtual_compare_value(uint64_t val)
2194{
2195  ARM_SWITCH_REGISTERS;
2196
2197  __asm__ volatile (
2198    ARM_SWITCH_TO_ARM
2199    "mcrr p15, 3, %Q[val], %R[val], c14\n"
2200    ARM_SWITCH_BACK
2201    : ARM_SWITCH_OUTPUT
2202    : [val] "r" (val)
2203  );
2204}
2205
2206/* CNTVOFF */
2207ARM_CP15_TEXT_SECTION static inline uint64_t
2208arm_cp15_get_counter_virtual_offset(void)
2209{
2210  ARM_SWITCH_REGISTERS;
2211  uint64_t val;
2212
2213  __asm__ volatile (
2214    ARM_SWITCH_TO_ARM
2215    "mrrc p15, 4, %Q[val], %R[val], c14\n"
2216    ARM_SWITCH_BACK
2217    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2218  );
2219
2220  return val;
2221}
2222
2223/* CNTVOFF */
2224ARM_CP15_TEXT_SECTION static inline void
2225arm_cp15_set_counter_virtual_offset(uint64_t val)
2226{
2227  ARM_SWITCH_REGISTERS;
2228
2229  __asm__ volatile (
2230    ARM_SWITCH_TO_ARM
2231    "mcrr p15, 4, %Q[val], %R[val], c14\n"
2232    ARM_SWITCH_BACK
2233    : ARM_SWITCH_OUTPUT
2234    : [val] "r" (val)
2235  );
2236}
2237
2238/**
2239 * @brief Sets the @a section_flags for the address range [@a begin, @a end).
2240 *
2241 * @return Previous section flags of the first modified entry.
2242 */
2243uint32_t arm_cp15_set_translation_table_entries(
2244  const void *begin,
2245  const void *end,
2246  uint32_t section_flags
2247);
2248
2249void arm_cp15_set_exception_handler(
2250  Arm_symbolic_exception_name exception,
2251  void (*handler)(void)
2252);
2253
2254/** @} */
2255
2256#ifdef __cplusplus
2257}
2258#endif /* __cplusplus */
2259
2260#endif /* LIBCPU_SHARED_ARM_CP15_H */
Note: See TracBrowser for help on using the repository browser.