低端内存高端内存是怎样划分的

1. 对UBboot传入的mem参数,kernel 是怎样处理的

在boot中 通过bootargs  env创建 commandline tag:

boot_prep_linux -> {

     char *commandline = getenv("bootargs");

    setup_commandline_tag(gd->bd, commandline);

}

Kernel 得到的command line 如下,其中包含mem=640M.

Kernel command line: root=/dev/sda2 rw rootwait mem=640M console=ttyS0,115200 init=/init video=nusmartfb:1024x600-16

内核对应的处理函数是:early_mem.

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;
}

2 sanity_check_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空间?是为了得到虚拟地址上连续,而物理上不连续的地址空间?


3 kernel处理boot传入参数的方法

1] early_param

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);

2] __setup

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);

3] 从命令行查找目标字符串

如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);
}


你可能感兴趣的:(kernel,memory)