GICv2与GICv3中断架构对比与LPI中断机制分析

往期内容

本文章相关专栏往期内容,PCI/PCIe子系统专栏:

  1. 嵌入式系统的内存访问和总线通信机制解析、PCI/PCIe引入
  2. 深入解析非桥PCI设备的访问和配置方法
  3. PCI桥设备的访问方法、软件角度讲解PCIe设备的硬件结构
  4. 深入解析PCIe设备事务层与配置过程
  5. PCIe的三种路由方式
  6. PCI驱动与AXI总线框架解析(RK3399)
  7. 深入解析PCIe地址空间与寄存器机制:从地址映射到TLP生成的完整流程
  8. PCIe_Host驱动分析_地址映射
  9. PCIe_Host驱动分析_设备枚举
  10. PCI/PCIe设备INTx中断机制和MSI中断机制
  11. MSI-X中断机制、MSI/MSI-X操作流程详解
  12. RK3399 PCIe 中断处理与映射分析(INTx中断机制源码分析)

Uart子系统专栏:

  1. 专栏地址:Uart子系统
  2. Linux内核早期打印机制与RS485通信技术
    – 末片,有专栏内容观看顺序

interrupt子系统专栏:

  1. 专栏地址:interrupt子系统
  2. Linux 链式与层级中断控制器讲解:原理与驱动开发
    – 末片,有专栏内容观看顺序

pinctrl和gpio子系统专栏:

  1. 专栏地址:pinctrl和gpio子系统

  2. 编写虚拟的GPIO控制器的驱动程序:和pinctrl的交互使用

    – 末片,有专栏内容观看顺序

input子系统专栏:

  1. 专栏地址:input子系统
  2. input角度:I2C触摸屏驱动分析和编写一个简单的I2C驱动程序
    – 末片,有专栏内容观看顺序

I2C子系统专栏:

  1. 专栏地址:IIC子系统
  2. 具体芯片的IIC控制器驱动程序分析:i2c-imx.c-优快云博客
    – 末篇,有专栏内容观看顺序

总线和设备树专栏:

  1. 专栏地址:总线和设备树
  2. 设备树与 Linux 内核设备驱动模型的整合-优快云博客
    – 末篇,有专栏内容观看顺序

img

目录

1.资料

2.GICv2

img

GICv2的三种中断类型

  1. 软件触发中断(SGI)

    • 由软件生成,主要用于不同CPU核之间的通信。每个CPU核可以通过写入SGI寄存器(如ICDSGIR)触发中断,并将其发送给所有核或指定的核。
    • SGI的中断号为0-15,这些号位于固定的中断号范围内。软件可以决定使用哪些号来通信。
  2. 私有外设中断(PPI)

    • 由特定CPU核私有的外设生成。这些中断源只针对单个CPU核,因此每个核独立处理自己的PPI。
    • PPI的中断号为16-31,典型的例子包括每个CPU核的定时器。
  3. 共享外设中断(SPI)

    • 由系统中共享的外设(即非核私有设备)生成。SPI可以路由到一个或多个CPU核,以处理来自系统级设备的中断请求。
    • SPI的中断号为32-1020,它们用于系统中广泛的外设,比如I/O控制器等。

这些中断类型在GICv2中构成了中断处理的基础框架,在GICv3中进一步增强了对更复杂中断场景的支持。

在GICv2里,设备向中断控制器发出中断,必须使用物理上的线路:

img

之前提到过,就像INTx#,这种采用传统的中断信号线传递中断信号的方式,如果有很多个外设的时候就需要有对应数量的信号线,这是不理想的,因此就引入了像MSI/MSI-X这种采用TPL包触发发送中断信息的方式,设备往某个地址写入数值,即可触发中断。

3.GICv3

MSI如何触发中断在之前的章节就讲过了,往特定的寄存器传值写入触发中断,那这个寄存器的地址???写什么值??? 继续往下看。

3.1 SPI触发

在GICv3中,SPI可以通过MSI的方式触发中断。通常情况下,传统的SPI由外围设备通过硬件信号产生,但通过MSI方式,设备可以直接通过写入消息的方式在GIC中触发中断。要产生或清除SPI中断时,涉及的寄存器操作如下:

产生中断:

  • 写寄存器**GICD_SETSPI_NSR**(Non-Secure Sets SPI Register)或**GICD_SETSPI_SR**(Secure Sets SPI Register)

    • 写入这些寄存器可以触发一个SPI中断。设备或软件可以使用这些寄存器来通知GIC某个中断已被请求。
    • 选择NSRSR取决于中断是在安全世界还是非安全世界触发的。

清除中断:

  • 写寄存器**GICD_CLRSPI_NSR**(Non-Secure Clear SPI Register)或**GICD_CLRSPI_SR**(Secure Clear SPI Register)

    • 在中断处理完成后,清除这些寄存器可以停止对应的SPI中断。

