Skip to contentSkip to conversation

Missing cache flush.

DISCUSSION David Woodhouse 17 participants 34 messages Jun 4, 2001 – Jun 8, 2001 Memory technology devices (MTD)

lore
Share & tools
lore
#0 lore raw

The flash mapping driver arch/cris/drivers/axisflashmap.c uses a cached mapping of the flash chips for bulk reads, but obviously an uncached mapping for sending commands and reading status when we're actually writing to or erasing parts of the chip.

However, it fails to flush the dcache for the range used when the flash is accessed through the uncached mapping. So after an erase or write, we may read old data from the cache for the changed area.

All the mapping driver needs to do is invalidate the dcache for the affected area before the next copy_from() operation. No need to worry about writeback in this case, because we never write to flash chips through the cached mapping.

However, I can't see a cache operation which performs this function. flush_dcache_page() is defined as a NOP on CRIS as, it seems, it is on most architectures. On other architectures, there's dma_cache_wback_inv(), but that also seems to be a NOP on i386, to pick a random example.

I'm aware that some architectures can't handle having both cached and uncached mappings of the same physical range - so to prevent dismissal of the question out of hand by people assuming all the world's a PeeCee - consider the alternative situation where we have ROM or RAM chips in a paged mapping such that only a 64K 'page' is visible by the CPU at a time (remember XMS?). Using an uncached mapping is extremely suboptimal - all we want to do is invalidate the cache when we change the page, or writeback and invalidate in the case of RAM.

I would have thought that's the function that dma_cache_wback_inv() is supposed to perform - but it seems not to do so.

So how is this _supposed_ to be done?

I was pointed at Documentation/DMA-mapping.txt but that doesn't seem very helpful - it's very PCI-specific, and a quick perusal of pci_dma_sync() on i386 shows that it doesn't do what's required anyway.

--
dwmw2

#1 lore raw
Quoted 3 lines · David Woodhouse

I was pointed at Documentation/DMA-mapping.txt but that doesn't seem very helpful - it's very PCI-specific, and a quick perusal of pci_dma_sync() on i386 shows that it doesn't do what's required anyway.

What should it do on i386? mb()?

Signature · 4 lines
Jeff Garzik      | Echelon words of the day, from The Register:
Building 1024    | FRU Lebed HALO Spetznaz Al Amn al-Askari Glock 26 
MandrakeSoft     | Steak Knife Kill the President anarchy echelon
                 | nuclear assassinate Roswell Waco World Trade Center
#2 lore raw
Quoted 5 lines · [email protected] said:
Quoted 3 lines

I was pointed at Documentation/DMA-mapping.txt but that doesn't seem very helpful - it's very PCI-specific, and a quick perusal of pci_dma_sync() on i386 shows that it doesn't do what's required anyway.

What should it do on i386? mb()?

For it to have any use in the situation I described, it would need to writeback and invalidate the dcache for the affected range. It doesn't seem to do so, so it seems that it isn't what I require.

The situation is simple - I have a paged RAM setup and I need it cached. All I want to do is flush and invalidate the cache when I'm about to waggle whatever I/O ports I waggle to change pages.

There are other situations in which I need the cache flushed, but the above is one of the simplest.

Even flush_page_to_ram() doesn't seem to do what its name implies, on most architectures.

--
dwmw2

#3 lore raw
Quoted 5 lines · David Woodhouse
Quoted 1 line

What should it do on i386? mb()?

For it to have any use in the situation I described, it would need to writeback and invalidate the dcache for the affected range. It doesn't seem to do so, so it seems that it isn't what I require.

It only needs to do that on cpus where the cache is not consistent with the rest of the system. x86 caches are fully consistent with the rest of the system, thus no flushing necessary.

Later,
David S. Miller
[email protected]

#4 lore raw
In reply to Jeff Garzik
Quoted 6 lines · Jeff Garzik
Quoted 3 lines · David Woodhouse

I was pointed at Documentation/DMA-mapping.txt but that doesn't seem very helpful - it's very PCI-specific, and a quick perusal of pci_dma_sync() on i386 shows that it doesn't do what's required anyway.

