From f587c5f019938e69f1dff07614b7463cc64dcbcc Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Mon, 23 Dec 2019 12:52:20 +0530 Subject: [PATCH] arch: arm64: mmu: Add zephyr execution regions Add zephyr execution regions(text, rodata, data, noinit, bss, etc.) with proper attributes to translation tables. Linker script has been modified a little to align these sections to minimum translation granule(4 kB). With this in place, code cannot be overwritten accidently as it is marked read only. Similarly, execution is prohibited from data/RW section as it is marked execute-never. Signed-off-by: Abhishek Shah --- arch/arm/core/aarch64/arm_mmu.c | 32 +++++++++++++++ include/arch/arm/aarch64/scripts/linker.ld | 48 ++++++++-------------- 2 files changed, 50 insertions(+), 30 deletions(-) diff --git a/arch/arm/core/aarch64/arm_mmu.c b/arch/arm/core/aarch64/arm_mmu.c index a6f8c42c185..1ee25f3c800 100644 --- a/arch/arm/core/aarch64/arm_mmu.c +++ b/arch/arm/core/aarch64/arm_mmu.c @@ -332,6 +332,31 @@ static void init_xlat_tables(const struct arm_mmu_region *region) } } +/* zephyr execution regions with appropriate attributes */ +static const struct arm_mmu_region mmu_zephyr_regions[] = { + + /* Mark text segment cacheable,read only and executable */ + MMU_REGION_FLAT_ENTRY("zephyr_code", + (uintptr_t)_image_text_start, + (uintptr_t)_image_text_size, + MT_CODE | MT_SECURE), + + /* Mark rodata segment cacheable, read only and execute-never */ + MMU_REGION_FLAT_ENTRY("zephyr_rodata", + (uintptr_t)_image_rodata_start, + (uintptr_t)_image_rodata_size, + MT_RODATA | MT_SECURE), + + /* Mark rest of the zephyr execution regions (data, bss, noinit, etc.) + * cacheable, read-write + * Note: read-write region is marked execute-ever internally + */ + MMU_REGION_FLAT_ENTRY("zephyr_data", + (uintptr_t)__kernel_ram_start, + (uintptr_t)__kernel_ram_size, + MT_NORMAL | MT_RW | MT_SECURE), +}; + static void setup_page_tables(void) { unsigned int index; @@ -355,6 +380,13 @@ static void setup_page_tables(void) if (region->size || region->attrs) init_xlat_tables(region); } + + /* setup translation table for zephyr execution regions */ + for (index = 0; index < ARRAY_SIZE(mmu_zephyr_regions); index++) { + region = &mmu_zephyr_regions[index]; + if (region->size || region->attrs) + init_xlat_tables(region); + } } static void enable_mmu_el1(unsigned int flags) diff --git a/include/arch/arm/aarch64/scripts/linker.ld b/include/arch/arm/aarch64/scripts/linker.ld index c2ab63887c1..6024579047d 100644 --- a/include/arch/arm/aarch64/scripts/linker.ld +++ b/include/arch/arm/aarch64/scripts/linker.ld @@ -39,6 +39,12 @@ #define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET) #endif +/* + * MMU currently supports 4 kB translation granule size, + * so all regions are required to be 4 kB aligned + */ +#define PAGE_SIZE 0x1000 + #if CONFIG_FLASH_LOAD_SIZE > 0 #define ROM_SIZE CONFIG_FLASH_LOAD_SIZE #else @@ -59,24 +65,14 @@ #define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS #endif -/* Set alignment to CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE - * to make linker section alignment comply with MPU granularity. - */ -#if defined(CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE) - _region_min_align = CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE; +#if defined(CONFIG_ARM_MMU) + _region_min_align = PAGE_SIZE; #else - /* If building without MPU support, use default 4-byte alignment. */ + /* If building without MMU support, use default 4-byte alignment. */ _region_min_align = 4; #endif -#if defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT) - #define MPU_ALIGN(region_size) \ - . = ALIGN(_region_min_align); \ - . = ALIGN( 1 << LOG2CEIL(region_size)) -#else - #define MPU_ALIGN(region_size) \ - . = ALIGN(_region_min_align) -#endif +#define MMU_ALIGN . = ALIGN(_region_min_align) MEMORY { @@ -139,9 +135,11 @@ SECTIONS #include #include + MMU_ALIGN; } GROUP_LINK_IN(ROMABLE_REGION) _image_text_end = .; + _image_text_size = _image_text_end - _image_text_start; #if defined (CONFIG_CPLUSPLUS) SECTION_PROLOGUE(.ARM.extab,,) @@ -199,27 +197,15 @@ SECTIONS #include #include - /* - * For XIP images, in order to avoid the situation when __data_rom_start - * is 32-bit aligned, but the actual data is placed right after rodata - * section, which may not end exactly at 32-bit border, pad rodata - * section, so __data_rom_start points at data and it is 32-bit aligned. - * - * On non-XIP images this may enlarge image size up to 3 bytes. This - * generally is not an issue, since modern ROM and FLASH memory is - * usually 4k aligned. - */ - . = ALIGN(4); } GROUP_LINK_IN(ROMABLE_REGION) #include + MMU_ALIGN; _image_rodata_end = .; - MPU_ALIGN(_image_rodata_end -_image_rom_start); + _image_rodata_size = _image_rodata_end - _image_rodata_start; _image_rom_end = .; - GROUP_END(ROMABLE_REGION) - /* * These are here according to 'arm-zephyr-elf-ld --verbose', * before data section. @@ -232,11 +218,13 @@ SECTIONS *(.igot) } + GROUP_END(ROMABLE_REGION) + GROUP_START(RAMABLE_REGION) . = RAM_ADDR; /* Align the start of image SRAM with the - * minimum granularity required by MPU. + * minimum granularity required by MMU. */ . = ALIGN(_region_min_align); _image_ram_start = .; @@ -248,7 +236,7 @@ SECTIONS #if defined(CONFIG_USERSPACE) #define APP_SHARED_ALIGN . = ALIGN(_region_min_align); -#define SMEM_PARTITION_ALIGN MPU_ALIGN +#define SMEM_PARTITION_ALIGN MMU_ALIGN #include