最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

linux kernel - Is it possible to map memory allocated with kmalloc to userspace, for use in sendmsg with the MSG_ZEROCOPY option

programmeradmin3浏览0评论

I am working on a project where we have a kernel module that allocates memory using kmalloc(), and maps it to userspace using remap_pfn_range(). In remap_pfn_range() the vm_area_structs has its vm_flags field set to VM_IO | VM_PFNMAP (as well as some other flags that seem irrelevant to my problem). When I call sendmsg() using the address returned by our mmap() implementation (which is where the remap_pfn_range() call happens) the sendmsg() call fails with errno EFAULT.

I have tracked down the location in the kernel where -EFAULT is first returned, it happens in check_vma_flags() in mm/gup.c, the problem is that the above mentioned flags are set in the vm_area_struct:

static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
{
    vm_flags_t vm_flags = vma->vm_flags;
    int write = (gup_flags & FOLL_WRITE);
    int foreign = (gup_flags & FOLL_REMOTE);

    if (vm_flags & (VM_IO | VM_PFNMAP))
        return -EFAULT; // <= This error propagates all the way back to userspace.

For background, the allocated memory is shared between the CPU and an FPGA in a Cyclone V SOC-FPGA. The FPGA writes the bulk of the data to the buffers and requires the memory to be physically contiguous. We are currently using v5.3-rc8 of the linux kernel.

The memory mapping works well for regular send() calls without any attempts at zero-copy, but now we need to improve the network transmission speed for our data. In investigating the zero-copy mode for sendmsg() we have observed up to 50% improvements in data transfer rate, when we are using regular userspace allocated memory through malloc().

I have tried unsetting the vm_area_struct.vm_flags bits that correspond to VM_IO and VM_PFNMAP after the call to remap_pfn_range(). This results in sendmsg() actually "succeeding", the syscall returns the size of the buffer that I wished to send. However, no data arrives on the client side. Also, when I reboot the kernel, there are a lot of errors printed on the serial console.

I don't expect what I did to be the correct way to do this. I have to assume that the vm_flags are set for a very good reason, and there are no conditions in remap_pfn_range() that would prevent the flags from being set.

Hence, my question in the title: Is there a way to map memory obtained form kmalloc() to userspace such that it can be passed to sendmsg() with MSG_ZEROCOPY?

Update: I see that there have been a few posts regarding this subject already:

  • Zero-copy user-space TCP send of dma_mmap_coherent() mapped memory

  • Map physical memory to userspace as normal, struct page backed mapping

I will try the suggested answers from those posts and report back here.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论