pico-sdk icon indicating copy to clipboard operation
pico-sdk copied to clipboard

Support for mixed architectures (ARM + RISC-V at the same time)

Open dsseng opened this issue 6 months ago • 9 comments

I could not find this neither in examples nor in the datasheet, but datasheet does mention that both architectures can be used at the same time, with sync primitives working as well.

I'm mostly asking for documentation here, not necessarily SDK support. So the known flow is that we can request BootROM to activate a certain arch at reboot, which will then be selected and an image will be found to make it run.

However, BootROM starts core 0, and it's program's job to bring up core 1. So some of my questions:

  1. Seems like I can place core 1 entrypoint outside of the main partition, in case I want it to evade Secure Boot? Use case: cpu0 runs "OS", and cpu1 runs user-modifiable code (a minimalist program not touching clocks or other hardware driven by cpu0). This is a rather specific task, but seems possible. Could you please confirm?
  2. Can we somehow set the core selection, then assert and deassert core 1 reset (as we must do to boot cpu1), so that it starts with the desired architecture?
  3. If Secure Boot is active, can I only force cpu0 (which actually runs SB checks) to the Arm-only mode, and make it bring up the second core as RISC-V? Or is the second core prevented from initializing to RISC-V after OTP is written for SB enable?

Thank you!

dsseng avatar Jun 04 '25 16:06 dsseng

Seems like I can place core 1 entrypoint outside of the main partition, in case I want it to evade Secure Boot? Use case: cpu0 runs "OS", and cpu1 runs user-modifiable code (a minimalist program not touching clocks or other hardware driven by cpu0). This is a rather specific task, but seems possible. Could you please confirm?

The way I have done this is building a RISC-V binary to embed inside the Arm binary, and forcing the RISC-V entry point to be at a known location (the start of the RISC-V binary).

You can embed one binary inside the other with #embed, xxd, .incbin etc

Can we somehow set the core selection, then assert and deassert core 1 reset (as we must do to boot cpu1), so that it starts with the desired architecture?

Yes. From core 0 just set bit 1 of otp_hw->archsel and then toggle the core 1 reset via PSM_FRCE_OFF_PROC1_BITS.

If Secure Boot is active, can I only force cpu0 (which actually runs SB checks) to the Arm-only mode, and make it bring up the second core as RISC-V? Or is the second core prevented from initializing to RISC-V after OTP is written for SB enable?

Enabling secure boot prevents selection of the RISC-V cores. You won't be able to write nonzero values to ARCHSEL.

Wren6991 avatar Jun 04 '25 16:06 Wren6991

Thanks for clarification, mixed-arch seems really cool!

The way I have done this is building a RISC-V binary to embed inside the Arm binary, and forcing the RISC-V entry point to be at a known location (the start of the RISC-V binary).

You can embed one binary inside the other with #embed, xxd, .incbin etc

Basically similar to what I want to use (but perhaps a separate partition at a known offset). Cool when you can handle the second CPU yourself!

Yes. From core 0 just set bit 1 of otp_hw->archsel and then toggle the core 1 reset via PSM_FRCE_OFF_PROC1_BITS.

Okay, so the ordinary core bring-up procedure makes the hardware re-read the ARCHSEL flag for it, without a full-chip reset. Cool! It just happens to be located in the OTP block, but is completely read-writeable and not persistent, right? Just want to be extra safe

Enabling secure boot prevents selection of the RISC-V cores. You won't be able to write nonzero values to ARCHSEL.

Got it, thanks! Might be a consideration for the next spin or something, since even if not possible to boot RISC-V securely, then only core 0 actually needs to be made ARM-only, and its firmware could take care of enforcing authenticity of the core 1 code (either by embedding into itself or verifying before execution).

dsseng avatar Jun 04 '25 16:06 dsseng

Okay, so the ordinary core bring-up procedure makes the hardware re-read the ARCHSEL flag for it, without a full-chip reset. Cool! It just happens to be located in the OTP block, but is completely read-writeable and not persistent, right? Just want to be extra safe

Yes, registers under OTP_BASE are just normal peripheral registers that happen to be closely associated with the OTP or the OTP PSM.

Got it, thanks! Might be a consideration for the next spin or something, since even if not possible to boot RISC-V securely, then only core 0 actually needs to be made ARM-only, and its firmware could take care of enforcing authenticity of the core 1 code (either by embedding into itself or verifying before execution).

We wanted to avoid any use of RISC-V cores or RISC-V debug to sidestep secure boot, and this was the simplest method.

Wren6991 avatar Jun 04 '25 16:06 Wren6991

Understood that, thanks. Should I close this or keep as a docs improvement proposal?

dsseng avatar Jun 04 '25 16:06 dsseng

Another question (not really practical yet a cool thing). Can I reset and re-select the architecture for cpu1 multiple times without full reset? Like archsel = 0, reset, run Arm code, archsel = 1, reset, run Hazard3 code, reset into Arm again? Basically the only prohibited management from cpu0 to cpu1 is resetting while running a critical section or holding spinlocks?

dsseng avatar Jun 04 '25 16:06 dsseng

Yes, I had a demo where all four cores were rendering 1/4 each of a DVI output by rebooting at 120 Hz.

I think the current level of documentation is a good self-selection for the people who want to try this :-)

Wren6991 avatar Jun 04 '25 16:06 Wren6991

Basically the only prohibited management from cpu0 to cpu1 is resetting while running a critical section or holding spinlocks?

Not just spinlocks, any reset of a processor that's holding any kind of software lock will lead to a sequence break. This is true even if you're not mixing your architectures.

Wren6991 avatar Jun 04 '25 16:06 Wren6991

Yes, I had a demo where all four cores were rendering 1/4 each of a DVI output by rebooting at 120 Hz.

I think the current level of documentation is a good self-selection for the people who want to try this :-)

Why did they have to reboot (and maybe switch arch?)?

dsseng avatar Jun 04 '25 17:06 dsseng

Basically the only prohibited management from cpu0 to cpu1 is resetting while running a critical section or holding spinlocks?

Not just spinlocks, any reset of a processor that's holding any kind of software lock will lead to a sequence break. This is true even if you're not mixing your architectures.

Gotcha, but actually re-resetting and re-selecting arch are both valid as long as the core isn't in critical sections nor holds a lock?

dsseng avatar Jun 04 '25 17:06 dsseng