Linux内存管理学习3 —— head.S中的段页表的建立
作者
彭东林
pengdonglin137@163.com
平台
TQ2440
Qemu+vexpress-ca9
Linux-4.10.17
正文
继续分析head.S:
ldr r13, =__mmap_switched @ address to jump to after
@ mmu has been enabled
badr lr, 1f @ return (PIC) address
mov r8, r4 @ set TTBR1 to swapper_pg_dir
ldr r12, [r10, #PROCINFO_INITFUNC]
add r12, r12, r10
ret r12
: 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中
.type __arm920_setup, #function
__arm920_setup:
mov r0, #
mcr p15, , r0, c7, c7 @ invalidate I,D caches on v4
mcr p15, , r0, c7, c10, @ drain write buffer on v4 mcr p15, , r0, c8, c7 @ invalidate I,D TLBs on v4 adr r5, arm920_crval
ldmia r5, {r5, r6}
mrc p15, , r0, c1, c0 @ get control register v4
bic r0, r0, r5
orr r0, r0, r6
ret lr
.size __arm920_setup, . - __arm920_setup /*
* R
* .RVI ZFRS BLDP WCAM
* ..11 0001 ..11 0101
*
*/
.type arm920_crval, #object
arm920_crval:
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继续分析。
__enable_mmu:
#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
orr r0, r0, #CR_A
#else
bic r0, r0, #CR_A
#endif mov r5, #DACR_INIT
mcr p15, , r5, c3, c0, @ load domain access register
mcr p15, , r4, c2, c0, @ load page table pointer 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:
.align
.pushsection .idmap.text, "ax"
ENTRY(__turn_mmu_on)
mov r0, r0
instr_sync
mcr p15, , r0, c1, c0, @ write control reg
mrc p15, , r3, c0, c0, @ read id reg
instr_sync
mov r3, r3
mov r3, r13
ret r3
__turn_mmu_on_end:
ENDPROC(__turn_mmu_on)
.popsection
第6行开启MMU, 由于之前已经建立了映射这部分的段表,所以程序可以继续执行,不会出错
第10行,r13中存放的是__mmap_switched的虚拟地址
第11行,开始跳到__mmap_switched处执行,自此以后的虚拟地址就跟链接地址相同了
__mmap_switched定义在arch/arm/kernel/head-common.S中:
__mmap_switched:
adr r3, __mmap_switched_data ldmia r3!, {r4, r5, r6, r7}
cmp r4, r5 @ Copy data segment if needed
: cmpne r5, r6
ldrne fp, [r4], #
strne fp, [r5], #
bne 1b mov fp, # @ Clear BSS (and zero fp)
: cmp r6, r7
strcc fp, [r6],#
bcc 1b ARM( ldmia r3, {r4, r5, r6, r7, sp}) str r9, [r4] @ Save processor ID
str r1, [r5] @ Save machine type
str r2, [r6] @ Save atags pointer
cmp r7, #
strne r0, [r7] @ Save control register values
b start_kernel
ENDPROC(__mmap_switched) .align
.type __mmap_switched_data, %object
__mmap_switched_data:
.long __data_loc @ r4
.long _sdata @ r5
.long __bss_start @ r6
.long _end @ r7
.long processor_id @ r4
.long __machine_arch_type @ r5
.long __atags_pointer @ r6
.long cr_alignment @ r7
.long init_thread_union + THREAD_START_SP @ sp
.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中的段页表的建立的更多相关文章
- Linux内存管理学习1 —— head.S中的段页表的建立
作者 彭东林 pengdonglin137@163.com 平台 TQ2440 Qemu+vexpress-ca9 Linux-4.10.17 概述 在Linux自解压完毕后,开始执行arch/arm ...
- Linux内存管理学习2 —— head.S中的段页表的建立
作者 彭东林 pengdonglin137@163.com 平台 TQ2440 Qemu+vexpress-ca9 Linux-4.10.17 正文 继续分析head.S: 此时r2存放的是设备树镜像 ...
- Linux内存管理学习资料
下面是Linux内存管理学习的一些资料. 博客 mlock() and mlockall() system calls. All about Linux swap space 逆向映射的演进 Linu ...
- Linux内存管理学习笔记 转
https://yq.aliyun.com/articles/11192?spm=0.0.0.0.hq1MsD 随着要维护的服务器增多,遇到的各种稀奇古怪的问题也会增多,要想彻底解决这些“小”问题往往 ...
- Linux内存管理学习笔记——内存寻址
最近开始想稍微深入一点地学习Linux内核,主要参考内容是<深入理解Linux内核>和<深入理解Linux内核架构>以及源码,经验有限,只能分析出有限的内容,看完这遍以后再更深 ...
- 郝健: Linux内存管理学习笔记-第1节课【转】
本文转载自:https://blog.csdn.net/juS3Ve/article/details/80035751 摘要 MMU与分页机制 内存区域(内存分ZONE) LinuxBuddy分配算法 ...
- 郝健: Linux内存管理学习笔记-第2节课【转】
本文转载自:https://blog.csdn.net/juS3Ve/article/details/80035753 摘要 slab./proc/slabinfo和slabtop 用户空间mallo ...
- Linux内存管理学习笔记--物理内存分配
http://blog.chinaunix.net/uid-20321537-id-3466022.html
- C++内存管理学习笔记(7)
/****************************************************************/ /* 学习是合作和分享式的! /* Auth ...
随机推荐
- Mini Twitter
Implement a simple twitter. Support the following method: postTweet(user_id, tweet_text). Post a twe ...
- C++获取文件夹下所有文件名
查找文件需要一个结构体和几个函数.结构体为struct _finddata_t,函数为_findfirst.findnext和_findclose. struct _finddata_t 这个结构体是 ...
- Oracle ORA-12541:TNS:无监听程序
Oracle ORA-12541:TNS:无监听程序 标签: Oracle DataBase 今天使用Oracle数据库,使用可视化连接工具连接测试环境的数据库时提示无监听程序,最后在老师帮助下终于搞 ...
- [USACO17FEB]Why Did the Cow Cross the Road I G
一开始想写$DP$,发现直接转移完全有后效性 所以本小蒟蒻写了个最短路 每走三步就要吃草是这个题最难搞的地方,我们建图时不妨只对于距离等于三的点连边 考虑完全覆盖所有情况,从一个点走一步,两步,然后三 ...
- 在centos中修改yum源为阿里源
cd /etc/yum.repos.d 备份旧的配置文件:mv CentOS-Base.repo CentOS-Base.repo.bak 下载阿里源的文件: wget -O CentOS-Base. ...
- Ruby语言学习笔记
在codecademy上开始玩ruby了 1.数据类型:boolean,string,number 变量直接用即可,不用声明(“拿来主义”) 运算符:+ - * / ** % == != && ...
- PowerDesigner的安装
1.下载 2.步骤 3.效果 二:破解 1.参考文档 https://www.7down.com/soft/180716.html 2.说明 主要是一个文件,替换掉文件中的文件即可.
- 2013-2014 ACM-ICPC Brazil Subregional Programming Contest 题解
[题目链接] 这场比赛题面英文都好长... ... A - Zero or One 模拟. #include <bits/stdc++.h> using namespace std; in ...
- 模拟app端上传图片
使用插件模块管理模式: jsp页面: <sys:fileUpload fieldName="picList" contentId="true" value ...
- 使用<c:set>标签配置项目路径
写在前面的话: 在java项目中,路径的配置是一项最基础也是最必不可少的工作,最初我们配置路径是根据<%=request.getContextPath()%>这个java代码块进行配置的, ...