read PCI memory and config spyce through /dev/mem

Warlich, Christof christof.warlich at siemens.com
Tue May 7 02:35:43 EDT 2013


> > $ dd if=/dev/mem bs=1 count=1024 skip=4150263808
> > dd: reading `/dev/mem': Bad address
> > 0+0 records in
> > 0+0 records out
> > 0 bytes (0 B) copied, 6.6658e-05 s, 0.0 kB/s
> >
> > The kernel config help says that _PCI_ memory access is even
> > possible with STRICT_DEVMEM enabled. Can anyone give me a hint
> > what I may do wrong?
> 
> You *do* realize that doing a byte access on a 64-bit PCI register
> will probably fail, right?  And changing it to bs=8 won't fix it either,
> because some registers are 32-bit, and some are write-only.

The real target that I need to explore is a custom FPGA device on an
embedded (i386) system. One of its BARs (at 0x81423000) point to memory
that _does_ allow unrestricted byte access and has a size of two pages.
But anyhow, all of the following commands show the same error:

$ dd if=/dev/mem bs=1 count=1 skip=2168598528 | hexdump
$ dd if=/dev/mem bs=2 count=1 skip=1084299264 | hexdump
$ dd if=/dev/mem bs=4 count=1 skip=542149632 | hexdump
$ dd if=/dev/mem bs=8 count=1 skip=271074816 | hexdump
$ dd if=/dev/mem bs=4096 count=1 skip=529443 | hexdump # 4096 being the system's page size

Furthermore, read / write access through a simple program using /dev/mem
_does_ work as expected:

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
int main( int argc, char *argv[]) {
  char *mem;
  int fd;
  fd = open ("/dev/mem", O_RDWR);
  assert(fd >= 0);
  mem = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t) 0x81423000);
  assert(mem != MAP_FAILED);
  printf("Memory pointer: %p\n", mem);
  printf("The PCI memory is : %#x\n", *mem);
  *mem = *argv[1];
  printf("The PCI memory is : %#x\n", *mem);
  munmap(mem, getpagesize());
  close(fd);
  return 0;
}

Calling it, yields:

$ led 4
Memory pointer: 0xb7678000
The PCI memory is : 0x33
The PCI memory is : 0x34

And the LED matrix display being behind that address switches from 3 to
4 as expected.

Thus, I still cannot see why the access through /dev/mem using dd doesn't
work.
 
> Bottom line - what you're doing wrong is not accessing the PCI address
> space in the exact manner that the PCI spec requires.  You're lucky it
> just threw "bad address" - it *is* possible to end up wiping your entire
> system this way if you screw up the PCI config for your disk controller or
> similar.  Be glad you didn't have to recover from your backups this time.
> 
> You *do* have backups, right?

Don't worry about that, I've restored the system in less than a minute. 



More information about the Kernelnewbies mailing list