我希望所有对PCIe设备的读写请求都由CPU缓存来缓存。但是,它没有按我预期的那样工作。

这些是我对回写MMIO区域的假设。

  • 仅在回写高速缓存时才写入PCIe设备。
  • TLP有效负载的大小为缓存块大小(64B)。

  • 但是,捕获的TLP不符合我的假设。
  • 对MMIO区域的每次写入都会发生对PCIe设备的写入。
  • TLP有效负载的大小为1B。

  • 我使用以下用户空间程序和设备驱动程序将8字节的0xff写入MMIO区域。

    用户程序的一部分
    struct pcie_ioctl ioctl_control;
    ioctl_control.bar_select = BAR_ID;
    ioctl_control.num_bytes_to_write = atoi(argv[1]);
    if (ioctl(fd, IOCTL_WRITE_0xFF, &ioctl_control) < 0) {
        printf("ioctl failed\n");
    }
    

    设备驱动程序的一部分
    case IOCTL_WRITE_0xFF:
    {
        int i;
        char *buff;
        struct pci_cdev_struct *pci_cdev = pci_get_drvdata(fpga_pcie_dev.pci_device);
        copy_from_user(&ioctl_control, (void __user *)arg, sizeof(ioctl_control));
        buff = kmalloc(sizeof(char) * ioctl_control.num_bytes_to_write, GFP_KERNEL);
        for (i = 0; i < ioctl_control.num_bytes_to_write; i++) {
            buff[i] = 0xff;
        }
        memcpy(pci_cdev->bar[ioctl_control.bar_select], buff, ioctl_control.num_bytes_to_write);
        kfree(buff);
        break;
    }
    

    我修改了MTRR以使相应的MMIO区域回写。 MMIO区域从0x0c7300000开始,长度为0x100000(1MB)。以下是不同策略的cat /proc/mtrr结果。请注意,我将每个地区都设为独家。

    不可缓存的
    reg00: base=0x080000000 ( 2048MB), size= 1024MB, count=1: uncachable
    reg01: base=0x380000000000 (58720256MB), size=524288MB, count=1: uncachable
    reg02: base=0x0c0000000 ( 3072MB), size=   64MB, count=1: uncachable
    reg03: base=0x0c4000000 ( 3136MB), size=   32MB, count=1: uncachable
    reg04: base=0x0c6000000 ( 3168MB), size=   16MB, count=1: uncachable
    reg05: base=0x0c7000000 ( 3184MB), size=    1MB, count=1: uncachable
    reg06: base=0x0c7100000 ( 3185MB), size=    1MB, count=1: uncachable
    reg07: base=0x0c7200000 ( 3186MB), size=    1MB, count=1: uncachable
    reg08: base=0x0c7300000 ( 3187MB), size=    1MB, count=1: uncachable
    reg09: base=0x0c7400000 ( 3188MB), size=    1MB, count=1: uncachable
    

    写组合
    reg00: base=0x080000000 ( 2048MB), size= 1024MB, count=1: uncachable
    reg01: base=0x380000000000 (58720256MB), size=524288MB, count=1: uncachable
    reg02: base=0x0c0000000 ( 3072MB), size=   64MB, count=1: uncachable
    reg03: base=0x0c4000000 ( 3136MB), size=   32MB, count=1: uncachable
    reg04: base=0x0c6000000 ( 3168MB), size=   16MB, count=1: uncachable
    reg05: base=0x0c7000000 ( 3184MB), size=    1MB, count=1: uncachable
    reg06: base=0x0c7100000 ( 3185MB), size=    1MB, count=1: uncachable
    reg07: base=0x0c7200000 ( 3186MB), size=    1MB, count=1: uncachable
    reg08: base=0x0c7300000 ( 3187MB), size=    1MB, count=1: write-combining
    reg09: base=0x0c7400000 ( 3188MB), size=    1MB, count=1: uncachable
    

    写回
    reg00: base=0x080000000 ( 2048MB), size= 1024MB, count=1: uncachable
    reg01: base=0x380000000000 (58720256MB), size=524288MB, count=1: uncachable
    reg02: base=0x0c0000000 ( 3072MB), size=   64MB, count=1: uncachable
    reg03: base=0x0c4000000 ( 3136MB), size=   32MB, count=1: uncachable
    reg04: base=0x0c6000000 ( 3168MB), size=   16MB, count=1: uncachable
    reg05: base=0x0c7000000 ( 3184MB), size=    1MB, count=1: uncachable
    reg06: base=0x0c7100000 ( 3185MB), size=    1MB, count=1: uncachable
    reg07: base=0x0c7200000 ( 3186MB), size=    1MB, count=1: uncachable
    reg08: base=0x0c7300000 ( 3187MB), size=    1MB, count=1: write-back
    reg09: base=0x0c7400000 ( 3188MB), size=    1MB, count=1: uncachable
    

    以下是使用不同策略进行8B写入的波形捕获。我已经使用集成逻辑分析仪(ILA)捕获这些波形。设置了pcie_endpoint_litepcietlpdepacketizer_tlp_req_payload_dat后,请观看pcie_endpoint_litepcietlpdepacketizer_tlp_req_valid。在这些波形示例中,您可以通过计算pcie_endpoint_litepcietlpdepacketizer_tlp_req_valid来计算数据包的数量。
  • 不可缓存的:link->正确,1B x 8包
  • 写组合:link->正确,8B x 1包
  • 写回:link->意外,1B x 8包

  • 系统配置如下。
  • CPU :英特尔(R)至强(R)CPU E5-2630 v4 @ 2.20GHz
  • 操作系统:Linux内核4.15.0-38
  • PCIe设备:用litepcie编程的Xilinx FPGA KC705

  • 相关链接
  • Generating a 64-byte read PCIe TLP from an x86 CPU
  • How to Implement a 64B PCIe* Burst Transfer on Intel® Architecture
  • Write Combining Buffer Out of Order Writes and PCIe
  • Do Ryzen support write-back caching for Memory Mapped IO (through PCIe interface)?
  • MTRR (Memory Type Range Register) control
  • PATting Linux
  • Down to the TLP: How PCI express devices talk (Part I)
  • 最佳答案

    简而言之,似乎在设计上无法映射MMIO区域回写。

    如果有人发现有可能,请上传答案。

    我来找约翰·麦卡宾(John McCalpin)的文章和答案。首先,无法映射MMIO区域回写。其次,可以在某些处理器上解决该问题。

  • 无法映射MMIO区域

    Quote from this link



    Quote from this link

  • 在某些处理器上可以解决方法

    Notes on Cached Access to Memory-Mapped IO Regions, John McCalpin

  • 关于linux - 映射MMIO区域回写不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53311131/

    10-16 12:21