arch: arm: core: aarch32: introduce basic ARMv7 MMU support

An initial implementation for memory management using the ARMv7 MMU.
A single L1 translation table for the whole 4 GB address space is al-
ways present, a configurable number of L2 page tables are linked to
the L1 table based on the static memory area configuration at boot
time, or whenever arch_mem_map/arch_mem_unmap are called at run-time.

Currently, a CPU with the Multiprocessor Extensions and execution at
PL1 are always assumed. Userspace-related features or thread stack
guard pages are not yet supported. Neither are LPAE, PXN or TEX re-
mapping. All mappings are currently assigned to the same domain. Re-
garding the permissions model, access permissions are specified using
the AP[2:1] model rather than the older AP[2:0] model, which, accor-
ding to ARM's documentation, is deprecated and should no longer be
used. The newer model adds some complexity when it comes to mapping
pages as unaccessible (the AP[2:1] model doesn't support explicit
specification of "no R, no W" permissions, it's always at least "RO"),
this is accomplished by invalidating the ID bits of the respective
page's PTE.

Includes sources, Kconfig integration, adjusted CMakeLists and the
modified linker command file (proper section alignment!).

Signed-off-by: Immo Birnbaum <Immo.Birnbaum@weidmueller.com>
This commit is contained in:
Immo Birnbaum 2021-07-15 10:33:58 +02:00 committed by Carles Cufí
commit 70c403c215
10 changed files with 1475 additions and 2 deletions

View file

@ -71,6 +71,8 @@ extern "C" {
*/
#if defined(CONFIG_USERSPACE)
#define Z_THREAD_MIN_STACK_ALIGN CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE
#elif defined(CONFIG_ARM_MMU)
#define Z_THREAD_MIN_STACK_ALIGN CONFIG_ARM_MMU_REGION_MIN_ALIGN_AND_SIZE
#else
#define Z_THREAD_MIN_STACK_ALIGN ARCH_STACK_PTR_ALIGN
#endif
@ -190,6 +192,9 @@ extern "C" {
#include <arch/arm/aarch32/mpu/nxp_mpu.h>
#endif /* CONFIG_CPU_HAS_NXP_MPU */
#endif /* CONFIG_ARM_MPU */
#ifdef CONFIG_ARM_AARCH32_MMU
#include <arch/arm/aarch32/mmu/arm_mmu.h>
#endif /* CONFIG_ARM_AARCH32_MMU */
#ifdef __cplusplus
}

View file

@ -58,6 +58,8 @@
*/
#if defined(CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE)
_region_min_align = CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE;
#elif defined(CONFIG_ARM_AARCH32_MMU)
_region_min_align = CONFIG_MMU_PAGE_SIZE;
#else
/* If building without MPU support, use default 4-byte alignment. */
_region_min_align = 4;
@ -72,6 +74,8 @@ _region_min_align = 4;
. = ALIGN(_region_min_align)
#endif
#define BSS_ALIGN ALIGN(_region_min_align)
MEMORY
{
FLASH (rx) : ORIGIN = ROM_ADDR, LENGTH = ROM_SIZE
@ -127,7 +131,11 @@ SECTIONS
SECTION_PROLOGUE(_TEXT_SECTION_NAME,,)
{
. = ALIGN(_region_min_align);
__text_region_start = .;
#ifndef CONFIG_XIP
z_mapped_start = .;
#endif
#include <linker/kobject-text.ld>
@ -144,6 +152,7 @@ SECTIONS
} GROUP_LINK_IN(ROMABLE_REGION)
__text_region_end = .;
. = ALIGN(_region_min_align);
#if defined (CONFIG_CPLUSPLUS)
SECTION_PROLOGUE(.ARM.extab,,)
@ -170,6 +179,7 @@ SECTIONS
__exidx_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
. = ALIGN(_region_min_align);
__rodata_region_start = .;
#include <linker/common-rom.ld>
@ -210,6 +220,7 @@ SECTIONS
__rodata_region_end = .;
__rom_region_end = .;
MPU_ALIGN(__rodata_region_end - __rom_region_start);
_image_rom_end_order = (LOG2CEIL(__rom_region_end) - 1) << 1;
GROUP_END(ROMABLE_REGION)
@ -234,6 +245,9 @@ SECTIONS
*/
. = ALIGN(_region_min_align);
_image_ram_start = .;
#ifdef CONFIG_XIP
z_mapped_start = .;
#endif
/* Located in generated directory. This file is populated by the
* zephyr_linker_sources() Cmake function.
@ -250,7 +264,7 @@ SECTIONS
_app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME);
#endif /* CONFIG_USERSPACE */
SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD), BSS_ALIGN)
{
/*
* For performance, BSS section is assumed to be 4 byte aligned and
@ -316,8 +330,10 @@ SECTIONS
/* Define linker symbols */
. = ALIGN(_region_min_align);
_image_ram_end = .;
_end = .; /* end of image */
z_mapped_end = .;
__kernel_ram_end = RAM_ADDR + RAM_SIZE;
__kernel_ram_size = __kernel_ram_end - __kernel_ram_start;

View file

@ -0,0 +1,105 @@
/*
* ARMv7 MMU support
*
* Copyright (c) 2021 Weidmueller Interface GmbH & Co. KG
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_ARCH_AARCH32_ARM_MMU_H_
#define ZEPHYR_INCLUDE_ARCH_AARCH32_ARM_MMU_H_
#ifndef _ASMLANGUAGE
/*
* Comp.:
* ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition,
* ARM document ID DDI0406C Rev. d, March 2018
* Memory type definitions:
* Table B3-10, chap. B3.8.2, p. B3-1363f.
* Outer / inner cache attributes for cacheable memory:
* Table B3-11, chap. B3.8.2, p. B3-1364
*/
/*
* The following definitions are used when specifying a memory
* range to be mapped at boot time using the MMU_REGION_ENTRY
* macro.
*/
#define MT_STRONGLY_ORDERED BIT(0)
#define MT_DEVICE BIT(1)
#define MT_NORMAL BIT(2)
#define MT_MASK 0x7
#define MPERM_R BIT(3)
#define MPERM_W BIT(4)
#define MPERM_X BIT(5)
#define MPERM_UNPRIVILEGED BIT(6)
#define MATTR_NON_SECURE BIT(7)
#define MATTR_NON_GLOBAL BIT(8)
#define MATTR_SHARED BIT(9)
#define MATTR_CACHE_OUTER_WB_WA BIT(10)
#define MATTR_CACHE_OUTER_WT_nWA BIT(11)
#define MATTR_CACHE_OUTER_WB_nWA BIT(12)
#define MATTR_CACHE_INNER_WB_WA BIT(13)
#define MATTR_CACHE_INNER_WT_nWA BIT(14)
#define MATTR_CACHE_INNER_WB_nWA BIT(15)
#define MATTR_MAY_MAP_L1_SECTION BIT(16)
/*
* The following macros are used for adding constant entries
* mmu_regions array of the mmu_config struct. Use MMU_REGION_ENTRY
* for the specification of mappings whose PA and VA differ,
* the use of MMU_REGION_FLAT_ENTRY always results in an identity
* mapping, which are used for the mappings of the Zephyr image's
* code and data.
*/
#define MMU_REGION_ENTRY(_name, _base_pa, _base_va, _size, _attrs) \
{\
.name = _name, \
.base_pa = _base_pa, \
.base_va = _base_va, \
.size = _size, \
.attrs = _attrs, \
}
#define MMU_REGION_FLAT_ENTRY(name, adr, sz, attrs) \
MMU_REGION_ENTRY(name, adr, adr, sz, attrs)
/* Region definition data structure */
struct arm_mmu_region {
/* Region Base Physical Address */
uintptr_t base_pa;
/* Region Base Virtual Address */
uintptr_t base_va;
/* Region size */
size_t size;
/* Region Name */
const char *name;
/* Region Attributes */
uint32_t attrs;
};
/* MMU configuration data structure */
struct arm_mmu_config {
/* Number of regions */
uint32_t num_regions;
/* Regions */
const struct arm_mmu_region *mmu_regions;
};
/*
* Reference to the MMU configuration.
*
* This struct is defined and populated for each SoC (in the SoC definition),
* and holds the build-time configuration information for the fixed MMU
* regions enabled during kernel initialization.
*/
extern const struct arm_mmu_config mmu_config;
int z_arm_mmu_init(void);
#endif /* _ASMLANGUAGE */
#endif /* ZEPHYR_INCLUDE_ARCH_AARCH32_ARM_MMU_H_ */