Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:23

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreCPUARMCP15
0007  *
0008  * @brief ARM co-processor 15 (CP15) API.
0009  */
0010 
0011 /*
0012  * Copyright (c) 2013 Hesham AL-Matary
0013  * Copyright (C) 2009, 2017 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #ifndef LIBCPU_SHARED_ARM_CP15_H
0038 #define LIBCPU_SHARED_ARM_CP15_H
0039 
0040 #include <rtems.h>
0041 
0042 #ifdef __cplusplus
0043 extern "C" {
0044 #endif /* __cplusplus */
0045 
0046 /*
0047  * Allow users of this header file to optionally place the inline functions
0048  * into a non-standard section.
0049  */
0050 #ifndef ARM_CP15_TEXT_SECTION
0051   #define ARM_CP15_TEXT_SECTION
0052 #endif
0053 
0054 #define ARM_CP15_CACHE_PREPARE_MVA(mva) \
0055   ((const void *) (((uint32_t) (mva)) & ~0x1fU))
0056 
0057 #define ARM_CP15_TLB_PREPARE_MVA(mva) \
0058   ((const void *) (((uint32_t) (mva)) & ~0x3fU))
0059 
0060 /**
0061  * @defgroup RTEMSScoreCPUARMCP15 ARM Co-Processor 15 Support
0062  *
0063  * @ingroup RTEMSScoreCPUARM
0064  *
0065  * @brief ARM co-processor 15 (CP15) support.
0066  *
0067  * @{
0068  */
0069 
0070 /**
0071  * @name MMU Defines
0072  *
0073  * See section B3.8.2, "Short-descriptor format memory region attributes,
0074  * without TEX remap" in the "ARM Architecture Reference Manual ARMv7-A and
0075  * ARMv7-R edition".
0076  *
0077  * @{
0078  */
0079 
0080 #define ARM_MMU_SECT_BASE_SHIFT 20
0081 #define ARM_MMU_SECT_BASE_MASK (0xfffU << ARM_MMU_SECT_BASE_SHIFT)
0082 #define ARM_MMU_SECT_NS (1U << 19)
0083 #define ARM_MMU_SECT_NG (1U << 17)
0084 #define ARM_MMU_SECT_S (1U << 16)
0085 #define ARM_MMU_SECT_AP_2 (1U << 15)
0086 #define ARM_MMU_SECT_TEX_2 (1U << 14)
0087 #define ARM_MMU_SECT_TEX_1 (1U << 13)
0088 #define ARM_MMU_SECT_TEX_0 (1U << 12)
0089 #define ARM_MMU_SECT_TEX_SHIFT 12
0090 #define ARM_MMU_SECT_TEX_MASK (0x3U << ARM_MMU_SECT_TEX_SHIFT)
0091 #define ARM_MMU_SECT_AP_1 (1U << 11)
0092 #define ARM_MMU_SECT_AP_0 (1U << 10)
0093 #define ARM_MMU_SECT_AP_SHIFT 10
0094 #define ARM_MMU_SECT_AP_MASK (0x23U << ARM_MMU_SECT_AP_SHIFT)
0095 #define ARM_MMU_SECT_DOMAIN_SHIFT 5
0096 #define ARM_MMU_SECT_DOMAIN_MASK (0xfU << ARM_MMU_SECT_DOMAIN_SHIFT)
0097 #define ARM_MMU_SECT_XN (1U << 4)
0098 #define ARM_MMU_SECT_C (1U << 3)
0099 #define ARM_MMU_SECT_B (1U << 2)
0100 #define ARM_MMU_SECT_PXN (1U << 0)
0101 #define ARM_MMU_SECT_DEFAULT 0x2U
0102 #define ARM_MMU_SECT_GET_INDEX(mva) \
0103   (((uint32_t) (mva)) >> ARM_MMU_SECT_BASE_SHIFT)
0104 #define ARM_MMU_SECT_MVA_ALIGN_UP(mva) \
0105   ((1U << ARM_MMU_SECT_BASE_SHIFT) \
0106     + ((((uint32_t) (mva) - 1U)) & ~((1U << ARM_MMU_SECT_BASE_SHIFT) - 1U)))
0107 
0108 #define ARM_MMU_PAGE_TABLE_BASE_SHIFT 10
0109 #define ARM_MMU_PAGE_TABLE_BASE_MASK (0x3fffffU << ARM_MMU_PAGE_TABLE_BASE_SHIFT)
0110 #define ARM_MMU_PAGE_TABLE_DOMAIN_SHIFT 5
0111 #define ARM_MMU_PAGE_TABLE_DOMAIN_MASK (0xfU << ARM_MMU_PAGE_TABLE_DOMAIN_SHIFT)
0112 #define ARM_MMU_PAGE_TABLE_NS (1U << 3)
0113 #define ARM_MMU_PAGE_TABLE_PXN (1U << 2)
0114 #define ARM_MMU_PAGE_TABLE_DEFAULT 0x1U
0115 
0116 #define ARM_MMU_SMALL_PAGE_BASE_SHIFT 12
0117 #define ARM_MMU_SMALL_PAGE_BASE_MASK (0xfffffU << ARM_MMU_SMALL_PAGE_BASE_SHIFT)
0118 #define ARM_MMU_SMALL_PAGE_NG (1U << 11)
0119 #define ARM_MMU_SMALL_PAGE_S (1U << 10)
0120 #define ARM_MMU_SMALL_PAGE_AP_2 (1U << 9)
0121 #define ARM_MMU_SMALL_PAGE_TEX_2 (1U << 8)
0122 #define ARM_MMU_SMALL_PAGE_TEX_1 (1U << 7)
0123 #define ARM_MMU_SMALL_PAGE_TEX_0 (1U << 6)
0124 #define ARM_MMU_SMALL_PAGE_TEX_SHIFT 6
0125 #define ARM_MMU_SMALL_PAGE_TEX_MASK (0x3U << ARM_MMU_SMALL_PAGE_TEX_SHIFT)
0126 #define ARM_MMU_SMALL_PAGE_AP_1 (1U << 5)
0127 #define ARM_MMU_SMALL_PAGE_AP_0 (1U << 4)
0128 #define ARM_MMU_SMALL_PAGE_AP_SHIFT 4
0129 #define ARM_MMU_SMALL_PAGE_AP_MASK (0x23U << ARM_MMU_SMALL_PAGE_AP_SHIFT)
0130 #define ARM_MMU_SMALL_PAGE_C (1U << 3)
0131 #define ARM_MMU_SMALL_PAGE_B (1U << 2)
0132 #define ARM_MMU_SMALL_PAGE_XN (1U << 0)
0133 #define ARM_MMU_SMALL_PAGE_DEFAULT 0x2U
0134 #define ARM_MMU_SMALL_PAGE_GET_INDEX(mva) \
0135   (((uint32_t) (mva)) >> ARM_MMU_SMALL_PAGE_BASE_SHIFT)
0136 #define ARM_MMU_SMALL_PAGE_MVA_ALIGN_UP(mva) \
0137   ((1U << ARM_MMU_SMALL_PAGE_BASE_SHIFT) \
0138     + ((((uint32_t) (mva) - 1U)) & ~((1U << ARM_MMU_SMALL_PAGE_BASE_SHIFT) - 1U)))
0139 
0140 #define ARM_MMU_SECT_FLAGS_TO_PAGE_TABLE(flags) \
0141   (ARM_MMU_PAGE_TABLE_DEFAULT \
0142     | ((flags) & ARM_MMU_SECT_DOMAIN_MASK) \
0143     | (((flags) & ARM_MMU_SECT_NS) >> 16) \
0144     | (((flags) & ARM_MMU_SECT_PXN) << 2))
0145 
0146 #define ARM_MMU_PAGE_TABLE_FLAGS_TO_SECT(flags) \
0147   (ARM_MMU_SECT_DEFAULT \
0148     | ((flags) & ARM_MMU_PAGE_TABLE_DOMAIN_MASK) \
0149     | (((flags) & ARM_MMU_PAGE_TABLE_NS) << 16) \
0150     | (((flags) & ARM_MMU_PAGE_TABLE_PXN) >> 2))
0151 
0152 #define ARM_MMU_SECT_FLAGS_TO_SMALL_PAGE(flags) \
0153   ((((flags) & 0x3fc00) >> 6) \
0154     | ((flags) & (ARM_MMU_SECT_C | ARM_MMU_SECT_B | 0x2)) \
0155     | (((flags) & ARM_MMU_SECT_XN) >> 4))
0156 
0157 #define ARM_MMU_SMALL_PAGE_FLAGS_TO_SECT(flags) \
0158   ((((flags) & 0xff0) << 6) \
0159     | ((flags) & (ARM_MMU_SMALL_PAGE_C | ARM_MMU_SMALL_PAGE_B | 0x2)) \
0160     | (((flags) & ARM_MMU_SMALL_PAGE_XN) << 4))
0161 
0162 #define ARM_MMU_TRANSLATION_TABLE_ENTRY_SIZE 4U
0163 #define ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT 4096U
0164 
0165 #define ARM_MMU_SMALL_PAGE_TABLE_ENTRY_SIZE 4U
0166 #define ARM_MMU_SMALL_PAGE_TABLE_ENTRY_COUNT 256U
0167 
0168 #define ARM_MMU_DEFAULT_CLIENT_DOMAIN 15U
0169 
0170 #define ARMV7_MMU_READ_ONLY \
0171   ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
0172     | ARM_MMU_SECT_AP_0 \
0173     | ARM_MMU_SECT_AP_2 \
0174     | ARM_MMU_SECT_DEFAULT)
0175 
0176 #define ARMV7_MMU_READ_ONLY_CACHED \
0177   (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
0178 
0179 #define ARMV7_MMU_READ_WRITE \
0180   ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
0181     | ARM_MMU_SECT_AP_0 \
0182     | ARM_MMU_SECT_DEFAULT)
0183 
0184 #ifdef RTEMS_SMP
0185   #define ARMV7_MMU_READ_WRITE_CACHED \
0186     (ARMV7_MMU_READ_WRITE \
0187       | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B | ARM_MMU_SECT_S)
0188 #else
0189   #define ARMV7_MMU_READ_WRITE_CACHED \
0190     (ARMV7_MMU_READ_WRITE \
0191       | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
0192 #endif
0193 
0194 #define ARMV7_MMU_DATA_READ_ONLY \
0195   (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0)
0196 
0197 #define ARMV7_MMU_DATA_READ_ONLY_CACHED \
0198   ARMV7_MMU_READ_ONLY_CACHED
0199 
0200 #define ARMV7_MMU_DATA_READ_WRITE \
0201   (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_TEX_0)
0202 
0203 #define ARMV7_MMU_DATA_READ_WRITE_CACHED \
0204   ARMV7_MMU_READ_WRITE_CACHED
0205 
0206 #define ARMV7_MMU_CODE \
0207   (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0)
0208 
0209 #define ARMV7_MMU_CODE_CACHED \
0210   ARMV7_MMU_READ_ONLY_CACHED
0211 
0212 #define ARMV7_MMU_DEVICE \
0213   (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_B)
0214 
0215 /** @} */
0216 
0217 /**
0218  * @name Control Register Defines
0219  *
0220  * @{
0221  */
0222 
0223 #define ARM_CP15_CTRL_TE (1U << 30)
0224 #define ARM_CP15_CTRL_AFE (1U << 29)
0225 #define ARM_CP15_CTRL_TRE (1U << 28)
0226 #define ARM_CP15_CTRL_NMFI (1U << 27)
0227 #define ARM_CP15_CTRL_EE (1U << 25)
0228 #define ARM_CP15_CTRL_VE (1U << 24)
0229 #define ARM_CP15_CTRL_XP (1U << 23)
0230 #define ARM_CP15_CTRL_U (1U << 22)
0231 #define ARM_CP15_CTRL_FI (1U << 21)
0232 #define ARM_CP15_CTRL_UWXN (1U << 20)
0233 #define ARM_CP15_CTRL_WXN (1U << 19)
0234 #define ARM_CP15_CTRL_HA (1U << 17)
0235 #define ARM_CP15_CTRL_L4 (1U << 15)
0236 #define ARM_CP15_CTRL_RR (1U << 14)
0237 #define ARM_CP15_CTRL_V (1U << 13)
0238 #define ARM_CP15_CTRL_I (1U << 12)
0239 #define ARM_CP15_CTRL_Z (1U << 11)
0240 #define ARM_CP15_CTRL_SW (1U << 10)
0241 #define ARM_CP15_CTRL_R (1U << 9)
0242 #define ARM_CP15_CTRL_S (1U << 8)
0243 #define ARM_CP15_CTRL_B (1U << 7)
0244 #define ARM_CP15_CTRL_CP15BEN (1U << 5)
0245 #define ARM_CP15_CTRL_C (1U << 2)
0246 #define ARM_CP15_CTRL_A (1U << 1)
0247 #define ARM_CP15_CTRL_M (1U << 0)
0248 
0249 /** @} */
0250 
0251 /**
0252  * @name Domain Access Control Defines
0253  *
0254  * @{
0255  */
0256 
0257 #define ARM_CP15_DAC_NO_ACCESS 0x0U
0258 #define ARM_CP15_DAC_CLIENT 0x1U
0259 #define ARM_CP15_DAC_MANAGER 0x3U
0260 #define ARM_CP15_DAC_DOMAIN(index, val) ((val) << (2 * index))
0261 
0262 /** @} */
0263 
0264 /**
0265  * @name Fault Status Register Defines
0266  *
0267  * @{
0268  */
0269 
0270 #define ARM_CP15_FAULT_STATUS_MASK 0x040F
0271 
0272 #define ARM_CP15_FSR_ALIGNMENT_FAULT   0x00000001
0273 #define ARM_CP15_FSR_BACKGROUND_FAULT  0x0000
0274 #define ARM_CP15_FSR_ACCESS_PERMISSION_FAULT 0x000D
0275 #define ARM_CP15_FSR_PRECISE_EXTERNAL_ABORT_FAULT 0x0008
0276 #define ARM_CP15_FSR_IMPRECISE_EXTERNAL_ABORT_FAULT 0x0406
0277 #define ARM_CP15_FSR_PRECISE_PARITY_ERROR_EXCEPTION 0x0006
0278 #define ARM_CP15_FSR_IMPRECISE_PARITY_ERROR_EXCEPTION 0x0408
0279 #define ARM_CP15_FSR_DEBUG_EVENT 0x0002
0280 
0281 /** @} */
0282 
0283 /**
0284  * @name CTR, Cache Type Register Defines
0285  *
0286  * The format can be obtained from CP15 by call
0287  * arm_cp15_cache_type_get_format(arm_cp15_get_cache_type());
0288  *
0289  * @{
0290  */
0291 
0292 #define ARM_CP15_CACHE_TYPE_FORMAT_ARMV6 0
0293 #define ARM_CP15_CACHE_TYPE_FORMAT_ARMV7 4
0294 
0295 /** @} */
0296 
0297 /**
0298  * @name CCSIDR, Cache Size ID Register Defines
0299  *
0300  * @{
0301  */
0302 
0303 #define ARM_CP15_CACHE_CSS_ID_DATA 0
0304 #define ARM_CP15_CACHE_CSS_ID_INSTRUCTION 1
0305 #define ARM_CP15_CACHE_CSS_LEVEL(level) ((level) << 1)
0306 
0307 /** @} */
0308 
0309 ARM_CP15_TEXT_SECTION static inline uint32_t
0310 arm_cp15_get_id_code(void)
0311 {
0312   ARM_SWITCH_REGISTERS;
0313   uint32_t val;
0314 
0315   __asm__ volatile (
0316     ARM_SWITCH_TO_ARM
0317     "mrc p15, 0, %[val], c0, c0, 0\n"
0318     ARM_SWITCH_BACK
0319     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0320   );
0321 
0322   return val;
0323 }
0324 
0325 ARM_CP15_TEXT_SECTION static inline uint32_t
0326 arm_cp15_get_tcm_status(void)
0327 {
0328   ARM_SWITCH_REGISTERS;
0329   uint32_t val;
0330 
0331   __asm__ volatile (
0332     ARM_SWITCH_TO_ARM
0333     "mrc p15, 0, %[val], c0, c0, 2\n"
0334     ARM_SWITCH_BACK
0335     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0336   );
0337 
0338   return val;
0339 }
0340 
0341 ARM_CP15_TEXT_SECTION static inline uint32_t
0342 arm_cp15_get_control(void)
0343 {
0344   ARM_SWITCH_REGISTERS;
0345   uint32_t val;
0346 
0347   __asm__ volatile (
0348     ARM_SWITCH_TO_ARM
0349     "mrc p15, 0, %[val], c1, c0, 0\n"
0350     ARM_SWITCH_BACK
0351     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0352   );
0353 
0354   return val;
0355 }
0356 
0357 ARM_CP15_TEXT_SECTION static inline void
0358 arm_cp15_set_control(uint32_t val)
0359 {
0360   ARM_SWITCH_REGISTERS;
0361 
0362   __asm__ volatile (
0363     ARM_SWITCH_TO_ARM
0364     "mcr p15, 0, %[val], c1, c0, 0\n"
0365     "nop\n"
0366     "nop\n"
0367     ARM_SWITCH_BACK
0368     : ARM_SWITCH_OUTPUT
0369     : [val] "r" (val)
0370     : "memory"
0371   );
0372 }
0373 
0374 /**
0375  * @name MMU Functions
0376  *
0377  * @{
0378  */
0379 
0380 /**
0381  * @brief Disable the MMU.
0382  *
0383  * This function will clean and invalidate eight cache lines before and after
0384  * the current stack pointer.
0385  *
0386  * @param[in] cls The data cache line size.
0387  *
0388  * @return The current control register value.
0389  */
0390 ARM_CP15_TEXT_SECTION static inline uint32_t
0391 arm_cp15_mmu_disable(uint32_t cls)
0392 {
0393   ARM_SWITCH_REGISTERS;
0394   uint32_t ctrl;
0395   uint32_t tmp_0;
0396   uint32_t tmp_1;
0397 
0398   __asm__ volatile (
0399     ARM_SWITCH_TO_ARM
0400     "mrc p15, 0, %[ctrl], c1, c0, 0\n"
0401     "bic %[tmp_0], %[ctrl], #1\n"
0402     "mcr p15, 0, %[tmp_0], c1, c0, 0\n"
0403     "nop\n"
0404     "nop\n"
0405     "mov %[tmp_1], sp\n"
0406     "rsb %[tmp_0], %[cls], #0\n"
0407     "and %[tmp_0], %[tmp_0], %[tmp_1]\n"
0408     "sub %[tmp_0], %[tmp_0], %[cls], asl #3\n"
0409     "add %[tmp_1], %[tmp_0], %[cls], asl #4\n"
0410     "1:\n"
0411     "mcr p15, 0, %[tmp_0], c7, c14, 1\n"
0412     "add %[tmp_0], %[tmp_0], %[cls]\n"
0413     "cmp %[tmp_1], %[tmp_0]\n"
0414     "bne 1b\n"
0415     ARM_SWITCH_BACK
0416     : [ctrl] "=&r" (ctrl),
0417       [tmp_0] "=&r" (tmp_0),
0418       [tmp_1] "=&r" (tmp_1)
0419       ARM_SWITCH_ADDITIONAL_OUTPUT
0420     : [cls] "r" (cls)
0421     : "memory", "cc"
0422   );
0423 
0424   return ctrl;
0425 }
0426 
0427 ARM_CP15_TEXT_SECTION static inline uint32_t
0428 *arm_cp15_get_translation_table_base(void)
0429 {
0430   ARM_SWITCH_REGISTERS;
0431   uint32_t *base;
0432 
0433   __asm__ volatile (
0434     ARM_SWITCH_TO_ARM
0435     "mrc p15, 0, %[base], c2, c0, 0\n"
0436     ARM_SWITCH_BACK
0437     : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
0438   );
0439 
0440   return base;
0441 }
0442 
0443 ARM_CP15_TEXT_SECTION static inline void
0444 arm_cp15_set_translation_table_base(uint32_t *base)
0445 {
0446   ARM_SWITCH_REGISTERS;
0447 
0448   __asm__ volatile (
0449     ARM_SWITCH_TO_ARM
0450     "mcr p15, 0, %[base], c2, c0, 0\n"
0451     ARM_SWITCH_BACK
0452     : ARM_SWITCH_OUTPUT
0453     : [base] "r" (base)
0454   );
0455 }
0456 
0457 /* Translation Table Base Control Register - DDI0301H arm1176jzfs TRM 3.2.15 */
0458 ARM_CP15_TEXT_SECTION static inline uint32_t
0459 arm_cp15_get_translation_table_base_control_register(void)
0460 {
0461   ARM_SWITCH_REGISTERS;
0462   uint32_t ttb_cr;
0463 
0464   __asm__ volatile (
0465     ARM_SWITCH_TO_ARM
0466     "mrc p15, 0, %[ttb_cr], c2, c0, 2\n"
0467     ARM_SWITCH_BACK
0468     : [ttb_cr] "=&r" (ttb_cr) ARM_SWITCH_ADDITIONAL_OUTPUT
0469   );
0470 
0471   return ttb_cr;
0472 }
0473 
0474 ARM_CP15_TEXT_SECTION static inline void
0475 arm_cp15_set_translation_table_base_control_register(uint32_t ttb_cr)
0476 {
0477   ARM_SWITCH_REGISTERS;
0478 
0479   __asm__ volatile (
0480     ARM_SWITCH_TO_ARM
0481     "mcr p15, 0, %[ttb_cr], c2, c0, 2\n"
0482     ARM_SWITCH_BACK
0483     : ARM_SWITCH_OUTPUT
0484     : [ttb_cr] "r" (ttb_cr)
0485   );
0486 }
0487 
0488 ARM_CP15_TEXT_SECTION static inline uint32_t
0489 arm_cp15_get_domain_access_control(void)
0490 {
0491   ARM_SWITCH_REGISTERS;
0492   uint32_t val;
0493 
0494   __asm__ volatile (
0495     ARM_SWITCH_TO_ARM
0496     "mrc p15, 0, %[val], c3, c0, 0\n"
0497     ARM_SWITCH_BACK
0498     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0499   );
0500 
0501   return val;
0502 }
0503 
0504 ARM_CP15_TEXT_SECTION static inline void
0505 arm_cp15_set_domain_access_control(uint32_t val)
0506 {
0507   ARM_SWITCH_REGISTERS;
0508 
0509   __asm__ volatile (
0510     ARM_SWITCH_TO_ARM
0511     "mcr p15, 0, %[val], c3, c0, 0\n"
0512     ARM_SWITCH_BACK
0513     : ARM_SWITCH_OUTPUT
0514     : [val] "r" (val)
0515   );
0516 }
0517 
0518 ARM_CP15_TEXT_SECTION static inline uint32_t
0519 arm_cp15_get_data_fault_status(void)
0520 {
0521   ARM_SWITCH_REGISTERS;
0522   uint32_t val;
0523 
0524   __asm__ volatile (
0525     ARM_SWITCH_TO_ARM
0526     "mrc p15, 0, %[val], c5, c0, 0\n"
0527     ARM_SWITCH_BACK
0528     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0529   );
0530 
0531   return val;
0532 }
0533 
0534 ARM_CP15_TEXT_SECTION static inline void
0535 arm_cp15_set_data_fault_status(uint32_t val)
0536 {
0537   ARM_SWITCH_REGISTERS;
0538 
0539   __asm__ volatile (
0540     ARM_SWITCH_TO_ARM
0541     "mcr p15, 0, %[val], c5, c0, 0\n"
0542     ARM_SWITCH_BACK
0543     : ARM_SWITCH_OUTPUT
0544     : [val] "r" (val)
0545   );
0546 }
0547 
0548 ARM_CP15_TEXT_SECTION static inline uint32_t
0549 arm_cp15_get_instruction_fault_status(void)
0550 {
0551   ARM_SWITCH_REGISTERS;
0552   uint32_t val;
0553 
0554   __asm__ volatile (
0555     ARM_SWITCH_TO_ARM
0556     "mrc p15, 0, %[val], c5, c0, 1\n"
0557     ARM_SWITCH_BACK
0558     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0559   );
0560 
0561   return val;
0562 }
0563 
0564 ARM_CP15_TEXT_SECTION static inline void
0565 arm_cp15_set_instruction_fault_status(uint32_t val)
0566 {
0567   ARM_SWITCH_REGISTERS;
0568 
0569   __asm__ volatile (
0570     ARM_SWITCH_TO_ARM
0571     "mcr p15, 0, %[val], c5, c0, 1\n"
0572     ARM_SWITCH_BACK
0573     : ARM_SWITCH_OUTPUT
0574     : [val] "r" (val)
0575   );
0576 }
0577 
0578 ARM_CP15_TEXT_SECTION static inline void
0579 *arm_cp15_get_fault_address(void)
0580 {
0581   ARM_SWITCH_REGISTERS;
0582   void *mva;
0583 
0584   __asm__ volatile (
0585     ARM_SWITCH_TO_ARM
0586     "mrc p15, 0, %[mva], c6, c0, 0\n"
0587     ARM_SWITCH_BACK
0588     : [mva] "=&r" (mva) ARM_SWITCH_ADDITIONAL_OUTPUT
0589   );
0590 
0591   return mva;
0592 }
0593 
0594 ARM_CP15_TEXT_SECTION static inline void
0595 arm_cp15_set_fault_address(const void *mva)
0596 {
0597   ARM_SWITCH_REGISTERS;
0598 
0599   __asm__ volatile (
0600     ARM_SWITCH_TO_ARM
0601     "mcr p15, 0, %[mva], c6, c0, 0\n"
0602     ARM_SWITCH_BACK
0603     : ARM_SWITCH_OUTPUT
0604     : [mva] "r" (mva)
0605   );
0606 }
0607 
0608 ARM_CP15_TEXT_SECTION static inline void
0609 arm_cp15_tlb_invalidate(void)
0610 {
0611   ARM_SWITCH_REGISTERS;
0612   uint32_t sbz = 0;
0613 
0614   __asm__ volatile (
0615     ARM_SWITCH_TO_ARM
0616     "mcr p15, 0, %[sbz], c8, c7, 0\n"
0617     ARM_SWITCH_BACK
0618     : ARM_SWITCH_OUTPUT
0619     : [sbz] "r" (sbz)
0620   );
0621 
0622   /*
0623    * ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, Issue C,
0624    * B3.10.1 General TLB maintenance requirements.
0625    */
0626   _ARM_Data_synchronization_barrier();
0627   _ARM_Instruction_synchronization_barrier();
0628 }
0629 
0630 ARM_CP15_TEXT_SECTION static inline void
0631 arm_cp15_tlb_invalidate_entry(const void *mva)
0632 {
0633   ARM_SWITCH_REGISTERS;
0634 
0635   mva = ARM_CP15_TLB_PREPARE_MVA(mva);
0636 
0637   __asm__ volatile (
0638     ARM_SWITCH_TO_ARM
0639     "mcr p15, 0, %[mva], c8, c7, 1\n"
0640     ARM_SWITCH_BACK
0641     : ARM_SWITCH_OUTPUT
0642     : [mva] "r" (mva)
0643   );
0644 }
0645 
0646 ARM_CP15_TEXT_SECTION static inline void
0647 arm_cp15_tlb_invalidate_entry_all_asids(const void *mva)
0648 {
0649   ARM_SWITCH_REGISTERS;
0650 
0651   mva = ARM_CP15_TLB_PREPARE_MVA(mva);
0652 
0653   __asm__ volatile (
0654     ARM_SWITCH_TO_ARM
0655     "mcr p15, 0, %[mva], c8, c7, 3\n"
0656     ARM_SWITCH_BACK
0657     : ARM_SWITCH_OUTPUT
0658     : [mva] "r" (mva)
0659   );
0660 }
0661 
0662 ARM_CP15_TEXT_SECTION static inline void
0663 arm_cp15_tlb_invalidate_entry_all_asids_inner_shareable(const void *mva)
0664 {
0665   ARM_SWITCH_REGISTERS;
0666 
0667   mva = ARM_CP15_TLB_PREPARE_MVA(mva);
0668 
0669   __asm__ volatile (
0670     ARM_SWITCH_TO_ARM
0671     "mcr p15, 0, %[mva], c8, c3, 3\n"
0672     ARM_SWITCH_BACK
0673     : ARM_SWITCH_OUTPUT
0674     : [mva] "r" (mva)
0675   );
0676 }
0677 
0678 ARM_CP15_TEXT_SECTION static inline void
0679 arm_cp15_tlb_instruction_invalidate(void)
0680 {
0681   ARM_SWITCH_REGISTERS;
0682   uint32_t sbz = 0;
0683 
0684   __asm__ volatile (
0685     ARM_SWITCH_TO_ARM
0686     "mcr p15, 0, %[sbz], c8, c5, 0\n"
0687     ARM_SWITCH_BACK
0688     : ARM_SWITCH_OUTPUT
0689     : [sbz] "r" (sbz)
0690   );
0691 }
0692 
0693 ARM_CP15_TEXT_SECTION static inline void
0694 arm_cp15_tlb_instruction_invalidate_entry(const void *mva)
0695 {
0696   ARM_SWITCH_REGISTERS;
0697 
0698   mva = ARM_CP15_TLB_PREPARE_MVA(mva);
0699 
0700   __asm__ volatile (
0701     ARM_SWITCH_TO_ARM
0702     "mcr p15, 0, %[mva], c8, c5, 1\n"
0703     ARM_SWITCH_BACK
0704     : ARM_SWITCH_OUTPUT
0705     : [mva] "r" (mva)
0706   );
0707 }
0708 
0709 ARM_CP15_TEXT_SECTION static inline void
0710 arm_cp15_tlb_data_invalidate(void)
0711 {
0712   ARM_SWITCH_REGISTERS;
0713   uint32_t sbz = 0;
0714 
0715   __asm__ volatile (
0716     ARM_SWITCH_TO_ARM
0717     "mcr p15, 0, %[sbz], c8, c6, 0\n"
0718     ARM_SWITCH_BACK
0719     : ARM_SWITCH_OUTPUT
0720     : [sbz] "r" (sbz)
0721   );
0722 }
0723 
0724 ARM_CP15_TEXT_SECTION static inline void
0725 arm_cp15_tlb_data_invalidate_entry(const void *mva)
0726 {
0727   ARM_SWITCH_REGISTERS;
0728 
0729   mva = ARM_CP15_TLB_PREPARE_MVA(mva);
0730 
0731   __asm__ volatile (
0732     ARM_SWITCH_TO_ARM
0733     "mcr p15, 0, %[mva], c8, c6, 1\n"
0734     ARM_SWITCH_BACK
0735     : ARM_SWITCH_OUTPUT
0736     : [mva] "r" (mva)
0737   );
0738 }
0739 
0740 ARM_CP15_TEXT_SECTION static inline void
0741 arm_cp15_tlb_lockdown_entry(const void *mva)
0742 {
0743   uint32_t arm_switch_reg;
0744 
0745   __asm__ volatile (
0746     ARM_SWITCH_TO_ARM
0747     "add %[arm_switch_reg], pc, #16\n"
0748     "mcr p15, 0, %[arm_switch_reg], c7, c13, 1\n"
0749     "mcr p15, 0, %[mva], c8, c7, 1\n"
0750     "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
0751     "orr %[arm_switch_reg], #0x1\n"
0752     "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
0753     "ldr %[mva], [%[mva]]\n"
0754     "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
0755     "bic %[arm_switch_reg], #0x1\n"
0756     "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
0757     ARM_SWITCH_BACK
0758     : [mva] "=r" (mva), [arm_switch_reg] "=&r" (arm_switch_reg)
0759     : "[mva]" (mva)
0760   );
0761 }
0762 
0763 /** @} */
0764 
0765 /**
0766  * @name Cache Functions
0767  *
0768  * @{
0769  */
0770 
0771 /* Read cache type register CTR */
0772 ARM_CP15_TEXT_SECTION static inline uint32_t
0773 arm_cp15_get_cache_type(void)
0774 {
0775   ARM_SWITCH_REGISTERS;
0776   uint32_t val;
0777 
0778   __asm__ volatile (
0779     ARM_SWITCH_TO_ARM
0780     "mrc p15, 0, %[val], c0, c0, 1\n"
0781     ARM_SWITCH_BACK
0782     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0783   );
0784 
0785   return val;
0786 }
0787 
0788 /* Extract format version from cache type CTR */
0789 ARM_CP15_TEXT_SECTION static inline int
0790 arm_cp15_cache_type_get_format(uint32_t ct)
0791 {
0792   return (ct >> 29) & 0x7U;
0793 }
0794 
0795 /* Read size of smallest cache line of all instruction/data caches controlled by the processor */
0796 ARM_CP15_TEXT_SECTION static inline uint32_t
0797 arm_cp15_get_min_cache_line_size(void)
0798 {
0799   uint32_t mcls = 0;
0800   uint32_t ct = arm_cp15_get_cache_type();
0801   uint32_t format = arm_cp15_cache_type_get_format(ct);
0802 
0803   if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
0804     /* ARMv7 format */
0805     mcls = (1U << (ct & 0xf)) * 4;
0806   } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
0807     /* ARMv6 format */
0808     uint32_t mask = (1U << 12) - 1;
0809     uint32_t dcls = (ct >> 12) & mask;
0810     uint32_t icls = ct & mask;
0811 
0812     mcls = dcls <= icls ? dcls : icls;
0813   }
0814 
0815   return mcls;
0816 }
0817 
0818 /* Read size of smallest data cache lines */
0819 ARM_CP15_TEXT_SECTION static inline uint32_t
0820 arm_cp15_get_data_cache_line_size(void)
0821 {
0822   uint32_t mcls = 0;
0823   uint32_t ct = arm_cp15_get_cache_type();
0824   uint32_t format = arm_cp15_cache_type_get_format(ct);
0825 
0826   if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
0827     /* ARMv7 format */
0828     mcls = (1U << ((ct & 0xf0000) >> 16)) * 4;
0829   } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
0830     /* ARMv6 format */
0831     uint32_t mask = (1U << 12) - 1;
0832     mcls = (ct >> 12) & mask;
0833   }
0834 
0835   return mcls;
0836 }
0837 
0838 /* Read size of smallest instruction cache lines */
0839 ARM_CP15_TEXT_SECTION static inline uint32_t
0840 arm_cp15_get_instruction_cache_line_size(void)
0841 {
0842   uint32_t mcls = 0;
0843   uint32_t ct = arm_cp15_get_cache_type();
0844   uint32_t format = arm_cp15_cache_type_get_format(ct);
0845 
0846   if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
0847     /* ARMv7 format */
0848     mcls = (1U << (ct & 0x0000f)) * 4;
0849   } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
0850     /* ARMv6 format */
0851     uint32_t mask = (1U << 12) - 1;
0852     mcls = ct & mask;;
0853   }
0854 
0855   return mcls;
0856 }
0857 
0858 /* CCSIDR, Cache Size ID Register */
0859 
0860 ARM_CP15_TEXT_SECTION static inline uint32_t
0861 arm_cp15_get_cache_size_id(void)
0862 {
0863   ARM_SWITCH_REGISTERS;
0864   uint32_t val;
0865 
0866   __asm__ volatile (
0867     ARM_SWITCH_TO_ARM
0868     "mrc p15, 1, %[val], c0, c0, 0\n"
0869      ARM_SWITCH_BACK
0870     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0871   );
0872 
0873   return val;
0874 }
0875 
0876 ARM_CP15_TEXT_SECTION static inline uint32_t
0877 arm_ccsidr_get_line_power(uint32_t ccsidr)
0878 {
0879   return (ccsidr & 0x7) + 4;
0880 }
0881 
0882 ARM_CP15_TEXT_SECTION static inline uint32_t
0883 arm_ccsidr_get_associativity(uint32_t ccsidr)
0884 {
0885   return ((ccsidr >> 3) & 0x3ff) + 1;
0886 }
0887 
0888 ARM_CP15_TEXT_SECTION static inline uint32_t
0889 arm_ccsidr_get_num_sets(uint32_t ccsidr)
0890 {
0891   return ((ccsidr >> 13) & 0x7fff) + 1;
0892 }
0893 
0894 /* CLIDR, Cache Level ID Register */
0895 
0896 ARM_CP15_TEXT_SECTION static inline uint32_t
0897 arm_cp15_get_cache_level_id(void)
0898 {
0899   ARM_SWITCH_REGISTERS;
0900   uint32_t val;
0901 
0902   __asm__ volatile (
0903     ARM_SWITCH_TO_ARM
0904     "mrc p15, 1, %[val], c0, c0, 1\n"
0905      ARM_SWITCH_BACK
0906     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0907   );
0908 
0909   return val;
0910 }
0911 
0912 ARM_CP15_TEXT_SECTION static inline uint32_t
0913 arm_clidr_get_level_of_coherency(uint32_t clidr)
0914 {
0915   return (clidr >> 24) & 0x7;
0916 }
0917 
0918 ARM_CP15_TEXT_SECTION static inline uint32_t
0919 arm_clidr_get_cache_type(uint32_t clidr, uint32_t level)
0920 {
0921   return (clidr >> (3 * level)) & 0x7;
0922 }
0923 
0924 /* CSSELR, Cache Size Selection Register */
0925 
0926 ARM_CP15_TEXT_SECTION static inline uint32_t
0927 arm_cp15_get_cache_size_selection(void)
0928 {
0929   ARM_SWITCH_REGISTERS;
0930   uint32_t val;
0931 
0932   __asm__ volatile (
0933     ARM_SWITCH_TO_ARM
0934     "mrc p15, 2, %[val], c0, c0, 0\n"
0935      ARM_SWITCH_BACK
0936     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
0937   );
0938 
0939   return val;
0940 }
0941 
0942 ARM_CP15_TEXT_SECTION static inline void
0943 arm_cp15_set_cache_size_selection(uint32_t val)
0944 {
0945   ARM_SWITCH_REGISTERS;
0946 
0947   __asm__ volatile (
0948     ARM_SWITCH_TO_ARM
0949     "mcr p15, 2, %[val], c0, c0, 0\n"
0950      ARM_SWITCH_BACK
0951     : ARM_SWITCH_OUTPUT
0952     : [val] "r" (val)
0953     : "memory"
0954   );
0955 }
0956 
0957 ARM_CP15_TEXT_SECTION static inline uint32_t
0958 arm_cp15_get_cache_size_id_for_level(uint32_t level_and_inst_dat)
0959 {
0960   rtems_interrupt_level irq_level;
0961   uint32_t ccsidr;
0962 
0963   rtems_interrupt_local_disable(irq_level);
0964   arm_cp15_set_cache_size_selection(level_and_inst_dat);
0965   _ARM_Instruction_synchronization_barrier();
0966   ccsidr = arm_cp15_get_cache_size_id();
0967   rtems_interrupt_local_enable(irq_level);
0968 
0969   return ccsidr;
0970 }
0971 
0972 ARM_CP15_TEXT_SECTION static inline void
0973 arm_cp15_cache_invalidate(void)
0974 {
0975   ARM_SWITCH_REGISTERS;
0976   uint32_t sbz = 0;
0977 
0978   __asm__ volatile (
0979     ARM_SWITCH_TO_ARM
0980     "mcr p15, 0, %[sbz], c7, c7, 0\n"
0981     ARM_SWITCH_BACK
0982     : ARM_SWITCH_OUTPUT
0983     : [sbz] "r" (sbz)
0984     : "memory"
0985   );
0986 }
0987 
0988 /* ICIALLUIS, Instruction Cache Invalidate All to PoU, Inner Shareable */
0989 
0990 ARM_CP15_TEXT_SECTION static inline void
0991 arm_cp15_instruction_cache_inner_shareable_invalidate_all(void)
0992 {
0993   ARM_SWITCH_REGISTERS;
0994   uint32_t sbz = 0;
0995 
0996   __asm__ volatile (
0997     ARM_SWITCH_TO_ARM
0998     "mcr p15, 0, %[sbz], c7, c1, 0\n"
0999     ARM_SWITCH_BACK
1000     : ARM_SWITCH_OUTPUT
1001     : [sbz] "r" (sbz)
1002     : "memory"
1003   );
1004 }
1005 
1006 /* BPIALLIS, Branch Predictor Invalidate All, Inner Shareable */
1007 
1008 ARM_CP15_TEXT_SECTION static inline void
1009 arm_cp15_branch_predictor_inner_shareable_invalidate_all(void)
1010 {
1011   ARM_SWITCH_REGISTERS;
1012   uint32_t sbz = 0;
1013 
1014   __asm__ volatile (
1015     ARM_SWITCH_TO_ARM
1016     "mcr p15, 0, %[sbz], c7, c1, 6\n"
1017     ARM_SWITCH_BACK
1018     : ARM_SWITCH_OUTPUT
1019     : [sbz] "r" (sbz)
1020     : "memory"
1021   );
1022 }
1023 
1024 /* BPIALL, Branch Predictor Invalidate All */
1025 
1026 ARM_CP15_TEXT_SECTION static inline void
1027 arm_cp15_branch_predictor_invalidate_all(void)
1028 {
1029   ARM_SWITCH_REGISTERS;
1030   uint32_t sbz = 0;
1031 
1032   __asm__ volatile (
1033     ARM_SWITCH_TO_ARM
1034     "mcr p15, 0, %[sbz], c7, c5, 6\n"
1035     ARM_SWITCH_BACK
1036     : ARM_SWITCH_OUTPUT
1037     : [sbz] "r" (sbz)
1038     : "memory"
1039   );
1040 }
1041 
1042 /* Flush Prefetch Buffer - DDI0301H arm1176jzfs TRM 3.2.22 */
1043 ARM_CP15_TEXT_SECTION static inline void
1044 arm_cp15_flush_prefetch_buffer(void)
1045 {
1046   ARM_SWITCH_REGISTERS;
1047   uint32_t sbz = 0;
1048 
1049   __asm__ volatile (
1050     ARM_SWITCH_TO_ARM
1051     "mcr p15, 0, %[sbz], c7, c5, 4\n"
1052     ARM_SWITCH_BACK
1053     : ARM_SWITCH_OUTPUT
1054     : [sbz] "r" (sbz)
1055     : "memory"
1056   );
1057 }
1058 
1059 ARM_CP15_TEXT_SECTION static inline void
1060 arm_cp15_instruction_cache_invalidate(void)
1061 {
1062   ARM_SWITCH_REGISTERS;
1063   uint32_t sbz = 0;
1064 
1065   __asm__ volatile (
1066     ARM_SWITCH_TO_ARM
1067     "mcr p15, 0, %[sbz], c7, c5, 0\n"
1068     ARM_SWITCH_BACK
1069     : ARM_SWITCH_OUTPUT
1070     : [sbz] "r" (sbz)
1071     : "memory"
1072   );
1073 }
1074 
1075 ARM_CP15_TEXT_SECTION static inline void
1076 arm_cp15_instruction_cache_invalidate_line(const void *mva)
1077 {
1078   ARM_SWITCH_REGISTERS;
1079 
1080   mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1081 
1082   __asm__ volatile (
1083     ARM_SWITCH_TO_ARM
1084     "mcr p15, 0, %[mva], c7, c5, 1\n"
1085     ARM_SWITCH_BACK
1086     : ARM_SWITCH_OUTPUT
1087     : [mva] "r" (mva)
1088     : "memory"
1089   );
1090 }
1091 
1092 ARM_CP15_TEXT_SECTION static inline void
1093 arm_cp15_instruction_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
1094 {
1095   ARM_SWITCH_REGISTERS;
1096 
1097   __asm__ volatile (
1098     ARM_SWITCH_TO_ARM
1099     "mcr p15, 0, %[set_and_way], c7, c5, 2\n"
1100     ARM_SWITCH_BACK
1101     : ARM_SWITCH_OUTPUT
1102     : [set_and_way] "r" (set_and_way)
1103     : "memory"
1104   );
1105 }
1106 
1107 ARM_CP15_TEXT_SECTION static inline void
1108 arm_cp15_instruction_cache_prefetch_line(const void *mva)
1109 {
1110   ARM_SWITCH_REGISTERS;
1111 
1112   mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1113 
1114   __asm__ volatile (
1115     ARM_SWITCH_TO_ARM
1116     "mcr p15, 0, %[mva], c7, c13, 1\n"
1117     ARM_SWITCH_BACK
1118     : ARM_SWITCH_OUTPUT
1119     : [mva] "r" (mva)
1120   );
1121 }
1122 
1123 ARM_CP15_TEXT_SECTION static inline void
1124 arm_cp15_data_cache_invalidate(void)
1125 {
1126   ARM_SWITCH_REGISTERS;
1127   uint32_t sbz = 0;
1128 
1129   __asm__ volatile (
1130     ARM_SWITCH_TO_ARM
1131     "mcr p15, 0, %[sbz], c7, c6, 0\n"
1132     ARM_SWITCH_BACK
1133     : ARM_SWITCH_OUTPUT
1134     : [sbz] "r" (sbz)
1135     : "memory"
1136   );
1137 }
1138 
1139 ARM_CP15_TEXT_SECTION static inline void
1140 arm_cp15_data_cache_invalidate_line(const void *mva)
1141 {
1142   ARM_SWITCH_REGISTERS;
1143 
1144   mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1145 
1146   __asm__ volatile (
1147     ARM_SWITCH_TO_ARM
1148     "mcr p15, 0, %[mva], c7, c6, 1\n"
1149     ARM_SWITCH_BACK
1150     : ARM_SWITCH_OUTPUT
1151     : [mva] "r" (mva)
1152     : "memory"
1153   );
1154 }
1155 
1156 ARM_CP15_TEXT_SECTION static inline void
1157 arm_cp15_data_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
1158 {
1159   ARM_SWITCH_REGISTERS;
1160 
1161   __asm__ volatile (
1162     ARM_SWITCH_TO_ARM
1163     "mcr p15, 0, %[set_and_way], c7, c6, 2\n"
1164     ARM_SWITCH_BACK
1165     : ARM_SWITCH_OUTPUT
1166     : [set_and_way] "r" (set_and_way)
1167     : "memory"
1168   );
1169 }
1170 
1171 ARM_CP15_TEXT_SECTION static inline void
1172 arm_cp15_cache_invalidate_level(uint32_t level, uint32_t inst_data_fl)
1173 {
1174   uint32_t ccsidr;
1175   uint32_t line_power;
1176   uint32_t associativity;
1177   uint32_t way;
1178   uint32_t way_shift;
1179 
1180   ccsidr = arm_cp15_get_cache_size_id_for_level((level << 1) | inst_data_fl);
1181 
1182   line_power = arm_ccsidr_get_line_power(ccsidr);
1183   associativity = arm_ccsidr_get_associativity(ccsidr);
1184   way_shift = __builtin_clz(associativity - 1);
1185 
1186   for (way = 0; way < associativity; ++way) {
1187     uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
1188     uint32_t set;
1189 
1190     for (set = 0; set < num_sets; ++set) {
1191       uint32_t set_way = (way << way_shift)
1192         | (set << line_power)
1193         | (level << 1);
1194 
1195       arm_cp15_data_cache_invalidate_line_by_set_and_way(set_way);
1196     }
1197   }
1198 }
1199 
1200 ARM_CP15_TEXT_SECTION static inline void
1201 arm_cp15_data_cache_invalidate_all_levels(void)
1202 {
1203   uint32_t clidr = arm_cp15_get_cache_level_id();
1204   uint32_t loc = arm_clidr_get_level_of_coherency(clidr);
1205   uint32_t level = 0;
1206 
1207   for (level = 0; level < loc; ++level) {
1208     uint32_t ctype = arm_clidr_get_cache_type(clidr, level);
1209 
1210     /* Check if this level has a data cache or unified cache */
1211     if (((ctype & (0x6)) == 2) || (ctype == 4)) {
1212       arm_cp15_cache_invalidate_level(level, 0);
1213     }
1214   }
1215 }
1216 
1217 ARM_CP15_TEXT_SECTION static inline void
1218 arm_cp15_data_cache_clean_line(const void *mva)
1219 {
1220   ARM_SWITCH_REGISTERS;
1221 
1222   mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1223 
1224   __asm__ volatile (
1225     ARM_SWITCH_TO_ARM
1226     "mcr p15, 0, %[mva], c7, c10, 1\n"
1227     ARM_SWITCH_BACK
1228     : ARM_SWITCH_OUTPUT
1229     : [mva] "r" (mva)
1230     : "memory"
1231   );
1232 }
1233 
1234 ARM_CP15_TEXT_SECTION static inline void
1235 arm_cp15_data_cache_clean_line_by_set_and_way(uint32_t set_and_way)
1236 {
1237   ARM_SWITCH_REGISTERS;
1238 
1239   __asm__ volatile (
1240     ARM_SWITCH_TO_ARM
1241     "mcr p15, 0, %[set_and_way], c7, c10, 2\n"
1242     ARM_SWITCH_BACK
1243     : ARM_SWITCH_OUTPUT
1244     : [set_and_way] "r" (set_and_way)
1245     : "memory"
1246   );
1247 }
1248 
1249 ARM_CP15_TEXT_SECTION static inline void
1250 arm_cp15_data_cache_clean_level(uint32_t level)
1251 {
1252   uint32_t ccsidr;
1253   uint32_t line_power;
1254   uint32_t associativity;
1255   uint32_t way;
1256   uint32_t way_shift;
1257 
1258   ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
1259 
1260   line_power = arm_ccsidr_get_line_power(ccsidr);
1261   associativity = arm_ccsidr_get_associativity(ccsidr);
1262   way_shift = __builtin_clz(associativity - 1);
1263 
1264   for (way = 0; way < associativity; ++way) {
1265     uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
1266     uint32_t set;
1267 
1268     for (set = 0; set < num_sets; ++set) {
1269       uint32_t set_way = (way << way_shift)
1270         | (set << line_power)
1271         | (level << 1);
1272 
1273       arm_cp15_data_cache_clean_line_by_set_and_way(set_way);
1274     }
1275   }
1276 }
1277 
1278 ARM_CP15_TEXT_SECTION static inline void
1279 arm_cp15_data_cache_clean_all_levels(void)
1280 {
1281   uint32_t clidr = arm_cp15_get_cache_level_id();
1282   uint32_t loc = arm_clidr_get_level_of_coherency(clidr);
1283   uint32_t level = 0;
1284 
1285   for (level = 0; level < loc; ++level) {
1286     uint32_t ctype = arm_clidr_get_cache_type(clidr, level);
1287 
1288     /* Check if this level has a data cache or unified cache */
1289     if (((ctype & (0x6)) == 2) || (ctype == 4)) {
1290       arm_cp15_data_cache_clean_level(level);
1291     }
1292   }
1293 }
1294 
1295 ARM_CP15_TEXT_SECTION static inline void
1296 arm_cp15_data_cache_test_and_clean(void)
1297 {
1298   ARM_SWITCH_REGISTERS;
1299 
1300   __asm__ volatile (
1301     ARM_SWITCH_TO_ARM
1302     "1:\n"
1303     "mrc p15, 0, r15, c7, c10, 3\n"
1304     "bne 1b\n"
1305     ARM_SWITCH_BACK
1306     : ARM_SWITCH_OUTPUT
1307     :
1308     : "memory"
1309   );
1310 }
1311 
1312 ARM_CP15_TEXT_SECTION static inline void
1313 arm_cp15_data_cache_clean_and_invalidate(void)
1314 {
1315   ARM_SWITCH_REGISTERS;
1316 
1317 #if __ARM_ARCH >= 6
1318   /*
1319    * In DDI0301H_arm1176jzfs_r0p7_trm
1320    * 'MCR p15, 0, <Rd>, c7, c14, 0' means
1321    * Clean and Invalidate Entire Data Cache
1322    */
1323   uint32_t sbz = 0;
1324 
1325   __asm__ volatile (
1326     ARM_SWITCH_TO_ARM
1327     "mcr p15, 0, %[sbz], c7, c14, 0\n"
1328     ARM_SWITCH_BACK
1329     : ARM_SWITCH_OUTPUT
1330     : [sbz] "r" (sbz)
1331     : "memory"
1332   );
1333 #else
1334   /*
1335    * Assume this is an ARM926EJ-S.  Use the test, clean, and invalidate DCache
1336    * operation.
1337    */
1338   __asm__ volatile (
1339     ARM_SWITCH_TO_ARM
1340     "1:\n"
1341     "mrc p15, 0, r15, c7, c14, 3\n"
1342     "bne 1b\n"
1343     ARM_SWITCH_BACK
1344     : ARM_SWITCH_OUTPUT
1345     :
1346     : "memory"
1347   );
1348 #endif
1349 }
1350 
1351 ARM_CP15_TEXT_SECTION static inline void
1352 arm_cp15_data_cache_clean_and_invalidate_line(const void *mva)
1353 {
1354   ARM_SWITCH_REGISTERS;
1355 
1356   mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
1357 
1358   __asm__ volatile (
1359     ARM_SWITCH_TO_ARM
1360     "mcr p15, 0, %[mva], c7, c14, 1\n"
1361     ARM_SWITCH_BACK
1362     : ARM_SWITCH_OUTPUT
1363     : [mva] "r" (mva)
1364     : "memory"
1365   );
1366 }
1367 
1368 ARM_CP15_TEXT_SECTION static inline void
1369 arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(uint32_t set_and_way)
1370 {
1371   ARM_SWITCH_REGISTERS;
1372 
1373   __asm__ volatile (
1374     ARM_SWITCH_TO_ARM
1375     "mcr p15, 0, %[set_and_way], c7, c14, 2\n"
1376     ARM_SWITCH_BACK
1377     : ARM_SWITCH_OUTPUT
1378     : [set_and_way] "r" (set_and_way)
1379     : "memory"
1380   );
1381 }
1382 
1383 ARM_CP15_TEXT_SECTION static inline void
1384 arm_cp15_data_cache_test_and_clean_and_invalidate(void)
1385 {
1386   ARM_SWITCH_REGISTERS;
1387 
1388   __asm__ volatile (
1389     ARM_SWITCH_TO_ARM
1390     "1:\n"
1391     "mrc p15, 0, r15, c7, c14, 3\n"
1392     "bne 1b\n"
1393     ARM_SWITCH_BACK
1394     : ARM_SWITCH_OUTPUT
1395     :
1396     : "memory"
1397   );
1398 }
1399 
1400 /** @} */
1401 
1402 ARM_CP15_TEXT_SECTION static inline void
1403 arm_cp15_drain_write_buffer(void)
1404 {
1405   ARM_SWITCH_REGISTERS;
1406   uint32_t sbz = 0;
1407 
1408   __asm__ volatile (
1409     ARM_SWITCH_TO_ARM
1410     "mcr p15, 0, %[sbz], c7, c10, 4\n"
1411     ARM_SWITCH_BACK
1412     : ARM_SWITCH_OUTPUT
1413     : [sbz] "r" (sbz)
1414     : "memory"
1415   );
1416 }
1417 
1418 ARM_CP15_TEXT_SECTION static inline void
1419 arm_cp15_wait_for_interrupt(void)
1420 {
1421   ARM_SWITCH_REGISTERS;
1422   uint32_t sbz = 0;
1423 
1424   __asm__ volatile (
1425     ARM_SWITCH_TO_ARM
1426     "mcr p15, 0, %[sbz], c7, c0, 4\n"
1427     ARM_SWITCH_BACK
1428     : ARM_SWITCH_OUTPUT
1429     : [sbz] "r" (sbz)
1430     : "memory"
1431   );
1432 }
1433 
1434 ARM_CP15_TEXT_SECTION static inline uint32_t
1435 arm_cp15_get_multiprocessor_affinity(void)
1436 {
1437   ARM_SWITCH_REGISTERS;
1438   uint32_t mpidr;
1439 
1440   __asm__ volatile (
1441     ARM_SWITCH_TO_ARM
1442       "mrc p15, 0, %[mpidr], c0, c0, 5\n"
1443     ARM_SWITCH_BACK
1444     : [mpidr] "=&r" (mpidr) ARM_SWITCH_ADDITIONAL_OUTPUT
1445   );
1446 
1447   return mpidr & 0xff;
1448 }
1449 
1450 ARM_CP15_TEXT_SECTION static inline uint32_t
1451 arm_cortex_a9_get_multiprocessor_cpu_id(void)
1452 {
1453   return arm_cp15_get_multiprocessor_affinity() & 0xff;
1454 }
1455 
1456 #define ARM_CORTEX_A9_ACTL_FW (1U << 0)
1457 #define ARM_CORTEX_A9_ACTL_L2_PREFETCH_HINT_ENABLE (1U << 1)
1458 #define ARM_CORTEX_A9_ACTL_L1_PREFETCH_ENABLE (1U << 2)
1459 #define ARM_CORTEX_A9_ACTL_WRITE_FULL_LINE_OF_ZEROS_MODE (1U << 3)
1460 #define ARM_CORTEX_A9_ACTL_SMP (1U << 6)
1461 #define ARM_CORTEX_A9_ACTL_EXCL (1U << 7)
1462 #define ARM_CORTEX_A9_ACTL_ALLOC_IN_ONE_WAY (1U << 8)
1463 #define ARM_CORTEX_A9_ACTL_PARITY_ON (1U << 9)
1464 
1465 ARM_CP15_TEXT_SECTION static inline uint32_t
1466 arm_cp15_get_auxiliary_control(void)
1467 {
1468   ARM_SWITCH_REGISTERS;
1469   uint32_t val;
1470 
1471   __asm__ volatile (
1472     ARM_SWITCH_TO_ARM
1473     "mrc p15, 0, %[val], c1, c0, 1\n"
1474     ARM_SWITCH_BACK
1475     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1476   );
1477 
1478   return val;
1479 }
1480 
1481 ARM_CP15_TEXT_SECTION static inline void
1482 arm_cp15_set_auxiliary_control(uint32_t val)
1483 {
1484   ARM_SWITCH_REGISTERS;
1485 
1486   __asm__ volatile (
1487     ARM_SWITCH_TO_ARM
1488     "mcr p15, 0, %[val], c1, c0, 1\n"
1489     ARM_SWITCH_BACK
1490     : ARM_SWITCH_OUTPUT
1491     : [val] "r" (val)
1492   );
1493 }
1494 
1495 /* ID_PFR1, Processor Feature Register 1 */
1496 
1497 ARM_CP15_TEXT_SECTION static inline uint32_t
1498 arm_cp15_get_processor_feature_1(void)
1499 {
1500   ARM_SWITCH_REGISTERS;
1501   uint32_t val;
1502 
1503   __asm__ volatile (
1504     ARM_SWITCH_TO_ARM
1505     "mrc p15, 0, %[val], c0, c1, 1\n"
1506     ARM_SWITCH_BACK
1507     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1508   );
1509 
1510   return val;
1511 }
1512 
1513 /* VBAR, Vector Base Address Register, Security Extensions */
1514 
1515 ARM_CP15_TEXT_SECTION static inline void
1516 *arm_cp15_get_vector_base_address(void)
1517 {
1518   ARM_SWITCH_REGISTERS;
1519   void *base;
1520 
1521   __asm__ volatile (
1522     ARM_SWITCH_TO_ARM
1523     "mrc p15, 0, %[base], c12, c0, 0\n"
1524     ARM_SWITCH_BACK
1525     : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1526   );
1527 
1528   return base;
1529 }
1530 
1531 ARM_CP15_TEXT_SECTION static inline void
1532 arm_cp15_set_vector_base_address(void *base)
1533 {
1534   ARM_SWITCH_REGISTERS;
1535 
1536   __asm__ volatile (
1537     ARM_SWITCH_TO_ARM
1538     "mcr p15, 0, %[base], c12, c0, 0\n"
1539     ARM_SWITCH_BACK
1540     : ARM_SWITCH_OUTPUT
1541     : [base] "r" (base)
1542   );
1543 }
1544 
1545 ARM_CP15_TEXT_SECTION static inline void
1546 *arm_cp15_get_hyp_vector_base_address(void)
1547 {
1548   ARM_SWITCH_REGISTERS;
1549   void *base;
1550 
1551   __asm__ volatile (
1552     ARM_SWITCH_TO_ARM
1553     "mrc p15, 4, %[base], c12, c0, 0\n"
1554     ARM_SWITCH_BACK
1555     : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
1556   );
1557 
1558   return base;
1559 }
1560 
1561 ARM_CP15_TEXT_SECTION static inline void
1562 arm_cp15_set_hyp_vector_base_address(void *base)
1563 {
1564   ARM_SWITCH_REGISTERS;
1565 
1566   __asm__ volatile (
1567     ARM_SWITCH_TO_ARM
1568     "mcr p15, 4, %[base], c12, c0, 0\n"
1569     ARM_SWITCH_BACK
1570     : ARM_SWITCH_OUTPUT
1571     : [base] "r" (base)
1572   );
1573 }
1574 
1575 /* PMCCNTR */
1576 ARM_CP15_TEXT_SECTION static inline uint32_t
1577 arm_cp15_get_performance_monitors_cycle_count(void)
1578 {
1579   ARM_SWITCH_REGISTERS;
1580   uint32_t val;
1581 
1582   __asm__ volatile (
1583     ARM_SWITCH_TO_ARM
1584     "mrc p15, 0, %[val], c9, c13, 0\n"
1585     ARM_SWITCH_BACK
1586     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1587   );
1588 
1589   return val;
1590 }
1591 
1592 /* PMCCNTR */
1593 ARM_CP15_TEXT_SECTION static inline void
1594 arm_cp15_set_performance_monitors_cycle_count(uint32_t val)
1595 {
1596   ARM_SWITCH_REGISTERS;
1597 
1598   __asm__ volatile (
1599     ARM_SWITCH_TO_ARM
1600     "mcr p15, 0, %[val], c9, c13, 0\n"
1601     ARM_SWITCH_BACK
1602     : ARM_SWITCH_OUTPUT
1603     : [val] "r" (val)
1604   );
1605 }
1606 
1607 /* PMCEID0 */
1608 ARM_CP15_TEXT_SECTION static inline uint32_t
1609 arm_cp15_get_performance_monitors_common_event_id_0(void)
1610 {
1611   ARM_SWITCH_REGISTERS;
1612   uint32_t val;
1613 
1614   __asm__ volatile (
1615     ARM_SWITCH_TO_ARM
1616     "mrc p15, 0, %[val], c9, c12, 6\n"
1617     ARM_SWITCH_BACK
1618     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1619   );
1620 
1621   return val;
1622 }
1623 
1624 /* PMCEID1 */
1625 ARM_CP15_TEXT_SECTION static inline uint32_t
1626 arm_cp15_get_performance_monitors_common_event_id_1(void)
1627 {
1628   ARM_SWITCH_REGISTERS;
1629   uint32_t val;
1630 
1631   __asm__ volatile (
1632     ARM_SWITCH_TO_ARM
1633     "mrc p15, 0, %[val], c9, c12, 7\n"
1634     ARM_SWITCH_BACK
1635     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1636   );
1637 
1638   return val;
1639 }
1640 
1641 #define ARM_CP15_PMCLRSET_CYCLE_COUNTER 0x80000000
1642 
1643 /* PMCCNTENCLR */
1644 ARM_CP15_TEXT_SECTION static inline uint32_t
1645 arm_cp15_get_performance_monitors_count_enable_clear(void)
1646 {
1647   ARM_SWITCH_REGISTERS;
1648   uint32_t val;
1649 
1650   __asm__ volatile (
1651     ARM_SWITCH_TO_ARM
1652     "mrc p15, 0, %[val], c9, c12, 2\n"
1653     ARM_SWITCH_BACK
1654     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1655   );
1656 
1657   return val;
1658 }
1659 
1660 /* PMCCNTENCLR */
1661 ARM_CP15_TEXT_SECTION static inline void
1662 arm_cp15_set_performance_monitors_count_enable_clear(uint32_t val)
1663 {
1664   ARM_SWITCH_REGISTERS;
1665 
1666   __asm__ volatile (
1667     ARM_SWITCH_TO_ARM
1668     "mcr p15, 0, %[val], c9, c12, 2\n"
1669     ARM_SWITCH_BACK
1670     : ARM_SWITCH_OUTPUT
1671     : [val] "r" (val)
1672   );
1673 }
1674 
1675 /* PMCCNTENSET */
1676 ARM_CP15_TEXT_SECTION static inline uint32_t
1677 arm_cp15_get_performance_monitors_count_enable_set(void)
1678 {
1679   ARM_SWITCH_REGISTERS;
1680   uint32_t val;
1681 
1682   __asm__ volatile (
1683     ARM_SWITCH_TO_ARM
1684     "mrc p15, 0, %[val], c9, c12, 1\n"
1685     ARM_SWITCH_BACK
1686     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1687   );
1688 
1689   return val;
1690 }
1691 
1692 /* PMCCNTENSET */
1693 ARM_CP15_TEXT_SECTION static inline void
1694 arm_cp15_set_performance_monitors_count_enable_set(uint32_t val)
1695 {
1696   ARM_SWITCH_REGISTERS;
1697 
1698   __asm__ volatile (
1699     ARM_SWITCH_TO_ARM
1700     "mcr p15, 0, %[val], c9, c12, 1\n"
1701     ARM_SWITCH_BACK
1702     : ARM_SWITCH_OUTPUT
1703     : [val] "r" (val)
1704   );
1705 }
1706 
1707 #define ARM_CP15_PMCR_IMP(x) ((x) << 24)
1708 #define ARM_CP15_PMCR_IDCODE(x) ((x) << 16)
1709 #define ARM_CP15_PMCR_N(x) ((x) << 11)
1710 #define ARM_CP15_PMCR_DP (1U << 5)
1711 #define ARM_CP15_PMCR_X (1U << 4)
1712 #define ARM_CP15_PMCR_D (1U << 3)
1713 #define ARM_CP15_PMCR_C (1U << 2)
1714 #define ARM_CP15_PMCR_P (1U << 1)
1715 #define ARM_CP15_PMCR_E (1U << 0)
1716 
1717 /* PMCR */
1718 ARM_CP15_TEXT_SECTION static inline uint32_t
1719 arm_cp15_get_performance_monitors_control(void)
1720 {
1721   ARM_SWITCH_REGISTERS;
1722   uint32_t val;
1723 
1724   __asm__ volatile (
1725     ARM_SWITCH_TO_ARM
1726     "mrc p15, 0, %[val], c9, c12, 0\n"
1727     ARM_SWITCH_BACK
1728     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1729   );
1730 
1731   return val;
1732 }
1733 
1734 /* PMCR */
1735 ARM_CP15_TEXT_SECTION static inline void
1736 arm_cp15_set_performance_monitors_control(uint32_t val)
1737 {
1738   ARM_SWITCH_REGISTERS;
1739 
1740   __asm__ volatile (
1741     ARM_SWITCH_TO_ARM
1742     "mcr p15, 0, %[val], c9, c12, 0\n"
1743     ARM_SWITCH_BACK
1744     : ARM_SWITCH_OUTPUT
1745     : [val] "r" (val)
1746   );
1747 }
1748 
1749 /* PMINTENCLR */
1750 ARM_CP15_TEXT_SECTION static inline uint32_t
1751 arm_cp15_get_performance_monitors_interrupt_enable_clear(void)
1752 {
1753   ARM_SWITCH_REGISTERS;
1754   uint32_t val;
1755 
1756   __asm__ volatile (
1757     ARM_SWITCH_TO_ARM
1758     "mrc p15, 0, %[val], c9, c14, 2\n"
1759     ARM_SWITCH_BACK
1760     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1761   );
1762 
1763   return val;
1764 }
1765 
1766 /* PMINTENCLR */
1767 ARM_CP15_TEXT_SECTION static inline void
1768 arm_cp15_set_performance_monitors_interrupt_enable_clear(uint32_t val)
1769 {
1770   ARM_SWITCH_REGISTERS;
1771 
1772   __asm__ volatile (
1773     ARM_SWITCH_TO_ARM
1774     "mcr p15, 0, %[val], c9, c14, 2\n"
1775     ARM_SWITCH_BACK
1776     : ARM_SWITCH_OUTPUT
1777     : [val] "r" (val)
1778   );
1779 }
1780 
1781 /* PMINTENSET */
1782 ARM_CP15_TEXT_SECTION static inline uint32_t
1783 arm_cp15_get_performance_monitors_interrupt_enable_set(void)
1784 {
1785   ARM_SWITCH_REGISTERS;
1786   uint32_t val;
1787 
1788   __asm__ volatile (
1789     ARM_SWITCH_TO_ARM
1790     "mrc p15, 0, %[val], c9, c14, 1\n"
1791     ARM_SWITCH_BACK
1792     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1793   );
1794 
1795   return val;
1796 }
1797 
1798 /* PMINTENSET */
1799 ARM_CP15_TEXT_SECTION static inline void
1800 arm_cp15_set_performance_monitors_interrupt_enable_set(uint32_t val)
1801 {
1802   ARM_SWITCH_REGISTERS;
1803 
1804   __asm__ volatile (
1805     ARM_SWITCH_TO_ARM
1806     "mcr p15, 0, %[val], c9, c14, 1\n"
1807     ARM_SWITCH_BACK
1808     : ARM_SWITCH_OUTPUT
1809     : [val] "r" (val)
1810   );
1811 }
1812 
1813 /* PMOVSR */
1814 ARM_CP15_TEXT_SECTION static inline uint32_t
1815 arm_cp15_get_performance_monitors_overflow_flag_status(void)
1816 {
1817   ARM_SWITCH_REGISTERS;
1818   uint32_t val;
1819 
1820   __asm__ volatile (
1821     ARM_SWITCH_TO_ARM
1822     "mrc p15, 0, %[val], c9, c12, 3\n"
1823     ARM_SWITCH_BACK
1824     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1825   );
1826 
1827   return val;
1828 }
1829 
1830 /* PMOVSR */
1831 ARM_CP15_TEXT_SECTION static inline void
1832 arm_cp15_set_performance_monitors_overflow_flag_status(uint32_t val)
1833 {
1834   ARM_SWITCH_REGISTERS;
1835 
1836   __asm__ volatile (
1837     ARM_SWITCH_TO_ARM
1838     "mcr p15, 0, %[val], c9, c12, 3\n"
1839     ARM_SWITCH_BACK
1840     : ARM_SWITCH_OUTPUT
1841     : [val] "r" (val)
1842   );
1843 }
1844 
1845 /* PMOVSSET */
1846 ARM_CP15_TEXT_SECTION static inline uint32_t
1847 arm_cp15_get_performance_monitors_overflow_flag_status_set(void)
1848 {
1849   ARM_SWITCH_REGISTERS;
1850   uint32_t val;
1851 
1852   __asm__ volatile (
1853     ARM_SWITCH_TO_ARM
1854     "mrc p15, 0, %[val], c9, c14, 3\n"
1855     ARM_SWITCH_BACK
1856     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1857   );
1858 
1859   return val;
1860 }
1861 
1862 /* PMOVSSET */
1863 ARM_CP15_TEXT_SECTION static inline void
1864 arm_cp15_set_performance_monitors_overflow_flag_status_set(uint32_t val)
1865 {
1866   ARM_SWITCH_REGISTERS;
1867 
1868   __asm__ volatile (
1869     ARM_SWITCH_TO_ARM
1870     "mcr p15, 0, %[val], c9, c14, 3\n"
1871     ARM_SWITCH_BACK
1872     : ARM_SWITCH_OUTPUT
1873     : [val] "r" (val)
1874   );
1875 }
1876 
1877 /* PMSELR */
1878 ARM_CP15_TEXT_SECTION static inline uint32_t
1879 arm_cp15_get_performance_monitors_event_counter_selection(void)
1880 {
1881   ARM_SWITCH_REGISTERS;
1882   uint32_t val;
1883 
1884   __asm__ volatile (
1885     ARM_SWITCH_TO_ARM
1886     "mrc p15, 0, %[val], c9, c12, 5\n"
1887     ARM_SWITCH_BACK
1888     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1889   );
1890 
1891   return val;
1892 }
1893 
1894 /* PMSELR */
1895 ARM_CP15_TEXT_SECTION static inline void
1896 arm_cp15_set_performance_monitors_event_counter_selection(uint32_t val)
1897 {
1898   ARM_SWITCH_REGISTERS;
1899 
1900   __asm__ volatile (
1901     ARM_SWITCH_TO_ARM
1902     "mcr p15, 0, %[val], c9, c12, 5\n"
1903     ARM_SWITCH_BACK
1904     : ARM_SWITCH_OUTPUT
1905     : [val] "r" (val)
1906   );
1907 }
1908 
1909 /* PMSWINC */
1910 ARM_CP15_TEXT_SECTION static inline void
1911 arm_cp15_set_performance_monitors_software_increment(uint32_t val)
1912 {
1913   ARM_SWITCH_REGISTERS;
1914 
1915   __asm__ volatile (
1916     ARM_SWITCH_TO_ARM
1917     "mcr p15, 0, %[val], c9, c12, 4\n"
1918     ARM_SWITCH_BACK
1919     : ARM_SWITCH_OUTPUT
1920     : [val] "r" (val)
1921   );
1922 }
1923 
1924 /* PMUSERENR */
1925 ARM_CP15_TEXT_SECTION static inline uint32_t
1926 arm_cp15_get_performance_monitors_user_enable(void)
1927 {
1928   ARM_SWITCH_REGISTERS;
1929   uint32_t val;
1930 
1931   __asm__ volatile (
1932     ARM_SWITCH_TO_ARM
1933     "mrc p15, 0, %[val], c9, c14, 0\n"
1934     ARM_SWITCH_BACK
1935     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1936   );
1937 
1938   return val;
1939 }
1940 
1941 /* PMUSERENR */
1942 ARM_CP15_TEXT_SECTION static inline void
1943 arm_cp15_set_performance_monitors_user_enable(uint32_t val)
1944 {
1945   ARM_SWITCH_REGISTERS;
1946 
1947   __asm__ volatile (
1948     ARM_SWITCH_TO_ARM
1949     "mcr p15, 0, %[val], c9, c14, 0\n"
1950     ARM_SWITCH_BACK
1951     : ARM_SWITCH_OUTPUT
1952     : [val] "r" (val)
1953   );
1954 }
1955 
1956 /* PMXEVCNTR */
1957 ARM_CP15_TEXT_SECTION static inline uint32_t
1958 arm_cp15_get_performance_monitors_event_count(void)
1959 {
1960   ARM_SWITCH_REGISTERS;
1961   uint32_t val;
1962 
1963   __asm__ volatile (
1964     ARM_SWITCH_TO_ARM
1965     "mrc p15, 0, %[val], c9, c13, 2\n"
1966     ARM_SWITCH_BACK
1967     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
1968   );
1969 
1970   return val;
1971 }
1972 
1973 /* PMXEVCNTR */
1974 ARM_CP15_TEXT_SECTION static inline void
1975 arm_cp15_set_performance_monitors_event_count(uint32_t val)
1976 {
1977   ARM_SWITCH_REGISTERS;
1978 
1979   __asm__ volatile (
1980     ARM_SWITCH_TO_ARM
1981     "mcr p15, 0, %[val], c9, c13, 2\n"
1982     ARM_SWITCH_BACK
1983     : ARM_SWITCH_OUTPUT
1984     : [val] "r" (val)
1985   );
1986 }
1987 
1988 /* PMXEVTYPER */
1989 ARM_CP15_TEXT_SECTION static inline uint32_t
1990 arm_cp15_get_performance_monitors_event_type_select(void)
1991 {
1992   ARM_SWITCH_REGISTERS;
1993   uint32_t val;
1994 
1995   __asm__ volatile (
1996     ARM_SWITCH_TO_ARM
1997     "mrc p15, 0, %[val], c9, c13, 1\n"
1998     ARM_SWITCH_BACK
1999     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2000   );
2001 
2002   return val;
2003 }
2004 
2005 /* PMXEVTYPER */
2006 ARM_CP15_TEXT_SECTION static inline void
2007 arm_cp15_set_performance_monitors_event_type_select(uint32_t val)
2008 {
2009   ARM_SWITCH_REGISTERS;
2010 
2011   __asm__ volatile (
2012     ARM_SWITCH_TO_ARM
2013     "mcr p15, 0, %[val], c9, c13, 1\n"
2014     ARM_SWITCH_BACK
2015     : ARM_SWITCH_OUTPUT
2016     : [val] "r" (val)
2017   );
2018 }
2019 
2020 /* CNTFRQ */
2021 ARM_CP15_TEXT_SECTION static inline uint32_t
2022 arm_cp15_get_counter_frequency(void)
2023 {
2024   ARM_SWITCH_REGISTERS;
2025   uint32_t val;
2026 
2027   __asm__ volatile (
2028     ARM_SWITCH_TO_ARM
2029     "mrc p15, 0, %[val], c14, c0, 0\n"
2030     ARM_SWITCH_BACK
2031     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2032   );
2033 
2034   return val;
2035 }
2036 
2037 /* CNTFRQ */
2038 ARM_CP15_TEXT_SECTION static inline void
2039 arm_cp15_set_counter_frequency(uint32_t val)
2040 {
2041   ARM_SWITCH_REGISTERS;
2042 
2043   __asm__ volatile (
2044     ARM_SWITCH_TO_ARM
2045     "mcr p15, 0, %[val], c14, c0, 0\n"
2046     ARM_SWITCH_BACK
2047     : ARM_SWITCH_OUTPUT
2048     : [val] "r" (val)
2049   );
2050 }
2051 
2052 /* CNTPCT */
2053 ARM_CP15_TEXT_SECTION static inline uint64_t
2054 arm_cp15_get_counter_physical_count(void)
2055 {
2056   ARM_SWITCH_REGISTERS;
2057   uint64_t val;
2058 
2059   __asm__ volatile (
2060     ARM_SWITCH_TO_ARM
2061     "mrrc p15, 0, %Q[val], %R[val], c14\n"
2062     ARM_SWITCH_BACK
2063     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2064   );
2065 
2066   return val;
2067 }
2068 
2069 /* CNTKCTL */
2070 ARM_CP15_TEXT_SECTION static inline uint32_t
2071 arm_cp15_get_counter_non_secure_pl1_control(void)
2072 {
2073   ARM_SWITCH_REGISTERS;
2074   uint32_t val;
2075 
2076   __asm__ volatile (
2077     ARM_SWITCH_TO_ARM
2078     "mrc p15, 0, %[val], c14, c1, 0\n"
2079     ARM_SWITCH_BACK
2080     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2081   );
2082 
2083   return val;
2084 }
2085 
2086 /* CNTKCTL */
2087 ARM_CP15_TEXT_SECTION static inline void
2088 arm_cp15_set_counter_non_secure_pl1_control(uint32_t val)
2089 {
2090   ARM_SWITCH_REGISTERS;
2091 
2092   __asm__ volatile (
2093     ARM_SWITCH_TO_ARM
2094     "mcr p15, 0, %[val], c14, c1, 0\n"
2095     ARM_SWITCH_BACK
2096     : ARM_SWITCH_OUTPUT
2097     : [val] "r" (val)
2098   );
2099 }
2100 
2101 /* CNTP_TVAL */
2102 ARM_CP15_TEXT_SECTION static inline uint32_t
2103 arm_cp15_get_counter_pl1_physical_timer_value(void)
2104 {
2105   ARM_SWITCH_REGISTERS;
2106   uint32_t val;
2107 
2108   __asm__ volatile (
2109     ARM_SWITCH_TO_ARM
2110     "mrc p15, 0, %[val], c14, c2, 0\n"
2111     ARM_SWITCH_BACK
2112     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2113   );
2114 
2115   return val;
2116 }
2117 
2118 /* CNTP_TVAL */
2119 ARM_CP15_TEXT_SECTION static inline void
2120 arm_cp15_set_counter_pl1_physical_timer_value(uint32_t val)
2121 {
2122   ARM_SWITCH_REGISTERS;
2123 
2124   __asm__ volatile (
2125     ARM_SWITCH_TO_ARM
2126     "mcr p15, 0, %[val], c14, c2, 0\n"
2127     ARM_SWITCH_BACK
2128     : ARM_SWITCH_OUTPUT
2129     : [val] "r" (val)
2130   );
2131 }
2132 
2133 /* CNTP_CTL */
2134 ARM_CP15_TEXT_SECTION static inline uint32_t
2135 arm_cp15_get_counter_pl1_physical_timer_control(void)
2136 {
2137   ARM_SWITCH_REGISTERS;
2138   uint32_t val;
2139 
2140   __asm__ volatile (
2141     ARM_SWITCH_TO_ARM
2142     "mrc p15, 0, %[val], c14, c2, 1\n"
2143     ARM_SWITCH_BACK
2144     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2145   );
2146 
2147   return val;
2148 }
2149 
2150 /* CNTP_CTL */
2151 ARM_CP15_TEXT_SECTION static inline void
2152 arm_cp15_set_counter_pl1_physical_timer_control(uint32_t val)
2153 {
2154   ARM_SWITCH_REGISTERS;
2155 
2156   __asm__ volatile (
2157     ARM_SWITCH_TO_ARM
2158     "mcr p15, 0, %[val], c14, c2, 1\n"
2159     ARM_SWITCH_BACK
2160     : ARM_SWITCH_OUTPUT
2161     : [val] "r" (val)
2162   );
2163 }
2164 
2165 /* CNTV_TVAL */
2166 ARM_CP15_TEXT_SECTION static inline uint32_t
2167 arm_cp15_get_counter_pl1_virtual_timer_value(void)
2168 {
2169   ARM_SWITCH_REGISTERS;
2170   uint32_t val;
2171 
2172   __asm__ volatile (
2173     ARM_SWITCH_TO_ARM
2174     "mrc p15, 0, %[val], c14, c3, 0\n"
2175     ARM_SWITCH_BACK
2176     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2177   );
2178 
2179   return val;
2180 }
2181 
2182 /* CNTV_TVAL */
2183 ARM_CP15_TEXT_SECTION static inline void
2184 arm_cp15_set_counter_pl1_virtual_timer_value(uint32_t val)
2185 {
2186   ARM_SWITCH_REGISTERS;
2187 
2188   __asm__ volatile (
2189     ARM_SWITCH_TO_ARM
2190     "mcr p15, 0, %[val], c14, c3, 0\n"
2191     ARM_SWITCH_BACK
2192     : ARM_SWITCH_OUTPUT
2193     : [val] "r" (val)
2194   );
2195 }
2196 
2197 /* CNTV_CTL */
2198 ARM_CP15_TEXT_SECTION static inline uint32_t
2199 arm_cp15_get_counter_pl1_virtual_timer_control(void)
2200 {
2201   ARM_SWITCH_REGISTERS;
2202   uint32_t val;
2203 
2204   __asm__ volatile (
2205     ARM_SWITCH_TO_ARM
2206     "mrc p15, 0, %[val], c14, c3, 1\n"
2207     ARM_SWITCH_BACK
2208     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2209   );
2210 
2211   return val;
2212 }
2213 
2214 /* CNTV_CTL */
2215 ARM_CP15_TEXT_SECTION static inline void
2216 arm_cp15_set_counter_pl1_virtual_timer_control(uint32_t val)
2217 {
2218   ARM_SWITCH_REGISTERS;
2219 
2220   __asm__ volatile (
2221     ARM_SWITCH_TO_ARM
2222     "mcr p15, 0, %[val], c14, c3, 1\n"
2223     ARM_SWITCH_BACK
2224     : ARM_SWITCH_OUTPUT
2225     : [val] "r" (val)
2226   );
2227 }
2228 
2229 /* CNTVCT */
2230 ARM_CP15_TEXT_SECTION static inline uint64_t
2231 arm_cp15_get_counter_virtual_count(void)
2232 {
2233   ARM_SWITCH_REGISTERS;
2234   uint64_t val;
2235 
2236   __asm__ volatile (
2237     ARM_SWITCH_TO_ARM
2238     "mrrc p15, 1, %Q[val], %R[val], c14\n"
2239     ARM_SWITCH_BACK
2240     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2241   );
2242 
2243   return val;
2244 }
2245 
2246 /* CNTP_CVAL */
2247 ARM_CP15_TEXT_SECTION static inline uint64_t
2248 arm_cp15_get_counter_pl1_physical_compare_value(void)
2249 {
2250   ARM_SWITCH_REGISTERS;
2251   uint64_t val;
2252 
2253   __asm__ volatile (
2254     ARM_SWITCH_TO_ARM
2255     "mrrc p15, 2, %Q[val], %R[val], c14\n"
2256     ARM_SWITCH_BACK
2257     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2258   );
2259 
2260   return val;
2261 }
2262 
2263 /* CNTP_CVAL */
2264 ARM_CP15_TEXT_SECTION static inline void
2265 arm_cp15_set_counter_pl1_physical_compare_value(uint64_t val)
2266 {
2267   ARM_SWITCH_REGISTERS;
2268 
2269   __asm__ volatile (
2270     ARM_SWITCH_TO_ARM
2271     "mcrr p15, 2, %Q[val], %R[val], c14\n"
2272     ARM_SWITCH_BACK
2273     : ARM_SWITCH_OUTPUT
2274     : [val] "r" (val)
2275   );
2276 }
2277 
2278 /* CNTV_CVAL */
2279 ARM_CP15_TEXT_SECTION static inline uint64_t
2280 arm_cp15_get_counter_pl1_virtual_compare_value(void)
2281 {
2282   ARM_SWITCH_REGISTERS;
2283   uint64_t val;
2284 
2285   __asm__ volatile (
2286     ARM_SWITCH_TO_ARM
2287     "mrrc p15, 3, %Q[val], %R[val], c14\n"
2288     ARM_SWITCH_BACK
2289     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2290   );
2291 
2292   return val;
2293 }
2294 
2295 /* CNTV_CVAL */
2296 ARM_CP15_TEXT_SECTION static inline void
2297 arm_cp15_set_counter_pl1_virtual_compare_value(uint64_t val)
2298 {
2299   ARM_SWITCH_REGISTERS;
2300 
2301   __asm__ volatile (
2302     ARM_SWITCH_TO_ARM
2303     "mcrr p15, 3, %Q[val], %R[val], c14\n"
2304     ARM_SWITCH_BACK
2305     : ARM_SWITCH_OUTPUT
2306     : [val] "r" (val)
2307   );
2308 }
2309 
2310 /* CNTVOFF */
2311 ARM_CP15_TEXT_SECTION static inline uint64_t
2312 arm_cp15_get_counter_virtual_offset(void)
2313 {
2314   ARM_SWITCH_REGISTERS;
2315   uint64_t val;
2316 
2317   __asm__ volatile (
2318     ARM_SWITCH_TO_ARM
2319     "mrrc p15, 4, %Q[val], %R[val], c14\n"
2320     ARM_SWITCH_BACK
2321     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2322   );
2323 
2324   return val;
2325 }
2326 
2327 /* CNTVOFF */
2328 ARM_CP15_TEXT_SECTION static inline void
2329 arm_cp15_set_counter_virtual_offset(uint64_t val)
2330 {
2331   ARM_SWITCH_REGISTERS;
2332 
2333   __asm__ volatile (
2334     ARM_SWITCH_TO_ARM
2335     "mcrr p15, 4, %Q[val], %R[val], c14\n"
2336     ARM_SWITCH_BACK
2337     : ARM_SWITCH_OUTPUT
2338     : [val] "r" (val)
2339   );
2340 }
2341 
2342 /* Diagnostic Control Register */
2343 ARM_CP15_TEXT_SECTION static inline uint32_t
2344 arm_cp15_get_diagnostic_control(void)
2345 {
2346   ARM_SWITCH_REGISTERS;
2347   uint32_t val;
2348 
2349   __asm__ volatile (
2350     ARM_SWITCH_TO_ARM
2351     "mrc p15, 0, %[val], c15, c0, 1\n"
2352     ARM_SWITCH_BACK
2353     : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
2354   );
2355 
2356   return val;
2357 }
2358 
2359 /* Diagnostic Control Register */
2360 ARM_CP15_TEXT_SECTION static inline void
2361 arm_cp15_set_diagnostic_control(uint32_t val)
2362 {
2363   ARM_SWITCH_REGISTERS;
2364 
2365   __asm__ volatile (
2366     ARM_SWITCH_TO_ARM
2367     "mcr p15, 0, %[val], c15, c0, 1\n"
2368     ARM_SWITCH_BACK
2369     : ARM_SWITCH_OUTPUT
2370     : [val] "r" (val)
2371   );
2372 }
2373 
2374 /* This is probably a Cortex-R5 specific operation */
2375 ARM_CP15_TEXT_SECTION static inline void
2376 arm_cp15_data_cache_all_invalidate(void)
2377 {
2378   ARM_SWITCH_REGISTERS;
2379   uint32_t sbz = 0;
2380 
2381   __asm__ volatile (
2382     ARM_SWITCH_TO_ARM
2383     "mcr p15, 0, %[sbz], c15, c5, 0\n"
2384     ARM_SWITCH_BACK
2385     : ARM_SWITCH_OUTPUT
2386     : [sbz] "r" (sbz)
2387     : "memory"
2388   );
2389 }
2390 
2391 /**
2392  * @brief Sets the @a section_flags for the address range [@a begin, @a end).
2393  *
2394  * @return Previous section flags of the first modified entry.
2395  */
2396 uint32_t arm_cp15_set_translation_table_entries(
2397   const void *begin,
2398   const void *end,
2399   uint32_t section_flags
2400 );
2401 
2402 /**
2403  * @brief Sets the @a exception @a handler in the vector table.
2404  *
2405  * @return Previous handler.
2406  */
2407 void* arm_cp15_set_exception_handler(
2408   Arm_symbolic_exception_name exception,
2409   void (*handler)(void)
2410 );
2411 
2412 /** @} */
2413 
2414 #ifdef __cplusplus
2415 }
2416 #endif /* __cplusplus */
2417 
2418 #endif /* LIBCPU_SHARED_ARM_CP15_H */