162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * PowerPC version 462306a36Sopenharmony_ci * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) 762306a36Sopenharmony_ci * and Cort Dougan (PReP) (cort@cs.nmt.edu) 862306a36Sopenharmony_ci * Copyright (C) 1996 Paul Mackerras 962306a36Sopenharmony_ci * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Derived from "arch/i386/mm/init.c" 1262306a36Sopenharmony_ci * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/memblock.h> 1662306a36Sopenharmony_ci#include <linux/highmem.h> 1762306a36Sopenharmony_ci#include <linux/suspend.h> 1862306a36Sopenharmony_ci#include <linux/dma-direct.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <asm/swiotlb.h> 2162306a36Sopenharmony_ci#include <asm/machdep.h> 2262306a36Sopenharmony_ci#include <asm/rtas.h> 2362306a36Sopenharmony_ci#include <asm/kasan.h> 2462306a36Sopenharmony_ci#include <asm/svm.h> 2562306a36Sopenharmony_ci#include <asm/mmzone.h> 2662306a36Sopenharmony_ci#include <asm/ftrace.h> 2762306a36Sopenharmony_ci#include <asm/code-patching.h> 2862306a36Sopenharmony_ci#include <asm/setup.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include <mm/mmu_decl.h> 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciunsigned long long memory_limit; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciunsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss; 3562306a36Sopenharmony_ciEXPORT_SYMBOL(empty_zero_page); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cipgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, 3862306a36Sopenharmony_ci unsigned long size, pgprot_t vma_prot) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci if (ppc_md.phys_mem_access_prot) 4162306a36Sopenharmony_ci return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci if (!page_is_ram(pfn)) 4462306a36Sopenharmony_ci vma_prot = pgprot_noncached(vma_prot); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return vma_prot; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ciEXPORT_SYMBOL(phys_mem_access_prot); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#ifdef CONFIG_MEMORY_HOTPLUG 5162306a36Sopenharmony_cistatic DEFINE_MUTEX(linear_mapping_mutex); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#ifdef CONFIG_NUMA 5462306a36Sopenharmony_ciint memory_add_physaddr_to_nid(u64 start) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci return hot_add_scn_to_nid(start); 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); 5962306a36Sopenharmony_ci#endif 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ciint __weak create_section_mapping(unsigned long start, unsigned long end, 6262306a36Sopenharmony_ci int nid, pgprot_t prot) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci return -ENODEV; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciint __weak remove_section_mapping(unsigned long start, unsigned long end) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci return -ENODEV; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ciint __ref arch_create_linear_mapping(int nid, u64 start, u64 size, 7362306a36Sopenharmony_ci struct mhp_params *params) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci int rc; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci start = (unsigned long)__va(start); 7862306a36Sopenharmony_ci mutex_lock(&linear_mapping_mutex); 7962306a36Sopenharmony_ci rc = create_section_mapping(start, start + size, nid, 8062306a36Sopenharmony_ci params->pgprot); 8162306a36Sopenharmony_ci mutex_unlock(&linear_mapping_mutex); 8262306a36Sopenharmony_ci if (rc) { 8362306a36Sopenharmony_ci pr_warn("Unable to create linear mapping for 0x%llx..0x%llx: %d\n", 8462306a36Sopenharmony_ci start, start + size, rc); 8562306a36Sopenharmony_ci return -EFAULT; 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci return 0; 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_civoid __ref arch_remove_linear_mapping(u64 start, u64 size) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci int ret; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /* Remove htab bolted mappings for this section of memory */ 9562306a36Sopenharmony_ci start = (unsigned long)__va(start); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci mutex_lock(&linear_mapping_mutex); 9862306a36Sopenharmony_ci ret = remove_section_mapping(start, start + size); 9962306a36Sopenharmony_ci mutex_unlock(&linear_mapping_mutex); 10062306a36Sopenharmony_ci if (ret) 10162306a36Sopenharmony_ci pr_warn("Unable to remove linear mapping for 0x%llx..0x%llx: %d\n", 10262306a36Sopenharmony_ci start, start + size, ret); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Ensure all vmalloc mappings are flushed in case they also 10562306a36Sopenharmony_ci * hit that section of memory 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_ci vm_unmap_aliases(); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* 11162306a36Sopenharmony_ci * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need 11262306a36Sopenharmony_ci * updating. 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_cistatic void update_end_of_memory_vars(u64 start, u64 size) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci unsigned long end_pfn = PFN_UP(start + size); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if (end_pfn > max_pfn) { 11962306a36Sopenharmony_ci max_pfn = end_pfn; 12062306a36Sopenharmony_ci max_low_pfn = end_pfn; 12162306a36Sopenharmony_ci high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciint __ref add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages, 12662306a36Sopenharmony_ci struct mhp_params *params) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci int ret; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci ret = __add_pages(nid, start_pfn, nr_pages, params); 13162306a36Sopenharmony_ci if (ret) 13262306a36Sopenharmony_ci return ret; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci /* update max_pfn, max_low_pfn and high_memory */ 13562306a36Sopenharmony_ci update_end_of_memory_vars(start_pfn << PAGE_SHIFT, 13662306a36Sopenharmony_ci nr_pages << PAGE_SHIFT); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return ret; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciint __ref arch_add_memory(int nid, u64 start, u64 size, 14262306a36Sopenharmony_ci struct mhp_params *params) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci unsigned long start_pfn = start >> PAGE_SHIFT; 14562306a36Sopenharmony_ci unsigned long nr_pages = size >> PAGE_SHIFT; 14662306a36Sopenharmony_ci int rc; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci rc = arch_create_linear_mapping(nid, start, size, params); 14962306a36Sopenharmony_ci if (rc) 15062306a36Sopenharmony_ci return rc; 15162306a36Sopenharmony_ci rc = add_pages(nid, start_pfn, nr_pages, params); 15262306a36Sopenharmony_ci if (rc) 15362306a36Sopenharmony_ci arch_remove_linear_mapping(start, size); 15462306a36Sopenharmony_ci return rc; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_civoid __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci unsigned long start_pfn = start >> PAGE_SHIFT; 16062306a36Sopenharmony_ci unsigned long nr_pages = size >> PAGE_SHIFT; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci __remove_pages(start_pfn, nr_pages, altmap); 16362306a36Sopenharmony_ci arch_remove_linear_mapping(start, size); 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci#endif 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci#ifndef CONFIG_NUMA 16862306a36Sopenharmony_civoid __init mem_topology_setup(void) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; 17162306a36Sopenharmony_ci min_low_pfn = MEMORY_START >> PAGE_SHIFT; 17262306a36Sopenharmony_ci#ifdef CONFIG_HIGHMEM 17362306a36Sopenharmony_ci max_low_pfn = lowmem_end_addr >> PAGE_SHIFT; 17462306a36Sopenharmony_ci#endif 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci /* Place all memblock_regions in the same node and merge contiguous 17762306a36Sopenharmony_ci * memblock_regions 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_ci memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_civoid __init initmem_init(void) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci sparse_init(); 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/* mark pages that don't exist as nosave */ 18862306a36Sopenharmony_cistatic int __init mark_nonram_nosave(void) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci unsigned long spfn, epfn, prev = 0; 19162306a36Sopenharmony_ci int i; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci for_each_mem_pfn_range(i, MAX_NUMNODES, &spfn, &epfn, NULL) { 19462306a36Sopenharmony_ci if (prev && prev < spfn) 19562306a36Sopenharmony_ci register_nosave_region(prev, spfn); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci prev = epfn; 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci return 0; 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci#else /* CONFIG_NUMA */ 20362306a36Sopenharmony_cistatic int __init mark_nonram_nosave(void) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci#endif 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/* 21062306a36Sopenharmony_ci * Zones usage: 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * We setup ZONE_DMA to be 31-bits on all platforms and ZONE_NORMAL to be 21362306a36Sopenharmony_ci * everything else. GFP_DMA32 page allocations automatically fall back to 21462306a36Sopenharmony_ci * ZONE_DMA. 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * By using 31-bit unconditionally, we can exploit zone_dma_bits to inform the 21762306a36Sopenharmony_ci * generic DMA mapping code. 32-bit only devices (if not handled by an IOMMU 21862306a36Sopenharmony_ci * anyway) will take a first dip into ZONE_NORMAL and get otherwise served by 21962306a36Sopenharmony_ci * ZONE_DMA. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_cistatic unsigned long max_zone_pfns[MAX_NR_ZONES]; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci/* 22462306a36Sopenharmony_ci * paging_init() sets up the page tables - in fact we've already done this. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_civoid __init paging_init(void) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci unsigned long long total_ram = memblock_phys_mem_size(); 22962306a36Sopenharmony_ci phys_addr_t top_of_ram = memblock_end_of_DRAM(); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci#ifdef CONFIG_HIGHMEM 23262306a36Sopenharmony_ci unsigned long v = __fix_to_virt(FIX_KMAP_END); 23362306a36Sopenharmony_ci unsigned long end = __fix_to_virt(FIX_KMAP_BEGIN); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci for (; v < end; v += PAGE_SIZE) 23662306a36Sopenharmony_ci map_kernel_page(v, 0, __pgprot(0)); /* XXX gross */ 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci map_kernel_page(PKMAP_BASE, 0, __pgprot(0)); /* XXX gross */ 23962306a36Sopenharmony_ci pkmap_page_table = virt_to_kpte(PKMAP_BASE); 24062306a36Sopenharmony_ci#endif /* CONFIG_HIGHMEM */ 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%llx\n", 24362306a36Sopenharmony_ci (unsigned long long)top_of_ram, total_ram); 24462306a36Sopenharmony_ci printk(KERN_DEBUG "Memory hole size: %ldMB\n", 24562306a36Sopenharmony_ci (long int)((top_of_ram - total_ram) >> 20)); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* 24862306a36Sopenharmony_ci * Allow 30-bit DMA for very limited Broadcom wifi chips on many 24962306a36Sopenharmony_ci * powerbooks. 25062306a36Sopenharmony_ci */ 25162306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_PPC32)) 25262306a36Sopenharmony_ci zone_dma_bits = 30; 25362306a36Sopenharmony_ci else 25462306a36Sopenharmony_ci zone_dma_bits = 31; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci#ifdef CONFIG_ZONE_DMA 25762306a36Sopenharmony_ci max_zone_pfns[ZONE_DMA] = min(max_low_pfn, 25862306a36Sopenharmony_ci 1UL << (zone_dma_bits - PAGE_SHIFT)); 25962306a36Sopenharmony_ci#endif 26062306a36Sopenharmony_ci max_zone_pfns[ZONE_NORMAL] = max_low_pfn; 26162306a36Sopenharmony_ci#ifdef CONFIG_HIGHMEM 26262306a36Sopenharmony_ci max_zone_pfns[ZONE_HIGHMEM] = max_pfn; 26362306a36Sopenharmony_ci#endif 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci free_area_init(max_zone_pfns); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci mark_nonram_nosave(); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_civoid __init mem_init(void) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci /* 27362306a36Sopenharmony_ci * book3s is limited to 16 page sizes due to encoding this in 27462306a36Sopenharmony_ci * a 4-bit field for slices. 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_ci BUILD_BUG_ON(MMU_PAGE_COUNT > 16); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci#ifdef CONFIG_SWIOTLB 27962306a36Sopenharmony_ci /* 28062306a36Sopenharmony_ci * Some platforms (e.g. 85xx) limit DMA-able memory way below 28162306a36Sopenharmony_ci * 4G. We force memblock to bottom-up mode to ensure that the 28262306a36Sopenharmony_ci * memory allocated in swiotlb_init() is DMA-able. 28362306a36Sopenharmony_ci * As it's the last memblock allocation, no need to reset it 28462306a36Sopenharmony_ci * back to to-down. 28562306a36Sopenharmony_ci */ 28662306a36Sopenharmony_ci memblock_set_bottom_up(true); 28762306a36Sopenharmony_ci swiotlb_init(ppc_swiotlb_enable, ppc_swiotlb_flags); 28862306a36Sopenharmony_ci#endif 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci kasan_late_init(); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci memblock_free_all(); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci#ifdef CONFIG_HIGHMEM 29762306a36Sopenharmony_ci { 29862306a36Sopenharmony_ci unsigned long pfn, highmem_mapnr; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci highmem_mapnr = lowmem_end_addr >> PAGE_SHIFT; 30162306a36Sopenharmony_ci for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) { 30262306a36Sopenharmony_ci phys_addr_t paddr = (phys_addr_t)pfn << PAGE_SHIFT; 30362306a36Sopenharmony_ci struct page *page = pfn_to_page(pfn); 30462306a36Sopenharmony_ci if (memblock_is_memory(paddr) && !memblock_is_reserved(paddr)) 30562306a36Sopenharmony_ci free_highmem_page(page); 30662306a36Sopenharmony_ci } 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci#endif /* CONFIG_HIGHMEM */ 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci#if defined(CONFIG_PPC_E500) && !defined(CONFIG_SMP) 31162306a36Sopenharmony_ci /* 31262306a36Sopenharmony_ci * If smp is enabled, next_tlbcam_idx is initialized in the cpu up 31362306a36Sopenharmony_ci * functions.... do it here for the non-smp case. 31462306a36Sopenharmony_ci */ 31562306a36Sopenharmony_ci per_cpu(next_tlbcam_idx, smp_processor_id()) = 31662306a36Sopenharmony_ci (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) - 1; 31762306a36Sopenharmony_ci#endif 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci#ifdef CONFIG_PPC32 32062306a36Sopenharmony_ci pr_info("Kernel virtual memory layout:\n"); 32162306a36Sopenharmony_ci#ifdef CONFIG_KASAN 32262306a36Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : kasan shadow mem\n", 32362306a36Sopenharmony_ci KASAN_SHADOW_START, KASAN_SHADOW_END); 32462306a36Sopenharmony_ci#endif 32562306a36Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : fixmap\n", FIXADDR_START, FIXADDR_TOP); 32662306a36Sopenharmony_ci#ifdef CONFIG_HIGHMEM 32762306a36Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : highmem PTEs\n", 32862306a36Sopenharmony_ci PKMAP_BASE, PKMAP_ADDR(LAST_PKMAP)); 32962306a36Sopenharmony_ci#endif /* CONFIG_HIGHMEM */ 33062306a36Sopenharmony_ci if (ioremap_bot != IOREMAP_TOP) 33162306a36Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : early ioremap\n", 33262306a36Sopenharmony_ci ioremap_bot, IOREMAP_TOP); 33362306a36Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : vmalloc & ioremap\n", 33462306a36Sopenharmony_ci VMALLOC_START, VMALLOC_END); 33562306a36Sopenharmony_ci#ifdef MODULES_VADDR 33662306a36Sopenharmony_ci pr_info(" * 0x%08lx..0x%08lx : modules\n", 33762306a36Sopenharmony_ci MODULES_VADDR, MODULES_END); 33862306a36Sopenharmony_ci#endif 33962306a36Sopenharmony_ci#endif /* CONFIG_PPC32 */ 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_civoid free_initmem(void) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci ppc_md.progress = ppc_printk_progress; 34562306a36Sopenharmony_ci mark_initmem_nx(); 34662306a36Sopenharmony_ci free_initmem_default(POISON_FREE_INITMEM); 34762306a36Sopenharmony_ci ftrace_free_init_tramp(); 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci/* 35162306a36Sopenharmony_ci * System memory should not be in /proc/iomem but various tools expect it 35262306a36Sopenharmony_ci * (eg kdump). 35362306a36Sopenharmony_ci */ 35462306a36Sopenharmony_cistatic int __init add_system_ram_resources(void) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci phys_addr_t start, end; 35762306a36Sopenharmony_ci u64 i; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci for_each_mem_range(i, &start, &end) { 36062306a36Sopenharmony_ci struct resource *res; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci res = kzalloc(sizeof(struct resource), GFP_KERNEL); 36362306a36Sopenharmony_ci WARN_ON(!res); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci if (res) { 36662306a36Sopenharmony_ci res->name = "System RAM"; 36762306a36Sopenharmony_ci res->start = start; 36862306a36Sopenharmony_ci /* 36962306a36Sopenharmony_ci * In memblock, end points to the first byte after 37062306a36Sopenharmony_ci * the range while in resourses, end points to the 37162306a36Sopenharmony_ci * last byte in the range. 37262306a36Sopenharmony_ci */ 37362306a36Sopenharmony_ci res->end = end - 1; 37462306a36Sopenharmony_ci res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; 37562306a36Sopenharmony_ci WARN_ON(request_resource(&iomem_resource, res) < 0); 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci return 0; 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_cisubsys_initcall(add_system_ram_resources); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci#ifdef CONFIG_STRICT_DEVMEM 38462306a36Sopenharmony_ci/* 38562306a36Sopenharmony_ci * devmem_is_allowed(): check to see if /dev/mem access to a certain address 38662306a36Sopenharmony_ci * is valid. The argument is a physical page number. 38762306a36Sopenharmony_ci * 38862306a36Sopenharmony_ci * Access has to be given to non-kernel-ram areas as well, these contain the 38962306a36Sopenharmony_ci * PCI mmio resources as well as potential bios/acpi data regions. 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_ciint devmem_is_allowed(unsigned long pfn) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci if (page_is_rtas_user_buf(pfn)) 39462306a36Sopenharmony_ci return 1; 39562306a36Sopenharmony_ci if (iomem_is_exclusive(PFN_PHYS(pfn))) 39662306a36Sopenharmony_ci return 0; 39762306a36Sopenharmony_ci if (!page_is_ram(pfn)) 39862306a36Sopenharmony_ci return 1; 39962306a36Sopenharmony_ci return 0; 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci#endif /* CONFIG_STRICT_DEVMEM */ 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci/* 40462306a36Sopenharmony_ci * This is defined in kernel/resource.c but only powerpc needs to export it, for 40562306a36Sopenharmony_ci * the EHEA driver. Drop this when drivers/net/ethernet/ibm/ehea is removed. 40662306a36Sopenharmony_ci */ 40762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(walk_system_ram_range); 408