blob: 30af42d78e35a4647affa010c4aa30e7adf14aea [file] [log] [blame]
Palmer Dabbelt76d2a042017-07-10 18:00:26 -07001/*
2 * Copyright (C) 2012 Regents of the University of California
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/init.h>
15#include <linux/mm.h>
Palmer Dabbelt76d2a042017-07-10 18:00:26 -070016#include <linux/memblock.h>
Mike Rapoport57c8a662018-10-30 15:09:49 -070017#include <linux/initrd.h>
Palmer Dabbelt76d2a042017-07-10 18:00:26 -070018#include <linux/swap.h>
Christoph Hellwig5ec9c4f2018-01-16 09:37:50 +010019#include <linux/sizes.h>
Anup Patel0651c262019-02-21 11:25:49 +053020#include <linux/of_fdt.h>
Palmer Dabbelt76d2a042017-07-10 18:00:26 -070021
22#include <asm/tlbflush.h>
23#include <asm/sections.h>
24#include <asm/pgtable.h>
25#include <asm/io.h>
26
27static void __init zone_sizes_init(void)
28{
Christoph Hellwig5ec9c4f2018-01-16 09:37:50 +010029 unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, };
Palmer Dabbelt76d2a042017-07-10 18:00:26 -070030
Zong Lid5fad482018-06-25 16:49:37 +080031#ifdef CONFIG_ZONE_DMA32
Guo Ren28198c42019-01-12 16:16:27 +080032 max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G,
33 (unsigned long) PFN_PHYS(max_low_pfn)));
Zong Lid5fad482018-06-25 16:49:37 +080034#endif
Christoph Hellwig5ec9c4f2018-01-16 09:37:50 +010035 max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
36
37 free_area_init_nodes(max_zone_pfns);
Palmer Dabbelt76d2a042017-07-10 18:00:26 -070038}
39
40void setup_zero_page(void)
41{
42 memset((void *)empty_zero_page, 0, PAGE_SIZE);
43}
44
45void __init paging_init(void)
46{
Palmer Dabbelt76d2a042017-07-10 18:00:26 -070047 setup_zero_page();
48 local_flush_tlb_all();
49 zone_sizes_init();
50}
51
52void __init mem_init(void)
53{
54#ifdef CONFIG_FLATMEM
55 BUG_ON(!mem_map);
56#endif /* CONFIG_FLATMEM */
57
58 high_memory = (void *)(__va(PFN_PHYS(max_low_pfn)));
Mike Rapoportc6ffc5c2018-10-30 15:09:30 -070059 memblock_free_all();
Palmer Dabbelt76d2a042017-07-10 18:00:26 -070060
61 mem_init_print_info(NULL);
62}
63
64void free_initmem(void)
65{
66 free_initmem_default(0);
67}
68
69#ifdef CONFIG_BLK_DEV_INITRD
Anup Patel0651c262019-02-21 11:25:49 +053070static void __init setup_initrd(void)
71{
72 unsigned long size;
73
74 if (initrd_start >= initrd_end) {
75 pr_info("initrd not found or empty");
76 goto disable;
77 }
78 if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
79 pr_err("initrd extends beyond end of memory");
80 goto disable;
81 }
82
83 size = initrd_end - initrd_start;
84 memblock_reserve(__pa(initrd_start), size);
85 initrd_below_start_ok = 1;
86
87 pr_info("Initial ramdisk at: 0x%p (%lu bytes)\n",
88 (void *)(initrd_start), size);
89 return;
90disable:
91 pr_cont(" - disabling initrd\n");
92 initrd_start = 0;
93 initrd_end = 0;
94}
95
Palmer Dabbelt76d2a042017-07-10 18:00:26 -070096void free_initrd_mem(unsigned long start, unsigned long end)
97{
98}
99#endif /* CONFIG_BLK_DEV_INITRD */
Anup Patel0651c262019-02-21 11:25:49 +0530100
101void __init setup_bootmem(void)
102{
103 struct memblock_region *reg;
104 phys_addr_t mem_size = 0;
105
106 /* Find the memory region containing the kernel */
107 for_each_memblock(memory, reg) {
108 phys_addr_t vmlinux_end = __pa(_end);
109 phys_addr_t end = reg->base + reg->size;
110
111 if (reg->base <= vmlinux_end && vmlinux_end <= end) {
112 /*
113 * Reserve from the start of the region to the end of
114 * the kernel
115 */
116 memblock_reserve(reg->base, vmlinux_end - reg->base);
117 mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET);
118 }
119 }
120 BUG_ON(mem_size == 0);
121
122 set_max_mapnr(PFN_DOWN(mem_size));
123 max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
124
125#ifdef CONFIG_BLK_DEV_INITRD
126 setup_initrd();
127#endif /* CONFIG_BLK_DEV_INITRD */
128
129 early_init_fdt_reserve_self();
130 early_init_fdt_scan_reserved_mem();
131 memblock_allow_resize();
132 memblock_dump_all();
133
134 for_each_memblock(memory, reg) {
135 unsigned long start_pfn = memblock_region_memory_base_pfn(reg);
136 unsigned long end_pfn = memblock_region_memory_end_pfn(reg);
137
138 memblock_set_node(PFN_PHYS(start_pfn),
139 PFN_PHYS(end_pfn - start_pfn),
140 &memblock.memory, 0);
141 }
142}