__cpu_setup。定义kernel\arch\arm64\mm\proc.S中。
#define MAIR(attr, mt)    ((attr) << ((mt) * 8))

/*
 *    __cpu_setup
 *
 *    Initialise the processor for turning the MMU on.  Return in x0 the
 *    value of the SCTLR_EL1 register.
 */
ENTRY(__cpu_setup)
    ic    iallu                // I+BTB cache invalidate // 使instruction和BTB cache中的所有的cache line是无效,直到PoU // BTB(Branch Target Buffer)
    tlbi    vmalle1is            // invalidate I + D TLBs // 使TLB内容无效vm-all-e1-is,vmall表示invalidate all TLB entry,e1表示EL1,is表示inner sharebility
    dsb    ish // dsb 数据同步屏蔽指令,确保前面的指令执行完成,ish表示inner shareable

mov    x0, #3 << 20
    msr    cpacr_el1, x0            // Enable FP/ASIMD // 使能SIMD and floating-point
    msr    mdscr_el1, xzr            // Reset mdscr_el1 // Monitor Debug System Control Register
    /*
     * Memory region attributes for LPAE:
     *
     *   n = AttrIndx[2:0] // 最重要的memory attributes指向MAIR_ELx中具体的memory attribute
     *            n    MAIR
     *   DEVICE_nGnRnE    000    00000000 // G:Gathering 表示对多个memory的访问是否可以合并
     *   DEVICE_nGnRE    001    00000100 // R: Re-ordering 表示是否允许处理器对内存访问指令进行重排
     *   DEVICE_GRE        010    00001100 // E: Early Write Acknowledgement
     *   NORMAL_NC        011    01000100 // 前面加n表示不允许
     *   NORMAL        100    11111111 // C: 表示是否cacheable
     */
    ldr    x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \
             MAIR(0x04, MT_DEVICE_nGnRE) | \
             MAIR(0x0c, MT_DEVICE_GRE) | \
             MAIR(0x44, MT_NORMAL_NC) | \
             MAIR(0xff, MT_NORMAL)
    msr    mair_el1, x5 // MAIR_EL1(Memory Attribute Indirection Register (EL1))
    /*
     * Prepare SCTLR
     */
    adr    x5, crval // crval的定义在底下
    ldp    w5, w6, [x5] // w5 = 0x000802c2 // w6 = 0x0405d03d
    mrs    x0, sctlr_el1 // System Control Register (EL1) // x0将作为传递给__enable_mmu时的参数
    bic    x0, x0, x5            // clear bits // 清0,0x000802c2中为1的位
    orr    x0, x0, x6            // set bits // 置1,0x0405d03d中为1的位
    /*
     * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for
     * both user and kernel.
     */
    ldr    x10, =TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \
            TCR_TG_FLAGS | TCR_ASID16 | TCR_TBI0 // ldr x10, 0xffffffc000d0ca38
    /*
     * Read the PARange bits from ID_AA64MMFR0_EL1 and set the IPS bits in
     * TCR_EL1.
     */
    mrs    x9, ID_AA64MMFR0_EL1
    bfi    x10, x9, #32, #3 // 将x9的[34:32]bit写入到x10的[34:32]bit
    msr    tcr_el1, x10
    ret                    // return to head.S // 由于lr保存的是__enable_mmu,因此返回到__enable_mmu函数继续执行
ENDPROC(__cpu_setup)

/*
     *                 n n            T
     *       U E      WT T UD     US IHBS
     *       CE0      XWHW CZ     ME TEEA S
     * .... .IEE .... NEAI TE.I ..AD DEN0 ACAM
     * 0011 0... 1101 ..0. ..0. 10.. .... .... < hardware reserved
     * .... .1.. .... 01.1 11.1 ..01 0001 1101 < software settings
     */
    .type    crval, #object
crval:
    .word    0x000802c2    // clear // SCTLR_EL1寄存器中需要清0的bit
    .word    0x0405d03d    // set // SCTLR_EL1寄存器中需要置1的bit

__enable_mmu。
/*
 * Setup common bits before finally enabling the MMU. Essentially this is just
 * loading the page table pointer and vector base registers.
 *
 * On entry to this code, x0 must contain the SCTLR_EL1 value for turning on
 * the MMU.
 */
