linux kernel中的中断处理流程
目录
- 1、linux kernel arm32的中断函数处理流程
- (1)、irq_handler宏
- (2)、arch_irq_handler_default 宏
- (3)、调用了asm_do_IRQ
- 2、linux kernel arm64的中断函数处理流程
- (1)、irq_handler宏 调用handle_arch_irq
- (2)、handle_arch_irq
- (3)、gic_handle_irq()
- (4)、handle_domain_irq()---->__handle_domain_irq()---->generic_handle_irq()---->generic_handle_irq_desc()
★★★ 友情链接 : 个人博客导读首页—点击此处 ★★★
1、linux kernel arm32的中断函数处理流程
我们从irq_handler宏函数看起
(1)、irq_handler宏
注意CONFIG_MULTI_IRQ_HANDLER宏表示"允许每台机器在运行时指定它自己的IRQ处理程序",当前默认是不开启的.
所以走else的arch_irq_handler_default逻辑
(arch/arm/kernel/entry-armV.S)
/** Interrupt handling.*/.macro irq_handler
#ifdef CONFIG_MULTI_IRQ_HANDLERldr r1, =handle_arch_irqmov r0, spbadr lr, 9997fldr pc, [r1]
#elsearch_irq_handler_default
#endif
9997:.endm
(2)、arch_irq_handler_default 宏
arch_irq_handler_default 宏 调用了asm_do_IRQ或do_IPI
(arch/arm/include/asr/entry-macro-multi.S)
/** Interrupt handling. Preserves r7, r8, r9*/.macro arch_irq_handler_defaultget_irqnr_preamble r6, lr
1: get_irqnr_and_base r0, r2, r6, lrmovne r1, sp@@ routine called with r0 = irq number, r1 = struct pt_regs *@badrne lr, 1bbne asm_do_IRQ#ifdef CONFIG_SMP/** XXX** this macro assumes that irqstat (r2) and base (r6) are* preserved from get_irqnr_and_base above*/ALT_SMP(test_for_ipi r0, r2, r6, lr)ALT_UP_B(9997f)movne r1, spbadrne lr, 1bbne do_IPI
#endif
9997:.endm
(3)、调用了asm_do_IRQ
asm_do_IRQ()—>handle_IRQ()—>__handle_domain_irq()—>generic_handle_irq()—>调用用户request_irq注册的中断处理函数
void handle_IRQ(unsigned int irq, struct pt_regs *regs)
{__handle_domain_irq(NULL, irq, false, regs);
}
/** asm_do_IRQ is the interface to be used from assembly code.*/
asmlinkage void __exception_irq_entry
asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{handle_IRQ(irq, regs);
}
int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,bool lookup, struct pt_regs *regs)
{struct pt_regs *old_regs = set_irq_regs(regs);unsigned int irq = hwirq;int ret = 0;irq_enter();#ifdef CONFIG_IRQ_DOMAINif (lookup)irq = irq_find_mapping(domain, hwirq);
#endif/** Some hardware gives randomly wrong interrupts. Rather* than crashing, do something sensible.*/if (unlikely(!irq || irq >= nr_irqs)) {ack_bad_irq(irq);ret = -EINVAL;} else {generic_handle_irq(irq);}irq_exit();set_irq_regs(old_regs);return ret;
}
(kernel/irq/irqdesc.c)
int generic_handle_irq(unsigned int irq)
{struct irq_desc *desc = irq_to_desc(irq);if (!desc)return -EINVAL;generic_handle_irq_desc(desc);return 0;
}
EXPORT_SYMBOL_GPL(generic_handle_irq);
(kernel/include/linux/irqdesc.h)
static inline void generic_handle_irq_desc(struct irq_desc *desc)
{desc->handle_irq(desc); // 这里真正调用到,用户request_irq注册的中断处理函数
}
2、linux kernel arm64的中断函数处理流程
我们依然从irq_handler宏函数看起
(1)、irq_handler宏 调用handle_arch_irq
(arch/arm/kernel/entry.S)
/** Interrupt handling.*/.macro irq_handlerldr_l x1, handle_arch_irqmov x0, spirq_stack_entryblr x1irq_stack_exit.endm
(2)、handle_arch_irq
handle_arch_irq是在set_handle_irq()设置的handle地址
void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
{if (handle_arch_irq)return;handle_arch_irq = handle_irq;
}
(3)、gic_handle_irq()
在gic_of_init初始化的时候,将gic_handle_irq()地址赋给了handle_arch_irq
static int __init gic_of_init(struct device_node *node, struct device_node *parent)
{......set_handle_irq(gic_handle_irq);
......
}
进入gic中的gic_handle_irq处理函数
在这里会调用handle_domain_irq函数或者handle_IPI函数
static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
{u32 irqnr;do {irqnr = gic_read_iar();if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) {int err;if (static_key_true(&supports_deactivate))gic_write_eoir(irqnr);err = handle_domain_irq(gic_data.domain, irqnr, regs);if (err) {WARN_ONCE(true, "Unexpected interrupt received!\n");if (static_key_true(&supports_deactivate)) {if (irqnr < 8192)gic_write_dir(irqnr);} else {gic_write_eoir(irqnr);}}continue;}if (irqnr < 16) {gic_write_eoir(irqnr);if (static_key_true(&supports_deactivate))gic_write_dir(irqnr);
#ifdef CONFIG_SMP/** Unlike GICv2, we don't need an smp_rmb() here.* The control dependency from gic_read_iar to* the ISB in gic_write_eoir is enough to ensure* that any shared data read by handle_IPI will* be read after the ACK.*/handle_IPI(irqnr, regs);
#elseWARN_ONCE(true, "Unexpected SGI received!\n");
#endifcontinue;}} while (irqnr != ICC_IAR1_EL1_SPURIOUS);
}
(4)、handle_domain_irq()---->__handle_domain_irq()---->generic_handle_irq()---->generic_handle_irq_desc()
int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,bool lookup, struct pt_regs *regs)
{struct pt_regs *old_regs = set_irq_regs(regs);unsigned int irq = hwirq;int ret = 0;irq_enter();#ifdef CONFIG_IRQ_DOMAINif (lookup)irq = irq_find_mapping(domain, hwirq);
#endif/** Some hardware gives randomly wrong interrupts. Rather* than crashing, do something sensible.*/if (unlikely(!irq || irq >= nr_irqs)) {ack_bad_irq(irq);ret = -EINVAL;} else {generic_handle_irq(irq);}irq_exit();set_irq_regs(old_regs);return ret;
}
int generic_handle_irq(unsigned int irq)
{struct irq_desc *desc = irq_to_desc(irq);if (!desc)return -EINVAL;generic_handle_irq_desc(desc);return 0;
}
EXPORT_SYMBOL_GPL(generic_handle_irq);static inline void generic_handle_irq_desc(struct irq_desc *desc)
{desc->handle_irq(desc);
}
linux kernel中的中断处理流程相关推荐
- linux kernel中的栈的介绍
目录 1.linux kernel中的中断irq的栈stack (1).arm32体系的irq的栈 (2).arm64体系的irq的栈 2.linux kernel中的栈stack (1).概念介绍: ...
- Linux kernel 中模块化的平台驱动代码介绍
介绍 在linux kernel中通过module_platform_driver来实现模块化平台驱动.大量的设备驱动程序都基于该种方式来实现,使用频次非常的高,在linux kernel 5.4.1 ...
- linux kernel中的进程栈
1.linux中的user mode的进程栈 在thread_info.h中,设置进程栈的大小为16k #define THREAD_SIZE 16384 #define THREAD_START_S ...
- Linux kernel中常见的宏整理
0x00 宏的基本知识 // object-like #define 宏名 替换列表 换行符 //function-like #define 宏名 ([标识符列表]) 替换列表 换行符 替换列表和标识 ...
- Linux Kernel中AEP的现状和发展
阿里 石洋内核月谈Yesterday AEP简介 AEP是Intel推出的一种新型的非易失Optane Memory设备,又被称作Apache Pass,所以一般习惯称作AEP.在这之前也有类似的设备 ...
- 内存访问顺序 - part2: 屏障及Linux kernel中屏障的使用
文章目录 屏障是什么 Linux Kernel 中的屏障 Linux 屏障 API 一般的屏障 强制性屏障 SMP 条件屏障 隐式屏障 其他屏障 屏障的开销 未来的文章 本文翻译自 Memory ac ...
- linux kernel中的cmdline的详细介绍
cmdline 1.向linux kernel添加cmdline的四种方式 (1). 在dts中的bootargs中添加 (2).在BoardConfig中添加 (3).在uboot中添加 (4).在 ...
- linux内核多队列,Linux Kernel 中 Workqueue 使用系统默认队列和创建队列的方法
关于workqueue,我们还是有很多话要说. 想必大家对workqueue相关的函数(schedule_work .queue_work.INIT_WORK.create_singlethread_ ...
- linux内核 漏洞扫描,Linux kernel中存在15年的漏洞
SCSI 定义了并行I/O 总线和数据协议来连接硬盘驱动.打印机.扫描仪.光驱.测试设备.医疗设备等外部设备到本地计算机.近日,GRIMM在Linux kernel SCSI (Small Compu ...
最新文章
- app开发学习需要经历哪些流程
- python编程、abc最大值_Python中abc
- python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑
- OpenWRT开发之——对C++的支持(解决库依赖问题)
- 8年了,这几个时间API你用过吗?
- mallcloud商城基于SpringBoot2.x
- python画简单图-使用Python中的Turtle库绘制简单的图形
- Computer Vision: Algorithms and Applications阅读笔记
- 对于刺头,怎么办?9个套路支招
- 计算机软件工程专业大学排名专科,2020软件工程专业大学排名一览表
- 基于SimpleLink CC26x2R LaunchPad的RTLS实时定位系统搭建
- 4、web(js):js 操作table: insertRow(),deleteRow(),insertCell(),deleteCell()方法
- HoloLens开发学习笔记(一):HoloLens简介
- 计算机术语access,计算机英语词汇术语:access(存取,访问)
- JAVA_OPTS设置
- 历届CSP真题题解-CSP刷真题之路
- Element Dialog
- 树莓派打造无线共享打印机
- Ad Hoc类问题求解案例
- pancakeswap 前端源码编译及部署-linux
热门文章
- IDC干货:5个维度!全面综合分析我国城市数据中心发展情况
- Java创建一个文件变量_java如何定义一个类,创建它的成员变量和方法?
- CSDN:解决粉丝网友集中问题留言处,把你所有的问题在留言处留言,我会一一回答
- 成功解决ModuleNotFoundError: No module named 'utils'
- MAT之GUI:GUI的方式创建/训练/仿真/预测神经网络
- 成功解决cv2.error: C:\projects\opencv-python\opencv\modules\imgproc\src\resize.cpp:4044: error: (-215) s
- Interview:互联网IT界技能进阶必备—各个职位推荐几个高含金量的证书
- Py之wxPython:利用wxPython设计GUI界面(图片背景+简单按钮)
- TF之DD:实现输出Inception模型内的某个卷积层或者所有卷积层的形状
- DL:The development history of the important stage of DL