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