title: Two-way communication to PCIe device via /dev/mem in Linux user-space?
body: <p>Pretty sure I already know the answer to this question since there are related questions on SO already (<a href="https://stackoverflow.com/questions/4401912/linux-contiguous-physical-memory-from-userspace">here</a>, <a href="https://stackoverflow.com/questions/5846537/howto-create-100m-byte-buffer">here</a>, and <a href="https://stackoverflow.com/questions/647783/direct-memory-access-in-linux">here</a>,, and <a href="https://unix.stackexchange.com/questions/47208/what-is-the-difference-between-kernel-drivers-and-kernel-modules">this</a> was useful),,, but I wanted to be absolutely sure before I dive into kernel-space driver land (never been there before).</p>
  
  <p>I have a PCIe device that I need to communicate with (and vice versa) from an app in linux user space.  By opening <code>/dev/mem</code>, then <code>mmap</code>'ing,, I have been able to write a user-space driver built on top of <a href="http://www.linuxfromscratch.org/blfs/view/svn/general/pciutils.html" rel="nofollow noreferrer">pciutils</a> that has allowed me to <code>mmap</code> the BARs and successfully write data to the device.  Now, we need comm to go the other direction, from the PCIe device to the linux user app.  In order for this to work, we believe we are going to need a large chunk (~100MB) of physically contiguous memory that never gets paged/swapped.  Once allocated, that address will need to be passed to the PCIe device so it knows where to write its data (thus I don't see how this could be virtual, swappable memory).  Is there any way to do this without a kernel space driver?  One idea here was floated,, perhaps we can open <code>/dev/mem</code> and then feed it an <code>ioctl</code> command to allocate what we need?  If this is possible, I haven't been able to find any examples online yet and will need to research it more heavily.</p>
  
  <p>Assuming we need a kernel space driver, it will be best to allocate our large chuck during bootup, then use <code>ioremap</code> to get a kernel virtual address, then <code>mmap</code> from there to user-space, correct?  From what I've read on <code>kmalloc</code>, we won't get anywhere close to 100MB using that call, and <code>vmalloc</code> is no good since that's virtual memory.  In order to allocate at bootup, the driver should be statically-linked into the kernel, correct?  This is basically an embedded application, so portability is not a huge concern to me.  A module rather than a statically-linked driver could probably work, but my worry there is memory fragmentation could prevent a physically contiguous region from being found, so I'd like to allocate it asap from power-on.  Any feedback?</p>
  
  <p>EDIT1: My CPU is an ARM7 architecture.</p>