• 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
    ",
            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
    ",
            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
    ",
            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
    ",
                    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
    ", 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);
  • 相关阅读:
    logging模块
    获得本机时间
    为了节约一台打印机,我也是无奈呀~~~~
    django通过管理页上传图片
    python打印爱心
    djago后台管理页面
    今天休年休找不到填年休的表了,结果就写了一个查找文件的缩引存起来方便下次用
    中间件调用顺序_______网站仿问过程
    django中间件
    py3.8安装
  • 原文地址:https://www.cnblogs.com/yangjiguang/p/9461274.html
Copyright © 2020-2023  润新知