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)), );
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的更多相关文章
- Uboot与Linux之间的参数传递
U-boot会给Linux Kernel传递很多参数,如:串口,RAM,videofb等.而Linux kernel也会读取和处理这些参数.两者之间通过struct tag来传递参数. U-boot把 ...
- linux内存管理初始化
内存管理子系统是linux内核最核心最重要的一部分,内核的其他部分都需要在内存管理子系统的基础上运行.而对其初始化是了解整个内存管理子系统的基础.对相关数据结构的初始化是从全局启动例程start_ke ...
- 内存管理 初始化(二)bootmem位图分配器建立 及 使用
本地的笔记有点长,先把bootmem位图分配器的建立 及 使用过程做下梳理. 都是代码,上面做了标注.开始的汇编部分省略了(涉及的内容不多,除了swapper_pg_dir的分配). 该记录不会再添 ...
- ARM Linux内核源码剖析索引
start_kernel -->asm-offset.h 生成 -->proc_info_list -->machine_desc -->__vet_atags --> ...
随机推荐
- 转 MySQL权限管理
###sample: #####view all userSELECT user, host from mysql.user;mysql> SELECT user, host from mysq ...
- Could not load file or assembly 'Oracle.ManagedDataAccessDTC.DLL' or one of its dependencies.
Could not load file or assembly 'Oracle.ManagedDataAccessDTC.DLL' or one of its dependencies. 不是有效的 ...
- Win7环境下配置FTP
1.打开 控制面板-->程序和功能-->打开或关闭Windows资源,在弹出的窗体里找到 “Internet信息服务”,展开后选择“Ftp服务器",然后点击"确定&qu ...
- c#基础2-out-ref
//out参数要求在方法的内部 ; JiangJin(ref salary1); Console.WriteLine(salary1); Console.ReadKey(); 必须为其赋值 out.r ...
- Kendo UI 初始化 Data 属性
初始化 Data 属性 前面在介绍准备 Kendo UI 开发环境时我们使用 jQuery 的方法将一个 HTML 元素转换成一个 Kendo UI 控制项: $(“#datepicker”).ke ...
- C语言中字符串数组的遍历和比较
/* The list of known types of default packet. */static char *_default_packet_types[] = { "d ...
- 使Win10用户获得特殊权限以便删除相应文件(夹)
依次访问: 本地用户和组(右击“此电脑”): 用户: 右击:当前用户名: 属性: 添加: 输入:System Managed Accounts Group: 检查名称(可选): 确定: 重启电脑. 参 ...
- SD Card Formatter for Mac Download
https://www.sdcard.org/downloads/formatter_4/eula_mac/ SDFormatter Mac版是一款Mac OS平台上的sd卡修复工具,SDFormat ...
- BCB:AnsiString BSTR WideString
WideString wstr;AnsiString astr;wchar_t *wp;//或者 BSTR wp; wp=wstr.c_bstr(); //WideString转化为BSTRwstr= ...
- 掉坑日志:Windows Native API与DPI缩放
高DPI显示器越来越普及,软件自然也要适应这个变化,最近实习的时候也遇到了一个关于DPI缩放的问题.因为内部框架的一个控件有BUG,会导致内容的显示出问题,后来实在没办法改成了用Windows Nat ...