All of lore.kernel.org
 help / color / mirror / Atom feed
* Strange, strange occurence
@ 2004-07-09 18:50 S C
  2004-07-10  7:33 ` Niels Sterrenburg
  2004-07-10 10:04 ` Ralf Baechle
  0 siblings, 2 replies; 28+ messages in thread
From: S C @ 2004-07-09 18:50 UTC (permalink / raw)
  To: linux-mips

Well I'm hoping it isn't so strange to some of you folks and you'll be able 
to tell what's going on :)

Here's my problem:

Using MontaVista Linux 3.1 on a Toshiba RBTx4938 board. Using YAMON, when I 
download the kernel via the debug ethernet port it runs fine. If I download 
the kernel via the Tx4938 inbuilt ethernet controller, it crashes!

Memory checksumming and a quick manual memory dump inspection reveals that 
the kernel download went perfectly ok, and the image is completely and 
correctly downloaded to RAM.

The crash is occuring inside the function r4k_flush_icache_range().

I tried 'flush -i' and 'flush -d' on YAMON after the download but before the 
'go', but that didn't help. I also tried completely disabling caches and 
loading/running uncached, but it gave the same error.

Now, the final twist! Using an ICE, I set a breakpoint at the 
r4k_flush_icache_range function. Then I loaded the kernel as usual, ran it 
with the ICE, stepped through a few instructions inside the 
r4k_flush_icache_range function and then did a 'cont'. The kernel now booted 
fine!

If I don't set the breakpoint inside that function though, and just try to 
run with the ICE the same
error (Inst fetch/Load error) occurs.

I'm at a loss trying to figure out what's going on. I suspect it has 
something to do with caches perhaps (duh!), but have no clue what!  Anybody 
out there face a similar kind of a situation before?

Thanks in advance for any help offered.

Regards,
-Steve

_________________________________________________________________
MSN 9 Dial-up Internet Access helps fight spam and pop-ups – now 2 months 
FREE! http://join.msn.click-url.com/go/onm00200361ave/direct/01/

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-09 18:50 S C
@ 2004-07-10  7:33 ` Niels Sterrenburg
  2004-07-10 10:04 ` Ralf Baechle
  1 sibling, 0 replies; 28+ messages in thread
From: Niels Sterrenburg @ 2004-07-10  7:33 UTC (permalink / raw)
  To: S C; +Cc: linux-mips

Hi Steve,

When you set a breakpoint with the ice and step through,
for each step the ICE set's a breakpoint on the next instruction:
e.g.:
- modifies next instruction in memory (via CPU !!!)
  with a breakpoint instruction,
- and update the cache so that the breakpoint instruction is really in
memory and that i-cache is invalid.
(or something like that)

So indead you have a cache problem which is explanable solved/disapeared
by steppig through with the ICE.

Maybe a stupid question from me but why flushing an icache ?:
r4k_flush_icache_range

regards,

Niels

> Well I'm hoping it isn't so strange to some of you folks and you'll be
> able
> to tell what's going on :)
>
> Here's my problem:
>
> Using MontaVista Linux 3.1 on a Toshiba RBTx4938 board. Using YAMON, when
> I
> download the kernel via the debug ethernet port it runs fine. If I
> download
> the kernel via the Tx4938 inbuilt ethernet controller, it crashes!
>
> Memory checksumming and a quick manual memory dump inspection reveals that
> the kernel download went perfectly ok, and the image is completely and
> correctly downloaded to RAM.
>
> The crash is occuring inside the function r4k_flush_icache_range().
>
> I tried 'flush -i' and 'flush -d' on YAMON after the download but before
> the
> 'go', but that didn't help. I also tried completely disabling caches and
> loading/running uncached, but it gave the same error.
>
> Now, the final twist! Using an ICE, I set a breakpoint at the
> r4k_flush_icache_range function. Then I loaded the kernel as usual, ran it
> with the ICE, stepped through a few instructions inside the
> r4k_flush_icache_range function and then did a 'cont'. The kernel now
> booted
> fine!
>
> If I don't set the breakpoint inside that function though, and just try to
> run with the ICE the same
> error (Inst fetch/Load error) occurs.
>
> I'm at a loss trying to figure out what's going on. I suspect it has
> something to do with caches perhaps (duh!), but have no clue what!
> Anybody
> out there face a similar kind of a situation before?
>
> Thanks in advance for any help offered.
>
> Regards,
> -Steve
>
> _________________________________________________________________
> MSN 9 Dial-up Internet Access helps fight spam and pop-ups – now 2 months
> FREE! http://join.msn.click-url.com/go/onm00200361ave/direct/01/
>
>
>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-09 18:50 S C
  2004-07-10  7:33 ` Niels Sterrenburg
@ 2004-07-10 10:04 ` Ralf Baechle
  2004-07-12 15:16     ` Kevin D. Kissell
  1 sibling, 1 reply; 28+ messages in thread
From: Ralf Baechle @ 2004-07-10 10:04 UTC (permalink / raw)
  To: S C; +Cc: linux-mips

On Fri, Jul 09, 2004 at 06:50:00PM +0000, S C wrote:

> Using MontaVista Linux 3.1 on a Toshiba RBTx4938 board. Using YAMON, when I 
> download the kernel via the debug ethernet port it runs fine. If I download 
> the kernel via the Tx4938 inbuilt ethernet controller, it crashes!

If you're using a Montavista kernel you should report to Montavista.  We
don't have the source so any comment here is speculation.

> The crash is occuring inside the function r4k_flush_icache_range().
> 
> I tried 'flush -i' and 'flush -d' on YAMON after the download but before 
> the 'go', but that didn't help. I also tried completely disabling caches 
> and loading/running uncached, but it gave the same error.
> 
> Now, the final twist! Using an ICE, I set a breakpoint at the 
> r4k_flush_icache_range function. Then I loaded the kernel as usual, ran it 
> with the ICE, stepped through a few instructions inside the 
> r4k_flush_icache_range function and then did a 'cont'. The kernel now 
> booted fine!

As already pointed out by the other poster Niels Sterrenburg using a
debugger unavoidably changes the state of the system to be debugged.

For at least some of the TX49xx processors there is a problem under certain
circumstances if a flush of an I-cache line flushes that cache instruction
itself.  Make sure you're not getting hit by that one.

  Ralf

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-12 15:16     ` Kevin D. Kissell
  0 siblings, 0 replies; 28+ messages in thread
From: Kevin D. Kissell @ 2004-07-12 15:16 UTC (permalink / raw)
  To: Ralf Baechle, S C; +Cc: linux-mips

[snip]
> > The crash is occuring inside the function r4k_flush_icache_range().
> > 
> > I tried 'flush -i' and 'flush -d' on YAMON after the download but before 
> > the 'go', but that didn't help. I also tried completely disabling caches 
> > and loading/running uncached, but it gave the same error.
> > 
> > Now, the final twist! Using an ICE, I set a breakpoint at the 
> > r4k_flush_icache_range function. Then I loaded the kernel as usual, ran it 
> > with the ICE, stepped through a few instructions inside the 
> > r4k_flush_icache_range function and then did a 'cont'. The kernel now 
> > booted fine!
> 
> As already pointed out by the other poster Niels Sterrenburg using a
> debugger unavoidably changes the state of the system to be debugged.
> 
> For at least some of the TX49xx processors there is a problem under certain
> circumstances if a flush of an I-cache line flushes that cache instruction
> itself.  Make sure you're not getting hit by that one.

It's not just the TX49xx series.  While many MIPS-compatible processors 
do handle the special case of flushing the active CACHE instruction itself, 
not all of them do, and the MIPS32 spec calls it out as having an "UNPREDICTABLE"
result.

