ikwzm / udmabuf

User space mappable dma buffer device driver for Linux.
BSD 2-Clause "Simplified" License
560 stars 168 forks source link

Uncached memory access for Core 1 #48

Closed darko31 closed 4 years ago

darko31 commented 4 years ago

Hello ikwzm,

thank you for this very useful driver. I'm using this driver for transferring data between PL and PS and also from Core 1 to Core 0 on Zynq 7000 device. Core 0 is running Linux while Core 1 is running bare metal application in sort of AMP mode. Sync mode is set to 1 so cache should be disabled. But, data read with udmabuf on Core 0 seems wrong, some data is good, some data is zero. It seems that cache is still enabled. This is confirmed by running Xil_DCacheFlushRange on the baremetal app for that specific address, then data seems good.

I know this isn't primary use case for udmabuf. Can you maybe point out how to flush and invalidate cache from Core 0 Linux/udmabuf instead of flushing cache from bare metal app after every write.

Best regards, Darko

ikwzm commented 4 years ago

Thank you for the issue.

Did you add O_SYNC when opening the device file?

    /* To disable CPU cache on the DMA buffer, */
    /* open udmabuf with the `O_SYNC` flag. */
    if ((fd  = open("/dev/udmabuf0", O_RDWR | O_SYNC)) != -1) {
        buf = mmap(NULL, buf_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        /* Read/write access to the buffer */
        close(fd);
    }
darko31 commented 4 years ago

Yes, this is the code for mapping udmabuf ` std::int32_t udmabuf_fd; void *udmabuf_pointer;

/* https://github.com/ikwzm/udmabuf */
/* To enable CPU cache on the DMA buffer, */
/* open udmabuf without specifying the `O_SYNC` flag. */
/* Cache is disabled */
udmabuf_fd = open(UDMABUF_DEVICE_PATH, O_RDWR | O_SYNC);
if (udmabuf_fd < 0){
    LOG(FATAL) << "Unable to open udmabuf device!";
}

udmabuf_pointer = mmap(NULL, current_device.udmabuf_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, udmabuf_fd, 0);

if (udmabuf_pointer == MAP_FAILED){
    LOG(FATAL) << "Failed to mmap udmabuf";
}

return udmabuf_pointer;`

This seems to be an issue with Core 1 not being aware of caching attributes of udmabuf memory region. Note that bootarg parameter contains maxcpus=1, so that Linux initiates only one core, so that other one can be available for baremetal application. Are you maybe aware of mechanism of flushing cache of Core 1 from Linux driver or userland?

Thank you

ikwzm commented 4 years ago

I'm sorry. I don't know how to control cache for memory area secured by udmabuf from bare metal application running on Core1.

darko31 commented 4 years ago

Ok, thank you, This issue can be closed then.

darko31 commented 4 years ago

Hello, just a quick update. Using custom function MyXil_SetTlbAttributes from XAPP1078 in bare metal application on Core 1 I was able to disable cache and kernel panics were not occurring anymore on Core 0. Everything worked as expected.

More info at https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841653/XAPP1078+Latest+Information