// 要求x0中保存SCTLR_EL1的值
__enable_mmu:
    ldr    x5, =vectors // vectors:EL1状态的异常向量表 ,定义在kernel\arch\arm64\kernel\entry.S中
    msr    vbar_el1, x5 // VBAR_EL1 Vector Base Address Register (EL1),保存EL1状态的异常向量表。
    msr    ttbr0_el1, x25            // load TTBR0 // idmap_pg_dir 用于用户空间的进程,在进程切换的时候,其地址空间的切换实际就是修改TTBR0的值
    msr    ttbr1_el1, x26            // load TTBR1 // swapper_pg_dir 用于kernel space,所有的内核线程都是共享一个空间
    isb // 指令同步屏障
    b    __turn_mmu_on
ENDPROC(__enable_mmu)

.align    4
__turn_mmu_on:
    msr    sctlr_el1, x0 // 配置sctlr_el1,系统控制寄存器
    isb  // 指令同步屏障
    br    x27 // 跳转到__mmap_switched执行
ENDPROC(__turn_mmu_on)

__mmap_switched。
/*
 * The following fragment of code is executed with the MMU on in MMU mode, and
 * uses absolute addresses; this is not position independent.
 */
__mmap_switched:
    adr    x3, __switch_data + 8 // 跳过__mmap_switched

ldp    x6, x7, [x3], #16 // x6 = __bss_start // x7 = __bss_stop
1:    cmp    x6, x7
    b.hs    2f
    str    xzr, [x6], #8            // Clear BSS // 循环清除bss段,BSS段用来存放程序中未初始化的全局变量和静态变量
    b    1b
2:
    ldp    x4, x5, [x3], #16 // x4 = processor_id // x5 = __fdt_pointer
    ldr    x6, [x3], #8 // x6 = memstart_addr
    ldr    x16, [x3] // init_thread_union + THREAD_START_SP // sp // THREAD_START_SP = THREAD_SIZE - 16
    mov    sp, x16 // 跳转到c语言前,必须设置好栈
    str    x22, [x4]            // Save processor ID // 将x22保存的当前cpu id保存到processor_id(在kernel/arch/arm64 /kernel/setup.c中定义的 )中
    str    x21, [x5]            // Save FDT pointer // 将x21暂存的device tree的地址保存到__fdt_pointer(在kernel/arch/arm64 /kernel/setup.c中定义的)中
    str    x24, [x6]            // Save PHYS_OFFSET // 将x24保存的kernel起始的地址保存到memstart_addr(在kernel/arch/arm64/mm/init.c中定义的)中
    mov    x29, #0 // 将x29清0,还不清楚为什么要特别的做这一步

b    start_kernel // 长出一口气,终于到C语言了。
ENDPROC(__mmap_switched)

.align    3
    .type    __switch_data, %object
__switch_data:
    .quad    __mmap_switched
    .quad    __bss_start            // x6
    .quad    __bss_stop            // x7
    .quad    processor_id            // x4
    .quad    __fdt_pointer            // x5
    .quad    memstart_addr            // x6 // phys_addr_t memstart_addr __read_mostly = 0;
    .quad    init_thread_union + THREAD_START_SP // sp // init_thread_uniond定义在kernel/init/init_task.c中

#define THREAD_SIZE        16384
#define THREAD_START_SP        (THREAD_SIZE - 16)

// 进入start_kernel之前瞥一眼init_thread_union这个联合体和init_task这个结构体,这里我们只需知道init_task 是0号swapper进程的task_struct,esp指针指向这个init_thread_union以上(16384 - 16)作为0号swapper进程的栈顶
union thread_union init_thread_union __init_task_data =
    { INIT_THREAD_INFO(init_task) };

#define __init_task_data __attribute__((__section__(".data..init_task")))

--------------------- 
作者:xichangbao 
来源:CSDN 
原文:https://blog.csdn.net/xichangbao/article/details/51605462 
版权声明:本文为博主原创文章,转载请附上博文链接!

