Re: Why do_swap() sets cpu.current before context switch?

Katsuhiro Suzuki


On 2021/09/08 11:35, andy-intel@... wrote:
Katsuhiro Suzuki wrote:
Newer switching sets NEW thread handle into _current_cpu.current
BEFORE calling arch_switch().  This implementation will face a
problem in RISC-V environment if thread calls do_swap() explicitly
and switch to thread B (use FPU) from thread A (not use FPU)
So... this is the very middle of a context switch.  The expectation of the kernel is that no exception/interrupt handlers are going to fire, because (by definition) if they do they will see corrupt/inconsistent thread state.  Or rather, if an architecture wants to allow that, it needs to be prepared to do the work.
I mean, the information is available to you: you know what the new thread is, because you're handed its switch handle which you created yourself.  You likewise know the old thread, because you're passed the address of its switch_handle field from which you can extract a pointer to the enclosing thread struct.  You know you're in the middle of a context switch, because arch_switch() was called.  You COULD write an FPU exception handler to detect this state and do the right thing.  I don't necessarily think this would be a good design, but it's possible.
Thanks for your advice.

Current RISC-V implementation (CONFIG_USE_SWITCH=n) is using 'ecall' (this is
SW interrupt instruction) to execute context switching explicitly.

And jump into interrupt handler that is used from not only SW interrupt but also
other interrupts. In interrupt handler, kernel saves FPU registers of current thread
that is pointing old thread.

I agree with you that I can add special path for explicit context switching.
If such path is needed, I will add that.

Can you explain why you need to take an FPU exception in the middle of a context switch?  That seems a little questionable to me.  Why are you hitting lazy-saved FPU registers in a situation where it would be faster to just check the mask state to see if they are populated or not?  (Forgive me: I don't know the RISC-V FPU architecture, but I assume that's the situation you're in: the FPU registers may or may not be in use and using them if they aren't will trap.)
In my understanding, RISC-V has not supported lazy-saved FPU yet. Always need to save
FPU registers at the beginning of interrupt handler.

RISC-V's FPU arch has the flag to permit/forbid using FPU. In Zephyr, this flag is set to
forbid side if thread was declared as not using FPU. And CPU raise interrupt when using
any FPU instruction at FPU forbidden state.

Best Regards,
Katsuhiro Suzuki

Join to automatically receive all group messages.