我希望对所有PCIe设备的读写请求都由CPU缓存来缓存。但是,它不符合我的预期。
这些是我对回写MMIO区域的假设。
但是,捕获的TLP不符合我的假设。
我使用以下用户空间程序和设备驱动程序将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
来计算数据包的数量。
系统配置如下。
相关链接
答案 0 :(得分:2)
简而言之,似乎在设计上无法映射MMIO区域回写。
如果有人发现有可能,请上传答案。
我来找John McCalpin的文章和答案。首先,无法映射MMIO区域回写。其次,可以在某些处理器上解决该问题。
无法映射MMIO区域回写
仅供参考:WB类型不适用于内存映射的IO。您可以 对位进行编程以将映射设置为WB,但是系统将 收到不知道如何处理的交易时便崩溃 处理。从理论上讲,可以使用WP或WT进行缓存 从MMIO读取数据,但必须通过软件处理一致性。
只有当我同时将PAT和MTRR都设置为WB时,内核才会崩溃
某些处理器上可能有解决方法
Notes on Cached Access to Memory-Mapped IO Regions, John McCalpin
至少可以对一组映射进行处理 x86-64处理器,它基于MMIO空间两次的映射。 用一组允许写合并的属性映射MMIO范围 存储(但仅未缓存的读取)。再次映射MMIO范围 具有一组允许高速缓存行读取的属性(但仅 未缓存的非写合并存储)。