Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2150647
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2013-08-13 15:26:52

start_kernel
    --> setup_arch    ; arch/arm/kernel/setup.c
  1. asmlinkage void __init start_kernel(void)
  2. {   
  3.     setup_arch(&command_line);
  4.     mm_init_owner(&init_mm, &init_task);
  5.     mm_init_cpumask(&init_mm);
  6.     page_alloc_init();
  7.     parse_early_param();
  8.     mm_init();
  9.     idr_init_cache();  
  10. }

在arch/arm/kernel/setup.c中
start_kernel
    --> setup_arch
  1. void __init setup_arch(char **cmdline_p)
  2. {
  3.     mdesc = setup_machine_fdt(__atags_pointer);
  4.     if (!mdesc)
  5.         mdesc = setup_machine_tags(machine_arch_type);    //1. meminfo的初始化  
  6.     parse_early_param();

  7.     sanity_check_meminfo();                               //1.2 结构体meminfo的初始化    
  8.     arm_memblock_init(&meminfo, mdesc);                   //1.3 将内存的block信息存在memblock中

  9.     paging_init(mdesc);
  10.     request_standard_resources(mdesc);

  11.     unflatten_device_tree();

  12.     if (mdesc->init_early)
  13.         mdesc->init_early();
  14. }
1.1 结构体meminfo的初始化
结构体meminfo的初始化比较难找
start_kernel
    --> setup_arch
  1. static struct machine_desc * __init setup_machine_tags(unsigned int nr)
  2. {   
  3.    .....                           //省略
  4.     if (mdesc->fixup)                 //mdesc->fixxp ==NULL,下句不执行
  5.         mdesc->fixup(mdesc, tags, &from, &meminfo);
  6.  
  7.     if (tags->hdr.tag == ATAG_CORE) {
  8.         if (meminfo.nr_banks != 0)
  9.             squash_mem_tags(tags);
  10.         save_atags(tags);
  11.         parse_tags(tags);           
  12.     }
  13.     return mdesc;
  14. }
start_kernel
    --> setup_arch
        --> parse_tags
  1. static void __init parse_tags(const struct tag *t)
  2. {
  3.     for (; t->hdr.size; t = tag_next(t))
  4.         if (!parse_tag(t))    //在此处调用tag中的函数指针
  5.             printk( "Ignoring unrecognised tag 0x%08x\n", t->hdr.tag);
  6. }
start_kernel
    --> setup_arch
        --> parse_tags
            --> parse_tag
  1. static int __init parse_tag(const struct tag *tag)
  2. {
  3.     extern struct tagtable __tagtable_begin, __tagtable_end;
  4.     struct tagtable *t;
  5.     for (t = &__tagtable_begin; t < &__tagtable_end; t++)
  6.         if (tag->hdr.tag == t->tag) {
  7.             t->parse(tag);  //在此处调用tag中的函数指针
  8.             break;
  9.         }
  10.     return t < &__tagtable_end;
  11. }
1.1.1 上面的函数指针是什么呢?
start_kernel
    --> setup_arch
        --> parse_tags
            --> parse_tag
                --> parse_tag_mem32
  1. 在arch/arm/kernel/setup.c中
  2. static int __init parse_tag_mem32(const struct tag *tag)
  3. {
  4.     return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
  5. }
  6. __tagtable(ATAG_MEM, parse_tag_mem32);
在arch/arm/include/asm/setup.h中有如下定义:
  1. #define __tag __used __attribute__((__section__(".taglist.init")))
  2. #define __tagtable(tag, fn) \
  3. static struct tagtable __tagtable_##fn __tag = { tag, fn }
  4. 所以把__tagtable(ATAG_MEM, parse_tag_mem32);展开后:
  5. static struct tagtable __tagtable_parse_tag_mem32
  6.     __used __attribute__((__section__(".taglist.init"))) = { ATAG_MEM , parse_tag_mem32};
start_kernel
    --> setup_arch
        --> parse_tags
            --> parse_tag
                --> parse_tag_mem32
                    --> arm_add_memory
