* Frame buffer / mmap() weirdness
@ 1999-11-30 22:06 Stephen Edie
1999-11-30 21:19 ` Geert Uytterhoeven
0 siblings, 1 reply; 12+ messages in thread
From: Stephen Edie @ 1999-11-30 22:06 UTC (permalink / raw)
To: linuxppc-dev, yellowdog-devel
Hello,
I have been noticing some strange behavior while working with Linux frame
buffer devices on PPC. Perhaps I am just doing something stupid. I open
the frame buffer using:
fbdev_handle = open("/dev/fb0", O_RDWR);
I can draw to the frame buffer using:
lseek(fbdev_handle, 0, SEEK_SET);
write(fbdev_handle, pixmap, size);
This part works fine. What causes problems is attempting to memory map
the frame buffer using:
address = mmap(0, screen.height * screen.stride * screen.bpp / 8,
PROT_READ | PROT_WRITE, MAP_SHARED, fbdev_handle, 0);
When doing this, address[0] points outside of the video memory and
strangely enough, address[512] points to the first pixel in memory! So if
I do the following, everything works as expected:
address = (char *)(mmap(0, screen.height * screen.stride * screen.bpp / 8
+ 512, PROT_READ | PROT_WRITE, MAP_SHARED,
fbdev_handle, 0)) + 512;
I don't think this is right! Is this a kernel bug in the frame buffer
driver code? (This is being tested using OFFB by the way) Is there
something weird going on here with page alignment or something?
Thanks,
Stephen
Terra Soft Solutions, Inc.
Yellow Dog Linux
"The Ultimate Companion for a Dedicated Server"
http://www.yellowdoglinux.com/
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: Frame buffer / mmap() weirdness
1999-11-30 22:06 Frame buffer / mmap() weirdness Stephen Edie
@ 1999-11-30 21:19 ` Geert Uytterhoeven
1999-11-30 22:43 ` Stephen Edie
0 siblings, 1 reply; 12+ messages in thread
From: Geert Uytterhoeven @ 1999-11-30 21:19 UTC (permalink / raw)
To: Stephen Edie; +Cc: linuxppc-dev, yellowdog-devel
On Tue, 30 Nov 1999, Stephen Edie wrote:
> I have been noticing some strange behavior while working with Linux frame
> buffer devices on PPC. Perhaps I am just doing something stupid. I open
> the frame buffer using:
>
> fbdev_handle = open("/dev/fb0", O_RDWR);
>
> I can draw to the frame buffer using:
>
> lseek(fbdev_handle, 0, SEEK_SET);
> write(fbdev_handle, pixmap, size);
>
> This part works fine. What causes problems is attempting to memory map
> the frame buffer using:
>
> address = mmap(0, screen.height * screen.stride * screen.bpp / 8,
> PROT_READ | PROT_WRITE, MAP_SHARED, fbdev_handle, 0);
>
> When doing this, address[0] points outside of the video memory and
> strangely enough, address[512] points to the first pixel in memory! So if
> I do the following, everything works as expected:
>
> address = (char *)(mmap(0, screen.height * screen.stride * screen.bpp / 8
> + 512, PROT_READ | PROT_WRITE, MAP_SHARED,
> fbdev_handle, 0)) + 512;
>
> I don't think this is right! Is this a kernel bug in the frame buffer
> driver code? (This is being tested using OFFB by the way) Is there
> something weird going on here with page alignment or something?
Perhaps the frame buffer memory is not aligned on a page boundary? What does
`fbset --info' say about the address?
If it's not aligned to a page boundary, the application has to mmap()
(address & 0xfffff000) and add (address & 0x00000fff) to the start address of
the returned region. Make sure to increase the size you pass to mmap(), so the
whole frame buffer memory is covered and size is a multiple of the page size.
Gr{oetje,eeting}s,
--
Geert Uytterhoeven -- Linux/{m68k~Amiga,PPC~CHRP} -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: Frame buffer / mmap() weirdness
1999-11-30 21:19 ` Geert Uytterhoeven
@ 1999-11-30 22:43 ` Stephen Edie
1999-12-01 7:28 ` Geert Uytterhoeven
0 siblings, 1 reply; 12+ messages in thread
From: Stephen Edie @ 1999-11-30 22:43 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: linuxppc-dev, yellowdog-devel
Geert,
According to fbset, it's at: 0x8a008900
I don't want to map /dev/mem if that's what you are talking about.
So I am assuming that mmap() will start mapping from the first page that
he frame buffer occupies... So I need to add the following to what
mmap() returns in order to get a valid pointer:
PAGE_ROUND_UP(phys_address) - phys_address
(PAGE_ROUND_UP is assumed to return the beginning of the page that starts
at or after the specified address)
This doesn't entirely make sense. Just now I tested the program and it
doesn't require re-alignment as I mention above.
(I'm thinking now that it only occurs in 32 bit color mode??)
Furthermore, it makes most sense that mmap() should take care of page
alignment issues for me so that the address returned by mmap() always
points to the data at [lseek(h, 0, SEEK_SET)]. This is not technically
difficult to implement, right?
Stephen
Terra Soft Solutions, Inc.
Yellow Dog Linux
"The Ultimate Companion for a Dedicated Server"
http://www.yellowdoglinux.com/
On Tue, 30 Nov 1999, Geert Uytterhoeven wrote:
> Perhaps the frame buffer memory is not aligned on a page boundary? What does
> `fbset --info' say about the address?
>
> If it's not aligned to a page boundary, the application has to mmap()
> (address & 0xfffff000) and add (address & 0x00000fff) to the start address of
> the returned region. Make sure to increase the size you pass to mmap(), so the
> whole frame buffer memory is covered and size is a multiple of the page size.
>
> Gr{oetje,eeting}s,
> --
> Geert Uytterhoeven -- Linux/{m68k~Amiga,PPC~CHRP} -- geert@linux-m68k.org
>
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
> -- Linus Torvalds
>
>
>
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: Frame buffer / mmap() weirdness
1999-11-30 22:43 ` Stephen Edie
@ 1999-12-01 7:28 ` Geert Uytterhoeven
1999-12-01 8:16 ` Momchil Velikov
1999-12-01 9:26 ` Michael Schmitz
0 siblings, 2 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 1999-12-01 7:28 UTC (permalink / raw)
To: Stephen Edie; +Cc: linuxppc-dev, yellowdog-devel
On Tue, 30 Nov 1999, Stephen Edie wrote:
> According to fbset, it's at: 0x8a008900
>
> I don't want to map /dev/mem if that's what you are talking about.
I did meant /dev/fb0, but I indeed incorrectly wrote `address & 0xfffff000',
while I meant `0' (offsets are relative to the start of the frame buffer
memory).
> So I am assuming that mmap() will start mapping from the first page that
> he frame buffer occupies... So I need to add the following to what
Yes.
> mmap() returns in order to get a valid pointer:
>
> PAGE_ROUND_UP(phys_address) - phys_address
Yes.
> (PAGE_ROUND_UP is assumed to return the beginning of the page that starts
> at or after the specified address)
>
> This doesn't entirely make sense. Just now I tested the program and it
> doesn't require re-alignment as I mention above.
>
> (I'm thinking now that it only occurs in 32 bit color mode??)
That's possible: on some hardware, the start address of the frame buffer
depends on the color depth.
> Furthermore, it makes most sense that mmap() should take care of page
> alignment issues for me so that the address returned by mmap() always
> points to the data at [lseek(h, 0, SEEK_SET)]. This is not technically
> difficult to implement, right?
I think it will make munmap() more difficult to implement. Furthermore I see no
provisions for this in the current mmap() code. And it will break backwards
compatibility.
> On Tue, 30 Nov 1999, Geert Uytterhoeven wrote:
> > Perhaps the frame buffer memory is not aligned on a page boundary? What does
> > `fbset --info' say about the address?
> >
> > If it's not aligned to a page boundary, the application has to mmap()
> > (address & 0xfffff000) and add (address & 0x00000fff) to the start address of
> > the returned region. Make sure to increase the size you pass to mmap(), so the
> > whole frame buffer memory is covered and size is a multiple of the page size.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven ----------------- Sony Suprastructure Center Europe (SUPC-E)
Geert.Uytterhoeven@sonycom.com ------------------- Sint-Stevens-Woluwestraat 55
Voice +32-2-7248632 Fax +32-2-7262686 ---------------- B-1130 Brussels, Belgium
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: Frame buffer / mmap() weirdness
1999-12-01 7:28 ` Geert Uytterhoeven
@ 1999-12-01 8:16 ` Momchil Velikov
1999-12-01 9:13 ` Geert Uytterhoeven
1999-12-01 9:26 ` Michael Schmitz
1 sibling, 1 reply; 12+ messages in thread
From: Momchil Velikov @ 1999-12-01 8:16 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: Stephen Edie, linuxppc-dev, yellowdog-devel
Geert Uytterhoeven wrote:
>
> On Tue, 30 Nov 1999, Stephen Edie wrote:
> > Furthermore, it makes most sense that mmap() should take care of page
> > alignment issues for me so that the address returned by mmap() always
> > points to the data at [lseek(h, 0, SEEK_SET)]. This is not technically
> > difficult to implement, right?
This behavior is mandated by POSIX:
" pa = mmap( addr, len, prot, flags, fildes, off)
The mmap() function establishes a mapping between the address space of
the process at an address pa for len bytes for memory object represented
by the file descriptor fildes at offset off for len bytes".
So, if pa[0] != [lseek(fildes, off, SEEK_SET], etc., the mmap()
implementation is clearly buggy or at least non-compliant.
> I think it will make munmap() more difficult to implement. Furthermore I see no
> provisions for this in the current mmap() code. And it will break backwards
> compatibility.
Don't know for mmap(), but it seems the only change to munmap() is
to clear the appropriate number of low-order bits in its first argument
( addr & 0xfffff000 for 32-bit machines with 4k page size).
Regards,
-velco
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: Frame buffer / mmap() weirdness
1999-12-01 8:16 ` Momchil Velikov
@ 1999-12-01 9:13 ` Geert Uytterhoeven
1999-12-01 9:54 ` Gabriel Paubert
1999-12-01 11:12 ` Michael Schmitz
0 siblings, 2 replies; 12+ messages in thread
From: Geert Uytterhoeven @ 1999-12-01 9:13 UTC (permalink / raw)
To: Momchil Velikov; +Cc: Stephen Edie, linuxppc-dev, yellowdog-devel
On Wed, 1 Dec 1999, Momchil Velikov wrote:
> Geert Uytterhoeven wrote:
> > On Tue, 30 Nov 1999, Stephen Edie wrote:
> > > Furthermore, it makes most sense that mmap() should take care of page
> > > alignment issues for me so that the address returned by mmap() always
> > > points to the data at [lseek(h, 0, SEEK_SET)]. This is not technically
> > > difficult to implement, right?
>
> This behavior is mandated by POSIX:
> " pa = mmap( addr, len, prot, flags, fildes, off)
> The mmap() function establishes a mapping between the address space of
> the process at an address pa for len bytes for memory object represented
> by the file descriptor fildes at offset off for len bytes".
> So, if pa[0] != [lseek(fildes, off, SEEK_SET], etc., the mmap()
> implementation is clearly buggy or at least non-compliant.
Hmmm...
> > I think it will make munmap() more difficult to implement. Furthermore I see no
> > provisions for this in the current mmap() code. And it will break backwards
> > compatibility.
>
> Don't know for mmap(), but it seems the only change to munmap() is
> to clear the appropriate number of low-order bits in its first argument
> ( addr & 0xfffff000 for 32-bit machines with 4k page size).
You are right. Since I guess the other mmap()s in the kernel are POSIX
compliant, I feel silly now.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven ----------------- Sony Suprastructure Center Europe (SUPC-E)
Geert.Uytterhoeven@sonycom.com ------------------- Sint-Stevens-Woluwestraat 55
Voice +32-2-7248632 Fax +32-2-7262686 ---------------- B-1130 Brussels, Belgium
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: Frame buffer / mmap() weirdness
1999-12-01 9:13 ` Geert Uytterhoeven
@ 1999-12-01 9:54 ` Gabriel Paubert
1999-12-01 11:02 ` Momchil Velikov
1999-12-01 11:12 ` Michael Schmitz
1 sibling, 1 reply; 12+ messages in thread
From: Gabriel Paubert @ 1999-12-01 9:54 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Momchil Velikov, Stephen Edie, linuxppc-dev, yellowdog-devel
Hi,
> > Don't know for mmap(), but it seems the only change to munmap() is
> > to clear the appropriate number of low-order bits in its first argument
> > ( addr & 0xfffff000 for 32-bit machines with 4k page size).
>
> You are right. Since I guess the other mmap()s in the kernel are POSIX
> compliant, I feel silly now.
I probably have missed something but recent 2.3.xx kernels apparently
prohibit performing mmap at non page aligned offsets since
arch/${ARCH}/kernel/somefile.c constains sys_mmap which calls (rather
directly) mm/mmap.c{do_mmap} where
if (off & ~PAGE_MASK)
return -EINVAL;
so does Posix the offset value passed to mmap to be restricted ?
Gabriel.
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: Frame buffer / mmap() weirdness
1999-12-01 9:54 ` Gabriel Paubert
@ 1999-12-01 11:02 ` Momchil Velikov
1999-12-01 13:02 ` Gabriel Paubert
0 siblings, 1 reply; 12+ messages in thread
From: Momchil Velikov @ 1999-12-01 11:02 UTC (permalink / raw)
To: Gabriel Paubert
Cc: Geert Uytterhoeven, Stephen Edie, linuxppc-dev, yellowdog-devel
Gabriel Paubert wrote:
>
> Hi,
>
> > > Don't know for mmap(), but it seems the only change to munmap() is
> > > to clear the appropriate number of low-order bits in its first argument
> > > ( addr & 0xfffff000 for 32-bit machines with 4k page size).
> >
> > You are right. Since I guess the other mmap()s in the kernel are POSIX
> > compliant, I feel silly now.
>
> I probably have missed something but recent 2.3.xx kernels apparently
> prohibit performing mmap at non page aligned offsets since
> arch/${ARCH}/kernel/somefile.c constains sys_mmap which calls (rather
> directly) mm/mmap.c{do_mmap} where
>
> if (off & ~PAGE_MASK)
> return -EINVAL;
>
> so does Posix the offset value passed to mmap to be restricted ?
>
> Gabriel.
The POSIX I have (POSIX 1003.1b-1993) allows the implementation
to require the off parameter to be a multiple of the page size.
But:
"NOTE: It is expected that a later amendment of this standard will
disallow the implementation from imposing the restriction on the
alignment of the off and addr arguments".
Anyway, whatever is the offset it is still required that
pa[i] == [lseek(fildes, off+i, SEEK_SET)] for each i : 0 <= i < len
after a successful
pa = mmap( addr, len, prot, flags, fildes, off)
Frankly speaking, I can't imagine why addresses returned by mmap()
have to be page aligned. If the frame buffer at address range
[a, a+off) is to be mapped at [b, b+off), just map the range
[a & ~PAGE_MASK, (a + off + PAGE_SIZE - 1) & ~PAGE_SIZE)
to
[b & ~PAGE_MASK, (b + off + PAGE_SIZE - 1) & ~PAGE_SIZE)
and give the user the value b. Upon munmap() mask the lower
bits of the address and you'll get the actual start address
of the mapping. Note that this can be implemented in the
library even if the kernel imposes restrictions on the
alignment of the addr and off parameters.
Also, the standard explicitly allows the end of the *actual* mapping
to be page aligned, but it does not *explicitly forbid* the
start of the *actual* mapping to be page aligned :-)
Regards,
-velco
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: Frame buffer / mmap() weirdness
1999-12-01 11:02 ` Momchil Velikov
@ 1999-12-01 13:02 ` Gabriel Paubert
1999-12-01 15:06 ` Momchil Velikov
0 siblings, 1 reply; 12+ messages in thread
From: Gabriel Paubert @ 1999-12-01 13:02 UTC (permalink / raw)
To: Momchil Velikov
Cc: Geert Uytterhoeven, Stephen Edie, linuxppc-dev, yellowdog-devel
On Wed, 1 Dec 1999, Momchil Velikov wrote:
> The POSIX I have (POSIX 1003.1b-1993) allows the implementation
> to require the off parameter to be a multiple of the page size.
> But:
> "NOTE: It is expected that a later amendment of this standard will
> disallow the implementation from imposing the restriction on the
> alignment of the off and addr arguments".
> Anyway, whatever is the offset it is still required that
> pa[i] == [lseek(fildes, off+i, SEEK_SET)] for each i : 0 <= i < len
> after a successful
> pa = mmap( addr, len, prot, flags, fildes, off)
>
> Frankly speaking, I can't imagine why addresses returned by mmap()
> have to be page aligned. If the frame buffer at address range
> [a, a+off) is to be mapped at [b, b+off), just map the range
> [a & ~PAGE_MASK, (a + off + PAGE_SIZE - 1) & ~PAGE_SIZE)
> to
> [b & ~PAGE_MASK, (b + off + PAGE_SIZE - 1) & ~PAGE_SIZE)
Some PAGE_SIZE are actually PAGE_MASK in this snippet...
> and give the user the value b. Upon munmap() mask the lower
> bits of the address and you'll get the actual start address
> of the mapping. Note that this can be implemented in the
> library even if the kernel imposes restrictions on the
> alignment of the addr and off parameters.
You can do anything when mapping a file privately (although being block
aligned certainly helps), not when mapping hardware or a file with write
sharing. At least the low order bits of a and b have to be the same
(that's only a problem when using MAP_FIXED).
Regards,
Gabriel.
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Frame buffer / mmap() weirdness
1999-12-01 13:02 ` Gabriel Paubert
@ 1999-12-01 15:06 ` Momchil Velikov
0 siblings, 0 replies; 12+ messages in thread
From: Momchil Velikov @ 1999-12-01 15:06 UTC (permalink / raw)
To: Gabriel Paubert
Cc: Geert Uytterhoeven, Stephen Edie, linuxppc-dev, yellowdog-devel
Gabriel Paubert wrote:
>
> On Wed, 1 Dec 1999, Momchil Velikov wrote:
> > [a & ~PAGE_MASK, (a + off + PAGE_SIZE - 1) & ~PAGE_SIZE)
> > to
> > [b & ~PAGE_MASK, (b + off + PAGE_SIZE - 1) & ~PAGE_SIZE)
>
> Some PAGE_SIZE are actually PAGE_MASK in this snippet...
Oops, my PAGE fault. It should be
[a & PAGE_MASK, (a + off + ~PAGE_MASK) & PAGE_MASK )
to
[b & PAGE_MASK, (b + off + ~PAGE_MASK) & PAGE_MASK )
where PAGE_MASK == ~(PAGE_SIZE -1).
Regards,
-velco
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Frame buffer / mmap() weirdness
1999-12-01 9:13 ` Geert Uytterhoeven
1999-12-01 9:54 ` Gabriel Paubert
@ 1999-12-01 11:12 ` Michael Schmitz
1 sibling, 0 replies; 12+ messages in thread
From: Michael Schmitz @ 1999-12-01 11:12 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Momchil Velikov, Stephen Edie, linuxppc-dev, yellowdog-devel
> > > I think it will make munmap() more difficult to implement. Furthermore I see no
> > > provisions for this in the current mmap() code. And it will break backwards
> > > compatibility.
> >
> > Don't know for mmap(), but it seems the only change to munmap() is
> > to clear the appropriate number of low-order bits in its first argument
> > ( addr & 0xfffff000 for 32-bit machines with 4k page size).
>
> You are right. Since I guess the other mmap()s in the kernel are POSIX
> compliant, I feel silly now.
It will still break backwards compatibility (i.e. old X servers). We can
catch the case of old kernels used with new X servers but not the other
way.
Either way - I recall getting errors from the generic mmap code when
passing not page aligned addresses back from fb_mmap. Has something
changed in the mmap code to remove this restriction?
Michael
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Frame buffer / mmap() weirdness
1999-12-01 7:28 ` Geert Uytterhoeven
1999-12-01 8:16 ` Momchil Velikov
@ 1999-12-01 9:26 ` Michael Schmitz
1 sibling, 0 replies; 12+ messages in thread
From: Michael Schmitz @ 1999-12-01 9:26 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: Stephen Edie, linuxppc-dev, yellowdog-devel
> > According to fbset, it's at: 0x8a008900
> > Furthermore, it makes most sense that mmap() should take care of page
> > alignment issues for me so that the address returned by mmap() always
> > points to the data at [lseek(h, 0, SEEK_SET)]. This is not technically
> > difficult to implement, right?
>
> I think it will make munmap() more difficult to implement. Furthermore I see no
> provisions for this in the current mmap() code. And it will break backwards
> compatibility.
And returning a different address than the one the kernel actually used
for the mapping isn't tecnically correct either.
The problem (if I understood your problem right) did occur for m68k Mac
framebuffers earlier, and we tried a few things (passing back the
address+offset, passing the offset into the first page in fb_info, ...)
and finally agreed on the current implementation. The corresponding code
should be in the fbdev X server since sometime last year (I hope; Geert
should have gotten the patch or made his own version).
Michael
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~1999-12-01 15:06 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
1999-11-30 22:06 Frame buffer / mmap() weirdness Stephen Edie
1999-11-30 21:19 ` Geert Uytterhoeven
1999-11-30 22:43 ` Stephen Edie
1999-12-01 7:28 ` Geert Uytterhoeven
1999-12-01 8:16 ` Momchil Velikov
1999-12-01 9:13 ` Geert Uytterhoeven
1999-12-01 9:54 ` Gabriel Paubert
1999-12-01 11:02 ` Momchil Velikov
1999-12-01 13:02 ` Gabriel Paubert
1999-12-01 15:06 ` Momchil Velikov
1999-12-01 11:12 ` Michael Schmitz
1999-12-01 9:26 ` Michael Schmitz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).