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

4.11
Last change on this file since ae3578a2 was ae3578a2, checked in by Pavel Pisa <pisa@…>, on 07/17/16 at 16:21:48

bsps/arm: do not disable MMU during translation table management operations.

Disabling MMU requires complex cache flushing and invalidation
operations. There is almost no way how to do that right
on SMP system without stopping all other CPUs. On the other hand,
there is documented sequence of operations which should be used
according to ARM manual and it guarantees even distribution
of maintenance operations to other cores for last generation
of Cortex-A cores with multiprocessor extension.

This change could require addition of appropriate entry
to arm_cp15_start_mmu_config_table for some BSPs to ensure
that MMU table stays accessible after MMU is enabled

{

.begin = (uint32_t) bsp_translation_table_base,
.end = (uint32_t) bsp_translation_table_base + 0x4000,
.flags = ARMV7_MMU_DATA_READ_WRITE_CACHED

}

Updates #2782
Updates #2783

  • Property mode set to 100644
File size: 30.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 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 */
1075    if ((ctype & 0x2) != 0) {
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_test_and_clean(void)
1138{
1139  ARM_SWITCH_REGISTERS;
1140
1141  __asm__ volatile (
1142    ARM_SWITCH_TO_ARM
1143    "1:\n"
1144    "mrc p15, 0, r15, c7, c10, 3\n"
1145    "bne 1b\n"
1146    ARM_SWITCH_BACK
1147    : ARM_SWITCH_OUTPUT
1148    :
1149    : "memory"
1150  );
1151}
1152
1153/*      In DDI0301H_arm1176jzfs_r0p7_trm
1154 *      'MCR p15, 0, <Rd>, c7, c14, 0' means
1155 *      Clean and Invalidate Entire Data Cache
1156 */
1157ARM_CP15_TEXT_SECTION static inline void
1158arm_cp15_data_cache_clean_and_invalidate(void)
1159{
1160  ARM_SWITCH_REGISTERS;
1161
1162  uint32_t sbz = 0;
1163
1164  __asm__ volatile (
1165    ARM_SWITCH_TO_ARM
1166    "mcr p15, 0, %[sbz], c7, c14, 0\n"
1167    ARM_SWITCH_BACK
1168    : ARM_SWITCH_OUTPUT
1169    : [sbz] "r" (sbz)
1170    : "memory"
1171  );
1172}
1173
1174ARM_CP15_TEXT_SECTION static inline void
1175arm_cp15_data_cache_clean_and_invalidate_line(const void *mva)
1176{
1177  ARM_SWITCH_REGISTERS;
1178
1179  mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1180
1181  __asm__ volatile (
1182    ARM_SWITCH_TO_ARM
1183    "mcr p15, 0, %[mva], c7, c14, 1\n"
1184    ARM_SWITCH_BACK
1185    : ARM_SWITCH_OUTPUT
1186    : [mva] "r" (mva)
1187    : "memory"
1188  );
1189}
1190
1191ARM_CP15_TEXT_SECTION static inline void
1192arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(uint32_t set_and_way)
1193{
1194  ARM_SWITCH_REGISTERS;
1195
1196  __asm__ volatile (
1197    ARM_SWITCH_TO_ARM
1198    "mcr p15, 0, %[set_and_way], c7, c14, 2\n"
1199    ARM_SWITCH_BACK
1200    : ARM_SWITCH_OUTPUT
1201    : [set_and_way] "r" (set_and_way)
1202    : "memory"
1203  );
1204}
1205
1206ARM_CP15_TEXT_SECTION static inline void
1207arm_cp15_data_cache_test_and_clean_and_invalidate(void)
1208{
1209  ARM_SWITCH_REGISTERS;
1210
1211  __asm__ volatile (
1212    ARM_SWITCH_TO_ARM
1213    "1:\n"
1214    "mrc p15, 0, r15, c7, c14, 3\n"
1215    "bne 1b\n"
1216    ARM_SWITCH_BACK
1217    : ARM_SWITCH_OUTPUT
1218    :
1219    : "memory"
1220  );
1221}
1222
1223/** @} */
1224
1225ARM_CP15_TEXT_SECTION static inline void
1226arm_cp15_drain_write_buffer(void)
1227{
1228  ARM_SWITCH_REGISTERS;
1229  uint32_t sbz = 0;
1230
1231  __asm__ volatile (
1232    ARM_SWITCH_TO_ARM
1233    "mcr p15, 0, %[sbz], c7, c10, 4\n"
1234    ARM_SWITCH_BACK
1235    : ARM_SWITCH_OUTPUT
1236    : [sbz] "r" (sbz)
1237    : "memory"
1238  );
1239}
1240
1241ARM_CP15_TEXT_SECTION static inline void
1242arm_cp15_wait_for_interrupt(void)
1243{
1244  ARM_SWITCH_REGISTERS;
1245  uint32_t sbz = 0;
1246
1247  __asm__ volatile (
1248    ARM_SWITCH_TO_ARM
1249    "mcr p15, 0, %[sbz], c7, c0, 4\n"
1250    ARM_SWITCH_BACK
1251    : ARM_SWITCH_OUTPUT
1252    : [sbz] "r" (sbz)
1253    : "memory"
1254  );
1255}
1256
1257ARM_CP15_TEXT_SECTION static inline uint32_t
1258arm_cp15_get_multiprocessor_affinity(void)
1259{
1260  ARM_SWITCH_REGISTERS;
1261  uint32_t mpidr;
1262
1263  __asm__ volatile (
1264    ARM_SWITCH_TO_ARM
1265          "mrc p15, 0, %[mpidr], c0, c0, 5\n"
1266    ARM_SWITCH_BACK
1267    : [mpidr] "=&r" (mpidr) ARM_SWITCH_ADDITIONAL_OUTPUT
1268  );
1269
1270  return mpidr & 0xff;
1271}
1272
1273ARM_CP15_TEXT_SECTION static inline uint32_t
1274arm_cortex_a9_get_multiprocessor_cpu_id(void)
1275{
1276  return arm_cp15_get_multiprocessor_affinity() & 0xff;
1277}
1278
1279#define ARM_CORTEX_A9_ACTL_FW (1U << 0)
1280#define ARM_CORTEX_A9_ACTL_L2_PREFETCH_HINT_ENABLE (1U << 1)
1281#define ARM_CORTEX_A9_ACTL_L1_PREFETCH_ENABLE (1U << 2)
1282#define ARM_CORTEX_A9_ACTL_WRITE_FULL_LINE_OF_ZEROS_MODE (1U << 3)
1283#define ARM_CORTEX_A9_ACTL_SMP (1U << 6)
1284#define ARM_CORTEX_A9_ACTL_EXCL (1U << 7)
1285#define ARM_CORTEX_A9_ACTL_ALLOC_IN_ONE_WAY (1U << 8)
1286#define ARM_CORTEX_A9_ACTL_PARITY_ON (1U << 9)
1287
1288ARM_CP15_TEXT_SECTION static inline uint32_t
1289arm_cp15_get_auxiliary_control(void)
1290{
1291  ARM_SWITCH_REGISTERS;
1292  uint32_t val;
1293
1294  __asm__ volatile (
1295    ARM_SWITCH_TO_ARM
1296    "mrc p15, 0, %[val], c1, c0, 1\n"
1297    ARM_SWITCH_BACK
1298    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1299  );
1300
1301  return val;
1302}
1303
1304ARM_CP15_TEXT_SECTION static inline void
1305arm_cp15_set_auxiliary_control(uint32_t val)
1306{
1307  ARM_SWITCH_REGISTERS;
1308
1309  __asm__ volatile (
1310    ARM_SWITCH_TO_ARM
1311    "mcr p15, 0, %[val], c1, c0, 1\n"
1312    ARM_SWITCH_BACK
1313    : ARM_SWITCH_OUTPUT
1314    : [val] "r" (val)
1315  );
1316}
1317
1318/* ID_PFR1, Processor Feature Register 1 */
1319
1320ARM_CP15_TEXT_SECTION static inline uint32_t
1321arm_cp15_get_processor_feature_1(void)
1322{
1323  ARM_SWITCH_REGISTERS;
1324  uint32_t val;
1325
1326  __asm__ volatile (
1327    ARM_SWITCH_TO_ARM
1328    "mrc p15, 0, %[val], c0, c1, 1\n"
1329    ARM_SWITCH_BACK
1330    : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1331  );
1332
1333  return val;
1334}
1335
1336/* VBAR, Vector Base Address Register, Security Extensions */
1337
1338ARM_CP15_TEXT_SECTION static inline void
1339*arm_cp15_get_vector_base_address(void)
1340{
1341  ARM_SWITCH_REGISTERS;
1342  void *base;
1343
1344  __asm__ volatile (
1345    ARM_SWITCH_TO_ARM
1346    "mrc p15, 0, %[base], c12, c0, 0\n"
1347    ARM_SWITCH_BACK
1348    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1349  );
1350
1351  return base;
1352}
1353
1354ARM_CP15_TEXT_SECTION static inline void
1355arm_cp15_set_vector_base_address(void *base)
1356{
1357  ARM_SWITCH_REGISTERS;
1358
1359  __asm__ volatile (
1360    ARM_SWITCH_TO_ARM
1361    "mcr p15, 0, %[base], c12, c0, 0\n"
1362    ARM_SWITCH_BACK
1363    : ARM_SWITCH_OUTPUT
1364    : [base] "r" (base)
1365  );
1366}
1367
1368ARM_CP15_TEXT_SECTION static inline void
1369*arm_cp15_get_hyp_vector_base_address(void)
1370{
1371  ARM_SWITCH_REGISTERS;
1372  void *base;
1373
1374  __asm__ volatile (
1375    ARM_SWITCH_TO_ARM
1376    "mrc p15, 4, %[base], c12, c0, 0\n"
1377    ARM_SWITCH_BACK
1378    : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1379  );
1380
1381  return base;
1382}
1383
1384ARM_CP15_TEXT_SECTION static inline void
1385arm_cp15_set_hyp_vector_base_address(void *base)
1386{
1387  ARM_SWITCH_REGISTERS;
1388
1389  __asm__ volatile (
1390    ARM_SWITCH_TO_ARM
1391    "mcr p15, 4, %[base], c12, c0, 0\n"
1392    ARM_SWITCH_BACK
1393    : ARM_SWITCH_OUTPUT
1394    : [base] "r" (base)
1395  );
1396}
1397
1398/**
1399 * @brief Sets the @a section_flags for the address range [@a begin, @a end).
1400 *
1401 * @return Previous section flags of the first modified entry.
1402 */
1403uint32_t arm_cp15_set_translation_table_entries(
1404  const void *begin,
1405  const void *end,
1406  uint32_t section_flags
1407);
1408
1409void arm_cp15_set_exception_handler(
1410  Arm_symbolic_exception_name exception,
1411  void (*handler)(void)
1412);
1413
1414/** @} */
1415
1416#ifdef __cplusplus
1417}
1418#endif /* __cplusplus */
1419
1420#endif /* LIBCPU_SHARED_ARM_CP15_H */
Note: See TracBrowser for help on using the repository browser.