投稿说明 bitsCN.com > 网络技术 > 安全防护 >
windowsCE异常和中断服务程序初探
windowsCE异常和中断[URL=http://www.heibai.net]服务[/URL]程序初探(-)
---------by
nasiry 转载请说明出处
1。中断/异常相量的装入和执行方式。
中断和异常都是异步发生的事件,当该事件发生,系统将停止目前正在执行的代码转而执行事件响应的[URL=http://www.heibai.net]服务[/URL]程序。而事件[URL=http://www.heibai.net]服务[/URL]程序的入口点就是中断/异常向量所在的位置。arm的中断向量可以是0x0开始的低地址向量,也可以是在FFFF0000位置的高向量地址。winCE下使用高地址作为trap区,所以在CE下arm使用高地址向量。下面我们来了解一下中断/异常向量的安装和执行过程。
在kernelStart的过程中通过程序将如下代码复制到ffff0000的位置.
VectorInstructions
ldr pc, [pc,
#0x3E0-8] ; reset
ldr pc, [pc,
#0x3E0-8] ; undefined
instruction
ldr pc, [pc,
#0x3E0-8] ; SVC
ldr pc, [pc,
#0x3E0-8] ; Prefetch abort
ldr pc, [pc,
#0x3E0-8] ; data abort
ldr pc, [pc,
#0x3E0-8] ; unused vector
location
ldr pc, [pc,
#0x3E0-8] ; IRQ
ldr pc, [pc,
#0x3E0-8] ; FIQ
而在ffff03e0的位置放上如下的[URL=http://www.heibai.net]数据[/URL],每一项(32bit)对应一个异常的跳转地址也就是winCE的异常/中断向量跳转表。该表项的内容就是发生异常后将要执行的[URL=http://www.heibai.net]服务[/URL]程序的入口地址。具体如下。
VectorTable
DCD
-1
; reset
DCD
UndefException
; undefined instruction
DCD
SWIHandler
; SVC
DCD
PrefetchAbort
; Prefetch abort
IF :DEF:ARMV4T :LOR: :DEF:ARMV4I
DCD
OEMDataAbortHandler ; data abort
ELSE
DCD
DataAbortHandler ;
data abort
ENDIF
DCD
-1
; unused vector
DCD
IRQHandler
; IRQ
DCD
FIQHandler
; FIQ
在上面的这些代码/[URL=http://www.heibai.net]数据[/URL]在内存空间上按照上述要求放置好以后,每次触发一个异常就[URL=http://www.heibai.net]自动[/URL]运行到相应跳转表项所对应的地址执行。
2.异常/中断[URL=http://www.heibai.net]服务[/URL]程序
在arm下,由于有7种异常状态包括reset、Undef exception、software interrupt(swi)、Prefech
Abort、DataAbort、IRQ、FIQ七种异常/中断。reset仅在复位时发生,其他6种都是在系统运行时发生。当任何一个异常发生并得到响应时,ARM
内核[URL=http://www.heibai.net]自动[/URL]完成以下动作:
拷贝
CPSR 到 SPSR_
设置适当的 CPSR 位:
改变处理器状态进入 ARM 状态
改变处理器模式进入相应的异常模式
设置中断禁止位禁止相应中断
更新 LR_
设置 PC 到相应的异常向量
同时不管异常发生在ARM 还是Thumb 状态下,处理器都将[URL=http://www.heibai.net]自动[/URL]进入ARM 状态。并且中断使能会[URL=http://www.heibai.net]自动[/URL]被关闭。在这个时候由于部分通用寄存器是不同模式公用的,所以还需要保存这些将会被破坏的寄存器,待到处理完成的时候恢复这些寄存器被中断前的状态。另外在进入异常模式后,lr的值不一定就是我们所需恢复执行的位置,该位置受到异常类型和流水线误差的影响。在SWI模式下,LR就是返回值。在IRQ和FIQ中LR=LR-4,DataAbort下LR=LR-8;具体原因我们就不讨论了,有兴趣可以参看一文。下面分别对这些[URL=http://www.heibai.net]服务[/URL]程序进行分析。
2-1.undef exception[URL=http://www.heibai.net]服务[/URL]程序
undef
exception在执行到过非法的指令时产生,通常来模拟一些处理器不支持的功能,如浮点运算。简单说一下undef
exception的过程:当当前指令为一条处理器不支持的指令时,处理器会[URL=http://www.heibai.net]自动[/URL]动将该指令送交各协处理器(如MMU、FPU)处理,如果这些协处理器都无法识别这条指令的时候,就产生该异常。下面开始看相应的代码。
NESTED_ENTRY UndefException
sub lr, lr,
#4
; (lr) = address of undefined instruction
stmdb sp, {r0-r3, lr}
mov r1,
#ID_UNDEF_INSTR
b CommonHandler
ENTRY_END UndefException
上面就是undef Exception的[URL=http://www.heibai.net]服务[/URL]程序的入口处(已经将不参与编译和Thumb模式下的代码去掉),通过lr-=4计算出触发异常前的指令地址,同时保存r0-r3和lr入undef_exception
stack用于最后恢复现场和取得异常指令本身,随后进入分发程序CommonHandler.CommonHandler是一个公共的异常[URL=http://www.heibai.net]服务[/URL]程序,它通过不同的传入参数来进行处理,在这里mov
r1,#ID_UNDEF_INSTR就是指定异常模式为undef Exception.
2-2.swi[URL=http://www.heibai.net]服务[/URL]程序
按在ARM处理器的设计意图,系统软件的系统调用(SystemCalls)都是通过SWI指令完成。SWI相当于一个中断指令,不同的是SWI不是由外部中断源产生的,同时对应于SWI的异常向量位于0xc的位置或0xffff
000c的位置。也就是说当执行一个swi指令后,当前程序流中断,并转入0xc或0xffff000c执行,同时将CPSR_mode(当前程序状态寄存器)复制入SPSR_svc,转入SVC模式运行(使用特权模式的寄存器组)。也就是说系统通过执行SWI引发系统swi异常后切换入特权模式,系统调用功能号由swi
xx后的xx决定,在运行完指定功能的代码后返回异常时的地址并恢复用户模式。我们看看,Wince中这部分代码是如何实现的。
DCD
SWIHandler
; SVC时间片已到,进行调度
beq %F10
;SYSINTR_DEVICES EQU
8 ;是否设备中断,中断号是否有效
;SYSINTR_MAX_DEVICES EQU 32
sub
r0, r0, #SYSINTR_DEVICES
cmp r0,
#SYSINTR_MAX_DEVICES
;由此可以看出windowsCE的系统中断号最大支持32种从9-40.
;其中第16号(24)被定义为SYSINTR_FIRMWARE
; If not a device request
(and not SYSINTR_RESCHED)
ldrhsb
r0, [lr, #bResched] ; (r0) =
reschedule flag
bhs
%F20
; not a device request
;PendEvents
EQU 0x340 ; offset
0x10*sizeof(DWORD) of aInfo
;device 中断
ldr r2, [lr,
#PendEvents] ; (r2) = pending interrupt
event mask
mov r1, #1
orr r2, r2, r1, LSL
r0 ; (r2) = new pending mask
str r2, [lr,
#PendEvents] ; save it
;*PendEvents = *PendEvents|(1=SYSINTR_MAX_DEVICES
10 ldrb r0, [lr,
#bResched] ; (r0) = reschedule
flag
orr r0, r0,
#1
; set "reschedule needed bit"
strb r0, [lr,
#bResched] ; update flag
20 mrs r1,
spsr
; (r1) = saved status register value
and r1,
r1,
#0x1F ;
(r1) = interrupted mode
cmp r1,
#USER_MODE
; previously in user mode?
cmpne r1,
#SYSTEM_MODE ; if
not, was it system mode?
cmpeq r0,
#1
; user or system: is resched == 1
;if(SytemMode(spsr)||UserMode(spsr))&&r0!=1) return;
ldmnefd sp!, {r0-r3, r12,
pc}^ ; can't reschedule right now so return
*************************************************************************************
sub lr, lr, #4
ldmfd sp!, {r0-r3, r12}
stmdb lr,
ldmfd sp!,
str r0,
[lr]
; save resume address
mov r1,
#ID_RESCHEDULE ; (r1) =
exception ID
b CommonHandler
ENTRY_END IRQHandler
将spsr_irq压入IRQ堆栈保存。为调用OEMInterruptHandler作准备。(通常中断处理程序切换入系统态执行的目的在于避免使用终端模式下的寄存器,以方便是实现终端套嵌,这儿切入系统态时终端使能是关闭的,对于模态切换的原因我很迷惑。)OEMInterrupt需要在特权模式下执行,所以这里增加了切换入特权(SVC)模式的内容。紧接着将要用与传递参数的寄存器保存。设定传入参数,r0就可以开始调用OEMInterruptHandler了,这里的调用规则遵循windowsCE的规范而不是ATPCS的规范。具体过程参考ARM
Parameter [URL=http://3800cc.com/news/w31/mailto:Passing@msdn]Passing@msdn[/URL]。下面是函数原形。int
OEMInterruptHandler(unsigned int
ra);这里传入的参数就是上面的r0,事实上r0代表的参数ra并没有实质的作用在这里仅仅是形式上的实现一下而已,不过在这儿可以看到这个传入的ra实际上就是被中断的地址,如果需要知道被中断的位置可以通过ra来查询,而msdn里面说这个参数是保留的。返回的参数也是保存在r0中。其中返回值是系统中断类型。其中SYSINTR_RESCHED为系统时钟中断,每次时间片用完,该时钟便产生中断,并设置kData结构的bResched位,进入调度流程。如果中断类型是系统设备中断,那就设置PendEvents,待再次调度的时候处理中断。所以OEMInterruptHandler必须提前就要对中断进行响应对该中断源设置mask,防止在这过程中同一中断不停发生,导致中断饱和影响程序流的执行,直道中断处理真正完成后再次开放该中断的mask。在这里还可以看到的是系统设备中断号的范围是从SYSINTR_DEVICES到SYSINTR_MAX_DEVICES,也就是从9-40一共32个设备中断号,其中SYSINTR_FIRMWARE为8+16号,这个在编写OAL的中断[URL=http://www.heibai.net]服务[/URL]程序时需要注意。如果当前的返回值既不是设备中断号又不是调度中断号,则读出当前调度标示,根据该标示进行判断是否调度/或返回.如果是进入调度流程则恢复初始的寄存器状态,再按CommonHandler的要求保存寄存器。进入CommonHandler,等待分发。
2-3 FIQ[URL=http://www.heibai.net]服务[/URL]程序
照例看看程序
NESTED_ENTRY FIQHandler
sub lr, lr,
#4
; fix return address
stmfd sp!, {r0-r3, r12,
lr}
PROLOG_END
CALL
OEMInterruptHandlerFIQ
ldmfd sp!, {r0-r3,
r12, pc}^ ; restore regs & return for
NOP
ENTRY_END FIQHandler
LTORG
FIQ是arm体系下特有的异常方式,其工作过程与IRQ类似都是由外部引脚触发但设计用途不同,IRQ用于通常的外部中断源的处理,是作为统一、通用的与外部器件交互的手段,而IRQ仅仅用于处理周期短同时又需要快速处理的场合其触发的事件源通常也来此外部FIQ中断。如:更换电池、[URL=http://www.heibai.net]数据[/URL]传输这类工作。可想而知FIQ讲究的是快速,精干。因此FIQ[URL=http://www.heibai.net]服务[/URL]程序通常没有分发,而仅仅是针对单一的工作进行处理保证处理的实时性。因此FIQ的处理相对IRQ就简单很多,直接调用
OEMInterruptHandlerFIQ进行处理后返回就完成了整个 FIQ[URL=http://www.heibai.net]服务[/URL]程序。
继续上次的内容,在上次的分析中我们已经对SWI,FIQ,IRQ的流程有了一个大概的认识,下面继续对DataAbort和PrefetchAbort以及公共分发程序CommonHandler进行一下认识,完整异常处理的流程。
2-4 DataAbort[URL=http://www.heibai.net]服务[/URL]程序
由[URL=http://www.heibai.net]数据[/URL]异常触发,通常有三种指令引发[URL=http://www.heibai.net]数据[/URL]异常,这些指令都是访存操作,而且都是由MMU的引入后才可能会发生的情况。1.LDR/STR指令.2.SWAP指令。3.LDM/STM指令。而MMU的失效类型又分为4种:存储访问失效、地址对齐失效、地址变换失效、域控制器失效、访问控制权限失效.因此当异常发生后,需要通过访问CP15来获知异常的产生具体原因和情况。mfc是微软的asmarm宏汇编器专用的宏指令,相当于mcr指令。[URL=http://www.heibai.net]数据[/URL]异常和中断模式一样都有可能在互锁时发生,所以同样需要对执行互锁的情形进行处理。正常的情况下在保存完相关的寄存器后就会读取CP15的c6,c5,c13三个寄存器。这三个寄存器分别是失效地址寄存器(FAR)、失效状态寄存器(FSR)、进程号寄存器(这个翻译得不好PCP15)然后根据具体的失效类型来进行处理。在ARM处理器中对于CP15有三种地址类型,VA,PA,MVA。VA(virtual
address)也就是我们通常说的虚拟地址或逻辑地址也就是通过CP15按照PT转换后的地址,而PA(physical
Address)则是对应于AMBA上的地址,对应的是电气介质也就是物理地址。而MVA(Modified virtual
address)则是对应于Cache和TLB中转换地址。
NESTED_ENTRY DataAbortHandler
sub lr, lr,
#8
; repair continuation address
stmfd sp!,
{r0-r3, r12, lr}
PROLOG_END
sub r0, lr, #INTERLOCKED_START
cmp r0, #INTERLOCKED_END-INTERLOCKED_START
bllo CheckInterlockedRestart
mfc15 r0,
c6
; (r0) = FAR
mfc15
r1,
c5
; (r1) = FSR
mfc15 r2,
c13
; (r2) = process base address
;
FAR=Fault address register
; CP = 15: CRn = 6, CRm = 0, op_1 = 0,
op_2 = 0
; FSR=Fault status register
; CP = 15: CRn = 5, CRm = 0, op_1 = 0, op_2 = 0
; PCP15: PID Process ID register
; CP = 15:
CRn = 13, CRm = 0, op_1 = 0, op_2 = 0
tst r0,
#0xFE000000 ; slot 0
reference?
orreq r0, r0,
r2
; (r0) = process slot based address
and r1,
r1,
#0x0D ;
type of data abort
cmp r1,
#0x05
; translation error?
movne r0, #0
CALLEQ
LoadPageTable
; (r0) = !0 if entry loaded
tst r0, r0
ldmnefd sp!, {r0-r3, r12,
pc}^ ; restore regs & continue
;*********************************************************************
ldr lr, =KData-4
ldmfd sp!, {r0-r3, r12}
stmdb lr,
ldmfd sp!,
str r0,
[lr]
; save resume address
mov r1,
#ID_DATA_ABORT ; (r1) =
exception ID
b CommonHandler
ENTRY_END DataAbortHandler
在DataAbort发生后c6中的[URL=http://www.heibai.net]数据[/URL]保存的就是导致异常的MVA地址,通过windowsCE memory
layout可以了解到,当前进程的运行空间是在slot0,也就是0x0-0x1fffffff的位置,事实上这个slot上的[URL=http://www.heibai.net]数据[/URL]仅仅是实际进程的一个副本所以如果[URL=http://www.heibai.net]数据[/URL]异常发生在slot0就需要去找到进程所在的实际slot的存放地址,然后尝试将内核的页表复制到硬件实际使用的页表以达到恢复的目的。如果复制动作成功则返回,否则进入异常分发程序CommonHandler。
2-5 PrefetchAbort[URL=http://www.heibai.net]服务[/URL]程序
对于ARM处理器来说,由于其内部使用了哈佛结构---独立的[URL=http://www.heibai.net]数据[/URL]的指令总线因此,在[URL=http://www.heibai.net]数据[/URL]/指令的读取过程中产生的异常也就很自然地可以区分开来,本质上而言,这些异常都是同属于存储访问失败产生的异常,因此这些异常都由MMU相关,在ARM手册中DataAbort和PrefetchAbort都称为Memory
abort。Prefetch也就是在预取指令的动作后产生的,当处理器运行到这个无效的指令时(这个无效与undefined
exception中的不可识别不同,是指不存在或是无法得到)就触发该异常。所以不是所有的指令无效都产生异常,例如:一个分支程序指向一个不可访问的区域,而之前的分支指向另一个可访问区域时。后一个区域尽管预取无效但是由于该分支并不执行所以并不产生异常。所以prefetch的准确定义应该是prefetch
and executes
Abort:).在ARMV5指令集中BKPT也可以产生预取无效但由于这儿的ARM通常都是ARM9的,也就是使用ARMV4指令所以不讨论BKPT的情形。由于[URL=http://www.heibai.net]数据[/URL]异常和指令异常同属存储异常而且两个异常不可能会相互中断所以在ARM的设计上这两个异常使用同一组寄存器abort组。
ALTERNATE_ENTRY PrefetchAbort
sub lr, lr, #0xF0000004
;考察产生异常的地址是否在0xf0000000-0xf0010400
cmp lr, #0x00010400 ;之间,如果是进入系统调用处理
bhs ProcessPrefAbort
;->>正常的预取异常 执行ProcessPrefAbort
...
ProcessPrefAbort
add lr, lr,
#0xF0000000 ; repair
continuation address
stmfd sp!, {r0-r3, r12,
lr}
mov r0,
lr
; (r0) = faulting address
mfc15 r2,
c13
; (r2) = process base address
tst r0,
#0xFE000000 ; slot 0
reference?
orreq r0, r0,
r2
; (r0) = process slot based address
CALL
LoadPageTable
; (r0) = !0 if entry loaded
tst r0, r0
ldmnefd sp!, {r0-r3, r12,
pc}^ ; restore regs & continue
ldmfd sp!, {r0-r3, r12}
ldr lr, =KData-4
stmdb lr,
ldmfd sp!,
str r0,
[lr]
; save resume address
mov r1,
#ID_PREFETCH_ABORT ; (r1) = exception ID
b CommonHandler
下面来结合windowsCE的情形。PrefetchAbort就是该[URL=http://www.heibai.net]服务[/URL]程序的入口,在程序的一开始将lr,也就是产生异常的地址+4(流水线导致)的地址减掉0xf000
0004并比较是否在0-0x10400之间,这是为什么呢?原来windowsCE除了使用PrefetchAbort[URL=http://www.heibai.net]服务[/URL]程序作为正常的异常处理以外还使用这个异常作为系统调用的手段。通过0xf0000000-0xf0010400这段地址的预取异常来进行系统调用。我们下面看处理预取失败的情况,绕开系统调用的先不管。也就是ProcessPrefAbort的分支。
这个分支的内容就与上面DataAbort的内容一样了,我就不再重复了。
2-6异常分发 CommonHandler
到此为止我们已经了解了windowsCE对各个异常/中断模式下的处理情况已经基本做了一个了解,但是仍然有一些情况是送到CommonHandler来处理的,下面就对这个分发程序进行分析,完整windowsCE对整个异常流程的处理。
ALTERNATE_ENTRY CommonHandler
mrs r2, spsr
msr cpsr_c,
#SVC_MODE:OR:0x80 ; switch to Supervisor mode w/IRQs
disabled
ldr r3,
=KData
; (r3) = ptr to KData page
在CommonHandler开始系统就转入Supervisor态来执行。
; Save the processor state into a thread structure. If the previous state was
; User or System and the kernel isn't busy, then save the state into the
current
; thread. Otherwise, create a temporary thread structure on the
kernel stack.
;
; (r1) = exception ID
; (r2) = SPSR
; (r3) =
ptr to KData page
; Interrupted r0-r3, and Pc saved
at (r3-0x14)
; In Supervisor Mode.
ALTERNATE_ENTRY SaveAndReschedule
and r0, r2,
#0x1f ;
(r0) = previous mode
cmp r0,
#USER_MODE
; 'Z' set if from user mode
cmpne r0,
#SYSTEM_MODE ; 'Z'
set if from System mode
bne
%F50
; reentering kernel, save state on stack
; 现场保护分支
;发生异常前模态是否是用户态和系统态。FIQ/IRQ/SVC/Abort/Undef
ldr r0,
[r3,#pCurThd] ; (r0)
= ptr to current thread
; r0
=kData+pCurThd
add r0, r0,
#TcxR4 ;
(r0) = ptr to r4 save
; r0 =kData+pCurThd+TcxR4
;THREAD_CONTEXT_OFFSET后的0x44bytes用于备份寄存器的内容
stmia r0,
^
; save User bank
registers
****************************************************
; Save registers for fault from a non-preemptible state.
50 sub sp, sp,
#TcxSizeof ; allocate space for
temp. thread structure
cmp r0, #SVC_MODE
bne
%F55
; must mode switch to save state
add r0, sp,
#TcxR4 ;
(r0) = ptr to r4 save area
stmia r0,
; save SVC state registers
add r4, sp,
#TcxSizeof ; (r4) = old SVC
stack pointer
str r4, [r0,
#TcxSp-TcxR4] ; update stack pointer value
b %B10
55
msr cpsr,
r2
; switch to mode exception came from
add r0, sp,
#TcxR4 ;
(r0) = ptr to r4 save area
stmia r0,
; save mode's register state
msr cpsr_c,
#SVC_MODE:OR:0x80 ; back to supervisor mode
b
%B10
; go save remaining state
在进行统一的处理之前需要保存前态寄存器组的状态以便后面恢复,在用户态和系统态的情况下直接保存用户态的寄存器。同时上面可以看到到达50的条件是前一状态为FIQ/IRQ/SVC/Abort/Undef,也就是说为异常套嵌的情况,系统套嵌的情形前面已经处理过了。这里首先处理的是SVC下被套嵌的情形,上面可以看到SVC模式都是用于异常/中断后的具体事件处理(eg:
HandleException),所以这个流程并不是独立存在的,因此当前寄存器就是前态寄存器,所以到这里需要重新计算stack指针的位置。而另外的FIQ/IRQ/Abort/Undef模式下的寄存器的保存则需要切换当前状态来进行,所以在进入真正的处理程序之前需要不同的分支来保存前态寄存器状态。可为什么前后都看不到System模式下的寄存器保存呢?这是因为系统态和用户态使用同一组寄存器所以保存用户态寄存器组就达到了现场保护了。这种设计完全是因为ARM分组寄存器的架构决定的,所以需要不同的处理。通过上面的处理所有的情况都已经统一的完成了现场保护的动作,下面就需要进一步处理这些异常了。
10 ldmdb r3,
; load saved r0-r3 & Pc
;KData之前的16byte用作传递参数用
;所以每个异常句柄最后都由将r0-r3和PC送到这个位置。
stmdb r0!,
; save Psr, r0-r3
sub r0, r0,
#THREAD_CONTEXT_OFFSET ; (r0) = ptr to Thread struct
str r7,
[r0,#TcxPc] ; save
Pc
mfc15 r2,
c6
; (r2) = fault address
mfc15 r3,
c5
; (r3) = fault status
;r0=&Kdata
;r1=exception ID
;r2=FAR
;r3=FSR
; Process an exception or
reschedule request.
FirstSchedule
20 msr cpsr_c,
#SVC_MODE ; enable
interrupts
CALL HandleException
ldr r2, [r0,
#TcxPsr] ; (r2) =
target status
and r1, r2,
#0x1f ;
(r1) = target mode
cmp r1, #USER_MODE
cmpne r1, #SYSTEM_MODE
bne
%F30
; not going back to user or system mode
;System mode and
user mode branch
add r0, r0, #TcxR3
ldmia r0,
^
; reload user/system mode registers
ldr r1,
=KData
msr cpsr_c,
#SVC_MODE:OR:0x80 ; disable all interrupts
ldrb r1, [r1,
#bResched] ; (r1) = nest level +
reschedule flag
cmp r1, #1
mov r1, #ID_RESCHEDULE
beq
%B20
; interrupted, reschedule again
msr spsr, r2
ldr lr, [r0, #TcxPc-TcxR3]
ldmdb r0,
movs pc,
lr
; return to user or system mode
HandleException是实际进行异常处理的函数,针对上面没有处理完的异常进一步分析并进行处理。这个函数是没有公开代码的,所以没有办法进一步深入下去。由于处理的异常类型比较多所以这个异常处理函数的代码量是相当大的,因此会耗费相对比较多的时钟周期,在之前的代码中我们都是在关闭中断的情况下进行异常处理,如果在这里还不打开中断的话整个异常处理过程会相当的长,这样会很大程度上影响系统的实时性,所以在这里调用HandleException之前是将中断重新打开的,待到处理完成再将中断关闭。对于这些异常,如果不能处理就只有两种情况:1.结束该进程/线程。2.挂起系统.第二种情况下挂起系统HandleException是不会返回的。因此,只有异常处理正常流程和结束线程的可能。对于返回的情况,这个时候如果返回触发异常的地址继续运行的话,仍然会导致异常,所以结束进程/线程都需要重新调度才能完成了。对于异常处理成功的情形,就不必调度了,直接就可以返回产生异常的地方继续执行。在这里还要考虑套嵌(这里仅仅是指系统模式和兼管模式的异常套嵌)的情形,也就是中断/异常已经进入调度状态又再次产生中断/异常,这个时候就强行取消上一次调度,进而重新调度.这用于调度过程中遇到异常恢复和剥夺的情况,如果不属于这种情况的话就直接恢复寄存器状态并且返回中断点继续执行。
; Return to a non-preemptible privileged mode.
;
; (r0) = ptr to THREAD structure
; (r2) = target mode
30 msr cpsr,
r2
; switch to target mode
add r0, r0, #TcxR0
ldmia r0,
; reload all registers & return
通过HandleException处理以后,已经完成了所有异常的处理,所以这里只是考虑反回的情况,由于这里不包含用户模式下的处理,所以这里处理的都是特权模式,完全可以访问kdata区域,这里就直接利用Kdata区域中的线程备份来完成恢复寄存器和返回。
顶一下(0)
踩一下(0)
上一篇:Linux操作系统的内核编译内幕详解
下一篇:让硬盘永远工作在最佳状态
查看所有评论最新评论
查看所有评论发表评论
推荐文章
相关文章
热门文章






























