We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

Showing results for 
Search instead for 
Did you mean: 
Visitor dwjbosman
Registered: ‎06-17-2018

mmap on zed board + yocto linux

I want to test inter cpu communication using shared memory between a Microblaze soft core and Zynq A9 ARM processors running Linux on a Zed board. First I want to do some basic tests using mmap.

In the device tree I have reserved some memory:

   reserved-memory {
      #address-cells = <1>;
      #size-cells = <1>;

      mb_shared_mem: buffer@0x10000000 {
         reg = <0x10000000 0x0e000000>;

   reserved-driver@0 {
      compatible = "xlnx,reserved-memory";
      memory-region = <&mb_shared_mem>;
  1. The Zed board has 512MB ram. If I reserve the upper 256MB then Linux won't start. Why? It works when I decrease the amount to 0x0e000000. The address editor in Vivado doesn't show any reserved address from 1e00_0000 to 2000_0000

  2. Do I need to use 'no-map'? The kernel should not use the memory, but I want to be able to access it using mmap.

I built a simple test program for mmap. The program writes a file byte by byte to a memory region mapped using mmap:

int write_file( char *argv[]) {
    int fd, fd_in;

    off_t size;
    off_t file_index;

    char* fname = 0;
    char* addr = argv[3];

    fname = argv[2];

    fd_in = open(fname, O_RDONLY);
    if (fd_in < 1) {
        printf("Unable to open input file %s\n",fname );

    void* load_address = (void*)strtoul(addr, NULL, 16);
    printf("Loading at address %p\n ",load_address);

    fd = open("/dev/mem", O_RDWR | O_SYNC);

    if (fd < 1) {
        printf("Unable to open mem device file\n");
        return -1;

    // determine size
    size = lseek(fd_in, 0L, SEEK_END);
    lseek(fd_in, 0L, SEEK_SET);

    printf("Copying %ld bytes\n", size);

    base_address = mmap(load_address, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_UNINITIALIZED | MAP_FIXED, fd, 0);
    if (base_address == MAP_FAILED) {
        printf("mmap failed! %s\n", strerror(errno));
        return -1;

    for (file_index = 0; file_index < size; file_index++) {
        uint8_t file_byte;
        ssize_t result = read(fd_in, &file_byte,1);

        if (result<0) {
            printf("Error during fileread: %s", strerror(errno));
        base_address[file_index] = file_byte;

        if (base_address[file_index] != file_byte) {
            printf("Write failed, offset %lx failed\n", file_index);
        if ((file_index % 100) == 0) {

    munmap(base_address, size);
    return 0;
  • 3. In most examples I found I see:

    mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, load_address);

    3.1 Why not specify the physical address as the first argument and 0 as the offset (last argument)?

    3.2 Why are the MAP_UNINITIALIZED | MAP_FIXED options almost never used in examples? Especially MAP_UNINITIALIZED seems required when reading the output from PL.

  • 4. The page size of the system is 4096 bytes. If I use the function to write a file of 2890 bytes the function returns without errors. With a file of 60000 bytes the kernel hangs/crashes.

  • 5. I also wrote a program to read memory using mmap. I tried the following:

write 2980 bytes of file_A to 0x1000_0000

write 2980 bytes of file_B to 0x1200_0000

read 2980 bytes of 0x1000_0000 > file_A_tst

read 2980 bytes of 0x1200_0000 > file_B_tst

  • 6. When checking the contents of the read files I see that 'file_A_tst' is equal to 'file_B_tst" and 'file_B'. So it seems that the written mapped memory is not actually flushed to the physical memory? I just get old data from the previous mmap. I need to use MAP_UNINITIALIZED because I don't wan't Linux to clear the physical memory.
0 Kudos