What should it do on i386? mb()?

The x86 doesn't have dumb caches, therefore it really doesn't need to flush anything. Maybe a mb(), but that is it.

Later,
David S. Miller
[email protected]

#5 lore raw
In reply to David Woodhouse

On Mon, Jun 04, 2001 at 07:03:01PM -0700, David S. Miller wrote:

The x86 doesn't have dumb caches, therefore it really doesn't need to flush anything. Maybe a mb(), but that is it.

What if the memory is erased underneath the CPU being aware of this? In such a way ig generates to bus traffic...

--cw

#6 lore raw
Quoted 7 lines · Chris Wedgwood

On Mon, Jun 04, 2001 at 07:03:01PM -0700, David S. Miller wrote:

The x86 doesn't have dumb caches, therefore it really doesn't need to flush anything. Maybe a mb(), but that is it.

What if the memory is erased underneath the CPU being aware of this? In such a way ig generates to bus traffic...

This doesn't happen on x86. The processor snoops all transactions done by other agents to/from main memory. The processor caches are always up to date.

Later,
David S. Miller
[email protected]

#7 lore raw
Quoted 7 lines · [email protected] said:
Quoted 2 lines · Chris Wedgwood

What if the memory is erased underneath the CPU being aware of this? In such a way ig generates to bus traffic...

This doesn't happen on x86. The processor snoops all transactions done by other agents to/from main memory. The processor caches are always up to date.

No. My original mail presented two situations in which this assumption is false.

1. Bank-switched RAM. You want to force a writeback before switching pages. I _guarantee_ you that the CPU isn't snooping my access to the I/O port which sets the latch that drives the upper few address bits of the RAM chips.

2. Flash. A few writes of magic data to magic addresses and a whole erase block suddenly contains 0xFF. The CPU doesn't notice that either.

What I want is a function like simon_says_flush_page_to_ram(). In this case, I _do_ know better than the CPU. It is _not_ coherent with these devices.

I'm actually working on a MIPS box at the moment - the particular problems with doing it on i386 don't interest me too much. To be honest, I could do it by sticking asm instructions inside ifdefs in what is otherwise arch-independent code. I'd rather not do it like that, though.

Surely stuff like that should be exported by the arch-specific code or include files somehow. Possibly with a #define or function I can use to tell whether a selective flush is actually available on the current CPU. If it's not possible to flush the dcache selectively, then the cost of doing a full flush probably outweighs the benefit¹ of running the flash cached in the first place. But it should still be possible to do it from arch-independent code without manually inserting asm instructions to do it.

--
dwmw2

¹ The _assumed_ benefit, admittedly. I should get some benchmarks to back up the comment about molasses in arch/cris/drivers/axisflashmap.c

#8 lore raw
Quoted 3 lines · David Woodhouse

What I want is a function like simon_says_flush_page_to_ram(). In this case, I _do_ know better than the CPU. It is _not_ coherent with these devices.

One way to do this, (even portably :-) is via displacement flushes. Linus mentioned this.

Basically if you know the L2 cache size and the assosciativity you can do this as long as you can get a "2 * L2 cache size * assosciativity" piece of contiguous physical memory. When you need this "simon says" flush, you basically read this physical memory span and this will guarentee that all dirty data has exited the L2 cache.

Later,
David S. Miller
[email protected]

#9 lore raw
Quoted 8 lines · [email protected] said:

One way to do this, (even portably :-) is via displacement flushes.
Linus mentioned this.

Basically if you know the L2 cache size and the assosciativity you can do this as long as you can get a "2 * L2 cache size * assosciativity" piece of contiguous physical memory. When you need this "simon says" flush, you basically read this physical memory span and this will guarentee that all dirty data has exited the L2 cache.

Fine. So it should be possible to do it on all architectures with physically-indexed caches - that's good. Architectures with virtually-indexed caches are going to have explicit cache management functionality anyway, presumably :)

Obviously the algorithm you describe should not be implemented in arch-independent drivers. It should be in include/asm-*, for those architectures which _can't_ do it with a single cache management instruction (or loop of same).

