diff options
Diffstat (limited to 'bsps/aarch64/include')
-rw-r--r-- | bsps/aarch64/include/bsp/aarch64-mmu.h | 154 | ||||
-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 | 29 |
4 files changed, 121 insertions, 68 deletions
diff --git a/bsps/aarch64/include/bsp/aarch64-mmu.h b/bsps/aarch64/include/bsp/aarch64-mmu.h index a5f6e846f3..8c69705230 100644 --- a/bsps/aarch64/include/bsp/aarch64-mmu.h +++ b/bsps/aarch64/include/bsp/aarch64-mmu.h @@ -37,54 +37,20 @@ #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 */ -/* VMSAv8 Long-descriptor fields */ -#define MMU_DESC_AF BSP_BIT64( 10 ) -#define MMU_DESC_SH_INNER ( BSP_BIT64( 9 ) | BSP_BIT64( 8 ) ) -#define MMU_DESC_WRITE_DISABLE BSP_BIT64( 7 ) -/* PAGE and TABLE flags are the same bit, but only apply on certain levels */ -#define MMU_DESC_TYPE_TABLE BSP_BIT64( 1 ) -#define MMU_DESC_TYPE_PAGE BSP_BIT64( 1 ) -#define MMU_DESC_VALID BSP_BIT64( 0 ) -#define MMU_DESC_MAIR_ATTR( val ) BSP_FLD64( val, 2, 3 ) -#define MMU_DESC_MAIR_ATTR_GET( reg ) BSP_FLD64GET( reg, 2, 3 ) -#define MMU_DESC_MAIR_ATTR_SET( reg, val ) BSP_FLD64SET( reg, val, 2, 3 ) -#define MMU_DESC_PAGE_TABLE_MASK 0xFFFFFFFFF000LL - -/* Page table configuration */ -#define MMU_PAGE_BITS 12 -#define MMU_PAGE_SIZE ( 1 << MMU_PAGE_BITS ) -#define MMU_BITS_PER_LEVEL 9 -#define MMU_TOP_LEVEL_PAGE_BITS ( 2 * MMU_BITS_PER_LEVEL + MMU_PAGE_BITS ) - -#define AARCH64_MMU_FLAGS_BASE \ - ( MMU_DESC_VALID | MMU_DESC_SH_INNER | MMU_DESC_AF ) - -#define AARCH64_MMU_DATA_RO_CACHED \ - ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 3 ) | MMU_DESC_WRITE_DISABLE ) -#define AARCH64_MMU_CODE_CACHED AARCH64_MMU_DATA_RO_CACHED -#define AARCH64_MMU_CODE_RW_CACHED AARCH64_MMU_DATA_RW_CACHED - -#define AARCH64_MMU_DATA_RO \ - ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 1 ) | MMU_DESC_WRITE_DISABLE ) -#define AARCH64_MMU_CODE AARCH64_MMU_DATA_RO -#define AARCH64_MMU_CODE_RW AARCH64_MMU_DATA_RW - -/* RW implied by not ORing in RO */ -#define AARCH64_MMU_DATA_RW_CACHED \ - ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 3 ) ) -#define AARCH64_MMU_DATA_RW \ - ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 1 ) ) -#define AARCH64_MMU_DEVICE ( AARCH64_MMU_FLAGS_BASE | MMU_DESC_MAIR_ATTR( 0 ) ) +/* 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; @@ -130,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 \ @@ -183,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; @@ -250,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 ) { @@ -267,23 +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 ) { + /* 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 ) { /* 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; } } else { uintptr_t block_top = RTEMS_ALIGN_UP( addr, granularity ); @@ -295,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; @@ -336,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, @@ -345,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 ); @@ -372,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 ); @@ -391,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 */ @@ -400,13 +415,32 @@ aarch64_mmu_enable( void ) _AArch64_Write_sctlr_el1( sctlr ); } +BSP_START_TEXT_SECTION static inline void +aarch64_mmu_disable( void ) +{ + uint64_t sctlr; + + /* + * 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 ); +} + 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 0911320851..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,12 +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(); - AArch64_interrupt_enable(1); - bsp_interrupt_handler_dispatch(vector); - _CPU_ISR_Set_level(interrupt_level); + uint32_t status = _CPU_ISR_Get_level(); + /* Enable interrupts for nesting */ + _CPU_ISR_Set_level(0); + return status; +} + +static inline void arm_interrupt_restore_interrupts(uint32_t status) +{ + /* Restore interrupts to previous level */ + _CPU_ISR_Set_level(status); } static inline void arm_interrupt_facility_set_exception_handler(void) @@ -66,6 +79,8 @@ static inline void arm_interrupt_facility_set_exception_handler(void) ); } +/** @} */ + #ifdef __cplusplus } #endif |