18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2020 Loongson Technology Corporation Limited 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#include <linux/bug.h> 68c2ecf20Sopenharmony_ci#include <linux/init.h> 78c2ecf20Sopenharmony_ci#include <linux/export.h> 88c2ecf20Sopenharmony_ci#include <linux/signal.h> 98c2ecf20Sopenharmony_ci#include <linux/sched.h> 108c2ecf20Sopenharmony_ci#include <linux/smp.h> 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/errno.h> 138c2ecf20Sopenharmony_ci#include <linux/string.h> 148c2ecf20Sopenharmony_ci#include <linux/types.h> 158c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 168c2ecf20Sopenharmony_ci#include <linux/ptrace.h> 178c2ecf20Sopenharmony_ci#include <linux/memblock.h> 188c2ecf20Sopenharmony_ci#include <linux/mm.h> 198c2ecf20Sopenharmony_ci#include <linux/mman.h> 208c2ecf20Sopenharmony_ci#include <linux/highmem.h> 218c2ecf20Sopenharmony_ci#include <linux/swap.h> 228c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 238c2ecf20Sopenharmony_ci#include <linux/pfn.h> 248c2ecf20Sopenharmony_ci#include <linux/hardirq.h> 258c2ecf20Sopenharmony_ci#include <linux/gfp.h> 268c2ecf20Sopenharmony_ci#include <linux/hugetlb.h> 278c2ecf20Sopenharmony_ci#include <linux/mmzone.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 308c2ecf20Sopenharmony_ci#include <asm/bootinfo.h> 318c2ecf20Sopenharmony_ci#include <asm/cpu.h> 328c2ecf20Sopenharmony_ci#include <asm/dma.h> 338c2ecf20Sopenharmony_ci#include <asm/kmap_types.h> 348c2ecf20Sopenharmony_ci#include <asm/mmu_context.h> 358c2ecf20Sopenharmony_ci#include <asm/sections.h> 368c2ecf20Sopenharmony_ci#include <asm/pgtable.h> 378c2ecf20Sopenharmony_ci#include <asm/pgalloc.h> 388c2ecf20Sopenharmony_ci#include <asm/tlb.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ciunsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss; 418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(empty_zero_page); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_civoid copy_user_highpage(struct page *to, struct page *from, 448c2ecf20Sopenharmony_ci unsigned long vaddr, struct vm_area_struct *vma) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci void *vfrom, *vto; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci vto = kmap_atomic(to); 498c2ecf20Sopenharmony_ci vfrom = kmap_atomic(from); 508c2ecf20Sopenharmony_ci copy_page(vto, vfrom); 518c2ecf20Sopenharmony_ci kunmap_atomic(vfrom); 528c2ecf20Sopenharmony_ci kunmap_atomic(vto); 538c2ecf20Sopenharmony_ci /* Make sure this page is cleared on other CPU's too before using it */ 548c2ecf20Sopenharmony_ci smp_wmb(); 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciint __ref page_is_ram(unsigned long pfn) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci unsigned long addr = PFN_PHYS(pfn); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci return memblock_is_memory(addr) && !memblock_is_reserved(addr); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#ifndef CONFIG_NEED_MULTIPLE_NODES 658c2ecf20Sopenharmony_civoid __init paging_init(void) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci unsigned long max_zone_pfns[MAX_NR_ZONES]; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#ifdef CONFIG_ZONE_DMA 708c2ecf20Sopenharmony_ci max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; 718c2ecf20Sopenharmony_ci#endif 728c2ecf20Sopenharmony_ci#ifdef CONFIG_ZONE_DMA32 738c2ecf20Sopenharmony_ci max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; 748c2ecf20Sopenharmony_ci#endif 758c2ecf20Sopenharmony_ci max_zone_pfns[ZONE_NORMAL] = max_low_pfn; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci free_area_init(max_zone_pfns); 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_civoid __init mem_init(void) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci max_mapnr = max_low_pfn; 838c2ecf20Sopenharmony_ci high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci memblock_free_all(); 868c2ecf20Sopenharmony_ci mem_init_print_info(NULL); 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci#endif /* !CONFIG_NEED_MULTIPLE_NODES */ 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_civoid __ref free_initmem(void) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci free_initmem_default(POISON_FREE_INITMEM); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#ifdef CONFIG_MEMORY_HOTPLUG 968c2ecf20Sopenharmony_ciint arch_add_memory(int nid, u64 start, u64 size, struct mhp_params *params) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci unsigned long start_pfn = start >> PAGE_SHIFT; 998c2ecf20Sopenharmony_ci unsigned long nr_pages = size >> PAGE_SHIFT; 1008c2ecf20Sopenharmony_ci int ret; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci ret = __add_pages(nid, start_pfn, nr_pages, params); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (ret) 1058c2ecf20Sopenharmony_ci printk("%s: Problem encountered in __add_pages() as ret=%d\n", 1068c2ecf20Sopenharmony_ci __func__, ret); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci return ret; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_civoid arch_remove_memory(int nid, u64 start, 1128c2ecf20Sopenharmony_ci u64 size, struct vmem_altmap *altmap) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci unsigned long start_pfn = start >> PAGE_SHIFT; 1158c2ecf20Sopenharmony_ci unsigned long nr_pages = size >> PAGE_SHIFT; 1168c2ecf20Sopenharmony_ci struct page *page = pfn_to_page(start_pfn); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* With altmap the first mapped page is offset from @start */ 1198c2ecf20Sopenharmony_ci if (altmap) 1208c2ecf20Sopenharmony_ci page += vmem_altmap_offset(altmap); 1218c2ecf20Sopenharmony_ci __remove_pages(start_pfn, nr_pages, altmap); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci#ifdef CONFIG_NUMA 1258c2ecf20Sopenharmony_ciint memory_add_physaddr_to_nid(u64 start) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci return pa_to_nid(start); 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); 1308c2ecf20Sopenharmony_ci#endif 1318c2ecf20Sopenharmony_ci#endif 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci#ifdef CONFIG_SPARSEMEM_VMEMMAP 1348c2ecf20Sopenharmony_civoid __meminit arch_vmemmap_verify(pte_t *pte, int node, 1358c2ecf20Sopenharmony_ci unsigned long start, unsigned long end) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci unsigned long pfn = pte_pfn(*pte); 1388c2ecf20Sopenharmony_ci int actual_node = early_pfn_to_nid(pfn); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (node_distance(actual_node, node) > LOCAL_DISTANCE) 1418c2ecf20Sopenharmony_ci pr_warn("[%lx-%lx] potential offnode page_structs\n", 1428c2ecf20Sopenharmony_ci start, end - 1); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_civoid * __meminit arch_vmemmap_alloc_block_zero(unsigned long size, int node) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci void *p = vmemmap_alloc_block(size, node); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (!p) 1508c2ecf20Sopenharmony_ci return NULL; 1518c2ecf20Sopenharmony_ci memset(p, 0, size); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci return p; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cipte_t * __meminit arch_vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci pte_t *pte = pte_offset_kernel(pmd, addr); 1598c2ecf20Sopenharmony_ci if (pte_none(*pte)) { 1608c2ecf20Sopenharmony_ci pte_t entry; 1618c2ecf20Sopenharmony_ci void *p = arch_vmemmap_alloc_block_zero(PAGE_SIZE, node); 1628c2ecf20Sopenharmony_ci if (!p) 1638c2ecf20Sopenharmony_ci return NULL; 1648c2ecf20Sopenharmony_ci entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL); 1658c2ecf20Sopenharmony_ci set_pte_at(&init_mm, addr, pte, entry); 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci return pte; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cipmd_t * __meminit arch_vmemmap_pmd_populate(pud_t *pud, unsigned long addr, int node) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci pmd_t *pmd = pmd_offset(pud, addr); 1738c2ecf20Sopenharmony_ci if (pmd_none(*pmd)) { 1748c2ecf20Sopenharmony_ci void *p = arch_vmemmap_alloc_block_zero(PAGE_SIZE, node); 1758c2ecf20Sopenharmony_ci if (!p) 1768c2ecf20Sopenharmony_ci return NULL; 1778c2ecf20Sopenharmony_ci pmd_populate_kernel(&init_mm, pmd, p); 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci return pmd; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cipud_t * __meminit arch_vmemmap_pud_populate(p4d_t *p4d, unsigned long addr, int node) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci pud_t *pud = pud_offset(p4d, addr); 1858c2ecf20Sopenharmony_ci if (pud_none(*pud)) { 1868c2ecf20Sopenharmony_ci void *p = arch_vmemmap_alloc_block_zero(PAGE_SIZE, node); 1878c2ecf20Sopenharmony_ci if (!p) 1888c2ecf20Sopenharmony_ci return NULL; 1898c2ecf20Sopenharmony_ci#ifndef __PAGETABLE_PMD_FOLDED 1908c2ecf20Sopenharmony_ci pmd_init((unsigned long)p, (unsigned long)invalid_pte_table); 1918c2ecf20Sopenharmony_ci#endif 1928c2ecf20Sopenharmony_ci pud_populate(&init_mm, pud, p); 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci return pud; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cip4d_t * __meminit arch_vmemmap_p4d_populate(pgd_t *pgd, unsigned long addr, int node) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci p4d_t *p4d = p4d_offset(pgd, addr); 2008c2ecf20Sopenharmony_ci if (p4d_none(*p4d)) { 2018c2ecf20Sopenharmony_ci void *p = arch_vmemmap_alloc_block_zero(PAGE_SIZE, node); 2028c2ecf20Sopenharmony_ci if (!p) 2038c2ecf20Sopenharmony_ci return NULL; 2048c2ecf20Sopenharmony_ci#ifndef __PAGETABLE_PUD_FOLDED 2058c2ecf20Sopenharmony_ci pud_init((unsigned long)p, (unsigned long)invalid_pmd_table); 2068c2ecf20Sopenharmony_ci#endif 2078c2ecf20Sopenharmony_ci p4d_populate(&init_mm, p4d, p); 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci return p4d; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cipgd_t * __meminit arch_vmemmap_pgd_populate(unsigned long addr, int node) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci pgd_t *pgd = pgd_offset_k(addr); 2158c2ecf20Sopenharmony_ci if (pgd_none(*pgd)) { 2168c2ecf20Sopenharmony_ci void *p = arch_vmemmap_alloc_block_zero(PAGE_SIZE, node); 2178c2ecf20Sopenharmony_ci if (!p) 2188c2ecf20Sopenharmony_ci return NULL; 2198c2ecf20Sopenharmony_ci pgd_populate(&init_mm, pgd, p); 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci return pgd; 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ciint __meminit arch_vmemmap_populate_basepages(unsigned long start, 2258c2ecf20Sopenharmony_ci unsigned long end, int node) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci unsigned long addr = start; 2288c2ecf20Sopenharmony_ci pgd_t *pgd; 2298c2ecf20Sopenharmony_ci p4d_t *p4d; 2308c2ecf20Sopenharmony_ci pud_t *pud; 2318c2ecf20Sopenharmony_ci pmd_t *pmd; 2328c2ecf20Sopenharmony_ci pte_t *pte; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci for (; addr < end; addr += PAGE_SIZE) { 2358c2ecf20Sopenharmony_ci pgd = arch_vmemmap_pgd_populate(addr, node); 2368c2ecf20Sopenharmony_ci if (!pgd) 2378c2ecf20Sopenharmony_ci return -ENOMEM; 2388c2ecf20Sopenharmony_ci p4d = arch_vmemmap_p4d_populate(pgd, addr, node); 2398c2ecf20Sopenharmony_ci if (!p4d) 2408c2ecf20Sopenharmony_ci return -ENOMEM; 2418c2ecf20Sopenharmony_ci pud = arch_vmemmap_pud_populate(p4d, addr, node); 2428c2ecf20Sopenharmony_ci if (!pud) 2438c2ecf20Sopenharmony_ci return -ENOMEM; 2448c2ecf20Sopenharmony_ci pmd = arch_vmemmap_pmd_populate(pud, addr, node); 2458c2ecf20Sopenharmony_ci if (!pmd) 2468c2ecf20Sopenharmony_ci return -ENOMEM; 2478c2ecf20Sopenharmony_ci pte = arch_vmemmap_pte_populate(pmd, addr, node); 2488c2ecf20Sopenharmony_ci if (!pte) 2498c2ecf20Sopenharmony_ci return -ENOMEM; 2508c2ecf20Sopenharmony_ci arch_vmemmap_verify(pte, node, addr, addr + PAGE_SIZE); 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci return 0; 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ciint __meminit arch_vmemmap_populate_hugepages(unsigned long start, 2578c2ecf20Sopenharmony_ci unsigned long end, int node) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci unsigned long addr = start; 2608c2ecf20Sopenharmony_ci unsigned long next; 2618c2ecf20Sopenharmony_ci pgd_t *pgd; 2628c2ecf20Sopenharmony_ci p4d_t *p4d; 2638c2ecf20Sopenharmony_ci pud_t *pud; 2648c2ecf20Sopenharmony_ci pmd_t *pmd; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci for (addr = start; addr < end; addr = next) { 2678c2ecf20Sopenharmony_ci next = pmd_addr_end(addr, end); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci pgd = arch_vmemmap_pgd_populate(addr, node); 2708c2ecf20Sopenharmony_ci if (!pgd) 2718c2ecf20Sopenharmony_ci return -ENOMEM; 2728c2ecf20Sopenharmony_ci p4d = arch_vmemmap_p4d_populate(pgd, addr, node); 2738c2ecf20Sopenharmony_ci if (!p4d) 2748c2ecf20Sopenharmony_ci return -ENOMEM; 2758c2ecf20Sopenharmony_ci pud = arch_vmemmap_pud_populate(p4d, addr, node); 2768c2ecf20Sopenharmony_ci if (!pud) 2778c2ecf20Sopenharmony_ci return -ENOMEM; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci pmd = pmd_offset(pud, addr); 2808c2ecf20Sopenharmony_ci if (pmd_none(*pmd)) { 2818c2ecf20Sopenharmony_ci void *p = NULL; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci p = arch_vmemmap_alloc_block_zero(PMD_SIZE, node); 2848c2ecf20Sopenharmony_ci if (p) { 2858c2ecf20Sopenharmony_ci pmd_t entry; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci entry = pfn_pmd(virt_to_pfn(p), PAGE_KERNEL); 2888c2ecf20Sopenharmony_ci pmd_val(entry) |= _PAGE_HUGE | _PAGE_HGLOBAL; 2898c2ecf20Sopenharmony_ci set_pmd_at(&init_mm, addr, pmd, entry); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci continue; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci } else if (pmd_val(*pmd) & _PAGE_HUGE) { 2948c2ecf20Sopenharmony_ci arch_vmemmap_verify((pte_t *)pmd, node, addr, next); 2958c2ecf20Sopenharmony_ci continue; 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci if (arch_vmemmap_populate_basepages(addr, next, node)) 2988c2ecf20Sopenharmony_ci return -ENOMEM; 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci return 0; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ciint __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, 3058c2ecf20Sopenharmony_ci struct vmem_altmap *altmap) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci return arch_vmemmap_populate_hugepages(start, end, node); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_civoid vmemmap_free(unsigned long start, unsigned long end, 3108c2ecf20Sopenharmony_ci struct vmem_altmap *altmap) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci#endif 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_cipte_t * __init populate_kernel_pte(unsigned long addr) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci pgd_t *pgd = pgd_offset_k(addr); 3188c2ecf20Sopenharmony_ci p4d_t *p4d = p4d_offset(pgd, addr); 3198c2ecf20Sopenharmony_ci pud_t *pud; 3208c2ecf20Sopenharmony_ci pmd_t *pmd; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci if (p4d_none(*p4d)) { 3238c2ecf20Sopenharmony_ci pud = memblock_alloc(PAGE_SIZE, PAGE_SIZE); 3248c2ecf20Sopenharmony_ci if (!pud) 3258c2ecf20Sopenharmony_ci panic("%s: Failed to allocate memory\n", __func__); 3268c2ecf20Sopenharmony_ci p4d_populate(&init_mm, p4d, pud); 3278c2ecf20Sopenharmony_ci#ifndef __PAGETABLE_PUD_FOLDED 3288c2ecf20Sopenharmony_ci pud_init((unsigned long)pud, (unsigned long)invalid_pmd_table); 3298c2ecf20Sopenharmony_ci#endif 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci pud = pud_offset(p4d, addr); 3338c2ecf20Sopenharmony_ci if (pud_none(*pud)) { 3348c2ecf20Sopenharmony_ci pmd = memblock_alloc(PAGE_SIZE, PAGE_SIZE); 3358c2ecf20Sopenharmony_ci if (!pmd) 3368c2ecf20Sopenharmony_ci panic("%s: Failed to allocate memory\n", __func__); 3378c2ecf20Sopenharmony_ci pud_populate(&init_mm, pud, pmd); 3388c2ecf20Sopenharmony_ci#ifndef __PAGETABLE_PMD_FOLDED 3398c2ecf20Sopenharmony_ci pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table); 3408c2ecf20Sopenharmony_ci#endif 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci pmd = pmd_offset(pud, addr); 3448c2ecf20Sopenharmony_ci if (!pmd_present(*pmd)) { 3458c2ecf20Sopenharmony_ci pte_t *pte; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE); 3488c2ecf20Sopenharmony_ci if (!pte) 3498c2ecf20Sopenharmony_ci panic("%s: Failed to allocate memory\n", __func__); 3508c2ecf20Sopenharmony_ci pmd_populate_kernel(&init_mm, pmd, pte); 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci return pte_offset_kernel(pmd, addr); 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_civoid __init __set_fixmap(enum fixed_addresses idx, 3578c2ecf20Sopenharmony_ci phys_addr_t phys, pgprot_t flags) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci unsigned long addr = __fix_to_virt(idx); 3608c2ecf20Sopenharmony_ci pte_t *ptep; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci ptep = populate_kernel_pte(addr); 3658c2ecf20Sopenharmony_ci if (!pte_none(*ptep)) { 3668c2ecf20Sopenharmony_ci pte_ERROR(*ptep); 3678c2ecf20Sopenharmony_ci return; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (pgprot_val(flags)) 3718c2ecf20Sopenharmony_ci set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, flags)); 3728c2ecf20Sopenharmony_ci else { 3738c2ecf20Sopenharmony_ci pte_clear(&init_mm, addr, ptep); 3748c2ecf20Sopenharmony_ci flush_tlb_kernel_range(addr, addr + PAGE_SIZE); 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci/* 3798c2ecf20Sopenharmony_ci * Align swapper_pg_dir in to 64K, allows its address to be loaded 3808c2ecf20Sopenharmony_ci * with a single LUI instruction in the TLB handlers. If we used 3818c2ecf20Sopenharmony_ci * __aligned(64K), its size would get rounded up to the alignment 3828c2ecf20Sopenharmony_ci * size, and waste space. So we place it in its own section and align 3838c2ecf20Sopenharmony_ci * it in the linker script. 3848c2ecf20Sopenharmony_ci */ 3858c2ecf20Sopenharmony_cipgd_t swapper_pg_dir[_PTRS_PER_PGD] __section(".bss..swapper_pg_dir"); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cipgd_t invalid_pg_dir[_PTRS_PER_PGD] __page_aligned_bss; 3888c2ecf20Sopenharmony_ci#ifndef __PAGETABLE_PUD_FOLDED 3898c2ecf20Sopenharmony_cipud_t invalid_pud_table[PTRS_PER_PUD] __page_aligned_bss; 3908c2ecf20Sopenharmony_ciEXPORT_SYMBOL(invalid_pud_table); 3918c2ecf20Sopenharmony_ci#endif 3928c2ecf20Sopenharmony_ci#ifndef __PAGETABLE_PMD_FOLDED 3938c2ecf20Sopenharmony_cipmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned_bss; 3948c2ecf20Sopenharmony_ciEXPORT_SYMBOL(invalid_pmd_table); 3958c2ecf20Sopenharmony_ci#endif 3968c2ecf20Sopenharmony_cipte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss; 3978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(invalid_pte_table); 398