Linux内核---41.arm 内存初始化

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 (= &__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 (= 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 (= 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 (= 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 (= 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 (= 0; i < memblock.memory.cnt; i++)
  6.         memblock.memory_size += memblock.memory.regions[i].size;    
  7.     memblock_can_resize = 1;
  8. }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值