You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM64平台如何实现类x86_64的软件触发中断?

ARM64 中断机制概述

ARM64架构依赖**GIC(通用中断控制器)**管理中断,与x86_64的中断模型差异显著:

  • 中断分为三类:SGI(软件生成中断,ID 0-15,用于核间通信或软件触发)、PPI(私有外设中断,ID 16-31)、SPI(共享外设中断,ID 32+)
  • 无x86独有的vector_irq per-cpu变量,中断映射与触发逻辑由GIC硬件及内核封装接口实现
  • 软件触发中断通常使用SGI,或通过直接操作GIC寄存器触发SPI中断
适配ARM64的软件触发中断实现方案

针对你的Ubuntu Server 22.04 ARM64(内核5.15.0-71)环境,按以下步骤修改驱动:

1. 移除x86平台专属代码

直接删除所有涉及vector_irq的代码,该符号为x86架构私有,ARM64内核无此定义。

2. 替换中断触发逻辑

方案一:使用SGI(软件生成中断)

SGI是ARM64原生支持的软件触发中断,适合核间通信或本地软件触发场景,使用内核封装的gic_send_sgi接口:

#include <linux/irqchip/arm-gic.h>
#include <linux/smp.h>

static ssize_t etx_read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
    int ret;
    const unsigned int sgi_id = 0; // 可选SGI ID范围0-15,避免占用内核默认使用的ID
    cpumask_t target_cpus;

    // 指定触发目标CPU(示例为当前CPU)
    cpumask_clear(&target_cpus);
    cpumask_set_cpu(smp_processor_id(), &target_cpus);

    // 触发SGI中断
    ret = gic_send_sgi(sgi_id, &target_cpus);
    if (ret) {
        pr_err("SGI trigger failed: %d\n", ret);
        return ret;
    }

    pr_info("SGI interrupt triggered\n");
    return len;
}

方案二:使用SPI中断(自定义外设中断)

若需要模拟外设中断的触发逻辑,可申请一个未被占用的SPI中断,通过GIC寄存器触发:

#include <linux/irq.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/smp.h>

static int irq_num; // 需替换为系统可用的SPI中断号,可通过`cat /proc/interrupts`查看

// 中断处理函数
static irqreturn_t etx_irq_handler(int irq, void *dev_id)
{
    pr_info("Interrupt received\n");
    return IRQ_HANDLED;
}

// 模块初始化时申请中断
static int __init etx_driver_init(void)
{
    int ret;

    // 替换为实际可用的SPI中断号
    irq_num = 50;
    ret = request_irq(irq_num, etx_irq_handler, IRQF_SHARED, "etx_softirq", NULL);
    if (ret) {
        pr_err("Request irq failed: %d\n", ret);
        return ret;
    }

    pr_info("Driver loaded\n");
    return 0;
}

// 在read函数中触发SPI中断
static ssize_t etx_read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
    struct irq_desc *desc = irq_to_desc(irq_num);
    if (!desc) {
        pr_err("Invalid irq number\n");
        return -EINVAL;
    }

    // 通过GIC寄存器触发中断
    gic_raise_softirq(cpumask_of(smp_processor_id()), irq_num);

    pr_info("SPI interrupt triggered\n");
    return len;
}

3. 内核配置与验证

  • 确保内核已开启CONFIG_GIC(ARM64 Ubuntu默认开启)
  • 加载驱动后,可通过dmesg查看中断触发与处理日志
  • 若SGI触发失败,需确认所选SGI ID未被内核占用(可参考内核文档中SGI的分配规则)

内容的提问来源于stack exchange,提问作者Dooraim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:30:22