shm_open, mmap and DMA buffers

Hi,

I have a DMA buffer created with mmap(…MAP_PHYS|MAP_ANON…), but now I
need to expose this DMA buffer through a shared memory object. I’ve tried
all sorts of combinations of shm_open, mmap, shm_ctl, but nothing seems to
work!

If someone knows the magic sequence please tell me!

Kieran.

Kieran Tyrrell wrote:

I have a DMA buffer created with mmap(…MAP_PHYS|MAP_ANON…), but
now I need to expose this DMA buffer through a shared memory object.
I’ve tried all sorts of combinations of shm_open, mmap, shm_ctl, but
nothing seems to work!

I believe you’re doing things backwards. First you create a shared
memory object with shm_open, grow it to the size you need using
ftruncate and them use mmap to map the shared object.

As far as I can tell, you can’t MAP_ANON memory and then expect to
turn it into a shared memory object.

Refer to the detailed examples at:
http://qdn.qnx.com/support/docs/neutrino_qrp/lib_ref/s/shm_open.html

Daryl Low
University of Waterloo

Thanks for the comments, but I’ve tried it that way round too. The problem
there is that I can’t pass the file descriptor returned from shm_open to
mmap when using the MAP_PHYS|MAP_ANON flags. The doc’s say (and I have
proved by trying) that to get physically contiguous memory you must pass
NOFD to mmap.
So how can I mmap physically contiguous memory, and associate it with the
shared mem object I have created (and have a descriptor for)?

“Daryl Low” <dlow@student.math.uwaterloo.ca> wrote in message
news:3A217696.D8DB7BB5@student.math.uwaterloo.ca

Kieran Tyrrell wrote:

I have a DMA buffer created with mmap(…MAP_PHYS|MAP_ANON…), but
now I need to expose this DMA buffer through a shared memory object.
I’ve tried all sorts of combinations of shm_open, mmap, shm_ctl, but
nothing seems to work!

I believe you’re doing things backwards. First you create a shared
memory object with shm_open, grow it to the size you need using
ftruncate and them use mmap to map the shared object.

As far as I can tell, you can’t MAP_ANON memory and then expect to
turn it into a shared memory object.

Refer to the detailed examples at:
http://qdn.qnx.com/support/docs/neutrino_qrp/lib_ref/s/shm_open.html

Daryl Low
University of Waterloo

Kieran Tyrrell <kieran.tyrrell@virgin.net> wrote:

Hi,

I have a DMA buffer created with mmap(…MAP_PHYS|MAP_ANON…), but now I
need to expose this DMA buffer through a shared memory object. I’ve tried
all sorts of combinations of shm_open, mmap, shm_ctl, but nothing seems to
work!

There was a discussion on how to do this in the qdn.public.articles
group. You want to shm_open the object with O_RDWR | O_CREAT,
then use shm_ctl with the SHMCTL_PHYS flag to make the object
overlay some physical memory.

If someone knows the magic sequence please tell me!

Kieran.

Kieran Tyrrell <kieran.tyrrell@virgin.net> wrote:

So how can I mmap physically contiguous memory, and associate it with the
shared mem object I have created (and have a descriptor for)?

Since numerous people have asked this, here’s a tested example:

#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>

main()
{
int fd;

fd = shm_open("/turnip", O_RDWR | O_CREAT, 0644);

if (fd == -1) {
perror(“shm_open”);
exit(EXIT_FAILURE);
}

if (shm_ctl(fd, SHMCTL_PHYS, 0xa0000, 0x1000) == -1) {
perror(“shm_open”);
exit(EXIT_FAILURE);
}
}

In your case, you would take the pointer you got when you allocated
the physically contiguous memory using mmap, call posix_mem_offset64
to get the physical address, and pass this physical address in place
of 0xa0000.

The shared memory object will show up under /dev/shmem.

In article <8vsn8a$e7c$1@nntp.qnx.com>, David Donohoe
<ddonohoe@qnx.com> wrote:

Kieran Tyrrell <> kieran.tyrrell@virgin.net> > wrote:

So how can I mmap physically contiguous memory, and associate it with
the
shared mem object I have created (and have a descriptor for)?

Since numerous people have asked this, here’s a tested example:

#include <sys/mman.h
#include <stdlib.h
#include <fcntl.h

main()
{
int fd;

fd = shm_open("/turnip", O_RDWR | O_CREAT, 0644);

if (fd == -1) {
perror(“shm_open”);
exit(EXIT_FAILURE);
}

if (shm_ctl(fd, SHMCTL_PHYS, 0xa0000, 0x1000) == -1) {
perror(“shm_open”);
exit(EXIT_FAILURE);
}
}

In your case, you would take the pointer you got when you allocated
the physically contiguous memory using mmap, call posix_mem_offset64
to get the physical address, and pass this physical address in place
of 0xa0000.

The shared memory object will show up under /dev/shmem.

After many problems and aborted attempts, I finally got my system to
work this afternoon. This snippet (and the assertion that it was tested)
helped a lot. Here are a couple gotchas.

  1. shm_ctl seems to want to run as root, at least if specifying the
    SHMCTL_PHYS flag). This is not horribly surprising, as setting up
    something to map physical memory is intuitively a privledged operation
    of sorts.

  2. The size passed to shm_ctl should be a non-zero multiple of the page
    size (sysconf(_SC_PAGE_SIZE).

#2 is what has been horking me for the past couple weeks. The actual
device I’ve been using for testing is only 256 bytes, so I’ve been
passing 0x100 for the size argument. Not good. I now round 0x100 up to a
page size and pass that size to shm_ctl. I then pass the real size
(0x100) to the mmap call which maps the memory area.

Thanks all for your help!
Eric