A truly safe and general I-cache flush routine should itself run uncached,
but a cursory glance at the linux-mips.org sources makes me think
that we do not take that precaution by default - the flush_icache_range
pointer looks to be set to the address of r4k_flush_icache_range()
function, rather than its (uncacheable) alias in kseg1.  Is this something
that's fixed in a linker script, or are we just living dangerously?

            Regards,

            Kevin K.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-12 15:16     ` Kevin D. Kissell
  0 siblings, 0 replies; 28+ messages in thread
From: Kevin D. Kissell @ 2004-07-12 15:16 UTC (permalink / raw)
  To: Ralf Baechle, S C; +Cc: linux-mips

[snip]
> > The crash is occuring inside the function r4k_flush_icache_range().
> > 
> > I tried 'flush -i' and 'flush -d' on YAMON after the download but before 
> > the 'go', but that didn't help. I also tried completely disabling caches 
> > and loading/running uncached, but it gave the same error.
> > 
> > Now, the final twist! Using an ICE, I set a breakpoint at the 
> > r4k_flush_icache_range function. Then I loaded the kernel as usual, ran it 
> > with the ICE, stepped through a few instructions inside the 
> > r4k_flush_icache_range function and then did a 'cont'. The kernel now 
> > booted fine!
> 
> As already pointed out by the other poster Niels Sterrenburg using a
> debugger unavoidably changes the state of the system to be debugged.
> 
> For at least some of the TX49xx processors there is a problem under certain
> circumstances if a flush of an I-cache line flushes that cache instruction
> itself.  Make sure you're not getting hit by that one.

It's not just the TX49xx series.  While many MIPS-compatible processors 
do handle the special case of flushing the active CACHE instruction itself, 
not all of them do, and the MIPS32 spec calls it out as having an "UNPREDICTABLE"
result.

A truly safe and general I-cache flush routine should itself run uncached,
but a cursory glance at the linux-mips.org sources makes me think
that we do not take that precaution by default - the flush_icache_range
pointer looks to be set to the address of r4k_flush_icache_range()
function, rather than its (uncacheable) alias in kseg1.  Is this something
that's fixed in a linker script, or are we just living dangerously?

            Regards,

            Kevin K.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-12 20:49 S C
  0 siblings, 0 replies; 28+ messages in thread
From: S C @ 2004-07-12 20:49 UTC (permalink / raw)
  To: ralf; +Cc: linux-mips

Hi Niels, Ralf, Kevin

Thanks for responding to my query! For the moment, I have fixed the 
symptoms, but still don't know what the problem is (it could be what you 
guys suspect it to be). The r4k_flush_icache_range() was being called from 
inside r4k_tlb_init() and the range being specified was KSEG0 to KSEG0 + 
0x80, i.e. the TLB handler. I commented out the call to 
r4k_flush_icache_range and now the kernel seems to boot normally! But I 
suspect I have not fixed a problem, merely sidestepped it.

So now maybe I should repeat the question Niels asked: why was that call 
necessary?

Thanks again,
-Steve.




>From: Ralf Baechle <ralf@linux-mips.org>
>To: S C <theansweriz42@hotmail.com>
>CC: linux-mips@linux-mips.org
>Subject: Re: Strange, strange occurence
>Date: Sat, 10 Jul 2004 12:04:12 +0200
>
>On Fri, Jul 09, 2004 at 06:50:00PM +0000, S C wrote:
>
> > Using MontaVista Linux 3.1 on a Toshiba RBTx4938 board. Using YAMON, 
>when I
> > download the kernel via the debug ethernet port it runs fine. If I 
>download
> > the kernel via the Tx4938 inbuilt ethernet controller, it crashes!
>
>If you're using a Montavista kernel you should report to Montavista.  We
>don't have the source so any comment here is speculation.
>
> > The crash is occuring inside the function r4k_flush_icache_range().
> >
> > I tried 'flush -i' and 'flush -d' on YAMON after the download but before
> > the 'go', but that didn't help. I also tried completely disabling caches
> > and loading/running uncached, but it gave the same error.
> >
> > Now, the final twist! Using an ICE, I set a breakpoint at the
> > r4k_flush_icache_range function. Then I loaded the kernel as usual, ran 
>it
> > with the ICE, stepped through a few instructions inside the
> > r4k_flush_icache_range function and then did a 'cont'. The kernel now
> > booted fine!
>
>As already pointed out by the other poster Niels Sterrenburg using a
>debugger unavoidably changes the state of the system to be debugged.
>
>For at least some of the TX49xx processors there is a problem under certain
>circumstances if a flush of an I-cache line flushes that cache instruction
>itself.  Make sure you're not getting hit by that one.
>
>   Ralf

_________________________________________________________________
FREE pop-up blocking with the new MSN Toolbar – get it now! 
http://toolbar.msn.click-url.com/go/onm00200415ave/direct/01/

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-12 21:23 S C
  2004-07-12 21:48   ` Kevin D. Kissell
  2004-07-12 23:00 ` Ralf Baechle
  0 siblings, 2 replies; 28+ messages in thread
From: S C @ 2004-07-12 21:23 UTC (permalink / raw)
  To: ralf; +Cc: linux-mips

And thinking about it a little more, I might as well clarfy my understanding 
while we're on the topic.

Here's a code snippet from r4k_tlb_init() in arch/mips/mm/c-r4k.c

memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
flush_icache_range(KSEG0, KSEG0 + 0x80);

So my understanding is that the TLB exception handler is being copied to the 
right memory location, and just in case some other TLB exception handler 
(YAMON's presumably) is residing in I-cache, to flush ( hit invalidate) it. 
Is this correct?

Shouldn't there be code to writeback_invalidate the exception handler from 
the data cache ? Presumably the memcpy causes the TLB handler to lodge 
itself in the D cache till it is moved to RAM (either explicitly or when 
some other lines replace the cache lines where the handler is), right?

Thanks in advance for helping me understand the issue here.

Regards,
-Steve.





>From: Ralf Baechle <ralf@linux-mips.org>
>To: S C <theansweriz42@hotmail.com>
>CC: linux-mips@linux-mips.org
>Subject: Re: Strange, strange occurence
>Date: Sat, 10 Jul 2004 12:04:12 +0200
>
>On Fri, Jul 09, 2004 at 06:50:00PM +0000, S C wrote:
>
> > Using MontaVista Linux 3.1 on a Toshiba RBTx4938 board. Using YAMON, 
>when I
> > download the kernel via the debug ethernet port it runs fine. If I 
>download
> > the kernel via the Tx4938 inbuilt ethernet controller, it crashes!
>
>If you're using a Montavista kernel you should report to Montavista.  We
>don't have the source so any comment here is speculation.
>
> > The crash is occuring inside the function r4k_flush_icache_range().
> >
> > I tried 'flush -i' and 'flush -d' on YAMON after the download but before
> > the 'go', but that didn't help. I also tried completely disabling caches
> > and loading/running uncached, but it gave the same error.
> >
> > Now, the final twist! Using an ICE, I set a breakpoint at the
> > r4k_flush_icache_range function. Then I loaded the kernel as usual, ran 
>it
> > with the ICE, stepped through a few instructions inside the
> > r4k_flush_icache_range function and then did a 'cont'. The kernel now
> > booted fine!
>
>As already pointed out by the other poster Niels Sterrenburg using a
>debugger unavoidably changes the state of the system to be debugged.
>
>For at least some of the TX49xx processors there is a problem under certain
>circumstances if a flush of an I-cache line flushes that cache instruction
>itself.  Make sure you're not getting hit by that one.
>
>   Ralf

_________________________________________________________________
Check out the latest news, polls and tools in the MSN 2004 Election Guide! 
http://special.msn.com/msn/election2004.armx

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-12 21:48   ` Kevin D. Kissell
  0 siblings, 0 replies; 28+ messages in thread
From: Kevin D. Kissell @ 2004-07-12 21:48 UTC (permalink / raw)
  To: S C, Ralf Baechle; +Cc: linux-mips

