From: Roland Dreier <roland@topspin.com>
To: linux-kernel@vger.kernel.org
Subject: PCI DMA to small buffers on cache-incoherent arch
Date: 08 Jun 2002 13:38:53 -0700 [thread overview]
Message-ID: <52vg8ta4ki.fsf@topspin.com> (raw)
I recently fixed some problems in the 2.4 USB stack that caused
crashes on the PowerPC 440GP (and probably other cache-incoherent
architectures). However, some parts of my fix have raised some
questions on the linux-usb-devel and linuxppc-embedded mailing lists
and I would like to raise these issues here so that we can get a
definitive answer. I would especially appreciate comments from David
Miller and other PCI DMA experts.
The problem that caused crashes on cache-incoherent architectures (my
specific system uses a PPC 440GP but this should apply in general) was
the following. The USB stack was doing PCI DMA into buffers that were
allocated on the stack, which causes stack corruption: on the PPC
440GP, pci_map_single() with PCI_DMA_FROMDEVICE just invalidates the
cache for the region being mapped. However, if a buffer is smaller
than a cache line, then two bad things can happen.
First, there may be valid data outside the buffer but in the same
cache line that has not been flushed to main memory yet. In that case
when the cache is invalidated the new data is lost and any access to
that memory will get the old data from main memory. Second, access to
the cache line after the cache has been invalidated but before the DMA
has completed will pull the cache line back into processor cache and
the DMA buffer will have invalid data.
The solution to this was simply to use kmalloc() to allocate buffers
instead of using automatic variables. On the PPC 440GP this is
definitely safe because the 440GP's has 32 byte cache lines and
kmalloc() will never return a buffer that is smaller than 32 bytes or
not 32-byte aligned. However, this leads to my first question: is
this safe on all architectures? Could there be a cache-incoherent
architecture where kmalloc() returned a buffer smaller than a cache
line?
The second question is related to this. There are other parts of the
USB stack where structures are defined:
struct something {
/* ... some members ... */
char buffer[SMALLER_THAN_L1_CACHE_LINE_SIZE];
/* ... some more members ... */
};
Then a struct something is kmalloc()'ed and buffer is used to DMA
into. However, even though the overall structure is aligned on a
cache line boundary, buffer is not aligned. It seems to me that this
is not safe because access to members near buffer during a DMA could
cause corruption (as detailed above). In my patch I changed code like
this to look like
struct something {
/* ... some members ... */
char *buffer;
/* ... some more members ... */
};
and then kmalloc()'ed buffer separately when kmalloc()'ing a struct
something.
However, there is some question about whether changing these buffers
is really necessary. Code like the above doesn't cause immediately
obvious crashes the way buffers on the stack do (since we usually get
lucky and don't touch the members near buffer around the DMA access).
I felt that relying on this coincidence is not safe and should be
fixed at the same time.
DMA-mapping.txt says kmalloc()'ed memory is OK for DMAs and does not
mention cache alignment. So the question is: did I misunderstand the
cache coherency issues or is my patch correct? At a higher level: how
is this supposed to work? Should code doing DMA into a smallish
buffer do
buffer = kmalloc(max(BUFFER_SIZE, L1_CACHE_BYTES), GFP_XXX);
or is a kmalloc()'ed buffer always safe? Does the code doing DMA need
to worry about the cache alignment of its buffer?
In any case this probably needs to be documented better. Once I
understand the answer I'll write up a patch to DMA-mapping.txt so no
one has to rediscover all this.
Thanks,
Roland
next reply other threads:[~2002-06-08 20:38 UTC|newest]
Thread overview: 99+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-06-08 20:38 Roland Dreier [this message]
2002-06-08 13:58 ` PCI DMA to small buffers on cache-incoherent arch Anton Blanchard
2002-06-09 0:52 ` Roland Dreier
2002-06-08 23:03 ` David S. Miller
2002-06-09 0:40 ` Roland Dreier
2002-06-09 0:53 ` David S. Miller
2002-06-09 1:26 ` Roland Dreier
2002-06-09 5:29 ` David S. Miller
2002-06-09 6:16 ` Roland Dreier
2002-06-10 16:03 ` Roland Dreier
2002-06-11 14:04 ` David Woodhouse
2002-06-09 6:45 ` Oliver Neukum
2002-06-10 4:24 ` David S. Miller
2002-06-10 10:00 ` Oliver Neukum
2002-06-10 10:24 ` David S. Miller
2002-06-09 9:51 ` Paul Mackerras
2002-06-09 10:54 ` Benjamin Herrenschmidt
2002-06-10 4:27 ` David S. Miller
2002-06-10 15:59 ` Roland Dreier
2002-06-10 17:03 ` Tom Rini
2002-06-10 17:22 ` Oliver Neukum
2002-06-10 17:29 ` Tom Rini
2002-06-10 17:39 ` Oliver Neukum
2002-06-10 19:03 ` Roland Dreier
2002-06-10 19:14 ` Tom Rini
2002-06-10 19:21 ` Roland Dreier
2002-06-10 19:26 ` Tom Rini
2002-06-10 17:57 ` Russell King
2002-06-10 17:28 ` Roland Dreier
2002-06-10 18:07 ` William Jhun
2002-06-10 18:29 ` William Jhun
2002-06-10 18:33 ` Mark Zealey
2002-06-10 18:44 ` Oliver Neukum
2002-06-11 3:10 ` David S. Miller
2002-06-11 4:04 ` Roland Dreier
2002-06-11 4:16 ` Brad Hards
2002-06-11 4:24 ` Roland Dreier
2002-06-11 4:24 ` David S. Miller
2002-06-11 4:21 ` David S. Miller
2002-06-11 4:39 ` Roland Dreier
2002-06-11 4:38 ` David S. Miller
2002-06-11 6:23 ` Oliver Neukum
2002-06-11 6:38 ` David S. Miller
2002-06-11 7:38 ` Oliver Neukum
2002-06-11 7:36 ` David S. Miller
2002-06-11 7:43 ` David S. Miller
2002-06-11 8:07 ` Oliver Neukum
2002-06-11 8:15 ` David S. Miller
2002-06-11 12:06 ` Oliver Neukum
2002-06-11 12:04 ` David S. Miller
2002-06-11 14:23 ` Oliver Neukum
2002-06-14 4:14 ` David S. Miller
2002-06-11 18:26 ` Roland Dreier
2002-06-11 17:29 ` Benjamin Herrenschmidt
2002-06-12 12:02 ` Oliver Neukum
2002-06-11 20:06 ` Benjamin Herrenschmidt
2002-06-12 12:02 ` David S. Miller
2002-06-11 23:00 ` Thunder from the hill
2002-06-11 23:56 ` Roland Dreier
2002-06-12 0:09 ` Thunder from the hill
2002-06-11 15:57 ` William Jhun
2002-06-12 9:06 ` Pavel Machek
2002-06-12 20:16 ` David S. Miller
2002-06-12 11:47 ` David S. Miller
2002-06-12 12:08 ` Oliver Neukum
2002-06-14 4:41 ` David S. Miller
2002-06-12 16:09 ` William Jhun
2002-06-09 1:30 ` Albert D. Cahalan
2002-06-09 5:29 ` David S. Miller
2002-06-09 6:33 ` Albert D. Cahalan
2002-06-09 6:50 ` Oliver Neukum
2002-06-09 6:57 ` Albert D. Cahalan
2002-06-09 7:15 ` Oliver Neukum
2002-06-09 8:48 ` Russell King
2002-06-09 15:42 ` Albert D. Cahalan
2002-06-09 23:26 ` Oliver Neukum
-- strict thread matches above, loose matches on Subject: below --
2002-06-11 5:31 David Brownell
2002-06-11 5:44 ` David S. Miller
2002-06-11 15:12 ` David Brownell
2002-06-11 15:44 ` Oliver Neukum
2002-06-12 3:25 ` David S. Miller
2002-06-11 17:33 ` Benjamin Herrenschmidt
2002-06-12 9:42 ` David S. Miller
2002-06-12 14:14 ` David Brownell
2002-06-12 15:00 ` Benjamin Herrenschmidt
2002-06-12 18:44 ` Roland Dreier
2002-06-12 19:13 ` David Brownell
2002-06-12 19:58 ` Oliver Neukum
2002-06-12 22:51 ` David S. Miller
2002-06-12 23:17 ` Oliver Neukum
2002-06-13 4:57 ` David Brownell
2002-06-12 22:46 ` David S. Miller
2002-06-13 5:13 ` David Brownell
2002-06-13 9:38 ` David S. Miller
2002-06-12 22:50 ` David S. Miller
2002-06-12 6:25 ` David Brownell
2002-06-12 6:24 ` David S. Miller
2002-06-12 7:06 ` David Brownell
2002-06-12 9:22 ` David S. Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52vg8ta4ki.fsf@topspin.com \
--to=roland@topspin.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox