diff options
Diffstat (limited to 'arch/arm64/mm/mmu.c')
-rw-r--r-- | arch/arm64/mm/mmu.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index a6885d896ab6..f4dd585898c5 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/nodemask.h> | 25 | #include <linux/nodemask.h> |
26 | #include <linux/memblock.h> | 26 | #include <linux/memblock.h> |
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/io.h> | ||
28 | 29 | ||
29 | #include <asm/cputype.h> | 30 | #include <asm/cputype.h> |
30 | #include <asm/sections.h> | 31 | #include <asm/sections.h> |
@@ -251,6 +252,47 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt, | |||
251 | } while (pgd++, addr = next, addr != end); | 252 | } while (pgd++, addr = next, addr != end); |
252 | } | 253 | } |
253 | 254 | ||
255 | #ifdef CONFIG_EARLY_PRINTK | ||
256 | /* | ||
257 | * Create an early I/O mapping using the pgd/pmd entries already populated | ||
258 | * in head.S as this function is called too early to allocated any memory. The | ||
259 | * mapping size is 2MB with 4KB pages or 64KB or 64KB pages. | ||
260 | */ | ||
261 | void __iomem * __init early_io_map(phys_addr_t phys, unsigned long virt) | ||
262 | { | ||
263 | unsigned long size, mask; | ||
264 | bool page64k = IS_ENABLED(ARM64_64K_PAGES); | ||
265 | pgd_t *pgd; | ||
266 | pud_t *pud; | ||
267 | pmd_t *pmd; | ||
268 | pte_t *pte; | ||
269 | |||
270 | /* | ||
271 | * No early pte entries with !ARM64_64K_PAGES configuration, so using | ||
272 | * sections (pmd). | ||
273 | */ | ||
274 | size = page64k ? PAGE_SIZE : SECTION_SIZE; | ||
275 | mask = ~(size - 1); | ||
276 | |||
277 | pgd = pgd_offset_k(virt); | ||
278 | pud = pud_offset(pgd, virt); | ||
279 | if (pud_none(*pud)) | ||
280 | return NULL; | ||
281 | pmd = pmd_offset(pud, virt); | ||
282 | |||
283 | if (page64k) { | ||
284 | if (pmd_none(*pmd)) | ||
285 | return NULL; | ||
286 | pte = pte_offset_kernel(pmd, virt); | ||
287 | set_pte(pte, __pte((phys & mask) | PROT_DEVICE_nGnRE)); | ||
288 | } else { | ||
289 | set_pmd(pmd, __pmd((phys & mask) | PROT_SECT_DEVICE_nGnRE)); | ||
290 | } | ||
291 | |||
292 | return (void __iomem *)((virt & mask) + (phys & ~mask)); | ||
293 | } | ||
294 | #endif | ||
295 | |||
254 | static void __init map_mem(void) | 296 | static void __init map_mem(void) |
255 | { | 297 | { |
256 | struct memblock_region *reg; | 298 | struct memblock_region *reg; |