共计 1860 个字符,预计需要花费 5 分钟才能阅读完成。
“各位小伙伴,我是小笨叔,从明天开始,笨叔尽量每天给大家分享一点点小东西,可能是笨笨的小点滴,就像小雨点一样,它会缓缓会合到大江大海!”
前两天有一个两个小伙伴探讨这么一个问题。
A : 在 do_page_fault 函数中有这样一段代码,这都是在内核中的代码了为什么还要判断是在内核态还是在用户态?解决异样时必定是在内核态吧?
if (!user_mode(regs))
goto no_context;
B:内核常驻内存,不会缺页,相同,用户态内存有可能会产生缺页,进入内核的异样解决流程入口执行异样解决,没感觉有什么不妥,缺页不肯定是在内核态,这个假如错的。
A:既然这样的话,那么内核的代码永远不会产生缺页中断了。只能是用户过程产生缺页中断了。
A 同学持续说。
A:当产生异样时,arm 的状态就会发生变化,此时不会是用户态的。arm 不是有 7 种工作模式吗?
cpsr 寄存器的低四位都为 0 的话,阐明是用户模式,产生异样时有相应的异样模式,然而必定不会是用户模式,所以我感觉内核代码中
if (user_mode(regs))
这条语句永远不会成立,
define user_mode(regs) \
(((regs)->ARM_cpsr & 0xf) == 0)
从它的实现来看,就是判断最低 4 位是否为 0,显然在异样模式下,不可能为 0 的
下面是 A 同学和 B 同学的对话,你们感觉他们探讨的货色都对吗?
图片
01 对于异样
—
咱们了解的 CPU 不就是干两件事件嘛?一个是取指令,另外一个是把指令给执行了。就好比我家小朋友,她名字叫做小笨笨。我和她说,小笨笨,你去冰箱里帮爸爸拿一罐可乐。小朋友第一件事件,就是要听到我说的话,这个就是取指令,她听懂了之后,她可能有如下几个行为。
1. 她去冰箱给我拿了一罐可乐给我
2. 她走去冰箱那里,然而中途遇到妈妈,妈妈逗她玩了一会,她去厨房给我拿了一个苹果
3. 耍赖,跑了
下面三种状况,就是 CPU 的三种状况,第一个是 CPU 失常执行了这条命令,第二种状况,正在执行这条指令的时候,中途遇到问题了,后果产生谬误了。第三条,几乎就是一条非法指令。
对于 ARM 处理器来说,反对 4 大类的异样。
1. 中断(interrupt)。就是咱们平时了解的中断,次要由外设触发,是典型的异步异样。ARM 中次要包含两种类型的中断:IRQ(一般中断) 和 FIQ。2. 异样(aborts)可能是同步或异步异样。包含指令异样 (取指令时产生)、数据异样 (读写内存数据时产生),能够由 MMU 产生 (比方典型的缺页异样),也能够由内部存储系统产生 (通常是硬件问题)。3. 复位(reset)复位被视为一种非凡的异样。4. 异样指令。由异样触发指令触发的异样,比方 Supervisor Call (SVC)、Hypervisor Call (HVC)、Secure monitor Call (SMC),SWI 等
那么 ARM 处理器在产生异样之后,通常会有一个异样向量表来和软件进行交互,因为异样产生了,处理器本人解决不了,须要操作系统或者软件来参加。上面这张图就是 ARM 手册上的列出来的异样向量表。
这张图是比较简单的明了的 vector table。
通常异样产生之后,ARM 处理器会帮咱们做一些事件,这些事件是硬件帮忙咱们做的:
- 把下一条指令的地址(返回地址)保留到新处理器模式的 LR 寄存器
- 把 cpsr 保留到 spsr 中
- 设置适当的 cpsr(扭转处理器的 ARM 状态、扭转处理器进入相应的异样模式、(视状况)扭转中断禁止位禁止相应中断)
- 设置 PC 指向异样向量表中对应的中央
那么软件须要做些啥呢???
-
保留以后共用寄存器的值,(如 SVC 模式和 IRQ 模式共用 r0~r12 以及 r15 及 pc)到以后模式的栈内存。保障之前模式的值不被毁坏。
-
进入异样处理函数。解决异样。
- 中断返回,将之前保留到栈里的值读回,并 SPSR 的值赋值给 CPSR 实现被动切换到之前的模式
-
02
—
所以回到方才那个同学的探讨,当执行到 do_page_fault 时,这时候曾经是在 SVC 模式,也就是内核模式,然而产生异样的那个工夫点,有可能是在用户模式也可能是在内核模式,所以,在 do_page_fault 时,数据结构 struct pt_regs 保留的是 产生异样现场时候的寄存器上下文,而不是 do_page_fault 以后的寄存器的状态,比方 CPSR。
留神这里 do_page_fault 函数里的第三个参数 regs, 不要被 regs 的名字蛊惑了,尽管她长得难看,然而不是示意以后这个工夫点的 寄存器的状态哟。
struct pt_regs 数据结构定义如下。
最初记得关注笨叔的 奔跑吧 Linux 社区哟!