Kernel启动流程源码解析 2 head.S相关推荐

  1. Kernel启动流程源码解析 1 head.S

    bootloader在跳转到kernel前,需要确保如下设置: MMU = off, D-cache = off, I-cache = on or off x0 = physical address ...

  2. NioEventLoop启动流程源码解析

    NioEventLoop的启动时机是在服务端的NioServerSocketChannel中的ServerSocketChannel初始化完成,且注册在NioEventLoop后执行的, 下一步就是去 ...

  3. SpringSecurity启动流程源码解析

    前面两期我讲了SpringSecurity认证流程和SpringSecurity鉴权流程,今天是第三期,是SpringSecurity的收尾工作,讲SpringSecurity的启动流程. 就像很多电 ...

  4. Android Launcher启动应用程序流程源码解析

    带着问题看源码 点击桌面Launcher图标后做了哪些工作? 应用程序什么时候被创建的? Application和MainActivity的onCreate()方法什么时候被调用的? 概述 在Andr ...

  5. Doris FE启动流程源码详细解析

    Doris FE启动流程源码详细解析 一.简介 Apache Doris是一个现代化的MPP分析型数据库产品.仅需亚秒级响应时间即可获得查询结果,有效地支持实时数据分析.Apache Doris的分布 ...

  6. swoole 启动流程_EasySwoole 服务启动过程以及主体设计流程源码解析

    EasySwoole 服务启动过程以及主体设计流程源码解析 本文主要讲解EasySwoole 服务的启动过程,会通过源码片段讲解主体的设计流程 命令启动 当我们通过php easyswoole sta ...

  7. 云原生小课堂|Envoy请求流程源码解析(三):请求解析

    ​ 前言 Envoy 是一款面向 Service Mesh 的高性能网络代理服务.它与应用程序并行运行,通过以平台无关的方式提供通用功能来抽象网络.当基础架构中的所有服务流量都通过 Envoy 网格时 ...

  8. SpringBoot2 | SpringBoot启动流程源码分析(一)

    首页 博客 专栏·视频 下载 论坛 问答 代码 直播 能力认证 高校 会员中心 收藏 动态 消息 创作中心 SpringBoot2 | SpringBoot启动流程源码分析(一) 置顶 张书康 201 ...

  9. BroadcastReceiver的跨进程注册、接收流程源码解析

    根据<Activity跨进程启动流程源码探究>我们可以清楚以下几点: 1)Context的通用实现是在ContextIml这个类中 2)Activity的启动过程需要借助ActivityM ...

最新文章

  1. 5大步骤+10个案例,堪称SQL优化万能公式
  2. IIS HTTP 错误 404.17 - Not Found 解决方法
  3. FIREBIRD浅历
  4. jquery获取select选中的文本的值
  5. mysql数据库入门教程(12):变量讲解大全
  6. VTK:变形3D用法实战
  7. [Vue.js] 基础 -- 综合案例 -- 图书管理
  8. c/c++标准库中的文件操作总结
  9. ubuntu16.04安装wordpress
  10. Java continue的关键字
  11. 面向对象高级编程(5)-使用元类
  12. django 使用新的虚拟环境
  13. iphone-common-codes-ccteam源代码 CCCompile.h
  14. 基于OpenCV实现二值图细化,骨骼化并求出端点和交叉点
  15. 下载mooc视频字幕
  16. 超级实用Windows快捷键 程序员必备 Windows 快捷操作大全
  17. 手机运作html实现弹窗,html5实现手机弹窗留言对话框(摘)
  18. 计算机科学 杂志 撤稿,哈佛教授2篇顶刊遭撤稿:相同样品花样“复用”,伪装成不同实验结果...
  19. 各个浏览器对应的驱动文件 driver
  20. 【记录一次windows技术学习】使用笔记本DOS命令搭建WLAN热点

热门文章

  1. 华为65英寸智慧屏面板用的哪家屏幕
  2. @font-face 加载字体引用字体之后不起作用
  3. 随记 - 牛奶可乐经济学
  4. 转载不女人唯独你不可以平庸
  5. 翌加科技:抖音昵称如何取比较好
  6. 解决华为手机隐藏虚拟按键Activity被重新创建的问题
  7. 华为(HuaWei)虚拟按键的判断和监听
  8. 【期货龙虎榜分析】PVC沪铝价格靠近新高,短纤空头席位主动出击
  9. 花 40 多万开发的 App 扰乱了一场大选,几乎毁了一家公司
  10. css hover变成手_如何用CSS设置连接鼠标在上面是变成手型