Skip to content

Add SMP support - #205

Merged
jonathanpallant merged 11 commits into
rust-embedded:mainfrom
thejpster:add-smp-support
Jul 25, 2026
Merged

Add SMP support#205
jonathanpallant merged 11 commits into
rust-embedded:mainfrom
thejpster:add-smp-support

Conversation

@thejpster

@thejpster thejpster commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Integrates SMP support into aarch32-rt. Now the default start-up routines (for Armv7-R, Armv7-A and Armv8-R) check MPIDR and do normal start-up on Core 0, and park any secondary core.

To get the secondary cores to work, you have to replace the park routine (_asm_secondary_core_park) with one that waits for a reliable signal from Core 0 (like a hardware register, not definitely not a RAM location because RAM has random contents) and then returns. After that, stacks are initialised and the core ends up in kmain_secondary.

This is a breaking change, but I think it makes SMP examples much easier to write. So much so, the mps3-an536-smp example folder has gone - they've been folded into the normal mps3-an536 examples because they are now so similar.

Closes #168
Closes #167

Also means we can collapse the mps3-an536-smp example back into
mps3-an536, because we don't need special start-up routines any more
(the presence of a custom `_default_start` before meant we weren't
testing the supplied `_default_start` routine, so we had to split the
example up).
You cannot check the stack contents of Core 1 on Core 0 when the MPU
is enabled. So, now I set a flag and make sure not to do that for that
particular test.
I copied from this example and got confused when it didn't work. Now
it's fixed.

@9names 9names left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a quick pass through. I'm not familiar with this part of the ARM spec so the review is mostly that comments make sense.

You mention in the code that the cores definitely have to wait on a hardware register because ram contents will be garbage.
Isn't the register value also not guaranteed at startup?
Also, I could imagine a scheme where either there's a shared address (that every core writes initially so it's not "random"), then spin for some amount of time that we can assume all cores will have done init, and then have the secondary cores poll for primary to set them.
Or, each core having it's own address and having cpu0 wake them all individually?

Comment thread aarch32-rt/src/arch_v7/boot_from_el2.rs Outdated
@thejpster

Copy link
Copy Markdown
Contributor Author

I did a quick pass through. I'm not familiar with this part of the ARM spec so the review is mostly that comments make sense.

You mention in the code that the cores definitely have to wait on a hardware register because ram contents will be garbage. Isn't the register value also not guaranteed at startup? Also, I could imagine a scheme where either there's a shared address (that every core writes initially so it's not "random"), then spin for some amount of time that we can assume all cores will have done init, and then have the secondary cores poll for primary to set them. Or, each core having it's own address and having cpu0 wake them all individually?

Peripheral registers generally go to known values on reset (think GPIO direction registers, or GPIO output data registers - pins are not randomised on boot-up).

The thing about this design - using a secondary core park function - is that the library user is entirely in charge of which mechanism to use. You could write a secondary core park function where each core writes a zero to the same memory location, waits 10 seconds, and then starts polling for a non-zero value. You could write a secondary core park function where each core waits on a different memory address. All very possible.

For the MPS3-AN536, waiting on the FPGA's LED register works, because it resets to zero.

Co-authored-by: 9names <60134748+9names@users.noreply.github.com>
Comment thread aarch32-rt/src/lib.rs Outdated
Comment thread aarch32-rt/src/arch_v8_hyp/boot.rs Outdated
Comment thread aarch32-rt/src/lib.rs
Comment thread aarch32-rt/src/lib.rs Outdated
Comment thread aarch32-rt/src/lib.rs Outdated
docs for each global_asm function.

The docs are easy to read outside of the assembly string, because they
get syntax highlighted as comments and not text.

Also swaps the last few .sections for .pushsection
@thejpster

Copy link
Copy Markdown
Contributor Author

error[E0779]: target does not support #[instruction_set]

OK, turns out we cannot write _vector_table as a naked function yet as the MSRV won't let us apply the instruction_set attribute to force it to be an A32 function and not a T32 function.

@jonathanpallant

Copy link
Copy Markdown
Contributor

Tested on the S32Z2, where it allowed me to delete a whole bunch of assembly code from the example and still enjoy SMP support.

@robamu

robamu commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

One general question: Assuming there are SoCs which even have something like 4 or 8 cores, maybe the kmain_secondary should receive the core ID as an input argument?

Comment thread examples/mps3-an536-el2/memory.x
Comment thread examples/mps3-an536/src/lib.rs
@thejpster

Copy link
Copy Markdown
Contributor Author

One general question: Assuming there are SoCs which even have something like 4 or 8 cores, maybe the kmain_secondary should receive the core ID as an input argument?

A quad core cluster is quite possible, or even multiple clusters with some number of cores in each.

But in that case, the secondary function can just read the CPUID register and work out what to do.

I think the important thing is the split between the primary core (that zeroes .bss and initialises .data) and the secondary cores (which do not).

@jonathanpallant
jonathanpallant added this pull request to the merge queue Jul 24, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Jul 24, 2026
@thejpster

Copy link
Copy Markdown
Contributor Author

Damn you GitHub. I’ll queue it again later on my work laptop.

@jonathanpallant
jonathanpallant added this pull request to the merge queue Jul 25, 2026
Merged via the queue into rust-embedded:main with commit 47e9038 Jul 25, 2026
95 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Supply a secondary start start-up routine Clarify naming of cores in an SMP system

4 participants