3.2 LPI触发

而GIC V3里新增加了一类中断:LPI(Locality-specific Peripheral Interrupts)框图如下:

img

在GICv3中,LPI(Locality-specific Peripheral Interrupt)是一种特别为MSI设计的低延迟中断。LPI专门用于大量MSI的场景,比如虚拟化环境中为每个虚拟设备提供独立的中断号。LPI的触发方式与传统的SPI不同。

触发方式1:写寄存器**GICR_SETLPIR**

  • GICR_SETLPIR寄存器用于直接触发某个特定的LPI中断。
  • 设备或软件可以通过写入该寄存器触发LPI,而不是依赖于GITS_TRANSLATER机制。这种方式更直接。

触发方式2:写寄存器**GITS_TRANSLATER**

  • GITS_TRANSLATER寄存器是GICv3中的一部分,位于ITS(Interrupt Translation Service)中。
  • 当设备触发MSI时,它会将数据写入GITS_TRANSLATER,其中的数据(称为EventID)与LPI的映射表关联,进而触发相应的LPI中断。
  • EventID可以看作是LPI的标识符。通过ITS,GIC能够将MSI消息转换为对应的LPI,并将其路由到适当的CPU。

3.3 GICv3所有的中断号

0~1023跟GICv2保存一致。

INTID

中断类型

描述

0~15

SGI

16~31

PPI

32~1019

SPI

设备发出的中断

1020~1023

SPI

用于特殊目的

1024~1055

-

保留

1056~1119

PPI

扩展的PPI,GICv3.1才支持

1120~4095

-

保留

4096~5119

SPI

扩展的SPI,GICv3.1才支持

5120~8191

-

保留

8192~芯片实现

LPI

4.LPI的触发方式

在上文中提到过两种触发方式,都是往寄存器写值,寄存器长啥样?写入什么类型的值?

4.1 第一种触发方式

直接写入GICR_SETLPIR寄存器

img

把LPI的中断号(INT ID)写入这个寄存器即可触发中断。

4.2 第二种触发方式(常用)

img

img

  1. 外设发送中断消息到ITS

    • img

    • 当外设产生中断时,它会通过写入GITS_TRANSLATER(上图)寄存器发送一个中断消息。这个消息中包含两个重要的标识符:

    • DeviceID:标识哪个设备发出了中断。这是外设的唯一ID。

    • EventID:标识同一个设备上哪个具体事件发生了中断。一个设备可以触发多个中断,每个中断对应不同的EventID。

    • 外设并不需要知道如何将这些ID转换成中断号(INTID)或路由到哪个处理器,这些都由GICv3的ITS模块处理。

  2. ITS查找Device Table

    • 当ITS接收到包含DeviceIDEventID的消息后,它会首先根据DeviceIDDevice Table中查找该设备的记录。

      • Device Table 是一个全局表,每个能够产生MSI中断的设备在这个表中有一项记录。
      • 这项记录指向该设备的Interrupt Translation Table(ITT, 中断转换表)。每个设备都有自己的ITT,用于将EventID映射到GIC中的中断ID(INTID)。
  3. ITS查找Interrupt Translation Table(ITT)

    • ITS使用EventID在设备的ITT中查找一项记录。

      • ITT 中的每一项记录包含:

        • INTID:这是最终传递到GIC中的中断标识符。GIC使用INTID来识别和处理这个中断。
        • Collection ID:用于标识该中断应该被路由到哪个处理器上的Redistributor。
  4. ITS查找Collection Table

    • ITS根据从ITT中找到的Collection IDCollection Table中查找。

    • Collection Table保存每个中断目标的信息。它包含将中断路由到哪个CPU核上的信息,即"Target Redistributor"。

  5. 中断路由到目标Redistributor

    • ITS查找完Collection Table后,找到中断应发送的目标处理器(Redistributor)。
    • 然后,它会将中断消息发往目标Redistributor,GIC最终将中断投递到对应的CPU核,完成中断处理。

总的大概就是:

  1. 外设发送中断消息(DeviceID + EventID) → ITS接收消息
  2. ITS使用DeviceID查找Device Table → 找到设备的ITT
  3. ITS使用EventID查找ITT → 找到INTIDCollection ID
  4. ITS使用Collection ID查找Collection Table → 找到目标Redistributor(处理器)
  5. 中断消息发送到目标Redistributor → 投递到CPU,处理中断

img

Device Table、Interrupt Translation Table、Collection Table都是在内存里,但是我们不能直接去设置内存。而是通过发送ITS命令来设置这些表格。

5.提问

回到之前的提问,MSI如何触发中断在之前的章节就讲过了,往特定的寄存器传值写入触发中断,那这个寄存器的地址???写什么值???

