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)), );

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 + ) / ; 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 = ; 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 == )
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 ;
}
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 ;
}

__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);

bootmem_init_node的更多相关文章

  1. Uboot与Linux之间的参数传递

    U-boot会给Linux Kernel传递很多参数,如:串口,RAM,videofb等.而Linux kernel也会读取和处理这些参数.两者之间通过struct tag来传递参数. U-boot把 ...

  2. linux内存管理初始化

    内存管理子系统是linux内核最核心最重要的一部分,内核的其他部分都需要在内存管理子系统的基础上运行.而对其初始化是了解整个内存管理子系统的基础.对相关数据结构的初始化是从全局启动例程start_ke ...

  3. 内存管理 初始化(二)bootmem位图分配器建立 及 使用

    本地的笔记有点长,先把bootmem位图分配器的建立 及  使用过程做下梳理. 都是代码,上面做了标注.开始的汇编部分省略了(涉及的内容不多,除了swapper_pg_dir的分配). 该记录不会再添 ...

  4. ARM Linux内核源码剖析索引

    start_kernel -->asm-offset.h 生成 -->proc_info_list   -->machine_desc -->__vet_atags --> ...

随机推荐

  1. FirstAFNetWorking

    // ViewController.h // FirstAFNetWorking // // Created by 张国锋 on 15/7/20. // Copyright (c) 2015年 张国锋 ...

  2. 开发中遇到的Cause: java.sql.SQLException: connection holder is null的异常

    异常的出现是属于获取连接超时,从而找不到持有者. 项目中的配置体现: <property name="removeAbandoned" value="true&qu ...

  3. BZOJ 1137: [POI2009]Wsp 岛屿 半平面交

    1137: [POI2009]Wsp 岛屿 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 165  Solved: ...

  4. Html.Action Html.RenderAction Html.Partial Html.RenderPartial Url.Action Html.ActionLink 大括号和小括号区别

    在查阅了一些资料后,结论如下: Action 是以mvchtmlstring的方式返回一个结果,RenderAction 无返回值,速度上action慢于RenderAction partial和Re ...

  5. UVA 1615 Highway 高速公路 (区间选点)

    题意:在一条线段上选出尽量少的点,使得和所有给出的n个点距离不超过D. 分别计算出每个点在线段的满足条件的区间,然后就转化成了区间选点的问题了,按照右端点排序,相同时按照左端点排序,按照之前的排序一定 ...

  6. self & this 上下文

    对象:指向对象的首地址: 函数:代表了函数运行的主要上下文: 内部:在类的内部使用. self Within the body of a class method, self refers to th ...

  7. 棋盘问题——POJ1321

    棋盘问题——深度优先搜索 题目描述: 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘 ...

  8. 谷歌浏览器 加安全地址 快捷方式加参数 chrome

    --unsafely-treat-insecure-origin-as-secure="http://192.168.43.17:8080"

  9. python 列表 字典转json

    一.Dictionary 转为JSON 将dict转为JSON,这里利用包json import jsonaItem = {}aItem["id"] = "2203&qu ...

  10. String中关于BeanFactory

    org.springframework.beans及org.springframework.context包是Spring IoC容器的基础.BeanFactory提供的高级配置机制,使得管理任何性质 ...