Large PCIe DMA Linux x86-64
Large PCIe DMA Linux x86-64
我使用的是一个高速串行卡,用于从外部源到带有PCIe卡的Linux机箱的高速数据传输。PCIe卡附带了一些第三方驱动程序,这些驱动程序使用dma_alloc_coherent来分配dma缓冲区以接收数据。然而,由于Linux的限制,这种方法将数据传输限制在4MB。我一直在阅读并尝试多种分配大DMA缓冲区的方法,但都没能找到一种方法。
这个系统有32GB的内存,运行的是内核版本为3.10的Red Hat,我想让其中的4GB可用于连续的DMA。我知道首选的方法是分散/聚集,但在我的情况下这是不可能的,因为有一个硬件芯片可以将串行协议转换为我无法控制的DMA,我唯一可以控制的就是向传入地址添加偏移(即,从外部系统看到的地址0可以映射到本地总线上的地址0x70000000)。
由于这是一台一次性的实验室机器,我认为最快/最简单的方法是使用mem=28GB引导配置参数。我可以很好地工作,但从虚拟空间访问内存的下一步是我遇到问题的地方。以下是我的代码浓缩到相关组件:
在内核模块中:
size_t len = 0x100000000ULL; // 4GB
size_t phys = 0x700000000ULL; // 28GB
size_t virt = ioremap_nocache( phys, len ); // address not usable via direct reference
size_t bus = (size_t)virt_to_bus( (void*)virt ); // this should be the same as phys for x86-64, shouldn't it?
// OLD WAY
/*size_t len = 0x400000; // 4MB
size_t bus;
size_t virt = dma_alloc_coherent( devHandle, len, &bus, GFP_ATOMIC );
size_t phys = (size_t)virt_to_phys( (void*)virt );*/
在应用程序中:
// Attempt to make a usable virtual pointer
u32 pSize = sysconf(_SC_PAGESIZE);
void* mapAddr = mmap(0, len+(phys%pSize), PROT_READ|PROT_WRITE, MAP_SHARED, devHandle, phys-(phys%pSize));
virt = (size_t)mapAddr + (phys%pSize);
// do DMA to 0x700000000 bus address
printf("Value %xn", *((u32*)virt)); // this is returning zero
另一件有趣的事情是,在完成所有这些之前,从dma_alloc_coherent返回的物理地址大于系统上的RAM数量(0x83d000000)。我认为在x86中,RAM将始终是最低的地址,因此我希望地址小于32GB。
如有任何帮助,我们将不胜感激。
不要通过mem
限制系统内存量,而是尝试使用CMA:https://lwn.net/Articles/486301/
使用CMA内核命令行参数可以为保证连续的DMA操作保留一定量的内存。内核将允许非DMA进程访问该内存,但一旦DMA操作需要该内存,非DMA进程就会被逐出。因此,我建议不要更改mem
参数,而是将cma=4G
添加到cmdline中。dma_alloc_coherent
应该自动从保留的空间中提取,但您可以在内核配置中启用CMA调试来确保这一点。
- 您选择的 CPU 不支持 x86-64 指令集
- std::atomic::fetch_add是x86-64上的串行化操作
- Apple Mach-O-Linker 错误:在体系结构 x86-64 中找不到从(行)引用的变量
- x86-64 程序集:为什么偏移 25 字节
- DIS(P X)-X在GCC Linux X86-64 C 中始终导致Pointer P和Integer X的P
- 什么是 gcc Linux x86-64 C++中的有效指针
- X86-64上的C :何时通过结构/类在寄存器中返回
- x86-64 调用约定中的返回值
- C++Mac上使用Linux库(x86_64-Apple-Darwin上的elf64-x86-64)
- 如何使用64-Linux上的C 中的新操作员动态分配大型内存,例如10 g
- x86-64上检查指针范围是否跨越N字节对齐地址的最快方法
- 如何使用C++11为x86(-64)安全地编写测试和测试集(TATAS)自旋锁
- 在 x86-64 平台上为 C(++) 中的 64 位无符号参数计算 (a*b)%n FAST
- x86-64 movl and cmpl difference
- visual x86-64 MSVC++/Intel C++更改int、long等的大小
- x86-64 汇编程序中的无限循环
- Large PCIe DMA Linux x86-64
- 读写线程安全智能指针在c++, x86-64
- (clang / llvm-mc / lld) hello world (x86-64 Windows & Linux)
- 用于 x86/64 的 Itanium 交叉编译器