Subject: port-powerpc/22487: powerpc mmmmap() in mem.c needs to return atop(off)???
To: None <gnats-bugs@gnats.netbsd.org>
From: None <mlr@rse.com>
List: netbsd-bugs
Date: 08/14/2003 17:29:10
>Number: 22487
>Category: port-powerpc
>Synopsis: powerpc mmmmap() in mem.c needs to return atop(off)???
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: port-powerpc-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Aug 14 22:31:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator: M L Riechers
>Release: NetBSD 1.6P
>Organization:
>Environment:
System: NetBSD t982.rse.com 1.6P NetBSD 1.6P (EASTERN-1.6P.backside) #0: Fri Mar 21 18:07:11 EST 2003 mlr@t982.rse.com:/mnt2/usr/local/src/usr/src/sys/arch/macppc/compile/EASTERN-1.6P.backside macppc
Architecture: powerpc
Machine: macppc
>Description:
While hacking X for the mbx port, I noticed an inconsistancy between
/dev/mem and the mmap produced by e.g.:
base = mmap(0, Size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, Base);
where fd is an open fd on /dev/mem.
This produced the result that the mmap'd area (which happend to be the
frame buffer) which was supposed to reflect Base didn't match
lseek(fd, Base + 0x00000, SEEK_SET);
read(fd, &buckett, whatever_framebuf_size_is);
and the mmap didn't reflect the frame buffer, while the lseek/read
did.
So, I nosed around and noticed that i386, amongst others, was returning
return (atop(off));
instead of
return (trunc_page((paddr_t)off));
in their respective mmmmap() in mem.c's, which means that
powerpc/powerpc/mem.c mmmmap() is off by a factor of page size.
I applied the patch under Fix; the /dev/mem read and the mmap then
matched, and X (ahem, with other hacks, eventually) worked.
>How-To-Repeat:
Search me. Perhaps this is the source of some powerpc problems:
> From: Andreas Drewke <andreas_dr@gmx.de>
> To: <port-macppc@NetBSD.org>
> Subject: XFree86 4.3.0
> Message-ID: <29698.1060762518@www56.gmx.net>
>
> ....
>
> So now I spend some hours to get XFree86 4.3.0 built, but at the end GUESS
> what the problem is
>
> coulnd not mmap screen [a=xxxxx, s=xxxxx] (Illegal argument)
> - the same I had with 4.2.0 -
>
> ....
>
> -A
>Fix:
I find it hard to believe that powerpc needs this patch; if it does,
it seems to me that lots of stuff, particularly X windows, ought to be
non-functional. So I hesitate, but here's the patch: (please forgive
the non-functional junk at the end, but it's a hack, and I didn't want
to mess up the diff).
--- mem.c.orig 2002-10-23 06:04:09.000000000 -0400
+++ mem.c 2003-04-03 14:46:59.000000000 -0500
@@ -133,11 +133,38 @@
int prot;
{
struct proc *p = curproc;
+ int ppn;
+
+ /*
+ * /dev/mem is the only one that makes sense through this
+ * interface. For /dev/kmem any physaddr we return here
+ * could be transient and hence incorrect or invalid at
+ * a later time. /dev/null just doesn't make any sense
+ * and /dev/zero is a hack that is handled via the default
+ * pager in mmap().
+ */
if (minor(dev) != DEV_MEM)
return (-1);
+ /* XXX This may botch our cacheing assumptions. Do we care? */
+ ppn = atop(off);
+ if (ppn < physmem || suser(p->p_ucred, &p->p_acflag) == 0)
+ return ppn;
+ return -1;
+
if (atop(off) >= physmem && suser(p->p_ucred, &p->p_acflag) != 0)
return (-1);
return (trunc_page((paddr_t)off));
+ /* XXX This may botch our cacheing assumptions. Do we care? */
+ ppn = atop(off);
+ if (ppn >= 0 && ppn < physmem)
+ return ppn;
+ return -1;
+
+ /* XXX This may botch our cacheing assumptions. Do we care? */
+ ppn = atop(off);
+ if (ppn < physmem || suser(p->p_ucred, &p->p_acflag) == 0)
+ return ppn;
+ return -1;
}
>Release-Note:
>Audit-Trail:
>Unformatted: