目录

  • 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中的中断处理流程相关推荐

  1. linux kernel中的栈的介绍

    目录 1.linux kernel中的中断irq的栈stack (1).arm32体系的irq的栈 (2).arm64体系的irq的栈 2.linux kernel中的栈stack (1).概念介绍: ...

  2. Linux kernel 中模块化的平台驱动代码介绍

    介绍 在linux kernel中通过module_platform_driver来实现模块化平台驱动.大量的设备驱动程序都基于该种方式来实现,使用频次非常的高,在linux kernel 5.4.1 ...

  3. linux kernel中的进程栈

    1.linux中的user mode的进程栈 在thread_info.h中,设置进程栈的大小为16k #define THREAD_SIZE 16384 #define THREAD_START_S ...

  4. Linux kernel中常见的宏整理

    0x00 宏的基本知识 // object-like #define 宏名 替换列表 换行符 //function-like #define 宏名 ([标识符列表]) 替换列表 换行符 替换列表和标识 ...

  5. Linux Kernel中AEP的现状和发展

    阿里 石洋内核月谈Yesterday AEP简介 AEP是Intel推出的一种新型的非易失Optane Memory设备,又被称作Apache Pass,所以一般习惯称作AEP.在这之前也有类似的设备 ...

  6. 内存访问顺序 - part2: 屏障及Linux kernel中屏障的使用

    文章目录 屏障是什么 Linux Kernel 中的屏障 Linux 屏障 API 一般的屏障 强制性屏障 SMP 条件屏障 隐式屏障 其他屏障 屏障的开销 未来的文章 本文翻译自 Memory ac ...

  7. linux kernel中的cmdline的详细介绍

    cmdline 1.向linux kernel添加cmdline的四种方式 (1). 在dts中的bootargs中添加 (2).在BoardConfig中添加 (3).在uboot中添加 (4).在 ...

  8. linux内核多队列,Linux Kernel 中 Workqueue 使用系统默认队列和创建队列的方法

    关于workqueue,我们还是有很多话要说. 想必大家对workqueue相关的函数(schedule_work .queue_work.INIT_WORK.create_singlethread_ ...

  9. linux内核 漏洞扫描,Linux kernel中存在15年的漏洞

    SCSI 定义了并行I/O 总线和数据协议来连接硬盘驱动.打印机.扫描仪.光驱.测试设备.医疗设备等外部设备到本地计算机.近日,GRIMM在Linux kernel SCSI (Small Compu ...

最新文章

  1. app开发学习需要经历哪些流程
  2. python编程、abc最大值_Python中abc
  3. python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑
  4. OpenWRT开发之——对C++的支持(解决库依赖问题)
  5. 8年了,这几个时间API你用过吗?
  6. mallcloud商城基于SpringBoot2.x
  7. python画简单图-使用Python中的Turtle库绘制简单的图形
  8. Computer Vision: Algorithms and Applications阅读笔记
  9. 对于刺头,怎么办?9个套路支招
  10. 计算机软件工程专业大学排名专科,2020软件工程专业大学排名一览表
  11. 基于SimpleLink CC26x2R LaunchPad的RTLS实时定位系统搭建
  12. 4、web(js):js 操作table: insertRow(),deleteRow(),insertCell(),deleteCell()方法
  13. HoloLens开发学习笔记(一):HoloLens简介
  14. 计算机术语access,计算机英语词汇术语:access(存取,访问)
  15. JAVA_OPTS设置
  16. 历届CSP真题题解-CSP刷真题之路
  17. Element Dialog
  18. 树莓派打造无线共享打印机
  19. Ad Hoc类问题求解案例
  20. pancakeswap 前端源码编译及部署-linux

热门文章

  1. IDC干货:5个维度!全面综合分析我国城市数据中心发展情况
  2. Java创建一个文件变量_java如何定义一个类,创建它的成员变量和方法?
  3. CSDN:解决粉丝网友集中问题留言处,把你所有的问题在留言处留言,我会一一回答
  4. 成功解决ModuleNotFoundError: No module named 'utils'
  5. MAT之GUI:GUI的方式创建/训练/仿真/预测神经网络
  6. 成功解决cv2.error: C:\projects\opencv-python\opencv\modules\imgproc\src\resize.cpp:4044: error: (-215) s
  7. Interview:互联网IT界技能进阶必备—各个职位推荐几个高含金量的证书
  8. Py之wxPython:利用wxPython设计GUI界面(图片背景+简单按钮)
  9. TF之DD:实现输出Inception模型内的某个卷积层或者所有卷积层的形状
  10. DL:The development history of the important stage of DL