linux-mips-fnet
[Top] [All Lists]

RE: mangled status

To: linux-mips@fnet.fr
Subject: RE: mangled status
From: Harald Koerfgen <harald.koerfgen@netcologne.de>
Date: Fri, 06 Nov 1998 20:08:59 +0100 (MET)
In-reply-to: <Pine.LNX.3.96.981105092652.26493C-100000@apt4g.a3nyc.com>
Organization: none
Reply-to: "Harald Koerfgen" <harald.koerfgen@netcologne.de>
Sender: harry@franz.no.dom
Hello all,

long time no see. I barely found time to do some DECstation hacking, so there's 
no
real progess yet. Anyway...

On 05-Nov-98 Thomas Riemer wrote:
> It does indeed appear that something is mangling the status register
> after the series of character writes - Checking the status register
> from the timer later indicates that the Status bit 12 has been turned
> off.  Which would explain why I get no interrupts - unfortunately,
> its not clear what to do about it...
> 
> I have to presume that the problem is something that is happening in
> dz.c.  Any ideas what might cause behavior like this?

There are indeed lots and lots of places in the linux kernel which mess around 
with
the Coprocessor 0 Status Register. Each save_and_cli(flags)/restore(flags) does 
it.

I have been able to let my DS5k/240 output "Stand alon" instead of "Stan" by 
simply
moving the request_irq(...) out of such a save/restore pair. Should be ok 
because
request_irq itself is interrupt safe.

To make things a little bit more complicated, each process has it's own local 
copies
of the CPUs register contents *including* CP0_STATUS (look at r*_resume in
r*_switch.S). That means if there are two processes A and B and A does something
which affects the interrupt mask in CP0_STATUS, like open a device or something 
like that, the switch to process B will turn this interrupt off. The switch to 
process A will turn this interrupt back on as long as A is active.

It's just like Ralf said:

On 19-Oct-98 ralf@uni-koblenz.de wrote:
> On Fri, Oct 16, 1998 at 12:44:45PM +0200, Harald Koerfgen wrote:
> 
>> People, when writing device drivers for DECstations, DO NEVER EVER use code 
>> like:
>> 
>>     save_flags(flags);
>>     [disable or enable interrupts with en/disable_irq(irq)]
>>     restore(flags);
>> 
>> That simply doesn't work and will cause endless headache.
> 
> Which is the proof that the implementation is broken.  Since restore_flags
> is only ever used to restore one single bit, the interrupt enable bit is
> actually the only bit that needs to be restored.  The current implementation
> deliberately ignores this because on the so far supported platforms there
> is no need to deal with this problem which saves a couple of instructions.
> 
> The second possibility to fix this is to modify enable_irq/disable_irq
> such that they don't actually fiddle around with the status register bits
> but either do nothing at all or use an interrupt disable bit in the
> external interrupt source.  The bits in the status register will then be
> set on bootup and will stay unchanged after that.

Unfortunately there are devices in some DECstations which generate interrupts 
which
cannot be turned off by other means than disabling them in CP0_STATUS.

Please correct me if I'm wrong, but as far as I can see, the only way to 
correctly
implement this would be to hack restore_flags() and r*_resume() to restore
CP0_STATUS without touching the interrupt mask. This will definitely add a few
cycles and thus have a negative impact on performance. Yes, Ralf, the R4k code 
will
be affected too to make the R4k DECstations happy.

Anyway, I think I will have some time to burn this weekend and have a look into 
this.

Happy hacking.
---
Regards,
Harald

<Prev in Thread] Current Thread [Next in Thread>