linux中断系统那些事之----中断处理过程

本文详细探讨了Linux中断处理过程中的关键问题,包括为何在中断处理函数中使用stubs_offset,选择b指令而非ldr绝对跳转的原因,为何首先进入head.S,中断必须进入svc模式的逻辑,以及跳转表中b指令和ldr指令的使用情况。同时解释了ARM架构如何处理中断以及中断向量表的存放位置。
摘要由CSDN通过智能技术生成

linux中断系统那些事之----中断处理过程


以外部中断irq为例来说明,当外部硬件产生中断时,linux的处理过程。首先先说明当外部中断产生时,硬件处理器所做的工作如下:

R14_irq = address of next instruction to be executed + 4/*将寄存器lr_mode设置成返回地址,即为当前pc的值,因为pc是当前执行指令的下两条指令*/

       SPSR_irq = CPSR                /*保存处理器当前状态、中断屏蔽位以及各条件标志位*/

       CPSR[4:0] = 0b10010         /*设置当前程序状态寄存器CPSR中相应的位进入IRQ模式,注意cpsr是所有模式共享的*/

       CPSR[5] = 0                        /*在ARM状态执行*/

                                          /*CPSR[6] 不变*/

       CPSR[7] = 1                       /*禁止正常中断*/

       If high vectors configured then

              PC=0xFFFF0018          /*将程序计数器(PC)值设置成该异常中断的中断向量地址,从而跳转到相应的异常中断处理程序处执行,对于ARMv7向量表普遍中断是0xFFFF0018*/

       else

              PC=0x00000018     /*对于低向量*/

假设在用户空间时,产生了外部硬件中断,则这个时候的指令跳转流程如下:
__vectors_start:---------------〉在中断向量表被拷贝后,该地址就是0xffff0000.
 ARM( swi SYS_ERROR0 )
 THUMB( svc #0 )
 THUMB( nop )
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)vector_irq + stubs_offset----------〉当外部中断产生时,pc直接指向这个地址。
W(b) vector_fiq + stubs_offset
.globl __vectors_end
下面的vector_stub irq, IRQ_MODE, 4语句,展开就是 vector_irq, 所以上述语句跳转到如下语句执行:
__stubs_start:
/*
 * Interrupt dispatcher
 */
vector_stub irq, IRQ_MODE, 4


.long __irq_usr@  0  (USR_26 / USR_32)
.long __irq_invalid@  1  (FIQ_26 / FIQ_32)
.long __irq_invalid@  2  (IRQ_26 / IRQ_32)
.long __irq_svc@  3  (SVC_26 / SVC_32)
.long __irq_invalid@  4
.long __irq_invalid@  5
.long __irq_invalid@  6
.long __irq_invalid@  7
.long __irq_invalid@  8
.long __irq_invalid@  9
.long __irq_invalid@  a
.long __irq_invalid@  b
.long __irq_invalid@  c
.long __irq_invalid@  d
.long __irq_invalid@  e
.long __irq_invalid@  f
vector_stub irq, IRQ_MODE, 4语句展开如下:
/*
 * Vector stubs.
 *
 * This code is copied to 0xffff0200 so we can use branches in the
 * vectors, rather than ldr's.  Note that this code must not
 * exceed 0x300 bytes.
 *
 * Common stub entry macro:
 *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
 *
 * SP points to a minimal amount of processor-private memory, the address
 * of which is copied into r0 for the mode specific abort handler.
 */
	.macro	vector_stub, name, mode, correction=0
	.align	5

vector_\name:
	.if \correction
	sub	lr, lr, #\correction  //因为硬件处理器是将当前指令的下两条指令的地址存储在lr寄存器中,所以这里需要减4,让他指向被中断指令的下一条,这样当中断被恢复时,可以继续被中断的指令继续执行。
	.endif			      //需要注意的是,这个时候的lr寄存器,已经是irq模式下的私有寄存器了,在中断产生时,硬件处理器已经自动为他赋了值。

	@
	@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
	@ (parent CPSR)
	@
	stmia	sp, {r0, lr}		@ save r0, lr//保存r0和lr寄存器,即被中断的下一条指令
	mrs	lr, spsr
	str	lr, [sp, #8]		@ save spsr

	@
	@ Prepare for SVC32 mode.  IRQs remain disabled.//准备从中断模式切换到管理模式,不同的模式,对应各自不同的堆栈。
	@
	mrs	r0, cpsr    
	eor	r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
	msr	spsr_cxsf, r0

	@
	@ the branch table must immediately follow this code
	@
	and	lr, lr, #0x0f           //获取被中断前,处理器所处的模式
 THUMB(	adr	r0, 1f			)
 THUMB(	ldr	lr, [r0, lr, lsl #2]	)
	mov	r0, sp			
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值