arm-linux内存管理学习笔记(2)-内核临时页表的建立

本文详细分析了ARM Linux内核启动初期临时内存页表的建立过程,探讨了页表更新的四个关键时机,并重点讨论了临时页表采用section-mapping时Linux如何填写页表项的控制位,以及临时页表映射的内核空间大小。此外,还解释了内核栈空间在临时页表中的映射情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习了arm内存页表的工作原理,接下来就开始咱们软件工程师的本职工作,对内核相关代码进行分析。内核代码那么复杂,该从哪里下手呢,想来想去。其实不管代码逻辑如何复杂,最终的落脚点都是在对页表项的操作上,那么内核是在什么时机会对页表项进行操作,如何操作?
对于一个页表项,抛开所有的软件复杂逻辑,操作无非就是2种吧。一是填写更新页表项,二是读取获取页表项。
MMU负责根据页表项进行虚实地址转换,因此读取获取页表项的工作是MMU硬件完成,软件是不参与的。内核代码的主体工作是来更新内存页表。页表更新的时机我的理解有4个:
(1)内核启动初期开启MMU阶段临时内存页表的建立
(2)start_kernel中完整的静态内存页表的建立
(3)内核空间中动态映射页表的建立,如vmalloc ioremap dma_alloc_coherent等
(4)用户空间访问虚拟地址时的缺页异常处理函数do_page_fault
由于内核空间的动态映射以及用户空间缺页异常处理中都涉及到了内存分配系统,放到后面再来分析,我们先来分析前2点。
并且除了第1点启动初期的临时页表是汇编中建立的外,其他3点无论其软件逻辑如何复杂,最终我们会看到都是调用了set_pte_ext来设置内存页表。

今天这篇文章先来分析临时内存页表的建立。
ARM在上电启动时MMU是关闭的,此时CPU访问的地址就是物理地址,并且在kernel之前的bootloader中也不会开启MMU,因此kernel开始运行时MMU是关闭的,这时kernel的运行地址与链接地址不一致。kernel是通过计算链接地址与运行地址的offset来对全局变量进行寻址的(对该过程感兴趣的朋友可以参考我另一篇分析内核启动过程的博文:http://blog.youkuaiyun.com/skyflying2012/article/details/41344377)。
这个痛苦的过程需要一直持续到MMU开启,当然在开启MMU之前需要将内存页表准备好,这个阶段kernel是建立了一个临时页表,完成了kernel_start到kernel_end的线性映射,这里页表映射采用的是section-mapping,内核代码在静态映射时更喜欢使用section-mapping,但是如果要映射地址不是1MB对齐,则使用page-mapping。这个在后面完整页表建立时还会有体现。
临时页表的建立以及为了完成开启MMU后地址的无缝过渡而建立的平映射,我在之前学习start_kernel之前页表建立的博文中有详细分析,地址如下:http://blog.youkuaiyun.com/skyflying2012/article/details/41447843
临时页表建立的逻辑在这篇博文中说的很详细了,今天就不说了,今天主要来分析下我对页表建立一些细节的疑问。

(1)临时页表采用section-mapping,那么在第一级页表项中除了高12位物理地址,linux对剩余20位的控制位如何填写

在start_kernel之前页表建立的博文中分析过,create_page_tables在填写页表前,会由proc_info_list结构体中获取__cpu_mm_mmu_flags,然后与物理地址相于,填写页表项,__cpu_mm_mmu_flags的值就是内核数据映射区的权限。
以公司的armv7处理器为例,proc_info_list结构体的获取与CPU ID相关,在kernel启动的__lookup_processor_type函数中进行获取,这部分的分析可以参考我的另一篇博文:http://blog.youkuaiyun.com/skyflying2012/article/details/48054417
根据CPU ID获取相应的proc_info_list结构体,armv7的结构体在./arch/arm/mm/proc-v7.S,如下:

.section ".proc.info.init", #alloc, #execinstr

    /*
     * Standard v7 proc info content
     */
.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0
    ALT_SMP(.long   PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
            PMD_SECT_AF | PMD_FLAGS_SMP | \mm_mmuflags)
    ALT_UP(.long    PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
            PMD_SECT_AF | PMD_FLAGS_UP | \mm_mmuflags)
    .long   PMD_TYPE_SECT | PMD_SECT_AP_WRITE | \
        PMD_SECT_AP_READ | PMD_SECT_AF | \io_mmuflags
    W(b)    \initfunc
    .long   cpu_arch_name
    .long   cpu_elf_name
    .long   HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | \
        HWCAP_EDSP | HWCAP_TLS | \hwcaps
    .long   cpu_v7_name
    .long   v7_processor_functions
    .long   v7wbi_tlb_fns
    .long   v6_user_fns
    .long   v7_cache_fns
.endm

#ifndef CONFIG_ARM_LPAE
    /*
     * ARM Ltd. Cortex A5 processor.
     */
    .type   __v7_ca5mp_proc_info, #object
__v7_ca5mp_proc_info:
    .long   0x410fc050
    .long   0xff0ffff0
    __v7_proc __v7_ca5mp_setup
    .size   __v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info

    /*
     * ARM Ltd. Cortex A9 processor.
     */
    .type   __v7_ca9mp_proc_info, #object
__v7_ca9mp_proc_info:
    .long   0x410fc090
    .long   0xff0ffff0
    __v7_proc __v7_ca9mp_setup
    .size   __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
#endif  /* CONFIG_ARM_LPAE */

    /*
     * ARM Ltd. Cortex A7 processor.
     */
    .type   __v7_ca7mp_proc_info, #object
__v7_ca7mp_proc_info:
    .long   0x410fc070
    .long   0xff0ffff0
    __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
    .size   __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
    /*
     * ARM Ltd. Cortex A15 processor.
     */
    .type   __v7_ca15mp_proc_info, #object
__v7_ca15mp_proc_info:
    .long   0x410fc0f0
    .long   0xff0ffff0
    __v7_pro
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值