Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Jan 2015 15:08:15 -0700
From:      Ian Lepore <ian@freebsd.org>
To:        Manuel =?ISO-8859-1?Q?St=FChn?= <freebsdnewbie@freenet.de>
Cc:        freebsd-arm@freebsd.org
Subject:   Re: mmap-issue
Message-ID:  <1421618895.14601.362.camel@freebsd.org>
In-Reply-To: <54BB871E.5050302@freenet.de>
References:  <54B945FB.10609@freenet.de> <1421432019.14601.302.camel@freebsd.org> <54BB871E.5050302@freenet.de>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 2015-01-18 at 11:12 +0100, Manuel St=FChn wrote:
> Am 16.01.2015 um 19:13 schrieb Ian Lepore:
> > My gut-level reply is "Don't try to access hardware registers like th=
at,
> > you're only going to run into problems" (as you already have).  But I=
've
> > just been informed that linux allows such things.  It seems crazy to =
me
> > to allow userland access to the same hardware that freebsd drivers ar=
e
> > trying to work with.
> >
> > So I think the right answer is that you should investigate using gpio=
ctl
> > and libgpio and the /dev/gpiocN devices.
>=20
> Please don't misunderstand me, i'm used to use drivers (if there are an=
y=20
> drivers) for a certain hardware. How could i possibly test, if the valu=
e=20
> is really written through directly? Reading it back in the program woul=
d=20
> have delivered me the cached value. This mmap-call was made to test if=20
> the value I wrote to the hardware gets written directly and drives the=20
> LED accordingly. I did this to prove my theory that the mmap-call is=20
> somehow/-where cached (what i did not expect because MAP_SHARED was=20
> set). The Linux-behavior was more what i did expect.
>=20
> > The direct answer to the problem you're seeing is probably that you n=
eed
> > to flush the L2 cache write buffers to ensure that the writes make it
> > all the way to the hardware, and there is no userland API for doing
> > that.  You may also be running into a problem related to an ARM
> > restriction that a given physical address must not be mapped twice us=
ing
> > different memory attributes, and those address ranges are already map=
ped
> > by the kernel as Device memory, so remapping them as Normal memory
> > via /dev/mem may result in the dreaded "undefined behavior."
> >
>=20
> What about making a kernel driver which itself maps the according memor=
y=20
> and provides it by implementing the mmap-stub? Would this be a proper=20
> way? But also in this case, caching is obstructive.

The big problem with mmap'ing device space is the ARM rule that you must
not map the same region multiple times with different memory attributes.
That is, don't map it as Device memory in the kernel and Normal-Uncached
in a user process (which is what that little hack of mine did).

The obvious solution is to have /dev/mem look up the existing attributes
for the memory you want to map, and create a new userspace mapping using
the same attributes.  Then your Device memory accesses would work
correctly (writes would go through to the device without caching or
write-combining).  The problem is that there is no mechanism for doing
that right now in the device-mmap support within the kernel.  It's
possible to specify a few generic parameters about the memory (uncached
or normal or whatever), but no way to express all the various
ARM-specific mapping attributes (inner/outer shared and so on) in a way
that the machine-independent VM layer can handle.

Even with the memory mapped correctly there could still be problems.
Device memory is write-buffered, but write-combining within the buffers
is prevented.  The buffering means that when you write a value to a
device it can linger for an unknown time in a buffer.  Within the kernel
we have mechanisms to force-drain the buffer and wait for that to
complete, but /dev/mem doesn't provide a parallel mechanism.

Also, any "look up the current attributes" mechanism will only work
right for device memory if the device is already mapped.  If you wanted
to access a device the kernel didn't already have mapped, the /dev/mem
driver would have no idea that the memory needed to be mapped with the
Device attribute.  This is something where a driver written specifically
to help you access a device directly from userland could do the right
thing.  That driver could perhaps also provide ioctl functions to let
you trigger a buffer-drain as needed. =20

-- Ian




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