Branch data Line data Source code
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 : : 21 : : #ifdef CONFIG_MMU 22 : : static int early_ioremap_debug __initdata; 23 : : 24 : 0 : static int __init early_ioremap_debug_setup(char *str) 25 : : { 26 : 0 : early_ioremap_debug = 1; 27 : : 28 : 0 : return 0; 29 : : } 30 : : early_param("early_ioremap_debug", early_ioremap_debug_setup); 31 : : 32 : : static int after_paging_init __initdata; 33 : : 34 : 0 : pgprot_t __init __weak early_memremap_pgprot_adjust(resource_size_t phys_addr, 35 : : unsigned long size, 36 : : pgprot_t prot) 37 : : { 38 : 0 : return prot; 39 : : } 40 : : 41 : 3 : void __init __weak early_ioremap_shutdown(void) 42 : : { 43 : 3 : } 44 : : 45 : 3 : void __init early_ioremap_reset(void) 46 : : { 47 : 3 : early_ioremap_shutdown(); 48 : 3 : after_paging_init = 1; 49 : 3 : } 50 : : 51 : : /* 52 : : * Generally, ioremap() is available after paging_init() has been called. 53 : : * Architectures wanting to allow early_ioremap after paging_init() can 54 : : * define __late_set_fixmap and __late_clear_fixmap to do the right thing. 55 : : */ 56 : : #ifndef __late_set_fixmap 57 : 0 : static inline void __init __late_set_fixmap(enum fixed_addresses idx, 58 : : phys_addr_t phys, pgprot_t prot) 59 : : { 60 : 0 : BUG(); 61 : : } 62 : : #endif 63 : : 64 : : #ifndef __late_clear_fixmap 65 : 0 : static inline void __init __late_clear_fixmap(enum fixed_addresses idx) 66 : : { 67 : 0 : BUG(); 68 : : } 69 : : #endif 70 : : 71 : : static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata; 72 : : static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata; 73 : : static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata; 74 : : 75 : 3 : void __init early_ioremap_setup(void) 76 : : { 77 : : int i; 78 : : 79 : 3 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++) 80 : 3 : if (WARN_ON(prev_map[i])) 81 : : break; 82 : : 83 : 3 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++) 84 : 3 : slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i); 85 : 3 : } 86 : : 87 : 3 : static int __init check_early_ioremap_leak(void) 88 : : { 89 : : int count = 0; 90 : : int i; 91 : : 92 : 3 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++) 93 : 3 : if (prev_map[i]) 94 : 0 : count++; 95 : : 96 : 3 : if (WARN(count, KERN_WARNING 97 : : "Debug warning: early ioremap leak of %d areas detected.\n" 98 : : "please boot with early_ioremap_debug and report the dmesg.\n", 99 : : count)) 100 : : return 1; 101 : 3 : return 0; 102 : : } 103 : : late_initcall(check_early_ioremap_leak); 104 : : 105 : : static void __init __iomem * 106 : 0 : __early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot) 107 : : { 108 : : unsigned long offset; 109 : : resource_size_t last_addr; 110 : : unsigned int nrpages; 111 : : enum fixed_addresses idx; 112 : : int i, slot; 113 : : 114 : 0 : WARN_ON(system_state >= SYSTEM_RUNNING); 115 : : 116 : : slot = -1; 117 : 0 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { 118 : 0 : if (!prev_map[i]) { 119 : 0 : slot = i; 120 : 0 : break; 121 : : } 122 : : } 123 : : 124 : 0 : if (WARN(slot < 0, "%s(%08llx, %08lx) not found slot\n", 125 : : __func__, (u64)phys_addr, size)) 126 : : return NULL; 127 : : 128 : : /* Don't allow wraparound or zero size */ 129 : 0 : last_addr = phys_addr + size - 1; 130 : 0 : if (WARN_ON(!size || last_addr < phys_addr)) 131 : : return NULL; 132 : : 133 : 0 : prev_size[slot] = size; 134 : : /* 135 : : * Mappings have to be page-aligned 136 : : */ 137 : 0 : offset = offset_in_page(phys_addr); 138 : 0 : phys_addr &= PAGE_MASK; 139 : 0 : size = PAGE_ALIGN(last_addr + 1) - phys_addr; 140 : : 141 : : /* 142 : : * Mappings have to fit in the FIX_BTMAP area. 143 : : */ 144 : 0 : nrpages = size >> PAGE_SHIFT; 145 : 0 : if (WARN_ON(nrpages > NR_FIX_BTMAPS)) 146 : : return NULL; 147 : : 148 : : /* 149 : : * Ok, go for it.. 150 : : */ 151 : 0 : idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; 152 : 0 : while (nrpages > 0) { 153 : 0 : if (after_paging_init) 154 : 0 : __late_set_fixmap(idx, phys_addr, prot); 155 : : else 156 : 0 : __early_set_fixmap(idx, phys_addr, prot); 157 : 0 : phys_addr += PAGE_SIZE; 158 : 0 : --idx; 159 : 0 : --nrpages; 160 : : } 161 : 0 : WARN(early_ioremap_debug, "%s(%08llx, %08lx) [%d] => %08lx + %08lx\n", 162 : : __func__, (u64)phys_addr, size, slot, offset, slot_virt[slot]); 163 : : 164 : 0 : prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]); 165 : 0 : return prev_map[slot]; 166 : : } 167 : : 168 : 0 : void __init early_iounmap(void __iomem *addr, unsigned long size) 169 : : { 170 : : unsigned long virt_addr; 171 : : unsigned long offset; 172 : : unsigned int nrpages; 173 : : enum fixed_addresses idx; 174 : : int i, slot; 175 : : 176 : : slot = -1; 177 : 0 : for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { 178 : 0 : if (prev_map[i] == addr) { 179 : 0 : slot = i; 180 : 0 : break; 181 : : } 182 : : } 183 : : 184 : 0 : if (WARN(slot < 0, "early_iounmap(%p, %08lx) not found slot\n", 185 : : addr, size)) 186 : : return; 187 : : 188 : 0 : if (WARN(prev_size[slot] != size, 189 : : "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n", 190 : : addr, size, slot, prev_size[slot])) 191 : : return; 192 : : 193 : 0 : WARN(early_ioremap_debug, "early_iounmap(%p, %08lx) [%d]\n", 194 : : addr, size, slot); 195 : : 196 : 0 : virt_addr = (unsigned long)addr; 197 : 0 : if (WARN_ON(virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))) 198 : : return; 199 : : 200 : 0 : offset = offset_in_page(virt_addr); 201 : 0 : nrpages = PAGE_ALIGN(offset + size) >> PAGE_SHIFT; 202 : : 203 : 0 : idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; 204 : 0 : while (nrpages > 0) { 205 : 0 : if (after_paging_init) 206 : 0 : __late_clear_fixmap(idx); 207 : : else 208 : 0 : __early_set_fixmap(idx, 0, FIXMAP_PAGE_CLEAR); 209 : 0 : --idx; 210 : 0 : --nrpages; 211 : : } 212 : 0 : prev_map[slot] = NULL; 213 : : } 214 : : 215 : : /* Remap an IO device */ 216 : : void __init __iomem * 217 : 0 : early_ioremap(resource_size_t phys_addr, unsigned long size) 218 : : { 219 : 0 : return __early_ioremap(phys_addr, size, FIXMAP_PAGE_IO); 220 : : } 221 : : 222 : : /* Remap memory */ 223 : : void __init * 224 : 0 : early_memremap(resource_size_t phys_addr, unsigned long size) 225 : : { 226 : 0 : pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, 227 : : FIXMAP_PAGE_NORMAL); 228 : : 229 : 0 : return (__force void *)__early_ioremap(phys_addr, size, prot); 230 : : } 231 : : #ifdef FIXMAP_PAGE_RO 232 : : void __init * 233 : 0 : early_memremap_ro(resource_size_t phys_addr, unsigned long size) 234 : : { 235 : 0 : pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, 236 : : FIXMAP_PAGE_RO); 237 : : 238 : 0 : return (__force void *)__early_ioremap(phys_addr, size, prot); 239 : : } 240 : : #endif 241 : : 242 : : #ifdef CONFIG_ARCH_USE_MEMREMAP_PROT 243 : : void __init * 244 : : early_memremap_prot(resource_size_t phys_addr, unsigned long size, 245 : : unsigned long prot_val) 246 : : { 247 : : return (__force void *)__early_ioremap(phys_addr, size, 248 : : __pgprot(prot_val)); 249 : : } 250 : : #endif 251 : : 252 : : #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT) 253 : : 254 : 0 : void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size) 255 : : { 256 : : unsigned long slop, clen; 257 : : char *p; 258 : : 259 : 0 : while (size) { 260 : 0 : slop = offset_in_page(src); 261 : : clen = size; 262 : 0 : if (clen > MAX_MAP_CHUNK - slop) 263 : : clen = MAX_MAP_CHUNK - slop; 264 : 0 : p = early_memremap(src & PAGE_MASK, clen + slop); 265 : 0 : memcpy(dest, p + slop, clen); 266 : : early_memunmap(p, clen + slop); 267 : 0 : dest += clen; 268 : 0 : src += clen; 269 : 0 : size -= clen; 270 : : } 271 : 0 : } 272 : : 273 : : #else /* CONFIG_MMU */ 274 : : 275 : : void __init __iomem * 276 : : early_ioremap(resource_size_t phys_addr, unsigned long size) 277 : : { 278 : : return (__force void __iomem *)phys_addr; 279 : : } 280 : : 281 : : /* Remap memory */ 282 : : void __init * 283 : : early_memremap(resource_size_t phys_addr, unsigned long size) 284 : : { 285 : : return (void *)phys_addr; 286 : : } 287 : : void __init * 288 : : early_memremap_ro(resource_size_t phys_addr, unsigned long size) 289 : : { 290 : : return (void *)phys_addr; 291 : : } 292 : : 293 : : void __init early_iounmap(void __iomem *addr, unsigned long size) 294 : : { 295 : : } 296 : : 297 : : #endif /* CONFIG_MMU */ 298 : : 299 : : 300 : 0 : void __init early_memunmap(void *addr, unsigned long size) 301 : : { 302 : 0 : early_iounmap((__force void __iomem *)addr, size); 303 : 0 : }