GIC/ITS代码分析(11)LPI中断虚拟化之概述

本文详细介绍了GICv3和GICv4中本地中断(LPI)的虚拟化处理。GICv3通过GICH和VGICC支持LPI中断,中断在物理和虚拟层面的传递涉及多个步骤,包括INTID的激活、转换和优先级管理。GICv4进一步优化,支持直接注入虚拟LPI中断,减少了虚拟化过程中的开销。内容涵盖了ITS(中断转换服务)的角色,以及在QEMU和内核KVM中的模拟实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        这里主要介绍ITS所产生的LPI中断的虚拟化。首先对ITS寄存器映射作简要介绍。

1 ITS寄存器映射

        ITS地址映射包含两个分开的64KB,该地址由ITS_base指定。基地址必须64KB对齐,这两个包含:

  1. control寄存器,地址位于ITS_base + 0x000000
  2. 中断转换空间,地址位于ITS_base + 0x010000
  3. vSGI空间,地址位于ITS_base + 0x020000

下表为GIC寄存器映射。

序号

类型

描述

GITS_CTLR

RW

ITS控制寄存器

GITS_IIDR

RO

ITS ID寄存器

GITS_TYPER

RO

ITS Type寄存器

GITS_MPAMIDR

RO

ITS支持MPAM大小

GITS_PARTIDR

RW

ITS PARTID寄存器

GITS_MPIDR

RO

ITS亲和性

GITS_STATUSR

RW

ITS错误报告状态寄存器

GITS_UMSIR

RO

ITS未映射MSI寄存器

GITS_CBASER

RW

ITS命令队列描述符

GITS_CWRITE

RW

ITS写寄存器

GITS_CREADR

RW

ITS读寄存器

GITS_BASER<n>

RW

ITS转换表描述符

GITS_TRANSLATER

WO

ITS转换寄存器

GITS_SGIR

WO

vSGI寄存器

2 ITS设备的模拟概述

        ITS设备的模拟包含两个部分,一部分在QEMU中,一部分在内核KVM模块中。QEMU中会模拟ITS设备,让guest中能够识别到ITS设备;另一部分在内核KVM中对于ITS MMIO等模拟。

        在guest中访问ITS设备寄存器所对应的MR时,会触发VM exit进入到host中,在host KVM中会根据访问不同的寄存器作不同的处理,完成MMIO处理后最终再次VM enter进入guest。

 3 GICv3中LPI中断的处理

        GICv3支持对LPI中断的虚拟化。GICv3增加了GICH和VGICC来支持LPI中断的虚拟化。

  1. 一个物理非安全Group1中断发送给Redistributor的物理CPU interface;
  2. 物理CPU interface检查物理中断是否发送给PE。默认情况下该检查通过,发出物理中断;
  3. 中断被带到EL2。hypervisor读取IAR寄存器,返回物理INTID。因此该物理INTID变成active状态。Hypervisor决定当前中断是否直接发送给当前运行vPE。hypervisor将物理INTID写入到ICC_EOIR1_EL1,在ICC_CTLR_EL1.EOImode=1情况下,该行为仅发出priority drop而不会deactive物理中断;
  4. Hypervisor写LR寄存器将虚拟中断变成pending状态。LR寄存器指定了vINTID。Hypervisor发出异常到vPE;
  5. 虚拟CPU interface检查虚拟中断是否发送给vPE。这些检查与物理中断相同,除了使用ICV寄存器。在这种情况下,检查通过并发出虚拟中断;
  6. 虚拟异常被带到非安全EL1。当软件读IAR时,虚拟INTID返回且虚拟中断变成active状态;
  7. Guest OS处理中断。当它完成中断处理时,它写EOIR发出priority drop和deactivation。因为LR寄存器记录物理INTID,它将deactivate虚拟INTID和物理INTID。

4 GICv4中LPI中断的处理

GICv4支持对虚拟LPI中断的直接注入,即不需要陷入到EL2,直接由Redistributor产生虚拟中断。

  1. ITS使用DeviceID从Device Table中获取合适的entry,它用于找到使用的Interrupt Translation table;
  2. ITS使用EventID从ITT表中选择合适的entry,它要么返回物理INTID和collection ID,要么返回vINTID和vPE ID;
  3. ITS使用vPE ID选择vPE表中的entry,vPE表返回目标Redistributor和vPE的VPT;
  4. ITS将vINTID,door-bell中断以及目标Redistributor的VPT地址;
  5. Redistributor比较ITS的VPT地址和当前GICR_VPENDBASER,若匹配,表示vPE被调度,虚拟INTID被发送给虚拟CPU interface;若不匹配,表明vPE没有被调度,vINTID被设置为pending状态。如果提供door-bell中断,物理INTID被发送给物理CPU interface。

 

