supermachine_kernel_x86_64/lib.rs
1//! Pre-built x86_64 runtime assets for supermachine's **KVM** backend,
2//! packaged as a Rust crate so embedders never fetch binaries out of band.
3//!
4//! This is the x86_64 counterpart of `supermachine-kernel-aarch64`. You
5//! normally don't depend on it directly — depend on the
6//! [`supermachine-kernel`] facade, which re-exports the right arch's crate by
7//! `target_arch`. Cargo only downloads the sub-crate matching the build
8//! target, so an x86_64 build pulls only this crate (and never the aarch64
9//! kernel), and vice-versa.
10//!
11//! Three assets are bundled:
12//!
13//! 1. **Linux kernel** ([`KERNEL_BYTES`]) — a minimal-config x86_64
14//! `bzImage` (Linux 6.12). Everything the microVM needs is built in
15//! (`MODULES=n`): virtio-MMIO (+`CMDLINE_DEVICES`), virtio-blk,
16//! virtio-vsock, squashfs, overlayfs, ext4, 8250 console. No module
17//! loading, no host-kernel coupling.
18//! 2. **busybox** ([`BUSYBOX_BYTES`]) — a static x86_64 busybox. The KVM
19//! bake stages it into the agent initramfs as the PID-1 init's toolbox
20//! (mount, switch_root, overlay setup).
21//! 3. **`supermachine-agent`** ([`SUPERMACHINE_AGENT_BYTES`]) — the in-VM
22//! control agent (static x86_64-musl). Runs as PID 1 inside the
23//! container after `switch_root`, serving `exec`/control RPCs over vsock.
24//!
25//! Unlike the aarch64/HVF crate, there is **no `init-oci` or `smpark.ko`**:
26//! the KVM backend builds the container rootfs (overlayfs + `switch_root`)
27//! directly in the agent initramfs's generated init, and does not park
28//! secondary vCPUs via a kernel module.
29//!
30//! [`supermachine-kernel`]: https://crates.io/crates/supermachine-kernel
31
32/// Raw bytes of the x86_64 kernel — a minimal-config Linux `bzImage`.
33///
34/// The supermachine KVM backend loads this as the guest kernel. The bytes are
35/// staged into `OUT_DIR` by `build.rs` (env override or bundled `kernel.xz`).
36pub const KERNEL_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/kernel"));
37
38/// Length of the kernel image in bytes — `KERNEL_BYTES.len()`, const-evaluable.
39pub const KERNEL_LEN: usize = KERNEL_BYTES.len();
40
41/// Raw bytes of the static x86_64 busybox staged into the agent initramfs.
42/// The generated PID-1 init uses it for the overlayfs + `switch_root` dance
43/// that builds the writable container rootfs from the read-only OCI squashfs.
44pub const BUSYBOX_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/busybox"));
45
46/// Length of the busybox binary in bytes.
47pub const BUSYBOX_LEN: usize = BUSYBOX_BYTES.len();
48
49/// Raw bytes of the in-VM `supermachine-agent` (static x86_64-musl ELF). Runs
50/// as PID 1 inside the container post-`switch_root`, serving docker-style
51/// `exec` and other control RPCs over vsock.
52pub const SUPERMACHINE_AGENT_BYTES: &[u8] =
53 include_bytes!(concat!(env!("OUT_DIR"), "/supermachine-agent"));
54
55/// Length of the supermachine-agent binary in bytes.
56pub const SUPERMACHINE_AGENT_LEN: usize = SUPERMACHINE_AGENT_BYTES.len();
57
58/// Write the bundled kernel image to `dest`. Overwrites any existing file;
59/// the parent dir must exist (use [`extract_kernel_to_with_parents`] to mkdir).
60pub fn extract_kernel_to(dest: &std::path::Path) -> std::io::Result<()> {
61 std::fs::write(dest, KERNEL_BYTES)
62}
63
64/// Like [`extract_kernel_to`] but `mkdir -p`'s the parent dir first.
65pub fn extract_kernel_to_with_parents(dest: &std::path::Path) -> std::io::Result<()> {
66 if let Some(parent) = dest.parent() {
67 std::fs::create_dir_all(parent)?;
68 }
69 extract_kernel_to(dest)
70}
71
72/// Write the bundled busybox to `dest`, executable (mode 0o755) on Unix.
73pub fn extract_busybox_to(dest: &std::path::Path) -> std::io::Result<()> {
74 std::fs::write(dest, BUSYBOX_BYTES)?;
75 set_executable(dest)
76}
77
78/// Like [`extract_busybox_to`] but `mkdir -p`'s the parent dir first.
79pub fn extract_busybox_to_with_parents(dest: &std::path::Path) -> std::io::Result<()> {
80 if let Some(parent) = dest.parent() {
81 std::fs::create_dir_all(parent)?;
82 }
83 extract_busybox_to(dest)
84}
85
86/// Write the bundled `supermachine-agent` to `dest`, executable on Unix.
87pub fn extract_supermachine_agent_to(dest: &std::path::Path) -> std::io::Result<()> {
88 std::fs::write(dest, SUPERMACHINE_AGENT_BYTES)?;
89 set_executable(dest)
90}
91
92/// Like [`extract_supermachine_agent_to`] but `mkdir -p`'s the parent first.
93pub fn extract_supermachine_agent_to_with_parents(dest: &std::path::Path) -> std::io::Result<()> {
94 if let Some(parent) = dest.parent() {
95 std::fs::create_dir_all(parent)?;
96 }
97 extract_supermachine_agent_to(dest)
98}
99
100#[cfg(unix)]
101fn set_executable(dest: &std::path::Path) -> std::io::Result<()> {
102 use std::os::unix::fs::PermissionsExt;
103 let mut perms = std::fs::metadata(dest)?.permissions();
104 perms.set_mode(0o755);
105 std::fs::set_permissions(dest, perms)
106}
107
108#[cfg(not(unix))]
109fn set_executable(_dest: &std::path::Path) -> std::io::Result<()> {
110 Ok(())
111}