What shall we call this function? The intuitive "flush_dcache_range" appears to have already been taken.

--
dwmw2

#10 lore raw
Quoted 2 lines · David Woodhouse

What shall we call this function? The intuitive "flush_dcache_range" appears to have already been taken.

Call it flush_ecache_full() or something.

Many architectures need to implement this anyways if they have parity error exception handling. Most platforms sadly do not. Sparc64 is one of the exceptions here...

Later,
David S. Miller
[email protected]

#11 lore raw
Quoted 5 lines · [email protected] said:
Quoted 2 lines · David Woodhouse

What shall we call this function? The intuitive "flush_dcache_range" appears to have already been taken.

Call it flush_ecache_full() or something.

Strange name. Why? How about __flush_cache_range()?

--
dwmw2

#12 lore raw
Quoted 3 lines · David Woodhouse
Quoted 1 line

Call it flush_ecache_full() or something.

Strange name. Why? How about __flush_cache_range()?

How about flush_cache_range_force() instead?

I want something in the name that tells the reader "this flushes the caches, even though under every other ordinary circumstance you would not need to".

Later,
David S. Miller
[email protected]

#13 lore raw
Quoted 4 lines · [email protected] said:

How about flush_cache_range_force() instead?
I want something in the name that tells the reader "this flushes the caches, even though under every other ordinary circumstance you would not need to".

OL, then. I would have thought it made more sense to have the flush_dcache_range() unconditionally do what its name implies, and to have a separate flush_dcache_range_for_dma() function which is optional. But that decision was already made - I suppose we can't change the semantics now.

--
dwmw2

#14 lore raw
In reply to David S. Miller
Quoted 11 lines · David S. Miller
Quoted 3 lines · David Woodhouse
Quoted 1 line

Call it flush_ecache_full() or something.

Strange name. Why? How about __flush_cache_range()?

How about flush_cache_range_force() instead?

I want something in the name that tells the reader "this flushes the caches, even though under every other ordinary circumstance you would not need to".

"flush" means what to you?

write-back
write-back-and-invalidate
discard-and-invalidate

All 3 behaviors are useful to me, and a few more. I've been using chunks of PowerPC assembly. Using PowerPC mnemonics...

dcba -- allocate a cache block with undefined content dcbf -- write to RAM, then invalidate ("data cache block flush") dcbi -- invalidate, discarding any data
dcbst -- initiate write if dirty
dcbt -- prefetch, hinting about future load instructions dcbtst -- prefetch, hinting about future store instructions dcbz -- allocate and zero a cache block (cacheable mem only!)

So dcbf_range() and dcbi_range() sound good to me. :-)

#15 lore raw
In reply to David S. Miller

Hi!

Quoted 2 lines

What shall we call this function? The intuitive "flush_dcache_range" appears to have already been taken.

Please do not use *_dcache_*. It would confuse me with dentry cache.

Flush data cche range would be ok.

[BTW what about just rewriting it with 0xffs after you zero the block? Someone already suggested that, and it seems ok.]

Signature · 2 lines
Philips Velo 1: 1"x4"x8", 300gram, 60, 12MB, 40bogomips, linux, mutt,
details at http://atrey.karlin.mff.cuni.cz/~pavel/velo/index.html.
#16 lore raw
In reply to David Woodhouse
Quoted 13 lines · David Woodhouse
Quoted 7 lines · [email protected] said:
Quoted 2 lines · Chris Wedgwood

What if the memory is erased underneath the CPU being aware of this? In such a way ig generates to bus traffic...

This doesn't happen on x86. The processor snoops all transactions done by other agents to/from main memory. The processor caches are always up to date.

No. My original mail presented two situations in which this assumption is false.

Quoted 7 lines

1. Bank-switched RAM. You want to force a writeback before switching pages. I _guarantee_ you that the CPU isn't snooping my access to the I/O port which sets the latch that drives the upper few address bits of the RAM chips.

2. Flash. A few writes of magic data to magic addresses and a whole erase block suddenly contains 0xFF. The CPU doesn't notice that either.

