内核内存配置解析

原创声明:作者保留一切权力,转载请注明出处。

所有资料均来源于互联网,若侵犯了您的权利,请告知,作者一定修正。

 

一、meminfo变量与结构体

内核在启动过程中通过一个全局变量‘meminfo’来配置内存。

巧合的是,这个全局变量与它的类型,一个特殊的结构体‘meminfo’同名。

 

变量的定义在

arch/arm/kernel/setup.c

 

static struct meminfo meminfo __initdata = { 0, };

 

这句话表示定义一个作用域是本文件的变量(static),这个变量的类型是个结构体(struct meminfo), 变量的名称是meminfo,它被定位在data段(__initdata),它同时被初始化({ 0, })。

 

 结构体struct meminfo  声明在

include/asm-arm/setup.h

 

struct meminfo {

            int nr_banks;

            struct membank bank[NR_BANKS];

};

 

二、内核配置内存的过程

系统对内存的默认配置是通过tag设置的。

 

arch/arm/kernel/setup.c 中事先定义了默认的 tags. 即全局变量 init_tags,

 

static struct init_tags {

            struct tag_header hdr1;

            struct tag_core   core;

            struct tag_header hdr2;

            struct tag_mem32  mem;

            struct tag_header hdr3;

} init_tags __initdata = {

            { tag_size(tag_core), ATAG_CORE },

            { 1, PAGE_SIZE, 0xff },

            { tag_size(tag_mem32), ATAG_MEM },

            { MEM_SIZE, PHYS_OFFSET },

            { 0, ATAG_NONE }

};

 

其中关于内存的默认配置是,

{ tag_size(tag_mem32), ATAG_MEM },

            { MEM_SIZE, PHYS_OFFSET }

 

所以 经过 parse_tags(tags) , 初始内存就配置好了.也就是说变量meminfo就有内容了。

它的内容会被用户自定义的设置所覆盖,如果有用户设置的话。

 

用户可以通过命令行中的mem来定义自己的设置。

   mem=16M@0xC0000000

表明内存大小为16M 起始地址是0xC000000

<Q001> 这个地址是物理地址还是逻辑地址?

 

[1] linux 2.6内核启动过程中,是如何得到内存大小的

引用{

arm linux中一般在cmdline或传递tag参数中设置, 个别板子在machine_desc.fixup函数中设置. 按顺序分别说明:

 

1, 出现顺序(内核版本2.6.25.20,下同)

start_kernel()

    ->setup_arch()

        ->mdesc->fixup()

        ->parse_tags()

            ->parse_tag_mem32()

        ->parse_cmdline()

            ->early_mem()

 

2, fixup()函数

这个函数arm平台用的很少. 我只找到eseries.c, mach-smdk2413.c, mach-vstms.c这几个arm板子有, smdk2413_fixup()是在bootloader传递tag地址与machine_desc预设tag地址(mem_PA+0x100)不同时设置memorystartsize. 如果fixup起作用, 会从tag中把mem tag改为ATAG_NONE, 后面的"parse_tag_mem32"就没用了.

 

3, parse_tag_mem32()

该函数定义在"arch/arm/kernel/setup.c". bootloader传入的mem tag(ATAG_MEM)startsize参数通过"arm_add_memory()"加入到meminfo的最后一个bank. startmemory物理起始地址.

 

4, early_mem()

该函数定义在"arch/arm/kernel/setup.c". 处理cmdline中的"mem=size@start".

如果没有定义mem起始地址, 使用'PHYS_OFFSET'(arm中应由arm开发板设置)作为start. early_mem()会覆盖前面设置的meminfo.

 

}引用

 

三、遗留问题

<Q001> 命令行mem定义的地址是物理地址还是逻辑地址?

<Q002>如果有两片以上且物理地址不连续的内存应该怎样定义?

 

四、参考资料

[1] linux 2.6内核启动过程中,是如何得到内存大小的

http://linux.chinaunix.net/bbs/thread-1062377-1-1.html

 

Logo

更多推荐