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/module.h>
1662306a36Sopenharmony_ci#include <linux/sched.h>
1762306a36Sopenharmony_ci#include <linux/kernel.h>
1862306a36Sopenharmony_ci#include <linux/errno.h>
1962306a36Sopenharmony_ci#include <linux/string.h>
2062306a36Sopenharmony_ci#include <linux/types.h>
2162306a36Sopenharmony_ci#include <linux/mm.h>
2262306a36Sopenharmony_ci#include <linux/stddef.h>
2362306a36Sopenharmony_ci#include <linux/init.h>
2462306a36Sopenharmony_ci#include <linux/highmem.h>
2562306a36Sopenharmony_ci#include <linux/initrd.h>
2662306a36Sopenharmony_ci#include <linux/pagemap.h>
2762306a36Sopenharmony_ci#include <linux/memblock.h>
2862306a36Sopenharmony_ci#include <linux/gfp.h>
2962306a36Sopenharmony_ci#include <linux/slab.h>
3062306a36Sopenharmony_ci#include <linux/hugetlb.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include <asm/io.h>
3362306a36Sopenharmony_ci#include <asm/mmu.h>
3462306a36Sopenharmony_ci#include <asm/smp.h>
3562306a36Sopenharmony_ci#include <asm/machdep.h>
3662306a36Sopenharmony_ci#include <asm/btext.h>
3762306a36Sopenharmony_ci#include <asm/tlb.h>
3862306a36Sopenharmony_ci#include <asm/sections.h>
3962306a36Sopenharmony_ci#include <asm/hugetlb.h>
4062306a36Sopenharmony_ci#include <asm/kup.h>
4162306a36Sopenharmony_ci#include <asm/kasan.h>
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#include <mm/mmu_decl.h>
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL)
4662306a36Sopenharmony_ci/* The amount of lowmem must be within 0xF0000000 - KERNELBASE. */
4762306a36Sopenharmony_ci#if (CONFIG_LOWMEM_SIZE > (0xF0000000 - PAGE_OFFSET))
4862306a36Sopenharmony_ci#error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_KERNEL_START"
4962306a36Sopenharmony_ci#endif
5062306a36Sopenharmony_ci#endif
5162306a36Sopenharmony_ci#define MAX_LOW_MEM	CONFIG_LOWMEM_SIZE
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ciphys_addr_t total_memory;
5462306a36Sopenharmony_ciphys_addr_t total_lowmem;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#ifdef CONFIG_RELOCATABLE
5762306a36Sopenharmony_ci/* Used in __va()/__pa() */
5862306a36Sopenharmony_cilong long virt_phys_offset;
5962306a36Sopenharmony_ciEXPORT_SYMBOL(virt_phys_offset);
6062306a36Sopenharmony_ci#endif
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ciphys_addr_t lowmem_end_addr;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ciint boot_mapsize;
6562306a36Sopenharmony_ci#ifdef CONFIG_PPC_PMAC
6662306a36Sopenharmony_ciunsigned long agp_special_page;
6762306a36Sopenharmony_ciEXPORT_SYMBOL(agp_special_page);
6862306a36Sopenharmony_ci#endif
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_civoid MMU_init(void);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/* max amount of low RAM to map in */
7362306a36Sopenharmony_ciunsigned long __max_low_memory = MAX_LOW_MEM;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/*
7662306a36Sopenharmony_ci * MMU_init sets up the basic memory mappings for the kernel,
7762306a36Sopenharmony_ci * including both RAM and possibly some I/O regions,
7862306a36Sopenharmony_ci * and sets up the page tables and the MMU hardware ready to go.
7962306a36Sopenharmony_ci */
8062306a36Sopenharmony_civoid __init MMU_init(void)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	if (ppc_md.progress)
8362306a36Sopenharmony_ci		ppc_md.progress("MMU:enter", 0x111);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	total_lowmem = total_memory = memblock_end_of_DRAM() - memstart_addr;
8662306a36Sopenharmony_ci	lowmem_end_addr = memstart_addr + total_lowmem;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci#ifdef CONFIG_PPC_85xx
8962306a36Sopenharmony_ci	/* Freescale Book-E parts expect lowmem to be mapped by fixed TLB
9062306a36Sopenharmony_ci	 * entries, so we need to adjust lowmem to match the amount we can map
9162306a36Sopenharmony_ci	 * in the fixed entries */
9262306a36Sopenharmony_ci	adjust_total_lowmem();
9362306a36Sopenharmony_ci#endif /* CONFIG_PPC_85xx */
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	if (total_lowmem > __max_low_memory) {
9662306a36Sopenharmony_ci		total_lowmem = __max_low_memory;
9762306a36Sopenharmony_ci		lowmem_end_addr = memstart_addr + total_lowmem;
9862306a36Sopenharmony_ci#ifndef CONFIG_HIGHMEM
9962306a36Sopenharmony_ci		total_memory = total_lowmem;
10062306a36Sopenharmony_ci		memblock_enforce_memory_limit(total_lowmem);
10162306a36Sopenharmony_ci#endif /* CONFIG_HIGHMEM */
10262306a36Sopenharmony_ci	}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	/* Initialize the MMU hardware */
10562306a36Sopenharmony_ci	if (ppc_md.progress)
10662306a36Sopenharmony_ci		ppc_md.progress("MMU:hw init", 0x300);
10762306a36Sopenharmony_ci	MMU_init_hw();
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/* Map in all of RAM starting at KERNELBASE */
11062306a36Sopenharmony_ci	if (ppc_md.progress)
11162306a36Sopenharmony_ci		ppc_md.progress("MMU:mapin", 0x301);
11262306a36Sopenharmony_ci	mapin_ram();
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	/* Initialize early top-down ioremap allocator */
11562306a36Sopenharmony_ci	ioremap_bot = IOREMAP_TOP;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if (ppc_md.progress)
11862306a36Sopenharmony_ci		ppc_md.progress("MMU:exit", 0x211);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	/* From now on, btext is no longer BAT mapped if it was at all */
12162306a36Sopenharmony_ci#ifdef CONFIG_BOOTX_TEXT
12262306a36Sopenharmony_ci	btext_unmap();
12362306a36Sopenharmony_ci#endif
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	kasan_mmu_init();
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	setup_kup();
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	update_mmu_feature_fixups(MMU_FTR_KUAP);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	/* Shortly after that, the entire linear mapping will be available */
13262306a36Sopenharmony_ci	memblock_set_current_limit(lowmem_end_addr);
13362306a36Sopenharmony_ci}
134