bootmem_init_node

static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)

in arch/arm/mm/init.c

1.1 根据内存信息重新映射页表,此处为低端内存的线性映射

  -->map_memory_bank(bank);

    -->create_mapping(&map);

      -->alloc_init_section(pgd, addr, next, phys, type);

        -->/*如果地址按SECTION对齐,只需一级页表,映射1MB空间*/

        /*如果地址不是SECTION对齐,需二级页表*/

        -->alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);

          /*最终调用的是proc_info_list->proc->set_pte_ext,汇编代码在arch/arm/mm/proc-macros.S*/

          -->set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)), 0);
map_memory_bank(bank)

1.2 Allocate the bootmem bitmap page

bootmem分配器用每一bit表示一个物理页框的使用情况,该函数计算表示所有的物理页框共需申请多少页的内存。

函数以总的物理页框数为输入参数,返回bitmap需要使用的页数。

/*

Convert a physical address to a Page Frame Number and back

#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
#define    __pfn_to_phys(pfn)    ((pfn) << PAGE_SHIFT)

end_pfn,start_pfn物理内存的起止页框号,

*/
/**
 * bootmem_bootmap_pages - calculate bitmap size in pages
 * @pages: number of pages the bitmap has to represent
 */
unsigned long __init bootmem_bootmap_pages(unsigned long pages)
{
    unsigned long bytes = bootmap_bytes(pages);

    return PAGE_ALIGN(bytes) >> PAGE_SHIFT;
}
static unsigned long __init bootmap_bytes(unsigned long pages)
{
    unsigned long bytes = (pages + 7) / 8;

    return ALIGN(bytes, sizeof(long));
}
bootmem_bootmap_pages

 1.3 boot_pfn = find_bootmap_pfn(node, mi, boot_pages);

寻找1.2中计算出的bitmap使用的若干页该对应到物理页框的什么位置。寻找的依据是从kernel的bss段结束位置开始寻找,找到能够放置bootmap_pages个页框的内存位置。

static unsigned int __init
find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages)
{
    unsigned int start_pfn, i, bootmap_pfn;

    start_pfn   = PAGE_ALIGN(__pa(_end)) >> PAGE_SHIFT;
    bootmap_pfn = 0;

    for_each_nodebank(i, mi, node) {
        struct membank *bank = &mi->bank[i];
        unsigned int start, end;

        start = bank_pfn_start(bank);
        end   = bank_pfn_end(bank);

        if (end < start_pfn)
            continue;

        if (start < start_pfn)
            start = start_pfn;

        if (end <= start)
            continue;

        if (end - start >= bootmap_pages) {
            bootmap_pfn = start;
            break;
        }
    }

    if (bootmap_pfn == 0)
        BUG();

    return bootmap_pfn;
}
find_bootmap_pfn

 1.4 init_bootmem_node

初始化pg_data_t->bdtat结构体,

将不同node的bdata添加到以bdata_list为首的链表。标记所有的bitmap位为1。

/*
 * node_bootmem_map is a map pointer - the bits represent all physical 
 * memory pages (including holes) on the node.
 */
typedef struct bootmem_data {
    unsigned long node_min_pfn;
    unsigned long node_low_pfn;
    void *node_bootmem_map;
    unsigned long last_end_off;
    unsigned long hint_idx;
    struct list_head list;
} bootmem_data_t;
/*
 * Called once to set up the allocator itself.
 */
static unsigned long __init init_bootmem_core(bootmem_data_t *bdata,
    unsigned long mapstart, unsigned long start, unsigned long end)
{
    unsigned long mapsize;

    mminit_validate_memmodel_limits(&start, &end);
    bdata->node_bootmem_map = phys_to_virt(PFN_PHYS(mapstart));
    bdata->node_min_pfn = start;
    bdata->node_low_pfn = end;
    link_bootmem(bdata);

    /*
     * Initially all pages are reserved - setup_arch() has to
     * register free RAM areas explicitly.
     */
    mapsize = bootmap_bytes(end - start);
    memset(bdata->node_bootmem_map, 0xff, mapsize);

    bdebug("nid=%td start=%lx map=%lx end=%lx mapsize=%lx\n",
        bdata - bootmem_node_data, start, mapstart, end, mapsize);

    return mapsize;
}

 init_bootmem_core
init_bootmem_core

1.5 free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));

把节点下所有的页框对应的bitmap位都设为0,标记为空闲。

这里最终调用bootmem底层的__free函数和__reserve函数。

static int __init mark_bootmem_node(bootmem_data_t *bdata,            unsigned long start, unsigned long end,int reserve, int flags)
{
    unsigned long sidx, eidx;

    bdebug("nid=%td start=%lx end=%lx reserve=%d flags=%x\n",
        bdata - bootmem_node_data, start, end, reserve, flags);

    BUG_ON(start < bdata->node_min_pfn);
    BUG_ON(end > bdata->node_low_pfn);

    sidx = start - bdata->node_min_pfn;
    eidx = end - bdata->node_min_pfn;

    if (reserve)
        return __reserve(bdata, sidx, eidx, flags);
    else
        __free(bdata, sidx, eidx);
    return 0;
}
static int __init __reserve(bootmem_data_t *bdata, unsigned long sidx,
            unsigned long eidx, int flags)
{
    unsigned long idx;
    int exclusive = flags & BOOTMEM_EXCLUSIVE;

    bdebug("nid=%td start=%lx end=%lx flags=%x\n",
        bdata - bootmem_node_data,
        sidx + bdata->node_min_pfn,
        eidx + bdata->node_min_pfn,
        flags);

    for (idx = sidx; idx < eidx; idx++)
        if (test_and_set_bit(idx, bdata->node_bootmem_map)) {
            if (exclusive) {
                __free(bdata, sidx, idx);
                return -EBUSY;
            }
            bdebug("silent double reserve of PFN %lx\n",
                idx + bdata->node_min_pfn);
        }
    return 0;
}
__reserve
static void __init __free(bootmem_data_t *bdata,
            unsigned long sidx, unsigned long eidx)
{
    unsigned long idx;

    bdebug("nid=%td start=%lx end=%lx\n", bdata - bootmem_node_data,
        sidx + bdata->node_min_pfn,
        eidx + bdata->node_min_pfn);

    if (bdata->hint_idx > sidx)
        bdata->hint_idx = sidx;

    for (idx = sidx; idx < eidx; idx++)
        if (!test_and_clear_bit(idx, bdata->node_bootmem_map))
            BUG();
}
__free

1.6 在bitmap中标记bitmap所占用的页框为使用状态

    /*
     * Reserve the bootmem bitmap for this node.
     */
    reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT,   boot_pages << PAGE_SHIFT, OOTMEM_DEFAULT);

 

posted @ 2018-08-11 21:59  bluebluebluesky  阅读(317)  评论(0编辑  收藏  举报