当前位置: 首页 > news >正文

linux head-common.s分析(转)

供head.S调用,其中__mmap_switched的b start_kernel跳转到C执行,且永不返回。

跳转到start_kernel时寄存器值:

R0 = cp#15 control register

R1 = machine id

R2 = atags/dtb pointer

R9 = processor ID

 

stext->__enable_mmu->__turn_mmu_on->ldr pc, __mmap_switched
->__mmap_switched(head-common.S)
->b start_kernel(init/main.c)

http://blog.chinaunix.net/uid-20451980-id-1945242.html

Linux kernel分析(二)
注:本文为Stephen Du原创,转载请注明

  这里开始讲解head-common.S的内容。另,我的讲解顺序是按照源码的顺序来进行的而不是按照函数调用的顺序进行,所以读者要注意函数的入口以及返回地址。

 这里定义了atag数据的存放地址

 14 #define ATAG_CORE 0x54410001

 15 #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)

 这个部分head.S里面开启MMU后执行。此处开始准备执行C代码做准备:主要是text段,初始化数据段的定位!起始kernel本身的段结构跟普通进程大致相同,这也是为什么它被成文宏内核的原因!
 __data_loc是kernel的text段的开始
 __bss_start是__data_loc的结束也是bss段的开始

 

  从上图看得出,kernel必须将text段跟初始化数据段准备好,对于未初始化数据段跟stack段,heap段都是不需要进行准备的!只需要设置stack指针以及heap起始地址就好!因此到了22行后未出现stack跟heap段的定义!

 

 17         .type   __switch_data, %object

 18 __switch_data:

 19         .long   __mmap_switched

 20         .long   __data_loc                      @ r4

 21         .long   __data_start                    @ r5

 22         .long   __bss_start                     @ r6

 23         .long   _end                            @ r7
 该内存位置存储了处理器的id,也就是r4寄存器的内容,以防后面的代码丢弃r4的内容

 24         .long   processor_id                    @ r4
 该内存位置存储了machine type的信息也是放置r5的内容被丢弃

 25         .long   __machine_arch_type             @ r5
 该内存存储了atag的地址指针,同理防止r6被丢弃了

 26         .long   __atags_pointer                 @ r6

 27         .long   cr_alignment                    @ r7
 这个内存位置放置了kernel的stack & heap的内存位置信息以后,只要将pc pointer指向这里就能执行C代码了!

 28         .long   init_thread_union + THREAD_START_SP @ sp

 29 

 

 此前的代码可能在NOR flash中以XIP方式运行(其实Nand flash也可以XIP,只是有点技术障碍),但是kernel的代码不能总在flash内运行,该函数会进行kernel段的搬移以及处理!

 39         .type   __mmap_switched, %function

 40 __mmap_switched:
 

 41         adr     r3, __switch_data + 4   // r3 point to __mmap_switched本处的注释错误!r3指向__data_loc!

 将代码段,初始化数据段以及未初始化的数据段地址分别加载进入r4~r7

 43         ldmia   r3!, {r4, r5, r6, r7}   // load the function's addr into r4~r7;r3 point to processor_id
 此处比较难以理解,r4=__data_loc是物理上段的存储位置(可能在flash中而不是在RAM中);r5=_data_start是数据在内存的地址,如果二者相等说明已经在RAM中不必做copy,如果不在RAM中则执行copy使之在内存中运行!

 44         cmp     r4, r5                  // Copy data segment if needed __data_start is the destination and __data_loc is the src!

 copy相关操作

 45 1:      cmpne   r5, r6                  // if __data_start and __data_loc is not the same start the transfer session

 46         ldrne   fp, [r4], #4

 47         strne   fp, [r5], #4

 48         bne     1b

 
 清空未初始化数据段,为执行C代码扫清障碍

 50         mov     fp, #0                          @ Clear BSS (and zero fp)

 51 1:      cmp     r6, r7

 52         strcc   fp, [r6],#4

 53         bcc     1b


 执行保存操作。此处最重要的是sp指针的加载!该语句后sp已经指向了kernel的stack上,执行C代码的条件就绪了(代码段ok,初始化数据段ok,未初始化数据段ok,stack ok)

 55         ldmia   r3, {r4, r5, r6, r7, sp}

 56         str     r9, [r4]                        @ Save processor ID

 57         str     r1, [r5]                        @ Save machine type

 58         str     r2, [r6]                        @ Save atags pointer

 59         bic     r4, r0, #CR_A                   @ Clear 'A' bit

 60         stmia   r7, {r0, r4}                    @ Save control register values

 61                                                 @Now we will enter the world of C code and the MMU is on now!

 62         b       entry_for_C_call

 63         //b     start_kernel                    @For ARM start_kernel is defined in the init/main.c we will never return from start_kernel at all

144 

145 /*

146  * Read processor ID register (CP#15, CR0), and look up in the linker-built

147  * supported processor list.  Note that we can't use the absolute addresses

148  * for the __proc_info lists since we aren't running with the MMU on

149  * (and therefore, we are not in the correct address space).  We have to

150  * calculate the offset.

151  *

152  *      r9 = cpuid

153  * Returns:

154  *      r3, r4, r6 corrupted

155  *      r5 = proc_info pointer in physical address space

156  *      r9 = cpuid (preserved)

157  */

158         .type   __lookup_processor_type, %function

159 __lookup_processor_type:

160         adr     r3, 3f

161         ldmda   r3, {r5 - r7}

162         sub     r3, r3, r7                      @ get offset between virt&phys

163         add     r5, r5, r3                      @ convert virt addresses to

164         add     r6, r6, r3                      @ physical address space

165 1:      ldmia   r5, {r3, r4}                    @ value, mask

