diff options
Diffstat (limited to 'bsps/aarch64/include')
-rw-r--r-- | bsps/aarch64/include/bsp/aarch64-mmu.h | 108 | ||||
-rw-r--r-- | bsps/aarch64/include/bsp/linker-symbols.h | 4 | ||||
-rw-r--r-- | bsps/aarch64/include/bsp/start.h | 2 | ||||
-rw-r--r-- | bsps/aarch64/include/dev/irq/arm-gic-arch.h | 25 |
4 files changed, 104 insertions, 35 deletions
diff --git a/bsps/aarch64/include/bsp/aarch64-mmu.h b/bsps/aarch64/include/bsp/aarch64-mmu.h index b1a471d534..8c69705230 100644 --- a/bsps/aarch64/include/bsp/aarch64-mmu.h +++ b/bsps/aarch64/include/bsp/aarch64-mmu.h @@ -37,17 +37,21 @@ #ifndef LIBBSP_AARCH64_SHARED_AARCH64_MMU_H #define LIBBSP_AARCH64_SHARED_AARCH64_MMU_H -#include <bsp/start.h> +#include <bsp/fatal.h> #include <bsp/linker-symbols.h> -#include <rtems/score/aarch64-system-registers.h> -#include <bspopts.h> +#include <bsp/start.h> #include <bsp/utility.h> +#include <bspopts.h> #include <libcpu/mmu-vmsav8-64.h> +#include <rtems/score/aarch64-system-registers.h> #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ +/* AArch64 uses levels 0, 1, 2, and 3 */ +#define MMU_MAX_SUBTABLE_PAGE_BITS ( 3 * MMU_BITS_PER_LEVEL + MMU_PAGE_BITS ) + typedef struct { uintptr_t begin; uintptr_t end; @@ -92,6 +96,10 @@ typedef struct { .end = (uintptr_t) bsp_section_rtemsstack_end, \ .flags = AARCH64_MMU_DATA_RW_CACHED \ }, { \ + .begin = (uintptr_t) bsp_section_noinit_begin, \ + .end = (uintptr_t) bsp_section_noinit_end, \ + .flags = AARCH64_MMU_DATA_RW_CACHED \ + }, { \ .begin = (uintptr_t) bsp_section_work_begin, \ .end = (uintptr_t) bsp_section_work_end, \ .flags = AARCH64_MMU_DATA_RW_CACHED \ @@ -145,8 +153,8 @@ BSP_START_TEXT_SECTION static inline rtems_status_code aarch64_mmu_page_table_alloc( uint64_t **page_table ) { /* First page table is already in use as TTB0 */ - static uintptr_t *current_page_table = - (uintptr_t *) bsp_translation_table_base; + static uintptr_t current_page_table = + (uintptr_t) bsp_translation_table_base; current_page_table += MMU_PAGE_SIZE; *page_table = (uint64_t *) current_page_table; @@ -212,15 +220,15 @@ aarch64_mmu_get_sub_table( BSP_START_TEXT_SECTION static inline rtems_status_code aarch64_mmu_map_block( uint64_t *page_table, - uintptr_t root_address, - uintptr_t addr, + uint64_t root_address, + uint64_t addr, uint64_t size, - uint32_t level, + int8_t level, uint64_t flags ) { uint32_t shift = ( 2 - level ) * MMU_BITS_PER_LEVEL + MMU_PAGE_BITS; - uintptr_t granularity = 1 << shift; + uint64_t granularity = 1LLU << shift; uint64_t page_flag = 0; if ( level == 2 ) { @@ -229,32 +237,35 @@ BSP_START_TEXT_SECTION static inline rtems_status_code aarch64_mmu_map_block( while ( size > 0 ) { uintptr_t index = aarch64_mmu_get_index( root_address, addr, shift ); - uintptr_t block_bottom = RTEMS_ALIGN_DOWN( addr, granularity ); + uint64_t block_bottom = RTEMS_ALIGN_DOWN( addr, granularity ); uint64_t chunk_size = granularity; /* check for perfect block match */ if ( block_bottom == addr ) { if ( size >= chunk_size ) { - /* when page_flag is set the last level must be a page descriptor */ - if ( page_flag || ( page_table[index] & MMU_DESC_TYPE_TABLE ) != MMU_DESC_TYPE_TABLE ) { - /* no sub-table, apply block properties */ - page_table[index] = addr | flags | page_flag; - size -= chunk_size; - addr += chunk_size; - continue; + /* level -1 can't contain block descriptors, fall through to subtable */ + if ( level != -1 ) { + /* when page_flag is set the last level must be a page descriptor */ + if ( page_flag || ( page_table[index] & MMU_DESC_TYPE_TABLE ) != MMU_DESC_TYPE_TABLE ) { + /* no sub-table, apply block properties */ + page_table[index] = addr | flags | page_flag; + size -= chunk_size; + addr += chunk_size; + continue; + } } } else { /* block starts on a boundary, but is short */ chunk_size = size; - /* it isn't possible to go beyond page table level 2 */ - if ( page_flag ) { + /* it isn't possible to go beyond page table level 2 */ + if ( page_flag ) { /* no sub-table, apply block properties */ page_table[index] = addr | flags | page_flag; size -= chunk_size; addr += chunk_size; continue; - } + } } } else { uintptr_t block_top = RTEMS_ALIGN_UP( addr, granularity ); @@ -266,7 +277,7 @@ BSP_START_TEXT_SECTION static inline rtems_status_code aarch64_mmu_map_block( } /* Deal with any subtable modification */ - uintptr_t new_root_address = root_address + index * granularity; + uint64_t new_root_address = root_address + index * granularity; uint64_t *sub_table = NULL; rtems_status_code sc; @@ -307,6 +318,33 @@ BSP_START_DATA_SECTION extern const aarch64_mmu_config_entry BSP_START_DATA_SECTION extern const size_t aarch64_mmu_config_table_size; +/* Get the maximum number of bits supported by this hardware */ +BSP_START_TEXT_SECTION static inline uint64_t +aarch64_mmu_get_cpu_pa_bits( void ) +{ + uint64_t id_reg = _AArch64_Read_id_aa64mmfr0_el1(); + + switch ( AARCH64_ID_AA64MMFR0_EL1_PARANGE_GET( id_reg ) ) { + case 0: + return 32; + case 1: + return 36; + case 2: + return 40; + case 3: + return 42; + case 4: + return 44; + case 5: + return 48; + case 6: + return 52; + default: + return 48; + } + return 48; +} + BSP_START_TEXT_SECTION static inline void aarch64_mmu_set_translation_table_entries( uint64_t *ttb, @@ -316,14 +354,19 @@ aarch64_mmu_set_translation_table_entries( /* Force alignemnt to 4k page size */ uintptr_t begin = RTEMS_ALIGN_DOWN( config->begin, MMU_PAGE_SIZE ); uintptr_t end = RTEMS_ALIGN_UP( config->end, MMU_PAGE_SIZE ); + uint64_t max_mappable = 1LLU << aarch64_mmu_get_cpu_pa_bits(); rtems_status_code sc; + if ( begin >= max_mappable || end > max_mappable ) { + bsp_fatal( BSP_FATAL_MMU_ADDRESS_INVALID ); + } + sc = aarch64_mmu_map_block( ttb, 0x0, begin, end - begin, - 0, + -1, config->flags ); @@ -343,7 +386,7 @@ BSP_START_TEXT_SECTION static inline void aarch64_mmu_setup_translation_table( aarch64_mmu_page_table_set_blocks( ttb, (uintptr_t) NULL, - MMU_TOP_LEVEL_PAGE_BITS, + MMU_MAX_SUBTABLE_PAGE_BITS, 0 ); @@ -362,7 +405,8 @@ aarch64_mmu_enable( void ) /* CPUECTLR_EL1.SMPEN is already set on ZynqMP and is not writable */ - /* Invalidate cache */ + /* Flush and invalidate cache */ + rtems_cache_flush_entire_data(); rtems_cache_invalidate_entire_data(); /* Enable MMU and cache */ @@ -376,7 +420,13 @@ aarch64_mmu_disable( void ) { uint64_t sctlr; - /* Enable MMU and cache */ + /* + * Flush data cache before disabling the MMU. While the MMU is disabled, all + * accesses are treated as uncached device memory. + */ + rtems_cache_flush_entire_data(); + + /* Disable MMU */ sctlr = _AArch64_Read_sctlr_el1(); sctlr &= ~(AARCH64_SCTLR_EL1_M); _AArch64_Write_sctlr_el1( sctlr ); @@ -385,10 +435,12 @@ aarch64_mmu_disable( void ) BSP_START_TEXT_SECTION static inline void aarch64_mmu_setup( void ) { /* Set TCR */ - /* 128GB/36 bits mappable (64-0x1c) */ + /* 256TB/48 bits mappable (64-0x10) */ _AArch64_Write_tcr_el1( - AARCH64_TCR_EL1_T0SZ( 0x1c ) | AARCH64_TCR_EL1_IRGN0( 0x1 ) | - AARCH64_TCR_EL1_ORGN0( 0x1 ) | AARCH64_TCR_EL1_SH0( 0x3 ) | AARCH64_TCR_EL1_TG0( 0x0 ) + AARCH64_TCR_EL1_T0SZ( 0x10 ) | AARCH64_TCR_EL1_IRGN0( 0x1 ) | + AARCH64_TCR_EL1_ORGN0( 0x1 ) | AARCH64_TCR_EL1_SH0( 0x3 ) | + AARCH64_TCR_EL1_TG0( 0x0 ) | AARCH64_TCR_EL1_IPS( 0x5ULL ) | + AARCH64_TCR_EL1_EPD1 ); /* Set MAIR */ diff --git a/bsps/aarch64/include/bsp/linker-symbols.h b/bsps/aarch64/include/bsp/linker-symbols.h index 38c655ba97..222c217abb 100644 --- a/bsps/aarch64/include/bsp/linker-symbols.h +++ b/bsps/aarch64/include/bsp/linker-symbols.h @@ -108,6 +108,10 @@ LINKER_SYMBOL(bsp_section_rtemsstack_begin) LINKER_SYMBOL(bsp_section_rtemsstack_end) LINKER_SYMBOL(bsp_section_rtemsstack_size) +LINKER_SYMBOL(bsp_section_noinit_begin) +LINKER_SYMBOL(bsp_section_noinit_end) +LINKER_SYMBOL(bsp_section_noinit_size) + LINKER_SYMBOL(bsp_section_work_begin) LINKER_SYMBOL(bsp_section_work_end) LINKER_SYMBOL(bsp_section_work_size) diff --git a/bsps/aarch64/include/bsp/start.h b/bsps/aarch64/include/bsp/start.h index 586eec4f48..f0af5be841 100644 --- a/bsps/aarch64/include/bsp/start.h +++ b/bsps/aarch64/include/bsp/start.h @@ -172,7 +172,7 @@ AArch64_start_set_vector_base(void) /* * Do not use bsp_vector_table_begin == 0, since this will get optimized away. */ - if (bsp_vector_table_end != bsp_vector_table_size) { + if (&bsp_vector_table_end[0] != &bsp_vector_table_size[0]) { __asm__ volatile ( "msr VBAR_EL1, %[vtable]\n" : : [vtable] "r" (bsp_start_vector_table_begin) diff --git a/bsps/aarch64/include/dev/irq/arm-gic-arch.h b/bsps/aarch64/include/dev/irq/arm-gic-arch.h index f1b6fdc03d..5ca2c7314e 100644 --- a/bsps/aarch64/include/dev/irq/arm-gic-arch.h +++ b/bsps/aarch64/include/dev/irq/arm-gic-arch.h @@ -3,9 +3,10 @@ /** * @file * - * @ingroup RTEMSBSPsAArch64Shared + * @ingroup DevIRQGIC * - * @brief AArch64-specific ARM GICv3 handlers. + * @brief This header file provides interfaces of the ARM Generic Interrupt + * Controller (GIC) support specific to the AArch64 architecture. */ /* @@ -46,14 +47,24 @@ extern "C" { #endif -static inline void arm_interrupt_handler_dispatch(rtems_vector_number vector) +/** + * @addtogroup DevIRQGIC + * + * @{ + */ + +static inline uint32_t arm_interrupt_enable_interrupts(void) { - uint32_t interrupt_level = _CPU_ISR_Get_level(); + uint32_t status = _CPU_ISR_Get_level(); /* Enable interrupts for nesting */ _CPU_ISR_Set_level(0); - bsp_interrupt_handler_dispatch(vector); + return status; +} + +static inline void arm_interrupt_restore_interrupts(uint32_t status) +{ /* Restore interrupts to previous level */ - _CPU_ISR_Set_level(interrupt_level); + _CPU_ISR_Set_level(status); } static inline void arm_interrupt_facility_set_exception_handler(void) @@ -68,6 +79,8 @@ static inline void arm_interrupt_facility_set_exception_handler(void) ); } +/** @} */ + #ifdef __cplusplus } #endif |