Kernel Remoteproc框架详解

Table of Contents

1. 简介

remoteproc(Remote Processor,远程处理器)是 Linux 内核提供的异构多核 处理器管理框架,用于统一管理 SoC 上的协处理器、MCU、DSP、RTOS 小核、蓝 牙基带、ISP、VPU 等非 Linux 运行的远程处理器。典型场景:

  • 主核:ARM Cortex-A/A55/A72 跑 Linux
  • 远程核:Cortex-R/M、DSP、RISC-V 跑 RTOS / 裸机固件
  • remoteproc 负责:固件加载、上电复位、启动停止、异常捕获、内存资源分 配、远程日志、故障恢复。

2. 核心作用

  • 把远程处理器抽象成统一设备,屏蔽各厂商上电、复位、内存映射差异;
  • 从文件系统加载固件(.elf/.bin)到远程核共享内存
  • 管理远程核生命周期:上电->加载固件->复位->启动->停止->下电
  • 预留、保护主核与远程核之间的共享内存、DMA 区域、中断资源
  • 配合 rpmsg 框架实现主核 Linux <–> 远程核的进程间通信
  • 远程核崩溃时捕获异常、收集 crash 日志、支持自动重启

3. 整体架构分层

3.1. 用户层接口

  • /dev/remoteprocX 字符设备:用户空间可通过 rprocctl、fw_loader 控制远 程核启停、加载固件
  • sysfs 节点:/sys/class/remoteproc/remoteprocX/

    state        # offlined/stopped/running
    firmware     # 指定固件名,如 imx_rproc_m4.elf
    recover      # 崩溃是否自动恢复
    crash         # 崩溃信息
    
  • 常用操作

    echo imx_m4_fw.elf > /sys/class/remoteproc/remoteproc0/firmware
    echo start > /sys/class/remoteproc/remoteproc0/state
    echo stop > /sys/class/remoteproc/remoteproc0/state
    

3.2. 核心层

  • 生命周期:remoteproc 核心(drivers/remoteproc/remoteproc_core.c), 定义 struct rproc 作为远程处理器抽象对象,统一生命周期管理:
    • rproc_add():注册到内核,创建 sysfs、字符设备
    • rproc_boot():启动流程:加载固件->解析ELF段->分配/映射内存->复位启动 远程核
    • rproc_shutdown():停止远程核、释放资源
    • 崩溃处理:远程核异常触发看门狗 / 异常中断 → 进入 rproc 崩溃处理,可 选自动重启
  • 关键数据结构

    struct rproc {
        struct list_head link;
        const char *name;
        const char *firmware;    // 要加载的固件文件名
        struct device dev;
        struct rproc_ops *ops;   // 平台底层操作回调
        struct fw_priv *fw;      // 固件解析后的段信息
        struct list_head segments; // ELF 代码段、数据段列表
        struct list_head mappings; // 共享内存映射
        void *priv;              // 平台私有数据
        bool auto_recover;       // 崩溃自动重启
        enum rproc_state state;  // 状态机
        ...
    };
    
  • 状态机:
    • RPROC_OFFLINE
    • RPROC_SUSPENDED
    • RPROC_RUNNING
    • RPROC_CRASHED
    • RPROC_STOPPED
    • RPROC_DELETED

3.3. 平台底层层

struct rproc_ops(厂商适配层),remoteproc 核心不直接操作寄存器,由各 SOC 厂商实现硬件操作回调:

struct rproc_ops {
    int (*start)(struct rproc *rproc);       // 上电、去复位、启动小核
    int (*stop)(struct rproc *rproc);        // 停核、复位、下电
    int (*prepare)(struct rproc *rproc);     // 启动前资源准备(时钟、电源、中断)
    int (*unprepare)(struct rproc *rproc);
    void (*kick)(struct rproc *rproc);       // 唤醒远程核(rpmsg 发送后触发)
    int (*da_to_va)(struct rproc *rproc, dma_addr_t da, void **va);
    int (*va_to_da)(struct rproc *rproc, void *va, dma_addr_t *da);
    // 崩溃、异常回调
    void (*crashed)(struct rproc *rproc);
};

3.4. 固件解析层(ELF 加载)

固件解析层采用remoteproc,默认支持 ELF 固件:

  • 内核请求 firmware_class 从 lib/firmware 加载固件文件
  • 解析 ELF 程序段(.text、.data、.bss、.resource 段)
  • 对每一段:
    1. 从 rproc_ops 申请远程核物理地址空间
    2. 将段内容拷贝到共享内存
    3. 建立主核虚拟地址 ↔ 远程核设备地址映射

特殊 .resource 段 远程核固件中自定义的 .resource ELF 段,用于向 Linux 声明需要的资源:

  • 共享内存区域(rpmsg 环形缓冲区)
  • 设备中断、DMA 预留区
  • trace、日志缓冲区
  • rproc 解析该段后自动预留内存,避免主核内存管理覆盖远程核固件区域。

3.5. 配套通信

通信采用rpmsg 子系统, remoteproc 负责把远程核跑起来,rpmsg 负责双核数 据通信,二者强绑定:

  • remoteproc 解析 .resource 段,创建 rpmsg 共享环形缓冲区
  • 注册 virtio 设备,主核 virtio 驱动与远程核 virtio 后端通信
  • 用户态可通过 /dev/rpmsgX、socket 方式收发双核数据

4. 远程核完整启动流程

  • DTS 中定义 remoteproc 节点:指定时钟、复位、共享内存区域、固件名
  • 平台驱动 probe:调用 rproc_alloc + 填充 rproc_ops + rproc_add
  • 用户态写固件名到 sysfs firmware 属性
  • 用户执行 echo start:
    • request_firmware 加载 ELF 固件
    • 解析 ELF 各个段,申请、映射共享内存
    • 执行 rproc_ops->prepare:开时钟、电源、配置内存保护
    • 把固件段拷贝到远程核运行地址
    • 调用 rproc_ops->start:释放复位,远程核从指定入口地址开始运行
  • 远程核启动后,初始化 virtio/rpmsg 驱动,双核建立通信通道

5. 关键资源管理

内存保护

  • DTS 中用 reserved-memory 预留一块物理内存,不进入 Linux 系统内存管理
  • remoteproc 将这块内存作为远程核固件运行区、rpmsg 共享缓冲区
  • 通过 iommu 或物理地址偏移映射,实现主核虚拟地址 ↔ 远程核设备地址转换
  • 禁止 Linux 内存碎片化、OOM 回收占用该区域

6. 常用调试手段

  • 状态和日志

    # 查看远程核状态
    cat /sys/class/remoteproc/remoteproc0/state
    # 查看崩溃日志
    cat /sys/class/remoteproc/remoteproc0/crash
    # 动态开关自动恢复
    echo 1 > /sys/class/remoteproc/remoteproc0/recover
    
  • 内核日志:dmesg | grep remoteproc
  • 固件加载失败常见原因:
    • 固件路径错误(必须放在 /lib/firmware)
    • ELF 段地址超出预留共享内存范围
    • DTS 未正确配置 reserved-memory、时钟复位
    • 内存地址映射、IOMMU 配置错误

7. 关键内核配置选项

CONFIG_REMOTEPROC=y/m          # 开启 remoteproc 核心框架
CONFIG_REMOTEPROC_CDEV=y       # 开启 /dev/remoteproc 字符设备
CONFIG_RPMSG=y                 # 双核通信
CONFIG_RPMSG_VIRTIO=y
CONFIG_FW_LOADER=y             # 固件加载依赖

Author: Joe

Email: bitman@163.com

Created: 2026-07-12 日 12:54

Validate