Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Jan 2015 10:09:59 -0800
From:      Thomas Skibo <thomasskibo@sbcglobal.net>
To:        =?utf-8?Q?Manuel_St=C3=BChn?= <freebsdnewbie@freenet.de>
Cc:        freebsd-arm@freebsd.org
Subject:   Re: mmap-issue
Message-ID:  <A46186E9-BAFD-47F1-AC23-2EE5FEDECDCB@sbcglobal.net>
In-Reply-To: <54B945FB.10609@freenet.de>
References:  <54B945FB.10609@freenet.de>

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

--Apple-Mail=_AAA02F0E-6E78-48B1-876D-03D6F8DE722D
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=utf-8



> On Jan 16, 2015, at 9:10 AM, Manuel St=C3=BChn =
<freebsdnewbie@freenet.de> wrote:
>=20
>=20
> I mapped for testing purposes the AM335x-GPIO-registers from /dev/mem.
> Writing into these mmap'ed registers for toggling some LEDs does not =
immediatly take effect. I have to call it several times to get one =
LED-toggle. Is there any data caching I'm missing?
>=20
> Thanks for hints.
>=20

Yes.  On arm, /dev/mem always maps pages into user space with the data =
cache enabled.  I=E2=80=99ve run into this too.

To work around it, I ported some code from another architecture (I =
can=E2=80=99t remember which) into sys/arm/arm/mem.c to allow =
memcontrol(8) to declare some physical addresses as uncacheable.  I =
don=E2=80=99t know if this is a proper long-term solution.

This patch has been lying around on my computer for a while and so I =
haven=E2=80=99t tested it in a while.

-------
Thomas Skibo
thomasskibo@sbcglobal.net


--Apple-Mail=_AAA02F0E-6E78-48B1-876D-03D6F8DE722D
Content-Disposition: attachment;
	filename=patch.memrange.txt
Content-Type: text/plain;
	name="patch.memrange.txt"
Content-Transfer-Encoding: quoted-printable

Index: sys/arm/arm/mem.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/arm/arm/mem.c	(revision 269763)
+++ sys/arm/arm/mem.c	(working copy)
@@ -68,9 +68,21 @@
 /*
  * Used in /dev/mem drivers and elsewhere
  */
+static void arm_mrinit(struct mem_range_softc *);
+static int arm_mrset(struct mem_range_softc *, struct mem_range_desc *, =
int *);
+
 MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors");
=20
-struct mem_range_softc mem_range_softc;
+static struct mem_range_ops arm_mem_range_ops =3D {
+	arm_mrinit,
+	arm_mrset,
+	NULL,
+	NULL
+};
+struct mem_range_softc mem_range_softc =3D {
+	&arm_mem_range_ops,
+	0, 0, NULL
+};=20
=20
 /* ARGSUSED */
 int
@@ -152,12 +164,132 @@
=20
 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) =3D=3D CDEV_MINOR_MEM)
+	int i;
+
+	if (dev2unit(dev) =3D=3D CDEV_MINOR_KMEM)
+        	*paddr =3D vtophys(offset);
+	else if (dev2unit(dev) =3D=3D CDEV_MINOR_MEM) {
 		*paddr =3D offset;
-	else if (dev2unit(dev) =3D=3D CDEV_MINOR_KMEM)
-        	*paddr =3D vtophys(offset);
+
+		for (i =3D 0; i < mem_range_softc.mr_ndesc; i++) {
+			if ((mem_range_softc.mr_desc[i].mr_flags &
+			     MDF_ACTIVE) !=3D 0 &&
+			    offset >=3D =
mem_range_softc.mr_desc[i].mr_base &&
+			    offset < mem_range_softc.mr_desc[i].mr_base =
+
+			    mem_range_softc.mr_desc[i].mr_len &&
+			    (mem_range_softc.mr_desc[i].mr_flags &
+			     MDF_ATTRMASK) =3D=3D MDF_UNCACHEABLE) {
+				*memattr =3D VM_MEMATTR_UNCACHEABLE;
+				break;
+			}
+		}
+	}
 	/* else panic! */
 	return (0);
 }
