ENDPROC(ret_to_user_from_irq)
ENDPROC(ret_to_user)
A:thread_info中的flags成员中有一些low level的标识,如果这些标识设定了就需要进行一些特别的处理,这里检测的flag主要包括:
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_RESUME)
这三个flag分别表示是否需要调度、是否有信号处理、返回用户空间之前是否需要调用callback函数。只要有一个flag被设定了,程序就进入work_pending这个分支(work_pending函数需要传递三个参数,第三个是参数why是标识哪一个系统调用,当然,我们这里传递的是0)。
B:从字面的意思也可以看成,这部分的代码就是将进入中断的时候保存的现场(寄存器值)恢复到实际的ARM的各个寄存器中,从而完全返回到了中断发生的那一点。具体的代码如下:
.macro restore_user_regs, fast = 0, offset = 0
ldr r1, [sp, #\offset + S_PSR] ----r1保存了pt_regs中的spsr,也就是发生中断时的CPSR
ldr lr, [sp, #\offset + S_PC]! ----lr保存了PC值,同时sp移动到了pt_regs中PC的位置
msr spsr_cxsf, r1 ---------赋值给spsr,进行返回用户空间的准备
clrex @ clear the exclusive monitor
.if \fast
ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
.else
ldmdb sp, {r0 - lr}^ ------将保存在内核栈上的数据保存到用户态的r0~r14寄存器
.endif
mov r0, r0 ---------NOP操作,ARMv5T之前的需要这个操作
add sp, sp, #S_FRAME_SIZE - S_PC----现场已经恢复,移动svc mode的sp到原来的位置
movs pc, lr --------返回用户空间
.endm
2、中断发生在svc mode下的退出过程。具体代码如下:
.macro svc_exit, rpsr, irq = 0
.if \irq != 0
@ IRQs already off
.else
@ IRQs off again before pulling preserved data off the stack
disable_irq_notrace
.endif
msr spsr_cxsf, \rpsr-------将中断现场的cpsr值保存到spsr中,准备返回中断发生的现场
ldmia sp, {r0 - pc}^ -----这条指令是ldm异常返回指令,这条指令除了字面上的操作,
还包括了将spsr copy到cpsr中。
.endm
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-76601-12.html
早
我们坚持捍卫