作者

彭东林

pengdonglin137@163.com

平台

TQ2440

Qemu+vexpress-ca9

Linux-4.10.17

正文

继续分析head.S:

1     ldr    r13, =__mmap_switched        @ address to jump to after
2                         @ mmu has been enabled
3     badr    lr, 1f                @ return (PIC) address
4     mov    r8, r4                @ set TTBR1 to swapper_pg_dir
5     ldr    r12, [r10, #PROCINFO_INITFUNC]
6     add    r12, r12, r10
7     ret    r12
8 1:    b    __enable_mmu

第1行将__mmp_switched标号的虚拟地址赋给r13,后面从__turn_mmu_on返回时会用到

第3行将1f标号的物理地址赋给lr,后面从__arm920_setup返回时会用到

第4行将段式页表的物理起始地址赋给r8,对于TQ2440来说,是0x3000_4000,对于vexpress是0x6000_4000

第5行,因为r10指向匹配到的proc_info_list结构体的首地址,对于TQ2440来说,偏移#PROCINFO_INITFUNC得到的是__arm920_setup 与__arm920_proc_info的差值,存放到r12中,此时r10存放的就是__arm920_proc_info物理地址

第6行,r10加r12就得到了__arm920_setup的物理地址,对于vexpress来说是__v7_ca9mp_setup

第7行,开始执行__arm920_setup,定义在arch/arm/mm/proc-arm920.S中

 1     .type    __arm920_setup, #function
 2 __arm920_setup:
 3     mov    r0, #0
 4     mcr    p15, 0, r0, c7, c7        @ invalidate I,D caches on v4
 5     mcr    p15, 0, r0, c7, c10, 4        @ drain write buffer on v4
 6
 7     mcr    p15, 0, r0, c8, c7        @ invalidate I,D TLBs on v4
 8
 9     adr    r5, arm920_crval
10     ldmia    r5, {r5, r6}
11     mrc    p15, 0, r0, c1, c0        @ get control register v4
12     bic    r0, r0, r5
13     orr    r0, r0, r6
14     ret    lr
15     .size    __arm920_setup, . - __arm920_setup
16
17     /*
18      *  R
19      * .RVI ZFRS BLDP WCAM
20      * ..11 0001 ..11 0101
21      *
22      */
23     .type    arm920_crval, #object
24 arm920_crval:
25     crval    clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130

这个函数执行一些开启MMU之前的准备工作。上面对cache、tlb的操作可以参考手册 ARM920T Technical Reference Manual 的2.3.11 Register 7, cache operations register和2.3.12 Register 8, TLB operations register

第14行执行完毕后,会跳转到前面所说的head.S中的1f标号处,也就是   b __enable_mmu

关于MMU的操作,可以参考手册 ARM920T Technical Reference Manual 的2.3.5 Register 1, control register

回到head.S继续分析。

 1 __enable_mmu:
 2 #if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
 3     orr    r0, r0, #CR_A
 4 #else
 5     bic    r0, r0, #CR_A
 6 #endif
 7
 8     mov    r5, #DACR_INIT
 9     mcr    p15, 0, r5, c3, c0, 0        @ load domain access register
10     mcr    p15, 0, r4, c2, c0, 0        @ load page table pointer
11
12     b    __turn_mmu_on

第10行将段表的物理起始地址设置到CP15的C2寄存器中,即0x30004000或者0x60004000,可以参考ARM920T Technical Reference Manual 的2.3.6 Register 2, translation table base (TTB) register

第12行准备打开MMU

下面开始打开MMU:

 1     .align    5
 2     .pushsection    .idmap.text, "ax"
 3 ENTRY(__turn_mmu_on)
 4     mov    r0, r0
 5     instr_sync
 6     mcr    p15, 0, r0, c1, c0, 0        @ write control reg
 7     mrc    p15, 0, r3, c0, c0, 0        @ read id reg
 8     instr_sync
 9     mov    r3, r3
10     mov    r3, r13
11     ret    r3
12 __turn_mmu_on_end:
13 ENDPROC(__turn_mmu_on)
14     .popsection

第6行开启MMU, 由于之前已经建立了映射这部分的段表,所以程序可以继续执行,不会出错

第10行,r13中存放的是__mmap_switched的虚拟地址

第11行,开始跳到__mmap_switched处执行,自此以后的虚拟地址就跟链接地址相同了

__mmap_switched定义在arch/arm/kernel/head-common.S中:

 1 __mmap_switched:
 2     adr    r3, __mmap_switched_data
 3
 4     ldmia    r3!, {r4, r5, r6, r7}
 5     cmp    r4, r5                @ Copy data segment if needed
 6 1:    cmpne    r5, r6
 7     ldrne    fp, [r4], #4
 8     strne    fp, [r5], #4
 9     bne    1b
10
11     mov    fp, #0                @ Clear BSS (and zero fp)
12 1:    cmp    r6, r7
13     strcc    fp, [r6],#4
14     bcc    1b
15
16  ARM(    ldmia    r3, {r4, r5, r6, r7, sp})
17
18     str    r9, [r4]            @ Save processor ID
19     str    r1, [r5]            @ Save machine type
20     str    r2, [r6]            @ Save atags pointer
21     cmp    r7, #0
22     strne    r0, [r7]            @ Save control register values
23     b    start_kernel
24 ENDPROC(__mmap_switched)
25
26     .align    2
27     .type    __mmap_switched_data, %object
28 __mmap_switched_data:
29     .long    __data_loc            @ r4
30     .long    _sdata                @ r5
31     .long    __bss_start            @ r6
32     .long    _end                @ r7
33     .long    processor_id            @ r4
34     .long    __machine_arch_type        @ r5
35     .long    __atags_pointer            @ r6
36     .long    cr_alignment            @ r7
37     .long    init_thread_union + THREAD_START_SP @ sp
38     .size    __mmap_switched_data, . - __mmap_switched_data

这里主要关注一下第16到第23行,这里将r9中存放的CPU ID赋给processor_id, 将dtb所在的物理地址赋给__atags_pointer,将sp设置为init_thread_union + THREAD_START_SP, 这里init_thread_union定义在init/init_task.c中,THREAD_START_SP的值是(8KB-8),也就是sp指向init进程的内核栈。然后第23行跳转到init/main.c中的start_kernel。

完。

Linux内存管理学习3 —— head.S中的段页表的建立相关推荐

  1. 郝健: Linux内存管理学习笔记-第5节课

    前序文章: 郝健: Linux内存管理学习笔记-第1节课 郝健: Linux内存管理学习笔记-第2节课 郝健: Linux内存管理学习笔记-第3节课 郝健: Linux内存管理学习笔记-第4节课 摘要 ...

  2. 郝健: Linux内存管理学习笔记-第6节课

    前序文章: 郝健: Linux内存管理学习笔记-第1节课 郝健: Linux内存管理学习笔记-第2节课 郝健: Linux内存管理学习笔记-第3节课 郝健: Linux内存管理学习笔记-第4节课 郝健 ...

  3. 郝健: Linux内存管理学习笔记-第4节课

    前序文章: 郝健: Linux内存管理学习笔记-第1节课 郝健: Linux内存管理学习笔记-第2节课 郝健: Linux内存管理学习笔记-第3节课 摘要 page cache free命令的详细解释 ...

  4. Linux内存管理学习资料

    下面是Linux内存管理学习的一些资料. 博客 mlock() and mlockall() system calls. All about Linux swap space 逆向映射的演进 Linu ...

  5. Linux 内存管理 | 地址映射:分段、分页、段页

    文章目录 分段 分页 多级页表 快表(TLB) 段页式 Linux Linux 内存管理 | 物理内存管理:内存碎片.伙伴系统.slab分配器 Linux 内存管理 | 虚拟内存管理:虚拟内存空间.虚 ...

  6. 郝健: Linux内存管理学习笔记-第1节课【转】

    本文转载自:https://blog.csdn.net/juS3Ve/article/details/80035751 摘要 MMU与分页机制 内存区域(内存分ZONE) LinuxBuddy分配算法 ...

  7. 郝健: Linux内存管理学习笔记-第3节课

    摘要 进程的虚拟地址空间VMA(Virtual Memory Area) Pagefault的几种可能性.VMA的作用.major缺页和minor缺页 进程内存消耗的4个概念:vss.rss.pss和 ...

  8. 郝健: Linux内存管理学习笔记-第2节课

    摘要 slab./proc/slabinfo和slabtop 用户空间malloc/free.内核空间kmalloc/kfee与Buddy的关系 mallopt vmalloc Linux为应用程序分 ...

  9. 郝健: Linux内存管理学习笔记-第1节课

    摘要 MMU与分页机制 内存区域(内存分ZONE) LinuxBuddy分配算法 CMA(连续内存分配器) 0.    课前阅读 宋宝华:CPU是如何访问到内存的?--MMU最基本原理 http:// ...

最新文章

  1. 怎么用vc采集ni卡数据_智能水表读数怎么看?家用智能水表怎么安装?
  2. C#基础-类成员(Day7)
  3. 智能车竞赛接入工程训练竞赛相关事项-建议稿件
  4. android ADT学习总结
  5. tensorflow从入门到精通100讲(七)-TensorFlow房价预估使用Keras快速构建模型
  6. RecyclerView复杂适配器的终极形态?代码更解耦
  7. 哨兵机器人钢力士_还记得秒杀X战警的哨兵机器人吗?在漫威原著里,X战警更憋屈...
  8. OpenCV3实现人脸识别(三)——训练与识别自己的人脸数据
  9. Android判断网络连接是否可用【从新浪云搬运】
  10. 【BIM入门实战】Revit入门基础知识选择题带答案解析(116题)
  11. MySQL行锁 表锁理解
  12. java应用挂死故障排查
  13. 阅文集团、微软小冰赋生了100部网文主角,可养成...
  14. 8.10 NOIP模拟测试16 Blue+Weed+Drink
  15. mysql 字符串函数
  16. 史上最简单的 SpringCloud 教程
  17. Visual Leak Detector(vld)无法显示内存泄露行号
  18. 做运营活动的几点心得
  19. fragment android:onclick,Android Fragment的布局中使用android:onClick 属性时需要注意的问题...
  20. 资深架构师推荐Spring技术内幕:深入了解Spring的底层机制

热门文章

  1. 语义分割 DeepLabv3--Rethinking Atrous Convolution for Semantic Image Segmentation
  2. Flink并行度与Slot的关系
  3. java 摘要算法_Java实现消息摘要算法加密
  4. C++——Lambda函数
  5. 数学建模python和java_参加数学建模用 MATLAB,还是 Python?
  6. Swift 异常处理
  7. SqlTransaction——事务详解
  8. linux升级补丁tar,Linux内核升级补丁安装手册(一)
  9. 禁用java rmi_java-如何安全关闭rmi客户端?
  10. python平方数迭代器_对python中的高效迭代器函数详解