Zephyr SMP support for Arm MCUs


Keith Morgan
 

I am interested in Zephyr SMP support for the Arm M class of microcontrollers [1]. It’s not clear from the Zephyr SMP documentation [2] which architectures Zephyr currently supports, but I’ve gathered from other links that ARC, RISC-V and ARM A class are supported – possibly others as well.

 

According to a thread on this list back in October of 2020 [3], “to fully implement SMP you'll need per-cpu variables, IPIs, some extra arch_* APIs implemented, etc.”

 

It sounds like a porting guide did not exist back then. Is there by chance now a porting guide for SMP that I could follow? If not, could somebody provide a little more guidance as to how to get started?

 

Thanks.

 

-Keith

 

 

[1] https://community.arm.com/arm-community-blogs/b/embedded-blog/posts/white-paper-multi-core-microcontroller-design-with-cortex-m-processors-and-coresight-soc

 

[2] https://docs.zephyrproject.org/latest/kernel/services/smp/smp.html

 

[3] https://lists.zephyrproject.org/g/devel/topic/smp_support_for_arm/77261991

 


Carlo Caione
 

On 21/06/2022 01:25, Keith Morgan via lists.zephyrproject.org wrote:
I am interested in Zephyr SMP support for the Arm M class of microcontrollers [1]. It’s not clear from the Zephyr SMP documentation [2] which architectures Zephyr currently supports, but I’ve gathered from other links that ARC, RISC-V and ARM A class are supported – possibly others as well.
According to a thread on this list back in October of 2020 [3], “to fully implement SMP you'll need per-cpu variables, IPIs, some extra arch_* APIs implemented, etc.”
It sounds like a porting guide did not exist back then. Is there by chance now a porting guide for SMP that I could follow? If not, could somebody provide a little more guidance as to how to get started?
There is no guide still (AFAIK), but [1] could be a good starting point.

But there are some prerequisites and low-hanging fruits that you could work on before tackling the task as a whole. For example cortex-M doesn't support CONFIG_USE_SWITCH that is needed to support SMP (but you can still use that in !SMP).

So I guess that should be the really first step for you, the rest can follow.

Cheers!

[1] https://docs.zephyrproject.org/latest/kernel/services/smp/smp.html
[2] https://docs.zephyrproject.org/latest/kconfig.html#CONFIG_USE_SWITCH

--
Carlo Caione


Andy Ross
 

(Sorry for the delay, had to figure out how to get a new address subscribed.)
 
Carlo Caione wrote:
> Keith Morgan wrote:
>> I am interested in Zephyr SMP support for the Arm M class of
>> microcontrollers [...] Is there by chance now a porting guide for
>> SMP that I could follow?
>
> There is no guide still (AFAIK), but [1] could be a good starting point.
>
> But there are some prerequisites and low-hanging fruits that you
> could work on before tackling the task as a whole. For example
> cortex-M doesn't support CONFIG_USE_SWITCH that is needed to support
> SMP (but you can still use that in !SMP).
 
(Brief aside: is there specific hardware you're looking at for this
port?  I'm not aware of any multiprocessor Cortex M boards but would
be very curious to see one.)
 
Indeed, there's no single document to step you through this.  The
truth is that there really isn't a lot of mandatory complexity, most
SMP features are optional and you can start bringup with a subset.
 
But Carlo identifies the big one: SMP requires the newer ("switch")
context switch primitive, which also requires a modification to the
interrupt exit path.  The ARM32 arch in Zephyr is still using the
older ("swap") mechanism, which uses scheduler internals in a way that
isn't MP-safe.  This is where most of your work is going to be spent
for sure.
 
After that: you need an implementation of arch_curr_cpu() that will
return a pointer to the cpu struct for the current processor.  This
gets hardware dependent, most multiprocessor architectures have a
scratch-ish register that can be used for this, but the details are
sometimes weird (e.g. x86_64 uses a segment register to point to a
per-cpu region that contains the pointer).
 
Somewhat obviously, you need to implement arch_start_cpu() to launch
the secondary cores at boot.  Again, different devices can have very
different power-on behavior, but Zephyr's rule is that only CPU 0
should begin running in Zephyr code (i.e. at z_cstart()), and that the
other ones shouldn't do anythign detectable until after after core 0
enters arch_start_cpu() with their index.
 
Most of the other stuff is either already present (ARM32 gets working
atomics support via gcc intrinsics already) or something to worry
about later (interprocessor interrupts are technically an optional
feature even though skipping them requires a hard busy loop in the
idle thread).
 
But... as far as development process, you do this the way you think
you might: set CONFIG_SMP=y on your working uniprocessor platform,
build, and see what fails.
 
Andy