X86 head_32.S文件中内存映射详解(附图)
时间:2011-02-20
来源:互联网
本帖最后由 cluter 于 2011-02-20 22:29 编辑
Non-PAE模式:
在non-PAE模式下,x86系统采用2-level页表。
相关的宏定义如下:
在Pgtable-2level_types.h文件中
//页全局目录的掩码
#define PGDIR_SHIFT 22
//页全局目录1024项
#define PTRS_PER_PGD 1024
//页表1024项
#define PTRS_PER_PTE 1024
在Page_32_types.h文件中
//定义内核大小为512MB---只是限制内核最大512MB
#define KERNEL_IMAGE_SIZE (512 * 1024 * 1024)
代码分析:
1 相关的宏定义
//页表的大小=页数量 / 每个页表中页目录的个数
#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
//映射内核线性地址空间需要的内存大小
MAPPING_BEYOND_END = \
PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
//内核页数量==(内核的大小+映射内核线性地址空间的页表的大小) / 页大小
//可以看出这个是 worst-case 下需要的内核页数量
KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT
//INIT_MAP_SIZE=初始化的时候必须要映射的内存大小,也就是上面kernel_pages的大小
INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
//在brk段 预留名字为pagetables大小为INIT_MAP_SIZE的空间
RESERVE_BRK(pagetables, INIT_MAP_SIZE)
2 页表相关数据的内存分配
//为页全局目录(pgd)分配1024*4byte的内存空间
ENTRY(swapper_pg_dir)
.fill 1024,4,0
//为固定映射页表分配1024*4byte的内存空间
swapper_pg_fixmap:
.fill 1024,4,0
//分配一页并初始化为0
ENTRY(empty_zero_page)
.fill 4096,1,0
3 临时页表初始化代码
//内核线性地址开始的地方在pgd中的偏移位置
//__PAGE_OFFSET>>12>>10计算出在pgd中的页目录项index
//(__PAGE_OFFSET>>12>>10)<<2计算出偏移地址(因为每个页目录项4byte)
page_pde_offset = (__PAGE_OFFSET >> 20);
//把开始存放页表(page table)的物理地址写入edi
movl $pa(__brk_base), %edi
//把页全局目录(pgd)的物理地址写入edx
movl $pa(swapper_pg_dir), %edx
//把页表项(pte)属性写入eax
movl $PTE_IDENT_ATTR, %eax
10:
//创建一个页表项(地址+属性)
leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */
//把页表项存入页全局目录(pgd)
movl %ecx,(%edx) /* Store identity PDE entry */
movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */
//指向页全局目录的下一项
addl $4,%edx
//建立一个页表
movl $1024, %ecx
11:
//把eax中的内容(页地址+页属性)写入edi指向的物理地址,同时edi+4
stosl
addl $0x1000,%eax
loop 11b
//必须映射(KERNEL_IMAGE_SIZE+PAGE_TABLE_SIZE)大小的内存区域
movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
cmpl %ebp,%eax
//如果还没有映射到则继续
jb 10b
//把页表结束的线性地址写入_brk_end变量中--->safe location
addl $__PAGE_OFFSET, %edi
movl %edi, pa(_brk_end)
//把最大映射的页框数量写入max_pfn_mapped变量中
shrl $12, %eax
movl %eax, pa(max_pfn_mapped)
//把pgd中的最后一个页全局目录项(pgd entry)设置成固定内存映射(fixmap)项
movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
movl %eax,pa(swapper_pg_dir+0xffc)
Non-PAE模式:
在non-PAE模式下,x86系统采用2-level页表。
相关的宏定义如下:
在Pgtable-2level_types.h文件中
//页全局目录的掩码
#define PGDIR_SHIFT 22
//页全局目录1024项
#define PTRS_PER_PGD 1024
//页表1024项
#define PTRS_PER_PTE 1024
在Page_32_types.h文件中
//定义内核大小为512MB---只是限制内核最大512MB
#define KERNEL_IMAGE_SIZE (512 * 1024 * 1024)
代码分析:
1 相关的宏定义
//页表的大小=页数量 / 每个页表中页目录的个数
#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
//映射内核线性地址空间需要的内存大小
MAPPING_BEYOND_END = \
PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
//内核页数量==(内核的大小+映射内核线性地址空间的页表的大小) / 页大小
//可以看出这个是 worst-case 下需要的内核页数量
KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT
//INIT_MAP_SIZE=初始化的时候必须要映射的内存大小,也就是上面kernel_pages的大小
INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
//在brk段 预留名字为pagetables大小为INIT_MAP_SIZE的空间
RESERVE_BRK(pagetables, INIT_MAP_SIZE)
2 页表相关数据的内存分配
//为页全局目录(pgd)分配1024*4byte的内存空间
ENTRY(swapper_pg_dir)
.fill 1024,4,0
//为固定映射页表分配1024*4byte的内存空间
swapper_pg_fixmap:
.fill 1024,4,0
//分配一页并初始化为0
ENTRY(empty_zero_page)
.fill 4096,1,0
3 临时页表初始化代码
//内核线性地址开始的地方在pgd中的偏移位置
//__PAGE_OFFSET>>12>>10计算出在pgd中的页目录项index
//(__PAGE_OFFSET>>12>>10)<<2计算出偏移地址(因为每个页目录项4byte)
page_pde_offset = (__PAGE_OFFSET >> 20);
//把开始存放页表(page table)的物理地址写入edi
movl $pa(__brk_base), %edi
//把页全局目录(pgd)的物理地址写入edx
movl $pa(swapper_pg_dir), %edx
//把页表项(pte)属性写入eax
movl $PTE_IDENT_ATTR, %eax
10:
//创建一个页表项(地址+属性)
leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */
//把页表项存入页全局目录(pgd)
movl %ecx,(%edx) /* Store identity PDE entry */
movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */
//指向页全局目录的下一项
addl $4,%edx
//建立一个页表
movl $1024, %ecx
11:
//把eax中的内容(页地址+页属性)写入edi指向的物理地址,同时edi+4
stosl
addl $0x1000,%eax
loop 11b
//必须映射(KERNEL_IMAGE_SIZE+PAGE_TABLE_SIZE)大小的内存区域
movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
cmpl %ebp,%eax
//如果还没有映射到则继续
jb 10b
//把页表结束的线性地址写入_brk_end变量中--->safe location
addl $__PAGE_OFFSET, %edi
movl %edi, pa(_brk_end)
//把最大映射的页框数量写入max_pfn_mapped变量中
shrl $12, %eax
movl %eax, pa(max_pfn_mapped)
//把pgd中的最后一个页全局目录项(pgd entry)设置成固定内存映射(fixmap)项
movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
movl %eax,pa(swapper_pg_dir+0xffc)
临时内核映射.jpg (45.7 KB) |
作者: cluter 发布时间: 2011-02-20

作者: ww2000e 发布时间: 2011-02-20
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28