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>