On 28 December 2011 10:58, Bruce Evans <b...@optusnet.com.au> wrote: > On Wed, 28 Dec 2011, Bruce Evans wrote: > >> On Wed, 28 Dec 2011, Sergey Kandaurov wrote: > > >>> These were used in probe routine and are left from the newbus rewrite. >>> I hacked ie a bit to build cleanly. [Not sure if I did this correctly.] >> >> >> Use of the __DEVOLATILE() abomination is never correct. It exploits the >> bug that -Wcast-qual is broken for casts through [u]intptr_t.
Agreed. > PS: I used to maintain some bad fixes in this area for ie, but now > have only the following: > > % .Index: if_ie.c > % .=================================================================== > % .RCS file: /home/ncvs/src/sys/dev/ie/if_ie.c,v > % .retrieving revision 1.99 > % .diff -u -2 -r1.99 if_ie.c > % .--- if_ie.c 17 Mar 2004 17:50:35 -0000 1.99 > % .+++ if_ie.c 31 May 2004 06:57:05 -0000 > % .@@ -159,4 +159,7 @@ > % . #define IE_BUF_LEN ETHER_MAX_LEN /* length of transmit buffer */ > % . % .+/* XXX this driver uses `volatile' and `caddr_t' to a fault. */ > % .+typedef volatile char *v_caddr_t; /* core address, pointer to > volatile */ > % .+ > % . /* Forward declaration */ > % . struct ie_softc; Perhaps, it should be finally committed. :) > I never allowed the __DEFOO() abominations in my <sys/cdefs.h>, and at > one time had all uses to them in /usr/src removed and ready to commit > (there were about 2 of them. There are hundreds if not thousands now :-(). > c_caddr_t and v_caddr_t are as abominable as __DEFOO(), so of course I > never allowed them in my <sys/types.h>. But v_caddr_t is still easy to > remove, since it is only used in the ie driver. It is used the break > warnings from -Wcast-qual that more natural casts would give (but warnings > still result from the implicit conversion for bcopy()): > > % if_ie.c:static v_caddr_t setup_rfa (struct ie_softc *, > v_caddr_t); > > The very idea of a v_caddr_t is nonsense. caddr_t is a bad old type for > a "core address". In most cases, it means the same as "void *", but was > used because "void *" didn't exist. In FreeBSD, it must be precisely > "char *" to work, since pointer arithmetic is perpetrated on it (the > pointer arithmetic defeats its opaqueness). In a few cases, it is > used for physical or device memory accesses. In must places, it should > be spelled "void *", and in other places it should be replaced by > a vm virtual or physical address type, or a bus space type. > > To this mess, the ie driver, but mercifully no other code in /usr/src, > adds v_caddr_t. caddr_t is supposed to be opaque, but if we just cast > to that we will get a cast-qual error if we start with one of ie's > excessively qualified pointers. Also, "const caddr_t" doesn't work > since it puts the const in the wrong place. This is "solved" by looking > inside caddr_t to add the const there. > > ie uses v_caddr_t as follows: > > First, in the above, some of the excessive qualifiers are in setup_rfa()'s > return type and second parameter... > > % if_ie.c: setup_rfa(sc, (v_caddr_t) sc->rframes[0]); > % if_ie.c: setup_rfa(sc, (v_caddr_t) sc->rframes[0]); /* ignore > cast-qual */ > > ... this makes even calling setup_rfa() difficult. We start with a > volatile struct ie_mumble **rframes. We can't just cast this to void * > or caddr_t since this would cause a -Wcast-qual warning. Casting it > to "volatile void *" would be even worse, since it removes a volatile > qualifier that is in the (technically) right place and adds it back in > a wrong place. So we use v_caddr_t to keep it in the same place. I should say for above that initially sc->rframes was: volatile struct ie_recv_frame_desc *rframes[MXFRAMES]; as well as its friends rbuffs, cbuffs, etc. Then it was changed to the current volatile ** form, and MXFRAMES was replaced to some dynamic value calculated from rman, so that gives even less chances to fix the ie code properly. /* * based on the amount of memory we have, allocate our tx and rx * resources. */ factor = rman_get_size(sc->mem_res) / 8192; sc->nframes = factor * NFRAMES; sc->nrxbufs = factor * NRXBUFS; sc->ntxbufs = factor * NTXBUFS; /* * Since all of these guys are arrays of pointers, allocate as one * big chunk and dole out accordingly. */ allocsize = sizeof(void *) * (sc->nframes + (sc->nrxbufs * 2) + (sc->ntxbufs * 3)); sc->rframes = (volatile struct ie_recv_frame_desc **) malloc(allocsize, M_DEVBUF, M_NOWAIT); then all these numerous buffs volatile friends point somewhere to this memory by setting its pointer to rframes like. sc->rbuffs = (volatile struct ie_recv_buf_desc **)&sc->rframes[sc->nframes]; This prompts me to that the volatile qualifier is probably abused for many sc fields there. > % if_ie.c: bcopy((v_caddr_t) (sc->cbuffs[head] + > offset), > % if_ie.c: bcopy((v_caddr_t) (sc->cbuffs[head] + > offset), > % if_ie.c: bcopy((v_caddr_t) (sc->cbuffs[head] + offset), > > Similarly. cbuffs is a volatile u_char **. We want to aplply bcopy() > to (cbuffs[head] + offset), which is a volatile u_char *. We assume that > bcopy() is still the 1980's version which takes a caddr_t, although it > took a (void *) even in 1992. So we originally tried to bogusly cast the > arg to caddr_t. This had no effect, as would the more correct cast to > (void *) have done, since the prototype converts to void * anyway. > Eventually, -Wcast-qual was used and this bug was detected. (There may be > a more serious bug involving char * being incompatble with void *. A > grandfather kludge keeps char * equivalent to void * in many context. > But it is not clear what happens with complicated qualifiers.) Some > time later, the -Wcast-qual was broken using a volatile cast. But > the warning for converting away the qualifier by the prototype > remained. Omitting the cast would have had the same effect. > > % if_ie.c: bcopy((v_caddr_t) (sc->rframes[num]), &rfd, > > Similarly. > > % if_ie.c:static v_caddr_t > % if_ie.c:setup_rfa(struct ie_softc *sc, v_caddr_t ptr) > > The definition matching the above prototype. > > % if_ie.c: bcopy((v_caddr_t) sc->mcast_addrs, (v_caddr_t) > cmd->ie_mcast_addrs, > > Similarly. > > % if_ie.c: bzero((v_caddr_t) sc->xmit_cmds[i], sizeof > *sc->xmit_cmds[i]); > % if_ie.c: bzero((v_caddr_t) sc->xmit_buffs[i], sizeof > *sc->xmit_buffs[i]); > > Same mistakes for bzero(). Honestly, I can hardly imagine where v_caddr_t is used there properly, and if not then why it still ever exists... [Of course, this can be explained by my low C skills.] > My change isolates the v_caddr_t mistake in ie. > > The c_caddr_t mistake is used 17 times in the kernel and 75 times in > /usr/src. > > Bruce Thanks for your valuable comments. -- wbr, pluknet _______________________________________________ freebsd-net@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-net To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"