QEMU 中的 ASPEED AST2700 中断控制器(INTC/INTCIO)架构与 GIC 映射详解
【免费下载链接】qemuOfficial QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.项目地址: https://gitcode.com/gh_mirrors/qe/qemu
ASPEED AST2700 是一款集成双核/四核 Armv8 处理器的服务器管理 SoC,其内部中断源多达 480 个,远超通用 GIC 所能直接承载的中断号范围,因此硬件引入了两级中断控制器:CPU Die 上的 INTC 与 I/O Die 上的 INTCIO,将中断源按 32 位一组压缩后统一送入 GIC。本文以仓库内设计规格文档 docs/specs/aspeed-intc.rst 为骨架,结合 QEMU 中 ASPEED INTC 设备实现(hw/intc/aspeed_intc.c)与 AST2700 SoC 集成代码(hw/arm/aspeed_ast27x0.c),深入讲解两级中断控制器的整体架构、GIC 192–201 的比特映射关系、GICINT 196 的完整信号通路,以及 QEMU 中可观测寄存器与中断处理流程,帮助你快速理解 AST2700 中断子系统在 QEMU 中的落地方式,为调试固件中断配置或扩展新中断源提供可直接对照的参考资料。
一、AST2700 两级中断控制器总体架构
根据 docs/specs/aspeed-intc.rst 的描述,AST2700 共存在480 个中断源。由于处理器 GIC 可分配的中断号有限,硬件将编号大于 127 的中断源每 32 个合并为一组,从而压缩中断线数量。整个中断子系统由两个层级的中断控制器构成:
| 层级 | 名称 | 所在 Die | 职责范围 |
|---|---|---|---|
| 第一级 | INTC(CPU Die) | CPU Die | 处理中断源 0 – 127,并汇聚 INTCIO 送入的信号 |
| 第二级 | INTCIO(I/O Die) | I/O Die | 独立处理中断源 128 – 319 |
在 QEMU 中,这一两级结构被建模为多个可独立实例化的 SysBus 设备类型(定义于 include/hw/intc/aspeed_intc.h):
aspeed.intc-ast2700:INTC(CPU Die);aspeed.intcio-ast2700:INTCIO(I/O Die);aspeed.intc-ast2700-ioexp1/aspeed.intc-ast2700-ioexp2:AST1700 外扩(IOEXP)INTCIO,对应 GIC 198–201;aspeed.intc-ast2700ssp/aspeed.intc-ast2700ssp-io、aspeed.intc-ast2700tsp/aspeed.intc-ast2700tsp-io:SSP(Secure System Processor)与 TSP(TEE System Processor)各自私有的 INTC/INTCIO,用于其 160–165 号私有中断。
每个设备实例通过AspeedINTCClass上的num_lines、num_inpins、num_outpins、mem_size、nr_regs、reg_offset与irq_table等类参数刻画各自的规格(include/hw/intc/aspeed_intc.h)。例如 AST2700 主 INTC 的类参数为:num_lines = 32、num_inpins = 1、num_outpins = 10、内存区大小0x4000、寄存器区相对偏移0x1000(hw/intc/aspeed_intc.c);而 INTCIO 则为num_inpins = 6、num_outpins = 6、内存区0x400、寄存器区偏移0x100(hw/intc/aspeed_intc.c)。
二、中断映射:INTC 与 INTCIO 的分工
文档明确了两个控制器的职责边界:
- INTC:处理中断源 0 – 127,并接收来自 INTCIO 的汇聚信号;
- INTCIO:独立处理中断源 128 – 319。
在 QEMU 实现中,这一分工通过每个输入引脚(inpin)对应的orgate(或门)来落实。AspeedINTCState内嵌了最多 10 个OrIRQState orgates[],每个 inpin 绑定一个 32 输入、1 输出的或门,将最多 32 个源信号“或”成一条线再送入 INTC 控制器主体(include/hw/intc/aspeed_intc.h、hw/intc/aspeed_intc.c)。aspeed_intc_orgate_levels()会把 orgate 上当前拉高的输入线汇聚成一个 32 位位图,作为该 inpin 的“源中断电平快照”(hw/intc/aspeed_intc.c)。
AST2700 主 INTC 的irq_table只有一项:
static AspeedINTCIRQ aspeed_2700_intc_irqs[ASPEED_INTC_MAX_INPINS] = { {0, 0, 10, R_GICINT192_201_EN, R_GICINT192_201_STATUS}, };含义是:输入引脚 0 对应输出引脚 0–9 共 10 条输出线,其使能寄存器为GICINT192_201_EN、状态寄存器为GICINT192_201_STATUS(hw/intc/aspeed_intc.c)。这正是文档所述“GIC 192 至 201 的中断源来自 INTCIO,经 INTC 输入引脚 0 汇入、由输出引脚 0–9 输出到 GIC”的代码体现。
三、INTC GIC_192_201 输出引脚映射表
文档给出了 INTCGIC_192_201组件的 10 个输出引脚与 GIC 中断号的对应关系:
| Bit | GIC |
|---|---|
| 0 | 192 |
| 1 | 193 |
| 2 | 194 |
| 3 | 195 |
| 4 | 196 |
| 5 | 197 |
| 6 | 198 |
| 7 | 199 |
| 8 | 200 |
| 9 | 201 |
该映射在 SoC 集成层被显式编码。hw/arm/aspeed_ast27x0.c中ast2700_gic_intcmap[]将 GIC 192–201 与 INTC 实例索引(intc_idx)及 orgate 索引(orgate_idx)关联起来:
static const struct gic_intc_irq_info ast2700_gic_intcmap[] = { {192, 1, 0, ast2700_gic192_intcmap}, {193, 1, 1, NULL}, {194, 1, 2, ast2700_gic194_intcmap}, {195, 1, 3, ast2700_gic195_intcmap}, {196, 1, 4, ast2700_gic196_intcmap}, {197, 1, 5, ast2700_gic197_intcmap}, {198, 2, 0, ast2700_gic198_intcmap}, {199, 2, 1, ast2700_gic199_intcmap}, {200, 3, 0, ast2700_gic200_intcmap}, {201, 3, 1, ast2700_gic201_intcmap}, };其中intc_idx = 1表示 INTCIO,intc_idx = 2/3表示两个 IOEXP INTCIO(hw/arm/aspeed_ast27x0.c)。SoC 的aspeed_soc_ast2700_get_irq()据此把设备中断请求线接到对应 orgate 的输入,例如 GIC 196 的所有源(ETH1/ETH2/ETH3、UART0/1/2/3/5–12、EHCI3/4、PCIE2)都落在intc[1].orgates[4]上(hw/arm/aspeed_ast27x0.c)。AST2700 的 GIC 中断号上限为AST2700_MAX_IRQ = 256,SoC 实例化 GICv3 时num-irq被配置为AST2700_MAX_IRQ + GIC_INTERNAL(hw/arm/aspeed_ast27x0.c、hw/arm/aspeed_ast27x0.c),为 GIC 192–201 这些 SPI 提供了充足的编号空间。
四、GICINT 196 信号通路设计解析
文档以GICINT 196为示例,给出了完整的信号通路设计,这也是 QEMU 中建模得最完整的一条链路:
- 一个 32 输入或门
orgates[0](文档图中对应输入 0–31),其输入汇集了 ETH1/ETH2/ETH3、UART0/1/2/3/5–12 等外设中断; - 该或门的输出接到 INTCIO 的
T0 GICINT_196输入引脚; - INTCIO 的输出引脚接到 INTC
GIC_192_201组的bit 4; - INTC
GIC_192_201的 bit 4 输出引脚接到GIC 196。
文档中的完整框图如下(AST2700 A1 设计):
|-------------------------------------------------------------------------------------------------------| | AST2700 A1 Design | | To GICINT196 | | | | ETH1 |-----------| |--------------------------| |--------------| | | ------->|0 | | INTCIO | | orgates[0] | | | ETH2 | 4| orgates[0]------>|inpin[0]-------->outpin[0]|------->| 0 | | | ------->|1 5| orgates[1]------>|inpin[1]-------->outpin[1]|------->| 1 | | | ETH3 | 6| orgates[2]------>|inpin[2]-------->outpin[2]|------->| 2 | | | ------->|2 19| orgates[3]------>|inpin[3]-------->outpin[3]|------->| 3 OR[0:9] |-----| | | UART0 | 20|-->orgates[4]------>|inpin[4]-------->outpin[4]|------->| 4 | | | | ------->|7 21| orgates[5]------>|inpin[5]-------->outpin[5]|------->| 5 | | | | UART1 | 22| orgates[6]------>|inpin[6]-------->outpin[6]|------->| 6 | | | | ------->|8 23| orgates[7]------>|inpin[7]-------->outpin[7]|------->| 7 | | | | UART2 | 24| orgates[8]------>|inpin[8]-------->outpin[8]|------->| 8 | | | | ------->|9 25| orgates[9]------>|inpin[9]-------->outpin[9]|------->| 9 | | | | UART3 | 26| |--------------------------| |--------------| | | | ------->|10 27| | | | UART5 | 28| | | | ------->|11 29| | | | UART6 | | | | | ------->|12 30| |-----------------------------------------------------------------------| | | UART7 | 31| | | | ------->|13 | | | | UART8 | OR[0:31] | | |-----------------------------| |----------| | | ------->|14 | | | INTC | | GIC | | | UART9 | | | |inpin[0:0]--------->outpin[0]|--------->|192 | | | ------->|15 | | |inpin[0:1]--------->outpin[1]|--------->|193 | | | UART10 | | | |inpin[0:2]--------->outpin[2]|--------->|194 | | | ------->|16 | | |inpin[0:3]--------->outpin[3]|--------->|195 | | | UART11 | | |--------------> |inpin[0:4]--------->outpin[4]|--------->|196 | | | ------->|17 | |inpin[0:5]--------->outpin[5]|--------->|197 | | | UART12 | | |inpin[0:6]--------->outpin[6]|--------->|198 | | | ------->|18 | |inpin[0:7]--------->outpin[7]|--------->|199 | | | |-----------| |inpin[0:8]--------->outpin[8]|--------->|200 | | | |inpin[0:9]--------->outpin[9]|--------->|201 | | | |-----------------------------| |----------| | |-------------------------------------------------------------------------------------------------------|这条通路在 QEMU 中通过 SoC realize 阶段的 GPIO 级联完整复现(hw/arm/aspeed_ast27x0.c):
- 每个 INTC 输入引脚由 orgate 驱动:
qdev_connect_gpio_out(orgates[i], 0, qdev_get_gpio_in(intc, i)); - INTC 的 10 个输出引脚按
ast2700_gic_intcmap[i].irq接到 GICv3 对应 SPI:sysbus_connect_irq(intc[0], i, qdev_get_gpio_in(gic, 192 + i)); - INTCIO 的 6 个输出引脚逐一接到 INTC 的
orgates[0]输入端:sysbus_connect_irq(intc[1], i, qdev_get_gpio_in(intc[0].orgates[0], i))。
由此可见,GICINT 196 恰好对应 INTCIO 输出引脚 4 → INTCorgates[0]输入端 4 → INTC 输出引脚 4 → GIC SPI 196,与文档框图完全一致。
五、QEMU 支持范围与实现要点
文档明确指出:当前 QEMU 仅支持 GIC 192 至 GIC 201,这些中断源全部来自 INTCIO,经 INTC 输入引脚 0 汇入、由输出引脚 0–9 输出到 GIC。与之对应,AST2700 的 INTCIO 设备irq_table包含 6 项,每项把 1 个 inpin 映射到 1 个 outpin(1:1 映射),覆盖 GICINT192–197:
static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS}, {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS}, {2, 2, 1, R_GICINT194_EN, R_GICINT194_STATUS}, {3, 3, 1, R_GICINT195_EN, R_GICINT195_STATUS}, {4, 4, 1, R_GICINT196_EN, R_GICINT196_STATUS}, {5, 5, 1, R_GICINT197_EN, R_GICINT197_STATUS}, };而 GIC 198–201 则由两个 IOEXP INTCIO 设备承接(aspeed_2700_intcioexp1_irqs/aspeed_2700_intcioexp2_irqs,各含 2 项,hw/intc/aspeed_intc.c),对应 AST1700 外扩处理器的 I2C/I3C 中断组。此外,SSP 与 TSP 各自拥有一对 INTC/INTCIO(aspeed_2700ssp_*、aspeed_2700tsp_*),为 SSP/TSP 私有中断源 160–165 提供同样的两级汇聚机制(hw/intc/aspeed_intc.c)。
设备地址映射方面,AST2700 中相关控制器的 MMIO 基址为(hw/arm/aspeed_ast27x0.c):
| 控制器 | MMIO 基址 |
|---|---|
| ASPEED_DEV_INTC(CPU Die INTC) | 0x12100000 |
| ASPEED_DEV_INTCIO(I/O Die INTCIO) | 0x14C18000 |
六、寄存器模型与中断处理语义
QEMU 为 INTC/INTCIO 定义了独立的寄存器位域,具体偏移见 hw/intc/aspeed_intc.c:
INTC(CPU Die)寄存器(MMIO 区起始于 0x1000,故寄存器偏移相对数据手册减 0x1000):
| 寄存器 | 偏移 | 说明 |
|---|---|---|
GICINT192_201_EN | 0xB00 | GIC 192–201 组使能寄存器 |
GICINT192_201_STATUS | 0xB04 | GIC 192–201 组状态寄存器 |
INTCIO(I/O Die)寄存器(MMIO 区起始于 0x100,偏移相对数据手册减 0x100):
| 寄存器 | 偏移 |
|---|---|
GICINT192_EN/GICINT192_STATUS | 0x00 / 0x04 |
GICINT193_EN/GICINT193_STATUS | 0x10 / 0x14 |
GICINT194_EN/GICINT194_STATUS | 0x20 / 0x24 |
GICINT195_EN/GICINT195_STATUS | 0x30 / 0x34 |
GICINT196_EN/GICINT196_STATUS | 0x40 / 0x44 |
GICINT197_EN/GICINT197_STATUS | 0x50 / 0x54 |
此外还有 SSP 的SSPINT160_169_EN/STATUS(0x2B00/0x2B04,INTCIO 侧 0x180–0x1D4)与 TSP 的TSPINT160_169_EN/STATUS(0x3B00/0x3B04,INTCIO 侧 0x200–0x254)两组私有寄存器。所有寄存器访问都限定为 32 位、小端访问(MemoryRegionOps中impl.min_access_size = max_access_size = 4,hw/intc/aspeed_intc.c),并配有aspeed_intc_read/write、aspeed_intcio_read/write、aspeed_ssp_intc_*、aspeed_tsp_intc_*多套读写回调分别挂到各设备的内存区。
中断状态机方面,设备维护了三组每输入引脚一份的软件状态:
enable[]:该 inpin 上各源中断的使能位图;mask[]:ISR 执行期间的掩码位图;pending[]:ISR 尚未完成时到达的源中断位图。
整体语义如下(hw/intc/aspeed_intc.c):
- 外设拉起某个源中断后,
aspeed_intc_set_irq()扫描 orgate 电平并过滤掉未使能的位,得到select位图; - 若对应 inpin 正处于掩码状态(
mask非 0)或状态寄存器中仍有未清除的位(说明前一个中断的 ISR 还没执行完),则把新到达的位追加到pending,不重复触发输出; - 否则把
select写入 STATUS 寄存器,并通过qemu_set_irq()把对应输出引脚拉高,通知 GIC; - 固件完成 ISR 后写 STATUS 寄存器清除相应位,
aspeed_intc_status_handler()在全部位清零后检查pending,若有滞留中断则重新置位 STATUS 并再次拉高输出,否则拉低输出(hw/intc/aspeed_intc.c)。
INTC 的GICINT192_201_STATUS走的是多输出引脚路径aspeed_intc_status_handler_multi_outpins(),逐 bit 独立完成上述“清除 → 重放 pending → 更新对应输出引脚”的流程(hw/intc/aspeed_intc.c),与文档中 10 个输出引脚一一对应的设计吻合。整个过程的读写、触发、屏蔽、pending 行为都通过 hw/intc/trace-events 中定义的aspeed_intc_*系列 trace 事件暴露,可用-trace aspeed_intc*观测。
七、固件侧配置要点
结合上述寄存器模型,固件在 QEMU 模拟的 AST2700 上配置 GICINT 196 的典型步骤为:
- 使能源中断:向 INTCIO 的
GICINT196_EN(基址0x14C18000+ 偏移0x40)写入需要使能的位图。例如使能 UART0(bit 7)与 ETH1(bit 0),即写入0x81; - 使能组中断:向 INTC 的
GICINT192_201_EN(基址0x12100000+ 偏移0x1000 + 0xB00)写入 bit 4(对应 GICINT 196),即写入0x10; - 配置 GICv3:为 SPI 196 配置优先级、目标核并
GICD_ISENABLER使能,等待中断上报; - ISR 完成后清状态:ISR 中读取
GICINT196_STATUS(0x14C18000 + 0x44)获取源中断位,处理完回写该位清除;QEMU 会自动重放 ISR 期间新到达的 pending 中断,无需额外处理丢失中断的情况。
需要注意的是,当前 QEMU 实现覆盖范围以文档声明为准(仅 GIC 192–201),GICINT 128–136 等文档未列出的中断映射在 SoC 层代码注释中有所提及(hw/intc/aspeed_intc.c),但尚未作为完整功能开放,调试时应以 docs/specs/aspeed-intc.rst 与 SoC 层ast2700_gic_intcmap[]的实际连线为准。
八、总结
AST2700 通过“INTC(CPU Die)+ INTCIO(I/O Die)”的两级中断控制器设计,把 480 个中断源压缩映射到 GIC 可承载的中断号上:每 32 个源合并为一个 or 门,经 INTCIO 汇聚到 INTC,再按 bit 位映射到 GIC 192–201。QEMU 中 hw/intc/aspeed_intc.c 完整建模了这套两级结构、寄存器集合、使能/掩码/pending 状态机与多输出引脚触发逻辑,hw/arm/aspeed_ast27x0.c 则在 SoC 层通过 orgate 级联与 GIC 连线将 GICINT 196 等通路逐一复现。阅读本文后,你可以对照寄存器偏移表与中断映射表,在 QEMU 中定位并验证 AST2700 任意已支持外设的中断行为,也可以基于 include/hw/intc/aspeed_intc.h 中清晰的类参数扩展新的 INTC 变体。
【免费下载链接】qemuOfficial QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.项目地址: https://gitcode.com/gh_mirrors/qe/qemu
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考