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

5
Last change on this file since 444cb5c was 444cb5c, checked in by Sebastian Huber <sebastian.huber@…>, on 02/15/17 at 10:12:40

bsps/arm: Fix prototype

  • Property mode set to 100644
File size: 32.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-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 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/**
1472 * @brief Sets the @a section_flags for the address range [@a begin, @a end).
1473 *
1474 * @return Previous section flags of the first modified entry.
1475 */
1476uint32_t arm_cp15_set_translation_table_entries(
1477  const void *begin,
1478  const void *end,
1479  uint32_t section_flags
1480);
1481
1482void arm_cp15_set_exception_handler(
1483  Arm_symbolic_exception_name exception,
1484  void (*handler)(void)
1485);
1486
1487/** @} */
1488
1489#ifdef __cplusplus
1490}
1491#endif /* __cplusplus */
1492
1493#endif /* LIBCPU_SHARED_ARM_CP15_H */
Note: See TracBrowser for help on using the repository browser.