linux中断流程总结

本篇文章是基于linux-4.9.88内核进行分析,使用的单板是imx6ull。

1、linux中断所涉及的各种数据结构关系

首先,我们要明确一点,hwirq与virq并不是一回事,hwirq就是硬件中断号,比如用户按键、串口中断、网络中断等这些,都会在gic通用中断控制器中标识出一个中断号,是属于硬件层面的序号。

为什么不直接使用hwirq呢?对于驱动工程师而言,我们和CPU视角是一样的,我们只希望得到一个IRQ number,而不关系具体是那个interrupt controller上的那个HW interrupt ID。这样一个好处是在中断相关的硬件发生变化的时候,驱动软件不需要修改。因此,linux kernel中的中断子系统需要提供一个将HW interrupt ID映射到IRQ number上来的机制,就是irq_domain结构的作用。

 从上图中可以看到,linux中断所涉及到的各个数据结构,主要是通过irq_desc这个结构进行链接

  • 用户申请到的每一个中断都会为它分配一个irq_desc结构。
  • irq_chip结构主要用来执行中断的各种操作,比如,屏蔽中断和使能中断
  • irq_domain结构主要用来保存hwirq和virq的映射关系,其中有两个重要的函数,.xlate和.map。
  • irq_desc结构中的handle_irq与action链表中的函数不是同一个函数,处理不同的事件,而用户注册的中断服务函数是action链表中的一个函数。

 2、异常向量表的注册

我们知道,当发生某一个中断时,CPU就会跳转到相应的异常入口中去执行异常函数,而中断也是异常的一种,因此,我们有必要分析一下异常向量表的注册。

arch/arm/kernel/entry-armv.S
	.section .vectors, "ax", %progbits
.L__vectors_start:
	W(b)	vector_rst
	W(b)	vector_und
	W(ldr)	pc, .L__vectors_start + 0x1000
	W(b)	vector_pabt
	W(b)	vector_dabt
	W(b)	vector_addrexcptn
	W(b)	vector_irq
	W(b)	vector_fiq

这些就是各种异常发生时跳转到的函数,其中中断发生会跳转到vector_irq中,下面就去查找vector_irq,结果是找不到的,它是一个宏,

	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

将 'stub'替换为 'irq'就是我们中断的跳转入口,对于user模式下,我们会跳转到__irq_usr这个位置,相应的svc模式下,将会跳转到__irq_svc的位置去执行,下面搜索__irq_usr

	.align	5
__irq_usr:
	usr_entry            /* 1. 保存现场 */
	kuser_cmpxchg_check
	irq_handler          /* 2. 处理 */
	get_thread_info tsk
	mov	why, #0
	b	ret_to_user_from_irq    /* 3. 恢复现场 */
 UNWIND(.fnend		)
ENDPROC(__irq_usr)

因此,irq_handler函数来处理中断,继续搜索

	.macro	irq_handler
#ifdef CONFIG_MULTI_IRQ_HANDLER
	ldr	r1, =handle_arch_irq
	mov	r0, sp
	badr	lr, 9997f
	ldr	pc, [r1]
#else
	arch_irq_handler_default
#endif

最终会执行到handle_arch_irq函数,这是在gic中设置的一个函数。在讲解如何设置该函数之前先看异常向量表是怎么让内核知道的。

// arch\arm\kernel\head.S
1. bl	__lookup_processor_type
   ...... 
2. bl	__
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值