我有一个pci设备驱动程序,它使用CMA分配机制进行DMA分配。它在32位模式下在内核3.18上工作正常但是当我尝试在64内核中使用它时(与32位相同的配置,但在64位模式下切换)dma分配失败。
我在dmesg中看到的只有:
fallback device: swiotlb buffer is full (sz: 8388608 bytes)
我使用内核cmdline:
swiotlb=16384 iommu=soft cma=256M
并分配8Mb。
函数调用是:
new_region->kaddr = dma_alloc_coherent( NULL, size, &new_region->paddr, GFP_KERNEL | GFP_DMA32 );
有人可以用64位模式解释这种行为吗?
答案 0 :(得分:2)
经过更多调查,我认为你可能和我有同样的根源,只是列出来供你参考。 CMA分配将从最高内存块开始,因此如果你有更多的3G内存,最后一个物理内存将高于0xFFFFFFFF,这意味着CMA的基地址高于4GB,但dma_allocat_coherent()要求地址低于掩码[(0x1<< 32)-1] = 0xFFFFFFFF,如果同步的dma结束地址大于0xFFFFFFFF,它将回退到swiotlb缓冲区,然后你会看到你描述的错误。请看下面的内存映射,最后2G是4GB以上的内存空间。
要解决此问题,我们可以指定cma起始地址,大小和限制大小以手动控制CMA保留位置。
e820: BIOS-provided physical RAM map:
BIOS-e820: [mem 0x0000000000000000-0x000000000009ffff] usable
BIOS-e820: [mem 0x00000000000a0000-0x00000000000fffff] reserved
BIOS-e820: [mem 0x0000000000100000-0x00000000779c4fff] usable
BIOS-e820: [mem 0x00000000779c5000-0x0000000077a45fff] reserved
BIOS-e820: [mem 0x0000000077a46000-0x0000000079426fff] usable
BIOS-e820: [mem 0x0000000079427000-0x000000007b32efff] reserved
BIOS-e820: [mem 0x000000007b32f000-0x000000007b985fff] ACPI NVS
BIOS-e820: [mem 0x000000007b986000-0x000000007bad3fff] ACPI data
BIOS-e820: [mem 0x000000007bad4000-0x000000007bafffff] usable
BIOS-e820: [mem 0x000000007bb00000-0x000000008fffffff] reserved
BIOS-e820: [mem 0x00000000fed1c000-0x00000000fed1ffff] reserved
BIOS-e820: [mem 0x0000000100000000-0x000000017fffffff] usable
cma=nn[MG]@[start[MG][-end[MG]]]
[ARM,X86,KNL]
Sets the size of kernel global memory area for
contiguous memory allocations and optionally the
placement constraint by the physical address range of
memory allocations. A value of 0 disables CMA
altogether. For more information, see
include/linux/dma-contiguous.h
首先为您提供解决方法,请在内核中添加“mem = 3072M” 命令行。然后它将适用于您的情况。你之所以看到 这可能与传递给函数的NULL有关 dma_alloc_coherent()。它默认使用x86_dma_fallback_dev。 一旦我获得更多信息,将会更新。