Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for 32-bit arm #196

Merged
merged 7 commits into from
Apr 16, 2021
Merged

Conversation

TheSven73
Copy link
Collaborator

@TheSven73 TheSven73 commented Apr 15, 2021

Add Rust support for 32-bit arm.

Fixes: #79
Tested on cortex-a9 (physical hardware) and cortex-a7 (QEMU).

Loose ends:

  • no pure gcc support yet

v1 -> v2:

  • trim arm-release defconfig to bring build time to ~10mins
  • add arm-debug defconfig
  • remove size_t/uintptr_t guard in 32-bit arm mode only
  • skip Rust stack probing on debug builds for now (doesn't work)
  • enable HAS_RUST only on arm cores compatible with the instruction set generated by rustc (armv6)
  • added extra intrinsics required for debug build
  • sort alphabetically where possible

v2 -> v3:

  • eliminate stack probe module crash on debug builds
  • document arm architecture limitations
  • defconfig: switch from SLAB to SLUB
  • config.debug: enable CONFIG_KASAN

v3 -> v4:

  • rebased to latest rust branch

Copy link
Member

@ojeda ojeda left a comment

Choose a reason for hiding this comment

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

Tested on cortex-a7 and cortex-a9.

Very nice! Was it in QEMU or in actual hardware by chance?

CI very slow (~50 min to build). Trim the defconfig?

Yeah, please copy the other architectures -- you will see they are pretty minimal for this reason (but we do want to test defconfig soon-ish).

no debug config yet (what should it include?)

Ditto.

init/Kconfig Outdated
@@ -58,7 +58,7 @@ config LLD_VERSION
default 0

config HAS_RUST
depends on ARM64 || (PPC64 && CPU_LITTLE_ENDIAN) || X86_64
depends on ARM64 || (PPC64 && CPU_LITTLE_ENDIAN) || X86_64 || ARM
Copy link
Member

Choose a reason for hiding this comment

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

Just a nit: please put it first to keep it the archs alphabetically sorted (same in a few other places).

Suggested change
depends on ARM64 || (PPC64 && CPU_LITTLE_ENDIAN) || X86_64 || ARM
depends on ARM || ARM64 || (PPC64 && CPU_LITTLE_ENDIAN) || X86_64

Copy link
Collaborator Author

@TheSven73 TheSven73 Apr 15, 2021

Choose a reason for hiding this comment

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

The most vanilla 32-bit arm triple arm-unknown-linux-gnueabi appears to make Rust generate code compatible with armv6 and up, in non-Thumb mode. I will make sure that HAS_RUST appears only when the kernel is built with a compatible instruction set.

Copy link
Collaborator Author

@TheSven73 TheSven73 Apr 15, 2021

Choose a reason for hiding this comment

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

Or, force Rust to generate lowest-common-denominator arm instructions, so it'll run on each and every arm core out there. But that will result in very bad performance on newer cores.

@ojeda we seem to have the following trade-off:
a) use newer instruction set for good performance on newer cores, but won't work on older cores (where HAS_RUST will be automatically disabled)
b) use lowest-common-denominator instruction set which will run on all cores, but results in bad performance on older cores

(this happens because we don't have the ability to mod target.json depending on defconfig. Or do we?)

What is your opinion?

Copy link
Member

@ojeda ojeda Apr 15, 2021

Choose a reason for hiding this comment

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

Do not worry too much about that -- we will have the ability to mod the target soon enough. So it is fine picking either one.

I think the lowest-common-denominator makes the most sense since anyhow we are not measuring performance yet, which I assume it is also the easiest of the two alternatives.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Supporting the newer instruction set turned out to be the path of least resistance...

rust/helpers.c Outdated
Comment on lines 84 to 86
// See https://github.com/rust-lang/rust-bindgen/issues/1671
static_assert(__builtin_types_compatible_p(size_t, uintptr_t),
"size_t must match uintptr_t, what architecture is this??");
Copy link
Member

Choose a reason for hiding this comment

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

I saw your other PR -- I guess this is fine, but perhaps it doesn't hurt to leave it just in case...

Copy link
Collaborator Author

@TheSven73 TheSven73 Apr 15, 2021

Choose a reason for hiding this comment

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

On 32-bit arm, size_t and uintptr_t are incompatible, so the static assert will be triggered. Maybe I should make that clearer in the commit msg.

Copy link
Member

Choose a reason for hiding this comment

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

Under #[cfg] perhaps?

@TheSven73
Copy link
Collaborator Author

Very nice! Was it in QEMU or in actual hardware by chance?

Thanks! cortex-a9 on actual hardware, cortex-a7 on QEMU.

Yeah, please copy the other architectures -- you will see they are pretty minimal for this reason (but we do want to test defconfig soon-ish).

Will do.

no debug config yet (what should it include?)

Ditto.

I will diff debug and release for the other architectures, and use that to generate debug.

@TheSven73 TheSven73 force-pushed the rust-for-linux-arm-32bit branch 4 times, most recently from d94b886 to 79c154c Compare April 15, 2021 19:46
@ojeda
Copy link
Member

ojeda commented Apr 16, 2021

LGTM -- @wedsonaf to make him aware of the couple binder changes.

@TheSven73
Copy link
Collaborator Author

LGTM -- @wedsonaf to make him aware of the couple binder changes.

Thank you!! Can you wait until I push v3? I'm going to get rid of the stack probe crash, and add KASAN to the debug config (it's currently missing for some reason).

