linux 页表管理代码,Linux页表机制管理初始化

/*

* Setup the direct mapping of the physical memory at PAGE_OFFSET.

* This runs before bootmem is initialized and gets pages directly from

* the physical memory. To access them they are temporarily mapped.

*/

/*建立页表映射。对于高端内存的固定映射区没有映射到实际的页面,只是这种

机制的初步建立,页表存储的空间保留*/

unsignedlong__init_refok init_memory_mapping(unsignedlongstart,

unsignedlongend)

{

unsignedlongpage_size_mask = 0;

unsignedlongstart_pfn, end_pfn;

unsignedlongret = 0;

unsignedlongpos;

structmap_range mr[NR_RANGE_MR];

intnr_range, i;

intuse_pse, use_gbpages;

printk(KERN_INFO"init_memory_mapping: %016lx-%016lx\n", start, end);

#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)

/*

* For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.

* This will simplify cpa(), which otherwise needs to support splitting

* large pages into small in interrupt context, etc.

*/

use_pse = use_gbpages = 0;

#else

use_pse = cpu_has_pse;

use_gbpages = direct_gbpages;

#endif

//定义了X86_PAE模式后进行调用;

set_nx();

if(nx_enabled)

printk(KERN_INFO"NX (Execute Disable) protection: active\n");

/* Enable PSE if available */

if(cpu_has_pse)

set_in_cr4(X86_CR4_PSE);

/* Enable PGE if available */

if(cpu_has_pge) {

set_in_cr4(X86_CR4_PGE);

__supported_pte_mask |= _PAGE_GLOBAL;

}

/*page_size_mask在这里更新,在后面对设置页表时用到*/

if(use_gbpages)

page_size_mask |= 1 <

if(use_pse)

page_size_mask |= 1 <

memset(mr, 0,sizeof(mr));

nr_range = 0;

/* head if not big page alignment ? */

start_pfn = start >> PAGE_SHIFT;/*在setup函数中调用时,这里为0*/

pos = start_pfn <

#ifdef CONFIG_X86_32

/*

* Don't use a large page for the first 2/4MB of memory

* because there are often fixed size MTRRs in there

* and overlapping MTRRs into large pages can cause

* slowdowns.

*/

if(pos == 0)/*end_pfn的大小为1k,也就是4M大小的内存*/

end_pfn = 1<

else

end_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)

<

#else /* CONFIG_X86_64 */

end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)

<

#endif

if(end_pfn > (end >> PAGE_SHIFT))

end_pfn = end >> PAGE_SHIFT;

if(start_pfn 

nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);

pos = end_pfn <

}

/* big page (2M) range */

/*对齐到PMD,换算成页面的多少*/

start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)

<

#ifdef CONFIG_X86_32

/*这里的结束地址设置为调用的结束位页面数,也就是

所有的物理页面数*/

end_pfn = (end>>PMD_SHIFT) <

#else /* CONFIG_X86_64 */

end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)

<

if(end_pfn > ((end>>PMD_SHIFT)<

end_pfn = ((end>>PMD_SHIFT)<

#endif

if(start_pfn 

/*将这段内存放入mr中,保存后面用到*/

nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,

page_size_mask & (1<

仍然为4K页面(上面的按位或和这里的按位与)*/

pos = end_pfn <

}

#ifdef CONFIG_X86_64

/* big page (1G) range */

start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)

<

end_pfn = (end >> PUD_SHIFT) <

if(start_pfn 

nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,

page_size_mask &

((1<

pos = end_pfn <

}

/* tail is not big page (1G) alignment */

start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)

<

end_pfn = (end >> PMD_SHIFT) <

if(start_pfn 

nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,

page_size_mask & (1<

pos = end_pfn <

}

#endif

/* tail is not big page (2M) alignment */

start_pfn = pos>>PAGE_SHIFT;

end_pfn = end>>PAGE_SHIFT;

nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);

/* try to merge same page size and continuous */

/*合并相同页面大小的连续的页面*/

for(i = 0; nr_range > 1 && i 

unsignedlongold_start;

if(mr[i].end != mr[i+1].start ||

mr[i].page_size_mask != mr[i+1].page_size_mask)

continue;

/* move it */

old_start = mr[i].start;

memmove(&mr[i], &mr[i+1],

(nr_range - 1 - i) *sizeof(structmap_range));

mr[i--].start = old_start;

nr_range--;

}

/*打印相关的信息*/

for(i = 0; i 

printk(KERN_DEBUG" %010lx - %010lx page %s\n",

mr[i].start, mr[i].end,

(mr[i].page_size_mask & (1<

(mr[i].page_size_mask & (1<

/*

* Find space for the kernel direct mapping tables.

*

* Later we should allocate these tables in the local node of the

* memory mapped. Unfortunately this is done currently before the

* nodes are discovered.

*/

if(!after_bootmem)/*如果内存启动分配器没有建立,

这里是直接总e820.map中找到合适的连续内存*/

/*找到存放页表机制中页表的空间

首地址为e820_table_start*/

find_early_table_space(end, use_pse, use_gbpages);

#ifdef CONFIG_X86_32

/*设置页表映射,其中变量page_size_mask的值,

传入代换成了是否运用PSE来进行页表映射,

也就是说,当不用pse时,全部的物理页面都用

4K的形式映射,而运用PSE时,开始的4M用4K形式一个页面

后面的大块用2M形式作为一个页面映射;*/

for(i = 0; i 

kernel_physical_mapping_init(mr[i].start, mr[i].end,

mr[i].page_size_mask);

ret = end;

#else /* CONFIG_X86_64 */

for(i = 0; i 

ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,

mr[i].page_size_mask);

#endif

#ifdef CONFIG_X86_32

/*对高端内存区域的固定区域进行映射而建立了页表等,一般

高端固定内存区域为一个页表,具体的页面映射的建立需要set_fix函数*/

early_ioremap_page_table_range_init();

/*放入CR3寄存器*/

load_cr3(swapper_pg_dir);

#endif

#ifdef CONFIG_X86_64

if(!after_bootmem && !start) {

pud_t *pud;

pmd_t *pmd;

mmu_cr4_features = read_cr4();

/*

* _brk_end cannot change anymore, but it and _end may be

* located on different 2M pages. cleanup_highmap(), however,

* can only consider _end when it runs, so destroy any

* mappings beyond _brk_end here.

*/

pud = pud_offset(pgd_offset_k(_brk_end), _brk_end);

pmd = pmd_offset(pud, _brk_end - 1);

while(++pmd <= pmd_offset(pud, (unsignedlong)_end - 1))

pmd_clear(pmd);

}

#endif

/*因为将基址放到了CR3寄存器中,所以这里要对其寄存器

刷新,以表示将内容放到内存中*/

__flush_tlb_all();

/*将分配给建立页表机制的内存空间保留*/

if(!after_bootmem && e820_table_end > e820_table_start)

reserve_early(e820_table_start <

e820_table_end <

/*下面的函数需要设置相关的宏没有设置*/

if(!after_bootmem)

early_memtest(start, end);

returnret >> PAGE_SHIFT;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值