1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Provide common bits of early_ioremap() support for architectures needing 4 * temporary mappings during boot before ioremap() is available. 5 * 6 * This is mostly a direct copy of the x86 early_ioremap implementation. 7 * 8 * (C) Copyright 1995 1996, 2014 Linus Torvalds 9 * 10 */ 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/io.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 #include <linux/mm.h> 17 #include <linux/vmalloc.h> 18 #include <asm/fixmap.h> 19 #include <asm/early_ioremap.h> 20 #include "internal.h" 21 22 #ifdef CONFIG_MMU 23 static int early_ioremap_debug __initdata; 24 25 static int __init early_ioremap_debug_setup(char *str) 26 { 27 early_ioremap_debug = 1; 28 29 return 0; 30 } 31 early_param("early_ioremap_debug", early_ioremap_debug_setup); 32 33 #define early_ioremap_dbg(fmt, args...) \ 34 do { \ 35 if (unlikely(early_ioremap_debug)) { \ 36 pr_warn(fmt, ##args); \ 37 dump_stack(); \ 38 } \ 39 } while (0) 40 41 static int after_paging_init __initdata; 42 43 pgprot_t __init __weak early_memremap_pgprot_adjust(resource_size_t phys_addr, 44 unsigned long size, 45 pgprot_t prot) 46 { 47 return prot; 48 } 49 50 /* 51 * Only architectures whose early_ioremap() must stop using __early_set_fixmap() 52 * after paging_init() need to call this. 53 */ 54 void __init early_ioremap_reset(void) 55 { 56 after_paging_init = 1; 57 } 58 59 /* 60 * Only architectures that call early_ioremap_reset() need to define 61 * __late_set_fixmap() and __late_clear_fixmap(), which early_ioremap() uses 62 * instead of __early_set_fixmap() after the reset. 63 */ 64 #ifndef __late_set_fixmap 65 static inline void __init __late_set_fixmap(enum fixed_addresses idx, 66 phys_addr_t phys, pgprot_t prot) 67 { 68 BUG(); 69 } 70 #endif 71 72 #ifndef __late_clear_fixmap 73 static inline void __init __late_clear_fixmap(enum fixed_addresses idx) 74 { 75 BUG(); 76 } 77 #endif 78 79 static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata; 80 static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata; 81 static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata; 82 83 void __init early_ioremap_setup(void) 84 { 85 int i; 86 87 for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { 88 WARN_ON_ONCE(prev_map[i]); 89 slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i); 90 } 91 } 92 93 static int __init check_early_ioremap_leak(void) 94 { 95 int count = 0; 96 int i; 97 98 for (i = 0; i < FIX_BTMAPS_SLOTS; i++) 99 if (prev_map[i]) 100 count++; 101 102 if (WARN(count, KERN_WARNING 103 "Debug warning: early ioremap leak of %d areas detected.\n" 104 "please boot with early_ioremap_debug and report the dmesg.\n", 105 count)) 106 return 1; 107 return 0; 108 } 109 late_initcall(check_early_ioremap_leak); 110 111 static void __init __iomem * 112 __early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot) 113 { 114 unsigned long offset; 115 resource_size_t last_addr; 116 unsigned int nrpages; 117 enum fixed_addresses idx; 118 int i, slot; 119 120 WARN_ON(system_state >= SYSTEM_RUNNING); 121 122 slot = -1; 123 for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { 124 if (!prev_map[i]) { 125 slot = i; 126 break; 127 } 128 } 129 130 if (WARN(slot < 0, "%s(%pa, %08lx) not found slot\n", 131 __func__, &phys_addr, size)) 132 return NULL; 133 134 /* Don't allow wraparound or zero size */ 135 last_addr = phys_addr + size - 1; 136 if (WARN_ON(!size || last_addr < phys_addr)) 137 return NULL; 138 139 prev_size[slot] = size; 140 /* 141 * Mappings have to be page-aligned 142 */ 143 offset = offset_in_page(phys_addr); 144 phys_addr &= PAGE_MASK; 145 size = PAGE_ALIGN(last_addr + 1) - phys_addr; 146 147 /* 148 * Mappings have to fit in the FIX_BTMAP area. 149 */ 150 nrpages = size >> PAGE_SHIFT; 151 if (WARN_ON(nrpages > NR_FIX_BTMAPS)) 152 return NULL; 153 154 early_ioremap_dbg("%s(%pa, %08lx) [%d] => %08lx + %08lx\n", 155 __func__, &phys_addr, size, slot, slot_virt[slot], offset); 156 157 /* 158 * Ok, go for it.. 159 */ 160 idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; 161 while (nrpages > 0) { 162 if (after_paging_init) 163 __late_set_fixmap(idx, phys_addr, prot); 164 else 165 __early_set_fixmap(idx, phys_addr, prot); 166 phys_addr += PAGE_SIZE; 167 --idx; 168 --nrpages; 169 } 170 171 prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]); 172 return prev_map[slot]; 173 } 174 175 void __init early_iounmap(void __iomem *addr, unsigned long size) 176 { 177 unsigned long virt_addr; 178 unsigned long offset; 179 unsigned int nrpages; 180 enum fixed_addresses idx; 181 int i, slot; 182 183 slot = -1; 184 for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { 185 if (prev_map[i] == addr) { 186 slot = i; 187 break; 188 } 189 } 190 191 if (WARN(slot < 0, "%s(%p, %08lx) not found slot\n", 192 __func__, addr, size)) 193 return; 194 195 if (WARN(prev_size[slot] != size, 196 "%s(%p, %08lx) [%d] size not consistent %08lx\n", 197 __func__, addr, size, slot, prev_size[slot])) 198 return; 199 200 early_ioremap_dbg("%s(%p, %08lx) [%d]\n", __func__, addr, size, slot); 201 202 virt_addr = (unsigned long)addr; 203 if (WARN_ON(virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))) 204 return; 205 206 offset = offset_in_page(virt_addr); 207 nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT; 208 209 idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; 210 while (nrpages > 0) { 211 if (after_paging_init) 212 __late_clear_fixmap(idx); 213 else 214 __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); 215 --idx; 216 --nrpages; 217 } 218 prev_map[slot] = NULL; 219 } 220 221 /* Remap an IO device */ 222 void __init __iomem * 223 early_ioremap(resource_size_t phys_addr, unsigned long size) 224 { 225 return __early_ioremap(phys_addr, size, FIXMAP_PAGE_IO); 226 } 227 228 /* Remap memory */ 229 void __init * 230 early_memremap(resource_size_t phys_addr, unsigned long size) 231 { 232 pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, 233 FIXMAP_PAGE_NORMAL); 234 235 return (__force void *)__early_ioremap(phys_addr, size, prot); 236 } 237 #ifdef FIXMAP_PAGE_RO 238 void __init * 239 early_memremap_ro(resource_size_t phys_addr, unsigned long size) 240 { 241 pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, 242 FIXMAP_PAGE_RO); 243 244 return (__force void *)__early_ioremap(phys_addr, size, prot); 245 } 246 #endif 247 248 #ifdef CONFIG_ARCH_USE_MEMREMAP_PROT 249 void __init * 250 early_memremap_prot(resource_size_t phys_addr, unsigned long size, 251 unsigned long prot_val) 252 { 253 return (__force void *)__early_ioremap(phys_addr, size, 254 __pgprot(prot_val)); 255 } 256 #endif 257 258 #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT) 259 260 /* 261 * If no empty slot, handle that and return -ENOMEM. 262 */ 263 int __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size) 264 { 265 unsigned long slop, clen; 266 char *p; 267 268 while (size) { 269 slop = offset_in_page(src); 270 clen = size; 271 if (clen > MAX_MAP_CHUNK - slop) 272 clen = MAX_MAP_CHUNK - slop; 273 p = early_memremap(src & PAGE_MASK, clen + slop); 274 if (!p) 275 return -ENOMEM; 276 memcpy(dest, p + slop, clen); 277 early_memunmap(p, clen + slop); 278 dest += clen; 279 src += clen; 280 size -= clen; 281 } 282 return 0; 283 } 284 285 #else /* CONFIG_MMU */ 286 287 void __init __iomem * 288 early_ioremap(resource_size_t phys_addr, unsigned long size) 289 { 290 return (__force void __iomem *)phys_addr; 291 } 292 293 /* Remap memory */ 294 void __init * 295 early_memremap(resource_size_t phys_addr, unsigned long size) 296 { 297 return (void *)phys_addr; 298 } 299 void __init * 300 early_memremap_ro(resource_size_t phys_addr, unsigned long size) 301 { 302 return (void *)phys_addr; 303 } 304 305 void __init early_iounmap(void __iomem *addr, unsigned long size) 306 { 307 } 308 309 #endif /* CONFIG_MMU */ 310 311 312 void __init early_memunmap(void *addr, unsigned long size) 313 { 314 early_iounmap((__force void __iomem *)addr, size); 315 } 316