+
+static void
+arm_mrinit(struct mem_range_softc *sc)
+{
+	sc->mr_cap =3D 0;
+	sc->mr_ndesc =3D 8; /* XXX: Should be dynamically expandable */
+	sc->mr_desc =3D malloc(sc->mr_ndesc * sizeof(struct =
mem_range_desc),
+	    M_MEMDESC, M_NOWAIT | M_ZERO);
+	if (sc->mr_desc =3D=3D NULL)
+		panic("%s: malloc returns NULL", __func__);
+}
+
+static int
+arm_mrset(struct mem_range_softc *sc, struct mem_range_desc *desc, int =
*arg)
+{
+	int i;
+
+	switch(*arg) {
+	case MEMRANGE_SET_UPDATE:
+		for (i =3D 0; i < sc->mr_ndesc; i++) {
+			if (!sc->mr_desc[i].mr_len) {
+				sc->mr_desc[i] =3D *desc;
+				sc->mr_desc[i].mr_flags |=3D MDF_ACTIVE;
+				return (0);
+			}
+			if (sc->mr_desc[i].mr_base =3D=3D desc->mr_base =
&&
+			    sc->mr_desc[i].mr_len =3D=3D desc->mr_len)
+				return (EEXIST);
+		}
+		return (ENOSPC);
+	case MEMRANGE_SET_REMOVE:
+		for (i =3D 0; i < sc->mr_ndesc; i++)
+			if (sc->mr_desc[i].mr_base =3D=3D desc->mr_base =
&&
+			    sc->mr_desc[i].mr_len =3D=3D desc->mr_len) {
+				bzero(&sc->mr_desc[i], =
sizeof(sc->mr_desc[i]));
+				return (0);
+			}
+		return (ENOENT);
+	default:
+		return (EOPNOTSUPP);
+	}
+
+	return (0);
+}
+
+/*
+ * Operations for changing memory attributes.
+ *
+ * This is basically just an ioctl shim for mem_range_attr_get
+ * and mem_range_attr_set.
+ */
+/* ARGSUSED */
+int=20
+memioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, int =
flags,
+	 struct thread *td)
+{
+	int nd, error =3D 0;
+	struct mem_range_op *mo =3D (struct mem_range_op *)data;
+	struct mem_range_desc *md;
+=09
+	/* is this for us? */
+	if ((cmd !=3D MEMRANGE_GET) &&
+	    (cmd !=3D MEMRANGE_SET))
+		return (ENOTTY);
+
+	/* any chance we can handle this? */
+	if (mem_range_softc.mr_op =3D=3D NULL)
+		return (EOPNOTSUPP);
+
+	/* do we have any descriptors? */
+	if (mem_range_softc.mr_ndesc =3D=3D 0)
+		return (ENXIO);
+
+	switch (cmd) {
+	case MEMRANGE_GET:
+		nd =3D imin(mo->mo_arg[0], mem_range_softc.mr_ndesc);
+		if (nd > 0) {
+			md =3D (struct mem_range_desc *)
+				malloc(nd * sizeof(struct =
mem_range_desc),
+				       M_MEMDESC, M_WAITOK);
+			error =3D mem_range_attr_get(md, &nd);
+			if (!error)
+				error =3D copyout(md, mo->mo_desc,=20
+					nd * sizeof(struct =
mem_range_desc));
+			free(md, M_MEMDESC);
+		}
+		else
+			nd =3D mem_range_softc.mr_ndesc;
+		mo->mo_arg[0] =3D nd;
+		break;
+	=09
+	case MEMRANGE_SET:
+		md =3D (struct mem_range_desc *)malloc(sizeof(struct =
mem_range_desc),
+						    M_MEMDESC, =
M_WAITOK);
+		error =3D copyin(mo->mo_desc, md, sizeof(struct =
mem_range_desc));
+		/* clamp description string */
+		md->mr_owner[sizeof(md->mr_owner) - 1] =3D 0;
+		if (error =3D=3D 0)
+			error =3D mem_range_attr_set(md, =
&mo->mo_arg[0]);
+		free(md, M_MEMDESC);
+		break;
+	}
+	return (error);
+}
Index: sys/arm/include/memdev.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/arm/include/memdev.h	(revision 269763)
+++ sys/arm/include/memdev.h	(working copy)
@@ -34,7 +34,7 @@
=20
 d_open_t	memopen;
 d_read_t	memrw;
+d_ioctl_t	memioctl;
 d_mmap_t	memmmap;
-#define		memioctl	(d_ioctl_t *)NULL
=20
 #endif /* _MACHINE_MEMDEV_H_ */

--Apple-Mail=_AAA02F0E-6E78-48B1-876D-03D6F8DE722D--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?A46186E9-BAFD-47F1-AC23-2EE5FEDECDCB>