> > But but but...
> > 
> >   do_idle()                 # IRQs on
> >     local_irq_disable();    # IRQs off
> >     defaul_idle_call()      # IRQs off
>       lockdep_hardirqs_on();  # IRQs off, but lockdep things they're on
> >       arch_cpu_idle()               # IRQs off
> >         enabled_wait()      # IRQs off
> >       raw_local_save()      # still off
> >       psw_idle()            # very much off
> >         ext_int_handler     # get an interrupt ?!?!
>             rcu_irq_enter()   # lockdep thinks IRQs are on <- FAIL
> 
> I can't much read s390 assembler, but ext_int_handler() has a
> TRACE_IRQS_OFF, which would be sufficient to re-align the lockdep state
> with the actual state, but there's some condition before it, what's that
> test and is that right?

After digging a bit into our asm code: no, it is not right, and only
for psw_idle() it is wrong.

What happens with the current code:

- default_idle_call() calls lockdep_hardirqs_on() before calling into
  arch_cpu_idle()

- our arch_cpu_idle() calls psw_idle() which enables irqs. the irq
  handler will call/use the SWITCH_ASYNC macro which clears the
  interrupt enabled bits in the old program status word (_only_ for
  psw_idle)

- this again causes the interrupt handler to _not_ call TRACE_IRQS_OFF
  and therefore lockdep thinks interrupts are enabled within the
  interrupt handler

So I guess my patch which I sent yesterday evening should fix all that
mess - plus an explicit trace_hardirqs_off() call in our udelay
implementation is required now.

I'll send a proper patch later.

Reply via email to