[PATCH] arm64/sve: Make kernel FPU protection RT friendly

Sebastian Andrzej Siewior bigeasy at linutronix.de
Thu Jul 29 07:17:48 PDT 2021


On 2021-07-29 14:54:59 [+0100], Dave Martin wrote:
> > index e098f6c67b1de..a208514bd69a9 100644
> > --- a/arch/arm64/kernel/fpsimd.c
> > +++ b/arch/arm64/kernel/fpsimd.c
> > @@ -177,10 +177,19 @@ static void __get_cpu_fpsimd_context(void)
> >   *
> >   * The double-underscore version must only be called if you know the task
> >   * can't be preempted.
> > + *
> > + * On RT kernels local_bh_disable() is not sufficient because it only
> > + * serializes soft interrupt related sections via a local lock, but stays
> > + * preemptible. Disabling preemption is the right choice here as bottom
> > + * half processing is always in thread context on RT kernels so it
> > + * implicitly prevents bottom half processing as well.
> >   */
> >  static void get_cpu_fpsimd_context(void)
> >  {
> > -	local_bh_disable();
> > +	if (!IS_ENABLED(CONFIG_PREEMPT_RT))
> > +		local_bh_disable();
> > +	else
> > +		preempt_disable();
> 
> Is this wrongly abstracted for RT?

No, we want to keep BH preemptible. Say your NAPI callback is busy for
the next 200us and your RT task needs the CPU now.

> The requirement here is that the code should temporarily be
> nonpreemptible by anything except hardirq context.

That is what I assumed.

> Having to do this conditional everywhere that is required feels fragile.
> Is a similar thing needed anywhere else?

pssst. I wisper now so that the other don't hear us. If you look at
arch/x86/include/asm/fpu/api.h and search for fpregs_lock() then you
find the same pattern. Even some of the comments look similar. And
please don't look up the original commit :)
x86 restores the FPU registers on return to userland (not immediately on
context switch) and requires the same kind of synchronisation/
protection regarding other tasks and crypto in softirq. So it should be
more the same thing that arm64 does here.

> If bh (as a preempting context) doesn't exist on RT, then can't
> local_bh_disable() just suppress all preemption up to but excluding
> hardirq?  Would anything break?

Yes. A lot. Starting with spin_lock_bh() itself because it does:
	local_bh_disable();
	spin_lock()

and with disabled preemption you can't do spin_lock() and you have to
because the owner may be preempted. The next thing is that kmalloc() and
friends won't work in a local_bh_disable() section for the same reason.
The list goes on.

> [...]
> 
> Cheers
> ---Dave

Sebastian



More information about the linux-arm-kernel mailing list