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.
In the device tree I have reserved some memory:
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
mb_shared_mem: buffer@0x10000000 {
no-map;
reg = <0x10000000 0x0e000000>;
};
};
reserved-driver@0 {
compatible = "xlnx,reserved-memory";
memory-region = <&mb_shared_mem>;
};
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
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");
close(fd_in);
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));
close(fd);
close(fd_in);
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));
break;
}
base_address[file_index] = file_byte;
if (base_address[file_index] != file_byte) {
printf("Write failed, offset %lx failed\n", file_index);
break;
}
if ((file_index % 100) == 0) {
printf(".");
}
}
printf("\n");
munmap(base_address, size);
close(fd_in);
close(fd);
return 0;
}
In most examples I found I see:
mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_UNINITIALIZED | MAP_FIXED, fd, load_address);
Why not specify the physical address as the first argument and 0 as the offset (last argument)?
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.
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
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.
User contributions licensed under CC BY-SA 3.0