1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/module.h> 3 #include <linux/kernel.h> 4 #include <linux/slab.h> 5 #include <linux/mm_types.h> 6 #include <linux/pgtable.h> 7 8 #include <asm/cputype.h> 9 #include <asm/idmap.h> 10 #include <asm/hwcap.h> 11 #include <asm/pgalloc.h> 12 #include <asm/sections.h> 13 #include <asm/system_info.h> 14 #include <asm/uaccess.h> 15 16 /* 17 * Note: accesses outside of the kernel image and the identity map area 18 * are not supported on any CPU using the idmap tables as its current 19 * page tables. 20 */ 21 pgd_t *idmap_pgd __ro_after_init; 22 long long arch_phys_to_idmap_offset __ro_after_init; 23 24 #ifdef CONFIG_ARM_LPAE 25 static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, 26 unsigned long prot) 27 { 28 pmd_t *pmd; 29 unsigned long next; 30 31 if (pud_none_or_clear_bad(pud) || (pud_val(*pud) & L_PGD_SWAPPER)) { 32 pmd = pmd_alloc_one(&init_mm, addr); 33 if (!pmd) { 34 pr_warn("Failed to allocate identity pmd.\n"); 35 return; 36 } 37 /* 38 * Copy the original PMD to ensure that the PMD entries for 39 * the kernel image are preserved. 40 */ 41 if (!pud_none(*pud)) 42 memcpy(pmd, pmd_offset(pud, 0), 43 PTRS_PER_PMD * sizeof(pmd_t)); 44 pud_populate(&init_mm, pud, pmd); 45 pmd += pmd_index(addr); 46 } else 47 pmd = pmd_offset(pud, addr); 48 49 do { 50 next = pmd_addr_end(addr, end); 51 *pmd = __pmd((addr & PMD_MASK) | prot); 52 flush_pmd_entry(pmd); 53 } while (pmd++, addr = next, addr != end); 54 } 55 #else /* !CONFIG_ARM_LPAE */ 56 static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, 57 unsigned long prot) 58 { 59 pmd_t *pmd = pmd_offset(pud, addr); 60 61 addr = (addr & PMD_MASK) | prot; 62 pmd[0] = __pmd(addr); 63 addr += SECTION_SIZE; 64 pmd[1] = __pmd(addr); 65 flush_pmd_entry(pmd); 66 } 67 #endif /* CONFIG_ARM_LPAE */ 68 69 static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, 70 unsigned long prot) 71 { 72 p4d_t *p4d = p4d_offset(pgd, addr); 73 pud_t *pud = pud_offset(p4d, addr); 74 unsigned long next; 75 76 do { 77 next = pud_addr_end(addr, end); 78 idmap_add_pmd(pud, addr, next, prot); 79 } while (pud++, addr = next, addr != end); 80 } 81 82 static void identity_mapping_add(pgd_t *pgd, const char *text_start, 83 const char *text_end, unsigned long prot) 84 { 85 unsigned long addr, end; 86 unsigned long next; 87 88 #ifdef CONFIG_XIP_KERNEL 89 addr = (phys_addr_t)(text_start) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) 90 + CONFIG_XIP_PHYS_ADDR; 91 end = (phys_addr_t)(text_end) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) 92 + CONFIG_XIP_PHYS_ADDR; 93 #else 94 addr = virt_to_idmap(text_start); 95 end = virt_to_idmap(text_end); 96 #endif 97 pr_info("Setting up static identity map for 0x%lx - 0x%lx\n", addr, end); 98 99 prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; 100 101 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale_family()) 102 prot |= PMD_BIT4; 103 104 pgd += pgd_index(addr); 105 do { 106 next = pgd_addr_end(addr, end); 107 idmap_add_pud(pgd, addr, next, prot); 108 } while (pgd++, addr = next, addr != end); 109 } 110 111 extern char __idmap_text_start[], __idmap_text_end[]; 112 113 static int __init init_static_idmap(void) 114 { 115 idmap_pgd = pgd_alloc(&init_mm); 116 if (!idmap_pgd) 117 return -ENOMEM; 118 119 identity_mapping_add(idmap_pgd, __idmap_text_start, 120 __idmap_text_end, 0); 121 122 /* Flush L1 for the hardware to see this page table content */ 123 if (!(elf_hwcap & HWCAP_LPAE)) 124 flush_cache_louis(); 125 126 return 0; 127 } 128 early_initcall(init_static_idmap); 129 130 /* 131 * In order to soft-boot, we need to switch to a 1:1 mapping for the 132 * cpu_reset functions. This will then ensure that we have predictable 133 * results when turning off the mmu. 134 */ 135 void setup_mm_for_reboot(void) 136 { 137 /* 138 * With CONFIG_CPU_TTBR0_PAN enabled, TTBCR.EPD0 is set whenever 139 * user-space access is disabled in order to block TTBR0 page-table 140 * walks. The identity mapping lives at low (user-space) virtual 141 * addresses and can only be reached via TTBR0, so we must re-enable 142 * those walks before switching page tables. On non-PAN kernels this 143 * is a no-op. 144 */ 145 if (IS_ENABLED(CONFIG_CPU_TTBR0_PAN)) 146 uaccess_save_and_enable(); 147 148 /* Switch to the identity mapping. */ 149 cpu_switch_mm(idmap_pgd, &init_mm); 150 local_flush_bp_all(); 151 152 #ifdef CONFIG_CPU_HAS_ASID 153 /* 154 * We don't have a clean ASID for the identity mapping, which 155 * may clash with virtual addresses of the previous page tables 156 * and therefore potentially in the TLB. 157 */ 158 local_flush_tlb_all(); 159 #endif 160 } 161