3. Buggy implementations like the Cyrix 486es that don't properly maintain cache coherency.

kira.

#17 lore raw
Quoted 2 lines

3. Buggy implementations like the Cyrix 486es that don't properly maintain cache coherency.

The early Cyrix CPUs (and some 1.x rev 6x86 cpus I believe too) arent supported and dont work. The problem is best corrected with a hammer and a visit to ebay

#18 lore raw

Earyly Cyrix CPUs was Re: Missing cache flush.

In reply to kira brown

Hi1

Quoted 6 lines
Quoted 2 lines

3. Buggy implementations like the Cyrix 486es that don't properly maintain cache coherency.

The early Cyrix CPUs (and some 1.x rev 6x86 cpus I believe too) arent supported and dont work. The problem is best corrected with a hammer and a visit to ebay

What is list of cpu's not supported? I want one ;-).

[It is even more broken than 386? Wow!]

[Is it really not work-aroundable? LIke declaring no DMA on system and using PIO for floppy?]
Pavel

Signature · 2 lines
Philips Velo 1: 1"x4"x8", 300gram, 60, 12MB, 40bogomips, linux, mutt,
details at http://atrey.karlin.mff.cuni.cz/~pavel/velo/index.html.
#19 lore raw

Re: Earyly Cyrix CPUs was Re: Missing cache flush.

Quoted 2 lines

What is list of cpu's not supported? I want one ;-). [It is even more broken than 386? Wow!]

Some of the early Cyrix cpus get cache corruption. I dont know of any work around. These are the CPU's that won't run some versions of gcc (optimised egcs 1.1.2 segfaulted at random non optimised worked, both work on other cpus)

#20 lore raw
In reply to David S. Miller

Possibly saying something extremly stupid here,
how about simply "fakewriting" 0xFF to the flash
after an erase to update any caches?

Quoted 2 lines

2. Flash. A few writes of magic data to magic addresses and a whole erase block suddenly contains 0xFF. The CPU doesn't notice that either.

do_erase_stuff();
/* While verifying, update cache */

                for (address = adr; address < (adr + size); address++) {
                        if ((verify = map->read8(map, address)) != 0xFF) {
                                error = 1;
                                break;
                        }
                        /* "Fake" write 0xFF's to the erased sector so that
caches are updated
                         *  after we verified that uncached data is ok
                         */
                        *(unsigned char*)CACHED(address) = 0xFF;
                }

/Johan

#21 lore raw
In reply to David S. Miller
Quoted 5 lines · David S. Miller

Basically if you know the L2 cache size and the assosciativity you can do this as long as you can get a "2 * L2 cache size * assosciativity" piece of contiguous physical memory. When you need this "simon says" flush, you basically read this physical memory span and this will guarentee that all dirty data has exited the L2 cache.

Whether this works depends on the cache line replacement policy. It will always work with LRU, for example, and probably everything else that exists. But it is not guaranteed, is it?

-- Jamie

#22 lore raw
In reply to David S. Miller

On Tue, Jun 05, 2001 at 07:01:28PM +0200, Jamie Lokier wrote:

Whether this works depends on the cache line replacement policy. It will always work with LRU, for example, and probably everything else that exists. But it is not guaranteed, is it?

Getting way OT here... didn't the K6 or something have the ability to lock cache lines?

--cw

#23 lore raw
Quoted 5 lines · Jamie Lokier

Whether this works depends on the cache line replacement policy. It will always work with LRU, for example, and probably everything else that exists. But it is not guaranteed, is it?

LFU, if used, wouldn't be flushed by this trick... Potentially, you could have a slice of kernel interrupt handler sitting in a cache line, having been accessed $BIG_NUMBER times... (Does anything actually use this approach, though???)

James.

#24 lore raw
In reply to David Woodhouse

In article <[email protected]>,

Quoted 7 lines · Chris Wedgwood

On Mon, Jun 04, 2001 at 07:03:01PM -0700, David S. Miller wrote:

The x86 doesn't have dumb caches, therefore it really doesn't need to flush anything. Maybe a mb(), but that is it.

