Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: initial LMB trial

Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

+83 -155
+1
arch/arm/Kconfig
··· 10 10 default y 11 11 select HAVE_AOUT 12 12 select HAVE_IDE 13 + select HAVE_MEMBLOCK 13 14 select RTC_LIB 14 15 select SYS_SUPPORTS_APM_EMULATION 15 16 select GENERIC_ATOMIC64 if (!CPU_32v6K)
+15
arch/arm/include/asm/memblock.h
··· 1 + #ifndef _ASM_ARM_MEMBLOCK_H 2 + #define _ASM_ARM_MEMBLOCK_H 3 + 4 + #ifdef CONFIG_MMU 5 + extern phys_addr_t lowmem_end_addr; 6 + #define MEMBLOCK_REAL_LIMIT lowmem_end_addr 7 + #else 8 + #define MEMBLOCK_REAL_LIMIT 0 9 + #endif 10 + 11 + struct meminfo; 12 + 13 + extern void arm_memblock_init(struct meminfo *); 14 + 15 + #endif
+3
arch/arm/kernel/setup.c
··· 25 25 #include <linux/smp.h> 26 26 #include <linux/fs.h> 27 27 #include <linux/proc_fs.h> 28 + #include <linux/memblock.h> 28 29 29 30 #include <asm/unified.h> 30 31 #include <asm/cpu.h> ··· 715 714 *cmdline_p = cmd_line; 716 715 717 716 parse_early_param(); 717 + 718 + arm_memblock_init(&meminfo); 718 719 719 720 paging_init(mdesc); 720 721 request_standard_resources(&meminfo, mdesc);
+45 -119
arch/arm/mm/init.c
··· 17 17 #include <linux/initrd.h> 18 18 #include <linux/highmem.h> 19 19 #include <linux/gfp.h> 20 + #include <linux/memblock.h> 20 21 21 22 #include <asm/mach-types.h> 22 23 #include <asm/sections.h> ··· 147 146 } 148 147 } 149 148 150 - /* 151 - * FIXME: We really want to avoid allocating the bootmap bitmap 152 - * over the top of the initrd. Hopefully, this is located towards 153 - * the start of a bank, so if we allocate the bootmap bitmap at 154 - * the end, we won't clash. 155 - */ 156 - static unsigned int __init 157 - find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages) 158 - { 159 - unsigned int start_pfn, i, bootmap_pfn; 160 - 161 - start_pfn = PAGE_ALIGN(__pa(_end)) >> PAGE_SHIFT; 162 - bootmap_pfn = 0; 163 - 164 - for_each_bank(i, mi) { 165 - struct membank *bank = &mi->bank[i]; 166 - unsigned int start, end; 167 - 168 - start = bank_pfn_start(bank); 169 - end = bank_pfn_end(bank); 170 - 171 - if (end < start_pfn) 172 - continue; 173 - 174 - if (start < start_pfn) 175 - start = start_pfn; 176 - 177 - if (end <= start) 178 - continue; 179 - 180 - if (end - start >= bootmap_pages) { 181 - bootmap_pfn = start; 182 - break; 183 - } 184 - } 185 - 186 - if (bootmap_pfn == 0) 187 - BUG(); 188 - 189 - return bootmap_pfn; 190 - } 191 - 192 - static int __init check_initrd(struct meminfo *mi) 193 - { 194 - int initrd = -2; 195 - #ifdef CONFIG_BLK_DEV_INITRD 196 - unsigned long end = phys_initrd_start + phys_initrd_size; 197 - 198 - /* 199 - * Make sure that the initrd is within a valid area of 200 - * memory. 201 - */ 202 - if (phys_initrd_size) { 203 - unsigned int i; 204 - 205 - initrd = -1; 206 - 207 - for (i = 0; i < mi->nr_banks; i++) { 208 - struct membank *bank = &mi->bank[i]; 209 - if (bank_phys_start(bank) <= phys_initrd_start && 210 - end <= bank_phys_end(bank)) 211 - initrd = 0; 212 - } 213 - } 214 - 215 - if (initrd == -1) { 216 - printk(KERN_ERR "INITRD: 0x%08lx+0x%08lx extends beyond " 217 - "physical memory - disabling initrd\n", 218 - phys_initrd_start, phys_initrd_size); 219 - phys_initrd_start = phys_initrd_size = 0; 220 - } 221 - #endif 222 - 223 - return initrd; 224 - } 225 - 226 149 static void __init arm_bootmem_init(struct meminfo *mi, 227 150 unsigned long start_pfn, unsigned long end_pfn) 228 151 { 229 - unsigned long boot_pfn; 230 152 unsigned int boot_pages; 153 + phys_addr_t bitmap; 231 154 pg_data_t *pgdat; 232 155 int i; 233 156 234 157 /* 235 - * Allocate the bootmem bitmap page. 158 + * Allocate the bootmem bitmap page. This must be in a region 159 + * of memory which has already been mapped. 236 160 */ 237 161 boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); 238 - boot_pfn = find_bootmap_pfn(mi, boot_pages); 162 + bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES, 163 + __pfn_to_phys(end_pfn)); 239 164 240 165 /* 241 166 * Initialise the bootmem allocator, handing the ··· 169 242 */ 170 243 node_set_online(0); 171 244 pgdat = NODE_DATA(0); 172 - init_bootmem_node(pgdat, boot_pfn, start_pfn, end_pfn); 245 + init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn); 173 246 174 247 for_each_bank(i, mi) { 175 248 struct membank *bank = &mi->bank[i]; ··· 178 251 } 179 252 180 253 /* 181 - * Reserve the bootmem bitmap. 254 + * Reserve the memblock reserved regions in bootmem. 182 255 */ 183 - reserve_bootmem(boot_pfn << PAGE_SHIFT, 184 - boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); 185 - } 186 - 187 - static void __init bootmem_reserve_initrd(void) 188 - { 189 - #ifdef CONFIG_BLK_DEV_INITRD 190 - int res; 191 - 192 - res = reserve_bootmem(phys_initrd_start, 193 - phys_initrd_size, BOOTMEM_EXCLUSIVE); 194 - 195 - if (res == 0) { 196 - initrd_start = __phys_to_virt(phys_initrd_start); 197 - initrd_end = initrd_start + phys_initrd_size; 198 - } else { 199 - printk(KERN_ERR 200 - "INITRD: 0x%08lx+0x%08lx overlaps in-use " 201 - "memory region - disabling initrd\n", 202 - phys_initrd_start, phys_initrd_size); 256 + for (i = 0; i < memblock.reserved.cnt; i++) { 257 + phys_addr_t start = memblock_start_pfn(&memblock.reserved, i); 258 + if (start >= start_pfn && 259 + memblock_end_pfn(&memblock.reserved, i) <= end_pfn) 260 + reserve_bootmem_node(pgdat, __pfn_to_phys(start), 261 + memblock_size_bytes(&memblock.reserved, i), 262 + BOOTMEM_DEFAULT); 203 263 } 204 - #endif 205 264 } 206 265 207 266 static void __init arm_bootmem_free(struct meminfo *mi) ··· 271 358 } 272 359 #endif 273 360 361 + void __init arm_memblock_init(struct meminfo *mi) 362 + { 363 + int i; 364 + 365 + memblock_init(); 366 + for (i = 0; i < mi->nr_banks; i++) 367 + memblock_add(mi->bank[i].start, mi->bank[i].size); 368 + 369 + /* Register the kernel text, kernel data and initrd with memblock. */ 370 + #ifdef CONFIG_XIP_KERNEL 371 + memblock_reserve(__pa(_data), _end - _data); 372 + #else 373 + memblock_reserve(__pa(_stext), _end - _stext); 374 + #endif 375 + #ifdef CONFIG_BLK_DEV_INITRD 376 + if (phys_initrd_size) { 377 + memblock_reserve(phys_initrd_start, phys_initrd_size); 378 + 379 + /* Now convert initrd to virtual addresses */ 380 + initrd_start = __phys_to_virt(phys_initrd_start); 381 + initrd_end = initrd_start + phys_initrd_size; 382 + } 383 + #endif 384 + 385 + arm_mm_memblock_reserve(); 386 + 387 + memblock_analyze(); 388 + memblock_dump_all(); 389 + } 390 + 274 391 void __init bootmem_init(struct machine_desc *mdesc) 275 392 { 276 393 struct meminfo *mi = &meminfo; 277 394 unsigned long min, max_low, max_high; 278 - int initrd; 279 - 280 - /* 281 - * Locate the ramdisk image, if any. 282 - */ 283 - initrd = check_initrd(mi); 284 395 285 396 max_low = max_high = 0; 286 397 ··· 312 375 313 376 arm_bootmem_init(mi, min, max_low); 314 377 315 - /* 316 - * Reserve any special regions. 317 - */ 318 - reserve_special_regions(); 319 - 320 378 if (mdesc->reserve) 321 379 mdesc->reserve(); 322 - 323 - /* 324 - * If the initrd is present, reserve its memory. 325 - */ 326 - if (initrd == 0) 327 - bootmem_reserve_initrd(); 328 380 329 381 /* 330 382 * Sparsemem tries to allocate bootmem in memory_present(),
+1 -1
arch/arm/mm/mm.h
··· 30 30 31 31 struct machine_desc; 32 32 void __init bootmem_init(struct machine_desc *); 33 - void reserve_special_regions(void); 33 + void arm_mm_memblock_reserve(void);
+15 -19
arch/arm/mm/mmu.c
··· 11 11 #include <linux/kernel.h> 12 12 #include <linux/errno.h> 13 13 #include <linux/init.h> 14 - #include <linux/bootmem.h> 15 14 #include <linux/mman.h> 16 15 #include <linux/nodemask.h> 16 + #include <linux/memblock.h> 17 17 #include <linux/sort.h> 18 18 19 19 #include <asm/cputype.h> ··· 489 489 490 490 static void __init *early_alloc(unsigned long sz) 491 491 { 492 - return alloc_bootmem_low_pages(sz); 492 + void *ptr = __va(memblock_alloc(sz, sz)); 493 + memset(ptr, 0, sz); 494 + return ptr; 493 495 } 494 496 495 497 static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot) ··· 707 705 } 708 706 early_param("vmalloc", early_vmalloc); 709 707 708 + phys_addr_t lowmem_end_addr; 709 + 710 710 static void __init sanity_check_meminfo(void) 711 711 { 712 712 int i, j, highmem = 0; 713 + 714 + lowmem_end_addr = __pa(vmalloc_min - 1) + 1; 713 715 714 716 for (i = 0, j = 0; i < meminfo.nr_banks; i++) { 715 717 struct membank *bank = &meminfo.bank[j]; ··· 840 834 } 841 835 842 836 /* 843 - * Reserve the various regions 837 + * Reserve the special regions of memory 844 838 */ 845 - void __init reserve_special_regions(void) 839 + void __init arm_mm_memblock_reserve(void) 846 840 { 847 - /* 848 - * Register the kernel text and data with bootmem. 849 - * Note that this can only be in node 0. 850 - */ 851 - #ifdef CONFIG_XIP_KERNEL 852 - reserve_bootmem(__pa(_data), _end - _data, BOOTMEM_DEFAULT); 853 - #else 854 - reserve_bootmem(__pa(_stext), _end - _stext, BOOTMEM_DEFAULT); 855 - #endif 856 - 857 841 /* 858 842 * Reserve the page tables. These are already in use, 859 843 * and can only be in node 0. 860 844 */ 861 - reserve_bootmem(__pa(swapper_pg_dir), 862 - PTRS_PER_PGD * sizeof(pgd_t), BOOTMEM_DEFAULT); 845 + memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t)); 863 846 864 847 #ifdef CONFIG_SA1111 865 848 /* 866 849 * Because of the SA1111 DMA bug, we want to preserve our 867 850 * precious DMA-able memory... 868 851 */ 869 - reserve_bootmem(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET, 870 - BOOTMEM_DEFAULT); 852 + memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); 871 853 #endif 872 854 } 873 855 ··· 998 1004 sanity_check_meminfo(); 999 1005 prepare_page_table(); 1000 1006 map_lowmem(); 1001 - bootmem_init(mdesc); 1002 1007 devicemaps_init(mdesc); 1003 1008 kmap_init(); 1004 1009 ··· 1005 1012 1006 1013 /* allocate the zero page. */ 1007 1014 zero_page = early_alloc(PAGE_SIZE); 1015 + 1016 + bootmem_init(mdesc); 1017 + 1008 1018 empty_zero_page = virt_to_page(zero_page); 1009 1019 __flush_dcache_page(NULL, empty_zero_page); 1010 1020 }
+3 -16
arch/arm/mm/nommu.c
··· 6 6 #include <linux/module.h> 7 7 #include <linux/mm.h> 8 8 #include <linux/pagemap.h> 9 - #include <linux/bootmem.h> 10 9 #include <linux/io.h> 10 + #include <linux/memblock.h> 11 11 12 12 #include <asm/cacheflush.h> 13 13 #include <asm/sections.h> ··· 17 17 18 18 #include "mm.h" 19 19 20 - /* 21 - * Reserve the various regions 22 - */ 23 - void __init reserve_special_regions(void) 20 + void __init arm_mm_memblock_reserve(void) 24 21 { 25 - /* 26 - * Register the kernel text and data with bootmem. 27 - * Note that this can only be in node 0. 28 - */ 29 - #ifdef CONFIG_XIP_KERNEL 30 - reserve_bootmem(__pa(_data), _end - _data, BOOTMEM_DEFAULT); 31 - #else 32 - reserve_bootmem(__pa(_stext), _end - _stext, BOOTMEM_DEFAULT); 33 - #endif 34 - 35 22 /* 36 23 * Register the exception vector page. 37 24 * some architectures which the DRAM is the exception vector to trap, 38 25 * alloc_page breaks with error, although it is not NULL, but "0." 39 26 */ 40 - reserve_bootmem(CONFIG_VECTORS_BASE, PAGE_SIZE, BOOTMEM_DEFAULT); 27 + memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE); 41 28 } 42 29 43 30 /*