source: rtems/c/src/lib/libcpu/arm/shared/include/arm-cp15.h @ 577e7fb

5
Last change on this file since 577e7fb was 577e7fb, checked in by Pavel Pisa <pisa@…>, on 07/17/16 at 17:31:33

arm/bsps: CP15 and basic cache support entire cache clean for more architecture variants now.

Next cache operations should work on most of cores now

rtems_cache_flush_entire_data()
rtems_cache_invalidate_entire_data()
rtems_cache_invalidate_entire_instruction()

Instruction cache invalidate works on the first level for now only.
Data cacache operations are extended to ensure flush/invalidate
on all cache levels.

The CP15 arm_cp15_data_cache_clean_all_levels() function extended
to continue through unified levels too (ctype = 4).

  • Property mode set to 100644
File size: 31.3 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-2013 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 CCSIDR, Cache Size ID Register Defines
215 *
216 * @{
217 */
218
219#define ARM_CP15_CACHE_CSS_ID_DATA 0
220#define ARM_CP15_CACHE_CSS_ID_INSTRUCTION 1
221#define ARM_CP15_CACHE_CSS_LEVEL(level) ((level) << 1)
222
223/** @} */
224
225ARM_CP15_TEXT_SECTION static inline uint32_t
226arm_cp15_get_id_code(void)
227{
228  ARM_SWITCH_REGISTERS;
229  uint32_t val;
230
231  __asm__ volatile (
232    ARM_SWITCH_TO_ARM
233    "mrc p15, 0, %[val], c0, c0, 0\n"
234    ARM_SWITCH_BACK
235    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
236  );
237
238  return val;
239}
240
241ARM_CP15_TEXT_SECTION static inline uint32_t
242arm_cp15_get_tcm_status(void)
243{
244  ARM_SWITCH_REGISTERS;
245  uint32_t val;
246
247  __asm__ volatile (
248    ARM_SWITCH_TO_ARM
249    "mrc p15, 0, %[val], c0, c0, 2\n"
250    ARM_SWITCH_BACK
251    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
252  );
253
254  return val;
255}
256
257ARM_CP15_TEXT_SECTION static inline uint32_t
258arm_cp15_get_control(void)
259{
260  ARM_SWITCH_REGISTERS;
261  uint32_t val;
262
263  __asm__ volatile (
264    ARM_SWITCH_TO_ARM
265    "mrc p15, 0, %[val], c1, c0, 0\n"
266    ARM_SWITCH_BACK
267    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
268  );
269
270  return val;
271}
272
273ARM_CP15_TEXT_SECTION static inline void
274arm_cp15_set_control(uint32_t val)
275{
276  ARM_SWITCH_REGISTERS;
277
278  __asm__ volatile (
279    ARM_SWITCH_TO_ARM
280    "mcr p15, 0, %[val], c1, c0, 0\n"
281    "nop\n"
282    "nop\n"
283    ARM_SWITCH_BACK
284    : ARM_SWITCH_OUTPUT
285    : [val] "r" (val)
286    : "memory"
287  );
288}
289
290/**
291 * @name MMU Functions
292 *
293 * @{
294 */
295
296/**
297 * @brief Disable the MMU.
298 *
299 * This function will clean and invalidate eight cache lines before and after
300 * the current stack pointer.
301 *
302 * @param[in] cls The data cache line size.
303 *
304 * @return The current control register value.
305 */
306ARM_CP15_TEXT_SECTION static inline uint32_t
307arm_cp15_mmu_disable(uint32_t cls)
308{
309  ARM_SWITCH_REGISTERS;
310  uint32_t ctrl;
311  uint32_t tmp_0;
312  uint32_t tmp_1;
313
314  __asm__ volatile (
315    ARM_SWITCH_TO_ARM
316    "mrc p15, 0, %[ctrl], c1, c0, 0\n"
317    "bic %[tmp_0], %[ctrl], #1\n"
318    "mcr p15, 0, %[tmp_0], c1, c0, 0\n"
319    "nop\n"
320    "nop\n"
321    "mov %[tmp_1], sp\n"
322    "rsb %[tmp_0], %[cls], #0\n"
323    "and %[tmp_0], %[tmp_0], %[tmp_1]\n"
324    "sub %[tmp_0], %[tmp_0], %[cls], asl #3\n"
325    "add %[tmp_1], %[tmp_0], %[cls], asl #4\n"
326    "1:\n"
327    "mcr p15, 0, %[tmp_0], c7, c14, 1\n"
328    "add %[tmp_0], %[tmp_0], %[cls]\n"
329    "cmp %[tmp_1], %[tmp_0]\n"
330    "bne 1b\n"
331    ARM_SWITCH_BACK
332    : [ctrl] "=&r" (ctrl),
333      [tmp_0] "=&r" (tmp_0),
334      [tmp_1] "=&r" (tmp_1)
335      ARM_SWITCH_ADDITIONAL_OUTPUT
336    : [cls] "r" (cls)
337    : "memory", "cc"
338  );
339
340  return ctrl;
341}
342
343ARM_CP15_TEXT_SECTION static inline uint32_t
344*arm_cp15_get_translation_table_base(void)
345{
346  ARM_SWITCH_REGISTERS;
347  uint32_t *base;
348
349  __asm__ volatile (
350    ARM_SWITCH_TO_ARM
351    "mrc p15, 0, %[base], c2, c0, 0\n"
352    ARM_SWITCH_BACK
353    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
354  );
355
356  return base;
357}
358
359ARM_CP15_TEXT_SECTION static inline void
360arm_cp15_set_translation_table_base(uint32_t *base)
361{
362  ARM_SWITCH_REGISTERS;
363
364  __asm__ volatile (
365    ARM_SWITCH_TO_ARM
366    "mcr p15, 0, %[base], c2, c0, 0\n"
367    ARM_SWITCH_BACK
368    : ARM_SWITCH_OUTPUT
369    : [base] "r" (base)
370  );
371}
372
373/* Translation Table Base Control Register - DDI0301H arm1176jzfs TRM 3.2.15 */
374ARM_CP15_TEXT_SECTION static inline uint32_t
375*arm_cp15_get_translation_table_base_control_register(void)
376{
377  ARM_SWITCH_REGISTERS;
378  uint32_t ttb_cr;
379
380  __asm__ volatile (
381    ARM_SWITCH_TO_ARM
382    "mrc p15, 0, %[ttb_cr], c2, c0, 2\n"
383    ARM_SWITCH_BACK
384    : [ttb_cr] "=&r" (ttb_cr) ARM_SWITCH_ADDITIONAL_OUTPUT
385  );
386
387  return ttb_cr;
388}
389
390ARM_CP15_TEXT_SECTION static inline void
391arm_cp15_set_translation_table_base_control_register(uint32_t ttb_cr)
392{
393  ARM_SWITCH_REGISTERS;
394
395  __asm__ volatile (
396    ARM_SWITCH_TO_ARM
397    "mcr p15, 0, %[ttb_cr], c2, c0, 2\n"
398    ARM_SWITCH_BACK
399    : ARM_SWITCH_OUTPUT
400    : [ttb_cr] "r" (ttb_cr)
401  );
402}
403
404ARM_CP15_TEXT_SECTION static inline uint32_t
405arm_cp15_get_domain_access_control(void)
406{
407  ARM_SWITCH_REGISTERS;
408  uint32_t val;
409
410  __asm__ volatile (
411    ARM_SWITCH_TO_ARM
412    "mrc p15, 0, %[val], c3, c0, 0\n"
413    ARM_SWITCH_BACK
414    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
415  );
416
417  return val;
418}
419
420ARM_CP15_TEXT_SECTION static inline void
421arm_cp15_set_domain_access_control(uint32_t val)
422{
423  ARM_SWITCH_REGISTERS;
424
425  __asm__ volatile (
426    ARM_SWITCH_TO_ARM
427    "mcr p15, 0, %[val], c3, c0, 0\n"
428    ARM_SWITCH_BACK
429    : ARM_SWITCH_OUTPUT
430    : [val] "r" (val)
431  );
432}
433
434ARM_CP15_TEXT_SECTION static inline uint32_t
435arm_cp15_get_data_fault_status(void)
436{
437  ARM_SWITCH_REGISTERS;
438  uint32_t val;
439
440  __asm__ volatile (
441    ARM_SWITCH_TO_ARM
442    "mrc p15, 0, %[val], c5, c0, 0\n"
443    ARM_SWITCH_BACK
444    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
445  );
446
447  return val;
448}
449
450ARM_CP15_TEXT_SECTION static inline void
451arm_cp15_set_data_fault_status(uint32_t val)
452{
453  ARM_SWITCH_REGISTERS;
454
455  __asm__ volatile (
456    ARM_SWITCH_TO_ARM
457    "mcr p15, 0, %[val], c5, c0, 0\n"
458    ARM_SWITCH_BACK
459    : ARM_SWITCH_OUTPUT
460    : [val] "r" (val)
461  );
462}
463
464ARM_CP15_TEXT_SECTION static inline uint32_t
465arm_cp15_get_instruction_fault_status(void)
466{
467  ARM_SWITCH_REGISTERS;
468  uint32_t val;
469
470  __asm__ volatile (
471    ARM_SWITCH_TO_ARM
472    "mrc p15, 0, %[val], c5, c0, 1\n"
473    ARM_SWITCH_BACK
474    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
475  );
476
477  return val;
478}
479
480ARM_CP15_TEXT_SECTION static inline void
481arm_cp15_set_instruction_fault_status(uint32_t val)
482{
483  ARM_SWITCH_REGISTERS;
484
485  __asm__ volatile (
486    ARM_SWITCH_TO_ARM
487    "mcr p15, 0, %[val], c5, c0, 1\n"
488    ARM_SWITCH_BACK
489    : ARM_SWITCH_OUTPUT
490    : [val] "r" (val)
491  );
492}
493
494ARM_CP15_TEXT_SECTION static inline void
495*arm_cp15_get_fault_address(void)
496{
497  ARM_SWITCH_REGISTERS;
498  void *mva;
499
500  __asm__ volatile (
501    ARM_SWITCH_TO_ARM
502    "mrc p15, 0, %[mva], c6, c0, 0\n"
503    ARM_SWITCH_BACK
504    : [mva] "=&r" (mva) ARM_SWITCH_ADDITIONAL_OUTPUT
505  );
506
507  return mva;
508}
509
510ARM_CP15_TEXT_SECTION static inline void
511arm_cp15_set_fault_address(const void *mva)
512{
513  ARM_SWITCH_REGISTERS;
514
515  __asm__ volatile (
516    ARM_SWITCH_TO_ARM
517    "mcr p15, 0, %[mva], c6, c0, 0\n"
518    ARM_SWITCH_BACK
519    : ARM_SWITCH_OUTPUT
520    : [mva] "r" (mva)
521  );
522}
523
524ARM_CP15_TEXT_SECTION static inline void
525arm_cp15_tlb_invalidate(void)
526{
527  ARM_SWITCH_REGISTERS;
528  uint32_t sbz = 0;
529
530  __asm__ volatile (
531    ARM_SWITCH_TO_ARM
532    "mcr p15, 0, %[sbz], c8, c7, 0\n"
533    ARM_SWITCH_BACK
534    : ARM_SWITCH_OUTPUT
535    : [sbz] "r" (sbz)
536  );
537
538  /*
539   * ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, Issue C,
540   * B3.10.1 General TLB maintenance requirements.
541   */
542  _ARM_Data_synchronization_barrier();
543  _ARM_Instruction_synchronization_barrier();
544}
545
546ARM_CP15_TEXT_SECTION static inline void
547arm_cp15_tlb_invalidate_entry(const void *mva)
548{
549  ARM_SWITCH_REGISTERS;
550
551  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
552
553  __asm__ volatile (
554    ARM_SWITCH_TO_ARM
555    "mcr p15, 0, %[mva], c8, c7, 1\n"
556    ARM_SWITCH_BACK
557    : ARM_SWITCH_OUTPUT
558    : [mva] "r" (mva)
559  );
560}
561
562ARM_CP15_TEXT_SECTION static inline void
563arm_cp15_tlb_invalidate_entry_all_asids(const void *mva)
564{
565  ARM_SWITCH_REGISTERS;
566
567  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
568
569  __asm__ volatile (
570    ARM_SWITCH_TO_ARM
571    "mcr p15, 0, %[mva], c8, c7, 3\n"
572    ARM_SWITCH_BACK
573    : ARM_SWITCH_OUTPUT
574    : [mva] "r" (mva)
575  );
576}
577
578ARM_CP15_TEXT_SECTION static inline void
579arm_cp15_tlb_instruction_invalidate(void)
580{
581  ARM_SWITCH_REGISTERS;
582  uint32_t sbz = 0;
583
584  __asm__ volatile (
585    ARM_SWITCH_TO_ARM
586    "mcr p15, 0, %[sbz], c8, c5, 0\n"
587    ARM_SWITCH_BACK
588    : ARM_SWITCH_OUTPUT
589    : [sbz] "r" (sbz)
590  );
591}
592
593ARM_CP15_TEXT_SECTION static inline void
594arm_cp15_tlb_instruction_invalidate_entry(const void *mva)
595{
596  ARM_SWITCH_REGISTERS;
597
598  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
599
600  __asm__ volatile (
601    ARM_SWITCH_TO_ARM
602    "mcr p15, 0, %[mva], c8, c5, 1\n"
603    ARM_SWITCH_BACK
604    : ARM_SWITCH_OUTPUT
605    : [mva] "r" (mva)
606  );
607}
608
609ARM_CP15_TEXT_SECTION static inline void
610arm_cp15_tlb_data_invalidate(void)
611{
612  ARM_SWITCH_REGISTERS;
613  uint32_t sbz = 0;
614
615  __asm__ volatile (
616    ARM_SWITCH_TO_ARM
617    "mcr p15, 0, %[sbz], c8, c6, 0\n"
618    ARM_SWITCH_BACK
619    : ARM_SWITCH_OUTPUT
620    : [sbz] "r" (sbz)
621  );
622}
623
624ARM_CP15_TEXT_SECTION static inline void
625arm_cp15_tlb_data_invalidate_entry(const void *mva)
626{
627  ARM_SWITCH_REGISTERS;
628
629  mva = ARM_CP15_TLB_PREPARE_MVA(mva);
630
631  __asm__ volatile (
632    ARM_SWITCH_TO_ARM
633    "mcr p15, 0, %[mva], c8, c6, 1\n"
634    ARM_SWITCH_BACK
635    : ARM_SWITCH_OUTPUT
636    : [mva] "r" (mva)
637  );
638}
639
640ARM_CP15_TEXT_SECTION static inline void
641arm_cp15_tlb_lockdown_entry(const void *mva)
642{
643  uint32_t arm_switch_reg;
644
645  __asm__ volatile (
646    ARM_SWITCH_TO_ARM
647    "add %[arm_switch_reg], pc, #16\n"
648    "mcr p15, 0, %[arm_switch_reg], c7, c13, 1\n"
649    "mcr p15, 0, %[mva], c8, c7, 1\n"
650    "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
651    "orr %[arm_switch_reg], #0x1\n"
652    "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
653    "ldr %[mva], [%[mva]]\n"
654    "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
655    "bic %[arm_switch_reg], #0x1\n"
656    "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
657    ARM_SWITCH_BACK
658    : [mva] "=r" (mva), [arm_switch_reg] "=&r" (arm_switch_reg)
659    : "[mva]" (mva)
660  );
661}
662
663/** @} */
664
665/**
666 * @name Cache Functions
667 *
668 * @{
669 */
670
671/* Read cache type register CTR */
672ARM_CP15_TEXT_SECTION static inline uint32_t
673arm_cp15_get_cache_type(void)
674{
675  ARM_SWITCH_REGISTERS;
676  uint32_t val;
677
678  __asm__ volatile (
679    ARM_SWITCH_TO_ARM
680    "mrc p15, 0, %[val], c0, c0, 1\n"
681    ARM_SWITCH_BACK
682    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
683  );
684
685  return val;
686}
687
688/* Read size of smallest cache line of all instruction/data caches controlled by the processor */
689ARM_CP15_TEXT_SECTION static inline uint32_t
690arm_cp15_get_min_cache_line_size(void)
691{
692  uint32_t mcls = 0;
693  uint32_t ct = arm_cp15_get_cache_type();
694  uint32_t format = (ct >> 29) & 0x7U;
695
696  if (format == 0x4) {
697    /* ARMv7 format */
698    mcls = (1U << (ct & 0xf)) * 4;
699  } else if (format == 0x0) {
700    /* ARMv6 format */
701    uint32_t mask = (1U << 12) - 1;
702    uint32_t dcls = (ct >> 12) & mask;
703    uint32_t icls = ct & mask;
704
705    mcls = dcls <= icls ? dcls : icls;
706  }
707
708  return mcls;
709}
710
711/* Read size of smallest data cache lines */
712ARM_CP15_TEXT_SECTION static inline uint32_t
713arm_cp15_get_data_cache_line_size(void)
714{
715  uint32_t mcls = 0;
716  uint32_t ct = arm_cp15_get_cache_type();
717  uint32_t format = (ct >> 29) & 0x7U;
718
719  if (format == 0x4) {
720    /* ARMv7 format */
721    mcls = (1U << ((ct & 0xf0000) >> 16)) * 4;
722  } else if (format == 0x0) {
723    /* ARMv6 format */
724    uint32_t mask = (1U << 12) - 1;
725    mcls = (ct >> 12) & mask;
726  }
727
728  return mcls;
729}
730
731/* Read size of smallest instruction cache lines */
732ARM_CP15_TEXT_SECTION static inline uint32_t
733arm_cp15_get_instruction_cache_line_size(void)
734{
735  uint32_t mcls = 0;
736  uint32_t ct = arm_cp15_get_cache_type();
737  uint32_t format = (ct >> 29) & 0x7U;
738
739  if (format == 0x4) {
740    /* ARMv7 format */
741    mcls = (1U << (ct & 0x0000f)) * 4;
742  } else if (format == 0x0) {
743    /* ARMv6 format */
744    uint32_t mask = (1U << 12) - 1;
745    mcls = ct & mask;;
746  }
747
748  return mcls;
749}
750
751/* CCSIDR, Cache Size ID Register */
752
753ARM_CP15_TEXT_SECTION static inline uint32_t
754arm_cp15_get_cache_size_id(void)
755{
756  ARM_SWITCH_REGISTERS;
757  uint32_t val;
758
759  __asm__ volatile (
760    ARM_SWITCH_TO_ARM
761    "mrc p15, 1, %[val], c0, c0, 0\n"
762     ARM_SWITCH_BACK
763    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
764  );
765
766  return val;
767}
768
769ARM_CP15_TEXT_SECTION static inline uint32_t
770arm_ccsidr_get_line_power(uint32_t ccsidr)
771{
772  return (ccsidr & 0x7) + 4;
773}
774
775ARM_CP15_TEXT_SECTION static inline uint32_t
776arm_ccsidr_get_associativity(uint32_t ccsidr)
777{
778  return ((ccsidr >> 3) & 0x3ff) + 1;
779}
780
781ARM_CP15_TEXT_SECTION static inline uint32_t
782arm_ccsidr_get_num_sets(uint32_t ccsidr)
783{
784  return ((ccsidr >> 13) & 0x7fff) + 1;
785}
786
787/* CLIDR, Cache Level ID Register */
788
789ARM_CP15_TEXT_SECTION static inline uint32_t
790arm_cp15_get_cache_level_id(void)
791{
792  ARM_SWITCH_REGISTERS;
793  uint32_t val;
794
795  __asm__ volatile (
796    ARM_SWITCH_TO_ARM
797    "mrc p15, 1, %[val], c0, c0, 1\n"
798     ARM_SWITCH_BACK
799    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
800  );
801
802  return val;
803}
804
805ARM_CP15_TEXT_SECTION static inline uint32_t
806arm_clidr_get_level_of_coherency(uint32_t clidr)
807{
808  return (clidr >> 24) & 0x7;
809}
810
811ARM_CP15_TEXT_SECTION static inline uint32_t
812arm_clidr_get_cache_type(uint32_t clidr, uint32_t level)
813{
814  return (clidr >> (3 * level)) & 0x7;
815}
816
817/* CSSELR, Cache Size Selection Register */
818
819ARM_CP15_TEXT_SECTION static inline uint32_t
820arm_cp15_get_cache_size_selection(void)
821{
822  ARM_SWITCH_REGISTERS;
823  uint32_t val;
824
825  __asm__ volatile (
826    ARM_SWITCH_TO_ARM
827    "mrc p15, 2, %[val], c0, c0, 0\n"
828     ARM_SWITCH_BACK
829    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
830  );
831
832  return val;
833}
834
835ARM_CP15_TEXT_SECTION static inline void
836arm_cp15_set_cache_size_selection(uint32_t val)
837{
838  ARM_SWITCH_REGISTERS;
839
840  __asm__ volatile (
841    ARM_SWITCH_TO_ARM
842    "mcr p15, 2, %[val], c0, c0, 0\n"
843     ARM_SWITCH_BACK
844    : ARM_SWITCH_OUTPUT
845    : [val] "r" (val)
846    : "memory"
847  );
848}
849
850ARM_CP15_TEXT_SECTION static inline uint32_t
851arm_cp15_get_cache_size_id_for_level(uint32_t level_and_inst_dat)
852{
853  rtems_interrupt_level irq_level;
854  uint32_t ccsidr;
855
856  rtems_interrupt_local_disable(irq_level);
857  arm_cp15_set_cache_size_selection(level_and_inst_dat);
858  _ARM_Instruction_synchronization_barrier();
859  ccsidr = arm_cp15_get_cache_size_id();
860  rtems_interrupt_local_enable(irq_level);
861
862  return ccsidr;
863}
864
865ARM_CP15_TEXT_SECTION static inline void
866arm_cp15_cache_invalidate(void)
867{
868  ARM_SWITCH_REGISTERS;
869  uint32_t sbz = 0;
870
871  __asm__ volatile (
872    ARM_SWITCH_TO_ARM
873    "mcr p15, 0, %[sbz], c7, c7, 0\n"
874    ARM_SWITCH_BACK
875    : ARM_SWITCH_OUTPUT
876    : [sbz] "r" (sbz)
877    : "memory"
878  );
879}
880
881/* ICIALLUIS, Instruction Cache Invalidate All to PoU, Inner Shareable */
882
883ARM_CP15_TEXT_SECTION static inline void
884arm_cp15_instruction_cache_inner_shareable_invalidate_all(void)
885{
886  ARM_SWITCH_REGISTERS;
887  uint32_t sbz = 0;
888
889  __asm__ volatile (
890    ARM_SWITCH_TO_ARM
891    "mcr p15, 0, %[sbz], c7, c1, 0\n"
892    ARM_SWITCH_BACK
893    : ARM_SWITCH_OUTPUT
894    : [sbz] "r" (sbz)
895    : "memory"
896  );
897}
898
899/* BPIALLIS, Branch Predictor Invalidate All, Inner Shareable */
900
901ARM_CP15_TEXT_SECTION static inline void
902arm_cp15_branch_predictor_inner_shareable_invalidate_all(void)
903{
904  ARM_SWITCH_REGISTERS;
905  uint32_t sbz = 0;
906
907  __asm__ volatile (
908    ARM_SWITCH_TO_ARM
909    "mcr p15, 0, %[sbz], c7, c1, 6\n"
910    ARM_SWITCH_BACK
911    : ARM_SWITCH_OUTPUT
912    : [sbz] "r" (sbz)
913    : "memory"
914  );
915}
916
917/* BPIALL, Branch Predictor Invalidate All */
918
919ARM_CP15_TEXT_SECTION static inline void
920arm_cp15_branch_predictor_invalidate_all(void)
921{
922  ARM_SWITCH_REGISTERS;
923  uint32_t sbz = 0;
924
925  __asm__ volatile (
926    ARM_SWITCH_TO_ARM
927    "mcr p15, 0, %[sbz], c7, c5, 6\n"
928    ARM_SWITCH_BACK
929    : ARM_SWITCH_OUTPUT
930    : [sbz] "r" (sbz)
931    : "memory"
932  );
933}
934
935/* Flush Prefetch Buffer - DDI0301H arm1176jzfs TRM 3.2.22 */
936ARM_CP15_TEXT_SECTION static inline void
937arm_cp15_flush_prefetch_buffer(void)
938{
939  ARM_SWITCH_REGISTERS;
940  uint32_t sbz = 0;
941
942  __asm__ volatile (
943    ARM_SWITCH_TO_ARM
944    "mcr p15, 0, %[sbz], c7, c5, 4\n"
945    ARM_SWITCH_BACK
946    : ARM_SWITCH_OUTPUT
947    : [sbz] "r" (sbz)
948    : "memory"
949  );
950}
951
952ARM_CP15_TEXT_SECTION static inline void
953arm_cp15_instruction_cache_invalidate(void)
954{
955  ARM_SWITCH_REGISTERS;
956  uint32_t sbz = 0;
957
958  __asm__ volatile (
959    ARM_SWITCH_TO_ARM
960    "mcr p15, 0, %[sbz], c7, c5, 0\n"
961    ARM_SWITCH_BACK
962    : ARM_SWITCH_OUTPUT
963    : [sbz] "r" (sbz)
964    : "memory"
965  );
966}
967
968ARM_CP15_TEXT_SECTION static inline void
969arm_cp15_instruction_cache_invalidate_line(const void *mva)
970{
971  ARM_SWITCH_REGISTERS;
972
973  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
974
975  __asm__ volatile (
976    ARM_SWITCH_TO_ARM
977    "mcr p15, 0, %[mva], c7, c5, 1\n"
978    ARM_SWITCH_BACK
979    : ARM_SWITCH_OUTPUT
980    : [mva] "r" (mva)
981    : "memory"
982  );
983}
984
985ARM_CP15_TEXT_SECTION static inline void
986arm_cp15_instruction_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
987{
988  ARM_SWITCH_REGISTERS;
989
990  __asm__ volatile (
991    ARM_SWITCH_TO_ARM
992    "mcr p15, 0, %[set_and_way], c7, c5, 2\n"
993    ARM_SWITCH_BACK
994    : ARM_SWITCH_OUTPUT
995    : [set_and_way] "r" (set_and_way)
996    : "memory"
997  );
998}
999
1000ARM_CP15_TEXT_SECTION static inline void
1001arm_cp15_instruction_cache_prefetch_line(const void *mva)
1002{
1003  ARM_SWITCH_REGISTERS;
1004
1005  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1006
1007  __asm__ volatile (
1008    ARM_SWITCH_TO_ARM
1009    "mcr p15, 0, %[mva], c7, c13, 1\n"
1010    ARM_SWITCH_BACK
1011    : ARM_SWITCH_OUTPUT
1012    : [mva] "r" (mva)
1013  );
1014}
1015
1016ARM_CP15_TEXT_SECTION static inline void
1017arm_cp15_data_cache_invalidate(void)
1018{
1019  ARM_SWITCH_REGISTERS;
1020  uint32_t sbz = 0;
1021
1022  __asm__ volatile (
1023    ARM_SWITCH_TO_ARM
1024    "mcr p15, 0, %[sbz], c7, c6, 0\n"
1025    ARM_SWITCH_BACK
1026    : ARM_SWITCH_OUTPUT
1027    : [sbz] "r" (sbz)
1028    : "memory"
1029  );
1030}
1031
1032ARM_CP15_TEXT_SECTION static inline void
1033arm_cp15_data_cache_invalidate_line(const void *mva)
1034{
1035  ARM_SWITCH_REGISTERS;
1036
1037  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1038
1039  __asm__ volatile (
1040    ARM_SWITCH_TO_ARM
1041    "mcr p15, 0, %[mva], c7, c6, 1\n"
1042    ARM_SWITCH_BACK
1043    : ARM_SWITCH_OUTPUT
1044    : [mva] "r" (mva)
1045    : "memory"
1046  );
1047}
1048
1049ARM_CP15_TEXT_SECTION static inline void
1050arm_cp15_data_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
1051{
1052  ARM_SWITCH_REGISTERS;
1053
1054  __asm__ volatile (
1055    ARM_SWITCH_TO_ARM
1056    "mcr p15, 0, %[set_and_way], c7, c6, 2\n"
1057    ARM_SWITCH_BACK
1058    : ARM_SWITCH_OUTPUT
1059    : [set_and_way] "r" (set_and_way)
1060    : "memory"
1061  );
1062}
1063
1064ARM_CP15_TEXT_SECTION static inline void
1065arm_cp15_data_cache_invalidate_all_levels(void)
1066{
1067  uint32_t clidr = arm_cp15_get_cache_level_id();
1068  uint32_t loc = arm_clidr_get_level_of_coherency(clidr);
1069  uint32_t level = 0;
1070
1071  for (level = 0; level < loc; ++level) {
1072    uint32_t ctype = arm_clidr_get_cache_type(clidr, level);
1073
1074    /* Check if this level has a data cache or unified cache */
1075    if (((ctype & (0x6)) == 2) || (ctype == 4)) {
1076      uint32_t ccsidr;
1077      uint32_t line_power;
1078      uint32_t associativity;
1079      uint32_t way;
1080      uint32_t way_shift;
1081
1082      ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
1083
1084      line_power = arm_ccsidr_get_line_power(ccsidr);
1085      associativity = arm_ccsidr_get_associativity(ccsidr);
1086      way_shift = __builtin_clz(associativity - 1);
1087
1088      for (way = 0; way < associativity; ++way) {
1089        uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
1090        uint32_t set;
1091
1092        for (set = 0; set < num_sets; ++set) {
1093          uint32_t set_way = (way << way_shift)
1094            | (set << line_power)
1095            | (level << 1);
1096
1097          arm_cp15_data_cache_invalidate_line_by_set_and_way(set_way);
1098        }
1099      }
1100    }
1101  }
1102}
1103
1104ARM_CP15_TEXT_SECTION static inline void
1105arm_cp15_data_cache_clean_line(const void *mva)
1106{
1107  ARM_SWITCH_REGISTERS;
1108
1109  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1110
1111  __asm__ volatile (
1112    ARM_SWITCH_TO_ARM
1113    "mcr p15, 0, %[mva], c7, c10, 1\n"
1114    ARM_SWITCH_BACK
1115    : ARM_SWITCH_OUTPUT
1116    : [mva] "r" (mva)
1117    : "memory"
1118  );
1119}
1120
1121ARM_CP15_TEXT_SECTION static inline void
1122arm_cp15_data_cache_clean_line_by_set_and_way(uint32_t set_and_way)
1123{
1124  ARM_SWITCH_REGISTERS;
1125
1126  __asm__ volatile (
1127    ARM_SWITCH_TO_ARM
1128    "mcr p15, 0, %[set_and_way], c7, c10, 2\n"
1129    ARM_SWITCH_BACK
1130    : ARM_SWITCH_OUTPUT
1131    : [set_and_way] "r" (set_and_way)
1132    : "memory"
1133  );
1134}
1135
1136ARM_CP15_TEXT_SECTION static inline void
1137arm_cp15_data_cache_clean_all_levels(void)
1138{
1139  uint32_t clidr = arm_cp15_get_cache_level_id();
1140  uint32_t loc = arm_clidr_get_level_of_coherency(clidr);
1141  uint32_t level = 0;
1142
1143  for (level = 0; level < loc; ++level) {
1144    uint32_t ctype = arm_clidr_get_cache_type(clidr, level);
1145
1146    /* Check if this level has a data cache or unified cache */
1147    if (((ctype & (0x6)) == 2) || (ctype == 4)) {
1148      uint32_t ccsidr;
1149      uint32_t line_power;
1150      uint32_t associativity;
1151      uint32_t way;
1152      uint32_t way_shift;
1153
1154      ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
1155
1156      line_power = arm_ccsidr_get_line_power(ccsidr);
1157      associativity = arm_ccsidr_get_associativity(ccsidr);
1158      way_shift = __builtin_clz(associativity - 1);
1159
1160      for (way = 0; way < associativity; ++way) {
1161        uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
1162        uint32_t set;
1163
1164        for (set = 0; set < num_sets; ++set) {
1165          uint32_t set_way = (way << way_shift)
1166            | (set << line_power)
1167            | (level << 1);
1168
1169          arm_cp15_data_cache_clean_line_by_set_and_way(set_way);
1170        }
1171      }
1172    }
1173  }
1174}
1175
1176ARM_CP15_TEXT_SECTION static inline void
1177arm_cp15_data_cache_test_and_clean(void)
1178{
1179  ARM_SWITCH_REGISTERS;
1180
1181  __asm__ volatile (
1182    ARM_SWITCH_TO_ARM
1183    "1:\n"
1184    "mrc p15, 0, r15, c7, c10, 3\n"
1185    "bne 1b\n"
1186    ARM_SWITCH_BACK
1187    : ARM_SWITCH_OUTPUT
1188    :
1189    : "memory"
1190  );
1191}
1192
1193/*      In DDI0301H_arm1176jzfs_r0p7_trm
1194 *      'MCR p15, 0, <Rd>, c7, c14, 0' means
1195 *      Clean and Invalidate Entire Data Cache
1196 */
1197ARM_CP15_TEXT_SECTION static inline void
1198arm_cp15_data_cache_clean_and_invalidate(void)
1199{
1200  ARM_SWITCH_REGISTERS;
1201
1202  uint32_t sbz = 0;
1203
1204  __asm__ volatile (
1205    ARM_SWITCH_TO_ARM
1206    "mcr p15, 0, %[sbz], c7, c14, 0\n"
1207    ARM_SWITCH_BACK
1208    : ARM_SWITCH_OUTPUT
1209    : [sbz] "r" (sbz)
1210    : "memory"
1211  );
1212}
1213
1214ARM_CP15_TEXT_SECTION static inline void
1215arm_cp15_data_cache_clean_and_invalidate_line(const void *mva)
1216{
1217  ARM_SWITCH_REGISTERS;
1218
1219  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1220
1221  __asm__ volatile (
1222    ARM_SWITCH_TO_ARM
1223    "mcr p15, 0, %[mva], c7, c14, 1\n"
1224    ARM_SWITCH_BACK
1225    : ARM_SWITCH_OUTPUT
1226    : [mva] "r" (mva)
1227    : "memory"
1228  );
1229}
1230
1231ARM_CP15_TEXT_SECTION static inline void
1232arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(uint32_t set_and_way)
1233{
1234  ARM_SWITCH_REGISTERS;
1235
1236  __asm__ volatile (
1237    ARM_SWITCH_TO_ARM
1238    "mcr p15, 0, %[set_and_way], c7, c14, 2\n"
1239    ARM_SWITCH_BACK
1240    : ARM_SWITCH_OUTPUT
1241    : [set_and_way] "r" (set_and_way)
1242    : "memory"
1243  );
1244}
1245
1246ARM_CP15_TEXT_SECTION static inline void
1247arm_cp15_data_cache_test_and_clean_and_invalidate(void)
1248{
1249  ARM_SWITCH_REGISTERS;
1250
1251  __asm__ volatile (
1252    ARM_SWITCH_TO_ARM
1253    "1:\n"
1254    "mrc p15, 0, r15, c7, c14, 3\n"
1255    "bne 1b\n"
1256    ARM_SWITCH_BACK
1257    : ARM_SWITCH_OUTPUT
1258    :
1259    : "memory"
1260  );
1261}
1262
1263/** @} */
1264
1265ARM_CP15_TEXT_SECTION static inline void
1266arm_cp15_drain_write_buffer(void)
1267{
1268  ARM_SWITCH_REGISTERS;
1269  uint32_t sbz = 0;
1270
1271  __asm__ volatile (
1272    ARM_SWITCH_TO_ARM
1273    "mcr p15, 0, %[sbz], c7, c10, 4\n"
1274    ARM_SWITCH_BACK
1275    : ARM_SWITCH_OUTPUT
1276    : [sbz] "r" (sbz)
1277    : "memory"
1278  );
1279}
1280
1281ARM_CP15_TEXT_SECTION static inline void
1282arm_cp15_wait_for_interrupt(void)
1283{
1284  ARM_SWITCH_REGISTERS;
1285  uint32_t sbz = 0;
1286
1287  __asm__ volatile (
1288    ARM_SWITCH_TO_ARM
1289    "mcr p15, 0, %[sbz], c7, c0, 4\n"
1290    ARM_SWITCH_BACK
1291    : ARM_SWITCH_OUTPUT
1292    : [sbz] "r" (sbz)
1293    : "memory"
1294  );
1295}
1296
1297ARM_CP15_TEXT_SECTION static inline uint32_t
1298arm_cp15_get_multiprocessor_affinity(void)
1299{
1300  ARM_SWITCH_REGISTERS;
1301  uint32_t mpidr;
1302
1303  __asm__ volatile (
1304    ARM_SWITCH_TO_ARM
1305          "mrc p15, 0, %[mpidr], c0, c0, 5\n"
1306    ARM_SWITCH_BACK
1307    : [mpidr] "=&r" (mpidr) ARM_SWITCH_ADDITIONAL_OUTPUT
1308  );
1309
1310  return mpidr & 0xff;
1311}
1312
1313ARM_CP15_TEXT_SECTION static inline uint32_t
1314arm_cortex_a9_get_multiprocessor_cpu_id(void)
1315{
1316  return arm_cp15_get_multiprocessor_affinity() & 0xff;
1317}
1318
1319#define ARM_CORTEX_A9_ACTL_FW (1U << 0)
1320#define ARM_CORTEX_A9_ACTL_L2_PREFETCH_HINT_ENABLE (1U << 1)
1321#define ARM_CORTEX_A9_ACTL_L1_PREFETCH_ENABLE (1U << 2)
1322#define ARM_CORTEX_A9_ACTL_WRITE_FULL_LINE_OF_ZEROS_MODE (1U << 3)
1323#define ARM_CORTEX_A9_ACTL_SMP (1U << 6)
1324#define ARM_CORTEX_A9_ACTL_EXCL (1U << 7)
1325#define ARM_CORTEX_A9_ACTL_ALLOC_IN_ONE_WAY (1U << 8)
1326#define ARM_CORTEX_A9_ACTL_PARITY_ON (1U << 9)
1327
1328ARM_CP15_TEXT_SECTION static inline uint32_t
1329arm_cp15_get_auxiliary_control(void)
1330{
1331  ARM_SWITCH_REGISTERS;
1332  uint32_t val;
1333
1334  __asm__ volatile (
1335    ARM_SWITCH_TO_ARM
1336    "mrc p15, 0, %[val], c1, c0, 1\n"
1337    ARM_SWITCH_BACK
1338    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1339  );
1340
1341  return val;
1342}
1343
1344ARM_CP15_TEXT_SECTION static inline void
1345arm_cp15_set_auxiliary_control(uint32_t val)
1346{
1347  ARM_SWITCH_REGISTERS;
1348
1349  __asm__ volatile (
1350    ARM_SWITCH_TO_ARM
1351    "mcr p15, 0, %[val], c1, c0, 1\n"
1352    ARM_SWITCH_BACK
1353    : ARM_SWITCH_OUTPUT
1354    : [val] "r" (val)
1355  );
1356}
1357
1358/* ID_PFR1, Processor Feature Register 1 */
1359
1360ARM_CP15_TEXT_SECTION static inline uint32_t
1361arm_cp15_get_processor_feature_1(void)
1362{
1363  ARM_SWITCH_REGISTERS;
1364  uint32_t val;
1365
1366  __asm__ volatile (
1367    ARM_SWITCH_TO_ARM
1368    "mrc p15, 0, %[val], c0, c1, 1\n"
1369    ARM_SWITCH_BACK
1370    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1371  );
1372
1373  return val;
1374}
1375
1376/* VBAR, Vector Base Address Register, Security Extensions */
1377
1378ARM_CP15_TEXT_SECTION static inline void
1379*arm_cp15_get_vector_base_address(void)
1380{
1381  ARM_SWITCH_REGISTERS;
1382  void *base;
1383
1384  __asm__ volatile (
1385    ARM_SWITCH_TO_ARM
1386    "mrc p15, 0, %[base], c12, c0, 0\n"
1387    ARM_SWITCH_BACK
1388    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1389  );
1390
1391  return base;
1392}
1393
1394ARM_CP15_TEXT_SECTION static inline void
1395arm_cp15_set_vector_base_address(void *base)
1396{
1397  ARM_SWITCH_REGISTERS;
1398
1399  __asm__ volatile (
1400    ARM_SWITCH_TO_ARM
1401    "mcr p15, 0, %[base], c12, c0, 0\n"
1402    ARM_SWITCH_BACK
1403    : ARM_SWITCH_OUTPUT
1404    : [base] "r" (base)
1405  );
1406}
1407
1408ARM_CP15_TEXT_SECTION static inline void
1409*arm_cp15_get_hyp_vector_base_address(void)
1410{
1411  ARM_SWITCH_REGISTERS;
1412  void *base;
1413
1414  __asm__ volatile (
1415    ARM_SWITCH_TO_ARM
1416    "mrc p15, 4, %[base], c12, c0, 0\n"
1417    ARM_SWITCH_BACK
1418    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1419  );
1420
1421  return base;
1422}
1423
1424ARM_CP15_TEXT_SECTION static inline void
1425arm_cp15_set_hyp_vector_base_address(void *base)
1426{
1427  ARM_SWITCH_REGISTERS;
1428
1429  __asm__ volatile (
1430    ARM_SWITCH_TO_ARM
1431    "mcr p15, 4, %[base], c12, c0, 0\n"
1432    ARM_SWITCH_BACK
1433    : ARM_SWITCH_OUTPUT
1434    : [base] "r" (base)
1435  );
1436}
1437
1438/**
1439 * @brief Sets the @a section_flags for the address range [@a begin, @a end).
1440 *
1441 * @return Previous section flags of the first modified entry.
1442 */
1443uint32_t arm_cp15_set_translation_table_entries(
1444  const void *begin,
1445  const void *end,
1446  uint32_t section_flags
1447);
1448
1449void arm_cp15_set_exception_handler(
1450  Arm_symbolic_exception_name exception,
1451  void (*handler)(void)
1452);
1453
1454/** @} */
1455
1456#ifdef __cplusplus
1457}
1458#endif /* __cplusplus */
1459
1460#endif /* LIBCPU_SHARED_ARM_CP15_H */
Note: See TracBrowser for help on using the repository browser.