18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * PowerPC version 48c2ecf20Sopenharmony_ci * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) 78c2ecf20Sopenharmony_ci * and Cort Dougan (PReP) (cort@cs.nmt.edu) 88c2ecf20Sopenharmony_ci * Copyright (C) 1996 Paul Mackerras 98c2ecf20Sopenharmony_ci * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Derived from "arch/i386/mm/init.c" 128c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/export.h> 168c2ecf20Sopenharmony_ci#include <linux/sched.h> 178c2ecf20Sopenharmony_ci#include <linux/kernel.h> 188c2ecf20Sopenharmony_ci#include <linux/errno.h> 198c2ecf20Sopenharmony_ci#include <linux/string.h> 208c2ecf20Sopenharmony_ci#include <linux/gfp.h> 218c2ecf20Sopenharmony_ci#include <linux/types.h> 228c2ecf20Sopenharmony_ci#include <linux/mm.h> 238c2ecf20Sopenharmony_ci#include <linux/stddef.h> 248c2ecf20Sopenharmony_ci#include <linux/init.h> 258c2ecf20Sopenharmony_ci#include <linux/memblock.h> 268c2ecf20Sopenharmony_ci#include <linux/highmem.h> 278c2ecf20Sopenharmony_ci#include <linux/initrd.h> 288c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 298c2ecf20Sopenharmony_ci#include <linux/suspend.h> 308c2ecf20Sopenharmony_ci#include <linux/hugetlb.h> 318c2ecf20Sopenharmony_ci#include <linux/slab.h> 328c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 338c2ecf20Sopenharmony_ci#include <linux/memremap.h> 348c2ecf20Sopenharmony_ci#include <linux/dma-direct.h> 358c2ecf20Sopenharmony_ci#include <linux/kprobes.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <asm/prom.h> 388c2ecf20Sopenharmony_ci#include <asm/io.h> 398c2ecf20Sopenharmony_ci#include <asm/mmu_context.h> 408c2ecf20Sopenharmony_ci#include <asm/mmu.h> 418c2ecf20Sopenharmony_ci#include <asm/smp.h> 428c2ecf20Sopenharmony_ci#include <asm/machdep.h> 438c2ecf20Sopenharmony_ci#include <asm/btext.h> 448c2ecf20Sopenharmony_ci#include <asm/tlb.h> 458c2ecf20Sopenharmony_ci#include <asm/sections.h> 468c2ecf20Sopenharmony_ci#include <asm/sparsemem.h> 478c2ecf20Sopenharmony_ci#include <asm/vdso.h> 488c2ecf20Sopenharmony_ci#include <asm/fixmap.h> 498c2ecf20Sopenharmony_ci#include <asm/swiotlb.h> 508c2ecf20Sopenharmony_ci#include <asm/rtas.h> 518c2ecf20Sopenharmony_ci#include <asm/kasan.h> 528c2ecf20Sopenharmony_ci#include <asm/svm.h> 538c2ecf20Sopenharmony_ci#include <asm/mmzone.h> 548c2ecf20Sopenharmony_ci#include <asm/ftrace.h> 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#include <mm/mmu_decl.h> 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#ifndef CPU_FTR_COHERENT_ICACHE 598c2ecf20Sopenharmony_ci#define CPU_FTR_COHERENT_ICACHE 0 /* XXX for now */ 608c2ecf20Sopenharmony_ci#define CPU_FTR_NOEXECUTE 0 618c2ecf20Sopenharmony_ci#endif 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ciunsigned long long memory_limit; 648c2ecf20Sopenharmony_cibool init_mem_is_free; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#ifdef CONFIG_HIGHMEM 678c2ecf20Sopenharmony_cipte_t *kmap_pte; 688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kmap_pte); 698c2ecf20Sopenharmony_ci#endif 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cipgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, 728c2ecf20Sopenharmony_ci unsigned long size, pgprot_t vma_prot) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci if (ppc_md.phys_mem_access_prot) 758c2ecf20Sopenharmony_ci return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (!page_is_ram(pfn)) 788c2ecf20Sopenharmony_ci vma_prot = pgprot_noncached(vma_prot); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci return vma_prot; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(phys_mem_access_prot); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#ifdef CONFIG_MEMORY_HOTPLUG 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#ifdef CONFIG_NUMA 878c2ecf20Sopenharmony_ciint memory_add_physaddr_to_nid(u64 start) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci return hot_add_scn_to_nid(start); 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci#endif 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ciint __weak create_section_mapping(unsigned long start, unsigned long end, 948c2ecf20Sopenharmony_ci int nid, pgprot_t prot) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci return -ENODEV; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ciint __weak remove_section_mapping(unsigned long start, unsigned long end) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci return -ENODEV; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci#define FLUSH_CHUNK_SIZE SZ_1G 1058c2ecf20Sopenharmony_ci/** 1068c2ecf20Sopenharmony_ci * flush_dcache_range_chunked(): Write any modified data cache blocks out to 1078c2ecf20Sopenharmony_ci * memory and invalidate them, in chunks of up to FLUSH_CHUNK_SIZE 1088c2ecf20Sopenharmony_ci * Does not invalidate the corresponding instruction cache blocks. 1098c2ecf20Sopenharmony_ci * 1108c2ecf20Sopenharmony_ci * @start: the start address 1118c2ecf20Sopenharmony_ci * @stop: the stop address (exclusive) 1128c2ecf20Sopenharmony_ci * @chunk: the max size of the chunks 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_cistatic void flush_dcache_range_chunked(unsigned long start, unsigned long stop, 1158c2ecf20Sopenharmony_ci unsigned long chunk) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci unsigned long i; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci for (i = start; i < stop; i += chunk) { 1208c2ecf20Sopenharmony_ci flush_dcache_range(i, min(stop, i + chunk)); 1218c2ecf20Sopenharmony_ci cond_resched(); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ciint __ref arch_add_memory(int nid, u64 start, u64 size, 1268c2ecf20Sopenharmony_ci struct mhp_params *params) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci unsigned long start_pfn = start >> PAGE_SHIFT; 1298c2ecf20Sopenharmony_ci unsigned long nr_pages = size >> PAGE_SHIFT; 1308c2ecf20Sopenharmony_ci int rc; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci start = (unsigned long)__va(start); 1338c2ecf20Sopenharmony_ci rc = create_section_mapping(start, start + size, nid, 1348c2ecf20Sopenharmony_ci params->pgprot); 1358c2ecf20Sopenharmony_ci if (rc) { 1368c2ecf20Sopenharmony_ci pr_warn("Unable to create mapping for hot added memory 0x%llx..0x%llx: %d\n", 1378c2ecf20Sopenharmony_ci start, start + size, rc); 1388c2ecf20Sopenharmony_ci return -EFAULT; 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return __add_pages(nid, start_pfn, nr_pages, params); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_civoid __ref arch_remove_memory(int nid, u64 start, u64 size, 1458c2ecf20Sopenharmony_ci struct vmem_altmap *altmap) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci unsigned long start_pfn = start >> PAGE_SHIFT; 1488c2ecf20Sopenharmony_ci unsigned long nr_pages = size >> PAGE_SHIFT; 1498c2ecf20Sopenharmony_ci int ret; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci __remove_pages(start_pfn, nr_pages, altmap); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* Remove htab bolted mappings for this section of memory */ 1548c2ecf20Sopenharmony_ci start = (unsigned long)__va(start); 1558c2ecf20Sopenharmony_ci flush_dcache_range_chunked(start, start + size, FLUSH_CHUNK_SIZE); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci ret = remove_section_mapping(start, start + size); 1588c2ecf20Sopenharmony_ci WARN_ON_ONCE(ret); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* Ensure all vmalloc mappings are flushed in case they also 1618c2ecf20Sopenharmony_ci * hit that section of memory 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_ci vm_unmap_aliases(); 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci#endif 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci#ifndef CONFIG_NEED_MULTIPLE_NODES 1688c2ecf20Sopenharmony_civoid __init mem_topology_setup(void) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; 1718c2ecf20Sopenharmony_ci min_low_pfn = MEMORY_START >> PAGE_SHIFT; 1728c2ecf20Sopenharmony_ci#ifdef CONFIG_HIGHMEM 1738c2ecf20Sopenharmony_ci max_low_pfn = lowmem_end_addr >> PAGE_SHIFT; 1748c2ecf20Sopenharmony_ci#endif 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* Place all memblock_regions in the same node and merge contiguous 1778c2ecf20Sopenharmony_ci * memblock_regions 1788c2ecf20Sopenharmony_ci */ 1798c2ecf20Sopenharmony_ci memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_civoid __init initmem_init(void) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci sparse_init(); 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci/* mark pages that don't exist as nosave */ 1888c2ecf20Sopenharmony_cistatic int __init mark_nonram_nosave(void) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci unsigned long spfn, epfn, prev = 0; 1918c2ecf20Sopenharmony_ci int i; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci for_each_mem_pfn_range(i, MAX_NUMNODES, &spfn, &epfn, NULL) { 1948c2ecf20Sopenharmony_ci if (prev && prev < spfn) 1958c2ecf20Sopenharmony_ci register_nosave_region(prev, spfn); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci prev = epfn; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci return 0; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci#else /* CONFIG_NEED_MULTIPLE_NODES */ 2038c2ecf20Sopenharmony_cistatic int __init mark_nonram_nosave(void) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci return 0; 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci#endif 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci/* 2108c2ecf20Sopenharmony_ci * Zones usage: 2118c2ecf20Sopenharmony_ci * 2128c2ecf20Sopenharmony_ci * We setup ZONE_DMA to be 31-bits on all platforms and ZONE_NORMAL to be 2138c2ecf20Sopenharmony_ci * everything else. GFP_DMA32 page allocations automatically fall back to 2148c2ecf20Sopenharmony_ci * ZONE_DMA. 2158c2ecf20Sopenharmony_ci * 2168c2ecf20Sopenharmony_ci * By using 31-bit unconditionally, we can exploit zone_dma_bits to inform the 2178c2ecf20Sopenharmony_ci * generic DMA mapping code. 32-bit only devices (if not handled by an IOMMU 2188c2ecf20Sopenharmony_ci * anyway) will take a first dip into ZONE_NORMAL and get otherwise served by 2198c2ecf20Sopenharmony_ci * ZONE_DMA. 2208c2ecf20Sopenharmony_ci */ 2218c2ecf20Sopenharmony_cistatic unsigned long max_zone_pfns[MAX_NR_ZONES]; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/* 2248c2ecf20Sopenharmony_ci * paging_init() sets up the page tables - in fact we've already done this. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_civoid __init paging_init(void) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci unsigned long long total_ram = memblock_phys_mem_size(); 2298c2ecf20Sopenharmony_ci phys_addr_t top_of_ram = memblock_end_of_DRAM(); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci#ifdef CONFIG_HIGHMEM 2328c2ecf20Sopenharmony_ci unsigned long v = __fix_to_virt(FIX_KMAP_END); 2338c2ecf20Sopenharmony_ci unsigned long end = __fix_to_virt(FIX_KMAP_BEGIN); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci for (; v < end; v += PAGE_SIZE) 2368c2ecf20Sopenharmony_ci map_kernel_page(v, 0, __pgprot(0)); /* XXX gross */ 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci map_kernel_page(PKMAP_BASE, 0, __pgprot(0)); /* XXX gross */ 2398c2ecf20Sopenharmony_ci pkmap_page_table = virt_to_kpte(PKMAP_BASE); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN)); 2428c2ecf20Sopenharmony_ci#endif /* CONFIG_HIGHMEM */ 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%llx\n", 2458c2ecf20Sopenharmony_ci (unsigned long long)top_of_ram, total_ram); 2468c2ecf20Sopenharmony_ci printk(KERN_DEBUG "Memory hole size: %ldMB\n", 2478c2ecf20Sopenharmony_ci (long int)((top_of_ram - total_ram) >> 20)); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* 2508c2ecf20Sopenharmony_ci * Allow 30-bit DMA for very limited Broadcom wifi chips on many 2518c2ecf20Sopenharmony_ci * powerbooks. 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PPC32)) 2548c2ecf20Sopenharmony_ci zone_dma_bits = 30; 2558c2ecf20Sopenharmony_ci else 2568c2ecf20Sopenharmony_ci zone_dma_bits = 31; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci#ifdef CONFIG_ZONE_DMA 2598c2ecf20Sopenharmony_ci max_zone_pfns[ZONE_DMA] = min(max_low_pfn, 2608c2ecf20Sopenharmony_ci 1UL << (zone_dma_bits - PAGE_SHIFT)); 2618c2ecf20Sopenharmony_ci#endif 2628c2ecf20Sopenharmony_ci max_zone_pfns[ZONE_NORMAL] = max_low_pfn; 2638c2ecf20Sopenharmony_ci#ifdef CONFIG_HIGHMEM 2648c2ecf20Sopenharmony_ci max_zone_pfns[ZONE_HIGHMEM] = max_pfn; 2658c2ecf20Sopenharmony_ci#endif 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci free_area_init(max_zone_pfns); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci mark_nonram_nosave(); 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_civoid __init mem_init(void) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci /* 2758c2ecf20Sopenharmony_ci * book3s is limited to 16 page sizes due to encoding this in 2768c2ecf20Sopenharmony_ci * a 4-bit field for slices. 2778c2ecf20Sopenharmony_ci */ 2788c2ecf20Sopenharmony_ci BUILD_BUG_ON(MMU_PAGE_COUNT > 16); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci#ifdef CONFIG_SWIOTLB 2818c2ecf20Sopenharmony_ci /* 2828c2ecf20Sopenharmony_ci * Some platforms (e.g. 85xx) limit DMA-able memory way below 2838c2ecf20Sopenharmony_ci * 4G. We force memblock to bottom-up mode to ensure that the 2848c2ecf20Sopenharmony_ci * memory allocated in swiotlb_init() is DMA-able. 2858c2ecf20Sopenharmony_ci * As it's the last memblock allocation, no need to reset it 2868c2ecf20Sopenharmony_ci * back to to-down. 2878c2ecf20Sopenharmony_ci */ 2888c2ecf20Sopenharmony_ci memblock_set_bottom_up(true); 2898c2ecf20Sopenharmony_ci if (is_secure_guest()) 2908c2ecf20Sopenharmony_ci svm_swiotlb_init(); 2918c2ecf20Sopenharmony_ci else 2928c2ecf20Sopenharmony_ci swiotlb_init(0); 2938c2ecf20Sopenharmony_ci#endif 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci kasan_late_init(); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci memblock_free_all(); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci#ifdef CONFIG_HIGHMEM 3028c2ecf20Sopenharmony_ci { 3038c2ecf20Sopenharmony_ci unsigned long pfn, highmem_mapnr; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci highmem_mapnr = lowmem_end_addr >> PAGE_SHIFT; 3068c2ecf20Sopenharmony_ci for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) { 3078c2ecf20Sopenharmony_ci phys_addr_t paddr = (phys_addr_t)pfn << PAGE_SHIFT; 3088c2ecf20Sopenharmony_ci struct page *page = pfn_to_page(pfn); 3098c2ecf20Sopenharmony_ci if (!memblock_is_reserved(paddr)) 3108c2ecf20Sopenharmony_ci free_highmem_page(page); 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci#endif /* CONFIG_HIGHMEM */ 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_FSL_BOOK3E) && !defined(CONFIG_SMP) 3168c2ecf20Sopenharmony_ci /* 3178c2ecf20Sopenharmony_ci * If smp is enabled, next_tlbcam_idx is initialized in the cpu up 3188c2ecf20Sopenharmony_ci * functions.... do it here for the non-smp case. 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_ci per_cpu(next_tlbcam_idx, smp_processor_id()) = 3218c2ecf20Sopenharmony_ci (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) - 1; 3228c2ecf20Sopenharmony_ci#endif 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci mem_init_print_info(NULL); 3258c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC32 3268c2ecf20Sopenharmony_ci pr_info("Kernel virtual memory layout:\n"); 3278c2ecf20Sopenharmony_ci#ifdef CONFIG_KASAN 3288c2ecf20Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : kasan shadow mem\n", 3298c2ecf20Sopenharmony_ci KASAN_SHADOW_START, KASAN_SHADOW_END); 3308c2ecf20Sopenharmony_ci#endif 3318c2ecf20Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : fixmap\n", FIXADDR_START, FIXADDR_TOP); 3328c2ecf20Sopenharmony_ci#ifdef CONFIG_HIGHMEM 3338c2ecf20Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : highmem PTEs\n", 3348c2ecf20Sopenharmony_ci PKMAP_BASE, PKMAP_ADDR(LAST_PKMAP)); 3358c2ecf20Sopenharmony_ci#endif /* CONFIG_HIGHMEM */ 3368c2ecf20Sopenharmony_ci if (ioremap_bot != IOREMAP_TOP) 3378c2ecf20Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : early ioremap\n", 3388c2ecf20Sopenharmony_ci ioremap_bot, IOREMAP_TOP); 3398c2ecf20Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : vmalloc & ioremap\n", 3408c2ecf20Sopenharmony_ci VMALLOC_START, VMALLOC_END); 3418c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC32 */ 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_civoid free_initmem(void) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci ppc_md.progress = ppc_printk_progress; 3478c2ecf20Sopenharmony_ci mark_initmem_nx(); 3488c2ecf20Sopenharmony_ci init_mem_is_free = true; 3498c2ecf20Sopenharmony_ci free_initmem_default(POISON_FREE_INITMEM); 3508c2ecf20Sopenharmony_ci ftrace_free_init_tramp(); 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci/** 3548c2ecf20Sopenharmony_ci * flush_coherent_icache() - if a CPU has a coherent icache, flush it 3558c2ecf20Sopenharmony_ci * @addr: The base address to use (can be any valid address, the whole cache will be flushed) 3568c2ecf20Sopenharmony_ci * Return true if the cache was flushed, false otherwise 3578c2ecf20Sopenharmony_ci */ 3588c2ecf20Sopenharmony_cistatic inline bool flush_coherent_icache(unsigned long addr) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci /* 3618c2ecf20Sopenharmony_ci * For a snooping icache, we still need a dummy icbi to purge all the 3628c2ecf20Sopenharmony_ci * prefetched instructions from the ifetch buffers. We also need a sync 3638c2ecf20Sopenharmony_ci * before the icbi to order the the actual stores to memory that might 3648c2ecf20Sopenharmony_ci * have modified instructions with the icbi. 3658c2ecf20Sopenharmony_ci */ 3668c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) { 3678c2ecf20Sopenharmony_ci mb(); /* sync */ 3688c2ecf20Sopenharmony_ci allow_read_from_user((const void __user *)addr, L1_CACHE_BYTES); 3698c2ecf20Sopenharmony_ci icbi((void *)addr); 3708c2ecf20Sopenharmony_ci prevent_read_from_user((const void __user *)addr, L1_CACHE_BYTES); 3718c2ecf20Sopenharmony_ci mb(); /* sync */ 3728c2ecf20Sopenharmony_ci isync(); 3738c2ecf20Sopenharmony_ci return true; 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci return false; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci/** 3808c2ecf20Sopenharmony_ci * invalidate_icache_range() - Flush the icache by issuing icbi across an address range 3818c2ecf20Sopenharmony_ci * @start: the start address 3828c2ecf20Sopenharmony_ci * @stop: the stop address (exclusive) 3838c2ecf20Sopenharmony_ci */ 3848c2ecf20Sopenharmony_cistatic void invalidate_icache_range(unsigned long start, unsigned long stop) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci unsigned long shift = l1_icache_shift(); 3878c2ecf20Sopenharmony_ci unsigned long bytes = l1_icache_bytes(); 3888c2ecf20Sopenharmony_ci char *addr = (char *)(start & ~(bytes - 1)); 3898c2ecf20Sopenharmony_ci unsigned long size = stop - (unsigned long)addr + (bytes - 1); 3908c2ecf20Sopenharmony_ci unsigned long i; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci for (i = 0; i < size >> shift; i++, addr += bytes) 3938c2ecf20Sopenharmony_ci icbi(addr); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci mb(); /* sync */ 3968c2ecf20Sopenharmony_ci isync(); 3978c2ecf20Sopenharmony_ci} 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci/** 4008c2ecf20Sopenharmony_ci * flush_icache_range: Write any modified data cache blocks out to memory 4018c2ecf20Sopenharmony_ci * and invalidate the corresponding blocks in the instruction cache 4028c2ecf20Sopenharmony_ci * 4038c2ecf20Sopenharmony_ci * Generic code will call this after writing memory, before executing from it. 4048c2ecf20Sopenharmony_ci * 4058c2ecf20Sopenharmony_ci * @start: the start address 4068c2ecf20Sopenharmony_ci * @stop: the stop address (exclusive) 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_civoid flush_icache_range(unsigned long start, unsigned long stop) 4098c2ecf20Sopenharmony_ci{ 4108c2ecf20Sopenharmony_ci if (flush_coherent_icache(start)) 4118c2ecf20Sopenharmony_ci return; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci clean_dcache_range(start, stop); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_44x)) { 4168c2ecf20Sopenharmony_ci /* 4178c2ecf20Sopenharmony_ci * Flash invalidate on 44x because we are passed kmapped 4188c2ecf20Sopenharmony_ci * addresses and this doesn't work for userspace pages due to 4198c2ecf20Sopenharmony_ci * the virtually tagged icache. 4208c2ecf20Sopenharmony_ci */ 4218c2ecf20Sopenharmony_ci iccci((void *)start); 4228c2ecf20Sopenharmony_ci mb(); /* sync */ 4238c2ecf20Sopenharmony_ci isync(); 4248c2ecf20Sopenharmony_ci } else 4258c2ecf20Sopenharmony_ci invalidate_icache_range(start, stop); 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(flush_icache_range); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci#if !defined(CONFIG_PPC_8xx) && !defined(CONFIG_PPC64) 4308c2ecf20Sopenharmony_ci/** 4318c2ecf20Sopenharmony_ci * flush_dcache_icache_phys() - Flush a page by it's physical address 4328c2ecf20Sopenharmony_ci * @physaddr: the physical address of the page 4338c2ecf20Sopenharmony_ci */ 4348c2ecf20Sopenharmony_cistatic void flush_dcache_icache_phys(unsigned long physaddr) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci unsigned long bytes = l1_dcache_bytes(); 4378c2ecf20Sopenharmony_ci unsigned long nb = PAGE_SIZE / bytes; 4388c2ecf20Sopenharmony_ci unsigned long addr = physaddr & PAGE_MASK; 4398c2ecf20Sopenharmony_ci unsigned long msr, msr0; 4408c2ecf20Sopenharmony_ci unsigned long loop1 = addr, loop2 = addr; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci msr0 = mfmsr(); 4438c2ecf20Sopenharmony_ci msr = msr0 & ~MSR_DR; 4448c2ecf20Sopenharmony_ci /* 4458c2ecf20Sopenharmony_ci * This must remain as ASM to prevent potential memory accesses 4468c2ecf20Sopenharmony_ci * while the data MMU is disabled 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_ci asm volatile( 4498c2ecf20Sopenharmony_ci " mtctr %2;\n" 4508c2ecf20Sopenharmony_ci " mtmsr %3;\n" 4518c2ecf20Sopenharmony_ci " isync;\n" 4528c2ecf20Sopenharmony_ci "0: dcbst 0, %0;\n" 4538c2ecf20Sopenharmony_ci " addi %0, %0, %4;\n" 4548c2ecf20Sopenharmony_ci " bdnz 0b;\n" 4558c2ecf20Sopenharmony_ci " sync;\n" 4568c2ecf20Sopenharmony_ci " mtctr %2;\n" 4578c2ecf20Sopenharmony_ci "1: icbi 0, %1;\n" 4588c2ecf20Sopenharmony_ci " addi %1, %1, %4;\n" 4598c2ecf20Sopenharmony_ci " bdnz 1b;\n" 4608c2ecf20Sopenharmony_ci " sync;\n" 4618c2ecf20Sopenharmony_ci " mtmsr %5;\n" 4628c2ecf20Sopenharmony_ci " isync;\n" 4638c2ecf20Sopenharmony_ci : "+&r" (loop1), "+&r" (loop2) 4648c2ecf20Sopenharmony_ci : "r" (nb), "r" (msr), "i" (bytes), "r" (msr0) 4658c2ecf20Sopenharmony_ci : "ctr", "memory"); 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ciNOKPROBE_SYMBOL(flush_dcache_icache_phys) 4688c2ecf20Sopenharmony_ci#endif // !defined(CONFIG_PPC_8xx) && !defined(CONFIG_PPC64) 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci/* 4718c2ecf20Sopenharmony_ci * This is called when a page has been modified by the kernel. 4728c2ecf20Sopenharmony_ci * It just marks the page as not i-cache clean. We do the i-cache 4738c2ecf20Sopenharmony_ci * flush later when the page is given to a user process, if necessary. 4748c2ecf20Sopenharmony_ci */ 4758c2ecf20Sopenharmony_civoid flush_dcache_page(struct page *page) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) 4788c2ecf20Sopenharmony_ci return; 4798c2ecf20Sopenharmony_ci /* avoid an atomic op if possible */ 4808c2ecf20Sopenharmony_ci if (test_bit(PG_arch_1, &page->flags)) 4818c2ecf20Sopenharmony_ci clear_bit(PG_arch_1, &page->flags); 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ciEXPORT_SYMBOL(flush_dcache_page); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_civoid flush_dcache_icache_page(struct page *page) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci#ifdef CONFIG_HUGETLB_PAGE 4888c2ecf20Sopenharmony_ci if (PageCompound(page)) { 4898c2ecf20Sopenharmony_ci flush_dcache_icache_hugepage(page); 4908c2ecf20Sopenharmony_ci return; 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci#endif 4938c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_8xx) || defined(CONFIG_PPC64) 4948c2ecf20Sopenharmony_ci /* On 8xx there is no need to kmap since highmem is not supported */ 4958c2ecf20Sopenharmony_ci __flush_dcache_icache(page_address(page)); 4968c2ecf20Sopenharmony_ci#else 4978c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_BOOKE) || sizeof(phys_addr_t) > sizeof(void *)) { 4988c2ecf20Sopenharmony_ci void *start = kmap_atomic(page); 4998c2ecf20Sopenharmony_ci __flush_dcache_icache(start); 5008c2ecf20Sopenharmony_ci kunmap_atomic(start); 5018c2ecf20Sopenharmony_ci } else { 5028c2ecf20Sopenharmony_ci unsigned long addr = page_to_pfn(page) << PAGE_SHIFT; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci if (flush_coherent_icache(addr)) 5058c2ecf20Sopenharmony_ci return; 5068c2ecf20Sopenharmony_ci flush_dcache_icache_phys(addr); 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci#endif 5098c2ecf20Sopenharmony_ci} 5108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(flush_dcache_icache_page); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci/** 5138c2ecf20Sopenharmony_ci * __flush_dcache_icache(): Flush a particular page from the data cache to RAM. 5148c2ecf20Sopenharmony_ci * Note: this is necessary because the instruction cache does *not* 5158c2ecf20Sopenharmony_ci * snoop from the data cache. 5168c2ecf20Sopenharmony_ci * 5178c2ecf20Sopenharmony_ci * @page: the address of the page to flush 5188c2ecf20Sopenharmony_ci */ 5198c2ecf20Sopenharmony_civoid __flush_dcache_icache(void *p) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci unsigned long addr = (unsigned long)p; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci if (flush_coherent_icache(addr)) 5248c2ecf20Sopenharmony_ci return; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci clean_dcache_range(addr, addr + PAGE_SIZE); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci /* 5298c2ecf20Sopenharmony_ci * We don't flush the icache on 44x. Those have a virtual icache and we 5308c2ecf20Sopenharmony_ci * don't have access to the virtual address here (it's not the page 5318c2ecf20Sopenharmony_ci * vaddr but where it's mapped in user space). The flushing of the 5328c2ecf20Sopenharmony_ci * icache on these is handled elsewhere, when a change in the address 5338c2ecf20Sopenharmony_ci * space occurs, before returning to user space. 5348c2ecf20Sopenharmony_ci */ 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci if (mmu_has_feature(MMU_FTR_TYPE_44x)) 5378c2ecf20Sopenharmony_ci return; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci invalidate_icache_range(addr, addr + PAGE_SIZE); 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_civoid clear_user_page(void *page, unsigned long vaddr, struct page *pg) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci clear_page(page); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci /* 5478c2ecf20Sopenharmony_ci * We shouldn't have to do this, but some versions of glibc 5488c2ecf20Sopenharmony_ci * require it (ld.so assumes zero filled pages are icache clean) 5498c2ecf20Sopenharmony_ci * - Anton 5508c2ecf20Sopenharmony_ci */ 5518c2ecf20Sopenharmony_ci flush_dcache_page(pg); 5528c2ecf20Sopenharmony_ci} 5538c2ecf20Sopenharmony_ciEXPORT_SYMBOL(clear_user_page); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_civoid copy_user_page(void *vto, void *vfrom, unsigned long vaddr, 5568c2ecf20Sopenharmony_ci struct page *pg) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci copy_page(vto, vfrom); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci /* 5618c2ecf20Sopenharmony_ci * We should be able to use the following optimisation, however 5628c2ecf20Sopenharmony_ci * there are two problems. 5638c2ecf20Sopenharmony_ci * Firstly a bug in some versions of binutils meant PLT sections 5648c2ecf20Sopenharmony_ci * were not marked executable. 5658c2ecf20Sopenharmony_ci * Secondly the first word in the GOT section is blrl, used 5668c2ecf20Sopenharmony_ci * to establish the GOT address. Until recently the GOT was 5678c2ecf20Sopenharmony_ci * not marked executable. 5688c2ecf20Sopenharmony_ci * - Anton 5698c2ecf20Sopenharmony_ci */ 5708c2ecf20Sopenharmony_ci#if 0 5718c2ecf20Sopenharmony_ci if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0)) 5728c2ecf20Sopenharmony_ci return; 5738c2ecf20Sopenharmony_ci#endif 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci flush_dcache_page(pg); 5768c2ecf20Sopenharmony_ci} 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_civoid flush_icache_user_page(struct vm_area_struct *vma, struct page *page, 5798c2ecf20Sopenharmony_ci unsigned long addr, int len) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci unsigned long maddr; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci maddr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK); 5848c2ecf20Sopenharmony_ci flush_icache_range(maddr, maddr + len); 5858c2ecf20Sopenharmony_ci kunmap(page); 5868c2ecf20Sopenharmony_ci} 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci/* 5898c2ecf20Sopenharmony_ci * System memory should not be in /proc/iomem but various tools expect it 5908c2ecf20Sopenharmony_ci * (eg kdump). 5918c2ecf20Sopenharmony_ci */ 5928c2ecf20Sopenharmony_cistatic int __init add_system_ram_resources(void) 5938c2ecf20Sopenharmony_ci{ 5948c2ecf20Sopenharmony_ci phys_addr_t start, end; 5958c2ecf20Sopenharmony_ci u64 i; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci for_each_mem_range(i, &start, &end) { 5988c2ecf20Sopenharmony_ci struct resource *res; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci res = kzalloc(sizeof(struct resource), GFP_KERNEL); 6018c2ecf20Sopenharmony_ci WARN_ON(!res); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci if (res) { 6048c2ecf20Sopenharmony_ci res->name = "System RAM"; 6058c2ecf20Sopenharmony_ci res->start = start; 6068c2ecf20Sopenharmony_ci /* 6078c2ecf20Sopenharmony_ci * In memblock, end points to the first byte after 6088c2ecf20Sopenharmony_ci * the range while in resourses, end points to the 6098c2ecf20Sopenharmony_ci * last byte in the range. 6108c2ecf20Sopenharmony_ci */ 6118c2ecf20Sopenharmony_ci res->end = end - 1; 6128c2ecf20Sopenharmony_ci res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; 6138c2ecf20Sopenharmony_ci WARN_ON(request_resource(&iomem_resource, res) < 0); 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci return 0; 6188c2ecf20Sopenharmony_ci} 6198c2ecf20Sopenharmony_cisubsys_initcall(add_system_ram_resources); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci#ifdef CONFIG_STRICT_DEVMEM 6228c2ecf20Sopenharmony_ci/* 6238c2ecf20Sopenharmony_ci * devmem_is_allowed(): check to see if /dev/mem access to a certain address 6248c2ecf20Sopenharmony_ci * is valid. The argument is a physical page number. 6258c2ecf20Sopenharmony_ci * 6268c2ecf20Sopenharmony_ci * Access has to be given to non-kernel-ram areas as well, these contain the 6278c2ecf20Sopenharmony_ci * PCI mmio resources as well as potential bios/acpi data regions. 6288c2ecf20Sopenharmony_ci */ 6298c2ecf20Sopenharmony_ciint devmem_is_allowed(unsigned long pfn) 6308c2ecf20Sopenharmony_ci{ 6318c2ecf20Sopenharmony_ci if (page_is_rtas_user_buf(pfn)) 6328c2ecf20Sopenharmony_ci return 1; 6338c2ecf20Sopenharmony_ci if (iomem_is_exclusive(PFN_PHYS(pfn))) 6348c2ecf20Sopenharmony_ci return 0; 6358c2ecf20Sopenharmony_ci if (!page_is_ram(pfn)) 6368c2ecf20Sopenharmony_ci return 1; 6378c2ecf20Sopenharmony_ci return 0; 6388c2ecf20Sopenharmony_ci} 6398c2ecf20Sopenharmony_ci#endif /* CONFIG_STRICT_DEVMEM */ 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci/* 6428c2ecf20Sopenharmony_ci * This is defined in kernel/resource.c but only powerpc needs to export it, for 6438c2ecf20Sopenharmony_ci * the EHEA driver. Drop this when drivers/net/ethernet/ibm/ehea is removed. 6448c2ecf20Sopenharmony_ci */ 6458c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(walk_system_ram_range); 646