From bb77aa845b3a420860d05b2a1380ffe14220625c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Kr=C3=B6ning?=
 <martin.kroening@eonerc.rwth-aachen.de>
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 <martin.kroening@eonerc.rwth-aachen.de>
---
 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 aab31a4c8fef7..7114c243ea14d 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -85,6 +85,7 @@ mod solaris_base;
 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 @@ supported_targets! {
     ("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 0000000000000..9ccd0a1e7caec
--- /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 0000000000000..2aa093b131f5f
--- /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 3dd4d8d6617bd..365deb8e155df 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -131,6 +131,8 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
     (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 bf46bd2f8a235..a02ce68903d1a 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -148,6 +148,7 @@ static TARGETS: &[&str] = &[
     "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?=
 <martin.kroening@eonerc.rwth-aachen.de>
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 <martin.kroening@eonerc.rwth-aachen.de>
---
 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 e5af8526bfc88..f108831138d85 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 959f61741925c..8c5dc11eeef37 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 0000000000000..90fa18b985783
--- /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?=
 <martin.kroening@eonerc.rwth-aachen.de>
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 <martin.kroening@eonerc.rwth-aachen.de>
---
 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 f3d95b57a76d7..400b07b1882cc 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 9321fc1bcb8b0..145ae6f44da39 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -206,7 +206,7 @@ than building it.
         }
 
         // 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?= <mkroening@posteo.net>
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 <martin.kroening@eonerc.rwth-aachen.de>
---
 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 326f1481e1918..9d52f414574a7 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -110,6 +110,11 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
             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?= <mkroening@posteo.net>
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 <martin.kroening@eonerc.rwth-aachen.de>
---
 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 9d52f414574a7..77ef086f29b59 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -170,7 +170,14 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
     }
 
     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