> And thinking about it a little more, I might as well clarfy my understanding 
> while we're on the topic.
> 
> Here's a code snippet from r4k_tlb_init() in arch/mips/mm/c-r4k.c
> 
> memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
> flush_icache_range(KSEG0, KSEG0 + 0x80);
> 
> So my understanding is that the TLB exception handler is being copied to the 
> right memory location, and just in case some other TLB exception handler 
> (YAMON's presumably) is residing in I-cache, to flush ( hit invalidate) it. 
> Is this correct?
> 
> Shouldn't there be code to writeback_invalidate the exception handler from 
> the data cache ? Presumably the memcpy causes the TLB handler to lodge 
> itself in the D cache till it is moved to RAM (either explicitly or when 
> some other lines replace the cache lines where the handler is), right?
> 
> Thanks in advance for helping me understand the issue here.

Your intuition is correct, and the code in r4k_tlb_init() does look scary.
But at least in the linux-mips CVS tree, flush_icache_range() tests to see
if "cpu_has_ic_fills_f_dc" (CPU has Icache fills from Dcache, I presume)
is set, and if it isn't, it pushes the specified range out of the Dcache before
flushing the Icache.  I would speculate that either your c-r4k.c is out of
sync with yout tlb-r4k.c, or you erroneously have cpu_has_ic_fills_f_dc
set.

            Regards,

            Kevin K.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-12 21:48   ` Kevin D. Kissell
  0 siblings, 0 replies; 28+ messages in thread
From: Kevin D. Kissell @ 2004-07-12 21:48 UTC (permalink / raw)
  To: S C, Ralf Baechle; +Cc: linux-mips

> And thinking about it a little more, I might as well clarfy my understanding 
> while we're on the topic.
> 
> Here's a code snippet from r4k_tlb_init() in arch/mips/mm/c-r4k.c
> 
> memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
> flush_icache_range(KSEG0, KSEG0 + 0x80);
> 
> So my understanding is that the TLB exception handler is being copied to the 
> right memory location, and just in case some other TLB exception handler 
> (YAMON's presumably) is residing in I-cache, to flush ( hit invalidate) it. 
> Is this correct?
> 
> Shouldn't there be code to writeback_invalidate the exception handler from 
> the data cache ? Presumably the memcpy causes the TLB handler to lodge 
> itself in the D cache till it is moved to RAM (either explicitly or when 
> some other lines replace the cache lines where the handler is), right?
> 
> Thanks in advance for helping me understand the issue here.

Your intuition is correct, and the code in r4k_tlb_init() does look scary.
But at least in the linux-mips CVS tree, flush_icache_range() tests to see
if "cpu_has_ic_fills_f_dc" (CPU has Icache fills from Dcache, I presume)
is set, and if it isn't, it pushes the specified range out of the Dcache before
flushing the Icache.  I would speculate that either your c-r4k.c is out of
sync with yout tlb-r4k.c, or you erroneously have cpu_has_ic_fills_f_dc
set.

            Regards,

            Kevin K.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-12 22:25     ` Kevin D. Kissell
  0 siblings, 0 replies; 28+ messages in thread
From: Kevin D. Kissell @ 2004-07-12 22:25 UTC (permalink / raw)
  To: Kevin D. Kissell, S C, Ralf Baechle; +Cc: linux-mips

> Your intuition is correct, and the code in r4k_tlb_init() does look scary.
> But at least in the linux-mips CVS tree, flush_icache_range() tests to see
> if "cpu_has_ic_fills_f_dc" (CPU has Icache fills from Dcache, I presume)
> is set, and if it isn't, it pushes the specified range out of the Dcache before
> flushing the Icache.  I would speculate that either your c-r4k.c is out of
> sync with yout tlb-r4k.c, or you erroneously have cpu_has_ic_fills_f_dc
> set.

Hmm.  On closer examination, there *is* a bug in the current r4k_flush_icache_range(),
in that it computes its cache flush loop for the I-cache based on the D-cache line size.
Those line sizes are *usually* the same.  By any chance are they different for the
TX49 family?  If the icache line is longer than the dcache line, there should be no
functional problem, just some wasted cycles.  But if the dcache line were, say, 
twice the length of the Icache line, only half of the icache lines would be invalidated...

            Regards,

            Kevin K.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-12 22:25     ` Kevin D. Kissell
  0 siblings, 0 replies; 28+ messages in thread
From: Kevin D. Kissell @ 2004-07-12 22:25 UTC (permalink / raw)
  To: Kevin D. Kissell, S C, Ralf Baechle; +Cc: linux-mips

> Your intuition is correct, and the code in r4k_tlb_init() does look scary.
> But at least in the linux-mips CVS tree, flush_icache_range() tests to see
> if "cpu_has_ic_fills_f_dc" (CPU has Icache fills from Dcache, I presume)
> is set, and if it isn't, it pushes the specified range out of the Dcache before
> flushing the Icache.  I would speculate that either your c-r4k.c is out of
> sync with yout tlb-r4k.c, or you erroneously have cpu_has_ic_fills_f_dc
> set.

Hmm.  On closer examination, there *is* a bug in the current r4k_flush_icache_range(),
in that it computes its cache flush loop for the I-cache based on the D-cache line size.
Those line sizes are *usually* the same.  By any chance are they different for the
TX49 family?  If the icache line is longer than the dcache line, there should be no
functional problem, just some wasted cycles.  But if the dcache line were, say, 
twice the length of the Icache line, only half of the icache lines would be invalidated...

            Regards,

            Kevin K.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-12 21:23 Strange, strange occurence S C
  2004-07-12 21:48   ` Kevin D. Kissell
@ 2004-07-12 23:00 ` Ralf Baechle
  1 sibling, 0 replies; 28+ messages in thread
From: Ralf Baechle @ 2004-07-12 23:00 UTC (permalink / raw)
  To: S C; +Cc: linux-mips

On Mon, Jul 12, 2004 at 09:23:20PM +0000, S C wrote:

> And thinking about it a little more, I might as well clarfy my 
> understanding while we're on the topic.
> 
> Here's a code snippet from r4k_tlb_init() in arch/mips/mm/c-r4k.c
> 
> memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
> flush_icache_range(KSEG0, KSEG0 + 0x80);
> 
> So my understanding is that the TLB exception handler is being copied to 
> the right memory location, and just in case some other TLB exception 
> handler (YAMON's presumably) is residing in I-cache, to flush ( hit 
> invalidate) it. Is this correct?
> 
> Shouldn't there be code to writeback_invalidate the exception handler from 
> the data cache ?

flush_icache_range() does that where necessary.

> Presumably the memcpy causes the TLB handler to lodge 
> itself in the D cache till it is moved to RAM

Correct.  All MIPS processors [1] do their primary I-cache refills from
second or third level cache or memory - whatever hits first.  If code
was changed a flush of the data cache is required so the I-cache can
actually fetch the new data and because old stale code might still be
in the I-cache an I-cache flush is also required.

> (either explicitly or when 
> some other lines replace the cache lines where the handler is), right?
> 
> Thanks in advance for helping me understand the issue here.

  Ralf

[1] Exceptions are the R4000/R4400 SC and MC versions in a split S-cache
    configuration where the primary I-cache is refilled from the secondary
    I-cache which mean this flush has to flush the secondary data cache
    back to memory also.  Linux doesn't support this configuration because
    no known system uses it iow it's only a theoretically possible config.

    The second exception are the AMD MIPS32 processors where the I-cache
    is snooping the D-cache and therefore the D-cache flush can is
    unnecessary.

    The third exception are R1x000 in SMP configurations where I-caches
    snoop remote stores so coherency doesn't need any maintenance in
    software at all.  Only the I-cache of the CPU that did modify the code
    needs flushing.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-12 23:10 S C
  0 siblings, 0 replies; 28+ messages in thread
From: S C @ 2004-07-12 23:10 UTC (permalink / raw)
  To: KevinK, ralf; +Cc: linux-mips

Hi Kevin and Ralf,

Thanks for your inputs and suggestions! In the case of the Tx49 family, the 
primary I and D cache lines are both the same size (8 words), so the problem 
you mention below will not arise.

  I didn't think about the meaning of cpu_has_ic_fills_f_dc before writing 
my previous mail, and I see now that my intuition (and your explanation 
helps) was correct.

  For the moment, the problem is fixed. But I'm going to try and get to the 
bottom of this when I have the time.

  Thanks,
-Steve.


>From: "Kevin D. Kissell" <KevinK@mips.com>
>To: "Kevin D. Kissell" <KevinK@mips.com>, "S C" 
><theansweriz42@hotmail.com>,        "Ralf Baechle" <ralf@linux-mips.org>
>CC: <linux-mips@linux-mips.org>
>Subject: Re: Strange, strange occurence
>Date: Tue, 13 Jul 2004 00:25:37 +0200
>
> > Your intuition is correct, and the code in r4k_tlb_init() does look 
>scary.
> > But at least in the linux-mips CVS tree, flush_icache_range() tests to 
>see
> > if "cpu_has_ic_fills_f_dc" (CPU has Icache fills from Dcache, I presume)
> > is set, and if it isn't, it pushes the specified range out of the Dcache 
>before
> > flushing the Icache.  I would speculate that either your c-r4k.c is out 
>of
> > sync with yout tlb-r4k.c, or you erroneously have cpu_has_ic_fills_f_dc
> > set.
>
>Hmm.  On closer examination, there *is* a bug in the current 
>r4k_flush_icache_range(),
>in that it computes its cache flush loop for the I-cache based on the 
>D-cache line size.
>Those line sizes are *usually* the same.  By any chance are they different 
>for the
>TX49 family?  If the icache line is longer than the dcache line, there 
>should be no
>functional problem, just some wasted cycles.  But if the dcache line were, 
>say,
>twice the length of the Icache line, only half of the icache lines would be 
>invalidated...
>
>             Regards,
>
>             Kevin K.
>

_________________________________________________________________
FREE pop-up blocking with the new MSN Toolbar – get it now! 
http://toolbar.msn.click-url.com/go/onm00200415ave/direct/01/

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-12 21:48   ` Kevin D. Kissell
  (?)
  (?)
@ 2004-07-12 23:11   ` Ralf Baechle
  -1 siblings, 0 replies; 28+ messages in thread
From: Ralf Baechle @ 2004-07-12 23:11 UTC (permalink / raw)
  To: Kevin D. Kissell; +Cc: S C, linux-mips

On Mon, Jul 12, 2004 at 11:48:31PM +0200, Kevin D. Kissell wrote:

> Your intuition is correct, and the code in r4k_tlb_init() does look scary.

Not scarry at all.  flush_icache_range() has to do whatever is needed to
maintain I-cache coherency for the range passed in as the argument.  And
I don't think we should really have to deal with all the complicated
details of cache maintenance in a function like r4k_tlb_init().

> But at least in the linux-mips CVS tree, flush_icache_range() tests to see
> if "cpu_has_ic_fills_f_dc" (CPU has Icache fills from Dcache, I presume)

Right.  Cpu_has_ic_fills_f_dc is only non-zero for the AMD processors
where the I-cache is refilled from the D-cache.  For typical kernel
configurations The definition of cpu_has_ic_fills_f_dc is a constant so
the compiler can optimize this further.

  Ralf

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-12 22:25     ` Kevin D. Kissell
  (?)
@ 2004-07-12 23:13     ` Ralf Baechle
  -1 siblings, 0 replies; 28+ messages in thread
From: Ralf Baechle @ 2004-07-12 23:13 UTC (permalink / raw)
  To: Kevin D. Kissell; +Cc: S C, linux-mips

On Tue, Jul 13, 2004 at 12:25:37AM +0200, Kevin D. Kissell wrote:

> Hmm.  On closer examination, there *is* a bug in the current r4k_flush_icache_range(),
> in that it computes its cache flush loop for the I-cache based on the D-cache line size.
> Those line sizes are *usually* the same.  By any chance are they different for the
> TX49 family?  If the icache line is longer than the dcache line, there should be no
> functional problem, just some wasted cycles.  But if the dcache line were, say, 
> twice the length of the Icache line, only half of the icache lines would be invalidated...

Whoops.  Fixing ...

  Ralf

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-12 15:16     ` Kevin D. Kissell
  (?)
@ 2004-07-13  0:33     ` Ralf Baechle
  2004-07-13 15:31         ` Kevin D. Kissell
  2004-07-14 16:35       ` Dominic Sweetman
  -1 siblings, 2 replies; 28+ messages in thread
From: Ralf Baechle @ 2004-07-13  0:33 UTC (permalink / raw)
  To: Kevin D. Kissell; +Cc: S C, linux-mips

On Mon, Jul 12, 2004 at 05:16:31PM +0200, Kevin D. Kissell wrote:

> A truly safe and general I-cache flush routine should itself run uncached,
> but a cursory glance at the linux-mips.org sources makes me think
> that we do not take that precaution by default - the flush_icache_range
> pointer looks to be set to the address of r4k_flush_icache_range()
> function, rather than its (uncacheable) alias in kseg1.  Is this something
> that's fixed in a linker script, or are we just living dangerously?

That's a new restriction in MIPS32 v2.0 and you're right, we're not trying
to deal with it yet except for the TX49xx.

  Ralf

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-13 15:31         ` Kevin D. Kissell
  0 siblings, 0 replies; 28+ messages in thread
From: Kevin D. Kissell @ 2004-07-13 15:31 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: S C, linux-mips

> > A truly safe and general I-cache flush routine should itself run uncached,
> > but a cursory glance at the linux-mips.org sources makes me think
> > that we do not take that precaution by default - the flush_icache_range
> > pointer looks to be set to the address of r4k_flush_icache_range()
> > function, rather than its (uncacheable) alias in kseg1.  Is this something
> > that's fixed in a linker script, or are we just living dangerously?
> 
> That's a new restriction in MIPS32 v2.0 and you're right, we're not trying
> to deal with it yet except for the TX49xx.

I'm pretty sure that restriction is not new to MIPS32 v2.0.  In any
case, there are pre-MIPS32/MIPS64 chips in current mass production
and use, under Linux among other OSes, which specify in their user
manuals that one should not invalidate the Icache line from which one
is currently executing.  The clause about unpredictable behavior in
that case went into the MIPS32 spec because it was known that such
parts existed, and we wanted to make it as easy as possible for such 
designs to be made compliant

Invalidating the entire Icache with a routine executing out of the Icache
is a Bad Idea, and will almost certainly cause problems some of the time
on some MIPS processors.  Reasonable people could disagree on whether
we want to handle that in the generic code, or create a variant icache flush 
routine which gets plugged in only for those parts that really need it.

            Regards,

            Kevin K.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-13 15:31         ` Kevin D. Kissell
  0 siblings, 0 replies; 28+ messages in thread
From: Kevin D. Kissell @ 2004-07-13 15:31 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: S C, linux-mips

> > A truly safe and general I-cache flush routine should itself run uncached,
> > but a cursory glance at the linux-mips.org sources makes me think
> > that we do not take that precaution by default - the flush_icache_range
> > pointer looks to be set to the address of r4k_flush_icache_range()
> > function, rather than its (uncacheable) alias in kseg1.  Is this something
> > that's fixed in a linker script, or are we just living dangerously?
> 
> That's a new restriction in MIPS32 v2.0 and you're right, we're not trying
> to deal with it yet except for the TX49xx.

I'm pretty sure that restriction is not new to MIPS32 v2.0.  In any
case, there are pre-MIPS32/MIPS64 chips in current mass production
and use, under Linux among other OSes, which specify in their user
manuals that one should not invalidate the Icache line from which one
is currently executing.  The clause about unpredictable behavior in
that case went into the MIPS32 spec because it was known that such
parts existed, and we wanted to make it as easy as possible for such 
designs to be made compliant

Invalidating the entire Icache with a routine executing out of the Icache
is a Bad Idea, and will almost certainly cause problems some of the time
on some MIPS processors.  Reasonable people could disagree on whether
we want to handle that in the generic code, or create a variant icache flush 
routine which gets plugged in only for those parts that really need it.

            Regards,

            Kevin K.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-13 15:31         ` Kevin D. Kissell
  (?)
@ 2004-07-14 12:02         ` Maciej W. Rozycki
  -1 siblings, 0 replies; 28+ messages in thread
From: Maciej W. Rozycki @ 2004-07-14 12:02 UTC (permalink / raw)
  To: Kevin D. Kissell; +Cc: Ralf Baechle, S C, linux-mips

On Tue, 13 Jul 2004, Kevin D. Kissell wrote:

> > That's a new restriction in MIPS32 v2.0 and you're right, we're not trying
> > to deal with it yet except for the TX49xx.
> 
> I'm pretty sure that restriction is not new to MIPS32 v2.0.  In any

 The restriction was apparently added in revision 1.00 of the MIPS32
architecture vol.II document.  I don't have that revision -- I have
versions 0.95 and 2.00 only -- without looking at the revision history in
2.00 I'd expect the original MIPS32 spec not to enforce such a
restriction, either.

> case, there are pre-MIPS32/MIPS64 chips in current mass production
> and use, under Linux among other OSes, which specify in their user
> manuals that one should not invalidate the Icache line from which one
> is currently executing.  The clause about unpredictable behavior in
> that case went into the MIPS32 spec because it was known that such
> parts existed, and we wanted to make it as easy as possible for such 
> designs to be made compliant

 Ugh, although I can imagine valid arguments for such a decision.

> Invalidating the entire Icache with a routine executing out of the Icache
> is a Bad Idea, and will almost certainly cause problems some of the time
> on some MIPS processors.  Reasonable people could disagree on whether
> we want to handle that in the generic code, or create a variant icache flush 
> routine which gets plugged in only for those parts that really need it.

 As executing code from an uncached space is terribly slow, there are at
least two points of optimization:

1. The Icache invalidation handler should run cached on processors known
to handle it gracefully.

2. For others, as you suggest, it should attempt to figure out whether its
code may invalidate itself and run uncached then, perhaps for the
problematic lines only.

  Maciej

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-13  0:33     ` Ralf Baechle
  2004-07-13 15:31         ` Kevin D. Kissell
@ 2004-07-14 16:35       ` Dominic Sweetman
  2004-07-14 17:45           ` Michael Uhler
                           ` (3 more replies)
  1 sibling, 4 replies; 28+ messages in thread
From: Dominic Sweetman @ 2004-07-14 16:35 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Kevin D. Kissell, S C, linux-mips


Ralf Baechle (ralf@linux-mips.org) writes:

> > A truly safe and general I-cache flush routine should itself run
> > uncached... 

It depends what you mean by general, and uncached is not the only
option.  The spec says:

 "The operation of the instruction is UNPREDICTABLE if the cache line
  that contains the CACHE instruction is the target of an
  invalidate..." 

If you use hit-type cache operations in a kernel routine, then you're
safe.  I can't envisage any circumstance in which Linux would try to
invalidate kernel mainline code locations from the I-cache (well, you
might be doing something fabulous with debugging the kernel, but
that's not normal and you'd hardly expect to be able to support such
an activity with standard cache management calls).

So this problem can only arise on index-type I-cache invalidation.  I
claim that a running kernel on a MIPS CPU should only use index-type
invalidation when it is necessary to invalidate the entire I-cache.
(If you use index-type operations for a range which doesn't resolve to
"the whole cache" then that should be fixed).

That implies that a MIPS32-paranoid "invalidate-whole-I-cache" routine
should:

1. Identify which indexes might alias to cache lines 
   containing the routines's own 'cache invalidate' instruction(s),
   and thus hit the problem.  There won't be that many of them.

2. Arrange to skip those indexes when zapping the cache, then do
   something weird to invalidate that handful of lines.  You could 
   do that by running uncached, but you could also do it just by using
   some auxiliary routine which is known to be more than a cache line
   but much less than a whole I-cache span distant, so can't possibly
   alias to the same thing...

This is fiddly, but not terribly difficult and should have a
negligible performance impact.

Does that make sense?  Am I now, having named the solution,
responsible for figuring out a patch (yeuch, I never wanted to be a
kernel programmer again...).

--
Dominic Sweetman
MIPS Technologies

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: Strange, strange occurence
@ 2004-07-14 17:45           ` Michael Uhler
  0 siblings, 0 replies; 28+ messages in thread
From: Michael Uhler @ 2004-07-14 17:45 UTC (permalink / raw)
  To: 'Dominic Sweetman', 'Ralf Baechle'
  Cc: 'Kevin D. Kissell', 'S C', linux-mips

Dom's proposed solution is probably the right thing to do.  We've got some
code in MIPS that does exactly this, and I've suggested that we convert this
to provide to the Linux community.

/gmu

---
Michael Uhler, Chief Technology Officer
MIPS Technologies, Inc.   Email: uhler@mips.com
1225 Charleston Road      Voice:  (650)567-5025   FAX:   (650)567-5225
Mountain View, CA 94043   Mobile: (650)868-6870   Admin: (650)567-5085


> -----Original Message-----
> From: linux-mips-bounce@linux-mips.org 
> [mailto:linux-mips-bounce@linux-mips.org] On Behalf Of 
> Dominic Sweetman
> Sent: Wednesday, July 14, 2004 9:35 AM
> To: Ralf Baechle
> Cc: Kevin D. Kissell; S C; linux-mips@linux-mips.org
> Subject: Re: Strange, strange occurence
> 
> 
> 
> Ralf Baechle (ralf@linux-mips.org) writes:
> 
> > > A truly safe and general I-cache flush routine should itself run 
> > > uncached...
> 
> It depends what you mean by general, and uncached is not the 
> only option.  The spec says:
> 
>  "The operation of the instruction is UNPREDICTABLE if the cache line
>   that contains the CACHE instruction is the target of an
>   invalidate..." 
> 
> If you use hit-type cache operations in a kernel routine, 
> then you're safe.  I can't envisage any circumstance in which 
> Linux would try to invalidate kernel mainline code locations 
> from the I-cache (well, you might be doing something fabulous 
> with debugging the kernel, but that's not normal and you'd 
> hardly expect to be able to support such an activity with 
> standard cache management calls).
> 
> So this problem can only arise on index-type I-cache 
> invalidation.  I claim that a running kernel on a MIPS CPU 
> should only use index-type invalidation when it is necessary 
> to invalidate the entire I-cache. (If you use index-type 
> operations for a range which doesn't resolve to "the whole 
> cache" then that should be fixed).
> 
> That implies that a MIPS32-paranoid "invalidate-whole-I-cache" routine
> should:
> 
> 1. Identify which indexes might alias to cache lines 
>    containing the routines's own 'cache invalidate' instruction(s),
>    and thus hit the problem.  There won't be that many of them.
> 
> 2. Arrange to skip those indexes when zapping the cache, then do
>    something weird to invalidate that handful of lines.  You could 
>    do that by running uncached, but you could also do it just by using
>    some auxiliary routine which is known to be more than a cache line
>    but much less than a whole I-cache span distant, so can't possibly
>    alias to the same thing...
> 
> This is fiddly, but not terribly difficult and should have a 
> negligible performance impact.
> 
> Does that make sense?  Am I now, having named the solution, 
> responsible for figuring out a patch (yeuch, I never wanted 
> to be a kernel programmer again...).
> 
> --
> Dominic Sweetman
> MIPS Technologies
> 
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: Strange, strange occurence
@ 2004-07-14 17:45           ` Michael Uhler
  0 siblings, 0 replies; 28+ messages in thread
From: Michael Uhler @ 2004-07-14 17:45 UTC (permalink / raw)
  To: 'Dominic Sweetman', 'Ralf Baechle'
  Cc: 'Kevin D. Kissell', 'S C', linux-mips

Dom's proposed solution is probably the right thing to do.  We've got some
code in MIPS that does exactly this, and I've suggested that we convert this
to provide to the Linux community.

/gmu

---
Michael Uhler, Chief Technology Officer
MIPS Technologies, Inc.   Email: uhler@mips.com
1225 Charleston Road      Voice:  (650)567-5025   FAX:   (650)567-5225
Mountain View, CA 94043   Mobile: (650)868-6870   Admin: (650)567-5085


> -----Original Message-----
> From: linux-mips-bounce@linux-mips.org 
> [mailto:linux-mips-bounce@linux-mips.org] On Behalf Of 
> Dominic Sweetman
> Sent: Wednesday, July 14, 2004 9:35 AM
> To: Ralf Baechle
> Cc: Kevin D. Kissell; S C; linux-mips@linux-mips.org
> Subject: Re: Strange, strange occurence
> 
> 
> 
> Ralf Baechle (ralf@linux-mips.org) writes:
> 
> > > A truly safe and general I-cache flush routine should itself run 
> > > uncached...
> 
> It depends what you mean by general, and uncached is not the 
> only option.  The spec says:
> 
>  "The operation of the instruction is UNPREDICTABLE if the cache line
>   that contains the CACHE instruction is the target of an
>   invalidate..." 
> 
> If you use hit-type cache operations in a kernel routine, 
> then you're safe.  I can't envisage any circumstance in which 
> Linux would try to invalidate kernel mainline code locations 
> from the I-cache (well, you might be doing something fabulous 
> with debugging the kernel, but that's not normal and you'd 
> hardly expect to be able to support such an activity with 
> standard cache management calls).
> 
> So this problem can only arise on index-type I-cache 
> invalidation.  I claim that a running kernel on a MIPS CPU 
> should only use index-type invalidation when it is necessary 
> to invalidate the entire I-cache. (If you use index-type 
> operations for a range which doesn't resolve to "the whole 
> cache" then that should be fixed).
> 
> That implies that a MIPS32-paranoid "invalidate-whole-I-cache" routine
> should:
> 
> 1. Identify which indexes might alias to cache lines 
>    containing the routines's own 'cache invalidate' instruction(s),
>    and thus hit the problem.  There won't be that many of them.
> 
> 2. Arrange to skip those indexes when zapping the cache, then do
>    something weird to invalidate that handful of lines.  You could 
>    do that by running uncached, but you could also do it just by using
>    some auxiliary routine which is known to be more than a cache line
>    but much less than a whole I-cache span distant, so can't possibly
>    alias to the same thing...
> 
> This is fiddly, but not terribly difficult and should have a 
> negligible performance impact.
> 
> Does that make sense?  Am I now, having named the solution, 
> responsible for figuring out a patch (yeuch, I never wanted 
> to be a kernel programmer again...).
> 
> --
> Dominic Sweetman
> MIPS Technologies
> 
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-14 16:35       ` Dominic Sweetman
  2004-07-14 17:45           ` Michael Uhler
@ 2004-07-15  1:34         ` Atsushi Nemoto
  2004-07-15  1:53         ` Ralf Baechle
  2004-07-16 12:24         ` Ralf Baechle
  3 siblings, 0 replies; 28+ messages in thread
From: Atsushi Nemoto @ 2004-07-15  1:34 UTC (permalink / raw)
  To: dom; +Cc: ralf, KevinK, theansweriz42, linux-mips

>>>>> On Wed, 14 Jul 2004 17:35:19 +0100, Dominic Sweetman <dom@mips.com> said:
dom> 2. Arrange to skip those indexes when zapping the cache, then do
dom> something weird to invalidate that handful of lines.  You could
dom> do that by running uncached, but you could also do it just by
dom> using some auxiliary routine which is known to be more than a
dom> cache line but much less than a whole I-cache span distant, so
dom> can't possibly alias to the same thing...

dom> This is fiddly, but not terribly difficult and should have a
dom> negligible performance impact.

Yes.  The cache routines for TX49XX surely do it (2 phase
invalidating).  Please look at tx49_blast_icache32() in c-r4k.c.

---
Atsushi Nemoto

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-14 16:35       ` Dominic Sweetman
  2004-07-14 17:45           ` Michael Uhler
  2004-07-15  1:34         ` Atsushi Nemoto
@ 2004-07-15  1:53         ` Ralf Baechle
  2004-07-16 12:24         ` Ralf Baechle
  3 siblings, 0 replies; 28+ messages in thread
From: Ralf Baechle @ 2004-07-15  1:53 UTC (permalink / raw)
  To: Dominic Sweetman; +Cc: Kevin D. Kissell, S C, linux-mips

On Wed, Jul 14, 2004 at 05:35:19PM +0100, Dominic Sweetman wrote:

> If you use hit-type cache operations in a kernel routine, then you're
> safe.  I can't envisage any circumstance in which Linux would try to
> invalidate kernel mainline code locations from the I-cache (well, you
> might be doing something fabulous with debugging the kernel, but
> that's not normal and you'd hardly expect to be able to support such
> an activity with standard cache management calls).
> 
> So this problem can only arise on index-type I-cache invalidation.  I
> claim that a running kernel on a MIPS CPU should only use index-type
> invalidation when it is necessary to invalidate the entire I-cache.
> (If you use index-type operations for a range which doesn't resolve to
> "the whole cache" then that should be fixed).
> 
> That implies that a MIPS32-paranoid "invalidate-whole-I-cache" routine
> should:
> 
> 1. Identify which indexes might alias to cache lines 
>    containing the routines's own 'cache invalidate' instruction(s),
>    and thus hit the problem.  There won't be that many of them.
> 
> 2. Arrange to skip those indexes when zapping the cache, then do
>    something weird to invalidate that handful of lines.  You could 
>    do that by running uncached, but you could also do it just by using
>    some auxiliary routine which is known to be more than a cache line
>    but much less than a whole I-cache span distant, so can't possibly
>    alias to the same thing...
> 
> This is fiddly, but not terribly difficult and should have a
> negligible performance impact.
> 
> Does that make sense?  Am I now, having named the solution,
> responsible for figuring out a patch (yeuch, I never wanted to be a
> kernel programmer again...).

You don't have to :-)  What became a architectural restriction for MIPS32
did already show up earlier as an erratum for the TX49/H2 core.  This is
the solution which we currently have in the kernel code:

#define JUMP_TO_ALIGN(order) \
	__asm__ __volatile__( \
		"b\t1f\n\t" \
		".align\t" #order "\n\t" \
		"1:\n\t" \
		)
#define CACHE32_UNROLL32_ALIGN	JUMP_TO_ALIGN(10) /* 32 * 32 = 1024 */
#define CACHE32_UNROLL32_ALIGN2	JUMP_TO_ALIGN(11)

static inline void mips32_blast_icache32(void)
{
	unsigned long start = INDEX_BASE;
	unsigned long end = start + current_cpu_data.icache.waysize;
	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
	unsigned long ws_end = current_cpu_data.icache.ways <<
	                       current_cpu_data.icache.waybit;
	unsigned long ws, addr;

	CACHE32_UNROLL32_ALIGN2;
	/* I'm in even chunk.  blast odd chunks */
	for (ws = 0; ws < ws_end; ws += ws_inc) 
		for (addr = start + 0x400; addr < end; addr += 0x400 * 2) 
			cache32_unroll32(addr|ws,Index_Invalidate_I);
	CACHE32_UNROLL32_ALIGN;
	/* I'm in odd chunk.  blast even chunks */
	for (ws = 0; ws < ws_end; ws += ws_inc) 
		for (addr = start; addr < end; addr += 0x400 * 2) 
			cache32_unroll32(addr|ws,Index_Invalidate_I);
}

All it takes is using this for all MIPS32 / MIPS64 or maybe even all
processors and some tuning of constants to make this suitable for
all possible I-cache configurations.

  Ralf

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-14 16:35       ` Dominic Sweetman
                           ` (2 preceding siblings ...)
  2004-07-15  1:53         ` Ralf Baechle
@ 2004-07-16 12:24         ` Ralf Baechle
  2004-07-16 16:05           ` Atsushi Nemoto
  3 siblings, 1 reply; 28+ messages in thread
From: Ralf Baechle @ 2004-07-16 12:24 UTC (permalink / raw)
  To: Dominic Sweetman; +Cc: Kevin D. Kissell, S C, linux-mips

On Wed, Jul 14, 2004 at 05:35:19PM +0100, Dominic Sweetman wrote:

> This is fiddly, but not terribly difficult and should have a
> negligible performance impact.
> 
> Does that make sense?  Am I now, having named the solution,
> responsible for figuring out a patch (yeuch, I never wanted to be a
> kernel programmer again...).

No and yes - but here is a simpler solution.  Below patch solves the
problem and adds just 32 bytes of code but removes the special case for
TX49/H2 entirely.

  Ralf

 arch/mips/mm/c-r4k.c        |   59 -------------------------------------------- include/asm-mips/r4kcache.h |   18 ++++++++-----
 include/asm-mips/war.h      |   14 ----------
 3 files changed, 13 insertions(+), 78 deletions(-)


Index: arch/mips/mm/c-r4k.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/c-r4k.c,v
retrieving revision 1.88
diff -u -r1.88 c-r4k.c
--- arch/mips/mm/c-r4k.c	16 Jul 2004 12:06:13 -0000	1.88
+++ arch/mips/mm/c-r4k.c	16 Jul 2004 12:17:05 -0000
@@ -96,16 +96,6 @@
 		r4k_blast_dcache = blast_dcache32;
 }
 
-/* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */
-#define JUMP_TO_ALIGN(order) \
-	__asm__ __volatile__( \
-		"b\t1f\n\t" \
-		".align\t" #order "\n\t" \
-		"1:\n\t" \
-		)
-#define CACHE32_UNROLL32_ALIGN	JUMP_TO_ALIGN(10) /* 32 * 32 = 1024 */
-#define CACHE32_UNROLL32_ALIGN2	JUMP_TO_ALIGN(11)
-
 static inline void blast_r4600_v1_icache32(void)
 {
 	unsigned long flags;
@@ -115,27 +105,6 @@
 	local_irq_restore(flags);
 }
 
-static inline void tx49_blast_icache32(void)
-{
-	unsigned long start = INDEX_BASE;
-	unsigned long end = start + current_cpu_data.icache.waysize;
-	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
-	unsigned long ws_end = current_cpu_data.icache.ways <<
-	                       current_cpu_data.icache.waybit;
-	unsigned long ws, addr;
-
-	CACHE32_UNROLL32_ALIGN2;
-	/* I'm in even chunk.  blast odd chunks */
-	for (ws = 0; ws < ws_end; ws += ws_inc) 
-		for (addr = start + 0x400; addr < end; addr += 0x400 * 2) 
-			cache32_unroll32(addr|ws,Index_Invalidate_I);
-	CACHE32_UNROLL32_ALIGN;
-	/* I'm in odd chunk.  blast even chunks */
-	for (ws = 0; ws < ws_end; ws += ws_inc) 
-		for (addr = start; addr < end; addr += 0x400 * 2) 
-			cache32_unroll32(addr|ws,Index_Invalidate_I);
-}
-
 static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page)
 {
 	unsigned long flags;
@@ -145,27 +114,6 @@
 	local_irq_restore(flags);
 }
 
-static inline void tx49_blast_icache32_page_indexed(unsigned long page)
-{
-	unsigned long start = page;
-	unsigned long end = start + PAGE_SIZE;
-	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
-	unsigned long ws_end = current_cpu_data.icache.ways <<
-	                       current_cpu_data.icache.waybit;
-	unsigned long ws, addr;
-
-	CACHE32_UNROLL32_ALIGN2;
-	/* I'm in even chunk.  blast odd chunks */
-	for (ws = 0; ws < ws_end; ws += ws_inc) 
-		for (addr = start + 0x400; addr < end; addr += 0x400 * 2) 
-			cache32_unroll32(addr|ws,Index_Invalidate_I);
-	CACHE32_UNROLL32_ALIGN;
-	/* I'm in odd chunk.  blast even chunks */
-	for (ws = 0; ws < ws_end; ws += ws_inc) 
-		for (addr = start; addr < end; addr += 0x400 * 2) 
-			cache32_unroll32(addr|ws,Index_Invalidate_I);
-}
-
 static void (* r4k_blast_icache_page)(unsigned long addr);
 
 static inline void r4k_blast_icache_page_setup(void)
@@ -190,10 +138,7 @@
 	if (ic_lsize == 16)
 		r4k_blast_icache_page_indexed = blast_icache16_page_indexed;
 	else if (ic_lsize == 32) {
-		if (TX49XX_ICACHE_INDEX_INV_WAR)
-			r4k_blast_icache_page_indexed =
-				tx49_blast_icache32_page_indexed;
-		else if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
+		if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
 			r4k_blast_icache_page_indexed =
 				blast_icache32_r4600_v1_page_indexed;
 		else
@@ -214,8 +159,6 @@
 	else if (ic_lsize == 32) {
 		if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
 			r4k_blast_icache = blast_r4600_v1_icache32;
-		else if (TX49XX_ICACHE_INDEX_INV_WAR)
-			r4k_blast_icache = tx49_blast_icache32;
 		else
 			r4k_blast_icache = blast_icache32;
 	} else if (ic_lsize == 64)
Index: include/asm-mips/r4kcache.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/r4kcache.h,v
retrieving revision 1.22
diff -u -r1.22 r4kcache.h
--- include/asm-mips/r4kcache.h	5 Jan 2004 01:56:01 -0000	1.22
+++ include/asm-mips/r4kcache.h	16 Jul 2004 12:17:05 -0000
@@ -192,7 +192,7 @@
 
 static inline void blast_icache16(void)
 {
-	unsigned long start = INDEX_BASE;
+	unsigned long start = (unsigned long) &&body + 0x100;
 	unsigned long end = start + current_cpu_data.icache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
 	unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -200,8 +200,10 @@
 	unsigned long ws, addr;
 
 	for (ws = 0; ws < ws_end; ws += ws_inc) 
-		for (addr = start; addr < end; addr += 0x200) 
+		for (addr = start; addr < end; addr += 0x200) {
+body:
 			cache16_unroll32(addr|ws,Index_Invalidate_I);
+		}
 }
 
 static inline void blast_icache16_page(unsigned long page)
@@ -335,7 +337,7 @@
 
 static inline void blast_icache32(void)
 {
-	unsigned long start = INDEX_BASE;
+	unsigned long start = (unsigned long) &&body + 0x200;
 	unsigned long end = start + current_cpu_data.icache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
 	unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -343,8 +345,10 @@
 	unsigned long ws, addr;
 
 	for (ws = 0; ws < ws_end; ws += ws_inc) 
-		for (addr = start; addr < end; addr += 0x400) 
+		for (addr = start; addr < end; addr += 0x400)  {
+body:
 			cache32_unroll32(addr|ws,Index_Invalidate_I);
+		}
 }
 
 static inline void blast_icache32_page(unsigned long page)
@@ -439,7 +443,7 @@
 
 static inline void blast_icache64(void)
 {
-	unsigned long start = INDEX_BASE;
+	unsigned long start = (unsigned long) &&body + 0x400;
 	unsigned long end = start + current_cpu_data.icache.waysize;
 	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
 	unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -447,8 +451,10 @@
 	unsigned long ws, addr;
 
 	for (ws = 0; ws < ws_end; ws += ws_inc) 
-		for (addr = start; addr < end; addr += 0x800) 
+		for (addr = start; addr < end; addr += 0x800) {
+body:
 			cache64_unroll32(addr|ws,Index_Invalidate_I);
+		}
 }
 
 static inline void blast_icache64_page(unsigned long page)
Index: include/asm-mips/war.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/war.h,v
retrieving revision 1.18
diff -u -r1.18 war.h
--- include/asm-mips/war.h	5 Mar 2004 02:47:19 -0000	1.18
+++ include/asm-mips/war.h	16 Jul 2004 12:17:05 -0000
@@ -158,17 +158,6 @@
 #endif
 
 /*
- * From TX49/H2 manual: "If the instruction (i.e. CACHE) is issued for
- * the line which this instruction itself exists, the following
- * operation is not guaranteed."
- *
- * Workaround: do two phase flushing for Index_Invalidate_I
- */
-#ifdef CONFIG_CPU_TX49XX
-#define TX49XX_ICACHE_INDEX_INV_WAR 1
-#endif
-
-/*
  * On the RM9000 there is a problem which makes the CreateDirtyExclusive
  * cache operation unusable on SMP systems.
  */
@@ -203,9 +192,6 @@
 #ifndef MIPS_CACHE_SYNC_WAR
 #define MIPS_CACHE_SYNC_WAR		0
 #endif
-#ifndef TX49XX_ICACHE_INDEX_INV_WAR
-#define TX49XX_ICACHE_INDEX_INV_WAR	0
-#endif
 #ifndef RM9000_CDEX_SMP_WAR
 #define RM9000_CDEX_SMP_WAR		0
 #endif

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-16 12:24         ` Ralf Baechle
@ 2004-07-16 16:05           ` Atsushi Nemoto
  0 siblings, 0 replies; 28+ messages in thread
From: Atsushi Nemoto @ 2004-07-16 16:05 UTC (permalink / raw)
  To: ralf; +Cc: dom, KevinK, theansweriz42, linux-mips

>>>>> On Fri, 16 Jul 2004 14:24:09 +0200, Ralf Baechle <ralf@linux-mips.org> said:

ralf> No and yes - but here is a simpler solution.  Below patch solves
ralf> the problem and adds just 32 bytes of code but removes the
ralf> special case for TX49/H2 entirely.

Hmm... Does this patch really solves the problem?

Here is a disassemble list of blast_icache32 (gcc 3.3.3).  The
comments on CACHE instructions are indices of cachelines which the
instruction invalidates.  (for 4 way 16KB cache --- 4KB waysize).

80039ca0 <blast_icache32>:
80039ca0:       3c048038        lui     a0,0x8038
80039ca4:       8c849e2c        lw      a0,-25044(a0)
80039ca8:       3c028038        lui     v0,0x8038
80039cac:       94429e22        lhu     v0,-25054(v0)
80039cb0:       3c038038        lui     v1,0x8038
80039cb4:       8c639e28        lw      v1,-25048(v1)
80039cb8:       00824004        sllv    t0,v0,a0
80039cbc:       24020001        li      v0,1
80039cc0:       3c018004        lui     at,0x8004
80039cc4:       24219ef4        addiu   at,at,-24844	# 80039ef4
80039cc8:       00231821        addu    v1,at,v1
80039ccc:       00823804        sllv    a3,v0,a0
80039cd0:       11000031        beqz    t0,80039d98 <blast_icache32+0xf8>
80039cd4:       00002821        move    a1,zero
80039cd8:       3c028004        lui     v0,0x8004
80039cdc:       24429ef4        addiu   v0,v0,-24844	# 80039ef4
80039ce0:       0043302b        sltu    a2,v0,v1
80039ce4:       3c048004        lui     a0,0x8004
80039ce8:       24849ef4        addiu   a0,a0,-24844	# 80039ef4
80039cec:       50c00027        beqzl   a2,80039d8c <blast_icache32+0xec>
80039cf0:       00a72821        addu    a1,a1,a3
80039cf4:       00851025        or      v0,a0,a1
80039cf8:       bc400000        cache   0x0,0(v0)	# ee0 2e0 6e0 ae0
80039cfc:       bc400020        cache   0x0,32(v0)	# f00 300 700 b00
80039d00:       bc400040        cache   0x0,64(v0)
80039d04:       bc400060        cache   0x0,96(v0)
80039d08:       bc400080        cache   0x0,128(v0)
80039d0c:       bc4000a0        cache   0x0,160(v0)
80039d10:       bc4000c0        cache   0x0,192(v0)
80039d14:       bc4000e0        cache   0x0,224(v0)
80039d18:       bc400100        cache   0x0,256(v0)
80039d1c:       bc400120        cache   0x0,288(v0)	# 000 400 800 c00
80039d20:       bc400140        cache   0x0,320(v0)
80039d24:       bc400160        cache   0x0,352(v0)
80039d28:       bc400180        cache   0x0,384(v0)
80039d2c:       bc4001a0        cache   0x0,416(v0)
80039d30:       bc4001c0        cache   0x0,448(v0)
80039d34:       bc4001e0        cache   0x0,480(v0)
80039d38:       bc400200        cache   0x0,512(v0)
80039d3c:       bc400220        cache   0x0,544(v0)	# 100 500 900 d00
80039d40:       bc400240        cache   0x0,576(v0)	# 120 520 920 d20
80039d44:       bc400260        cache   0x0,608(v0)	# 140 540 940 d40 !!!
80039d48:       bc400280        cache   0x0,640(v0)
80039d4c:       bc4002a0        cache   0x0,672(v0)
80039d50:       bc4002c0        cache   0x0,704(v0)
80039d54:       bc4002e0        cache   0x0,736(v0)
80039d58:       bc400300        cache   0x0,768(v0)
80039d5c:       bc400320        cache   0x0,800(v0)	# 200 600 a00 e00
80039d60:       bc400340        cache   0x0,832(v0)
80039d64:       bc400360        cache   0x0,864(v0)
80039d68:       bc400380        cache   0x0,896(v0)
80039d6c:       bc4003a0        cache   0x0,928(v0)
80039d70:       bc4003c0        cache   0x0,960(v0)
80039d74:       bc4003e0        cache   0x0,992(v0)
80039d78:       24840400        addiu   a0,a0,1024
80039d7c:       0083102b        sltu    v0,a0,v1
80039d80:       1440ffdd        bnez    v0,80039cf8 <blast_icache32+0x58>
80039d84:       00851025        or      v0,a0,a1
80039d88:       00a72821        addu    a1,a1,a3
80039d8c:       00a8102b        sltu    v0,a1,t0
80039d90:       1440ffd4        bnez    v0,80039ce4 <blast_icache32+0x44>
80039d94:       00000000        nop
80039d98:       03e00008        jr      ra
80039d9c:       00000000        nop


The target address of the first CACHE instruction is 0x80039ef4.  It
invalidates index 0xee0 line.  The CACHE instruction on 0x80039d44
invalidates index 0xd40 line which may contains the
instruction... Ouch!!!

I suppose "two-phase invalidating" must be required to solve this
problem.

---
Atsushi Nemoto

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
@ 2004-07-30 21:06 G H
  2004-07-31  5:09 ` Ralf Baechle
  0 siblings, 1 reply; 28+ messages in thread
From: G H @ 2004-07-30 21:06 UTC (permalink / raw)
  To: linux-mips

[-- Attachment #1: Type: text/plain, Size: 1070 bytes --]

Is the suggested patch below going to be added to CVS or is considered too experimental to add ?
 
>No and yes - but here is a simpler solution.  Below patch solves the
>problem and adds just 32 bytes of code but removes the special case for
>TX49/H2 entirely.

>  Ralf

> arch/mips/mm/c-r4k.c        |   59 
>-------------------------------------------- include/asm-mips/r4kcache.h |   18 
>++++++++-----
> include/asm-mips/war.h      |   14 ----------
> 3 files changed, 13 insertions(+), 78 deletions(-)
>
>
>Index: arch/mips/mm/c-r4k.c
>===================================================================
>RCS file: /home/cvs/linux/arch/mips/mm/c-r4k.c,v
>retrieving revision 1.88
>diff -u -r1.88 c-r4k.c
>--- arch/mips/mm/c-r4k.c        16 Jul 2004 12:06:13 -0000      1.88
>+++ arch/mips/mm/c-r4k.c        16 Jul 2004 12:17:05 -0000
>@@ -96,16 +96,6 @@
>                r4k_blast_dcache = blast_dcache32;
> }


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

[-- Attachment #2: Type: text/html, Size: 1521 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Strange, strange occurence
  2004-07-30 21:06 G H
@ 2004-07-31  5:09 ` Ralf Baechle
  0 siblings, 0 replies; 28+ messages in thread
From: Ralf Baechle @ 2004-07-31  5:09 UTC (permalink / raw)
  To: G H; +Cc: linux-mips

On Fri, Jul 30, 2004 at 02:06:39PM -0700, G H wrote:

> Is the suggested patch below going to be added to CVS or is considered too experimental to add ?

No, that patch is simply wrong.

I'll implement a new one but being on a trip through the Silicon Valley
right now that's a little hard to do from here.

  Ralf

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2004-07-31  5:09 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-07-12 21:23 Strange, strange occurence S C
2004-07-12 21:48 ` Kevin D. Kissell
2004-07-12 21:48   ` Kevin D. Kissell
2004-07-12 22:25   ` Kevin D. Kissell
2004-07-12 22:25     ` Kevin D. Kissell
2004-07-12 23:13     ` Ralf Baechle
2004-07-12 23:11   ` Ralf Baechle
2004-07-12 23:00 ` Ralf Baechle
  -- strict thread matches above, loose matches on Subject: below --
2004-07-30 21:06 G H
2004-07-31  5:09 ` Ralf Baechle
2004-07-12 23:10 S C
2004-07-12 20:49 S C
2004-07-09 18:50 S C
2004-07-10  7:33 ` Niels Sterrenburg
2004-07-10 10:04 ` Ralf Baechle
2004-07-12 15:16   ` Kevin D. Kissell
2004-07-12 15:16     ` Kevin D. Kissell
2004-07-13  0:33     ` Ralf Baechle
2004-07-13 15:31       ` Kevin D. Kissell
2004-07-13 15:31         ` Kevin D. Kissell
2004-07-14 12:02         ` Maciej W. Rozycki
2004-07-14 16:35       ` Dominic Sweetman
2004-07-14 17:45         ` Michael Uhler
2004-07-14 17:45           ` Michael Uhler
2004-07-15  1:34         ` Atsushi Nemoto
2004-07-15  1:53         ` Ralf Baechle
2004-07-16 12:24         ` Ralf Baechle
2004-07-16 16:05           ` Atsushi Nemoto

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.