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/module.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/types.h>
218c2ecf20Sopenharmony_ci#include <linux/mm.h>
228c2ecf20Sopenharmony_ci#include <linux/stddef.h>
238c2ecf20Sopenharmony_ci#include <linux/init.h>
248c2ecf20Sopenharmony_ci#include <linux/highmem.h>
258c2ecf20Sopenharmony_ci#include <linux/initrd.h>
268c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
278c2ecf20Sopenharmony_ci#include <linux/memblock.h>
288c2ecf20Sopenharmony_ci#include <linux/gfp.h>
298c2ecf20Sopenharmony_ci#include <linux/slab.h>
308c2ecf20Sopenharmony_ci#include <linux/hugetlb.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#include <asm/prom.h>
338c2ecf20Sopenharmony_ci#include <asm/io.h>
348c2ecf20Sopenharmony_ci#include <asm/mmu.h>
358c2ecf20Sopenharmony_ci#include <asm/smp.h>
368c2ecf20Sopenharmony_ci#include <asm/machdep.h>
378c2ecf20Sopenharmony_ci#include <asm/btext.h>
388c2ecf20Sopenharmony_ci#include <asm/tlb.h>
398c2ecf20Sopenharmony_ci#include <asm/sections.h>
408c2ecf20Sopenharmony_ci#include <asm/hugetlb.h>
418c2ecf20Sopenharmony_ci#include <asm/kup.h>
428c2ecf20Sopenharmony_ci#include <asm/kasan.h>
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#include <mm/mmu_decl.h>
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL)
478c2ecf20Sopenharmony_ci/* The amount of lowmem must be within 0xF0000000 - KERNELBASE. */
488c2ecf20Sopenharmony_ci#if (CONFIG_LOWMEM_SIZE > (0xF0000000 - PAGE_OFFSET))
498c2ecf20Sopenharmony_ci#error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_KERNEL_START"
508c2ecf20Sopenharmony_ci#endif
518c2ecf20Sopenharmony_ci#endif
528c2ecf20Sopenharmony_ci#define MAX_LOW_MEM	CONFIG_LOWMEM_SIZE
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ciphys_addr_t total_memory;
558c2ecf20Sopenharmony_ciphys_addr_t total_lowmem;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#ifdef CONFIG_RELOCATABLE
588c2ecf20Sopenharmony_ci/* Used in __va()/__pa() */
598c2ecf20Sopenharmony_cilong long virt_phys_offset;
608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(virt_phys_offset);
618c2ecf20Sopenharmony_ci#endif
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ciphys_addr_t lowmem_end_addr;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ciint boot_mapsize;
668c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_PMAC
678c2ecf20Sopenharmony_ciunsigned long agp_special_page;
688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(agp_special_page);
698c2ecf20Sopenharmony_ci#endif
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_civoid MMU_init(void);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/*
748c2ecf20Sopenharmony_ci * this tells the system to map all of ram with the segregs
758c2ecf20Sopenharmony_ci * (i.e. page tables) instead of the bats.
768c2ecf20Sopenharmony_ci * -- Cort
778c2ecf20Sopenharmony_ci */
788c2ecf20Sopenharmony_ciint __map_without_bats;
798c2ecf20Sopenharmony_ciint __map_without_ltlbs;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/* max amount of low RAM to map in */
828c2ecf20Sopenharmony_ciunsigned long __max_low_memory = MAX_LOW_MEM;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/*
858c2ecf20Sopenharmony_ci * Check for command-line options that affect what MMU_init will do.
868c2ecf20Sopenharmony_ci */
878c2ecf20Sopenharmony_cistatic void __init MMU_setup(void)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	/* Check for nobats option (used in mapin_ram). */
908c2ecf20Sopenharmony_ci	if (strstr(boot_command_line, "nobats")) {
918c2ecf20Sopenharmony_ci		__map_without_bats = 1;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	if (strstr(boot_command_line, "noltlbs")) {
958c2ecf20Sopenharmony_ci		__map_without_ltlbs = 1;
968c2ecf20Sopenharmony_ci	}
978c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_PPC_8xx))
988c2ecf20Sopenharmony_ci		return;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	if (debug_pagealloc_enabled())
1018c2ecf20Sopenharmony_ci		__map_without_ltlbs = 1;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	if (strict_kernel_rwx_enabled())
1048c2ecf20Sopenharmony_ci		__map_without_ltlbs = 1;
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/*
1088c2ecf20Sopenharmony_ci * MMU_init sets up the basic memory mappings for the kernel,
1098c2ecf20Sopenharmony_ci * including both RAM and possibly some I/O regions,
1108c2ecf20Sopenharmony_ci * and sets up the page tables and the MMU hardware ready to go.
1118c2ecf20Sopenharmony_ci */
1128c2ecf20Sopenharmony_civoid __init MMU_init(void)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	if (ppc_md.progress)
1158c2ecf20Sopenharmony_ci		ppc_md.progress("MMU:enter", 0x111);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	/* parse args from command line */
1188c2ecf20Sopenharmony_ci	MMU_setup();
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	/*
1218c2ecf20Sopenharmony_ci	 * Reserve gigantic pages for hugetlb.  This MUST occur before
1228c2ecf20Sopenharmony_ci	 * lowmem_end_addr is initialized below.
1238c2ecf20Sopenharmony_ci	 */
1248c2ecf20Sopenharmony_ci	if (memblock.memory.cnt > 1) {
1258c2ecf20Sopenharmony_ci#ifndef CONFIG_WII
1268c2ecf20Sopenharmony_ci		memblock_enforce_memory_limit(memblock.memory.regions[0].size);
1278c2ecf20Sopenharmony_ci		pr_warn("Only using first contiguous memory region\n");
1288c2ecf20Sopenharmony_ci#else
1298c2ecf20Sopenharmony_ci		wii_memory_fixups();
1308c2ecf20Sopenharmony_ci#endif
1318c2ecf20Sopenharmony_ci	}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	total_lowmem = total_memory = memblock_end_of_DRAM() - memstart_addr;
1348c2ecf20Sopenharmony_ci	lowmem_end_addr = memstart_addr + total_lowmem;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci#ifdef CONFIG_FSL_BOOKE
1378c2ecf20Sopenharmony_ci	/* Freescale Book-E parts expect lowmem to be mapped by fixed TLB
1388c2ecf20Sopenharmony_ci	 * entries, so we need to adjust lowmem to match the amount we can map
1398c2ecf20Sopenharmony_ci	 * in the fixed entries */
1408c2ecf20Sopenharmony_ci	adjust_total_lowmem();
1418c2ecf20Sopenharmony_ci#endif /* CONFIG_FSL_BOOKE */
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	if (total_lowmem > __max_low_memory) {
1448c2ecf20Sopenharmony_ci		total_lowmem = __max_low_memory;
1458c2ecf20Sopenharmony_ci		lowmem_end_addr = memstart_addr + total_lowmem;
1468c2ecf20Sopenharmony_ci#ifndef CONFIG_HIGHMEM
1478c2ecf20Sopenharmony_ci		total_memory = total_lowmem;
1488c2ecf20Sopenharmony_ci		memblock_enforce_memory_limit(total_lowmem);
1498c2ecf20Sopenharmony_ci#endif /* CONFIG_HIGHMEM */
1508c2ecf20Sopenharmony_ci	}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	/* Initialize the MMU hardware */
1538c2ecf20Sopenharmony_ci	if (ppc_md.progress)
1548c2ecf20Sopenharmony_ci		ppc_md.progress("MMU:hw init", 0x300);
1558c2ecf20Sopenharmony_ci	MMU_init_hw();
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* Map in all of RAM starting at KERNELBASE */
1588c2ecf20Sopenharmony_ci	if (ppc_md.progress)
1598c2ecf20Sopenharmony_ci		ppc_md.progress("MMU:mapin", 0x301);
1608c2ecf20Sopenharmony_ci	mapin_ram();
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	/* Initialize early top-down ioremap allocator */
1638c2ecf20Sopenharmony_ci	ioremap_bot = IOREMAP_TOP;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	if (ppc_md.progress)
1668c2ecf20Sopenharmony_ci		ppc_md.progress("MMU:exit", 0x211);
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	/* From now on, btext is no longer BAT mapped if it was at all */
1698c2ecf20Sopenharmony_ci#ifdef CONFIG_BOOTX_TEXT
1708c2ecf20Sopenharmony_ci	btext_unmap();
1718c2ecf20Sopenharmony_ci#endif
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	kasan_mmu_init();
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	setup_kup();
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	/* Shortly after that, the entire linear mapping will be available */
1788c2ecf20Sopenharmony_ci	memblock_set_current_limit(lowmem_end_addr);
1798c2ecf20Sopenharmony_ci}
180