What if the memory is erased underneath the CPU being aware of this? In such a way ig generates to bus traffic...

Doing bank switching etc is outside the scope of the current DMA cache flush macros - they are there only for "sane" cache coherency issues, not to be used as generic "we have to flush the cache because we went behind the back of the CPU and switched a bank of memory around".

You will have to come up with some new primitive for this.

The x86 has the "wbinval" instruction, although it should be noted that

- it is buggy and will lock up some CPU's. Use with EXTREME CAUTION. Intel set a special field in the MP table for whether wbinval is usable or not, and you can probably find their errata on which CPU's it doesn't work on (I think it was some early PPro steppings).

When wbinval doesn't work, there's another strategy to flush the cache, but I forget what it was. It was something ridiculous like reading in a few megabytes of memory from consecutive physical addresses to make sure that the cache has been replaced.

- even when it works, it is necessarily very very very slow. Not to be used lightly. As you can imagine, the work-around is even slower.

On the whole, I would suggest avoiding this like the plague, and just marking such memory to be non-cacheable, regardless of whether there is a performance impact or not. If you mark it write-combining and speculative, it's going to perform a bit better.

Linus

#25 lore raw
Quoted 4 lines

- it is buggy and will lock up some CPU's. Use with EXTREME CAUTION. Intel set a special field in the MP table for whether wbinval is usable or not, and you can probably find their errata on which CPU's it doesn't work on (I think it was some early PPro steppings).

Also some intel chipsets it didnt work with (notably earlier PCI ones) - indeed that seems to be the cause of the 'bzImage wont boot on XYZ 486 tosh laptop' bug.

Quoted 4 lines

On the whole, I would suggest avoiding this like the plague, and just marking such memory to be non-cacheable, regardless of whether there is a performance impact or not. If you mark it write-combining and speculative, it's going to perform a bit better.

Or memcpy the blocks into the block or page cache when you need them.

#26 lore raw
In reply to Linus Torvalds
Quoted 2 lines · Linus Torvalds

- even when it works, it is necessarily very very very slow. Not to be used lightly. As you can imagine, the work-around is even slower.

i've measured it once, IIRC it was around 10-15 millisecs on normal pentiums, so while it's indeed the slowest x86 instruction on the planet, it's still perhaps acceptable for hot-swapping ECC RAM.

Ingo

#27 lore raw
In reply to Linus Torvalds
Quoted 6 lines · Ingo Molnar
Quoted 2 lines

- even when it works, it is necessarily very very very slow. Not to be used lightly. As you can imagine, the work-around is even slower.

i've measured it once, IIRC it was around 10-15 millisecs on normal pentiums, so while it's indeed the slowest x86 instruction on the planet, it's still perhaps acceptable for hot-swapping ECC RAM.

I can already hear the realtime crowd bitch ...

Ralf

#28 lore raw
In reply to David Woodhouse
Quoted 8 lines · David Woodhouse

The flash mapping driver arch/cris/drivers/axisflashmap.c uses a cached mapping of the flash chips for bulk reads, but obviously an uncached mapping for sending commands and reading status when we're actually writing to or erasing parts of the chip.

However, it fails to flush the dcache for the range used when the flash is accessed through the uncached mapping. So after an erase or write, we may read old data from the cache for the changed area.

I'll start by saying that axisflashmap.c was not meant to be used by any other archs, that's why it's in arch/cris. But if anyone find it useful, that's great. Just be aware that it's not _designed_ for general use and something like this might be just what that might mean.

CRIS is cache coherent just like the x86 cache and does not need any explicit cache flushes for the write case. Even when doing cache bypass writing, if a cacheline already exist with the referenced memory, the cacheline is updated.

In the erase case though, yes there should be a flush. However during the 1-2 seconds it takes to erase a sector, you can with very high certainity guarantee that the direct-mapped unified 8 kB cache on the CRIS is flushed from any flash references at all.. I mean, it's one-way associative, during 1-2 seconds it executes potentially 200 million instructions. So we haven't really bothered to think about the problem..