@ojeda
Copy link
Member

ojeda commented Apr 16, 2021

Sure, no rush! Take as much time as you need.

@TheSven73 TheSven73 force-pushed the rust-for-linux-arm-32bit branch from 79c154c to b692fbe Compare April 16, 2021 15:20
@TheSven73
Copy link
Collaborator Author

@ojeda this should be good to go from my end. Wait for @wedsonaf 's opinion on the binder changes?

@wedsonaf
Copy link

@ojeda this should be good to go from my end. Wait for @wedsonaf 's opinion on the binder changes?

Thanks for the ping. I'm happy with the changes (these should eventually move into the kernel crate). Ship it!

@ojeda
Copy link
Member

ojeda commented Apr 16, 2021

It seems you have re-applied/rebased two existing commits in the repo and GitHub's diff gets confused.

@TheSven73
Copy link
Collaborator Author

It seems you have re-applied/rebased two existing commits in the repo and GitHub's diff gets confused.

rust/rust probably moved on while I was working on the PR. I'll rebase and push as v4.

Sven Van Asbroeck added 7 commits April 16, 2021 13:12
This is simply based on output from:
 $ rustc +nightly -Z unstable-options \
     --target=arm-unknown-linux-gnueabi \
     --print target-spec-json

Changes made:
- removed "unsupported-abis"
  (does not build)
- added   "function-sections": false
  (all kernel functions should go in the .text section)
- added   "relocation-model": "static"
  (kernel does not support .data.rel.ro sections)

Note that the vanilla `arm-unknown-linux-gnueabi` triple lets
rustc generate the armv6 instruction set.

Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
On 32-bit arm, `size_t` and 'uintptr_t` are incompatible,
which will trigger the static assertion.

The bug which this guard protects against
(rust-lang/rust-bindgen#1671)
was fixed upstream as of rust-bindgen v0.53:
rust-lang/rust-bindgen#1688
d650823839f7 ("Remove size_t to usize conversion")

The current recommended rust-bindgen version for building
the Linux kernel is v0.56, so the guard can be safely
dropped.

Out of an abundance of caution, remove the guard only
if building for 32-bit arm.

Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Add panic handlers for the following 32-bit arm intrinsics:
- __aeabi_ul2f, __aeabi_ul2d,
          __aeabi_{f,d}cmpeq  : floating-point operations
- __aeabi_uldivmod, __mulodi4 : 64-bit division

Neither floating point operations, nor native 64-bit
division are supported inside the kernel, so we can
safely implement these with a panic handler.

Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Remove the assumption that c_types::c_ulong is u64. This is true
only on 64-bit cpu architectures.

Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Update the arch-support Rust documentation for arm 32-bit.

Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Everything is now in place to enable Rust support on 32-bit
arm. Enable only on architectures compatible with the armv6
instruction set.

Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
qemu emulates the virt machine running a cortex-a7.

kernel-arm-release.config corresponds to:
- arch/arm/configs/realview_defconfig (includes cortex-a7 virt support)
- remove unused kernel infrastructure and drivers
- enable rust support, enable rust samples (as modules)
- enable android/binder rust support
- switch from SLAB to SLUB

kernel-arm-debug.config corresponds to:
- kernel-arm-release.config
- add debug settings under "Kernel Hacking", borrowed from arm64
- use RUST_OPT_LEVEL_2 to prevent stack overflows
- enable CONFIG_KASAN

Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
@TheSven73 TheSven73 force-pushed the rust-for-linux-arm-32bit branch from b692fbe to 7e0815b Compare April 16, 2021 17:40
@TheSven73 TheSven73 requested a review from ojeda April 16, 2021 18:48
@TheSven73
Copy link
Collaborator Author

Not sure how rude it is to push that "request review" button! No rush @ojeda, it's the weekend, enjoy !!

@ojeda
Copy link
Member

ojeda commented Apr 16, 2021

It is fine to push it as long as you do not expect a very quick reply ;-P

@ojeda ojeda merged commit 30d13c6 into Rust-for-Linux:rust Apr 16, 2021
@TheSven73
Copy link
Collaborator Author

Awesome!! Thank you so much @ojeda and @wedsonaf for reviewing !!

@TheSven73 TheSven73 deleted the rust-for-linux-arm-32bit branch April 16, 2021 19:03
@ojeda
Copy link
Member

ojeda commented Apr 16, 2021

Thanks to you for the work!

@TheSven73
Copy link
Collaborator Author

If you guys like a helping hand with anything else, do let me know. It feels kind of rude to just grab something that's open, without communicating to you folks first.

@ojeda
Copy link
Member

ojeda commented Apr 16, 2021

No worries! If you want to get involved more, the best is that you come to the meetings (join the mailing list to be aware of them, it is a low volume list so far). We will likely have them every week or two weeks.

Otherwise, feel free to pick one of the issues (though ones that are about implementing something new is usually best to ping before in case someone is doing it) or work on something you like even if it is not there yet. Testing and reviewing other PRs is also very welcome.

@TheSven73
Copy link
Collaborator Author

Thanks for the warm welcome! Just out of curiosity, which organisations/people are the driving force behind Rust-for-Linux? Judging by the ambitious scope and activity, I'm assuming that this isn't "just" a 20% project to the key contributors.

@ojeda
Copy link
Member

ojeda commented Apr 18, 2021

Actually, it has been a hobby project for most of us!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Support arm (i.e. 32-bit)
3 participants