> [I am forwarding this to the list so that someone can correct me, if I am
> writing bullsh*t]
It looks more or less right.
> > What we still can't understand is when we must flush
> > I-cache. Well, we do understand it in theory - I-cache must be
> > flushed when new mapping for a physical page occurs.
There are two operations you can need to do on a cache line. You can
*invalidate* it (so any further access to it will re-fetch it from
memory?); you can do a *writeback* - write it back to memory, if
there's any data the CPU written but which has so far only got stored
in the cache.
The word "flush" is widely used to mean invalidate, and widely used to
mean invalidate and writeback, and probably sometimes used to mean
just writeback. So I'd recommend you don't use that word at all...
> Well, this is true for a R4k but not for a R3000. The R4k (and
> higher) have virtually indexed caches, the R3000 (and R2000) have
> physically indexed caches.
o R2000/3000 = cache on physical addresses, write-through (you never
have to do a writeback on this sort of cache).
o R4000+ primary cache - odd arrangement using virtual addresses to
index the cache, but the physical 'tag' (that's the cache-held field
which holds the physical address so the CPU can check whether the
cache holds the data it wants).
The mix of virtual index and physical tags can lead to the strange
and feared "cache aliases" mentioned by an earlier correspondent;
it's possible to get copies of the same memory location stored in
different cache lines, if that location is being accessed at two
different virtual addresses.
[R4000's designers took the risk because it gave them a higher clock
rate - the cache lookup with the virtual address can now be done
in parallel with address translation. Neat.]
R4000 caches are "write-back" - data written to them does not always
get immediately forwarded to memory, so you sometimes need to do an
explicit writeback operation.
Note that R4000SC secondary caches are physically indexed and
addressed, and you get no aliases there.
> If I understand this right, the only need for cacheflushing would be:
> o DMA, obviously. Here both caches have to be flushed.
When filling memory with DMA, the corresponding regions in both caches
should be invalidated. When taking data from memory with DMA, the
corresponding region in the data cache should first be written-back.
> o Copying code. In this case the D-cache would be up to date, but
> the I-cache doesn't know that code has changed. Here the I-cache has
> to be flushed.
You need to do a D-cache writeback, followed by an I-cache invalidate,
of any cache lines containing the code area you've copied to.
BUT you don't normally need to do anything to MIPS caches when you
change page mappings.
You would only need to do something if your OS deliberately maps pages
so as to risk cache aliases; this is possible on the R4000SC and
R4000MC CPUs, because they use their secondary cache tags to watch for
aliases and report (via an exception) when one tries to happen.
Most OS' avoid cache aliases. This is in fact quite easy. Because
MIPS memory virtual->physical translation is paged in 4K chunks,
address bits 0-11 are the same as physical addresses. An 8K
direct-mapped primary cache only employs address bits up to 12 in its
index; so a particularly *physical* location can only ever appear in
two places in the cache - depending on the value of bit 13 in the
virtual address which currently maps to it.
You can avoid aliases, therefore, by insisting that all the virtual
addresses which map to any particular physical location are the same
modulo 64Kbytes (or any other power of two bigger than the cache
size). Generally, OS' only allocate a second virtual address to data
under unusual circumstances, and the address space is big enough to
stick to such rules.
> > ... because user may wish to execute a code which was formed in a
> > data segment.
Any application using self-modifying code must explicitly D-cache
writeback and I-cache invalidate the code which has been modified or
created. Since cache ops are privileged, that will need a system
call. Simple self-modifying code just doesn't work on MIPS CPUs.