On Sun, 2010-01-24 at 11:45 +0100, Jan Kiszka wrote:
> Philippe Gerum wrote:
> > On Sat, 2010-01-23 at 11:33 +0100, Jan Kiszka wrote:
> >> Philippe Gerum wrote:
> >>> On Sat, 2010-01-23 at 11:09 +0100, Jan Kiszka wrote:
> >>>> Philippe Gerum wrote:
> >>>>> On Fri, 2010-01-22 at 19:08 +0100, Philippe Gerum wrote:
> >>>>>> On Fri, 2010-01-22 at 19:03 +0100, Jan Kiszka wrote:
> >>>>>>> Philippe Gerum wrote:
> >>>>>>>> On Fri, 2010-01-22 at 18:41 +0100, Jan Kiszka wrote:
> >>>>>>>>> Gilles Chanteperdrix wrote:
> >>>>>>>>>> Philippe Gerum wrote:
> >>>>>>>>>>> On Fri, 2010-01-22 at 17:58 +0100, Jan Kiszka wrote: 
> >>>>>>>>>>>> Hi guys,
> >>>>>>>>>>>>
> >>>>>>>>>>>> we are currently trying to catch an ugly Linux pipeline state 
> >>>>>>>>>>>> corruption
> >>>>>>>>>>>> on x86-64.
> >>>>>>>>>>>>
> >>>>>>>>>>>> Conceptual question: If a Xenomai task causes a fault, we enter
> >>>>>>>>>>>> ipipe_trap_notify over the primary domain and leave it over the 
> >>>>>>>>>>>> root
> >>>>>>>>>>>> domain, right? Now, if the root domain happened to be stalled 
> >>>>>>>>>>>> when the
> >>>>>>>>>>>> exception happened, where should it normally be unstalled again,
> >>>>>>>>>>>> *for_that_task*? Our problem is that we generate a code path 
> >>>>>>>>>>>> where this
> >>>>>>>>>>>> does not happen.
> >>>>>>>>>>> xnhadow_relax -> ipipe_reenter_root -> finish_task_switch ->
> >>>>>>>>>>> finish_lock_switch -> unstall
> >>>>>>>>>>>
> >>>>>>>>>>> Since xnshadow_relax is called on behalf the event dispatcher, we 
> >>>>>>>>>>> should
> >>>>>>>>>>> expect it to return with the root domain unstalled after a domain
> >>>>>>>>>>> downgrade, from primary to root.
> >>>>>>>>>> Ok, but what about local_irq_restore_nosync at the end of the 
> >>>>>>>>>> function ?
> >>>>>>>>>>
> >>>>>>>>> That is, IMO, our problem: It replays the root state on fault 
> >>>>>>>>> entry, but
> >>>>>>>>> that one is totally unrelated to the (Xenomai) task that caused the 
> >>>>>>>>> fault.
> >>>>>>>> The code seems fishy. Try restoring only when the incoming domain was
> >>>>>>>> the root one. Indeed.
> >>>>>>>>
> >>>>>>> Something like this?
> >>>>>>>
> >>>>>>> diff --git a/arch/x86/kernel/ipipe.c b/arch/x86/kernel/ipipe.c
> >>>>>>> index 4442d96..0558ea3 100644
> >>>>>>> --- a/arch/x86/kernel/ipipe.c
> >>>>>>> +++ b/arch/x86/kernel/ipipe.c
> >>>>>>> @@ -702,19 +702,21 @@ static int __ipipe_xlate_signo[] = {
> >>>>>>>  
> >>>>>>>  int __ipipe_handle_exception(struct pt_regs *regs, long error_code, 
> >>>>>>> int vector)
> >>>>>>>  {
> >>>>>>> +     bool restore_flags = false;
> >>>>>>>       unsigned long flags;
> >>>>>>>  
> >>>>>>> -     /* Pick up the root domain state of the interrupted context. */
> >>>>>>> -     local_save_flags(flags);
> >>>>>>> +     if (ipipe_root_domain_p && irqs_disabled_hw()) {
> >>>>>>> +             /* Pick up the root domain state of the interrupted 
> >>>>>>> context. */
> >>>>>>> +             local_save_flags(flags);
> >>>>>>>  
> >>>>>>> -     if (ipipe_root_domain_p) {
> >>>>>>>               /*
> >>>>>>>                * Replicate hw interrupt state into the virtual mask 
> >>>>>>> before
> >>>>>>>                * calling the I-pipe event handler over the root 
> >>>>>>> domain. Also
> >>>>>>>                * required later when calling the Linux exception 
> >>>>>>> handler.
> >>>>>>>                */
> >>>>>>> -             if (irqs_disabled_hw())
> >>>>>>> -                     local_irq_disable();
> >>>>>>> +             local_irq_disable();
> >>>>>>> +
> >>>>>>> +             restore_flags = true;
> >>>>>>>       }
> >>>>>>>  #ifdef CONFIG_KGDB
> >>>>>>>       /* catch exception KGDB is interested in over non-root domains 
> >>>>>>> */
> >>>>>>> @@ -725,7 +727,8 @@ int __ipipe_handle_exception(struct pt_regs 
> >>>>>>> *regs, long error_code, int vector)
> >>>>>>>  #endif /* CONFIG_KGDB */
> >>>>>>>  
> >>>>>>>       if (unlikely(ipipe_trap_notify(vector, regs))) {
> >>>>>>> -             local_irq_restore_nosync(flags);
> >>>>>>> +             if (restore_flags)
> >>>>>>> +                     local_irq_restore_nosync(flags);
> >>>>>>>               return 1;
> >>>>>>>       }
> >>>>>>>  
> >>>>>>> @@ -770,7 +773,8 @@ int __ipipe_handle_exception(struct pt_regs 
> >>>>>>> *regs, long error_code, int vector)
> >>>>>>>        * Relevant for 64-bit: Restore root domain state as the 
> >>>>>>> low-level
> >>>>>>>        * return code will not align it to regs.flags.
> >>>>>>>        */
> >>>>>>> -     local_irq_restore_nosync(flags);
> >>>>>>> +     if (restore_flags)
> >>>>>>> +             local_irq_restore_nosync(flags);
> >>>>>>>  
> >>>>>>>       return 0;
> >>>>>>>  }
> >>>>>>>
> >>>>>>>
> >>>>>>> We are currently not able to test this on the system that triggers it,
> >>>>>>> but we'll do so tomorrow (yeah...).
> >>>>>>>
> >>>>>> Should work. Famous last words.
> >>>>>>
> >>>>> Strike that. This won't work, because the fixup code will use the saved
> >>>>> flags even when root is not the incoming domain and/or hw IRQs are on on
> >>>>> entry. In short, local_save_flags() must be done unconditionally, as
> >>>>> previously.
> >>>> It will accidentally work for 64-bit where __fixup_if is empty. And for
> >>>> 32-bit, I would say we need to make it depend on restore_flags as well.
> >>>>
> >>> AFAIK, Gilles is working on this. We just need to avoid stepping on
> >>> 32bit toes to fix 64.
> >>>
> >> OK.
> >>
> >> Just realized that my suggestion would conflict with the comment above
> >> __fixup_if. So I think we first need to clarify the various scenarios
> >> again to avoid breaking one while fixing another.
> >>
> >> Entry over non-root, exit over non-root:
> >>  - no need to fiddle with the root state
> >>
> > 
> > Correct.
> > 
> >> Entry over root, exit over root, !irqs_disabled_hw():
> >>  - no need to fiddle with the root state
> >>  - 32 bit: regs fixup required?
> >>
> > 
> > The iret emulation via iret_root needs proper fixup to have taken place,
> > so doing the fixup is mandatory in any case.
> > 
> >> Entry over root, exit over root, irqs_disabled_hw():
> >>  - save root state & disable root IRQs on entry
> >>  - 32 bit: replicate saved state into regs.eflags before calling linux
> >>    handler
> >>  - restore saved state on exit
> > 
> > Correct.
> > 
> >> Entry over non-root, exit over root:
> >>  - ?
> >>
> >> I tend to think that, for the 32-bit cases, we should pick up the flags
> >> from the root state _after_ returning from ipipe_trap_notify and only if
> >> we are truly running in the root domain then. That should be the value
> >> the migration left behind, so the correct one, right?
> >>
> > 
> > Yes.
> > 
> >> Any scenario missing?
> >>
> > 
> > Should be ok. But the more I think of it, the more I'm convinced that we
> > should make the 32 and 64 bit implementation converge to the x86_64 one.
> > iret_root emulation is required because we virtualize the interrupt
> > masking in the assembly-written portions for x86_32, which we don't for
> > x86_64. 
> > 
> > Hyste^Horically, there was a strong requirement to do that with legacy
> > 2.4 kernels the 32 bit implementation was designed for, because lengthy
> > masked sections would raise the latency above the top. With current
> > 2.6/x86 kernels, I don't think virtualizing interrupt masking in the
> > assembly-written portions makes a lot of sense anymore, since
> > significant work took place upstream over time, to allow for
> > fine-grained preemption there.
> 
> I'm all for this, but I think it should happen gradually. In step 1, we
> should fix the current situation. Step 2 would obsolete __fixup_if by
> moving x86-32 towards the 64-bit scheme.

I'm not saying anything else. But I want to stress the fact that we are
fixing the current mess for the last time; next time, let's kick out
this legacy.

> 
> So a discussion of my last patch would be warmly welcomed.
> 
> Jan
> 


-- 
Philippe.



_______________________________________________
Xenomai-core mailing list
Xenomai-core@gna.org
https://mail.gna.org/listinfo/xenomai-core

Reply via email to