Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Jan 2015 20:48:35 -0700
From:      Ian Lepore <ian@freebsd.org>
To:        Johny Mattsson <johny.mattsson+fbsd@gmail.com>
Cc:        freebsd-arm@freebsd.org
Subject:   Re: mmap-issue
Message-ID:  <1421466515.14601.323.camel@freebsd.org>
In-Reply-To: <CAGW5k5YqK-xP_erf6H2XXUKmX8Dkbex81SYC5am5saAAqRfp8A@mail.gmail.com>
References:  <54B945FB.10609@freenet.de> <1421432019.14601.302.camel@freebsd.org> <CAGW5k5YqK-xP_erf6H2XXUKmX8Dkbex81SYC5am5saAAqRfp8A@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--=-unJQW8/bIhpk1ulCm/5l
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit

On Sat, 2015-01-17 at 10:34 +1100, Johny Mattsson wrote:
> On 17 January 2015 at 05:13, Ian Lepore <ian@freebsd.org> wrote:
> 
> > My gut-level reply is "Don't try to access hardware registers like that,
> > you're only going to run into problems" (as you already have).  But I've
> > just been informed that linux allows such things.
> 
> 
> Indeed it does, and what a life^Wproject-saver it can be! Only last year I
> had to deal with an existing large-scale deployment (100,000s of devices)
> where a peripheral on the SPI bus had a hardware bug where it could
> intermittently "lose" a clock pulse and get itself completely out of sync
> on the bus. Being able to quietly pull the SPI control from the driver and
> do a little dance on the clock and data lines in GPIO mode before returning
> control to the driver saved the day on that one.
> 
> A few years before that, we had some extremely performance sensitive
> network I/O to deal with, where we effectively had a driver stub which
> allocated the resources and then allowed them to be mmap()ed into userspace
> for direct hardware control. Given the complexity of the system, it wasn't
> considered viable to have this processing done in the kernel.
> 

That's a very different thing... a driver that exists primarily to give
userland access to hardware can be written to map the memory correctly
and presumably won't be accessing the hardware concurrently with
userland and so on.  It's a bit safer than just using /dev/mem to start
bashing on hardware without any cooperation from the bits of the OS
doing the same.

Anyway, after glancing at the code implementing /dev/mem on freebsd arm
I think it's woefully incomplete.  It's basically a copy of the i386
code, which means it assumes that caches take care of themselves at some
hardware level.  What we need is something more like the PowerPC
implementation that supports the ioctls documented in mem(4) for setting
up uncached mappings.

All in all, I think it could take a while to fix this properly.  For the
near term, the attached patch may be a reasonable(ish) hack to get
device access to work.  (Its drawback is that it can only detect device
memory if it's part of the statically-mapped resources for the platform.
On the plus side, for beaglebone all device memory is statically mapped
in ti_machdep.c.)

This is completely untested other than "it compiles."

-- Ian


--=-unJQW8/bIhpk1ulCm/5l
Content-Disposition: inline; filename="devmem_uncacheable_hack.diff"
Content-Type: text/x-patch; name="devmem_uncacheable_hack.diff"; charset="us-ascii"
Content-Transfer-Encoding: 7bit

Index: sys/arm/arm/mem.c
===================================================================
--- sys/arm/arm/mem.c	(revision 277262)
+++ sys/arm/arm/mem.c	(working copy)
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/pmap.h>
 #include <vm/vm_extern.h>
 
+#include <machine/devmap.h>
 #include <machine/memdev.h>
 #include <machine/vmparam.h>
 
@@ -152,7 +153,7 @@ memrw(struct cdev *dev, struct uio *uio, int flags
 
 int
 memmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
-    int prot __unused, vm_memattr_t *memattr __unused)
+    int prot __unused, vm_memattr_t *memattr)
 {
 	if (dev2unit(dev) == CDEV_MINOR_MEM)
 		*paddr = offset;
@@ -159,5 +160,7 @@ memmmap(struct cdev *dev, vm_ooffset_t offset, vm_
 	else if (dev2unit(dev) == CDEV_MINOR_KMEM)
         	*paddr = vtophys(offset);
 	/* else panic! */
+    if (arm_devmap_ptov(*paddr, 4) != NULL)
+        *memattr = VM_MEMATTR_UNCACHEABLE;
 	return (0);
 }

--=-unJQW8/bIhpk1ulCm/5l--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1421466515.14601.323.camel>