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

5
Last change on this file since 19a9090 was 19a9090, checked in by Pavel Pisa <pisa@…>, on 06/30/16 at 22:05:33

arm/score and shared: define ARM hypervisor mode and alternate vector table base access.

The main reason for inclusion of minimum hypervisor related defines
is that current ARM boards firmware and loaders (U-boot for example)
start loaded operating system kernel in HYP mode to allow it take
control of virtualization (Linux/KVM for example).

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