odd mmap behavior

Brett brettgraham at gmail.com
Wed Oct 21 09:50:29 EDT 2009


On Oct 21, 8:02 am, Carl Banks <pavlovevide... at gmail.com> wrote:
> On Oct 20, 5:03 pm, Brett <brettgra... at gmail.com> wrote:
>
>
>
> > I'm trying to read and write from /dev/mem on a linux system using the
> > mmap module. When I run this minimal example:
> > -------------------------------
> > import os, mmap
>
> > MAP_MASK = mmap.PAGESIZE - 1
>
> > addr = 0x48088024
>
> > f = os.open("/dev/mem", os.O_RDWR | os.O_SYNC)
> > m = mmap.mmap(f, mmap.PAGESIZE, mmap.MAP_SHARED, mmap.PROT_WRITE |
> > mmap.PROT_READ, offset=addr & ~MAP_MASK)
> > m.seek(addr & MAP_MASK)
> > c = m.read_byte()
> > print c
> > m.close()
> > os.close(f)
> > -------------------------------
>
> > I get the following error:
> > Unhandled fault: external abort on non-linefetch (0x1018) at
> > 0x40020024
> > Bus error
>
> > and python crashes. What is odd is that if I try to read the same
> > memory address using the devmem2 program (i'll attach the source at
> > the end), everything works fine. Here are the truncated straces for
> > each program:
>
> > ----- devmem2 0x48088024 -----
> > open("/dev/mem", O_RDWR|O_SYNC)         = 3
> > fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
> > mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
> > 0) = 0x4001f000
> > write(1, "/dev/mem opened.\n", 17)      = 17
> > mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0x48088) =
> > 0x40020000
> > write(1, "Memory mapped at address 0x40020"..., 37) = 37
> > write(1, "Value at address 0x48088024 (0x4"..., 46) = 46
> > munmap(0x40020000, 4096)                = 0
> > close(3)                                = 0
> > io_submit(0, 0, 0xfbad2088 <unfinished ... exit status 0>
> > Process 1635 detached
>
> > ------ the above minimal python example -----
> > open("/dev/mem", O_RDWR|O_SYNC|O_LARGEFILE) = 3
> > fstat64(3, {st_mode=S_IFCHR|0640, st_rdev=makedev(1, 1), ...}) = 0
> > dup(3)                                  = 4
> > mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0x48088) =
> > 0x40020000
> > --- SIGBUS (Bus error) @ 0 (0) ---
> > +++ killed by SIGBUS +++
> > Process 1633 detached
>
> > Am I using mmap incorrectly?
>
> Looks like you're using it ok to me.
>
> One thing to keep in mind is that the offset parameter was added to
> mmap recently, only in Python 2.6 I think, so it might not have been
> so battle-tested as the rest of Python.  Also, I would guess the file-
> like methods (seek, read, etc.) are not commonly used.  Perhaps those
> methods don't play nice with the offset method?  It's possible the
> mmap object doesn't recon the seek pointer relative to the offset,
> meaning you'd have to use m.seek(addr) instead of m.seek(addr &
> MAP_MASK)
>
> Another possibility is that the mmap object is accessing the memory
> with bad alignment (when I see bus error the first thing I think of is
> that a word was read from a non-word-aligned address).  You don't
> happen to be running this on a Power PC?  What happens when you try
> accessing the mmap data like an regular array?
>
> All speculation, but my gut feeling is bug in mmap module.
>
> Carl Banks

I also posted this question to the linux-omap list and received some
helpful (and timely) assistance. I'm running this on an ARM (omap
3530, gumstix). Here is the take-home message (from the omap technical
reference and reported to me here http://www.spinics.net/lists/linux-omap/msg19347.html):
"CAUTION
The GP timer registers are limited to 32-bit and 16-bit data accesses;
8-bit access is not allowed and can corrupt the register content."

So... instead of calling mmap.read_byte() i'm calling mmap.read(4).
The thing I'm still wondering, is if python 'under-the-hood' is still
making 8-bit accesses. I thought it was fixed, but just got another
'Unhandled fault'. Any hints?

Also, thanks for the suggestion about accessing it as an array. I will
try to find out if one method of access (array-like or reading as a
string) results in more errors.



More information about the Python-list mailing list