memblock add memblock region流程

来源:互联网 发布:淘宝店铺被扣48分 编辑:程序博客网 时间:2024/06/02 01:33

memblock初始化流程:

start_kernel()->setup_arch()->arm64_memblock_init().

下面以memblock reserve操作为例讲解memblock add memblock region的基础:

void __init arm64_memblock_init(void){phys_addr_t dma_phys_limit = 0;/* * Register the kernel text, kernel data, initrd, and initial * pagetables with memblock. */memblock_reserve(__pa(_text), _end - _text);//_text = 0xffffffc000080000 _end = 0xffffffc0021ec000#ifdef CONFIG_BLK_DEV_INITRDif (initrd_start)memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);#endifearly_init_fdt_scan_reserved_mem();/* 4GB maximum for 32-bit only capable devices */if (IS_ENABLED(CONFIG_ZONE_DMA))dma_phys_limit = max_zone_dma_phys();dma_contiguous_reserve(dma_phys_limit);mrdump_rsvmem();memblock_allow_resize();memblock_dump_all();}
首先调用memblock_reserve()将kernel text, kernel data, initrd, and initial reserve.

具体调用和计算方法如下:

int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size){return memblock_reserve_region(base, size, MAX_NUMNODES, 0);}static int __init_memblock memblock_reserve_region(phys_addr_t base,   phys_addr_t size,   int nid,   unsigned long flags){struct memblock_type *_rgn = &memblock.reserved;pr_err("memblock_reserve: [%#016llx-%#016llx] flags %#02lx %pF\n",//打印出通过memblock reserve的memory     (unsigned long long)base,     (unsigned long long)base + size - 1,     flags, (void *)_RET_IP_);#ifdef CONFIG_MTK_MEMCFGif (memblock_reserve_count < MAX_MEMBLOCK_RECORD) {struct stack_trace trace;memblock_record[memblock_reserve_count].base = base;memblock_record[memblock_reserve_count].end = base + size - 1;memblock_record[memblock_reserve_count].size = size;memblock_record[memblock_reserve_count].flags = flags;memblock_record[memblock_reserve_count].ip = (unsigned long) _RET_IP_;init_memblock_stack_trace(&memblock_stack_trace[memblock_reserve_count],&trace, (unsigned long)size, 0);save_stack_trace_tsk(current, &trace);memblock_stack_trace[memblock_reserve_count].count =trace.nr_entries;}memblock_reserve_count++;#endifreturn memblock_add_range(_rgn, base, size, nid, flags);}int __init_memblock memblock_add_range(struct memblock_type *type,phys_addr_t base, phys_addr_t size,int nid, unsigned long flags){bool insert = false;phys_addr_t obase = base;phys_addr_t end = base + memblock_cap_size(base, &size);//初始化添加的memblock region的起始地址int i, nr_new;if (!size)return 0;/* special case for empty array */if (type->regions[0].size == 0) {//如果要添加的memblock region是该类型memblock的第一个region,则初始化region[0],然后return,添加region工作完成WARN_ON(type->cnt != 1 || type->total_size);type->regions[0].base = base;type->regions[0].size = size;type->regions[0].flags = flags;memblock_set_region_node(&type->regions[0], nid);type->total_size = size;return 0;}repeat://如果该memblock已有region在,则往下执行/* * The following is executed twice.  Once with %false @insert and * then with %true.  The first counts the number of regions needed * to accomodate the new area.  The second actually inserts them. */base = obase;nr_new = 0;for (i = 0; i < type->cnt; i++) {//遍历所有的memblock的regionstruct memblock_region *rgn = &type->regions[i];phys_addr_t rbase = rgn->base;//获取当前所遍历的region的起始地址和大小(PS:每个memblock type所有的region信息都是保存在region[]的结构体数组中)phys_addr_t rend = rbase + rgn->size;if (rbase >= end)//如果当前region的起始地址大于要加入的memblock region的结束地址,则说明加入的block必须放在当前region的前面,breakbreak;if (rend <= base)//如果当前region的结束地址小于要加入的region的起始地址,说明还没有找到要加入的region的地方,continuecontinue;/* * @rgn overlaps.  If it separates the lower part of new * area, insert that portion. */if (rbase > base) {//如果不满足以上两种情况,当前的region起始地址大于要加入的region的起始地址,则说明要加入的region和当前region起码有一部分重合nr_new++;//新加入的region个数+1if (insert)//第一次repeat,insert = false,当第二次repeat时insert=truememblock_insert_region(type, i++, base,       rbase - base, nid,       flags);//此时新加入的region至少分成两个region,第一个是当前region起始地址减去新加入region的起始地址,第二个是当前region}/* area below @rend is dealt with, forget about it */base = min(rend, end);//此时的base等于当前region的结束地址和要加入region的结束地址中较小的一个,                                       再次进行for循环会break,因为已经找到要插入的地方。}/* insert the remaining portion */if (base < end) {//如果此条件成立,说明要加入的region结束地址比当前region的结束地址大,需要将新加入的region的结束地址减去当前region的结束地址这部分memblock插进来nr_new++;//新加入的region个数再+1if (insert)//第一次repeat,insert=false,当第二次repeat时insert=truememblock_insert_region(type, i, base, end - base,       nid, flags);           //此时新加入的region至少分成两个region,第一个是当前region,第二个是新加入region结束地址减去当前region的结束地址        }//如果以上两个if (base < end)和if (rbase > base)都满足,则说明此事新加入的region包含了当前region,而整个memblock type的region个数多了2个,即新加入的region被当前region分成了三个部分/* * If this was the first round, resize array and repeat for actual * insertions; otherwise, merge and return. */if (!insert) {while (type->cnt + nr_new > type->max)if (memblock_double_array(type, obase, size) < 0)return -ENOMEM;insert = true;//将insert置为truegoto repeat;} else {memblock_merge_regions(type);//如果以上新加入的region和memblock已有的region有重合,且memblock已有的region不能完全包含新加入的region,则需要通过此函数将相邻的region进行合并return 0;}}static void __init_memblock memblock_insert_region(struct memblock_type *type,//主要是将要添加的region添加到memblock type中   int idx, phys_addr_t base,   phys_addr_t size,   int nid, unsigned long flags){struct memblock_region *rgn = &type->regions[idx];BUG_ON(type->cnt >= type->max);memmove(rgn + 1, rgn, (type->cnt - idx) * sizeof(*rgn));rgn->base = base;rgn->size = size;rgn->flags = flags;memblock_set_region_node(rgn, nid);type->cnt++;type->total_size += size;}static void __init_memblock memblock_merge_regions(struct memblock_type *type){int i = 0;/* cnt never goes below 1 */while (i < type->cnt - 1) {//遍历memblock的所有regionstruct memblock_region *this = &type->regions[i];struct memblock_region *next = &type->regions[i + 1];if (this->base + this->size != next->base ||    memblock_get_region_node(this) !=    memblock_get_region_node(next) ||    this->flags != next->flags) {BUG_ON(this->base + this->size > next->base);i++;continue;}this->size += next->size;//将首尾相连的region进行合并/* move forward from next + 1, index of which is i + 2 */memmove(next, next + 1, (type->cnt - (i + 2)) * sizeof(*next));type->cnt--;}}


memblock_reserve()->memblock_reserve_region()->memblock_add_range().

在memblock_reserve_region函数每次调用都会打印系统透过memblock reserve的所有的memory block,具体如下:

[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x00000040080000-0x000000421ebfff] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x00000045000000-0x000000452499eb] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x00000044000000-0x0000004401d1b8] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x00000040000000-0x00000040000fff] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x000000444f0000-0x000000444fffff] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x00000044800000-0x000000448fffff] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x00000046000000-0x000000463fffff] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x00000044400000-0x0000004440ffff] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x00000044410000-0x000000444effff] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x0000013ffa0fc0-0x0000013ffa0ff7] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x0000013ffa0f80-0x0000013ffa0fb7] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x0000013ffa0f40-0x0000013ffa0f77] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x0000013ffa0f00-0x0000013ffa0f37] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x0000013ffa0ec0-0x0000013ffa0ef7] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x0000013ffa0e80-0x0000013ffa0eb7] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x0000013ffa0e40-0x0000013ffa0e77] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x0000013ffa0e00-0x0000013ffa0e37] flags 0x0 memblock_reserve+0xc/0x14[    0.000000] <0>-(0)[0:swapper]memblock_reserve: [0x0000013ffa0dc0-0x0000013ffa0df7] flags 0x0 memblock_reserve+0xc/0x14

