arm64 linux 除零正常返回,arm64上的Linux:从mmapped相干DMA缓冲区发送数据时,sendto会导致“未处理的故障:对齐故障(0x96000021)”...

我正在构建基于配备arm64 CPU的UltraScale + FPGA的数据采集系统。 数据通过DMA传输到RAM。在驱动程序中的DMA缓冲区如下保留:arm64上的Linux:从mmapped相干DMA缓冲区发送数据时,sendto会导致“未处理的故障:对齐故障(0x96000021)”

virt_buf[i] = dma_zalloc_coherent(&pdev->dev, BUF_SIZE, &phys_buf[i],GFP_KERNEL);

在驾驶员MMAP功能,映射到用户空间通过以下方式完成:

#ifdef ARCH_HAS_DMA_MMAP_COHERENT

printk(KERN_INFO "Mapping with dma_map_coherent DMA buffer at phys: %p virt %p\n",phys_buf[off],virt_buf[off]);

res = dma_mmap_coherent(&my_pdev->dev, vma, virt_buf[off], phys_buf[off], vsize);

#else

physical = phys_buf[off];

res=remap_pfn_range(vma,vma->vm_start, physical >> PAGE_SHIFT , vsize, pgprot_noncached(vma->vm_page_prot));

printk(KERN_INFO "Mapping with remap_pfn_range DMA buffer at phys: %p virt %p\n",physical,virt_buf[off]);

#endif

在我的UltraScale + CPU remap_pfn_range是用过的。 在用户空间应用程序中,数据从缓冲区读取,并且当前立即以长度限制为MAX_DGRAM(原始等于572)的UDP数据包发送。

int i = 0;

int bleft = nbytes;

while(i

int bts = bleft < MAX_DGRAM ? bleft : MAX_DGRAM;

if (sendto(fd,&buf[nbuf][i],bts,0, res2->ai_addr,res2->ai_addrlen)==-1) {

printf("%s",strerror(errno));

exit(1);

}

bleft -= bts;

i+= bts;

}

在32位Zynq FPGA上一切正常。但是,在将其移至64位UltraScale + FPGA之后,经过几百次传输后,我开始收到随机错误。

[ 852.703491] Unhandled fault: alignment fault (0x96000021) at 0x0000007f82635584

[ 852.710739] Internal error: : 96000021 [#4] SMP

[ 852.715235] Modules linked in: axi4s2dmov(O) ksgpio(O)

[ 852.720358] CPU: 0 PID: 1870 Comm: a4s2dmov_send Tainted: G D O 4.4.0 #3

[ 852.728001] Hardware name: ZynqMP ZCU102 RevB (DT)

[ 852.732769] task: ffffffc0718ac180 ti: ffffffc0718b8000 task.ti: ffffffc0718b8000

[ 852.740248] PC is at __copy_from_user+0x8c/0x180

[ 852.744836] LR is at copy_from_iter+0x70/0x24c

[ 852.749261] pc : [] lr : [] pstate: 80000145

[ 852.756644] sp : ffffffc0718bba40

[ 852.759935] x29: ffffffc0718bba40 x28: ffffffc06a4bae00

[ 852.765228] x27: ffffffc0718ac820 x26: 000000000000000c

[ 852.770523] x25: 0000000000000014 x24: 0000000000000000

[ 852.775818] x23: ffffffc0718bbe08 x22: ffffffc0710eba38

[ 852.781112] x21: ffffffc0718bbde8 x20: 000000000000000c

[ 852.786407] x19: 000000000000000c x18: ffffffc000823020

[ 852.791702] x17: 0000000000000000 x16: 0000000000000000

[ 852.796997] x15: 0000000000000000 x14: 00000000c0a85f32

[ 852.802292] x13: 0000000000000000 x12: 0000000000000032

[ 852.807586] x11: 0000000000000014 x10: 0000000000000014

[ 852.812881] x9 : ffffffc0718bbcf8 x8 : 000000000000000c

[ 852.818176] x7 : ffffffc0718bbdf8 x6 : ffffffc0710eba2c

[ 852.823471] x5 : ffffffc0710eba38 x4 : 0000000000000000

[ 852.828766] x3 : 000000000000000c x2 : 000000000000000c

[ 852.834061] x1 : 0000007f82635584 x0 : ffffffc0710eba2c

[ 852.839355]

[ 852.840833] Process a4s2dmov_send (pid: 1870, stack limit = 0xffffffc0718b8020)

[ 852.848134] Stack: (0xffffffc0718bba40 to 0xffffffc0718bc000)

[ 852.853858] ba40: ffffffc0718bba90 ffffffc0006a1b2c 000000000000000c ffffffc06a9bdb00

[ 852.861676] ba60: 00000000000005dc ffffffc071a0d200 0000000000000000 ffffffc0718bbdf8

[ 852.869488] ba80: 0000000000000014 ffffffc06a959000 ffffffc0718bbad0 ffffffc0006a2358

[...]

[ 853.213212] Call trace:

[ 853.215639] [] __copy_from_user+0x8c/0x180

[ 853.221284] [] ip_generic_getfrag+0xa4/0xc4

[ 853.227011] [] __ip_append_data.isra.43+0x80c/0xa70

[ 853.233434] [] ip_make_skb+0xc4/0x148

[ 853.238642] [] udp_sendmsg+0x280/0x740

[ 853.243937] [] inet_sendmsg+0x7c/0xbc

[ 853.249145] [] sock_sendmsg+0x18/0x2c

[ 853.254352] [] SyS_sendto+0xb0/0xf0

[ 853.259388] [] el0_svc_naked+0x24/0x28

[ 853.264682] Code: a88120c7 a8c12027 a88120c7 36180062 (f8408423)

[ 853.270791] ---[ end trace 30e1cd8e2ccd56c5 ]---

Segmentation fault

[email protected]_2:~#

奇怪的是,当我只是从缓冲区读取单词时,它不会导致任何对齐错误。

看来,该发送工作不正常使用__copy_from_user功能,引起对齐的内存访问。问题是:它是内核错误,还是我做了不正确的事情?

但是,通常情况下,发送不是以8字节边界开始的数据块不会触发对齐错误。问题发生的概率相对较低。我无法隔离导致错误的条件。

我已经通过调整MAX_DGRAM来解决这个问题,所以它是8的倍数。但是我担心,如果mmapped缓冲区中的数据被提交给更复杂的处理,问题可能会重新出现。有些人在arm64体系结构中报告了与memcpy函数相关的类似问题(例如[https://bugs.launchpad.net/linux-linaro/+bug/1271649]))。

将连贯DMA缓冲区映射到用户空间以避免内存对齐错误的正确方法是什么?

2016-12-12

wzab

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值