source: rtems/cpukit/score/cpu/arm/include/libcpu/arm-cp15.h @ 7abc497

Last change on this file since 7abc497 was 7abc497, checked in by Kinsey Moore <nyphbl8d@…>, on Feb 21, 2019 at 10:13:58 PM

bsps/arm: Fix system register for virtual timer

The system register in use for retrieval of the virtual timer value was
mistakenly copied from the physical timer value retrieval function.
Virtual timer value retrieval should use the same system register as the
virtual timer value setter.

Close #3699.

  • 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, c3, 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.