summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-12-13 08:42:34 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-12-13 09:04:21 +0100
commit8e8cf723a3c7048e4418781a494cba82042b645b (patch)
tree6a5b21a401c3f112b335ce1c600c797e82324639 /cpukit/score/cpu
parenttm08: Do not use RTEMS_INTERRUPT_MASK for no reschedule case (diff)
downloadrtems-8e8cf723a3c7048e4418781a494cba82042b645b.tar.bz2
arm: Move <libcpu/arm-cp15.h> to cpukit
Update #3254.
Diffstat (limited to 'cpukit/score/cpu')
-rw-r--r--cpukit/score/cpu/arm/Makefile.am3
-rw-r--r--cpukit/score/cpu/arm/include/libcpu/arm-cp15.h2260
-rw-r--r--cpukit/score/cpu/arm/preinstall.am9
3 files changed, 2272 insertions, 0 deletions
diff --git a/cpukit/score/cpu/arm/Makefile.am b/cpukit/score/cpu/arm/Makefile.am
index 6e98ed5cac..a0881e80e9 100644
--- a/cpukit/score/cpu/arm/Makefile.am
+++ b/cpukit/score/cpu/arm/Makefile.am
@@ -12,6 +12,9 @@ include_rtems_score_HEADERS += rtems/score/armv7m.h
include_rtems_score_HEADERS += rtems/score/types.h
include_rtems_score_HEADERS += rtems/score/cpuatomic.h
+include_libcpudir = $(includedir)/libcpu
+include_libcpu_HEADERS = include/libcpu/arm-cp15.h
+
noinst_LIBRARIES = libscorecpu.a
libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
libscorecpu_a_SOURCES =
diff --git a/cpukit/score/cpu/arm/include/libcpu/arm-cp15.h b/cpukit/score/cpu/arm/include/libcpu/arm-cp15.h
new file mode 100644
index 0000000000..54a8e7516c
--- /dev/null
+++ b/cpukit/score/cpu/arm/include/libcpu/arm-cp15.h
@@ -0,0 +1,2260 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreCPUARMCP15
+ *
+ * @brief ARM co-processor 15 (CP15) API.
+ */
+
+/*
+ * Copyright (c) 2013 Hesham AL-Matary
+ * Copyright (c) 2009-2017 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <info@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef LIBCPU_SHARED_ARM_CP15_H
+#define LIBCPU_SHARED_ARM_CP15_H
+
+#include <rtems.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * Allow users of this header file to optionally place the inline functions
+ * into a non-standard section.
+ */
+#ifndef ARM_CP15_TEXT_SECTION
+ #define ARM_CP15_TEXT_SECTION
+#endif
+
+#define ARM_CP15_CACHE_PREPARE_MVA(mva) \
+ ((const void *) (((uint32_t) (mva)) & ~0x1fU))
+
+#define ARM_CP15_TLB_PREPARE_MVA(mva) \
+ ((const void *) (((uint32_t) (mva)) & ~0x3fU))
+
+/**
+ * @defgroup ScoreCPUARMCP15 ARM Co-Processor 15 Support
+ *
+ * @ingroup ScoreCPUARM
+ *
+ * @brief ARM co-processor 15 (CP15) support.
+ *
+ * @{
+ */
+
+/**
+ * @name MMU Defines
+ *
+ * See section B3.8.2, "Short-descriptor format memory region attributes,
+ * without TEX remap" in the "ARM Architecture Reference Manual ARMv7-A and
+ * ARMv7-R edition".
+ *
+ * @{
+ */
+
+#define ARM_MMU_SECT_BASE_SHIFT 20
+#define ARM_MMU_SECT_BASE_MASK (0xfffU << ARM_MMU_SECT_BASE_SHIFT)
+#define ARM_MMU_SECT_NS (1U << 19)
+#define ARM_MMU_SECT_NG (1U << 17)
+#define ARM_MMU_SECT_S (1U << 16)
+#define ARM_MMU_SECT_AP_2 (1U << 15)
+#define ARM_MMU_SECT_TEX_2 (1U << 14)
+#define ARM_MMU_SECT_TEX_1 (1U << 13)
+#define ARM_MMU_SECT_TEX_0 (1U << 12)
+#define ARM_MMU_SECT_TEX_SHIFT 12
+#define ARM_MMU_SECT_TEX_MASK (0x3U << ARM_MMU_SECT_TEX_SHIFT)
+#define ARM_MMU_SECT_AP_1 (1U << 11)
+#define ARM_MMU_SECT_AP_0 (1U << 10)
+#define ARM_MMU_SECT_AP_SHIFT 10
+#define ARM_MMU_SECT_AP_MASK (0x23U << ARM_MMU_SECT_AP_SHIFT)
+#define ARM_MMU_SECT_DOMAIN_SHIFT 5
+#define ARM_MMU_SECT_DOMAIN_MASK (0xfU << ARM_MMU_SECT_DOMAIN_SHIFT)
+#define ARM_MMU_SECT_XN (1U << 4)
+#define ARM_MMU_SECT_C (1U << 3)
+#define ARM_MMU_SECT_B (1U << 2)
+#define ARM_MMU_SECT_PXN (1U << 0)
+#define ARM_MMU_SECT_DEFAULT 0x2U
+#define ARM_MMU_SECT_GET_INDEX(mva) \
+ (((uint32_t) (mva)) >> ARM_MMU_SECT_BASE_SHIFT)
+#define ARM_MMU_SECT_MVA_ALIGN_UP(mva) \
+ ((1U << ARM_MMU_SECT_BASE_SHIFT) \
+ + ((((uint32_t) (mva) - 1U)) & ~((1U << ARM_MMU_SECT_BASE_SHIFT) - 1U)))
+
+#define ARM_MMU_TRANSLATION_TABLE_ENTRY_SIZE 4U
+#define ARM_MMU_TRANSLATION_TABLE_ENTRY_COUNT 4096U
+
+#define ARM_MMU_DEFAULT_CLIENT_DOMAIN 15U
+
+#define ARMV7_MMU_READ_ONLY \
+ ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
+ | ARM_MMU_SECT_AP_0 \
+ | ARM_MMU_SECT_AP_2 \
+ | ARM_MMU_SECT_DEFAULT)
+
+#define ARMV7_MMU_READ_ONLY_CACHED \
+ (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
+
+#define ARMV7_MMU_READ_WRITE \
+ ((ARM_MMU_DEFAULT_CLIENT_DOMAIN << ARM_MMU_SECT_DOMAIN_SHIFT) \
+ | ARM_MMU_SECT_AP_0 \
+ | ARM_MMU_SECT_DEFAULT)
+
+#ifdef RTEMS_SMP
+ #define ARMV7_MMU_READ_WRITE_CACHED \
+ (ARMV7_MMU_READ_WRITE \
+ | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B | ARM_MMU_SECT_S)
+#else
+ #define ARMV7_MMU_READ_WRITE_CACHED \
+ (ARMV7_MMU_READ_WRITE \
+ | ARM_MMU_SECT_TEX_0 | ARM_MMU_SECT_C | ARM_MMU_SECT_B)
+#endif
+
+#define ARMV7_MMU_DATA_READ_ONLY \
+ (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0)
+
+#define ARMV7_MMU_DATA_READ_ONLY_CACHED \
+ ARMV7_MMU_READ_ONLY_CACHED
+
+#define ARMV7_MMU_DATA_READ_WRITE \
+ (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_TEX_0)
+
+#define ARMV7_MMU_DATA_READ_WRITE_CACHED \
+ ARMV7_MMU_READ_WRITE_CACHED
+
+#define ARMV7_MMU_CODE \
+ (ARMV7_MMU_READ_ONLY | ARM_MMU_SECT_TEX_0)
+
+#define ARMV7_MMU_CODE_CACHED \
+ ARMV7_MMU_READ_ONLY_CACHED
+
+#define ARMV7_MMU_DEVICE \
+ (ARMV7_MMU_READ_WRITE | ARM_MMU_SECT_B)
+
+/** @} */
+
+/**
+ * @name Control Register Defines
+ *
+ * @{
+ */
+
+#define ARM_CP15_CTRL_TE (1U << 30)
+#define ARM_CP15_CTRL_AFE (1U << 29)
+#define ARM_CP15_CTRL_TRE (1U << 28)
+#define ARM_CP15_CTRL_NMFI (1U << 27)
+#define ARM_CP15_CTRL_EE (1U << 25)
+#define ARM_CP15_CTRL_VE (1U << 24)
+#define ARM_CP15_CTRL_XP (1U << 23)
+#define ARM_CP15_CTRL_U (1U << 22)
+#define ARM_CP15_CTRL_FI (1U << 21)
+#define ARM_CP15_CTRL_UWXN (1U << 20)
+#define ARM_CP15_CTRL_WXN (1U << 19)
+#define ARM_CP15_CTRL_HA (1U << 17)
+#define ARM_CP15_CTRL_L4 (1U << 15)
+#define ARM_CP15_CTRL_RR (1U << 14)
+#define ARM_CP15_CTRL_V (1U << 13)
+#define ARM_CP15_CTRL_I (1U << 12)
+#define ARM_CP15_CTRL_Z (1U << 11)
+#define ARM_CP15_CTRL_SW (1U << 10)
+#define ARM_CP15_CTRL_R (1U << 9)
+#define ARM_CP15_CTRL_S (1U << 8)
+#define ARM_CP15_CTRL_B (1U << 7)
+#define ARM_CP15_CTRL_CP15BEN (1U << 5)
+#define ARM_CP15_CTRL_C (1U << 2)
+#define ARM_CP15_CTRL_A (1U << 1)
+#define ARM_CP15_CTRL_M (1U << 0)
+
+/** @} */
+
+/**
+ * @name Domain Access Control Defines
+ *
+ * @{
+ */
+
+#define ARM_CP15_DAC_NO_ACCESS 0x0U
+#define ARM_CP15_DAC_CLIENT 0x1U
+#define ARM_CP15_DAC_MANAGER 0x3U
+#define ARM_CP15_DAC_DOMAIN(index, val) ((val) << (2 * index))
+
+/** @} */
+
+/**
+ * @name Fault Status Register Defines
+ *
+ * @{
+ */
+
+#define ARM_CP15_FAULT_STATUS_MASK 0x040F
+
+#define ARM_CP15_FSR_ALIGNMENT_FAULT 0x00000001
+#define ARM_CP15_FSR_BACKGROUND_FAULT 0x0000
+#define ARM_CP15_FSR_ACCESS_PERMISSION_FAULT 0x000D
+#define ARM_CP15_FSR_PRECISE_EXTERNAL_ABORT_FAULT 0x0008
+#define ARM_CP15_FSR_IMPRECISE_EXTERNAL_ABORT_FAULT 0x0406
+#define ARM_CP15_FSR_PRECISE_PARITY_ERROR_EXCEPTION 0x0006
+#define ARM_CP15_FSR_IMPRECISE_PARITY_ERROR_EXCEPTION 0x0408
+#define ARM_CP15_FSR_DEBUG_EVENT 0x0002
+
+/** @} */
+
+/**
+ * @name CTR, Cache Type Register Defines
+ *
+ * The format can be obtained from CP15 by call
+ * arm_cp15_cache_type_get_format(arm_cp15_get_cache_type());
+ *
+ * @{
+ */
+
+#define ARM_CP15_CACHE_TYPE_FORMAT_ARMV6 0
+#define ARM_CP15_CACHE_TYPE_FORMAT_ARMV7 4
+
+/** @} */
+
+/**
+ * @name CCSIDR, Cache Size ID Register Defines
+ *
+ * @{
+ */
+
+#define ARM_CP15_CACHE_CSS_ID_DATA 0
+#define ARM_CP15_CACHE_CSS_ID_INSTRUCTION 1
+#define ARM_CP15_CACHE_CSS_LEVEL(level) ((level) << 1)
+
+/** @} */
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_id_code(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c0, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_tcm_status(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c0, c0, 2\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_control(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c1, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_control(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c1, c0, 0\n"
+ "nop\n"
+ "nop\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ : "memory"
+ );
+}
+
+/**
+ * @name MMU Functions
+ *
+ * @{
+ */
+
+/**
+ * @brief Disable the MMU.
+ *
+ * This function will clean and invalidate eight cache lines before and after
+ * the current stack pointer.
+ *
+ * @param[in] cls The data cache line size.
+ *
+ * @return The current control register value.
+ */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_mmu_disable(uint32_t cls)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t ctrl;
+ uint32_t tmp_0;
+ uint32_t tmp_1;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[ctrl], c1, c0, 0\n"
+ "bic %[tmp_0], %[ctrl], #1\n"
+ "mcr p15, 0, %[tmp_0], c1, c0, 0\n"
+ "nop\n"
+ "nop\n"
+ "mov %[tmp_1], sp\n"
+ "rsb %[tmp_0], %[cls], #0\n"
+ "and %[tmp_0], %[tmp_0], %[tmp_1]\n"
+ "sub %[tmp_0], %[tmp_0], %[cls], asl #3\n"
+ "add %[tmp_1], %[tmp_0], %[cls], asl #4\n"
+ "1:\n"
+ "mcr p15, 0, %[tmp_0], c7, c14, 1\n"
+ "add %[tmp_0], %[tmp_0], %[cls]\n"
+ "cmp %[tmp_1], %[tmp_0]\n"
+ "bne 1b\n"
+ ARM_SWITCH_BACK
+ : [ctrl] "=&r" (ctrl),
+ [tmp_0] "=&r" (tmp_0),
+ [tmp_1] "=&r" (tmp_1)
+ ARM_SWITCH_ADDITIONAL_OUTPUT
+ : [cls] "r" (cls)
+ : "memory", "cc"
+ );
+
+ return ctrl;
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+*arm_cp15_get_translation_table_base(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t *base;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[base], c2, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return base;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_translation_table_base(uint32_t *base)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[base], c2, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [base] "r" (base)
+ );
+}
+
+/* Translation Table Base Control Register - DDI0301H arm1176jzfs TRM 3.2.15 */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_translation_table_base_control_register(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t ttb_cr;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[ttb_cr], c2, c0, 2\n"
+ ARM_SWITCH_BACK
+ : [ttb_cr] "=&r" (ttb_cr) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return ttb_cr;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_translation_table_base_control_register(uint32_t ttb_cr)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[ttb_cr], c2, c0, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [ttb_cr] "r" (ttb_cr)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_domain_access_control(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c3, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_domain_access_control(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c3, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_data_fault_status(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c5, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_data_fault_status(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c5, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_instruction_fault_status(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c5, c0, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_instruction_fault_status(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c5, c0, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+*arm_cp15_get_fault_address(void)
+{
+ ARM_SWITCH_REGISTERS;
+ void *mva;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[mva], c6, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [mva] "=&r" (mva) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return mva;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_fault_address(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c6, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_tlb_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c8, c7, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ );
+
+ /*
+ * ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition, Issue C,
+ * B3.10.1 General TLB maintenance requirements.
+ */
+ _ARM_Data_synchronization_barrier();
+ _ARM_Instruction_synchronization_barrier();
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_tlb_invalidate_entry(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_TLB_PREPARE_MVA(mva);
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c8, c7, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_tlb_invalidate_entry_all_asids(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_TLB_PREPARE_MVA(mva);
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c8, c7, 3\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_tlb_instruction_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c8, c5, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_tlb_instruction_invalidate_entry(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_TLB_PREPARE_MVA(mva);
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c8, c5, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_tlb_data_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c8, c6, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_tlb_data_invalidate_entry(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_TLB_PREPARE_MVA(mva);
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c8, c6, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_tlb_lockdown_entry(const void *mva)
+{
+ uint32_t arm_switch_reg;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "add %[arm_switch_reg], pc, #16\n"
+ "mcr p15, 0, %[arm_switch_reg], c7, c13, 1\n"
+ "mcr p15, 0, %[mva], c8, c7, 1\n"
+ "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
+ "orr %[arm_switch_reg], #0x1\n"
+ "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
+ "ldr %[mva], [%[mva]]\n"
+ "mrc p15, 0, %[arm_switch_reg], c10, c0, 0\n"
+ "bic %[arm_switch_reg], #0x1\n"
+ "mcr p15, 0, %[arm_switch_reg], c10, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [mva] "=r" (mva), [arm_switch_reg] "=&r" (arm_switch_reg)
+ : "[mva]" (mva)
+ );
+}
+
+/** @} */
+
+/**
+ * @name Cache Functions
+ *
+ * @{
+ */
+
+/* Read cache type register CTR */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_cache_type(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c0, c0, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* Extract format version from cache type CTR */
+ARM_CP15_TEXT_SECTION static inline int
+arm_cp15_cache_type_get_format(uint32_t ct)
+{
+ return (ct >> 29) & 0x7U;
+}
+
+/* Read size of smallest cache line of all instruction/data caches controlled by the processor */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_min_cache_line_size(void)
+{
+ uint32_t mcls = 0;
+ uint32_t ct = arm_cp15_get_cache_type();
+ uint32_t format = arm_cp15_cache_type_get_format(ct);
+
+ if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
+ /* ARMv7 format */
+ mcls = (1U << (ct & 0xf)) * 4;
+ } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
+ /* ARMv6 format */
+ uint32_t mask = (1U << 12) - 1;
+ uint32_t dcls = (ct >> 12) & mask;
+ uint32_t icls = ct & mask;
+
+ mcls = dcls <= icls ? dcls : icls;
+ }
+
+ return mcls;
+}
+
+/* Read size of smallest data cache lines */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_data_cache_line_size(void)
+{
+ uint32_t mcls = 0;
+ uint32_t ct = arm_cp15_get_cache_type();
+ uint32_t format = arm_cp15_cache_type_get_format(ct);
+
+ if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
+ /* ARMv7 format */
+ mcls = (1U << ((ct & 0xf0000) >> 16)) * 4;
+ } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
+ /* ARMv6 format */
+ uint32_t mask = (1U << 12) - 1;
+ mcls = (ct >> 12) & mask;
+ }
+
+ return mcls;
+}
+
+/* Read size of smallest instruction cache lines */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_instruction_cache_line_size(void)
+{
+ uint32_t mcls = 0;
+ uint32_t ct = arm_cp15_get_cache_type();
+ uint32_t format = arm_cp15_cache_type_get_format(ct);
+
+ if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
+ /* ARMv7 format */
+ mcls = (1U << (ct & 0x0000f)) * 4;
+ } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
+ /* ARMv6 format */
+ uint32_t mask = (1U << 12) - 1;
+ mcls = ct & mask;;
+ }
+
+ return mcls;
+}
+
+/* CCSIDR, Cache Size ID Register */
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_cache_size_id(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 1, %[val], c0, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_ccsidr_get_line_power(uint32_t ccsidr)
+{
+ return (ccsidr & 0x7) + 4;
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_ccsidr_get_associativity(uint32_t ccsidr)
+{
+ return ((ccsidr >> 3) & 0x3ff) + 1;
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_ccsidr_get_num_sets(uint32_t ccsidr)
+{
+ return ((ccsidr >> 13) & 0x7fff) + 1;
+}
+
+/* CLIDR, Cache Level ID Register */
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_cache_level_id(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 1, %[val], c0, c0, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_clidr_get_level_of_coherency(uint32_t clidr)
+{
+ return (clidr >> 24) & 0x7;
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_clidr_get_cache_type(uint32_t clidr, uint32_t level)
+{
+ return (clidr >> (3 * level)) & 0x7;
+}
+
+/* CSSELR, Cache Size Selection Register */
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_cache_size_selection(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 2, %[val], c0, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_cache_size_selection(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 2, %[val], c0, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_cache_size_id_for_level(uint32_t level_and_inst_dat)
+{
+ rtems_interrupt_level irq_level;
+ uint32_t ccsidr;
+
+ rtems_interrupt_local_disable(irq_level);
+ arm_cp15_set_cache_size_selection(level_and_inst_dat);
+ _ARM_Instruction_synchronization_barrier();
+ ccsidr = arm_cp15_get_cache_size_id();
+ rtems_interrupt_local_enable(irq_level);
+
+ return ccsidr;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_cache_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c7, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+/* ICIALLUIS, Instruction Cache Invalidate All to PoU, Inner Shareable */
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_instruction_cache_inner_shareable_invalidate_all(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c1, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+/* BPIALLIS, Branch Predictor Invalidate All, Inner Shareable */
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_branch_predictor_inner_shareable_invalidate_all(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c1, 6\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+/* BPIALL, Branch Predictor Invalidate All */
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_branch_predictor_invalidate_all(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c5, 6\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+/* Flush Prefetch Buffer - DDI0301H arm1176jzfs TRM 3.2.22 */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_flush_prefetch_buffer(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c5, 4\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_instruction_cache_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c5, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_instruction_cache_invalidate_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c5, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_instruction_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[set_and_way], c7, c5, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [set_and_way] "r" (set_and_way)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_instruction_cache_prefetch_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c13, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c6, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_invalidate_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c6, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[set_and_way], c7, c6, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [set_and_way] "r" (set_and_way)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_cache_invalidate_level(uint32_t level, uint32_t inst_data_fl)
+{
+ uint32_t ccsidr;
+ uint32_t line_power;
+ uint32_t associativity;
+ uint32_t way;
+ uint32_t way_shift;
+
+ ccsidr = arm_cp15_get_cache_size_id_for_level((level << 1) | inst_data_fl);
+
+ line_power = arm_ccsidr_get_line_power(ccsidr);
+ associativity = arm_ccsidr_get_associativity(ccsidr);
+ way_shift = __builtin_clz(associativity - 1);
+
+ for (way = 0; way < associativity; ++way) {
+ uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
+ uint32_t set;
+
+ for (set = 0; set < num_sets; ++set) {
+ uint32_t set_way = (way << way_shift)
+ | (set << line_power)
+ | (level << 1);
+
+ arm_cp15_data_cache_invalidate_line_by_set_and_way(set_way);
+ }
+ }
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_invalidate_all_levels(void)
+{
+ uint32_t clidr = arm_cp15_get_cache_level_id();
+ uint32_t loc = arm_clidr_get_level_of_coherency(clidr);
+ uint32_t level = 0;
+
+ for (level = 0; level < loc; ++level) {
+ uint32_t ctype = arm_clidr_get_cache_type(clidr, level);
+
+ /* Check if this level has a data cache or unified cache */
+ if (((ctype & (0x6)) == 2) || (ctype == 4)) {
+ arm_cp15_cache_invalidate_level(level, 0);
+ }
+ }
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_clean_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c10, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_clean_line_by_set_and_way(uint32_t set_and_way)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[set_and_way], c7, c10, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [set_and_way] "r" (set_and_way)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_clean_level(uint32_t level)
+{
+ uint32_t ccsidr;
+ uint32_t line_power;
+ uint32_t associativity;
+ uint32_t way;
+ uint32_t way_shift;
+
+ ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
+
+ line_power = arm_ccsidr_get_line_power(ccsidr);
+ associativity = arm_ccsidr_get_associativity(ccsidr);
+ way_shift = __builtin_clz(associativity - 1);
+
+ for (way = 0; way < associativity; ++way) {
+ uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
+ uint32_t set;
+
+ for (set = 0; set < num_sets; ++set) {
+ uint32_t set_way = (way << way_shift)
+ | (set << line_power)
+ | (level << 1);
+
+ arm_cp15_data_cache_clean_line_by_set_and_way(set_way);
+ }
+ }
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_clean_all_levels(void)
+{
+ uint32_t clidr = arm_cp15_get_cache_level_id();
+ uint32_t loc = arm_clidr_get_level_of_coherency(clidr);
+ uint32_t level = 0;
+
+ for (level = 0; level < loc; ++level) {
+ uint32_t ctype = arm_clidr_get_cache_type(clidr, level);
+
+ /* Check if this level has a data cache or unified cache */
+ if (((ctype & (0x6)) == 2) || (ctype == 4)) {
+ arm_cp15_data_cache_clean_level(level);
+ }
+ }
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_test_and_clean(void)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "1:\n"
+ "mrc p15, 0, r15, c7, c10, 3\n"
+ "bne 1b\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ :
+ : "memory"
+ );
+}
+
+/* In DDI0301H_arm1176jzfs_r0p7_trm
+ * 'MCR p15, 0, <Rd>, c7, c14, 0' means
+ * Clean and Invalidate Entire Data Cache
+ */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_clean_and_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c14, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_clean_and_invalidate_line(const void *mva)
+{
+ ARM_SWITCH_REGISTERS;
+
+ mva = ARM_CP15_CACHE_PREPARE_MVA(mva);
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[mva], c7, c14, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [mva] "r" (mva)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_clean_and_invalidate_line_by_set_and_way(uint32_t set_and_way)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[set_and_way], c7, c14, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [set_and_way] "r" (set_and_way)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_test_and_clean_and_invalidate(void)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "1:\n"
+ "mrc p15, 0, r15, c7, c14, 3\n"
+ "bne 1b\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ :
+ : "memory"
+ );
+}
+
+/** @} */
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_drain_write_buffer(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c10, 4\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_wait_for_interrupt(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t sbz = 0;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[sbz], c7, c0, 4\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [sbz] "r" (sbz)
+ : "memory"
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_multiprocessor_affinity(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t mpidr;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[mpidr], c0, c0, 5\n"
+ ARM_SWITCH_BACK
+ : [mpidr] "=&r" (mpidr) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return mpidr & 0xff;
+}
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cortex_a9_get_multiprocessor_cpu_id(void)
+{
+ return arm_cp15_get_multiprocessor_affinity() & 0xff;
+}
+
+#define ARM_CORTEX_A9_ACTL_FW (1U << 0)
+#define ARM_CORTEX_A9_ACTL_L2_PREFETCH_HINT_ENABLE (1U << 1)
+#define ARM_CORTEX_A9_ACTL_L1_PREFETCH_ENABLE (1U << 2)
+#define ARM_CORTEX_A9_ACTL_WRITE_FULL_LINE_OF_ZEROS_MODE (1U << 3)
+#define ARM_CORTEX_A9_ACTL_SMP (1U << 6)
+#define ARM_CORTEX_A9_ACTL_EXCL (1U << 7)
+#define ARM_CORTEX_A9_ACTL_ALLOC_IN_ONE_WAY (1U << 8)
+#define ARM_CORTEX_A9_ACTL_PARITY_ON (1U << 9)
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_auxiliary_control(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c1, c0, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_auxiliary_control(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c1, c0, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* ID_PFR1, Processor Feature Register 1 */
+
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_processor_feature_1(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c0, c1, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* VBAR, Vector Base Address Register, Security Extensions */
+
+ARM_CP15_TEXT_SECTION static inline void
+*arm_cp15_get_vector_base_address(void)
+{
+ ARM_SWITCH_REGISTERS;
+ void *base;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[base], c12, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return base;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_vector_base_address(void *base)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[base], c12, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [base] "r" (base)
+ );
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+*arm_cp15_get_hyp_vector_base_address(void)
+{
+ ARM_SWITCH_REGISTERS;
+ void *base;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 4, %[base], c12, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [base] "=&r" (base) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return base;
+}
+
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_hyp_vector_base_address(void *base)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 4, %[base], c12, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [base] "r" (base)
+ );
+}
+
+/* PMCCNTR */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_cycle_count(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c13, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMCCNTR */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_cycle_count(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c13, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMCEID0 */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_common_event_id_0(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c12, 6\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMCEID1 */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_common_event_id_1(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c12, 7\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+#define ARM_CP15_PMCLRSET_CYCLE_COUNTER 0x80000000
+
+/* PMCCNTENCLR */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_count_enable_clear(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c12, 2\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMCCNTENCLR */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_count_enable_clear(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c12, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMCCNTENSET */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_count_enable_set(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c12, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMCCNTENSET */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_count_enable_set(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c12, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+#define ARM_CP15_PMCR_IMP(x) ((x) << 24)
+#define ARM_CP15_PMCR_IDCODE(x) ((x) << 16)
+#define ARM_CP15_PMCR_N(x) ((x) << 11)
+#define ARM_CP15_PMCR_DP (1U << 5)
+#define ARM_CP15_PMCR_X (1U << 3)
+#define ARM_CP15_PMCR_D (1U << 4)
+#define ARM_CP15_PMCR_C (1U << 2)
+#define ARM_CP15_PMCR_P (1U << 1)
+#define ARM_CP15_PMCR_E (1U << 0)
+
+/* PMCR */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_control(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c12, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMCR */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_control(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c12, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMINTENCLR */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_interrupt_enable_clear(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c14, 2\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMINTENCLR */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_interrupt_enable_clear(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c14, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMINTENSET */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_interrupt_enable_set(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c14, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMINTENSET */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_interrupt_enable_set(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c14, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMOVSR */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_overflow_flag_status(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c12, 3\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMOVSR */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_overflow_flag_status(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c12, 3\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMOVSSET */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_overflow_flag_status_set(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c14, 3\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMOVSSET */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_overflow_flag_status_set(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c14, 3\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMSELR */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_event_counter_selection(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c12, 5\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMSELR */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_event_counter_selection(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c12, 5\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMSWINC */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_software_increment(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c12, 4\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMUSERENR */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_user_enable(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c14, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMUSERENR */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_user_enable(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c14, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMXEVCNTR */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_event_count(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c13, 2\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMXEVCNTR */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_event_count(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c13, 2\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* PMXEVTYPER */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_performance_monitors_event_type_select(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c9, c13, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* PMXEVTYPER */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_performance_monitors_event_type_select(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c9, c13, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* CNTFRQ */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_counter_frequency(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c14, c0, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTFRQ */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_counter_frequency(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c14, c0, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* CNTPCT */
+ARM_CP15_TEXT_SECTION static inline uint64_t
+arm_cp15_get_counter_physical_count(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint64_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrrc p15, 0, %Q[val], %R[val], c14\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTKCTL */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_counter_non_secure_pl1_control(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c14, c1, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTKCTL */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_counter_non_secure_pl1_control(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c14, c1, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* CNTP_TVAL */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_counter_pl1_physical_timer_value(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c14, c2, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTP_TVAL */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_counter_pl1_physical_timer_value(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c14, c2, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* CNTP_CTL */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_counter_pl1_physical_timer_control(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c14, c2, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTP_CTL */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_counter_pl1_physical_timer_control(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c14, c2, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* CNTV_TVAL */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_counter_pl1_virtual_timer_value(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c14, c2, 0\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTV_TVAL */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_counter_pl1_virtual_timer_value(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c14, c3, 0\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* CNTV_CTL */
+ARM_CP15_TEXT_SECTION static inline uint32_t
+arm_cp15_get_counter_pl1_virtual_timer_control(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint32_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrc p15, 0, %[val], c14, c3, 1\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTV_CTL */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_counter_pl1_virtual_timer_control(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcr p15, 0, %[val], c14, c3, 1\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* CNTVCT */
+ARM_CP15_TEXT_SECTION static inline uint64_t
+arm_cp15_get_counter_virtual_count(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint64_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrrc p15, 1, %Q[val], %R[val], c14\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTP_CVAL */
+ARM_CP15_TEXT_SECTION static inline uint64_t
+arm_cp15_get_counter_pl1_physical_compare_value(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint64_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrrc p15, 2, %Q[val], %R[val], c14\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTP_CVAL */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_counter_pl1_physical_compare_value(uint64_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcrr p15, 2, %Q[val], %R[val], c14\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* CNTV_CVAL */
+ARM_CP15_TEXT_SECTION static inline uint64_t
+arm_cp15_get_counter_pl1_virtual_compare_value(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint64_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrrc p15, 3, %Q[val], %R[val], c14\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTV_CVAL */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_counter_pl1_virtual_compare_value(uint64_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcrr p15, 3, %Q[val], %R[val], c14\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/* CNTVOFF */
+ARM_CP15_TEXT_SECTION static inline uint64_t
+arm_cp15_get_counter_virtual_offset(void)
+{
+ ARM_SWITCH_REGISTERS;
+ uint64_t val;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mrrc p15, 4, %Q[val], %R[val], c14\n"
+ ARM_SWITCH_BACK
+ : [val] "=&r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ );
+
+ return val;
+}
+
+/* CNTVOFF */
+ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_set_counter_virtual_offset(uint64_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "mcrr p15, 4, %Q[val], %R[val], c14\n"
+ ARM_SWITCH_BACK
+ : ARM_SWITCH_OUTPUT
+ : [val] "r" (val)
+ );
+}
+
+/**
+ * @brief Sets the @a section_flags for the address range [@a begin, @a end).
+ *
+ * @return Previous section flags of the first modified entry.
+ */
+uint32_t arm_cp15_set_translation_table_entries(
+ const void *begin,
+ const void *end,
+ uint32_t section_flags
+);
+
+void arm_cp15_set_exception_handler(
+ Arm_symbolic_exception_name exception,
+ void (*handler)(void)
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBCPU_SHARED_ARM_CP15_H */
diff --git a/cpukit/score/cpu/arm/preinstall.am b/cpukit/score/cpu/arm/preinstall.am
index 15a0f08c7e..3bdbb63561 100644
--- a/cpukit/score/cpu/arm/preinstall.am
+++ b/cpukit/score/cpu/arm/preinstall.am
@@ -59,3 +59,12 @@ $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h: rtems/score/cpuatomic.h $(PROJECT_IN
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpuatomic.h
+$(PROJECT_INCLUDE)/libcpu/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)/libcpu
+ @: > $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+
+$(PROJECT_INCLUDE)/libcpu/arm-cp15.h: include/libcpu/arm-cp15.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
+