0001
0002
0003
0004
0005
0006 #include <linux/kernel.h>
0007 #include <linux/mm.h>
0008 #include <linux/memblock.h>
0009 #ifdef CONFIG_BLK_DEV_INITRD
0010 #include <linux/initrd.h>
0011 #endif
0012 #include <linux/of_fdt.h>
0013 #include <linux/swap.h>
0014 #include <linux/module.h>
0015 #include <linux/highmem.h>
0016 #include <asm/page.h>
0017 #include <asm/sections.h>
0018 #include <asm/arcregs.h>
0019
0020 pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE);
0021 char empty_zero_page[PAGE_SIZE] __aligned(PAGE_SIZE);
0022 EXPORT_SYMBOL(empty_zero_page);
0023
0024 static const unsigned long low_mem_start = CONFIG_LINUX_RAM_BASE;
0025 static unsigned long low_mem_sz;
0026
0027 #ifdef CONFIG_HIGHMEM
0028 static unsigned long min_high_pfn, max_high_pfn;
0029 static phys_addr_t high_mem_start;
0030 static phys_addr_t high_mem_sz;
0031 unsigned long arch_pfn_offset;
0032 EXPORT_SYMBOL(arch_pfn_offset);
0033 #endif
0034
0035 long __init arc_get_mem_sz(void)
0036 {
0037 return low_mem_sz;
0038 }
0039
0040
0041 static int __init setup_mem_sz(char *str)
0042 {
0043 low_mem_sz = memparse(str, NULL) & PAGE_MASK;
0044
0045
0046 pr_info("\"mem=%s\": mem sz set to %ldM\n", str, TO_MB(low_mem_sz));
0047
0048 return 0;
0049 }
0050 early_param("mem", setup_mem_sz);
0051
0052 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
0053 {
0054 int in_use = 0;
0055
0056 if (!low_mem_sz) {
0057 if (base != low_mem_start)
0058 panic("CONFIG_LINUX_RAM_BASE != DT memory { }");
0059
0060 low_mem_sz = size;
0061 in_use = 1;
0062 memblock_add_node(base, size, 0, MEMBLOCK_NONE);
0063 } else {
0064 #ifdef CONFIG_HIGHMEM
0065 high_mem_start = base;
0066 high_mem_sz = size;
0067 in_use = 1;
0068 memblock_add_node(base, size, 1, MEMBLOCK_NONE);
0069 memblock_reserve(base, size);
0070 #endif
0071 }
0072
0073 pr_info("Memory @ %llx [%lldM] %s\n",
0074 base, TO_MB(size), !in_use ? "Not used":"");
0075 }
0076
0077 bool arch_has_descending_max_zone_pfns(void)
0078 {
0079 return !IS_ENABLED(CONFIG_ARC_HAS_PAE40);
0080 }
0081
0082
0083
0084
0085
0086
0087
0088 void __init setup_arch_memory(void)
0089 {
0090 unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
0091
0092 setup_initial_init_mm(_text, _etext, _edata, _end);
0093
0094
0095 min_low_pfn = virt_to_pfn(CONFIG_LINUX_RAM_BASE);
0096
0097
0098 max_low_pfn = max_pfn = PFN_DOWN(low_mem_start + low_mem_sz);
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 memblock_reserve(CONFIG_LINUX_LINK_BASE,
0114 __pa(_end) - CONFIG_LINUX_LINK_BASE);
0115
0116 #ifdef CONFIG_BLK_DEV_INITRD
0117 if (phys_initrd_size) {
0118 memblock_reserve(phys_initrd_start, phys_initrd_size);
0119 initrd_start = (unsigned long)__va(phys_initrd_start);
0120 initrd_end = initrd_start + phys_initrd_size;
0121 }
0122 #endif
0123
0124 early_init_fdt_reserve_self();
0125 early_init_fdt_scan_reserved_mem();
0126
0127 memblock_dump_all();
0128
0129
0130 max_zone_pfn[ZONE_NORMAL] = max_low_pfn;
0131
0132 #ifdef CONFIG_HIGHMEM
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143 min_high_pfn = PFN_DOWN(high_mem_start);
0144 max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz);
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 max_zone_pfn[ZONE_HIGHMEM] = max_high_pfn;
0156
0157 high_memory = (void *)(min_high_pfn << PAGE_SHIFT);
0158
0159 arch_pfn_offset = min(min_low_pfn, min_high_pfn);
0160 kmap_init();
0161
0162 #else
0163
0164 max_mapnr = max_low_pfn - min_low_pfn;
0165
0166 #endif
0167
0168 free_area_init(max_zone_pfn);
0169 }
0170
0171 static void __init highmem_init(void)
0172 {
0173 #ifdef CONFIG_HIGHMEM
0174 unsigned long tmp;
0175
0176 memblock_phys_free(high_mem_start, high_mem_sz);
0177 for (tmp = min_high_pfn; tmp < max_high_pfn; tmp++)
0178 free_highmem_page(pfn_to_page(tmp));
0179 #endif
0180 }
0181
0182
0183
0184
0185
0186
0187
0188 void __init mem_init(void)
0189 {
0190 memblock_free_all();
0191 highmem_init();
0192
0193 BUILD_BUG_ON((PTRS_PER_PGD * sizeof(pgd_t)) > PAGE_SIZE);
0194 BUILD_BUG_ON((PTRS_PER_PUD * sizeof(pud_t)) > PAGE_SIZE);
0195 BUILD_BUG_ON((PTRS_PER_PMD * sizeof(pmd_t)) > PAGE_SIZE);
0196 BUILD_BUG_ON((PTRS_PER_PTE * sizeof(pte_t)) > PAGE_SIZE);
0197 }
0198
0199 #ifdef CONFIG_HIGHMEM
0200 int pfn_valid(unsigned long pfn)
0201 {
0202 return (pfn >= min_high_pfn && pfn <= max_high_pfn) ||
0203 (pfn >= min_low_pfn && pfn <= max_low_pfn);
0204 }
0205 EXPORT_SYMBOL(pfn_valid);
0206 #endif