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