其虚拟地址的信息如下:

[    0.000000] <0>-(0)[0:swapper]Virtual kernel memory layout:[    0.000000] <0>    vmalloc : 0xffffff8000000000 - 0xffffffbdffff0000   (   247 GB)[    0.000000] <0>    vmemmap : 0xffffffbe00000000 - 0xffffffbfc0000000   (     7 GB maximum)[    0.000000] <0>              0xffffffbe00000000 - 0xffffffbe03800000   (    56 MB actual)[    0.000000] <0>    PCI I/O : 0xffffffbffa000000 - 0xffffffbffb000000   (    16 MB)[    0.000000] <0>    fixed   : 0xffffffbffbdfd000 - 0xffffffbffbdff000   (     8 KB)[    0.000000] <0>    modules : 0xffffffbffc000000 - 0xffffffc000000000   (    64 MB)[    0.000000] <0>    memory  : 0xffffffc000000000 - 0xffffffc100000000   (  4096 MB)[    0.000000] <0>      .init : 0xffffffc0011f8000 - 0xffffffc001302000   (  1064 KB)[    0.000000] <0>      .text : 0xffffffc000080000 - 0xffffffc0011f7094   ( 17885 KB)[    0.000000] <0>      .data : 0xffffffc00131d000 - 0xffffffc0014f0248   (  1869 KB)
然后会调用memblock_add_range()函数将所要reserve的一个memblock region添加到相应的type的memblock中。相关函数的运行逻辑,请见上面的注释。

