Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Nov 2014 19:14:59 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r274191 - head/sys/arm/arm
Message-ID:  <201411061914.sA6JExbo018006@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Thu Nov  6 19:14:58 2014
New Revision: 274191
URL: https://svnweb.freebsd.org/changeset/base/274191

Log:
  Strengthen the sanity checking of busdma tag parameters.
  
  It turns out an alignment of zero can lead to an endless loop in the
  vm reservations code, so specifically disallow that.  The manpage says
  hardware which can do dma at any address should use a value of one, which
  hints at the forbiddeness of zero without exactly saying it.  Several
  other conditions which could lead to insanity in working with the tag are
  also checked now.
  
  Every existing call to bus_dma_tag_create() (about 680 of them) was
  eyeballed for violations of these things, and two alignment=0 glitches
  were fixed.  It's possible something was missed, but overall this
  shouldn't lead to any arm users suddenly experiencing failures.

Modified:
  head/sys/arm/arm/busdma_machdep-v6.c

Modified: head/sys/arm/arm/busdma_machdep-v6.c
==============================================================================
--- head/sys/arm/arm/busdma_machdep-v6.c	Thu Nov  6 18:50:59 2014	(r274190)
+++ head/sys/arm/arm/busdma_machdep-v6.c	Thu Nov  6 19:14:58 2014	(r274191)
@@ -64,6 +64,8 @@ __FBSDID("$FreeBSD$");
 #include <machine/cpufunc.h>
 #include <machine/md_var.h>
 
+#define	IS_POWER_OF_2(val)	(((val) & ((val) - 1)) == 0)
+
 #define MAX_BPAGES 64
 #define MAX_DMA_SEGMENTS	4096
 #define BUS_DMA_EXCL_BOUNCE	BUS_DMA_BUS2
@@ -466,17 +468,18 @@ bus_dma_tag_create(bus_dma_tag_t parent,
 		parent = arm_root_dma_tag;
 #endif
 
-	/* Basic sanity checking */
-	if (boundary != 0 && boundary < maxsegsz)
-		maxsegsz = boundary;
+	/* Basic sanity checking. */
+	KASSERT(boundary == 0 || IS_POWER_OF_2(boundary),
+	    ("dma tag boundary %lu, must be a power of 2", boundary));
+	KASSERT(boundary == 0 || boundary >= maxsegsz,
+	    ("dma tag boundary %lu is < maxsegsz %lu\n", boundary, maxsegsz));
+	KASSERT(alignment != 0 && IS_POWER_OF_2(alignment),
+	    ("dma tag alignment %lu, must be non-zero power of 2", alignment));
+	KASSERT(maxsegsz != 0, ("dma tag maxsegsz must not be zero"));
 
 	/* Return a NULL tag on failure */
 	*dmat = NULL;
 
-	if (maxsegsz == 0) {
-		return (EINVAL);
-	}
-
 	newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF,
 	    M_ZERO | M_NOWAIT);
 	if (newtag == NULL) {



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