2. 内核解压-关中断进入svc模式
内核解压的代码在arch/arm/boot/compressed/head.S
start:.type start,#function.rept 7__nop.endr
#ifndef CONFIG_THUMB2_KERNELmov r0, r0
#elseAR_CLASS( sub pc, pc, #3 ) @ A/R: switch to Thumb2 modeM_CLASS( nop.w ) @ M: already in Thumb2 mode .thumb
#endifW(b) 1f .word _magic_sig @ Magic numbers to help the loader.word _magic_start @ absolute load/run zImage address.word _magic_end @ zImage end address.word 0x04030201 @ endianness flag .word 0x45454545 @ another magic number to indicate.word _magic_table @ additional data table__EFI_HEADER
1:ARM_BE8( setend be ) @ go BE8 if compiled for BE8AR_CLASS( mrs r9, cpsr )
首先将start定义成函数类型
然后放置了7个nop指令,由于没有配置THUMB2,所以会有指令 mov r0, r0 等同nop
也就是说内核上来就执行了8个nop指令
注意这里的__nop是一个宏定义 arch/arm/boot/compressed/efi-header.S
.macro __nop
#ifdef CONFIG_EFI_STUB@ This is almost but not quite a NOP, since it does clobber the @ condition flags. But it is the best we can do for EFI, since@ PE/COFF expects the magic string "MZ" at offset 0, while the @ ARM/Linux boot protocol expects an executable instruction@ there..inst MZ_MAGIC | (0x1310 << 16) @ tstne r0, #0x4d000
#elseAR_CLASS( mov r0, r0 ) M_CLASS( nop.w )
#endif
平台是armv7A,所以上面就是8个 mov r0, r0指令
这里验证一下我们的猜想,首先看一个mov的机器码
其中cond的值如下
这样就可以知道mov r0, r0的机器码是 1110_0001_1010_0000_0000_0000_0000_0000 = 0xE1A00000
hexdump kernel/arch/arm/boot/zImage -n 64
0000000 0000 e1a0 0000 e1a0 0000 e1a0 0000 e1a0
*
0000020 0005 ea00 2818 016f 0000 0000 74c0 005c
0000030 0201 0403 4545 4545 3d40 0000 9000 e10f
对比压缩的内核镜像,可以看到确实如此,猜想没有问题
对于下面的.word其实也是可以看出来的,比如 _magic_sig = (0x016f2818);这个是vmlinux.lds中定义的,继续分析上面的数据
0000020 0005 ea00 <- W(b) 1f 2818 016f <- _magic_sig 0000 0000 <- _magic_start 74c0 005c <- _magic_end
0000030 0201 0403 <- 0x04030201 4545 4545 <- 0x45454545 3d40 0000 <- _magic_table 9000 e10f <- mrs r9, cpsr
cpsr寄存器如下
其中M bit
#ifdef CONFIG_ARM_VIRT_EXTbl __hyp_stub_install @ get into SVC mode, reversibly
#endif
这部分是虚拟化相关的,不了解
mov r7, r1 @ save architecture IDmov r8, r2 @ save atags pointer#ifndef CONFIG_CPU_V7M/** Booting from Angel - need to enter SVC mode and disable* FIQs/IRQs (numeric definitions from angel arm.h source).* We only do this if we were in user mode on entry.*/mrs r2, cpsr @ get current modetst r2, #3 @ not user?bne not_angelmov r0, #0x17 @ angel_SWIreason_EnterSVCARM( swi 0x123456 ) @ angel_SWI_ARMTHUMB( svc 0xab ) @ angel_SWI_THUMB
not_angel:safe_svcmode_maskall r0msr spsr_cxsf, r9 @ Save the CPU boot mode in@ SPSR
#endif
首先判断是不是用户模式,只要最低2个bit不是0,那么就不是user模式。
对于非user模式进入的则跳到not_angle,对于通过angle进来的则是user模式,用户模式直接调用swi进入svc模式。
这里的angle百度了一下,好像是arm的调试协议,这里忽略。
arch/arm/include/asm/assembler.h
.macro safe_svcmode_maskall reg:req
#if __LINUX_ARM_ARCH__ >= 6 && !defined(CONFIG_CPU_V7M)/* 读取cpsr的值 */mrs \reg , cpsr/* HYP_MODE值是0x1a * 异或之后,只有bit[0] bit[2]可能值为1 */eor \reg, \reg, #HYP_MODE/* #define MODE_MASK 0x0000001f* bit[4:0]]*//* 判断cpsr的低5bits值* 如果是0,则Z=1* 否则Z=0*/tst \reg, #MODE_MASK/* 低5bits清0 */bic \reg , \reg , #MODE_MASK/* #define PSR_I_BIT 0x00000080 * #define PSR_F_BIT 0x00000040* #define SVC_MODE 0x00000013* 或操作* 关闭FIQ IRQ 设置为SVC模式*/orr \reg , \reg , #PSR_I_BIT | PSR_F_BIT | SVC_MODETHUMB( orr \reg , \reg , #PSR_T_BIT ) /* bne跳转的条件是z==0 * 也就是说明进来的时候不是用户模式*/ bne 1f/* 禁止异步中止 *//* asynchronous abort来自外部memory system,* 源于bus上的一些错误,例如不可恢复的ECC error */orr \reg, \reg, #PSR_A_BIT/* badr是一个宏 调用的是adr指令* adr r0, _start 得到的是_start的当前执行位置,* 由 pc+offset 决定的 得到有效地址* ldr r0, =_start 得到的是绝对的地址,链接时决定;*//* 这里为什么要提前保存lr ? */badr lr, 2f/** c - control field mask byte(xPSR[7:0])* x - extension field mask byte(xPSR[15:8])* s - status field mask byte(xPSR[23:16)* f - flags field mask byte(xPSR[31:24]).* reg的值写到spsr中*/msr spsr_cxsf, \reg__MSR_ELR_HYP(14)__ERET
1: msr cpsr_c, \reg
2:
#else
/** workaround for possibly broken pre-v6 hardware* (akita, Sharp Zaurus C-1000, PXA270-based)*/setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, \reg
#endif
.endm
这章节有个疑惑,badr lr, 2f,为什么提前保存lr?
2. 内核解压-关中断进入svc模式相关推荐
- linux内核如何读写ddr,linux内核解压详解.doc
linux内核解压详解 Description: /*?OldLinux论坛 -- 有关早期Linux内核代码发展的论坛. 9!%83gY* ?linux/arch/arm/boot/compress ...
- Linux开机启动过程(5):内核解压
内核引导过程. Part 5. 内核解压 这是内核引导过程系列文章的第五部分.在前一部分我们看到了切换到64位模式的过程,在这一部分我们会从这里继续.我们会看到跳进内核代码的最后步骤:内核解压前的准备 ...
- 内核解压失败或【system halted】问题汇总
文章目录 1.内核解压失败 2.system halted 内核死机 1.内核解压失败 出现这种情况,一般主要体现在以下几个方面: uboot 环境变量 bootcmd 参数配置不正确.举例: 1.1 ...
- 3. 内核解压-确定解压信息
源码位置arch/arm/boot/compressed/head.S #ifdef CONFIG_AUTO_ZRELADDR/* * Find the start of physical memor ...
- linux 解压安卓内核,解压内核镜像
这里将告诉您解压内核镜像,教程操作步骤: 步骤 0 uboot 将 zImage 复制到内存之后,跳转到 zImage 处开始执行,首先执行的代码是 arch/arm/boot/compressed/ ...
- 【Linux 内核】编译 Linux 内核 ② ( 解压内核源码 | 查询当前 Linux 内核版本号 | 进入并查看 linux 内核源码目录 )
文章目录 一.解压内核源码 二.查询当前 Linux 内核版本号 三.进入并查看 linux 内核源码目录 一.解压内核源码 将 下载的 Linux 内核源码 linux-5.6.14.tar.gz ...
- ubuntu生成Linux内核解压,Ubuntu下生成linux内核
写在前面:由于老师所给的指导文档经过测试之后发现已经不太适用于现在ubuntu下面的实际操作情况(貌似这个是按照RED HAT下面的情况来写的),具体体现在一些指令不适用(mkinitrd),还有引导 ...
- 无法解压文件请重新启动计算机,为什么rar文件无法解压,显示数据错误,文
2008-10-03 你下载的之后出了一点问题于是损坏了也有个也许是资源虽然就有问题------昨天下载了一个将近一G的工具,在解压时,提示"CRC校验失败,文件被破坏",不毕竟再 ...
- C++ 项目实战:跨平台的文件与视频压缩解压工具的设计与实现
C++实战:跨平台文件与视频压缩解压工具的设计与实现 一.引言(Introduction) 1.1 项目背景与目标 1.2 技术选型:C++.FFmpeg.libarchive.libzip.Qt C ...
最新文章
- Selenium的简单操作
- ALV_GRID介绍
- Python 爬虫之 Beautiful Soup 模块使用指南
- BS的data-toggle/data-target
- 心动的本质是什么_《心动的信号3》:在“烟火气”里嗑糖,素人恋爱究竟有多上头?...
- Asp.net Ajax Control Toolkit设计编程备忘录(色眼窥观版)——第5回(错不了专辑)
- 《实现模式(修订版)》—第2章模式
- docker搭建单节点mongodb
- 54. Attribute isId 属性
- mysql 索引触发_mysql 添加索引后 在查询的时候怎么触发?
- [51nod]1284 2 3 5 7的倍数
- 服务器中硬盘JBOD模式和RAID0模式区别
- oracle 图片批量导入,【SQL】Oracle BLOB 批量导入导出图片到文件夹相关语句
- 总线收发器是干什么的_总线耦合器到底是做什么用的
- 七大顶级Linux桌面比较
- 齿轮标准模数c语言编程,齿轮标准模数可以使用( )表示
- 大四会计转码 初学c语言的心路历程
- 微软发布命令行神器,文件误删秒恢复
- Matlab基本函数-floor函数
- bio 生信博主网站 blog
热门文章
- matplotlib 画图刻度尺控制
- Windows10系统保留正版系统重装 与 热迁移系统
- Redis(3.2.3)集群部署实战
- redis可持续化存储的时候出现Can t save in background fork Cannot allocate memory
- [运算放大器]佛朗哥笔记 - 非线性电路 - 模拟开关
- 推荐系统的常用算法,选择,漫谈,推荐系统开源软件汇总
- 【Python爬虫】 爬取京东商品图片并下载
- Java的宝贝——反射
- 今日芯声 | 台积电或投资3000亿新台币建新工厂,进军高端封测服务
- 欢迎来到北工大换书网