Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:42

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup aarch64_start
0007  *
0008  * @brief AArch64 MMU configuration.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2021 On-Line Applications Research Corporation (OAR)
0013  * Written by Kinsey Moore <kinsey.moore@oarcorp.com>
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 LIBBSP_AARCH64_SHARED_AARCH64_MMU_H
0038 #define LIBBSP_AARCH64_SHARED_AARCH64_MMU_H
0039 
0040 #include <bsp/fatal.h>
0041 #include <bsp/linker-symbols.h>
0042 #include <bsp/start.h>
0043 #include <bsp/utility.h>
0044 #include <bspopts.h>
0045 #include <libcpu/mmu-vmsav8-64.h>
0046 #include <rtems/score/aarch64-system-registers.h>
0047 
0048 #ifdef __cplusplus
0049 extern "C" {
0050 #endif /* __cplusplus */
0051 
0052 typedef struct {
0053   uintptr_t begin;
0054   uintptr_t end;
0055   uint64_t flags;
0056 } aarch64_mmu_config_entry;
0057 
0058 #define AARCH64_MMU_DEFAULT_SECTIONS \
0059   { \
0060     .begin = (uintptr_t) bsp_section_fast_text_begin, \
0061     .end = (uintptr_t) bsp_section_fast_text_end, \
0062     .flags = AARCH64_MMU_CODE_CACHED \
0063   }, { \
0064     .begin = (uintptr_t) bsp_section_fast_data_begin, \
0065     .end = (uintptr_t) bsp_section_fast_data_end, \
0066     .flags = AARCH64_MMU_DATA_RW_CACHED \
0067   }, { \
0068     .begin = (uintptr_t) bsp_section_start_begin, \
0069     .end = (uintptr_t) bsp_section_start_end, \
0070     .flags = AARCH64_MMU_CODE_CACHED \
0071   }, { \
0072     .begin = (uintptr_t) bsp_section_vector_begin, \
0073     .end = (uintptr_t) bsp_section_vector_end, \
0074     .flags = AARCH64_MMU_DATA_RW_CACHED \
0075   }, { \
0076     .begin = (uintptr_t) bsp_section_text_begin, \
0077     .end = (uintptr_t) bsp_section_text_end, \
0078     .flags = AARCH64_MMU_CODE_CACHED \
0079   }, { \
0080     .begin = (uintptr_t) bsp_section_rodata_begin, \
0081     .end = (uintptr_t) bsp_section_rodata_end, \
0082     .flags = AARCH64_MMU_DATA_RO_CACHED \
0083   }, { \
0084     .begin = (uintptr_t) bsp_section_data_begin, \
0085     .end = (uintptr_t) bsp_section_data_end, \
0086     .flags = AARCH64_MMU_DATA_RW_CACHED \
0087   }, { \
0088     .begin = (uintptr_t) bsp_section_bss_begin, \
0089     .end = (uintptr_t) bsp_section_bss_end, \
0090     .flags = AARCH64_MMU_DATA_RW_CACHED \
0091   }, { \
0092     .begin = (uintptr_t) bsp_section_rtemsstack_begin, \
0093     .end = (uintptr_t) bsp_section_rtemsstack_end, \
0094     .flags = AARCH64_MMU_DATA_RW_CACHED \
0095   }, { \
0096     .begin = (uintptr_t) bsp_section_noinit_begin, \
0097     .end = (uintptr_t) bsp_section_noinit_end, \
0098     .flags = AARCH64_MMU_DATA_RW_CACHED \
0099   }, { \
0100     .begin = (uintptr_t) bsp_section_work_begin, \
0101     .end = (uintptr_t) bsp_section_work_end, \
0102     .flags = AARCH64_MMU_DATA_RW_CACHED \
0103   }, { \
0104     .begin = (uintptr_t) bsp_section_stack_begin, \
0105     .end = (uintptr_t) bsp_section_stack_end, \
0106     .flags = AARCH64_MMU_DATA_RW_CACHED \
0107   }, { \
0108     .begin = (uintptr_t) bsp_section_nocache_begin, \
0109     .end = (uintptr_t) bsp_section_nocache_end, \
0110     .flags = AARCH64_MMU_DEVICE \
0111   }, { \
0112     .begin = (uintptr_t) bsp_section_nocachenoload_begin, \
0113     .end = (uintptr_t) bsp_section_nocachenoload_end, \
0114     .flags = AARCH64_MMU_DEVICE \
0115   }, { \
0116     .begin = (uintptr_t) bsp_translation_table_base, \
0117     .end = (uintptr_t) bsp_translation_table_end, \
0118     .flags = AARCH64_MMU_DATA_RW_CACHED \
0119   }, { \
0120 /*
0121  * The vector table must be in writable and executable memory as it stores both
0122  * exception code and the mutable pointer to which it jumps
0123  */ \
0124     .begin = (uintptr_t) bsp_start_vector_table_begin, \
0125     .end = (uintptr_t) bsp_start_vector_table_end, \
0126     .flags = AARCH64_MMU_CODE_RW_CACHED \
0127   }
0128 
0129 /**
0130  * @brief This is the AArch64 MMU configuration table.
0131  *
0132  * The default table is provided by the BSP.  Applications may provide their
0133  * own.
0134  */
0135 extern const aarch64_mmu_config_entry aarch64_mmu_config_table[];
0136 
0137 /**
0138  * @brief This is the count of entries in the AArch64 MMU configuration table.
0139  *
0140  * The default table is provided by the BSP.  Applications may provide their
0141  * own.
0142  */
0143 extern const size_t aarch64_mmu_config_table_size;
0144 
0145 /**
0146  * @brief This structure represents the state to maintain the MMU translation
0147  *   tables.
0148  */
0149 typedef struct {
0150   /**
0151    * @brief This member references the translation table base.
0152    */
0153   uint64_t *ttb;
0154 
0155   /**
0156    * @brief This member contains the count of used page tables.
0157    *
0158    * A maximum of ::AARCH64_MMU_TRANSLATION_TABLE_PAGES can be used.
0159    */
0160   size_t used_page_tables;
0161 } aarch64_mmu_control;
0162 
0163 /**
0164  * @brief This object is used to maintain the MMU translation tables.
0165  */
0166 extern aarch64_mmu_control aarch64_mmu_instance;
0167 
0168 /**
0169  * @brief Sets the MMU translation table entries associated with the memory
0170  *   region.
0171  *
0172  * @param[in, out] control is a reference to the MMU control state.
0173  *
0174  * @param[in] config is the configuration entry with the memory region and
0175  *   region attributes.
0176  *
0177  * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
0178  *
0179  * @retval ::RTEMS_INVALID_ADDRESS The begin address of the memory region
0180  *   cannot be mapped by the MMU.
0181  *
0182  * @retval ::RTEMS_INVALID_SIZE The end address of the memory region cannot be
0183  *   mapped by the MMU.
0184  *
0185  * @retval ::RTEMS_TOO_MANY There was no page table entry available to perform
0186  *   the mapping.
0187  */
0188 rtems_status_code aarch64_mmu_set_translation_table_entries(
0189   aarch64_mmu_control *control,
0190   const aarch64_mmu_config_entry *config
0191 );
0192 
0193 /**
0194  * @brief Sets up the MMU translation table.
0195  *
0196  * The memory regions of the configuration table are mapped by the MMU.  If a
0197  * mapping is infeasible, then the BSP fatal error
0198  * ::AARCH64_FATAL_MMU_CANNOT_MAP_BLOCK will be issued.
0199  *
0200  * @param[in, out] control is a reference to the MMU control state.
0201  *
0202  * @param[in] config_table is the configuration table with memory regions and
0203  *   region attributes.
0204  *
0205  * @param config_count is the count of configuration table entries.
0206  */
0207 void aarch64_mmu_setup_translation_table(
0208   aarch64_mmu_control *control,
0209   const aarch64_mmu_config_entry *config_table,
0210   size_t config_count
0211 );
0212 
0213 BSP_START_TEXT_SECTION static inline void
0214 aarch64_mmu_enable( const aarch64_mmu_control *control )
0215 {
0216   uint64_t sctlr;
0217 
0218   /* CPUECTLR_EL1.SMPEN is already set on ZynqMP and is not writable */
0219 
0220   /* Flush and invalidate cache */
0221   rtems_cache_flush_entire_data();
0222 
0223   _AArch64_Write_ttbr0_el1( (uintptr_t) control->ttb );
0224   _AARCH64_Instruction_synchronization_barrier();
0225 
0226   /* Enable MMU and cache */
0227   sctlr = _AArch64_Read_sctlr_el1();
0228   sctlr |= AARCH64_SCTLR_EL1_I | AARCH64_SCTLR_EL1_C | AARCH64_SCTLR_EL1_M;
0229   _AArch64_Write_sctlr_el1( sctlr );
0230 }
0231 
0232 BSP_START_TEXT_SECTION static inline void
0233 aarch64_mmu_disable( void )
0234 {
0235   uint64_t sctlr;
0236 
0237   /*
0238    * Flush data cache before disabling the MMU. While the MMU is disabled, all
0239    * accesses are treated as uncached device memory.
0240    */
0241   rtems_cache_flush_entire_data();
0242 
0243   /* Disable MMU */
0244   sctlr = _AArch64_Read_sctlr_el1();
0245   sctlr &= ~(AARCH64_SCTLR_EL1_M);
0246   _AArch64_Write_sctlr_el1( sctlr );
0247 }
0248 
0249 BSP_START_TEXT_SECTION static inline void aarch64_mmu_setup( void )
0250 {
0251   /* Set TCR */
0252   /* 256TB/48 bits mappable (64-0x10) */
0253   _AArch64_Write_tcr_el1(
0254     AARCH64_TCR_EL1_T0SZ( 0x10 ) | AARCH64_TCR_EL1_IRGN0( 0x1 ) |
0255     AARCH64_TCR_EL1_ORGN0( 0x1 ) | AARCH64_TCR_EL1_SH0( 0x3 ) |
0256     AARCH64_TCR_EL1_TG0( 0x0 ) | AARCH64_TCR_EL1_IPS( 0x5ULL ) |
0257     AARCH64_TCR_EL1_EPD1
0258   );
0259 
0260   /* Set MAIR */
0261   _AArch64_Write_mair_el1(
0262     AARCH64_MAIR_EL1_ATTR0( 0x0 ) | AARCH64_MAIR_EL1_ATTR1( 0x4 ) |
0263     AARCH64_MAIR_EL1_ATTR2( 0x44 ) | AARCH64_MAIR_EL1_ATTR3( 0xFF )
0264   );
0265 }
0266 
0267 #ifdef __cplusplus
0268 }
0269 #endif /* __cplusplus */
0270 
0271 #endif /* LIBBSP_AARCH64_SHARED_AARCH64_MMU_H */