18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2005, Paul Mackerras, IBM Corporation. 48c2ecf20Sopenharmony_ci * Copyright 2009, Benjamin Herrenschmidt, IBM Corporation. 58c2ecf20Sopenharmony_ci * Copyright 2015-2016, Aneesh Kumar K.V, IBM Corporation. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/sched.h> 98c2ecf20Sopenharmony_ci#include <linux/memblock.h> 108c2ecf20Sopenharmony_ci#include <asm/pgalloc.h> 118c2ecf20Sopenharmony_ci#include <asm/tlb.h> 128c2ecf20Sopenharmony_ci#include <asm/dma.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <mm/mmu_decl.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#ifdef CONFIG_SPARSEMEM_VMEMMAP 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci * On Book3E CPUs, the vmemmap is currently mapped in the top half of 198c2ecf20Sopenharmony_ci * the vmalloc space using normal page tables, though the size of 208c2ecf20Sopenharmony_ci * pages encoded in the PTEs can be different 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ciint __meminit vmemmap_create_mapping(unsigned long start, 238c2ecf20Sopenharmony_ci unsigned long page_size, 248c2ecf20Sopenharmony_ci unsigned long phys) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci /* Create a PTE encoding without page size */ 278c2ecf20Sopenharmony_ci unsigned long i, flags = _PAGE_PRESENT | _PAGE_ACCESSED | 288c2ecf20Sopenharmony_ci _PAGE_KERNEL_RW; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci /* PTEs only contain page size encodings up to 32M */ 318c2ecf20Sopenharmony_ci BUG_ON(mmu_psize_defs[mmu_vmemmap_psize].enc > 0xf); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci /* Encode the size in the PTE */ 348c2ecf20Sopenharmony_ci flags |= mmu_psize_defs[mmu_vmemmap_psize].enc << 8; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci /* For each PTE for that area, map things. Note that we don't 378c2ecf20Sopenharmony_ci * increment phys because all PTEs are of the large size and 388c2ecf20Sopenharmony_ci * thus must have the low bits clear 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ci for (i = 0; i < page_size; i += PAGE_SIZE) 418c2ecf20Sopenharmony_ci BUG_ON(map_kernel_page(start + i, phys, __pgprot(flags))); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci return 0; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#ifdef CONFIG_MEMORY_HOTPLUG 478c2ecf20Sopenharmony_civoid vmemmap_remove_mapping(unsigned long start, 488c2ecf20Sopenharmony_ci unsigned long page_size) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci#endif 528c2ecf20Sopenharmony_ci#endif /* CONFIG_SPARSEMEM_VMEMMAP */ 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic void __init *early_alloc_pgtable(unsigned long size) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci void *ptr; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci ptr = memblock_alloc_try_nid(size, size, MEMBLOCK_LOW_LIMIT, 598c2ecf20Sopenharmony_ci __pa(MAX_DMA_ADDRESS), NUMA_NO_NODE); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (!ptr) 628c2ecf20Sopenharmony_ci panic("%s: Failed to allocate %lu bytes align=0x%lx max_addr=%lx\n", 638c2ecf20Sopenharmony_ci __func__, size, size, __pa(MAX_DMA_ADDRESS)); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return ptr; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* 698c2ecf20Sopenharmony_ci * map_kernel_page currently only called by __ioremap 708c2ecf20Sopenharmony_ci * map_kernel_page adds an entry to the ioremap page table 718c2ecf20Sopenharmony_ci * and adds an entry to the HPT, possibly bolting it 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ciint __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci pgd_t *pgdp; 768c2ecf20Sopenharmony_ci p4d_t *p4dp; 778c2ecf20Sopenharmony_ci pud_t *pudp; 788c2ecf20Sopenharmony_ci pmd_t *pmdp; 798c2ecf20Sopenharmony_ci pte_t *ptep; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci BUILD_BUG_ON(TASK_SIZE_USER64 > PGTABLE_RANGE); 828c2ecf20Sopenharmony_ci if (slab_is_available()) { 838c2ecf20Sopenharmony_ci pgdp = pgd_offset_k(ea); 848c2ecf20Sopenharmony_ci p4dp = p4d_offset(pgdp, ea); 858c2ecf20Sopenharmony_ci pudp = pud_alloc(&init_mm, p4dp, ea); 868c2ecf20Sopenharmony_ci if (!pudp) 878c2ecf20Sopenharmony_ci return -ENOMEM; 888c2ecf20Sopenharmony_ci pmdp = pmd_alloc(&init_mm, pudp, ea); 898c2ecf20Sopenharmony_ci if (!pmdp) 908c2ecf20Sopenharmony_ci return -ENOMEM; 918c2ecf20Sopenharmony_ci ptep = pte_alloc_kernel(pmdp, ea); 928c2ecf20Sopenharmony_ci if (!ptep) 938c2ecf20Sopenharmony_ci return -ENOMEM; 948c2ecf20Sopenharmony_ci } else { 958c2ecf20Sopenharmony_ci pgdp = pgd_offset_k(ea); 968c2ecf20Sopenharmony_ci p4dp = p4d_offset(pgdp, ea); 978c2ecf20Sopenharmony_ci if (p4d_none(*p4dp)) { 988c2ecf20Sopenharmony_ci pudp = early_alloc_pgtable(PUD_TABLE_SIZE); 998c2ecf20Sopenharmony_ci p4d_populate(&init_mm, p4dp, pudp); 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci pudp = pud_offset(p4dp, ea); 1028c2ecf20Sopenharmony_ci if (pud_none(*pudp)) { 1038c2ecf20Sopenharmony_ci pmdp = early_alloc_pgtable(PMD_TABLE_SIZE); 1048c2ecf20Sopenharmony_ci pud_populate(&init_mm, pudp, pmdp); 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci pmdp = pmd_offset(pudp, ea); 1078c2ecf20Sopenharmony_ci if (!pmd_present(*pmdp)) { 1088c2ecf20Sopenharmony_ci ptep = early_alloc_pgtable(PTE_TABLE_SIZE); 1098c2ecf20Sopenharmony_ci pmd_populate_kernel(&init_mm, pmdp, ptep); 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci ptep = pte_offset_kernel(pmdp, ea); 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, prot)); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci smp_wmb(); 1168c2ecf20Sopenharmony_ci return 0; 1178c2ecf20Sopenharmony_ci} 118