将内存起始与长度存在meminfo的bank中:
如果多次调用arm_add_memory,即板子上有多个内存bank,因为meminfo.nr_banks是一个全局变量,
这将会对每一个bank的起始与长度都保存到数组中,但不能超过8个
  1. int __init arm_add_memory(phys_addr_t start, unsigned long size)
  2. {
  3.     struct membank *bank = &meminfo.bank[meminfo.nr_banks];
  4.     if (meminfo.nr_banks >= NR_BANKS)    //#define NR_BANKS 8
            return -EINVAL;   
  5.     size -= start & ~PAGE_MASK;
  6.     bank->start = PAGE_ALIGN(start);     //start = 0x50000000
  7.     bank->size = size & PAGE_MASK;       //size = 0x8000000=128M
  8.     if (bank->size == 0)
  9.         return -EINVAL;
  10.     meminfo.nr_banks++;                   //现在nr_banks由0->1
  11.     return 0;
  12. }

1.2 结构体meminfo的初始化
setup_arch
    --> sanity_check_meminfo
在初始化好meminfo后就知道了内存中每个bank的起始地址和长度
  1. void __init sanity_check_meminfo(void)
  2. {
  3.     // PHYS_OFFSET=0x50000000, PAGE_OFFSET=0xc0000000
        // VMALLOC_START=0x800000, VMALLOC_END=0xf4000000
  4.     // __va(bank->start)=0xc0000000,vmalloc_min=0xec000000
  5.     for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
  6.         struct membank *bank = &meminfo.bank[j];
  7.         *bank = meminfo.bank[i];

  8.         // CONFIG_HIGHMEM=y
  9.         //物理内存映射后在高端,则highmem=1
  10.         if (__va(bank->start) >= vmalloc_min || __va(bank->start) < (void *)PAGE_OFFSET)
  11.             highmem = 1;
  12.         bank->highmem = highmem;                           //此处highmem=0
  13.         //如果物理内存映射后不在高端,但地址范围超过了高端地址,则highmem=1
  14.         if (__va(bank->start) < vmalloc_min && bank->size > vmalloc_min - __va(bank->start))
  15.            ;
  16.         //开发板不属于以上两种情况,即highmem=0
  17.         if (!bank->highmem && bank->start + bank->size > lowmem_limit)
  18.             lowmem_limit = bank->start + bank->size;

  19.         j++;
  20.     }
  21.     if (highmem) {      
  22.     }
  23.     meminfo.nr_banks = j;                        //j=1
  24.     memblock_set_current_limit(lowmem_limit);    //lowmem_limit=0x58000000
  25. }
1.3 将内存的block信息存在memblock中
setup_arch
    --> arm_memblock_init
  1. void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
  2. {
  3.     //因为meminfo.nr_banks=1,所以这个sort没有起作用
  4.     sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
  5.     memblock_init();                          //1.3.1 初始化memblock结构体
  6.     for (i = 0; i < mi->nr_banks; i++)        //nr_banks=1,所以只执行一次memblock_add
  7.         memblock_add(mi->bank[i].start, mi->bank[i].size);   //1.3.2初始化memblock的memory.region
  8.   
  9.     memblock_reserve(__pa(_stext), _end - _stext);           //1.3.3初始化memblock的reserve.region
  10.     arm_mm_memblock_reserve();                              //1.3.4再次初始化memblock的reserve.region
  11.     arm_dt_memblock_reserve();                              //空函数,不用管
  12.     if (mdesc->reserve)           //没有定义mdesc->reserve
  13.         mdesc->reserve();
  14.     memblock_analyze();                                      //1.3.5 将整个内存的大小存在memory_size中
  15.     memblock_dump_all();
  16. }

1.3.1 初始化memblock结构体
setup_arch
    --> arm_memblock_init
        --> iniit_memblock_init
