【问题标题】:How does Linux kernel set PCI BARs so that there is no address conflict?Linux 内核如何设置 PCI BAR 以保证没有地址冲突?
【发布时间】:2020-01-17 20:23:58
【问题描述】:

据我了解,(这很可能是错误的)每个 PCI 设备都知道它想要声明多少(大小)iomem/ioport 地址空间,但它不知道在哪里(偏移量)。只有 BIOS 或 OS 可以告诉设备该位置应该在哪里,因为有人必须与所有 PCI 设备通信并协调它们的 iomem/ioport 地址分配请求,以便分配的地址不会重叠,并且这种协调发生在启动时,或热插拔事件,或在pci rescan 期间。但是,在 Linux 内核代码中,我只找到了一个函数 (pci_read_bases),它读取 BAR 信息,并相应地设置 pci_dev & iomem_resource/ioport_resource,而不更改 BAR。所以问题是:

  1. 操作系统(Linux 内核)可以更改 BAR 吗?还是只有 BIOS 才能在加载操作系统之前做到这一点?
  2. 如果内核可以更改 BAR,那么协调地址分配的逻辑在哪里? (我确实看到了像 pbus_assign_resources_sorted 这样的函数,但在我看来,该函数只将现有的 BAR 映射到像 iomem_resource 这样的内核对象,而不是更改 BAR)

【问题讨论】:

    标签: c io linux-kernel pci


    【解决方案1】:

    对于正常的静态分配,BIOS 写入 BAR,内核在启动时读取它们。有趣的是动态分配的设备,例如 NVMe 卡的热插拔。在这种情况下,BIOS 必须保留一个范围,以防插入的设备在启动时不存在或大于移除的设备。内核收到一个中断,必须读取新的 BAR 值并将它们添加到地址空间。例如见nvme_remap_barhttps://elixir.bootlin.com/linux/v5.4/source/drivers/nvme/host/pci.c#L1649

    【讨论】:

    • 谢谢。所以这意味着内核永远不会写入 BAR?对于热插拔设备和静态设备,负责分配引导未使用地址空间的 BAR 的是 BIOS?
    • BIOS 枚举设备并分配 PCI 地址。我不会说内核从不写 BAR,因为那里有很多奇怪的设备——比如带有 PCI 开关的双根复合体。但是,如果您做任何正常的事情,您只需阅读 BAR。
    猜你喜欢
    • 2014-06-16
    • 2020-05-02
    • 2015-04-02
    • 2011-09-08
    • 2016-05-05
    • 2023-03-06
    • 2020-08-21
    • 1970-01-01
    • 2017-11-26
    相关资源
    最近更新 更多