boot_prep_linux -> {
char *commandline = getenv("bootargs");
setup_commandline_tag(gd->bd, commandline);
}
Kernel command line: root=/dev/sda2 rw rootwait mem=640M console=ttyS0,115200 init=/init video=nusmartfb:1024x600-16
Setup.c (arch\arm\kernel):early_param("mem", early_mem);
/*
* 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;
/*这里的算法是:如果没有开始地址,就使用PHYS_OFFSET
*这里也解释了为什么bootargs mem=xx没有设置开始地址的原因
*/
start = PHYS_OFFSET;
size = memparse(p, &endp);
if (*endp == '@')
start = memparse(endp + 1, NULL);
arm_add_memory(start, size);
return 0;
}
int __init arm_add_memory(phys_addr_t start, unsigned long size)
{
//赋值了全局变量struct meminfo meminfo;
}
根据boot传入的mem参数,meminfo已经赋值,该函数对memory进一步处理。
arch/arm/include/asm/pgtable.h
/*
* Just any arbitrary offset to the start of the vmalloc VM area: the
* current 8MB value just means that there will be a 8MB "hole" after the
* physical memory until the kernel virtual memory starts. That means that
* any out-of-bounds memory accesses will hopefully be caught.
* The vmalloc() routines leaves a hole of 4kB between each vmalloced
* area for the same reason. ;)
*/
#define VMALLOC_OFFSET (8*1024*1024)
#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#define VMALLOC_END 0xff000000UL
arch/arm/mm/mmu.c:
static void * __initdata vmalloc_min = (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
high_memory = __va(arm_lowmem_limit - 1) + 1;
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];
if (bank->start > ULONG_MAX)
highmem = 1;
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 (!bank->highmem &&
bank->start + bank->size > arm_lowmem_limit)
arm_lowmem_limit = bank->start + bank->size;
j++;
}
meminfo.nr_banks = j;
high_memory = __va(arm_lowmem_limit - 1) + 1;
memblock_set_current_limit(arm_lowmem_limit);
}
1]. 如果memory超过了vmalloc_min这个固定值,就会出现high memory;
划分的标准或者说点是vmalloc_min这个固定值和memory 大小的关系。
2]. high_memory的开始地址由arm_lowmem_limit决定,但不会无限制的先后挪,去挤压vmallo的空间
比如说Memory 1G多,并不是说high_memory的值就很大。
3]. 为什么要有vmalloc空间?是为了得到虚拟地址上连续,而物理上不连续的地址空间?
early_param("mem", early_mem);
Mmu.c (arch\arm\mm):early_param("cachepolicy", early_cachepolicy);
Mmu.c (arch\arm\mm):early_param("nocache", early_nocache);
Mmu.c (arch\arm\mm):early_param("nowb", early_nowrite);
Mmu.c (arch\arm\mm):early_param("ecc", early_ecc);
Mmu.c (arch\arm\mm):early_param("vmalloc", early_vmalloc);
Get_bootargs.c (arch\arm\mach-ns115):__setup("pmem=", pmem_mem_setup);
Get_bootargs.c (arch\arm\mach-ns115):__setup("gpumem=", gpu_mem_setup);
Get_bootargs.c (arch\arm\mach-ns115):__setup("umpmem=", ump_mem_setup);
Get_bootargs.c (arch\arm\mach-ns115):__setup("vpumem=", vpu_mem_setup);
Get_bootargs.c (arch\arm\mach-ns115):__setup("fbmem=", fb_mem_setup);
如reserver_crashkernel
/**
* reserve_crashkernel() - reserves memory are for crash kernel
*
* This function reserves memory area given in "crashkernel=" kernel command
* line parameter. The memory reserved is used by a dump capture kernel when
* primary kernel is crashing.
*/
static void __init reserve_crashkernel(void)
{
unsigned long long crash_size, crash_base;
unsigned long long total_mem;
int ret;
total_mem = get_total_mem();
ret = parse_crashkernel(boot_command_line, total_mem,
&crash_size, &crash_base);
if (ret)
return;
ret = reserve_bootmem(crash_base, crash_size, BOOTMEM_EXCLUSIVE);
if (ret < 0) {
printk(KERN_WARNING "crashkernel reservation failed - "
"memory is in use (0x%lx)\n", (unsigned long)crash_base);
return;
}
printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
"for crashkernel (System RAM: %ldMB)\n",
(unsigned long)(crash_size >> 20),
(unsigned long)(crash_base >> 20),
(unsigned long)(total_mem >> 20));
crashk_res.start = crash_base;
crashk_res.end = crash_base + crash_size - 1;
insert_resource(&iomem_resource, &crashk_res);
}