kern/154259: [sound][snd_emu10kx][patch] Fix data type overflow (signed/unsigned mismatch) in args of bus_dma_tag_create

Vladislav Movchan vladislav.movchan at gmail.com
Mon Jan 24 12:40:14 UTC 2011


>Number:         154259
>Category:       kern
>Synopsis:       [sound][snd_emu10kx][patch] Fix data type overflow (signed/unsigned mismatch) in args of bus_dma_tag_create
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jan 24 12:40:10 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator:     Vladislav Movchan
>Release:        FreeBSD 9.0-CURRENT r217756 amd64
>Organization:
>Environment:
FreeBSD ground 9.0-CURRENT FreeBSD 9.0-CURRENT #5 r217756: Sun Jan 23 21:25:58 EET 2011     user at ground:/usr/obj/usr/src/sys/Mephistophelis  amd64
>Description:
If you use snd_emu10k1 or snd_emu10kx drivers on amd64 system there is a chance that you hear high frequency noise / buzz instead of sound. It is much higher probability to reproduce this problem if you use any of drivers mentioned above as separate kernel modules loaded at the end of boot process, then if you compile this devices into kernel.

This problem was mentioned several times in mail lists (but without solution):
http://lists.freebsd.org/pipermail/freebsd-multimedia/2010-April/010928.html
http://lists.freebsd.org/pipermail/freebsd-stable/2010-July/057687.html

This problem caused by data type overflow (signed/unsigned mismatch) in one of arguments of bus_dma_tag_create() during data type conversion:
lowaddr argument set as "1 << 31" and because of "1" is signed (by default) "1 << 31" (10000000000000000000000000000000 in binary) become 18446744071562067968 (1111111111111111111111111111111110000000000000000000000000000000 in binary) when it is converted to bus_addr_t data type (what is typedef-ed to uint64_t).

As result address range (for DMA) will not be limited to 0-2Gb (only range that hardware is possible to address), and when driver will be forced to use addresses higher than 2Gb you hear noise instead of sound. 

If you are using snd_emu10kx and selected "Boot FreeBSD with verbose logging" in loader prompt, then you are able to see wrong mappings in logs:

Jan 23 22:37:28 ground kernel: emu10kx: setmap (43390000, 1000), nseg=1, error=0
Jan 23 22:37:28 ground kernel: emu10kx: setmap (119cf0000, 1000), nseg=1, error=0
Jan 23 22:37:28 ground kernel: emu10kx: setmap (12f3d0000, 1000), nseg=1, error=0
Jan 23 22:37:28 ground kernel: emu10kx: setmap (be830000, 1000), nseg=1, error=0

Second, third and fourth lines shows mappings above 2Gb, what should not happened.


PS: I suppose it is necessary to have more than 2 Gb of ram installed on amd64 machine to be able to reproduce this problem (I have 6Gb on test system).

Also I was not able to reproduce original problem on i386 with 4Gb of ram installed. Looks like it is related to amd64 only.

This problem is related to snd_emu10k1 and snd_emu10kx drivers. Problem was reproduced by me and fix was tested for both drivers.
>How-To-Repeat:
Use snd_emu10k1 or snd_emu10kx as module, load it at the end of boot process. If you are still able play music correctly - do 

kldunload  /boot/kernel/snd_emu10kx.ko;
kldload /boot/kernel/snd_emu10kx.ko;
mpg123 test.mp3;

several iterations of kldunload / kldload usually enough to hear high frequency noise instead of music.
>Fix:
Attached patch fixed this problem for me (both drivers tested)

Patch attached with submission follows:

Index: sys/dev/sound/pci/emu10k1.c
===================================================================
--- sys/dev/sound/pci/emu10k1.c	(revision 217774)
+++ sys/dev/sound/pci/emu10k1.c	(working copy)
@@ -2017,7 +2017,7 @@
 
 	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
 		/*boundary*/0,
-		/*lowaddr*/1 << 31, /* can only access 0-2gb */
+		/*lowaddr*/1u << 31, /* can only access 0-2gb */
 		/*highaddr*/BUS_SPACE_MAXADDR,
 		/*filter*/NULL, /*filterarg*/NULL,
 		/*maxsize*/sc->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
Index: sys/dev/sound/pci/emu10kx.c
===================================================================
--- sys/dev/sound/pci/emu10kx.c	(revision 217774)
+++ sys/dev/sound/pci/emu10kx.c	(working copy)
@@ -2700,7 +2700,7 @@
 
 	if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(sc->dev),
 	     /* alignment */ 2, /* boundary */ 0,
-	     /* lowaddr */ 1 << 31,	/* can only access 0-2gb */
+	     /* lowaddr */ 1u << 31,	/* can only access 0-2gb */
 	     /* highaddr */ BUS_SPACE_MAXADDR,
 	     /* filter */ NULL, /* filterarg */ NULL,
 	     /* maxsize */ EMU_MAX_BUFSZ, /* nsegments */ 1, /* maxsegz */ 0x3ffff,


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list