1
votes

I have a problem considering the usage of mmap. I am trying to map a pci device to a virtual address and read its content. In the future I am planning to write values to it as well.

The problem is that I (seemingly) successfully mapped the device to virtual memory space. However when I read the content of that virtual address all values are zero, despite the file not being empty.

Here is my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "../include/types.h"
#include "../include/pci.h"

#define PRINT_ERROR \
    do { \
        fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
        __LINE__, __FILE__, errno, strerror(errno)); exit(1);\
     } while(0)

#define MAP_SIZE 4069
#define MAP_MASK (MAP_SIZE - 1)

int main(int argc, char *argv[])
{
    int pci_dev;
    int *mmap_base;
    int *content;
    char file[] = {"/sys/bus/pci/devices/0000:04:00.0/resource"};
    int i;

    printf("File to be read from: %s\n", file);

    pci_dev = open(file, O_RDONLY);
    if (pci_dev < 0)
    {
        PRINT_ERROR;
    }

    mmap_base = mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_ANON, pci_dev, 0);
    if (mmap_base == (void *)-1 || mmap_base == NULL)
    {
        PRINT_ERROR;
    }
    printf("Mapped on address %p of size %d Byte\n", mmap_base, (int)MAP_SIZE);
    content = (int *)mmap_base;

    for(i = 0; i < 1024; i++)
    {
        printf("%x", content[i]);
    }


    return 0;
}

Here's the content of the first line from the file "/sys/bus/pci/devices/0000:04:00.0/resource" that I am trying to access:

0x00000000cd000000 0x00000000cd07ffff 0x0000000000040200

However the output I get is:

File to be read from: /sys/bus/pci/devices/0000:04:00.0/resource
Mapped on address 0xb7705000 of size 4096 Byte
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...

Am I doing something wrong? Every help is appreciated!

1
On a note unrelated to your problem, do you really mean 4069 for MAP_SIZE? Not the usual power-of-two value of 4096? Is it a typo in the actual code, or did you rewrite the code for the question? If the latter, then don't do that. Copy-paste the Minimal, Complete, and Verifiable Example instead. That way you won't introduce unrelated errors, or perhaps even (by mistake and without realizing it) fix the problem.Some programmer dude
No, that is the actual code of my file. When I just write 4096 I get a warning that int is the wrong data type. Does it matter in that case? Edit: I changed the value to (int) 4096 and now I don't get a warning anymore... I got the warning when I was still struggling with getting a pointer from mmap instead of an error code.A.Z.
Then it would not build (#include ...), and the output you show doesn't match the code (the code says MAP_SIZE is 4069 but your output shows it as 4096). So the code you show is not the actual code you build and run. Small things like that makes it harder for us to trust the rest of the code, so many who could help you won't do it.Some programmer dude
I swear the only thing I changed was deleting the includes. I edited my post and included a screenshot.A.Z.
"MAP_PRIVATE | MAP_ANON" ,replace this by "MAP_SHARED" ,then it can print the file. I change the argument to simulate an old program of mmap demo,but I am not sure what's the problem in your argument, I will check it laterpeter__barnes

1 Answers

0
votes

Actually you've got 2 mistakes:

  1. Don't use MAP_ANON when you create a map for a real file on the file system, it's meant for IPC and requiring extra memory from OS e.g. while malloc().
  2. When you remove the flag, the mmap() will likely return ENODEV, because linux sysfs doesn't support mmaping; So you have to use read()'s here.