Address mapping of PCI-memory in Kernel space

吃可爱长大的小学妹 提交于 2019-12-05 14:03:57

I think your code is corrent but you are supposed to check your resource files for the PCI host driver. When you call the funtion "pci_ioremap_bar(pdev, 2)", the function needs some resource data to remap the memory space.

For example,

[2] = {
    .name   = "ep_mem2",
    .start  = PCIE_BASE + 0x1000,
    .end    = PCIE_BASE + 0x2000 - 1,
    .flags  = IORESOURCE_MEM,
}

I think that you accessed the memory space which is not mapped to the PCIe memory spaces for the PCIe device. As you know, BAR is defined by PCIe devices at booting time or rescan time. So the size of BAR is also decided by PCIe devices. You can check it with the booting log. As a result, you should access the memory within the size which is defined by the PCIe device.

Originally PCI buses were like a tree, with "PCI host controller" at the root, bridges at branches, and devices at the leaves. When the CPU writes to the physical address space corresponding to a device's MMIO area, the memory controller has to forward the access to the right PCI host controller (and not RAM or a different PCI host controller and not a different NUMA node), the PCI host controller forwards it to the first PCI bus, then all the bridges on that PCI bus decide to accept or ignore the access and one of them will forward the access to its "secondary bus" (the bus on the other side of the bridge), and so on until it ends up on the bus that the device is on and that device accepts the access (and any other devices on that bus ignore it). Of course you can't have 2 or more devices using the same area of the physical address space for different MMIO areas because that'd be cause conflicts.

For more modern systems there's extra layers of shenanigans (e.g. IOMMUs); and for PCI-express it changed from "tree" to "direct links" (but this doesn't mean you can't and won't see "PCI-E to PCI conventional" bridges with "tree" on the other side of the bridge).

The important thing to understand here is that the firmware configures most of this (and a few other things) to ensure that accesses actually get to the device that they're supposed to (and the kernel may also configure some - e.g. IOMMUs), but a device driver should not randomly decide to trash everything on a whim.

A device driver should not modify PCI BARs, at all, ever. No excuses.

Note: Ideally (for buses that provide device enumeration and resource auto-configuration capabilities - e.g. EISA, MCA, PCI, ..) the kernel would figure everything out, then start the driver and tell the driver which resources (MMIO areas, IRQs, ...) its device uses; and the device driver wouldn't know or care which type of bus the device uses and wouldn't touch PCI configuration space (which might not exist as soon as a "yet another different bus" is invented and the same device is slapped onto a different type of bus).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!