定义在mm/memblock.c中
static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS + 1] __initdata_memblock;
  1. void __init memblock_init(void)
  2. {
  3.     //函数只可执行一次
  4.     static int init_done __initdata = 0;
  5.     if (init_done)
  6.         return;
  7.     init_done = 1;

  8.     memblock.memory.regions    = memblock_memory_init_regions;
  9.     memblock.memory.max        = INIT_MEMBLOCK_REGIONS;
  10.     memblock.reserved.regions  = memblock_reserved_init_regions;
  11.     memblock.reserved.max      = INIT_MEMBLOCK_REGIONS;

  12.     memblock.memory.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE;
  13.     memblock.reserved.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE;
  14.     memblock.memory.regions[0].base = 0;
  15.     memblock.memory.regions[0].size = 0;
  16.     memblock.memory.cnt = 1;

  17.     memblock.reserved.regions[0].base = 0;
  18.     memblock.reserved.regions[0].size = 0;
  19.     memblock.reserved.cnt = 1;

  20.     memblock.current_limit = MEMBLOCK_ALLOC_ANYWHERE;
  21. }
1.3.2 初始化memblock结构体中的memory.region
setup_arch
    --> arm_memblock_init
        --> memblock_add
             --> memblock_add_region
memblock_add(mi->bank[i].start, mi->bank[i].size);
  1. long __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
  2. {
  3.     return memblock_add_region(&memblock.memory, base, size);
  4. }
  5. static long __init_memblock memblock_add_region(struct memblock_type *type,
  6.                         phys_addr_t base, phys_addr_t size)
  7. {
  8.     phys_addr_t end = base + size;        //在函数memblock_init初始化中rgn->size=0
  9.     for (i = 0; i < type->cnt; i++) {     //所以这儿直接break了
  10.         if (rgn->base > end || rgn->size == 0)
  11.             break;
  12.     }
  13.     if ((type->cnt == 1) && (type->regions[0].size == 0)) {   //进行两个赋值
  14.         type->regions[0].base = base;      //base=0x50000000
  15.         type->regions[0].size = size;      //size=0x8000000
  16.         return 0;
  17.     }
  18. }
1.3.3 初始化memblock结构体中的resever.region
setup_arch
    --> arm_memblock_init
           -->  memblock_reserve
执行memblock_reserve的过程与 memblock_add的过程是一样的只是把memory.region.base与memory.region.size赋值了.

memblock.memory.regions[0].base = 0x50008000;         
memblock.memory.regions[0].size = 0x8000000;             //128M
memblock.memory.cnt = 1;

memblock.reserved.regions[0].base = 0x50008000;
memblock.reserved.regions[0].size = 0x734b10;             //解压后内核在内存中的大小
memblock.reserved.cnt = 1;

1.3.4 还没有看明白
好像是将swap的信息整一下
setup_arch
    --> arm_memblock_init
        --> arm_mm_memblock_reserve
            --> memblock_reserve
                 --> memblock_add_region

  1. void __init arm_mm_memblock_reserve(void)
  2. {
  3.     //swap=0x50004000, size=0x4000
  4.     memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
  5. }
  6. long __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
  7. {
  8.     struct memblock_type *_rgn = &memblock.reserved;
  9.     //base=0x50004000, size=0x4000
  10.     return memblock_add_region(_rgn, base, size);
  11. }

  12. static long __init_memblock memblock_add_region(struct memblock_type *type,
  13.                         phys_addr_t base, phys_addr_t size)
  14. {
  15.     phys_addr_t end = base + size;
  16.     for (i = 0; i < type->cnt; i++) {
  17.         struct memblock_region *rgn = &type->regions[i];
  18.         phys_addr_t rend = rgn->base + rgn->size;                    
  19.         rgn->base = base;
  20.         rgn->size = rend - base;
  21.         if (rend >= end)
  22.             return 0;
  23.     }
  24. }
memblock.reserved.regions[0].base = 0x50004000;        //由0x50008000 --> 0x50004000
memblock.reserved.regions[0].size = 0x734b10;             //解压后内核在内存中的大小
memblock.reserved.cnt = 1;
1.3.5 将整个内存的大小存在memory_size中
setup_arch
    --> arm_memblock_init
        --> memblock_analyze
  1. void __init memblock_analyze(void)
  2. {
  3.     memblock.memory_size = 0;
  4.     //memblock.memory_size=0x8000000
  5.     for (i = 0; i < memblock.memory.cnt; i++)
  6.         memblock.memory_size += memblock.memory.regions[i].size;    
  7.     memblock_can_resize = 1;
  8. }


阅读(4852) | 评论(0) | 转发(4) |
给主人留下些什么吧!~~