看完上面就知道的差不多了,只不过需要注意的是寄存器的地址,外设在使用的时候是经过映射的pci_addr

img

<think>好的,我现在需要帮助用户解决如何在ARM架构中配置或关闭GICv3中断控制器的问题。首先,我要回顾用户提供的引用内容,看看有没有相关的信息。引用[1]提到GICv3是根中断控制器,mt_eint是二级控制器,这可能涉及到中断控制器的层级结构。引用[2]讨论了设置EOI模式,这可能和中断处理完成后的操作有关。引用[3]则提供了GICv3的文档资料,包括SPI和LPI的触发方式,以及中断号的信息。 用户的问题是关于关闭GICv3的配置方法。首先,我需要考虑在ARM架构中,中断控制器的配置通常是在系统初始化阶段由固件或操作系统完成的,比如U-Boot或Linux内核。关闭中断控制器可能不是一个常见的操作,因为系统需要中断来处理各种事件。但用户可能有特殊需求,比如调试或特定低功耗场景。 根据GICv3架构文档,中断控制器的配置涉及到寄存器设置。可能的步骤包括:禁用中断分发、屏蔽所有中断源、设置相关控制寄存器。例如,GICD_CTLR寄存器控制分发器的全局启用,将其设置为0可以禁用所有中断的分发。此外,每个CPU接口的寄存器(如ICC_CTLR_EL1)也需要配置,可能涉及EOI模式或中断组的启用。 另外,用户可能需要知道如何在操作系统层面关闭中断,比如在Linux中使用API或内核模块来操作GICv3。但需要注意,直接操作硬件寄存器需要权限,通常在内核空间进行。 还需要考虑安全性,错误配置可能导致系统不稳定或崩溃。因此,在指导用户时必须强调谨慎操作,并建议参考官方文档和代码示例。同时,提醒用户关闭中断控制器可能影响系统功能,需确保有替代的中断处理机制。 最后,生成相关问题时要围绕配置、调试、关闭中断的影响等方面,帮助用户深入理解相关主题。</think>### ARM架构GICv3中断控制器的配置关闭方法 在ARM架构中,GICv3中断控制器的配置关闭需通过寄存器操作实现,通常分为以下步骤: --- #### **1. 全局关闭中断分发** GICv3的**分发器(Distributor)**控制全局中断分发,通过`GICD_CTLR`寄存器实现: - **寄存器地址**:基地址 + `0x1000`(GICD_CTLR偏移量) - **操作方式**: ```c // 关闭所有中断分发(Group0/1) write_gicd_reg(GICD_CTLR, 0x0); ``` 该操作会停止所有中断的全局分发,但CPU接口可能仍会处理已分发的中断[^2]。 --- #### **2. 屏蔽CPU接口的中断处理** 每个CPU接口通过`ICC_CTLR_EL1`或`ICC_CTLR_EL3`控制中断信号: - **操作方式**: ```c // 关闭CPU接口的中断信号(EL1为例) msr ICC_CTLR_EL1, 0x0; ``` 此操作会禁用CPU对中断的响应,但需注意不同异常级别(EL1/EL3)的权限要求[^2]。 --- #### **3. 屏蔽特定中断源** 通过配置`GICD_ISENABLERn`和`GICD_ICENABLERn`寄存器,关闭特定中断: ```c // 关闭中断号为INT_ID的中断 int reg_offset = (INT_ID / 32) * 4; uint32_t mask = 1 << (INT_ID % 32); write_gicd_reg(GICD_ICENABLERn + reg_offset, mask); ``` --- #### **4. 关闭LPI中断(可选)** 若系统支持LPI(Locality-specific Peripheral Interrupt),需操作`GICR_CTLR`寄存器: ```c // 关闭Redistributor的LPI功能 write_gicr_reg(GICR_CTLR, 0x0); ``` --- #### **注意事项** 1. **硬件依赖**:寄存器地址和位定义可能因具体实现(如GIC-600 vs GIC-500)而异,需查阅芯片手册。 2. **权限要求**:部分寄存器需在EL3或安全状态下操作。 3. **系统影响**:关闭GICv3可能导致系统无法响应中断,仅建议在调试或低功耗场景使用。 --- ### **示例代码(U-Boot/Linux内核)** ```c // 关闭GICv3分发器 void disable_gicv3(void) { // 关闭全局中断分发 writel(0x0, GICD_BASE + GICD_CTLR); // 关闭所有CPU接口 for (int i = 0; i < NR_CPUS; i++) { writel(0x0, GICR_BASE(i) + GICR_CTLR); } // 屏蔽所有SPI中断 for (int i = 32; i < MAX_IRQ; i += 32) { writel(0xFFFFFFFF, GICD_BASE + GICD_ICENABLERn + (i / 8)); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值