cpu/native: Draft: Support native CPU on macOS
Hi!
This is an early draft of PR reviving macOS support for RIOT native. It builds upon #20739. It is still a draft, e.g., tuntap is not supported on macOS, and still has some rough edges. Perhaps, by making this public, people can experiment with RIOT native on macOS 😅 Feel free to leave your thoughts on this.
Motivation
To date, running RIOT native on a Mac requires a Linux container of some sort.
In my experience, building in an x86_64 Linux docker container was rather slow which is not ideal if, say, you're writing an entire library for RIOT. To mitigate this, you can turn to virtualizing an arm64 Linux on an Apple Silicon Mac, which is in on itself way faster than emulating x86, but still not ideal.
Background
In the past I have done this with `lima` (though there're alternatives like OrbStack, colima, UTM, just qemu, etc). Without arm64 Linux support (prior to #20739), you'd need to cross-compile an x86_64 binary in the arm64 Linux container. This binary is then run using Rosetta 2 in the Linux VM (which is cool). This is quite fast. But, debugging that binary requires more steps than usual. On top of this, networking (and IPv6 in particular) is not always easy to get right (see `socket_vmnet`).If you could run RIOT natively on macOS, this would be easier and, I think, would also lower the entrance barrier for people new to RIOT.
Changes
haven‘t rebased yet…
XFA
One tricky thing was XFA; you can read more about that here. Unfortunately, the solution I have found for XFA on macOS has the following implications.
- if you do not need macOS support, nothing needs to change
- if you do want to support all of macOS, Linux, etc, you would need to change your XFA definitions to include the element name as the last argument:
XFA(int, favorite_numbers, 1) answer = 42would become
XFA(int, favorite_numbers, 1, answer) = 42. This also works on Linux/....
... Is there a better way?
TODO: use ld's -alias instead of assembly workaround
Testing Procedure
- tests/unittests:
ASAN_BOARDS= TOOLCHAIN=llvm BOARD=native64 make flash term...
ping @Teufelchen1 if you haven't synced already
Murdock results
:x: FAILED
aec7d2daf2dd348ed1a9bcc3dfce6e687bd3ad65 core/xfa: support existing XFAs on macOS
| Success | Failures | Total | Runtime |
|---|---|---|---|
| 26 | 1 | 9299 | 01m:16s |
Build failures (1)
| Application | Target | Toolchain | Runtime (s) | Worker |
|---|---|---|---|---|
| tests/drivers/at_unit | msba2 | gnu | 0.61 | mobi6 |
Artifacts
Looks cool but running the hello world segfaults before reaching main(). At least the hardware init completed, so printf debugging is possible! :smile:
Found another issue! This line resets the free stack space to all zero. But RIOT pre-fills the stack with marker values. If not cared for, this results in constant panics where riot thinks the stack has overflowed.
Found another issue! This line resets the free stack space to all zero. But RIOT pre-fills the stack with marker values. If not cared for, this results in constant panics where riot thinks the stack has overflowed.
I think it's funny how we both fell for the same snare. I have already had a fight with that exact gnarly line, and thought I fixed that
Oh, funny. I forgot to include the fix in the PR. Great.
Rebased this onto #20739. Also picked up the lost commit circumventing the bzero in libplatform.
[native] CPU: thread_stack_init
[native] CPU: thread_stack_init
[native] CPU: _isr_schedule_and_switch
[native] CPU: ... ISR: switching to user thread, calling setcontext(main)
[native] CPU: thread_stack_init
[native] CPU: yielding higher priority thread, switching to ISR context ...
[native] CPU: ... ISR: switched to ISR context, scheduling
[native] CPU: ... ISR: switching to user thread, calling setcontext(pktdump)
[native] CPU: yielding higher priority thread, switching to ISR context ...
[native] CPU: ... ISR: switched to ISR context, scheduling
[native] CPU: ... ISR: switching to user thread, calling setcontext(main)
[1] 33460 killed ./bin/native64/default.macho
I think I have enough of it for today. The log above indicates that starting, running and suspending threads works. But it also indicates that resuming (here main) threads does not.