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

关于设备树中PCIe根复合体节点ranges属性内核用途的疑问

问题:BIOS预分配PCIe地址后,Linux内核如何使用设备树的ranges属性?

以下是来自linux-5.15.68的arch/arm64/boot/dts/ti/k3-am64-main.dtsi的示例代码:

&cbass_main {
    ... skip ...
    pcie0_rc: pcie@f102000 {
        compatible = "ti,am64-pcie-host", "ti,j721e-pcie-host";
        reg = <0x00 0x0f102000 0x00 0x1000>,
              <0x00 0x0f100000 0x00 0x400>,
              <0x00 0x0d000000 0x00 0x00800000>,
              <0x00 0x68000000 0x00 0x00001000>;
        reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
        ... skip ...   
        #address-cells = <3>;
        #size-cells = <2>;
        ... skip ...
        msi-map = <0x0 &gic_its 0x0 0x10000>;
        ranges = <0x01000000 0x00 0x68001000  0x00 0x68001000  0x00 0x0010000>,
             <0x02000000 0x00 0x68011000  0x00 0x68011000  0x00 0x7fef000>;
        dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x00000010 0x0>;
    };
};

这段ranges属性定义了两个映射规则:

  • 起始地址为0x68001000、大小64KiB的IO空间,映射到父总线地址0x68001000;
  • 起始地址为0x68011000、大小0x7fef000的32位内存空间,映射到父总线地址0x68011000。

根据设备树文档,这些地址均为物理地址。已知BIOS会在枚举过程中为PCIe端点设备的BAR分配总线地址,该操作无需ranges信息,仅按需分配空闲地址范围。当Linux内核读取ranges属性时,BIOS或引导加载程序已为设备分配了与ranges中不同的PCIe地址,此时内核如何使用该ranges属性?


答案

  • 校验地址合法性:内核会用ranges定义的地址范围,检查BIOS分配的BAR地址是否落在PCIe根端口预定义的合法地址空间内。如果分配的地址超出范围,内核会判定地址非法,可能拒绝初始化设备或输出错误日志。
  • 实现地址转换:ranges的核心作用是定义PCIe总线地址到系统物理地址的映射规则。哪怕BIOS已经分配了总线地址,内核仍需要通过ranges来确定这些总线地址对应的系统物理地址,才能在内存中建立正确的映射,让内核和驱动访问到PCIe设备的寄存器或内存区域。
  • 检测资源冲突:内核会基于ranges规定的可用地址范围,排查BIOS分配的地址是否与系统其他设备的资源(如内存、外设地址)冲突。若发现冲突,内核可能尝试重新分配地址(部分场景支持)或记录冲突信息。
  • 支撑DMA地址映射:配合dma-ranges属性,ranges会帮助内核确定PCIe设备DMA操作的地址转换规则,确保设备能正确访问系统内存中的DMA缓冲区——哪怕BIOS已经分配了BAR地址,DMA的地址转换仍依赖这些预定义的映射范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 18:32:28