ARM Linux中断机制分析
2.2.11 ret_to_user
以上内容处理结束后,退回用户层。
arch/arm/kernel/entry-common.S /* * "slow" syscall return path. "why" tells us if this was a real syscall. */ ENTRY(ret_to_user) ret_slow_syscall: disable_irq @ disable interrupts ldr r1, [tsk, #TI_FLAGS]//从任务的TI_FLAGS标志判断是否需要处理抢占或者信号。 tst r1, #_TIF_WORK_MASK bne work_pending//处理抢占或者信号 no_work_pending: //没有抢占或者信号需要处理,或者已经处理完毕,开始退回用户态 #if defined(CONFIG_IRQSOFF_TRACER)//退回用户态必然会打开中断,这里记录下打开中断的事实,供调试用。 asm_trace_hardirqs_on #endif /* perform architecture specific actions before user return */ arch_ret_to_user r1, lr//在返回用户态前,处理各个体系结构的钩子 restore_user_regs fast = 0, offset = 0//恢复寄存器现场,并切回用户态。这里不再具体分析恢复方式。 ENDPROC(ret_to_user) |
3.问题及解答
问题1:vector_irq已经是异常、中断处理的入口函数了,为什么还要加stubs_offset?( b vector_irq + stubs_offset)
答:(1)内核刚启动时(head.S文件)通过设置CP15的c1寄存器已经确定了异常向量表的起始地址(例如0xffff0000),因此需要把已经写好的内核代码中的异常向量表考到0xffff0000处,只有这样在发生异常时内核才能正确的处理异常。
(2)从上面代码看出向量表和stubs(中断处理函数)都发生了搬移,如果还用bvector_irq,那么实际执行的时候就无法跳转到搬移后的vector_irq处,因为指令码里写的是原来的偏移量,所以需要把指令码中的偏移量写成搬移后的。至于为什么搬移后的地址是vector_irq+stubs_offset,如图一所示。下图是搬移示意图更加清晰说明了搬移过程。。
问题2:为什么在异常向量表中,用b指令跳转而不是用ldr绝对跳转?
答:因为使用b指令跳转比绝对跳转(ldr pc,XXXX)效率高,正因为效率高,所以把__stubs_start~__stubs_end之间的代码考到了0xffff0200起始处。
注意:
因为b跳转指令只能在+/-32MB之内跳转,所以必须拷贝到0xffff0000附近。
b指令是相对于当前PC的跳转,当汇编器看到 B 指令后会把要跳转的标签转化为相对于当前PC的偏移量写入指令码。
经过Uboot的启动,内核跳入linux/arch/arm/kernel/head.S开始执行。
问题1:为什么首先进入head.S开始执行?
问题3:为什么首先进入head.S开始执行?
答:内核源代码顶层目录下的Makefile制定了vmlinux生成规则:
# vmlinux image - includingupdated kernel symbols
vmlinux: $(vmlinux-lds)$(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o)FORCE
其中$(vmlinux-lds)是编译连接脚本,对于ARM平台,就是arch/arm/kernel/vmlinux-lds文件。vmlinux-init也在顶层Makefile中定义:
vmlinux-init := $(head-y)$(init-y)
head-y 在arch/arm/Makefile中定义:
head-y:=arch/arm/kernel/head$(MMUEX T).o arch/arm/kernel/init_task.o
…
ifeq ($(CONFIG_MMU),)
MMUEXT := -nommu
endif
对于有MMU的处理器,MMUEXT为空白字符串,所以arch/arm/kernel/head.O 是第一个连接的文件,而这个文件是由arch/arm/kernel/head.S编译产生成的。
综合以上分析,可以得出结论,非压缩ARM Linux内核的入口点在arch/arm/kernel/head.s中。
问题4: 中断为什么必须进入svc模式?
一个最重要原因是:
如果一个中断模式(例如从usr进入irq模式,在irq模式中)中重新允许了中断,并且在这个中断例程中使用了BL指令调用子程序,BL指令会自动将子程序返回地址保存到当前模式的lr(即r14_irq)中,这个地址随后会被在当前模式下产生的中断所破坏,因为产生中断时CPU会将当前模式的PC保存到r14_irq,这样就把刚刚保存的子程序返回地址冲掉。为了避免这种情况,中断例程应该切换到SVC或者系统模式,这样的话,BL指令可以使用r14_svc来保存子程序的返回地址。
问题5:为什么跳转表中有的用了b指令跳转,而有的用了ldr px,xxxx?
W(b) vector_und+ stubs_offset
W(ldr) pc, .LCvswi + stubs_offset
W(b) vector_pabt+ stubs_offset
W(b) vector_dabt+ stubs_offset
W(b) vector_addrexcptn+ stubs_offset
W(b) v
ARMLinux中断机 相关文章:
- ARM Linux中断机制之中断的初始化(11-10)
- ARM Linux中断机制之中断的申请(11-10)
- ARM Linux中断机制之中断处理(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)