当前位置: 首页 > article >正文

4.2.1 通过DTS传递物理中断号给Linux

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客 

4.2.1 通过DTS传递物理中断号给Linux

参考《GICv3_Software_Overview_Official_Release_B》,下表描述了GIC V3支持的INTID(硬件中断号)的范围。

SGI (Software Generated Interrupt):软件触发的中断。Linux内核可以通过写GICD_SGIR寄存器来触发一个中断事件,用于CPU core之间的通信。

PPI (Private Peripheral Interrupt):私有外设中断。这是每个核心私有的中断。PPI会送达到指定的CPU上,应用场景有CPU本地时钟。

SPI (Shared Peripheral Interrupt):软件触发的中断。软件可以通过写GICD_SGIR寄存器来触发一个中断事件,一般用于核间通信。

LPI (Locality-specific Peripheral Interrupt):LPI是GICv3中的新特性,是基于消息的中断。当前GIC V3驱动irq-gic-v3.c的参数gicv3_nolpi默认为0,所以默认是默认支持LPI的。

SOC芯片在设计的时候,不同设备会分配到自己固定的硬件中断号,一般在手册里都会说明。这些硬件中断号如何告知内核呢?通过open firmware device tree,经常简称device tree。设备树通常以 .dts(Device Tree Source)文件的形式编写,这是一种人类可读的文本格式。.dts 文件会被编译成二进制的 .dtb(Device Tree Blob)文件,供内核在启动时使用。

以dts中的timer设备为例,说明一下硬件中断号是如何传入Linux中的。

/dts-v1/;

/ {
    ......

    timer {
        compatible = "arm,armv8-timer";
        interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>,
                     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>,
                     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>,
                     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
    };

    ......
};

interrupts 属性定义了定时器产生的中断。每个中断由三个字段组成:

  • 第一个字段是中断类型,0代表GIC_SPI,1代表GIC_PPI

 

  • 第二个字段是中断号。这个中断号并不是GIC中的硬件中断号,而是PPI或SPI各自范围的逻辑编号。对于PPI来说,范围是0~15;对于SPI来说,范围是0~987。例子中有四个PPI中断号:中断号13 (0x0d)、中断号14 (0x0e)、中断号11 (0x0b)、中断号10 (0x0a)。
  • 第三个字段是中断的属性,包括2个字节。低字节是中断的触发类型,在这个例子中,中断是高电平触发。高字节表示中断的目标 CPU 掩码,例如GIC_CPU_MASK_SIMPLE(8)可以表示所有 8 个 CPU 都可以接收这个中断。

 dts里面的中断号,是如何传递到Linux中呢?Linux根据dts中的timer节点来创建设备时,需要计算出真实的hwirq。以GIC IRQ V3来说,使用gic_irq_domain_translate函数,根据中断类型进行转换。对于PPI,要加上16;对于SPI,要加上32.

最后一个问题,对于timer设备来说,四个中断最终使用哪个中断?根据compatible = "arm,armv8-timer",确认匹配的驱动程序为drivers/clocksource/arm_arch_timer.c。四个中断的定义在include/clocksource/arm_arch_timer.h。 

drivers/clocksource/arm_arch_timer.c
TIMER_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);

include/clocksource/arm_arch_timer.h
enum arch_timer_ppi_nr {
    ARCH_TIMER_PHYS_SECURE_PPI,   // 对应timer中的PPI 13
    ARCH_TIMER_PHYS_NONSECURE_PPI, //对应timer中的PPI 14
    ARCH_TIMER_VIRT_PPI,          //对应timer中的PPI 11
    ARCH_TIMER_HYP_PPI,           //对应timer中的PPI 10
    ARCH_TIMER_MAX_TIMER_PPI      // 用于边界检查
};

以我用的QEMU virt为例,arch_timer_of_init调用arch_timer_select_ppi()选择了ARCH_TIMER_VIRT_PPI,对应timer中的PPI 11。根据上面的分析,针对PPI中断,Linux会加上偏移量16,最终得到hwirq 27!

通过cat /proc/interrupts来验证一下,arch_timer的硬件中断号hwirq确实是27!

注意看图上的第一列,显示的是Linux中断号。arch_timer的硬件中断号hwirq 27对应Linux的中断号为3,二者是怎么映射的,下一章继续分析。

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客

原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!


http://www.kler.cn/a/326844.html

相关文章:

  • Halcon例程代码解读:安全环检测(附源码|图像下载链接)
  • CTFHUB 历年真题 afr-1
  • ubuntu22.04.5本地apt源部署
  • microk8s使用
  • Oracle 数据库函数的用法(一)
  • 【Windows版】opencv 和opencv_contrib配置
  • 全面指南:探索并实施解决Windows系统中“mfc140u.dll丢失”的解决方法
  • NAND Flash虚拟层坏块管理机制
  • python爬虫案例——抓取链家租房信息(8)
  • Solaris11.4配置远程桌面登录
  • STM32 软件触发ADC采集
  • 基于MATLAB的苹果外观特征检测
  • 【计算机网络 - 基础问题】每日 3 题(二十六)
  • 针对考研的C语言学习(定制化快速掌握重点4)
  • IDEA几大常用AI插件
  • Splashtop 加入 Microsoft 智能安全协会
  • VBA解除Excel工作表保护
  • 浅析Android中的View事件分发机制
  • 19.2 编写dockerfile和k8s yaml
  • 迁移学习案例-python代码
  • Redis一些简单通用命令认识常用数据类型和编码方式认识Redis单线程模型
  • OJ题之单链表排序
  • 智慧城市运营模式--联合公司运营
  • ThinkPHP发送邮件教程:从配置到发送指南!
  • ChatGPT的150个角色提示场景实测(9)讲故事
  • django drf 分页器