From cbcf79698e4534aa3b7f568217a2a593b8e8b932 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 17 Jul 2024 00:25:15 -0400 Subject: [PATCH] arm64: demand_paging: add support for on-demand mappings This makes ARM64 compatible with K_MEM_MAP_UNPAGED. (cherry picked from commit be279d878ec0428cc6a1b2a0684068cd6092d704) Original-Signed-off-by: Nicolas Pitre GitOrigin-RevId: be279d878ec0428cc6a1b2a0684068cd6092d704 Cr-Build-Id: 8736917283475341809 Cr-Build-Url: https://cr-buildbucket.appspot.com/build/8736917283475341809 Copybot-Job-Name: zephyr-main-copybot-downstream Change-Id: Ia5f91ce197b6395ec6f88cc7102dc1e62e0dd101 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/5856312 Commit-Queue: Keith Short Tested-by: ChromeOS Prod (Robot) Reviewed-by: Keith Short --- arch/arm64/core/mmu.c | 20 ++++++++++++++++++-- include/zephyr/arch/arm64/arm_mmu.h | 11 +++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/arch/arm64/core/mmu.c b/arch/arm64/core/mmu.c index 85bae34718e..a914916d605 100644 --- a/arch/arm64/core/mmu.c +++ b/arch/arm64/core/mmu.c @@ -243,8 +243,15 @@ static void set_pte_table_desc(uint64_t *pte, uint64_t *table, unsigned int leve static void set_pte_block_desc(uint64_t *pte, uint64_t desc, unsigned int level) { - if (desc) { - desc |= (level == XLAT_LAST_LEVEL) ? PTE_PAGE_DESC : PTE_BLOCK_DESC; + if (level != XLAT_LAST_LEVEL) { + desc |= PTE_BLOCK_DESC; + } else if (!IS_ENABLED(CONFIG_DEMAND_PAGING) || (desc & PTE_BLOCK_DESC_AF) != 0) { + desc |= PTE_PAGE_DESC; + } else { + /* + * Demand paging configured and AF unset: leave the descriptor + * type to "invalid" as in arch_mem_page_out(). + */ } *pte = desc; debug_show_pte(pte, level); @@ -677,6 +684,11 @@ static uint64_t get_region_desc(uint32_t attrs) /* the access flag */ desc |= PTE_BLOCK_DESC_AF; + if (IS_ENABLED(CONFIG_DEMAND_PAGING) && (attrs & MT_PAGED_OUT) != 0) { + /* set it up for demand paging like arch_mem_page_out() */ + desc &= ~PTE_BLOCK_DESC_AF; + desc |= PTE_BLOCK_DESC_AP_RO; + } /* memory attribute index field */ mem_type = MT_TYPE(attrs); @@ -1090,6 +1102,10 @@ static int __arch_mem_map(void *virt, uintptr_t phys, size_t size, uint32_t flag entry_flags |= MT_RW_AP_ELx; } + if (IS_ENABLED(CONFIG_DEMAND_PAGING) && (flags & K_MEM_MAP_UNPAGED) != 0) { + entry_flags |= MT_PAGED_OUT; + } + return add_map(ptables, "generic", phys, (uintptr_t)virt, size, entry_flags); } diff --git a/include/zephyr/arch/arm64/arm_mmu.h b/include/zephyr/arch/arm64/arm_mmu.h index 7b6ce32a65c..450a8238faa 100644 --- a/include/zephyr/arch/arm64/arm_mmu.h +++ b/include/zephyr/arch/arm64/arm_mmu.h @@ -45,6 +45,7 @@ * attrs[7] : Mirror RO/RW permissions to EL0 * attrs[8] : Overwrite existing mapping if any * attrs[9] : non-Global mapping (nG) + * attrs[10]: Paged-out mapping * */ #define MT_PERM_SHIFT 3U @@ -54,6 +55,7 @@ #define MT_RW_AP_SHIFT 7U #define MT_NO_OVERWRITE_SHIFT 8U #define MT_NON_GLOBAL_SHIFT 9U +#define MT_PAGED_OUT_SHIFT 10U #define MT_RO (0U << MT_PERM_SHIFT) #define MT_RW (1U << MT_PERM_SHIFT) @@ -75,6 +77,8 @@ #define MT_G (0U << MT_NON_GLOBAL_SHIFT) #define MT_NG (1U << MT_NON_GLOBAL_SHIFT) +#define MT_PAGED_OUT (1U << MT_PAGED_OUT_SHIFT) + #define MT_P_RW_U_RW (MT_RW | MT_RW_AP_ELx | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER) #define MT_P_RW_U_NA (MT_RW | MT_RW_AP_EL_HIGHER | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER) #define MT_P_RO_U_RO (MT_RO | MT_RW_AP_ELx | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER) @@ -95,6 +99,13 @@ #define ARCH_DATA_PAGE_DIRTY BIT(2) #define ARCH_DATA_PAGE_NOT_MAPPED BIT(3) +/* + * Special unpaged "location" tags (highest possible descriptor physical + * address values unlikely to conflict with backing store locations) + */ +#define ARCH_UNPAGED_ANON_ZERO 0x0000fffffffff000 +#define ARCH_UNPAGED_ANON_UNINIT 0x0000ffffffffe000 + #ifndef _ASMLANGUAGE /* Region definition data structure */