-
Notifications
You must be signed in to change notification settings - Fork 435
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
[BROKEN] 32-bit x86 (i386) support #966
base: rust
Are you sure you want to change the base?
Conversation
While the kernel deliberately doesn't implement compiler builtins for 64-bit division and modulus on 32-bit x86, it seems that rust may require them for some standard library code. Add basic implementations which are based on the math64.h macros. Note that these currently live in moddiv_32.c, because they're for 32-bit x86, even though they operate on 64-bit integers (confusing, isn't it). The right solution is probably to put them in rust's compiler_builtins implentation, with all of its symbol hiding, etc. Signed-off-by: David Gow <davidgow@google.com>
Add support for 32-bit i386 targets when building Rust code. In addition, support 32-bit i386 for UML. Note that this doesn't work at the moment, due to a nasty crash which I _think_ is somewhere deep in the printk / fmt code. It does, however, work fine under UML, so all is not yet totally lost. I've not got around to setting CI up (since it's broken anyway), but some KUnit commands for testing work for me: qemu/i386: ./tools/testing/kunit/kunit.py run --arch i386 --make_options LLVM=1 --kconfig_add CONFIG_RUST=y UML/i386: ./tools/testing/kunit/kunit.py run --make_options LLVM=1 --kconfig_add CONFIG_RUST=y --kconfig_add CONFIG_64BIT=n Signed-off-by: David Gow <davidgow@google.com>
It should be |
It looks like the test tries to |
For x86 32-bit we need |
Ah, yup, that'd explain it! Adding |
Yeah, exactly. |
Probably not too bad to re-implement that logic in the front end. I don't see how we simplify the IR for this. Removing |
Thanks Nick. I was thinking of adding a module/target option so that LLVM would handle it (while keeping |
Rustc handles most abi calculation itself independent of the codegen backend in rustc_target::abi::call. The advantage of this is that it allow sharing the code between all codegen backends. |
rustc could add i.e. if |
At present, Rust in the kernel only supports 64-bit x86, so UML has followed suit. However, it's significantly easier to support 32-bit i386 on UML than on bare metal, as UML does not use the -mregparm option (which alters the ABI), which is not yet supported by rustc[1]. Add support for CONFIG_RUST on um/i386, by adding a new target config to generate_rust_target, and replacing various checks on CONFIG_X86_64 to also support CONFIG_X86_32. We still use generate_rust_target, rather than a built-in rustc target, in order to match x86_64, provide a future place for -mregparm, and more easily disable floating point instructions. With these changes, the KUnit tests pass with: kunit.py run --make_options LLVM=1 --kconfig_add CONFIG_RUST=y --kconfig_add CONFIG_64BIT=n --kconfig_add CONFIG_FORTIFY_SOURCE=n An earlier version of these changes was proposed on the Rust-for-Linux github[2]. [1]: rust-lang/rust#116972 [2]: Rust-for-Linux#966 Signed-off-by: David Gow <davidgow@google.com>
At present, Rust in the kernel only supports 64-bit x86, so UML has followed suit. However, it's significantly easier to support 32-bit i386 on UML than on bare metal, as UML does not use the -mregparm option (which alters the ABI), which is not yet supported by rustc[1]. Add support for CONFIG_RUST on um/i386, by adding a new target config to generate_rust_target, and replacing various checks on CONFIG_X86_64 to also support CONFIG_X86_32. We still use generate_rust_target, rather than a built-in rustc target, in order to match x86_64, provide a future place for -mregparm, and more easily disable floating point instructions. With these changes, the KUnit tests pass with: kunit.py run --make_options LLVM=1 --kconfig_add CONFIG_RUST=y --kconfig_add CONFIG_64BIT=n --kconfig_add CONFIG_FORTIFY_SOURCE=n An earlier version of these changes was proposed on the Rust-for-Linux github[2]. [1]: rust-lang/rust#116972 [2]: Rust-for-Linux#966 Signed-off-by: David Gow <davidgow@google.com> Link: https://patch.msgid.link/20240604224052.3138504-1-davidgow@google.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
I've made a few attempts to get Rust-for-Linux going under 32-bit x86, and have hit some crashes (I think with printk) that I haven't been able to resolve. (Interestingly, it seems to work on 32-bit UML, so that's interesting…)
This currently consists of two patches:
__udivdi3
/__umoddi3
to provide 64-bit integer division. This probably should ultimately live in compiler_builtins instead.generate_rust_target.rs
and the various Makefiles.I've not yet added either CI support or updated the
arch-support.rst
documentation.At the moment, it's crashing in
rust_fmt_argument
whenever printk is called from Rust:(Out of curiosity, is there a reason
rust_fmt_argument
is not declaredextern "C"
? Doing so doesn't fix this issue, but since it's called by the C printk code when %pA appears, I'd've thought it needed to use a C ABI?)In any case, that issue doesn't seem to show up under UML, and all of the doctest KUnit tests pass:
# rust_kernel_doctests: pass:92 fail:0 skip:0 total:92
I'm testing this with KUnit's tooling, using the following commands:
QEMU/i386:
./tools/testing/kunit/kunit.py run --arch i386 --make_options LLVM=1 --kconfig_add CONFIG_RUST=y
UML/i386:
./tools/testing/kunit/kunit.py run --make_options LLVM=1 --kconfig_add CONFIG_RUST=y --kconfig_add CONFIG_64BIT=n
If anyone has any ideas what could be causing these problems, I'd love to hear them!