For other CPU's it might be more dangerous, although I don't hold my breath.. 1-2 seconds is a long time when talking about L1 caches.

Quoted 4 lines

However, I can't see a cache operation which performs this function. flush_dcache_page() is defined as a NOP on CRIS as, it seems, it is on most architectures. On other architectures, there's dma_cache_wback_inv(), but that also seems to be a NOP on i386, to pick a random example.

I'd agree that to be really certain, a "flush_dcache()" function should be implemented and used when an erase finishes. Like David Miller wrote somewhere in the thread, one way is to use your knowledge of the arch's cache and do suitable dummy accesses to flush it, if there is no explicit command to do it. But that's just up to the arch coders..

-bw

#29 lore raw
Quoted 7 lines · Bjorn Wesen

I'd agree that to be really certain, a "flush_dcache()" function should be implemented and used when an erase finishes. Like David Miller wrote somewhere in the thread, one way is to use your knowledge of the arch's cache and do suitable dummy accesses to flush it, if there is no explicit command to do it. But that's just up to the arch coders..

Here's a stupid question: Are there any processors out there that have a cache but no explicit cache-flush command?

If not (i.e. no such "funny" processors), then what's wrong with the arch dependent include through a define to execute the
arch specific asm command?

The only issue (besides knowing the cache size at run time) that I can think about the "dummy" eviction scheme is that you now need to xfer potentially 3 times the cache
size data to and from memory:

#1. The dummy read
#2. The eviction of the entire cache data being evicted
#3. The refilling of the cache with good data again, as the dummy data cannot really represent anything useful.

Is my thinking here completely non coherent with others? ;)

Vipin

#30 lore raw
In reply to Bjorn Wesen

On Tue, Jun 05, 2001 at 09:22:13AM -0500, Vipin Malik wrote:

Here's a stupid question: Are there any processors out there that have a cache but no explicit cache-flush command?

Yes, and as Linus pointed out, some with the ability are broken anyhow.

--cw

#31 lore raw
In reply to David Woodhouse

On Tue, Jun 05, 2001 at 11:17:48AM +0200, Bjorn Wesen wrote:

In the erase case though, yes there should be a flush. However during the 1-2 seconds it takes to erase a sector, you can with very high certainity guarantee that the direct-mapped unified 8 kB cache on the CRIS is flushed from any flash references at all.. I mean, it's one-way as\sociative, during 1-2 seconds it executes potentially 200 million instructions. So we haven't really bothered to think about the problem..

For other CPU's it might be more dangerous, although I don't hold my breath.. 1-2 seconds is a long time when talking about L1 caches.

I don't know about the CRIS (never heard of it, what is it?), but on an Athlon when benchmarking stuff, I could still see L1 cache hits from data that was 15 seconds old under certain work-loads (obviously not gcc!). Does anyone know how old something may exisit in cache before being written back to RAM?

Even though you potentially execute millions of instructions, they are often the same ones over and over when the machine is near idle.

--cw

#32 lore raw
In reply to David Woodhouse
Quoted 5 lines · Chris Wedgwood

I don't know about the CRIS (never heard of it, what is it?), but on an Athlon when benchmarking stuff, I could still see L1 cache hits from data that was 15 seconds old under certain work-loads (obviously not gcc!). Does anyone know how old something may exisit in cache before being written back to RAM?

I know of no architecture that has a time limit that after which's expire caches get written back to memory. In other words cache lines may stay dirty for an indefinate time if things are just right.

Ralf

#33 lore raw
In reply to David Woodhouse
Quoted 1 line · Chris Wedgwood

I don't know about the CRIS (never heard of it, what is it?)

I wondered about that too. From Documentation/cris:

What is CRIS ?
--------------
CRIS is an acronym for 'Code Reduced Instruction Set'. It is the CPU architecture in Axis Communication AB's range of embeddedn etwork CPU's, called ETRAX. The latest CPU is called

ETRAX 100LX, where LX stands for 'Linux' because the chip was designed to be a good host for the Linux operating system.

Interesting, huh?

--
Daniel