物理内存实际layout:

[    0.000000] <0>-(0)[0:swapper][PHY layout]atf-reserved-memory@44600000   :   0x44600000 - 0x4460ffff (0x10000)[    0.000000] <0>-(0)[0:swapper][PHY layout]atf-ramdump-memory@44610000   :   0x44610000 - 0x4463ffff (0x30000)[    0.000000] <0>-(0)[0:swapper][PHY layout]cache-dump-memory@44640000   :   0x44640000 - 0x4466ffff (0x30000)[    0.000000] <0>-(0)[0:swapper][PHY layout]consys-reserve-memory   :   0xbde00000 - 0xbdffffff (0x200000)[    0.000000] <0>-(0)[0:swapper][PHY layout]spm-reserve-memory   :   0xbe180000 - 0xbe195fff (0x16000)[    0.000000] <0>-(0)[0:swapper][PHY layout]reserve-memory-scp_share   :   0x8f000000 - 0x8fffffff (0x1000000)[    0.000000] <0>-(0)[0:swapper][PHY layout]spi-reserve-memory   :   0xbe160000 - 0xbe175fff (0x16000)[    0.000000] <0>-(0)[0:swapper][PHY layout]kernel   :   0x40000000 - 0x445fffff (0x4600000)[    0.000000] <0>-(0)[0:swapper][PHY layout]kernel   :   0x44670000 - 0x87ffffff (0x43990000)[    0.000000] <0>-(0)[0:swapper][PHY layout]kernel   :   0x88200000 - 0x8effffff (0x6e00000)[    0.000000] <0>-(0)[0:swapper][PHY layout]kernel   :   0x90000000 - 0xb3ffffff (0x24000000)[    0.000000] <0>-(0)[0:swapper][PHY layout]kernel   :   0xbb000000 - 0xbddfffff (0x2e00000)[    0.000000] <0>-(0)[0:swapper][PHY layout]kernel   :   0xbe000000 - 0xbe15ffff (0x160000)[    0.000000] <0>-(0)[0:swapper][PHY layout]kernel   :   0xbe176000 - 0xbe17ffff (0xa000)[    0.000000] <0>-(0)[0:swapper][PHY layout]kernel   :   0xbe196000 - 0xbe19ffff (0xa000)[    0.000000] <0>-(0)[0:swapper][PHY layout]kernel   :   0xc0000000 - 0x13fffffff (0x80000000)[    0.565275] <4>.(4)[1:swapper/0][PHY layout]tee_reserved_mem   :   0xbff80000 - 0xbffbffff (0x40000)[    0.566463] <4>[PHY layout]FB (dt) :  0xbe3a0000 - 0xbff7ffff  (0x1be0000)[    1.724283] <4>.(4)[1:swapper/0][PHY layout]ccci_md0 at LK  :  0xb4000000 - 0xbaffffff  (0x7000000)[    1.726314] <4>.(4)[1:swapper/0][PHY layout]ccci_share_mem at LK  :  0x88000000 - 0x881fffff  (0x200000)
memblock_add_range()的执行效果可以如下图:






阅读全文
1 0
原创粉丝点击