166         and     r4, r4, r9                      @ mask wanted bits

167         teq     r3, r4

168         beq     2f

169         add     r5, r5, #PROC_INFO_SZ           @ sizeof(proc_info_list)

170         cmp     r5, r6

171         blo     1b

172         mov     r5, #0                          @ unknown processor

173 2:      mov     pc, lr

174 

175 /*

176  * This provides a C-API version of the above function.

177  */

178 ENTRY(lookup_processor_type)

179         stmfd   sp!, {r4 - r7, r9, lr}

180         mov     r9, r0

181         bl      __lookup_processor_type

182         mov     r0, r5

183         ldmfd   sp!, {r4 - r7, r9, pc}

184 

185 /*

186  * Look in and arch/arm/kernel/arch.[ch] for

187  * more information about the __proc_info and __arch_info structures.

188  */

189         .long   __proc_info_begin

190         .long   __proc_info_end

191 3:      .long   .

192         .long   __arch_info_begin

193         .long   __arch_info_end

194 

195 /*

196  * Lookup machine architecture in the linker-build list of architectures.

197  * Note that we can't use the absolute addresses for the __arch_info

198  * lists since we aren't running with the MMU on (and therefore, we are

199  * not in the correct address space).  We have to calculate the offset.

200  *

201  *  r1 = machine architecture number

202  * Returns:

203  *  r3, r4, r6 corrupted

204  *  r5 = mach_info pointer in physical address space

205  */

206         .type   __lookup_machine_type, %function

207 __lookup_machine_type:

208         adr     r3, 3b

209         ldmia   r3, {r4, r5, r6}

210         sub     r3, r3, r4                      @ get offset between virt&phys

211         add     r5, r5, r3                      @ convert virt addresses to

212         add     r6, r6, r3                      @ physical address space

213 1:      ldr     r3, [r5, #MACHINFO_TYPE]        @ get machine type

214         teq     r3, r1                          @ matches loader number?

215         beq     2f                              @ found

216         add     r5, r5, #SIZEOF_MACHINE_DESC    @ next machine_desc

217         cmp     r5, r6

218         blo     1b

219         mov     r5, #0                          @ unknown machine

220 2:      mov     pc, lr

221 

222 /*

223  * This provides a C-API version of the above function.

224  */

225 ENTRY(lookup_machine_type)

226         stmfd   sp!, {r4 - r6, lr}

227         mov     r1, r0

228         bl      __lookup_machine_type

229         mov     r0, r5

230         ldmfd   sp!, {r4 - r6, pc}

231 

232 /* Determine validity of the r2 atags pointer.  The heuristic requires

233  * that the pointer be aligned, in the first 16k of physical RAM and

234  * that the ATAG_CORE marker is first and present.  Future revisions

235  * of this function may be more lenient with the physical address and

236  * may also be able to move the ATAGS block if necessary.

237  *

238  * r8  = machinfo

239  *

240  * Returns:

241  *  r2 either valid atags pointer, or zero

242  *  r5, r6 corrupted

243  */

244 

245         .type   __vet_atags, %function

246 __vet_atags:

247         tst     r2, #0x3                        @ aligned?

248         bne     1f

249 

250         ldr     r5, [r2, #0]                    @ is first tag ATAG_CORE?

251         subs    r5, r5, #ATAG_CORE_SIZE

252         bne     1f

253         ldr     r5, [r2, #4]

254         ldr     r6, =ATAG_CORE

255         cmp     r5, r6

256         bne     1f

257 

258         mov     pc, lr                          @ atag pointer is ok

259 

260 1:      mov     r2, #0

261         mov     pc, lr

 

相关文章:

  • 使opensuse界面不显示中文
  • echo
  • python学习笔记(六)之集合1
  • 转java中静态方法和非静态方法的存储
  • 五周第二次课(11月14日) 7.6 yum更换国内源 7.7 yum下载rpm包 7.8/7.9 源码包安装...
  • Android样式的开发:Style篇
  • npm-folders
  • Android怎么使用字体图标 自定义FontTextView字体图标控件-- 使用方法
  • JAVA 设计模式 模板方法模式
  • C++primer 9.49
  • springmvc学习笔记--json--返回json的日期格式问题
  • 在php中,如何将一个页面中的标签,替换为用户想输出的内容
  • docker常用命令
  • Java 反射 ParameterizedType 参数化类型
  • 基于jQuery的下拉菜单插件,诸位上眼!!!
  • 4个实用的微服务测试策略
  • idea + plantuml 画流程图
  • IDEA 插件开发入门教程
  • Java反射-动态类加载和重新加载
  • JS基础之数据类型、对象、原型、原型链、继承
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • React Native移动开发实战-3-实现页面间的数据传递
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 给新手的新浪微博 SDK 集成教程【一】
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 记录一下第一次使用npm
  • 技术:超级实用的电脑小技巧
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 深度学习中的信息论知识详解
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 通信类
  • 小李飞刀:SQL题目刷起来!
  • 一个JAVA程序员成长之路分享
  • 一天一个设计模式之JS实现——适配器模式
  • 在Mac OS X上安装 Ruby运行环境
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​第20课 在Android Native开发中加入新的C++类
  • !!java web学习笔记(一到五)
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (6)STL算法之转换
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (二)c52学习之旅-简单了解单片机
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (南京观海微电子)——COF介绍
  • (十八)SpringBoot之发送QQ邮件
  • (一) springboot详细介绍
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net FrameWork简介,数组,枚举
  • .Net Memory Profiler的使用举例
  • .NET MVC第三章、三种传值方式
  • .Net Web项目创建比较不错的参考文章
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .net中生成excel后调整宽度