微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux中断机制分析

ARM Linux中断机制分析

时间:11-09 来源:互联网 点击:

方向移动一个pt_regs结构大小,用于保存svc模式下的寄存器现常

ARM( stmib sp, {r1 - r12} )@向svc32堆栈中保存寄存器现场

THUMB( stmia sp, {r0 - r12} )

ldmia r0, {r3 - r5}@前面r0存放的是irq模式下的栈指针sp的值,从栈中取出r0-r2存放到r3-r5中

add r0, sp, #S_PC@ here for interlock avoidance;S_PC定义为offsetof(struct pt_regs, ARM_pc),所

以这里通过add指令将r0指向ARM_pc

mov r6, #-1 @r6中保存-1

str r3, [sp] @ save the "real" r0 copied从中断栈中取出真实的r0存放到pt_regs->r0中。

@ from the exception stack

2.2.2 usr_entry

@ We are now ready to fill in the remaining blanks on the stack:

@

@ r4 - lr_, already fixed up for correct return/restart

@ r5 - spsr_

@ r6 - orig_r0 (see pt_regs definition in ptrace.h)

@

@ Also, separately save sp_usr and lr_usr

@

stmia r0, {r4 - r6}//stmia将svc模式下的寄存器r4-r6保存到ARM_pc,ARM_cpsr和

ARM_ORIG_r0,显然ARM_ORIG_r0保存了-1(r6)这个常量

ARM( stmdb r0, {sp, lr}^ )//stmdb指令的^标志表示存储发生中断的模式下的sp,lr寄存器

到ARM_sp和ARM_lr中。

THUMB( store_user_sp_lr r0, r1, S_SP - S_PC )

@ Enable the alignment trap while in kernel mode

alignment_trap r0//alignment_trap在配置CONFIG_ALIGNMENT_TRAP时有效,如果开启了该选

//项,中断处理中将支持对齐跟踪

@ Clear FP to mark the first stack frame

zero_fp//zero_fp用来设置fp栈帧寄存器为0

#ifdef CONFIG_IRQSOFF_TRACER

bl trace_hardirqs_off

#endif

.endm@usr_entry宏定义结束

以上的指令的作用可以总结如下,其中将普通寄存器r1到r12保存到ARM_r1- ARM_r12,这相当于把发生中断时的寄存器r1-r12进行了保存。接下来保存中断发生时的r0,lr_irq和spsr_irq保存到r1-r3,r4赋值为-1,它们接下来将被使用。接下来保存r0到ARM_r0,lr_irq,spsr_irq和-1到ARM_pc ARM_cpsr ARM_ORIG_R0,注意到stmdb指令中的"^",它保存sp_usr和lr_usr分别到ARM_sp和ARM_lr,显然这里将所有中断发生时的寄存器都进行了保存。

图3 保存中断堆栈

2.2.3 get_thread_info

get_thread_info宏用来根据当前的sp值,通过lsr和lsl分别右移左移13位,相当于对sp向下圆整到8K对齐。这里也就是thread_info所在的地址。

arch/arm/kernel/entry-header.S

.macroget_thread_info, rd

mov \rd, sp, lsr #13

mov \rd, \rd, lsl #13

.endm

linux/arch/arm/kernel/entry-armv.S

/*

* Interrupt handling. Preserves r7, r8, r9

*/

.macroirq_handler

#ifdef CONFIG_MULTI_IRQ_HANDLER

ldr r5, =handle_arch_irq

mov r0, sp

ldr r5, [r5]

adr lr, BSYM(9997f)

teq r5, #0

movne pc, r5

#endif

arch_irq_handler_default

9997:

.endm

2.2.4 irq_handler

linux/arch/arm/kernel/entry-armv.S

/*

* Interrupt handling. Preserves r7, r8, r9

*/

.macroirq_handler

#ifdefCONFIG_MULTI_IRQ_HANDLER

ldr r5,=handle_arch_irq

mov r0,sp

ldr r5,[r5]

adr lr,BSYM(9997f)

teq r5,#0

movne pc,r5

#endif

arch_irq_handler_default

9997:

.endm

2.2.5 arch_irq_handler_default

irq_handler是真正的IRQ中断处理入口,在中断处理中需要预留r7,r8和r9寄存器。它们被用来处理内核抢占。在没有配置MULTI_IRQ_HANDLER 的情况下,irq_handler的逻辑很简单,就是简单的调用arch_irq_handler_default。

如果配置了该选项,平台代码可以修改全局变量:handle_arch_irq,这里只讨论默认实现.

arch/arm/include/asm/entry_macro_multi.S

/*

* Interrupt handling. Preserves r7, r8, r9

*/

.macroarch_irq_handler_default //get_irqnr_preamble用来获取中断状态寄存器基地址

get_irqnr_preamble r5, lr//将中断控制器的状态寄存器的地址存储到r5

1: get_irqnr_and_base r0, r6, r5, lr//判断中断号,通过r0返回

movne r1, sp//如果还存在中断,就将sp作为第二个参数,调用asm_do_IRQ。sp目前指向pt_regs

@

@ routine called with r0 = irq number, r1 = struct pt_regs *

@

adrne lr, BSYM(1b)//这里将lr设置为get_irqnr_and_base的第二条指令,因为第二次循环时,不必执行其第一条指令(加载寄存器基址)

bne asm_do_IRQ //将中断号、pt_regs(中断前的寄存器现场)传递给asm_do_IRQ。asm_do_IRQ返回时,

//会返回到get_irqnr_and_base处,直到所有中断都已经处理完毕才退出循环。

#ifdef CONFIG_SMP//针对SMP

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top