From bb77aa845b3a420860d05b2a1380ffe14220625c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 6 Jul 2023 11:59:14 +0200 Subject: [PATCH 1/5] compiler: Add `x86_64-unikraft-linux-musl` target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- compiler/rustc_target/src/spec/mod.rs | 3 +++ .../src/spec/unikraft_linux_musl_base.rs | 15 +++++++++++++++ .../src/spec/x86_64_unikraft_linux_musl.rs | 19 +++++++++++++++++++ src/bootstrap/lib.rs | 2 ++ src/tools/build-manifest/src/main.rs | 1 + 5 files changed, 40 insertions(+) create mode 100644 compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs create mode 100644 compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index aab31a4c8fe..7114c243ea1 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -85,6 +85,7 @@ mod solid_base; mod thumb_base; mod uefi_msvc_base; +mod unikraft_linux_musl_base; mod vxworks_base; mod wasm_base; mod windows_gnu_base; @@ -1421,6 +1422,8 @@ fn $module() { ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit), ("x86_64-unknown-hermit", x86_64_unknown_hermit), + ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl), + ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf), ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf), ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf), diff --git a/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs b/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs new file mode 100644 index 00000000000..9ccd0a1e7ca --- /dev/null +++ b/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs @@ -0,0 +1,15 @@ +use crate::spec::{cvs, PanicStrategy, RelocModel, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { + os: "linux".into(), + env: "musl".into(), + vendor: "unikraft".into(), + linker: Some("kraftld".into()), + relocation_model: RelocModel::Static, + families: cvs!["unix"], + has_thread_local: true, + panic_strategy: PanicStrategy::Abort, + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs new file mode 100644 index 00000000000..2aa093b131f --- /dev/null +++ b/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs @@ -0,0 +1,19 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "x86_64-unknown-linux-musl".into(), + pointer_width: 64, + arch: "x86_64".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + .into(), + options: TargetOptions { + cpu: "x86-64".into(), + plt_by_default: false, + pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]), + max_atomic_width: Some(64), + stack_probes: StackProbeType::X86, + ..super::unikraft_linux_musl_base::opts() + }, + } +} diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 3dd4d8d6617..365deb8e155 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -131,6 +131,8 @@ pub unsafe fn setup(_build: &mut crate::Build) {} (Some(Mode::Std), "freebsd13", None), (Some(Mode::Std), "backtrace_in_libstd", None), /* Extra values not defined in the built-in targets yet, but used in std */ + // #[cfg(bootstrap)] + (Some(Mode::Std), "target_vendor", Some(&["unikraft"])), (Some(Mode::Std), "target_env", Some(&["libnx"])), // (Some(Mode::Std), "target_os", Some(&[])), // #[cfg(bootstrap)] mips32r6, mips64r6 diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index bf46bd2f8a2..a02ce68903d 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -148,6 +148,7 @@ "x86_64-pc-windows-msvc", "x86_64-sun-solaris", "x86_64-pc-solaris", + "x86_64-unikraft-linux-musl", "x86_64-unknown-freebsd", "x86_64-unknown-illumos", "x86_64-unknown-linux-gnu", From 71ad5587a1f2730053279408d1dc70da1b094a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 6 Jul 2023 12:00:41 +0200 Subject: [PATCH 2/5] compiler: Add `*-unikraft-linux-musl` documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../platform-support/unikraft-linux-musl.md | 67 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 src/doc/rustc/src/platform-support/unikraft-linux-musl.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index e5af8526bfc..f108831138d 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -42,6 +42,7 @@ - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) + - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) - [*-unknown-hermit](platform-support/hermit.md) - [\*-unknown-netbsd\*](platform-support/netbsd.md) - [*-unknown-openbsd](platform-support/openbsd.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 959f6174192..8c5dc11eeef 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -326,6 +326,7 @@ target | std | host | notes [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support `x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos +[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku [`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit diff --git a/src/doc/rustc/src/platform-support/unikraft-linux-musl.md b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md new file mode 100644 index 00000000000..90fa18b9857 --- /dev/null +++ b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md @@ -0,0 +1,67 @@ +# `*-unikraft-linux-musl` + +**Tier: 3** + +Targets for the [Unikraft] Unikernel Development Kit (with musl). + +[Unikraft]: https://unikraft.org/ + +Target triplets available so far: + +- `x86_64-unikraft-linux-musl` + +## Target maintainers + +- Martin Kröning ([@mkroening](https://github.com/mkroening)) + +## Requirements + +These targets only support cross-compilation. +The targets do support std. + +Unikraft pretends to behave exactly like Linux. +How much of that functionality is available depends on the individual unikernel configuration. +For example, the basic Unikraft + musl config does not support `poll` or networking out of the box. +That functionality requires enabling [`LIBPOSIX_EVENT`] or [lwIP] respectively. + +[`LIBPOSIX_EVENT`]: https://github.com/unikraft/unikraft/blob/RELEASE-0.13.1/lib/posix-event/Config.uk +[lwIP]: https://github.com/unikraft/lib-lwip + +The Unikraft targets follow Linux's `extern "C"` calling convention. + +For these targets, `rustc` does not perform the final linking step. +Instead, the Unikraft build system will produce the final Unikernel image for the selected platform (e.g., KVM, Linux user space, and Xen). + +## Building the targets + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: + +```toml +[build] +build-stage = 1 +target = [ "x86_64-unikraft-linux-musl" ] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for these targets. +To compile for these targets, you will either need to build Rust with the targets enabled +(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar. + +Linking requires a [KraftKit] shim. +See [unikraft/kraftkit#612] for more information. + +[KraftKit]: https://github.com/unikraft/kraftkit +[unikraft/kraftkit#612]: https://github.com/unikraft/kraftkit/issues/612 + +## Testing + +The targets do support running binaries in the form of unikernel images. +How the unikernel image is run depends on the specific platform (e.g., KVM, Linux user space, and Xen). +The targets do not support running the Rust test suite. + +## Cross-compilation toolchains and C code + +The targets do support C code. +To build compatible C code, you have to use the same compiler and flags as does the Unikraft build system for your specific configuration. +The easiest way to achieve that, is to build the C code with the Unikraft build system when building your unikernel image. From 2b8a284d78b40da55733d56f3229274aaa6f9716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 5 Jul 2023 17:01:01 +0200 Subject: [PATCH 3/5] bootstrap: Don't bundle musl on Unikraft MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/bootstrap/compile.rs | 2 +- src/bootstrap/sanity.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index f3d95b57a76..400b07b1882 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -261,7 +261,7 @@ fn copy_self_contained_objects( // to using gcc from a glibc-targeting toolchain for linking. // To do that we have to distribute musl startup objects as a part of Rust toolchain // and link with them manually in the self-contained mode. - if target.contains("musl") { + if target.contains("musl") && !target.contains("unikraft") { let srcdir = builder.musl_libdir(target).unwrap_or_else(|| { panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple) }); diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 9321fc1bcb8..145ae6f44da 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -206,7 +206,7 @@ pub fn check(build: &mut Build) { } // Make sure musl-root is valid - if target.contains("musl") { + if target.contains("musl") && !target.contains("unikraft") { // If this is a native target (host is also musl) and no musl-root is given, // fall back to the system toolchain in /usr before giving up if build.musl_root(*target).is_none() && build.config.build == *target { From 7485e9c9652c8add0a10302b4a4076148f3b626c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 5 Jul 2023 12:49:35 +0200 Subject: [PATCH 4/5] `unix::init`: Handle `ENOSYS` from `poll` on Unikraft. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- library/std/src/sys/unix/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 326f1481e19..9d52f414574 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -110,6 +110,11 @@ unsafe fn sanitize_standard_fds() { while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 { match errno() { libc::EINTR => continue, + #[cfg(target_vendor = "unikraft")] + libc::ENOSYS => { + // Not all configurations of Unikraft enable `LIBPOSIX_EVENT`. + break 'poll; + } libc::EINVAL | libc::EAGAIN | libc::ENOMEM => { // RLIMIT_NOFILE or temporary allocation failures // may be preventing use of poll(), fall back to fcntl From 553804754a3031cf98394d67966257196aabe724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sat, 1 Jul 2023 17:48:40 +0200 Subject: [PATCH 5/5] `unix::init`: Don't use `signal` on Unikraft. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- library/std/src/sys/unix/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 9d52f414574..77ef086f29b 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -170,7 +170,14 @@ unsafe fn sanitize_standard_fds() { } unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) { - #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))] + #[cfg(not(any( + target_os = "emscripten", + target_os = "fuchsia", + target_os = "horizon", + // Unikraft's `signal` implementation is currently broken: + // https://github.com/unikraft/lib-musl/issues/57 + target_vendor = "unikraft", + )))] { // We don't want to add this as a public type to std, nor do we // want to `include!` a file from the compiler (which would break