- void __init bootmem_init(void)
- {
-
unsigned long min, max_low, max_high; -
max_low = max_high = 0; -
find_limits(&min, &max_low, &max_high); -
arm_bootmem_init(min, max_low); -
/* -
* Sparsemem tries to allocate bootmem in memory_present(), -
* so must be done after the fixed reservations -
*/ -
arm_memory_present(); -
/* -
* sparse_init() needs the bootmem allocator up and running. -
*/ -
sparse_init(); -
/* -
* Now free the memory - free_area_init_node needs -
* the sparse mem_map arrays initialized by sparse_init() -
* for memmap_init_zone(), otherwise all PFNs are invalid. -
*/ -
arm_bootmem_free(min, max_low, max_high); -
high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) - 1) + 1; -
/* -
* This doesn't seem to be used by the Linux memory manager any -
* more, but is used by ll_rw_block. If we can get rid of it, we -
* also get rid of some of the stuff above as well. -
* -
* Note: max_low_pfn and max_pfn reflect the number of _pages_ in -
* the system, not the maximum PFN. -
*/ -
max_low_pfn = max_low - PHYS_PFN_OFFSET; -
max_pfn = max_high - PHYS_PFN_OFFSET; - }
- static void __init find_limits(unsigned long
*min, unsigned long *max_low, -
unsigned long *max_high) - {
-
struct meminfo *mi = &meminfo; -
int i; -
*min = -1UL; -
*max_low = *max_high = 0; -
for_each_bank (i, mi) { -
struct membank *bank = &mi->bank[i]; -
unsigned long start, end; -
start = bank_pfn_start(bank); -
end = bank_pfn_end(bank); -
if (*min > start) -
*min = start; -
if (*max_high < end) -
*max_high = end; -
if (bank->highmem) -
continue; -
if (*max_low < end) -
*max_low = end; -
} - }
- min :内存物理地址起始
- max_low :低端内存区物理地址末端
- max_high :高端内存区物理地址末端
- “如果这个内存bank是高端内存(bank->highmem != 0),跳过max_low = end;语句,max_low和max_high将不同(结果实际上是max_high >
max_low); - 否则假设没有一个内存bank是高端内存(所有bank->highmem == 0)max_low和max_high必然一致(高端内存大小为0)”
- struct meminfo meminfo;
- /*
-
* Memory map description -
*/ - #define NR_BANKS 8
- struct membank {
-
phys_addr_t start; -
unsigned long size; -
unsigned int highmem; - };
- struct meminfo {
-
int nr_banks; -
struct membank bank[NR_BANKS]; - };
- extern struct meminfo meminfo;
- #define for_each_bank(iter,mi)
\ -
for (iter = 0; iter < (mi)->nr_banks; iter++)
- void __init setup_arch(char **cmdline_p)
- {
-
struct machine_desc *mdesc; -
unwind_init(); -
setup_processor(); -
mdesc = setup_machine_fdt(__atags_pointer); -
if (!mdesc) -
mdesc = setup_machine_tags(machine_arch_type); -
machine_desc = mdesc; -
machine_name = mdesc->name; -
if (mdesc->soft_reboot) -
reboot_setup("s"); -
init_mm.start_code = (unsigned long) _text; -
init_mm.end_code = (unsigned long) _etext; -
init_mm.end_data = (unsigned long) _edata; -
init_mm.brk = (unsigned long) _end; -
-
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); -
*cmdline_p = cmd_line; -
parse_early_param(); -
sanity_check_meminfo(); -
arm_memblock_init(&meminfo, mdesc); -
paging_init(mdesc); -
request_standard_resources(mdesc); -
unflatten_device_tree(); - #ifdef CONFIG_SMP
-
if (is_smp()) -
smp_init_cpus(); - #endif
-
reserve_crashkernel(); -
cpu_init(); -
tcm_init(); - #ifdef CONFIG_MULTI_IRQ_HANDLER
-
handle_arch_irq = mdesc->handle_irq; - #endif
- #ifdef CONFIG_VT
- #if defined(CONFIG_VGA_CONSOLE)
-
conswitchp = &vga_con; - #elif defined(CONFIG_DUMMY_CONSOLE)
-
conswitchp = &dummy_con; - #endif
- #endif
-
early_trap_init(); -
if (mdesc->init_early) -
mdesc->init_early(); - }
- int __init arm_add_memory(phys_addr_t start, unsigned long size)
- {
-
struct membank *bank = &meminfo.bank[meminfo.nr_banks]; -
if (meminfo.nr_banks >= NR_BANKS) { -
printk(KERN_CRIT "NR_BANKS too low, " -
"ignoring memory at 0xllx\n", (long long)start); -
return -EINVAL; -
} -
/* -
* Ensure that start/size are aligned to a page boundary. -
* Size is appropriately rounded down, start is rounded up. -
*/ -
size -= start & ~PAGE_MASK; -
bank->start = PAGE_ALIGN(start); -
bank->size = size & PAGE_MASK; -
/* -
* Check whether this memory region has non-zero size or -
* invalid node number. -
*/ -
if (bank->size == 0) -
return -EINVAL; -
meminfo.nr_banks++; -
return 0; - }
- /*
-
* Pick out the memory size. We look for mem=size@start, -
* where start and size are "size[KkMm]" -
*/ - static int __init early_mem(char *p)
- {
-
static int usermem __initdata = 0; -
unsigned long size; -
phys_addr_t start; -
char *endp; -
/* -
* If the user specifies memory size, we -
* blow away any automatically generated -
* size. -
*/ -
if (usermem == 0) { -
usermem = 1; -
meminfo.nr_banks = 0; -
} -
start = PHYS_OFFSET; -
size = memparse(p, &endp); -
if (*endp == '@') -
start = memparse(endp + 1, NULL); -
arm_add_memory(start, size); -
return 0; - }
- early_param("mem", early_mem);
- static void * __initdata vmalloc_min = (void *)(VMALLOC_END - SZ_128M);
- /*
-
* vmalloc=size forces the vmalloc area to be exactly 'size' -
* bytes. This can be used to increase (or decrease) the vmalloc -
* area - the default is 128m. -
*/ - static int __init early_vmalloc(char *arg)
- {
-
unsigned long vmalloc_reserve = memparse(arg, NULL); -
if (vmalloc_reserve < SZ_16M) { -
vmalloc_reserve = SZ_16M; -
printk(KERN_WARNING -
"vmalloc area too small, limiting to %luMB\n", -
vmalloc_reserve >> 20); -
} -
if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) { -
vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M); -
printk(KERN_WARNING -
"vmalloc area is too big, limiting to %luMB\n", -
vmalloc_reserve >> 20); -
} -
vmalloc_min = (void *)(VMALLOC_END - vmalloc_reserve); -
-
return 0; - }
- early_param("vmalloc", early_vmalloc);
- static phys_addr_t lowmem_limit __initdata = 0;
- void __init sanity_check_meminfo(void)
- {
-
int i, j, highmem = 0; -
for (i = 0, j = 0; i < meminfo.nr_banks; i++) { -
struct membank *bank = &meminfo.bank[j]; -
*bank = meminfo.bank[i]; - #ifdef CONFIG_HIGHMEM
-
if (__va(bank->start) >= vmalloc_min || -
__va(bank->start) < (void *)PAGE_OFFSET) -
highmem = 1; -
bank->highmem = highmem; -
/* -
* Split those memory banks which are partially overlapping -
* the vmalloc area greatly simplifying things later. -
*/ -
if (__va(bank->start) < vmalloc_min && -
bank->size > vmalloc_min - __va(bank->start)) { -
if (meminfo.nr_banks >= NR_BANKS) { -
printk(KERN_CRIT "NR_BANKS too low, " -
"ignoring high memory\n"); -
} else { -
memmove(bank + 1, bank, -
(meminfo.nr_banks - i) * sizeof(*bank)); -
meminfo.nr_banks++; -
i++; -
bank[1].size -= vmalloc_min - __va(bank->start); -
bank[1].start = __pa(vmalloc_min - 1) + 1; -
bank[1].highmem = highmem = 1; -
j++; -
} -
bank->size = vmalloc_min - __va(bank->start); -
} - #else
-
bank->highmem = highmem; -
/* -
* Check whether this memory bank would entirely overlap -
* the vmalloc area. -
*/ -
if (__va(bank->start) >= vmalloc_min || -
__va(bank->start) < (void *)PAGE_OFFSET) { -
printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx " -
"(vmalloc region overlap).\n", -
(unsigned long long)bank->start, -
(unsigned long long)bank->start + bank->size - 1); -
continue; -
} -
/* -
* Check whether this memory bank would partially overlap -
* the vmalloc area. -
*/ -
if (__va(bank->start + bank->size) > vmalloc_min || -
__va(bank->start + bank->size) < __va(bank->start)) { -
unsigned long newsize = vmalloc_min - __va(bank->start); -
printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx " -
"to -%.8llx (vmalloc region overlap).\n", -
(unsigned long long)bank->start, -
(unsigned long long)bank->start + bank->size - 1, -
(unsigned long long)bank->start + newsize - 1); -
bank->size = newsize; -
} - #endif
-
if (!bank->highmem && bank->start + bank->size > lowmem_limit) -
lowmem_limit = bank->start + bank->size; -
j++; -
} - #ifdef CONFIG_HIGHMEM
-
if (highmem) { -
const char *reason = NULL; -
if (cache_is_vipt_aliasing()) { -
/* -
* Interactions between kmap and other mappings -
* make highmem support with aliasing VIPT caches -
* rather difficult. -
*/ -
reason = "with VIPT aliasing cache"; -
} -
if (reason) { -
printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n", -
reason); -
while (j > 0 && meminfo.bank[j - 1].highmem) -
j--; -
} -
} - #endif
-
meminfo.nr_banks = j; -
memblock_set_current_limit(lowmem_limit); - }
- static int __init meminfo_cmp(const void *_a, const void *_b)
- {
-
const struct membank *a = _a, *b = _b; -
long cmp = bank_pfn_start(a) - bank_pfn_start(b); -
return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; - }
- void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
- {
-
int i; -
sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); -
memblock_init(); -
for (i = 0; i < mi->nr_banks; i++) -
memblock_add(mi->bank[i].start, mi->bank[i].size); -
/* Register the kernel text, kernel data and initrd with memblock. */ - #ifdef CONFIG_XIP_KERNEL
-
memblock_reserve(__pa(_sdata), _end - _sdata); - #else
-
memblock_reserve(__pa(_stext), _end - _stext); - #endif
- #ifdef CONFIG_BLK_DEV_INITRD
-
if (phys_initrd_size && -
!memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) { -
pr_err("INITRD: 0xlx+0xlx is not a memory region - disabling initrd\n", -
phys_initrd_start, phys_initrd_size); -
phys_initrd_start = phys_initrd_size = 0; -
} -
if (phys_initrd_size && -
memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) { -
pr_err("INITRD: 0xlx+0xlx overlaps in-use memory region - disabling initrd\n", -
phys_initrd_start, phys_initrd_size); -
phys_initrd_start = phys_initrd_size = 0; -
} -
if (phys_initrd_size) { -
memblock_reserve(phys_initrd_start, phys_initrd_size); -
/* Now convert initrd to virtual addresses */ -
initrd_start = __phys_to_virt(phys_initrd_start); -
initrd_end = initrd_start + phys_initrd_size; -
} - #endif
-
arm_mm_memblock_reserve(); -
arm_dt_memblock_reserve(); -
/* reserve any platform specific memblock areas */ -
if (mdesc->reserve) -
mdesc->reserve(); -
memblock_analyze(); -
memblock_dump_all(); - }
上一篇:JTAG接口技术及ETM
下一篇:如何安装arm-linux-gcc编译器
推荐阅读最新更新时间:2024-03-16 14:51