Search code examples
cmmap

Segmentation fault on Memory Access


I have mmapped a base address of 0x40000000 to a virtual memory address. But when I try to read the value of register on the location of 0x40100000, I get a segmentation fault. The page size used in the mmap() function is 4K where the file descriptor has a value of 3.

The init() function is called from the main to initialize the memory: Here UWord8 is unsigned char and UWord32 is unsigned int.

UWord8 init()
{
    UWord8 error;
    printf("Initializing Devices in Zynq...\n\r\n\r");
    error = initMemory();

    if(error)
    {
        printf("PL:\tAccess Denied\n\r");
        return 1;
    }

    if(!error)
    {
        error = initFpga();
        if(error)
        {
            printf("Access Denied to mmap...\n\r");
            return 1;
        }
    }
}

UWord8 initMemory(void)
{
    UWord8 error = 0;

    //Initializing /dev/mem
    fd = open(MEMORY_ACCESS, READ_WRITE);

    if(fd < 1)
    {
        error = 1;
        #if DEBUG_MODE
            printf("Could not open /dev/mem for access\n");
        #endif
    }
    else
    {
        printf("Value of fd is %u\n", fd);
        page_size = sysconf(_SC_PAGESIZE);
        printf("The page size is %u\n", page_size);
        #if DEBUG_MODE
            printf("Successfully opened /dev/mem for access\n");
        #endif
    }

    //Opening text file for writing pointer data
    fp = fopen("/home/pointer_data.txt", "a");

    if(fp == NULL)
    {
        error = 1;
        #if DEBUG_MODE
            printf("Could not open text file for writing.\n\r");
        #endif
    }
    else
    {
        #if DEBUG_MODE
            printf("Successfully opened text file for writing.\n\r");
        #endif
    }
    return error;
}

UWord8 initFpga(void)
{
    UWord8 error = 0;
    unsigned page_addr, device_addr;

    device_addr = BASE_ADDRESS;
    page_addr = (device_addr & (~(page_size-1)));
    fpga_pageOffset = device_addr - page_addr;
    fpga_ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_addr); //mmap the device into memory

    if(fpga_ptr == NULL)
    {
        printf("Memory mapping to Base address 0x%08x failed...\n\r",BASE_ADDRESS);
        error = 1;
    }   
    return error;
}

The following is the function is read the value at a particular address, the address being sent to the function is the offset from base address:

UWord32 _getWord(UWord32 address)
{
    UWord32 data = *((unsigned *)(fpga_ptr + fpga_pageOffset + address));
    printf("peek 0x%08x =0x%08x\n\r", BASE_ADDRESS + address, data);
    return data;
}

There is no error on this line:

_getWord(0x000ffff8)

But I get a segmentation fault on:

_getWord(0x00100000)

Solution

  • When you create your memory map, you give it a size equal to your pagesize- 4kb.

    fpga_ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_addr); //mmap the device into memory
    

    This translates to 0x1000 bytes, however you attempt to access data 0x100000 bytes after the beginning of your map, which raises the segmentation fault. To fix this issue, map a larger region of memory. For example:

    fpga_ptr = mmap(NULL, 0x1000 * page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_addr);
    

    This will allow you to access the next 0x1000000 bytes after the beginning of your memory map.