免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2059 | 回复: 0
打印 上一主题 下一主题

[内核入门] memblock的问题。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-01-02 22:26 |只看该作者 |倒序浏览
在bootloader传递给过去关于内存的tag之后被解析到meminfo结构体中。
void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
{
        int i;

        for (i = 0; i < mi->nr_banks; i++)
                memblock_add(mi->bank[i].start, mi->bank[i].size); //添加memblock.memory

        arm_mm_memblock_reserve();  //页表处的内存区域(in use)添加到memblock.reserve
        arm_dt_memblock_reserve();   //先不考虑,假设为tags形式传递参数过来

        if (mdesc->reserve)
                mdesc->reserve();        //head.s中可以确定的mdesc


        dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit));

        arm_memblock_steal_permitted = false;
        memblock_allow_resize();
        memblock_dump_all();
}

确定了memblock结构体的各种信息之后,从memblock上memblock_alloc_base函数上进行分配内存。
memblock_alloc_base -> __memblock_alloc_base -> memblock_alloc_base_nid -> memblock_find_in_range_node-> for_each_free_mem_range_reverse


#define for_each_free_mem_range_reverse(i, nid, p_start, p_end, p_nid)        \
        for (i = (u64)ULLONG_MAX,                                        \
             __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid);        \
             i != (u64)ULLONG_MAX;                                        \
             __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid))

//分配内存区域
void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid,
                                           phys_addr_t *out_start,
                                           phys_addr_t *out_end, int *out_nid)
{
        struct memblock_type *mem = &memblock.memory;
        struct memblock_type *rsv = &memblock.reserved;
        int mi = *idx & 0xffffffff;
        int ri = *idx >> 32;

        if (*idx == (u64)ULLONG_MAX) {
                mi = mem->cnt - 1; //从最高的regions[mi]开始往下分配
                ri = rsv->cnt;     //
        }

        for ( ; mi >= 0; mi--) {
                struct memblock_region *m = &mem->regions[mi];
                phys_addr_t m_start = m->base;
                phys_addr_t m_end = m->base + m->size;

                /* only memory regions are associated with nodes, check it */
                if (nid != MAX_NUMNODES && nid != memblock_get_region_node(m)) //nid 指定从哪个node分配则需要检查
                        continue;

                /* scan areas before each reservation for intersection *///检查交集
                for ( ; ri >= 0; ri--) {
                        struct memblock_region *r = &rsv->regions[ri];
                        phys_addr_t r_start = ri ? r[-1].base + r[-1].size : 0;
                        phys_addr_t r_end = ri < rsv->cnt ? r->base : ULLONG_MAX;

                        /* if ri advanced past mi, break out to advance mi */
                        if (r_end <= m_start)
                                break;
                        /* if the two regions intersect, we're done */
                        if (m_end > r_start) {
                                if (out_start)
                                        *out_start = max(m_start, r_start);
                                if (out_end)
                                        *out_end = min(m_end, r_end);
                                if (out_nid)
                                        *out_nid = memblock_get_region_node(m);

                                if (m_start >= r_start)
                                        mi--;
                                else
                                        ri--;
                                *idx = (u32)mi | (u64)ri << 32;
                                return;
                        }
                }
        }

        *idx = ULLONG_MAX;
}
关于这个函数,哪个大哥可以指点一下么,谢谢了。
我怎么感觉返回的out_start  out_end正是memory和reserved之间交集的区域。



您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP