6

On windows there is this program called pcitree that allows you to set and read memory without writing a device driver. Is there a linux alternative to pcitree that will allow me read memory on block 0 of my pcie card?

A simple use case would be that I use driver code to write a 32bit integer on the first memory address in block zero of my pci-e card. I then use pcitree alternative to read the value at the first memory address of block zero and see my integer.

Thank you

user514156
  • 630
  • 1
  • 7
  • 14

3 Answers3

3

I found some code online that does what I want here github.com/billfarrow/pcimem. As I understand it this link offers code that maps kernel memory to user memory via the system call "mmap"

This was mostly stolen from the readme of the program, and the man pages of mmap. mmap takes

  • a start address
  • a size
  • memory protection flags
  • file descriptor that that is linked to bar0 of your pci-card.
  • and an offset

mmap returns a userspace pointer to the memory defined by the start address and size parameters.

This code shows an example of mmaps usage.

//The file handle can be found by typing "lspci -v "
//    and looking for your device.
fd = open("/sys/devices/pci0001\:00/0001\:00\:07.0/resource0", O_RDWR | O_SYNC);
//mmap returns a userspace address
//0, 4096 tells it to pull one page 
ptr = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
printf("PCI BAR0 0x0000 = 0x%4x\n", *((unsigned short *) ptr);
Community
  • 1
  • 1
user514156
  • 630
  • 1
  • 7
  • 14
0

I use the way to get PCI BAR0 register described above but get the segmentation fault back. I use gdb to debug the error from my code as follows and it shows the return value of mmap() is (void *) 0xffffffffffffffff

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.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 4096UL
#define MAP_MASK (MAP_SIZE - 1)

int main(int argc, char **argv) {

    int fd;
    void *ptr;
    //The file handle can be found by typing lscpi -v
    //and looking for your device.
    fd = open("/sys/bus/pci/devices/0000\:00\:05.0/resource0", O_RDWR | O_SYNC);
    //mmap returns a userspace address
    //0, 4096 tells it to pull one page
    ptr = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    printf("PCI BAR0 0x0000 = 0x%4x\n", *((unsigned short *) ptr));

    if(munmap(ptr, 4096) == -1) PRINT_ERROR;
    close(fd);
    return 0;
}
TeYen Liu
  • 13
  • 2
0

On a system with functioning /dev/mem in the kernel it is possible to read a bar for a device using:

sudo dd if=/dev/mem skip=13701120 count=1 bs=256 | hexdump

Look at the dd man page. In the above example 13701120 * 256 is the start physical address at which 256 bytes will be read.

ashutosh
  • 451
  • 4
  • 5