Linux 内核页表初始化
2018-02-07 10:31
411 查看
前面我们讨论了页描述符对象分配,以及初始化。接下来我们再来了解内核页表建立初始化处理。针对ARM64进行。start_kernel --> setup_arch --> paging_init()
void __init paging_init(void){ phys_addr_t pgd_phys = early_pgtable_alloc(); 分配页全局目录表地址
pgd_t *pgd = pgd_set_fixmap(pgd_phys);
map_kernel(pgd); 创建内核空间映射
map_mem(pgd); 对其他的一些bank块进行映射。
下面就是一些针对pgd进行设置。
/* * We want to reuse the original swapper_pg_dir so we don't have to * communicate the new address to non-coherent secondaries in * secondary_entry, and so cpu_switch_mm can generate the address with * adrp+add rather than a load from some global variable. * * To do this we need to go via a temporary pgd. */ cpu_replace_ttbr1(__va(pgd_phys)); memcpy(swapper_pg_dir, pgd, PAGE_SIZE); cpu_replace_ttbr1(swapper_pg_dir);
pgd_clear_fixmap(); memblock_free(pgd_phys, PAGE_SIZE);
/* * We only reuse the PGD from the swapper_pg_dir, not the pud + pmd * allocated with it. */ memblock_free(__pa(swapper_pg_dir) + PAGE_SIZE, SWAPPER_DIR_SIZE - PAGE_SIZE);}
static void __init map_kernel(pgd_t *pgd){ static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_init, vmlinux_data;
map_kernel_segment(pgd, _text, _etext, PAGE_KERNEL_EXEC, &vmlinux_text); map_kernel_segment(pgd, __start_rodata, __init_begin, PAGE_KERNEL, &vmlinux_rodata); map_kernel_segment(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC, &vmlinux_init); map_kernel_segment(pgd, _data, _end, PAGE_KERNEL, &vmlinux_data);
if (!pgd_val(*pgd_offset_raw(pgd, FIXADDR_START))) { /* * The fixmap falls in a separate pgd to the kernel, and doesn't * live in the carveout for the swapper_pg_dir. We can simply * re-use the existing dir for the fixmap. */ set_pgd(pgd_offset_raw(pgd, FIXADDR_START), *pgd_offset_k(FIXADDR_START)); } else if (CONFIG_PGTABLE_LEVELS > 3) { /* * The fixmap shares its top level pgd entry with the kernel * mapping. This can really only occur when we are running * with 16k/4 levels, so we can simply reuse the pud level * entry instead. */ BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES)); set_pud(pud_set_fixmap_offset(pgd, FIXADDR_START), __pud(__pa(bm_pmd) | PUD_TYPE_TABLE)); pud_clear_fixmap(); } else { BUG(); }
kasan_copy_shadow(pgd);}
static void __init map_mem(pgd_t *pgd){ struct memblock_region *reg;
/* map all the memory banks */ for_each_memblock(memory, reg) { phys_addr_t start = reg->base; phys_addr_t end = start + reg->size;
if (start >= end) break; if (memblock_is_nomap(reg)) continue;
__map_memblock(pgd, start, end); }}
相关文章推荐
- linux-3.2.36内核启动3-setup_arch中的内存初始化2(arm平台 分析建立页表)
- linux-3.2.36内核启动3-setup_arch中的内存初始化2(arm平台 分析建立页表)
- linux 内核 内存管理 初始化 页表
- Linux初始化内核临时页表之后的setup_memory函数
- linux-2.6.25启动分析(引导+内核初始化)
- LINUX内核和驱动中常见的 C语法---》标记化 初始化
- 《linux 内核完全剖析》 chapter 7 初始化程序
- 【Linux 内核网络协议栈源码剖析】系统网络协议栈初始化及数据传输通道建立过程
- Linux 0.11内核--硬盘初始化
- Linux 内核--硬件中断初始化及中断描述符表
- Linux2.6内核 -- 结构的初始化
- linux进程创建与守护;exec 进程内核页表建立
- Linux虚拟文件系统(内核初始化<二>)
- linux内核--进程任务结构化与初始化
- 学习Linux-4.12内核网路协议栈(1.5)——协议栈的初始化(inet_init主要数据结构)
- 转 嵌入式Linux内核时钟初始化问题
- linux内存源码分析 - 页表的初始化
- Linux内核代码之初始化内核临时页表---经典至极(FutureChen的日记)
- arm-linux内存管理学习笔记(2)-内核临时页表的建立
- linux进程创建与守护;exec 进程内核页表建立