Date: Mon, 27 Aug 2012 09:57:48 -0600 From: Warner Losh <imp@bsdimp.com> To: Ian Lepore <freebsd@damnhippie.dyndns.org> Cc: freebsd-arm@freebsd.org, freebsd-arch@freebsd.org, freebsd-mips@freebsd.org, Hans Petter Selasky <hans.petter.selasky@bitfrost.no> Subject: Re: Partial cacheline flush problems on ARM and MIPS Message-ID: <AAA06FDC-19E1-47B3-B29F-FD2E8F57022B@bsdimp.com> In-Reply-To: <1346081557.1140.181.camel@revolution.hippie.lan> References: <1345757300.27688.535.camel@revolution.hippie.lan> <3A08EB08-2BBF-4B0F-97F2-A3264754C4B7@bsdimp.com> <1345763393.27688.578.camel@revolution.hippie.lan> <FD8DC82C-AD3B-4EBC-A625-62A37B9ECBF1@bsdimp.com> <1345765503.27688.602.camel@revolution.hippie.lan> <CAJ-VmonOwgR7TNuYGtTOhAbgz-opti_MRJgc8G%2BB9xB3NvPFJQ@mail.gmail.com> <1345766109.27688.606.camel@revolution.hippie.lan> <CAJ-VmomFhqV5rTDf-kKQfbSuW7SSiSnqPEjGPtxWjaHFA046kQ@mail.gmail.com> <F8C9E811-8597-4ED0-9F9D-786EB2301D6F@bsdimp.com> <1346002922.1140.56.camel@revolution.hippie.lan> <CAP%2BM-_HZ4yARwZA2koPJDeJWHT-1LORupjymuVnMtLBzeXe=DA@mail.gmail.com> <1346005507.1140.69.camel@revolution.hippie.lan> <10307B47-13F3-45C0-87F7-66FD3ACA3F86@bsdimp.com> <1346081557.1140.181.camel@revolution.hippie.lan>
next in thread | previous in thread | raw e-mail | index | archive | help
On Aug 27, 2012, at 9:32 AM, Ian Lepore wrote: > On Sun, 2012-08-26 at 17:13 -0600, Warner Losh wrote: >> On Aug 26, 2012, at 12:25 PM, Ian Lepore wrote: >>> In this regard, it's the busdma implementation that's broken, = because it >>> should bounce those IOs through a DMA-safe buffer. There's = absolutely >>> no rule that I've ever heard of in FreeBSD that says IO can only = take >>> place using memory allocated from busdma. >>=20 >> That's partially true. Since BUSDMA grew up in the storage area, you = must allocate the memory from busdma, or it must be page aligned has = been the de-facto rule here. =20 >=20 > Where does anything say that you must allocate the memory from busdma = if > it's not mbuf/page-aligned? I've never seen it in any docs. I > certainly find contrary evidence in existing driver code (and I'm not > talking about USB here). Where does it say that you are allowed to not use the routines? >> The mbuf and uio variants of load were invented to cope with common = cases of mbufs and user I/O to properly flag things. >>=20 >=20 > What does that mean, "to properly flag things"? >=20 > I think with uio we come to the crux of the issue. Userland buffers = are > not allocated with knowledge of the busdma constraints. That leads to > some choices: >=20 > * We don't support IO with a userland buffer at all. You may have to bounce here. > * We support userland IO if the userland buffers are accidentally > aligned properly for the platform, otherwise the call fails. You may have to bounce here. > * We support userland buffers by making any driver which wants to > do so responsible for always copying the data to aligned = buffers > (each individual driver handles bounces). This is what most drivers that want to do zero copying do. > * We support userland buffers by having the busdma layer handle > the bouncing when required. I thought that's what the uio variants of the map loading routines were = supposed to do. > The first two seem untenable to me. The third one comes down to = "every > driver must always bounce all userland data" because the driver = doesn't > actually have access to the info to decide whether a userland buffer = is > aligned properly or not for a given platform. >=20 > That leaves the option where the busdma layer handles bouncing for > unaligned userland buffers. If that's possible, then the busdma layer > could automatically bounce any unaligned request, whether it came from > userland or a driver reading a status response into an unaligned local > buffer in kernel memory. Right, the uio load option is supposed to do this. >> How does busdma know that it is using memory that's not from its = allocator? >=20 > The busdma code allocates the map along with the buffer, and can = record > information in the map that it can use during mapping and sync > operations to know whether it allocated the buffer. >=20 >>> The rule is only that the >>> proper sequence of busdma operation must be called, and beyond that = it's >>> up to the busdma implementation to make it work. =20 >>=20 >> No. Bouncing is needed due to poor alignment of the underlying = device. Not due to cache effects. >=20 > Says who? This statement seems to me to be more about opinion and = dogma > than about a documented API or technical concerns about how to = implement > it. IMO, bouncing is needed when that's the only way to make a > particular busdma sequence work correctly given the parameters of the > hardware and the transfer. Says the people that wrote and use busdma? There's no requirement for = cache effects for the transfer, so there's no constraints for the = transfer. The requirement is about having a buffer that's suitable for = DMA. This means either the buffer (not the start of the transfer) be = aligned to a cache line and be an integral number of cache lines in = size, or it means that you have 100% perfect hygiene when it comes to = ensuring the CPU touches the buffer or the device touches it and ever = have cross threading. I'd agree that better docs here would help. > To put it another way, the busdma subsystem is responsible for helping > make DMA transfers work on a platform without every driver needing to > contain platform-specific code, and bouncing is one of the techniques > available to it. Buffers allocated through the busdma system do this. >> There's a limited number of things that we support with busdma. = Arbitrary data from malloc that might be shared with the CPU isn't on = that list. >>=20 >=20 > Where are those limitations documented? =20 Where is it documented that memory returned from malloc may be used for = DMA? I agree that docs could be better here. > This isn't some small oversight in the documention, if the rule is = "IO, > any IO at all, can only be performed using buffers allocated from > busdma" that's a pretty major thing that ought to appear in multiple > manpages relating to driver development. >=20 > If you don't think "any IO at all" is the right characterization, read > all the way to the end before responding. Yes. I'd state it another way. "Buffers returned from the busdma = allocation routines is always safe." Everything else may or may not be = safe. mbufs, for example, happen to be safe because there is a rigid = protocol for sharing between the driver and the device. uio buffers can = be made safe. busdma has routines to ensure that these types of data = are handled properly. >>> Our biggest problem, I think, is that we don't have a sufficient >>> definition of "the proper sequence of busdma operations." >>=20 >> I disagree. The sequence has been known for a long time. >>=20 >>> I don't think it will be very hard to make the arm and mips busdma >>> implementations work correctly. It won't even be too hard to make = them >>> fairly efficient at bouncing small IOs (my thinking is that we can = make >>> small bounces no more expensive than the current partial cacheline = flush >>> implementation which copies the data multiple times). Bouncing = large IO >>> will never be efficient, but the inefficiency will be a powerful >>> motivator to update drivers that do large IO to work better, such as >>> using buffers allocated from busdma. >>=20 >> I don't think the cache line problem can be solved with bounce = buffers. Trying to accommodate broken drivers is what lead us to this = spot. We need to fix the broken drivers. If that's impossible, then = the best we can do is have the driver set a 'always bounce' flag in the = tag it creates and use that to always bounce for operations through that = tag. >=20 > So you'd be okay with a driver setting a flag that says "always = bounce" > but not okay with the busdma layer bouncing only when it's actually > necessary? I'm confused -- do you think the busdma layer will be = unable > to detect when it's necessary unless directed from the outside? Actually, it is good you are confused. I was wrong when I said I'd be = happy with a flag that says always bounce. The reason is that the driver = can do this all the time for those cases like the at91 mci driver does. > Let me pose a question back to you... if it is up to a driver to > allocate DMA buffers using the busdma allocator, how is any given = driver > to know whether DMA is going to be involved in the transfer? =20 because it does the dma? > Don't think USB or ATA here... think iicbus/foo_temperature_sensor, or > the mmc/sd driver. Those drivers know nothing about the hardware = bridge > layers beneath them and whether DMA is involved or not. They just = know > "I need to read a 2-byte value from a register on this IIC chip" or "I > need to retrieve the 32-bit CSD data from the SD card" and they > accomplish that by calling a read method of some lower-level bridge > driver. In each of those cases we have both PIO and DMA = implementations > of the lower-level drivers that move bits over a wire. The bridge here would know and have to cope. However, the real issue in = this case wouldn't be the transfer alignment, but what traffic might be = happening to other parts of the cache line. For small things like this, typically data copies are involved. There's = a few places that break these rules (I think mci might be breaking the = rules for small transfers, for example). > If the concensus is that such drivers should always allocate all IO > buffers using busdma, even though they have no idea whether DMA is = going > to be involved, then we certainly have a lot of work ahead of us in > terms of "fixing broken drivers." That also implies that > bus_dmamem_alloc() is misnamed and implemented in the wrong place, > because it's not really about dma at all. You can't get around the hardware requirement that any I/O going to the = device cannot share cache lines with other data on the system. > If you push the responsibility down to the layer where it is known > whether DMA is going to be involved, then we're back to the need for > many individual drivers to bounce every request, because they don't = have > access to the info needed to know whether bouncing is required or not > for a given buffer they were handed from higher layers. (Remember = when > I proposed exporting that info to drivers so they could decide whether = a > buffer is dma-aligned or not, the response was "No, keep it all hidden > in the busdma layer," which I think is the right response.) Right now we support only a few things doing DMA on the system. We = support pages, mbufs and to a limited extent uio buffers (but to be = honest, we may have exposure on smaller transfers here). > Or if you push the responsibility down to the busdma layer where all > that info resides, all drivers which use DMA and adhere to the busdma > rules just work, without needing to know anything about the buffers = that > were handed to them and without needing to know anything about the > platform requirements. I'm not sure I follow this last bit... Warner
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AAA06FDC-19E1-47B3-B29F-FD2E8F57022B>