<think>好的,我现在需要帮助用户了解Linux下的GIC(通用中断控制器)相关知识或配置方法。首先,我需要回顾一下GIC的基本概念和它在Linux中的作用。GIC是ARM架构中用于管理中断的控制器,负责接收、分发和处理来自外设的中断请求。Linux内核中对GIC的支持主要通过设备树配置和相应的驱动代码实现。 根据用户提供的引用内容,特别是引用[2]和[3],GIC的三大核心组件是Distributor、Redistributor和CPU Interfaces。GIC-CPU-IF是处理中断优先级的关键部分,涉及到系统寄存器的配置。用户可能需要了解如何在内核中配置这些部分,或者如何查看相关的寄存器设置。 接下来,我需要考虑用户可能的实际需求。他们可能想知道如何在设备树中描述GIC,或者如何在内核中启用特定的GIC驱动。例如,不同的GIC版本(如GICv2、GICv3)在配置上可能有差异,需要分别说明。此外,中断的优先级配置、亲和性设置以及如何调试中断问题也是常见的配置问题。 用户的问题提到“configuration or implementation”,所以需要覆盖配置方法和实现机制。设备树中的节点结构是关键,比如gic的节点通常包含寄存器地址、中断控制器类型、中断域配置等。例如,一个典型的GIC设备树节点可能如下: ```dts interrupt-controller@fee00000 { compatible = "arm,gic-v3"; reg = <0x0 0xfee00000 0x0 0x10000>, // Distributor <0x0 0xfef00000 0x0 0x200000>; // Redistributors interrupts = <1 9 4>; interrupt-controller; #interrupt-cells = <3>; }; ``` 这里需要解释每个属性的含义,比如compatible字段指定驱动类型,reg定义寄存器地址范围,interrupts是GIC自己的中断信号,用于虚拟化或维护操作。#interrupt-cells说明每个中断描述符的单元格数量,通常是3个(类型、中断号、标志)。 在实现层面,Linux内核中的GIC驱动代码位于drivers/irqchip/目录下,如irq-gic.c、irq-gic-v3.c等。这些驱动负责初始化GIC硬件,注册中断控制器,并提供中断处理函数。例如,gic_of_init()函数会解析设备树信息,配置Distributor和CPU Interface。 此外,用户可能对如何查看当前系统的中断分配和状态感兴趣。这可以通过/proc/interrupts文件查看,其中列出了每个中断号、触发次数和对应的设备名称。GIC相关的条目会以GIC开头,比如GIC0或GICv3。 关于中断优先级,引用[2]提到GIC-CPU-IF通过系统寄存器处理优先级。在Linux中,优先级配置可能涉及设置中断的抢占和优先级掩码。例如,使用irq_set_priority()函数可以调整特定中断的优先级,但这通常由内核自动管理,用户可能需要通过内核配置或启动参数进行调整。 用户还可能遇到多核系统中的中断亲和性问题,即如何将中断绑定到特定的CPU核心。这可以通过修改/proc/irq/<irq_num>/smp_affinity文件来实现,其值代表目标CPU的位掩码。例如,echo 1 > smp_affinity将中断绑定到CPU0。 最后,需要考虑GIC版本之间的差异。GICv3引入了新的特性,如支持更多的CPU和中断号,使用系统寄存器而非内存映射接口进行部分操作。在配置时,需确保内核支持对应的GIC版本,并且设备树正确无误。 总结,回答需要涵盖设备树配置、驱动实现、中断查看与调试方法、优先级和亲和性设置,以及不同GIC版本的区别。同时,结合用户提供的引用内容,强调GIC组件的作用和系统寄存器的重要性,确保信息准确且有参考依据。</think>### Linux下的GIC配置与实现 #### 1. **GIC基本架构与组件** 通用中断控制器(GIC)在ARM架构中负责管理硬件中断的接收、优先级排序和分发。其核心组件包括: - **Distributor**:全局中断管理(使能/禁用、优先级配置、分发策略)[^2]。 - **Redistributor**(GICv3+):在多核系统中为每个CPU分配独立中断队列。 - **CPU Interface**:处理中断优先级抢占,通过系统寄存器(如`ICC_PMR_EL1`)实现优先级掩码控制[^2]。 #### 2. **Linux内核中的GIC配置** **(1) 设备树配置** GIC信息需在设备树中声明,以下为GICv3示例: ```dts interrupt-controller@fee00000 { compatible = "arm,gic-v3"; // 驱动匹配关键字 reg = <0x0 0xfee00000 0x10000>, // Distributor寄存器基地址 <0x0 0xfef00000 0x200000>; // Redistributor区域 interrupts = <1 9 4>; // GIC自身维护中断(如虚拟化) #interrupt-cells = <3>; // 中断描述符格式(类型、编号、标志) interrupt-controller; // 标记为中断控制器 }; ``` **(2) 驱动实现** Linux内核中GIC驱动位于`drivers/irqchip/irq-gic-v3.c`,关键流程包括: - **初始化**:通过`gic_of_init()`解析设备树,映射寄存器,注册中断控制器。 - **中断处理**:硬件中断触发后,CPU Interface通过异常向量表跳转到`handle_IRQ()`,最终调用GIC驱动的中断处理函数。 #### 3. **关键操作与调试** **(1) 中断状态查看** 通过`/proc/interrupts`查看GIC管理的中断统计: ```bash cat /proc/interrupts CPU0 CPU1 GICv3 27: 1000 1200 arch_timer // 示例:计时器中断 ``` **(2) 中断亲和性设置** 将中断绑定到指定CPU核心(需root权限): ```bash echo 2 > /proc/irq/27/smp_affinity # 将中断27绑定至CPU1(二进制掩码) ``` **(3) 优先级配置** GICv3中优先级通过系统寄存器`ICC_PMR_EL1`控制,Linux内核默认优先级为`0x80`(允许所有中断)。可通过内核启动参数调整: ```bash bootargs="irqchip.gicv3_pseudo_nmi=1" # 启用伪NMI(优先级高于普通中断) ``` #### 4. **版本差异与优化** - **GICv2 vs GICv3**:GICv3引入Redistributor和ITS中断转换服务),支持更多CPU和消息信号中断(MSI)。 - **性能优化**:启用中断分组(安全/非安全)、调整LPI(Locality-specific Peripheral Interrupt)配置[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值