From 445cc0a89899f6bc9501650e5c4bd9a30a89b958 Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 17:12:47 +0200 Subject: [PATCH 01/12] examples: replace deprecated krun_set_root_disk/krun_set_data_disk with krun_add_disk Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- examples/boot_efi.c | 2 +- examples/launch-tee.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/boot_efi.c b/examples/boot_efi.c index 5105d46df..5891c35ee 100644 --- a/examples/boot_efi.c +++ b/examples/boot_efi.c @@ -197,7 +197,7 @@ int main(int argc, char *const argv[]) return -1; } - if (err = krun_set_root_disk(ctx_id, cmdline.disk_image)) { + if (err = krun_add_disk(ctx_id, "root", cmdline.disk_image, false)) { errno = -err; perror("Error configuring disk image"); return -1; diff --git a/examples/launch-tee.c b/examples/launch-tee.c index 063cdd5f3..1eadf193e 100644 --- a/examples/launch-tee.c +++ b/examples/launch-tee.c @@ -68,7 +68,7 @@ int main(int argc, char *const argv[]) } // Use the first command line argument as the disk image containing the root fs. - if (err = krun_set_root_disk(ctx_id, argv[1])) { + if (err = krun_add_disk(ctx_id, "root", argv[1], false)) { errno = -err; perror("Error configuring root disk image"); return -1; @@ -114,7 +114,7 @@ int main(int argc, char *const argv[]) return -1; } - if (err = krun_set_data_disk(ctx_id, argv[3])) { + if (err = krun_add_disk(ctx_id, "data", argv[3], false)) { errno = -err; perror("Error configuring the TEE config data disk"); return -1; From cfde4708e0b0c63b73cabedb78fe3aee9f40c5c1 Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 17:23:09 +0200 Subject: [PATCH 02/12] lib: remove deprecated krun_set_root_disk and krun_set_data_disk These were replaced by krun_add_disk. Also remove the internal root_block_cfg/data_block_cfg fields and their setters, and simplify get_block_cfg() now that the legacy compat path is gone. Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- include/libkrun.h | 39 ----------------- init/init.c | 5 +-- src/libkrun/src/lib.rs | 96 +----------------------------------------- 3 files changed, 3 insertions(+), 137 deletions(-) diff --git a/include/libkrun.h b/include/libkrun.h index 9a71e946d..a912bea53 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -118,45 +118,12 @@ int32_t krun_set_vm_config(uint32_t ctx_id, uint8_t num_vcpus, uint32_t ram_mib) */ int32_t krun_set_root(uint32_t ctx_id, const char *root_path); -/** - * DEPRECATED. Use krun_add_disk instead. - * - * Sets the path to the disk image that contains the file-system to be used as root for the microVM. - * The only supported image format is "raw". - * - * Arguments: - * "ctx_id" - the configuration context ID. - * "disk_path" - a null-terminated string representing the path leading to the disk image that - * contains the root file-system. - * - * Returns: - * Zero on success or a negative error number on failure. - */ -int32_t krun_set_root_disk(uint32_t ctx_id, const char *disk_path); -/** - * DEPRECATED. Use krun_add_disk instead. - * - * Sets the path to the disk image that contains the file-system to be used as - * a data partition for the microVM. The only supported image format is "raw". - * - * Arguments: - * "ctx_id" - the configuration context ID. - * "disk_path" - a null-terminated string representing the path leading to the disk image that - * contains the root file-system. - * - * Returns: - * Zero on success or a negative error number on failure. - */ -int32_t krun_set_data_disk(uint32_t ctx_id, const char *disk_path); /** * Adds a disk image to be used as a general partition for the microVM. The only supported image * format is "raw". * - * This API is mutually exclusive with the deprecated krun_set_root_disk and - * krun_set_data_disk methods and must not be used together. - * * This function deliberately only handles images in the Raw format, because it doesn't allow * specifying an image format, and probing an image's format is dangerous. For more information, * see the security note on `krun_add_disk2`, which allows opening non-Raw images. @@ -183,9 +150,6 @@ int32_t krun_add_disk(uint32_t ctx_id, const char *block_id, const char *disk_pa * Adds a disk image to be used as a general partition for the microVM. The supported * image formats are: "raw" and "qcow2". * - * This API is mutually exclusive with the deprecated krun_set_root_disk and - * krun_set_data_disk methods and must not be used together. - * * SECURITY NOTE: * Non-Raw images can reference other files, which libkrun will automatically open, and to which the * guest will have access. Libkrun should therefore never be asked to open an image in a non-Raw @@ -254,9 +218,6 @@ int32_t krun_add_disk2(uint32_t ctx_id, /** * Adds a disk image to be used as a general partition for the microVM. * - * This API is mutually exclusive with the deprecated krun_set_root_disk and - * krun_set_data_disk methods and must not be used together. - * * SECURITY NOTE: * See the security note for `krun_add_disk2`. * diff --git a/init/init.c b/init/init.c index a65d68015..4a73fad9d 100644 --- a/init/init.c +++ b/init/init.c @@ -210,9 +210,8 @@ static char *get_luks_passphrase(int *pass_len) return_str = NULL; /* - * If a user registered the TEE config data disk with - * krun_set_data_disk(), it would appear as /dev/vdb in the guest. - * Mount this device and read the config. + * If a TEE config data disk was registered, it would appear as + * /dev/vdb in the guest. Mount this device and read the config. */ if (mkdir("/dev", 0755) < 0 && errno != EEXIST) { perror("mkdir(/dev)"); diff --git a/src/libkrun/src/lib.rs b/src/libkrun/src/lib.rs index 696642325..26274ab10 100644 --- a/src/libkrun/src/lib.rs +++ b/src/libkrun/src/lib.rs @@ -168,10 +168,6 @@ struct ContextConfig { #[cfg(feature = "blk")] block_cfgs: Vec, #[cfg(feature = "blk")] - root_block_cfg: Option, - #[cfg(feature = "blk")] - data_block_cfg: Option, - #[cfg(feature = "blk")] block_root: Option, #[cfg(feature = "tee")] tee_config_file: Option, @@ -275,31 +271,9 @@ impl ContextConfig { self.block_cfgs.push(block_cfg); } - #[cfg(feature = "blk")] - fn set_root_block_cfg(&mut self, block_cfg: BlockDeviceConfig) { - self.root_block_cfg = Some(block_cfg); - } - - #[cfg(feature = "blk")] - fn set_data_block_cfg(&mut self, block_cfg: BlockDeviceConfig) { - self.data_block_cfg = Some(block_cfg); - } - #[cfg(feature = "blk")] fn get_block_cfg(&self) -> Vec { - // For backwards compat, when cfgs is empty (the new API is not used), this needs to be - // root and then data, in that order. Also for backwards compat, root/data are setters and - // need to discard redundant calls. So we have simple setters above and fix up here. - // - // When the new API is used, this is simpler. - if self.block_cfgs.is_empty() { - [&self.root_block_cfg, &self.data_block_cfg] - .into_iter() - .filter_map(|cfg| cfg.clone()) - .collect() - } else { - self.block_cfgs.clone() - } + self.block_cfgs.clone() } #[cfg(feature = "net")] @@ -876,74 +850,6 @@ pub unsafe extern "C" fn krun_add_disk3( } } -#[allow(clippy::missing_safety_doc)] -#[unsafe(no_mangle)] -#[cfg(feature = "blk")] -pub unsafe extern "C" fn krun_set_root_disk(ctx_id: u32, c_disk_path: *const c_char) -> i32 { - unsafe { - let disk_path = match CStr::from_ptr(c_disk_path).to_str() { - Ok(disk) => disk, - Err(_) => return -libc::EINVAL, - }; - - match CTX_MAP.lock().unwrap().entry(ctx_id) { - Entry::Occupied(mut ctx_cfg) => { - let cfg = ctx_cfg.get_mut(); - let block_device_config = BlockDeviceConfig { - block_id: "root".to_string(), - cache_type: CacheType::auto(disk_path), - disk_image_path: disk_path.to_string(), - disk_image_format: ImageType::Raw, - is_disk_read_only: false, - direct_io: false, - #[cfg(not(target_os = "macos"))] - sync_mode: SyncMode::Full, - #[cfg(target_os = "macos")] - sync_mode: SyncMode::Relaxed, - }; - cfg.set_root_block_cfg(block_device_config); - } - Entry::Vacant(_) => return -libc::ENOENT, - } - - KRUN_SUCCESS - } -} - -#[allow(clippy::missing_safety_doc)] -#[unsafe(no_mangle)] -#[cfg(feature = "blk")] -pub unsafe extern "C" fn krun_set_data_disk(ctx_id: u32, c_disk_path: *const c_char) -> i32 { - unsafe { - let disk_path = match CStr::from_ptr(c_disk_path).to_str() { - Ok(disk) => disk, - Err(_) => return -libc::EINVAL, - }; - - match CTX_MAP.lock().unwrap().entry(ctx_id) { - Entry::Occupied(mut ctx_cfg) => { - let cfg = ctx_cfg.get_mut(); - let block_device_config = BlockDeviceConfig { - block_id: "data".to_string(), - cache_type: CacheType::auto(disk_path), - disk_image_path: disk_path.to_string(), - disk_image_format: ImageType::Raw, - is_disk_read_only: false, - direct_io: false, - #[cfg(not(target_os = "macos"))] - sync_mode: SyncMode::Full, - #[cfg(target_os = "macos")] - sync_mode: SyncMode::Relaxed, - }; - cfg.set_data_block_cfg(block_device_config); - } - Entry::Vacant(_) => return -libc::ENOENT, - } - - KRUN_SUCCESS - } -} - /* * Send the VFKIT magic after establishing the connection, * as required by gvproxy in vfkit mode. From 36af82e5813cc32e25a6dc76b454d38e7289730e Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 17:25:46 +0200 Subject: [PATCH 03/12] lib: remove deprecated krun_set_passt_fd, krun_set_gvproxy_path, krun_set_net_mac These were replaced by krun_add_net_unixstream, krun_add_net_unixgram, and krun_add_net_tap (which take mac as a parameter directly). Also remove the internal LegacyNetworkConfig enum, legacy_net_cfg and legacy_mac fields, the compat path in krun_start_enter that converted them to the new net backend, and the now-unused NET_COMPAT_FEATURES constant. Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- include/libkrun.h | 58 ++------------------ src/libkrun/src/lib.rs | 121 +---------------------------------------- 2 files changed, 6 insertions(+), 173 deletions(-) diff --git a/include/libkrun.h b/include/libkrun.h index a912bea53..29b401475 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -332,7 +332,7 @@ int32_t krun_add_virtiofs3(uint32_t ctx_id, #define NET_FEATURE_HOST_TSO6 1 << 12 #define NET_FEATURE_HOST_UFO 1 << 14 -/* These are the features enabled by krun_set_passt_fd and krun_set_gvproxy_path. */ +/* These are the default features used by krun_add_net_unixstream and krun_add_net_unixgram. */ #define COMPAT_NET_FEATURES NET_FEATURE_CSUM | NET_FEATURE_GUEST_CSUM | \ NET_FEATURE_GUEST_TSO4 | NET_FEATURE_GUEST_UFO | \ NET_FEATURE_HOST_TSO4 | NET_FEATURE_HOST_UFO @@ -453,57 +453,6 @@ int32_t krun_add_net_tap(uint32_t ctx_id, uint32_t features, uint32_t flags); -/** - * DEPRECATED. Use krun_add_net_unixstream instead. - * - * Configures the networking to use passt. - * Call to this function disables TSI backend to use passt instead. - * - * Arguments: - * "ctx_id" - the configuration context ID. - * "fd" - a file descriptor to communicate with passt - * - * Notes: - * If you never call this function, networking uses the TSI backend. - * This function should be called before krun_set_port_map. - * - * Returns: - * Zero on success or a negative error number on failure. - */ -int32_t krun_set_passt_fd(uint32_t ctx_id, int fd); - -/** - * DEPRECATED. Use krun_add_net_unixgram instead. - * - * Configures the networking to use gvproxy in vfkit mode. - * Call to this function disables TSI backend to use gvproxy instead. - * - * Arguments: - * "ctx_id" - the configuration context ID. - * "c_path" - a null-terminated string representing the path for - * gvproxy's listen-vfkit unixdgram socket. - * - * Notes: - * If you never call this function, networking uses the TSI backend. - * This function should be called before krun_set_port_map. - * - * Returns: - * Zero on success or a negative error number on failure. - */ -int32_t krun_set_gvproxy_path(uint32_t ctx_id, char *c_path); - -/** - * Sets the MAC address for the virtio-net device when using the passt backend. - * - * Arguments: - * "ctx_id" - the configuration context ID. - * "mac" - MAC address as an array of 6 uint8_t entries. - * - * Returns: - * Zero on success or a negative error number on failure. - */ -int32_t krun_set_net_mac(uint32_t ctx_id, uint8_t *const c_mac); - /** * Configures a map of host to guest TCP ports for the microVM. * @@ -526,8 +475,9 @@ int32_t krun_set_net_mac(uint32_t ctx_id, uint8_t *const c_mac); * means that for a map such as "8080:80", applications running inside the guest will also * need to access the service through the "8080" port. * - * If past networking mode is used (krun_set_passt_fd was called), port mapping is not supported - * as an API of libkrun (but you can still do port mapping using command line arguments of passt) + * If passt networking mode is used, port mapping is not supported as an API + * of libkrun (but you can still do port mapping using command line arguments + * of passt) */ int32_t krun_set_port_map(uint32_t ctx_id, const char *const port_map[]); diff --git a/src/libkrun/src/lib.rs b/src/libkrun/src/lib.rs index 26274ab10..0909776b8 100644 --- a/src/libkrun/src/lib.rs +++ b/src/libkrun/src/lib.rs @@ -142,13 +142,6 @@ impl KrunfwBindings { } } -#[derive(Clone)] -#[cfg(feature = "net")] -enum LegacyNetworkConfig { - VirtioNetPasst(RawFd), - VirtioNetGvproxy(PathBuf), -} - #[derive(Default)] struct ContextConfig { krunfw: Option, @@ -158,10 +151,6 @@ struct ContextConfig { env: Option, args: Option, rlimits: Option, - #[cfg(feature = "net")] - legacy_net_cfg: Option, - #[cfg(feature = "net")] - legacy_mac: Option<[u8; 6]>, net_index: u8, tsi_port_map: Option>, vsock_config: VsockConfig, @@ -276,11 +265,6 @@ impl ContextConfig { self.block_cfgs.clone() } - #[cfg(feature = "net")] - fn set_net_mac(&mut self, mac: [u8; 6]) { - self.legacy_mac = Some(mac); - } - fn set_port_map(&mut self, new_port_map: HashMap) -> Result<(), ()> { if self.net_index != 0 { return Err(()); @@ -878,19 +862,7 @@ const NET_FEATURE_HOST_TSO4: u32 = 1 << 11; const NET_FEATURE_HOST_TSO6: u32 = 1 << 12; #[cfg(feature = "net")] const NET_FEATURE_HOST_UFO: u32 = 1 << 14; -/* - * These are the flags enabled by default on each virtio-net instance - * before the introduction of "krun_add_net_*". They are now used in - * the legacy API ("krun_set_passt_fd" and "krun_set_gvproxy_path") - * for compatiblity reasons. - */ -#[cfg(feature = "net")] -const NET_COMPAT_FEATURES: u32 = NET_FEATURE_CSUM - | NET_FEATURE_GUEST_CSUM - | NET_FEATURE_GUEST_TSO4 - | NET_FEATURE_GUEST_UFO - | NET_FEATURE_HOST_TSO4 - | NET_FEATURE_HOST_UFO; + #[cfg(feature = "net")] const NET_ALL_FEATURES: u32 = NET_FEATURE_CSUM | NET_FEATURE_GUEST_CSUM @@ -1094,79 +1066,6 @@ pub unsafe extern "C" fn krun_add_net_tap( -libc::EINVAL } -#[allow(clippy::missing_safety_doc)] -#[unsafe(no_mangle)] -#[cfg(feature = "net")] -pub unsafe extern "C" fn krun_set_passt_fd(ctx_id: u32, fd: c_int) -> i32 { - if fd < 0 { - return -libc::EINVAL; - } - - match CTX_MAP.lock().unwrap().entry(ctx_id) { - Entry::Occupied(mut ctx_cfg) => { - let cfg = ctx_cfg.get_mut(); - // The legacy interface only supports a single network interface. - if cfg.net_index != 0 { - return -libc::EINVAL; - } - cfg.legacy_net_cfg = Some(LegacyNetworkConfig::VirtioNetPasst(fd)); - } - Entry::Vacant(_) => return -libc::ENOENT, - } - KRUN_SUCCESS -} - -#[allow(clippy::missing_safety_doc)] -#[unsafe(no_mangle)] -#[cfg(feature = "net")] -pub unsafe extern "C" fn krun_set_gvproxy_path(ctx_id: u32, c_path: *const c_char) -> i32 { - unsafe { - let path_str = match CStr::from_ptr(c_path).to_str() { - Ok(path) => path, - Err(e) => { - debug!("Error parsing gvproxy_path: {e:?}"); - return -libc::EINVAL; - } - }; - - let path = PathBuf::from(path_str); - - match CTX_MAP.lock().unwrap().entry(ctx_id) { - Entry::Occupied(mut ctx_cfg) => { - let cfg = ctx_cfg.get_mut(); - // The legacy interface only supports a single network interface. - if cfg.net_index != 0 { - return -libc::EINVAL; - } - cfg.legacy_net_cfg = Some(LegacyNetworkConfig::VirtioNetGvproxy(path)); - } - Entry::Vacant(_) => return -libc::ENOENT, - } - KRUN_SUCCESS - } -} - -#[allow(clippy::missing_safety_doc)] -#[unsafe(no_mangle)] -#[cfg(feature = "net")] -pub unsafe extern "C" fn krun_set_net_mac(ctx_id: u32, c_mac: *const u8) -> i32 { - unsafe { - let mac: [u8; 6] = match slice::from_raw_parts(c_mac, 6).try_into() { - Ok(m) => m, - Err(_) => return -libc::EINVAL, - }; - - match CTX_MAP.lock().unwrap().entry(ctx_id) { - Entry::Occupied(mut ctx_cfg) => { - let cfg = ctx_cfg.get_mut(); - cfg.set_net_mac(mac); - } - Entry::Vacant(_) => return -libc::ENOENT, - } - KRUN_SUCCESS - } -} - #[allow(clippy::missing_safety_doc)] #[unsafe(no_mangle)] pub unsafe extern "C" fn krun_set_port_map(ctx_id: u32, c_port_map: *const *const c_char) -> i32 { @@ -2891,22 +2790,6 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 { return -libc::EINVAL; } - #[cfg(feature = "net")] - { - if let Some(legacy_net_cfg) = ctx_cfg.legacy_net_cfg.clone() { - let backend = match legacy_net_cfg { - LegacyNetworkConfig::VirtioNetGvproxy(path) => { - VirtioNetBackend::UnixgramPath(path, true) - } - LegacyNetworkConfig::VirtioNetPasst(fd) => VirtioNetBackend::UnixstreamFd(fd), - }; - let mac = ctx_cfg - .legacy_mac - .unwrap_or([0x5a, 0x94, 0xef, 0xe4, 0x0c, 0xee]); - create_virtio_net(&mut ctx_cfg, backend, mac, NET_COMPAT_FEATURES); - } - } - match &ctx_cfg.vsock_config { VsockConfig::Disabled => (), VsockConfig::Explicit { tsi_flags } => { @@ -2923,7 +2806,7 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 { // Implicit vsock configuration - use heuristics // Check if TSI should be enabled based on network configuration #[cfg(feature = "net")] - let enable_tsi = ctx_cfg.vmr.net.list.is_empty() && ctx_cfg.legacy_net_cfg.is_none(); + let enable_tsi = ctx_cfg.vmr.net.list.is_empty(); #[cfg(not(feature = "net"))] let enable_tsi = true; From bec825f96da4cdf08f8546268de69a2a348c893c Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 17:28:19 +0200 Subject: [PATCH 04/12] tests/examples: replace krun_set_log_level with krun_init_log Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- examples/boot_efi.c | 2 +- examples/consoles.c | 2 +- examples/external_kernel.c | 2 +- examples/launch-tee.c | 2 +- examples/nitro.c | 2 +- tests/test_cases/src/test_augmentfs.rs | 2 +- tests/test_cases/src/test_freebsd_boot.rs | 9 +++++++-- .../src/test_freebsd_gvproxy_tcp_guest_connect.rs | 11 ++++++++--- .../src/test_freebsd_gvproxy_tcp_guest_listen.rs | 11 ++++++++--- tests/test_cases/src/test_multiport_console.rs | 2 +- tests/test_cases/src/test_net/mod.rs | 2 +- tests/test_cases/src/test_root_disk_remount.rs | 7 ++++++- tests/test_cases/src/test_tsi_tcp_guest_connect.rs | 2 +- tests/test_cases/src/test_tsi_tcp_guest_listen.rs | 2 +- tests/test_cases/src/test_virtiofs_misc.rs | 2 +- tests/test_cases/src/test_virtiofs_root_ro.rs | 7 ++++++- tests/test_cases/src/test_vm_config.rs | 2 +- tests/test_cases/src/test_vsock_guest_connect.rs | 2 +- 18 files changed, 48 insertions(+), 23 deletions(-) diff --git a/examples/boot_efi.c b/examples/boot_efi.c index 5891c35ee..089fd39e9 100644 --- a/examples/boot_efi.c +++ b/examples/boot_efi.c @@ -169,7 +169,7 @@ int main(int argc, char *const argv[]) } // Set the log level to "off". - err = krun_set_log_level(0); + err = krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_OFF, KRUN_LOG_STYLE_AUTO, 0); if (err) { errno = -err; perror("Error configuring log level"); diff --git a/examples/consoles.c b/examples/consoles.c index 30a17a492..fe3a98271 100644 --- a/examples/consoles.c +++ b/examples/consoles.c @@ -119,7 +119,7 @@ int main(int argc, char *const argv[]) const char *const *command_args = (argc > 3) ? (const char *const *)&argv[3] : NULL; const char *const envp[] = { 0 }; - krun_set_log_level(KRUN_LOG_LEVEL_WARN); + krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_WARN, KRUN_LOG_STYLE_AUTO, 0); int err; int ctx_id = krun_create_ctx(); diff --git a/examples/external_kernel.c b/examples/external_kernel.c index 14649881d..ab857719d 100644 --- a/examples/external_kernel.c +++ b/examples/external_kernel.c @@ -218,7 +218,7 @@ int main(int argc, char *const argv[]) } // Set the log level to "off". - err = krun_set_log_level(0); + err = krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_OFF, KRUN_LOG_STYLE_AUTO, 0); if (err) { errno = -err; diff --git a/examples/launch-tee.c b/examples/launch-tee.c index 1eadf193e..df5f78f66 100644 --- a/examples/launch-tee.c +++ b/examples/launch-tee.c @@ -45,7 +45,7 @@ int main(int argc, char *const argv[]) } // Set the log level to "error". - err = krun_set_log_level(1); + err = krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_ERROR, KRUN_LOG_STYLE_AUTO, 0); if (err) { errno = -err; perror("Error configuring log level"); diff --git a/examples/nitro.c b/examples/nitro.c index 2a80e02fd..2b4578d54 100644 --- a/examples/nitro.c +++ b/examples/nitro.c @@ -180,7 +180,7 @@ int main(int argc, char *const argv[]) // Enable debug output if configured. log_level = (cmdline.debug) ? KRUN_LOG_LEVEL_DEBUG : KRUN_LOG_LEVEL_OFF; - err = krun_set_log_level(log_level); + err = krun_init_log(KRUN_LOG_TARGET_DEFAULT, log_level, KRUN_LOG_STYLE_AUTO, 0); if (err) { errno = -err; perror("Error configuring log level"); diff --git a/tests/test_cases/src/test_augmentfs.rs b/tests/test_cases/src/test_augmentfs.rs index 24032033c..a3d87c636 100644 --- a/tests/test_cases/src/test_augmentfs.rs +++ b/tests/test_cases/src/test_augmentfs.rs @@ -48,7 +48,7 @@ mod host { let marker: &'static [u8] = b"virtual-file-marker-content-12345"; unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; diff --git a/tests/test_cases/src/test_freebsd_boot.rs b/tests/test_cases/src/test_freebsd_boot.rs index 866007f74..6b669fed9 100644 --- a/tests/test_cases/src/test_freebsd_boot.rs +++ b/tests/test_cases/src/test_freebsd_boot.rs @@ -7,7 +7,7 @@ mod host { use super::*; use crate::common_freebsd::{freebsd_assets, normalize_serial_output, setup_kernel_and_enter}; - use crate::{ShouldRun, Test, TestOutcome, TestSetup, krun_call, krun_call_u32}; + use crate::{krun_call, krun_call_u32, ShouldRun, Test, TestOutcome, TestSetup}; use krun_sys::*; impl Test for TestFreeBsdBoot { @@ -26,7 +26,12 @@ mod host { fn start_vm(self: Box, test_setup: TestSetup) -> anyhow::Result<()> { let assets = freebsd_assets().expect("FreeBSD assets must be present when test runs"); unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; setup_kernel_and_enter(ctx, test_setup, assets)?; diff --git a/tests/test_cases/src/test_freebsd_gvproxy_tcp_guest_connect.rs b/tests/test_cases/src/test_freebsd_gvproxy_tcp_guest_connect.rs index 007058ab7..bf0994e60 100644 --- a/tests/test_cases/src/test_freebsd_gvproxy_tcp_guest_connect.rs +++ b/tests/test_cases/src/test_freebsd_gvproxy_tcp_guest_connect.rs @@ -28,8 +28,8 @@ mod host { freebsd_assets, normalize_serial_output, setup_gvproxy_backend, setup_kernel_and_enter, }; use crate::test_net::gvproxy::gvproxy_path; - use crate::{ShouldRun, Test, TestOutcome, TestSetup}; use crate::{krun_call, krun_call_u32}; + use crate::{ShouldRun, Test, TestOutcome, TestSetup}; use krun_sys::*; use std::thread; @@ -52,7 +52,12 @@ mod host { thread::spawn(move || self.tcp_tester.run_server(listener)); unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; setup_gvproxy_backend(ctx, &test_setup)?; @@ -78,8 +83,8 @@ mod host { #[guest] mod guest { use super::*; - use crate::Test; use crate::freebsd_network::configure_virtio_net_ip; + use crate::Test; impl Test for TestFreeBsdGvproxyTcpGuestConnect { fn in_guest(self: Box) { diff --git a/tests/test_cases/src/test_freebsd_gvproxy_tcp_guest_listen.rs b/tests/test_cases/src/test_freebsd_gvproxy_tcp_guest_listen.rs index 00ccebc79..7001c5f5b 100644 --- a/tests/test_cases/src/test_freebsd_gvproxy_tcp_guest_listen.rs +++ b/tests/test_cases/src/test_freebsd_gvproxy_tcp_guest_listen.rs @@ -26,8 +26,8 @@ mod host { freebsd_assets, normalize_serial_output, setup_gvproxy_backend, setup_kernel_and_enter, }; use crate::test_net::gvproxy::{gvproxy_path, setup_gvproxy_port_forward}; - use crate::{ShouldRun, Test, TestOutcome, TestSetup}; use crate::{krun_call, krun_call_u32}; + use crate::{ShouldRun, Test, TestOutcome, TestSetup}; use krun_sys::*; use std::net::Ipv4Addr; use std::thread; @@ -50,7 +50,12 @@ mod host { let assets = freebsd_assets().expect("freebsd assets must be available"); unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; let net_sock = setup_gvproxy_backend(ctx, &test_setup)?; @@ -89,8 +94,8 @@ mod host { #[guest] mod guest { use super::*; - use crate::Test; use crate::freebsd_network::configure_virtio_net_ip; + use crate::Test; impl Test for TestFreeBsdGvproxyTcpGuestListen { fn in_guest(self: Box) { diff --git a/tests/test_cases/src/test_multiport_console.rs b/tests/test_cases/src/test_multiport_console.rs index 8fcbf6033..2948b7369 100644 --- a/tests/test_cases/src/test_multiport_console.rs +++ b/tests/test_cases/src/test_multiport_console.rs @@ -50,7 +50,7 @@ mod host { impl Test for TestMultiportConsole { fn start_vm(self: Box, test_setup: TestSetup) -> anyhow::Result<()> { unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_disable_implicit_console(ctx))?; diff --git a/tests/test_cases/src/test_net/mod.rs b/tests/test_cases/src/test_net/mod.rs index 394464115..a27637e13 100644 --- a/tests/test_cases/src/test_net/mod.rs +++ b/tests/test_cases/src/test_net/mod.rs @@ -122,7 +122,7 @@ mod host { thread::spawn(move || tcp_tester.run_server(listener)); unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; diff --git a/tests/test_cases/src/test_root_disk_remount.rs b/tests/test_cases/src/test_root_disk_remount.rs index 11a445a81..81c5623e4 100644 --- a/tests/test_cases/src/test_root_disk_remount.rs +++ b/tests/test_cases/src/test_root_disk_remount.rs @@ -98,7 +98,12 @@ mod host { let test_case = CString::new(test_setup.test_case)?; unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; diff --git a/tests/test_cases/src/test_tsi_tcp_guest_connect.rs b/tests/test_cases/src/test_tsi_tcp_guest_connect.rs index c3bb6c33d..158810c48 100644 --- a/tests/test_cases/src/test_tsi_tcp_guest_connect.rs +++ b/tests/test_cases/src/test_tsi_tcp_guest_connect.rs @@ -31,7 +31,7 @@ mod host { let listener = self.tcp_tester.create_server_socket(); thread::spawn(move || self.tcp_tester.run_server(listener)); unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; setup_fs_and_enter(ctx, test_setup)?; diff --git a/tests/test_cases/src/test_tsi_tcp_guest_listen.rs b/tests/test_cases/src/test_tsi_tcp_guest_listen.rs index c1a8d8721..4a0f9fd62 100644 --- a/tests/test_cases/src/test_tsi_tcp_guest_listen.rs +++ b/tests/test_cases/src/test_tsi_tcp_guest_listen.rs @@ -33,7 +33,7 @@ mod host { self.tcp_tester.run_client(); }); - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; let ctx = krun_call_u32!(krun_create_ctx())?; let port_mapping = format!("{PORT}:{PORT}"); let port_mapping = CString::new(port_mapping).unwrap(); diff --git a/tests/test_cases/src/test_virtiofs_misc.rs b/tests/test_cases/src/test_virtiofs_misc.rs index cb5b3730b..c59eeb8c7 100644 --- a/tests/test_cases/src/test_virtiofs_misc.rs +++ b/tests/test_cases/src/test_virtiofs_misc.rs @@ -17,7 +17,7 @@ mod host { impl Test for TestVirtioFsMisc { fn start_vm(self: Box, test_setup: TestSetup) -> anyhow::Result<()> { unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 1024))?; setup_fs_and_enter(ctx, test_setup)?; diff --git a/tests/test_cases/src/test_virtiofs_root_ro.rs b/tests/test_cases/src/test_virtiofs_root_ro.rs index 31cbd1cb2..21332153e 100644 --- a/tests/test_cases/src/test_virtiofs_root_ro.rs +++ b/tests/test_cases/src/test_virtiofs_root_ro.rs @@ -42,7 +42,12 @@ mod host { let envp = [null()]; unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; diff --git a/tests/test_cases/src/test_vm_config.rs b/tests/test_cases/src/test_vm_config.rs index 207f2b460..bd5c9addf 100644 --- a/tests/test_cases/src/test_vm_config.rs +++ b/tests/test_cases/src/test_vm_config.rs @@ -17,7 +17,7 @@ mod host { impl Test for TestVmConfig { fn start_vm(self: Box, test_setup: TestSetup) -> anyhow::Result<()> { unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, self.num_cpus, self.ram_mib))?; setup_fs_and_enter(ctx, test_setup)?; diff --git a/tests/test_cases/src/test_vsock_guest_connect.rs b/tests/test_cases/src/test_vsock_guest_connect.rs index 686d15654..84fec166d 100644 --- a/tests/test_cases/src/test_vsock_guest_connect.rs +++ b/tests/test_cases/src/test_vsock_guest_connect.rs @@ -65,7 +65,7 @@ mod host { thread::spawn(move || server(listener)); unsafe { - krun_call!(krun_set_log_level(KRUN_LOG_LEVEL_TRACE))?; + krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_add_vsock_port( ctx, From 012821f841edc0b119ea42602eecde4d875244ea Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 17:29:17 +0200 Subject: [PATCH 05/12] lib: propagate KRUN_NITRO_DEBUG flag in krun_init_log krun_set_log_level set KRUN_NITRO_DEBUG when level==4 (debug), but krun_init_log did not. Fix the omission so removing krun_set_log_level doesn't regress nitro debug logging. Also fix the condition to level >= 4 so that trace (level 5) also enables nitro debug. Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- src/libkrun/src/lib.rs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/libkrun/src/lib.rs b/src/libkrun/src/lib.rs index 0909776b8..93b72efc0 100644 --- a/src/libkrun/src/lib.rs +++ b/src/libkrun/src/lib.rs @@ -419,26 +419,6 @@ fn log_level_to_filter_str(level: u32) -> &'static str { } } -#[unsafe(no_mangle)] -pub extern "C" fn krun_set_log_level(level: u32) -> i32 { - let filter = log_level_to_filter_str(level); - env_logger::Builder::from_env(Env::default().default_filter_or(filter)) - .format_timestamp_micros() - .init(); - - #[cfg(feature = "aws-nitro")] - { - // Notify krun-awsnitro to enable debug for log level. - if level == 4 { - let mut debug = KRUN_NITRO_DEBUG.lock().unwrap(); - - *debug = true; - } - } - - KRUN_SUCCESS -} - mod log_defs { pub const KRUN_LOG_STYLE_AUTO: u32 = 0; pub const KRUN_LOG_STYLE_ALWAYS: u32 = 1; @@ -487,6 +467,14 @@ pub unsafe extern "C" fn krun_init_log(target: RawFd, level: u32, style: u32, op }; builder.format_timestamp_micros().target(target).init(); + #[cfg(feature = "aws-nitro")] + { + // Notify krun-awsnitro to enable debug for log level. + if level >= 4 { + *KRUN_NITRO_DEBUG.lock().unwrap() = true; + } + } + KRUN_SUCCESS } } From 4b46f2b5369eb7698c68a535bc253d4f8cc79a96 Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 17:30:47 +0200 Subject: [PATCH 06/12] lib: remove deprecated krun_set_log_level Superseded by krun_init_log which provides control over target fd, log style, and env override options. Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- include/libkrun.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/include/libkrun.h b/include/libkrun.h index 29b401475..d34d255c4 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -10,24 +10,6 @@ extern "C" { #include #include -/** - * Sets the log level for the library. - * - * Arguments: - * "level" can be one of the following values: - * 0: Off - * 1: Error - * 2: Warn - * 3: Info - * 4: Debug - * 5: Trace - * - * Returns: - * Zero on success or a negative error number on failure. - */ -int32_t krun_set_log_level(uint32_t level); - - #define KRUN_LOG_TARGET_DEFAULT -1 #define KRUN_LOG_LEVEL_OFF 0 From 7396c1e8d4ebb5165a01c669857f331380484479 Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 17:44:40 +0200 Subject: [PATCH 07/12] lib: remove unsupported krun_set_mapped_volumes This function has been returning -EINVAL unconditionally. Remove it. Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- include/libkrun.h | 16 ---------------- src/libkrun/src/lib.rs | 10 ---------- 2 files changed, 26 deletions(-) diff --git a/include/libkrun.h b/include/libkrun.h index d34d255c4..efcb2af5c 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -226,22 +226,6 @@ int32_t krun_add_disk2(uint32_t ctx_id, bool direct_io, uint32_t sync_mode); -/** - * NO LONGER SUPPORTED. DO NOT USE. - * - * Configures the mapped volumes for the microVM. Only supported on macOS, on Linux use - * user_namespaces and bind-mounts instead. Not available in libkrun-SEV. - * - * Arguments: - * "ctx_id" - the configuration context ID. - * "mapped_volumes" - an array of string pointers with format "host_path:guest_path" representing - * the volumes to be mapped inside the microVM - * - * Returns: - * Zero on success or a negative error number on failure. - */ -int32_t krun_set_mapped_volumes(uint32_t ctx_id, const char *const mapped_volumes[]); - /** * Adds an independent virtio-fs device pointing to a host's directory with a tag. * diff --git a/src/libkrun/src/lib.rs b/src/libkrun/src/lib.rs index 93b72efc0..39309c796 100644 --- a/src/libkrun/src/lib.rs +++ b/src/libkrun/src/lib.rs @@ -664,16 +664,6 @@ pub unsafe extern "C" fn krun_add_virtiofs3( } } -#[allow(clippy::missing_safety_doc)] -#[unsafe(no_mangle)] -#[cfg(not(feature = "tee"))] -pub unsafe extern "C" fn krun_set_mapped_volumes( - _ctx_id: u32, - _c_mapped_volumes: *const *const c_char, -) -> i32 { - -libc::EINVAL -} - #[allow(clippy::missing_safety_doc)] #[unsafe(no_mangle)] #[cfg(feature = "blk")] From 022cb7c3fa15cdbb3a0fc8fe82356611dfefe013 Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 17:54:07 +0200 Subject: [PATCH 08/12] tests/examples: use explicit krun_add_virtio_console_default everywhere Replace implicit console creation with explicit krun_add_virtio_console_default calls. Also replace krun_set_console_output in nitro.c with krun_add_virtio_console_default. No test or example relies on implicit console injection anymore. Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- examples/boot_efi.c | 6 ++++++ examples/chroot_vm.c | 6 ++++++ examples/external_kernel.c | 7 +++++++ examples/gui_vm/src/main.rs | 15 +++++++++++---- examples/launch-tee.c | 6 ++++++ examples/nitro.c | 4 ++-- tests/test_cases/src/common_freebsd.rs | 5 ++--- tests/test_cases/src/test_augmentfs.rs | 7 +++++++ tests/test_cases/src/test_net/mod.rs | 14 +++++++++++++- tests/test_cases/src/test_net_perf.rs | 7 +++++++ tests/test_cases/src/test_pjdfstest.rs | 7 +++++++ tests/test_cases/src/test_root_disk_remount.rs | 7 +++++++ .../test_cases/src/test_tsi_tcp_guest_connect.rs | 14 +++++++++++++- tests/test_cases/src/test_tsi_tcp_guest_listen.rs | 14 +++++++++++++- tests/test_cases/src/test_virtiofs_misc.rs | 14 +++++++++++++- tests/test_cases/src/test_virtiofs_root_ro.rs | 7 +++++++ tests/test_cases/src/test_vm_config.rs | 14 +++++++++++++- tests/test_cases/src/test_vsock_guest_connect.rs | 7 +++++++ 18 files changed, 147 insertions(+), 14 deletions(-) diff --git a/examples/boot_efi.c b/examples/boot_efi.c index 089fd39e9..5b84e2c56 100644 --- a/examples/boot_efi.c +++ b/examples/boot_efi.c @@ -191,6 +191,12 @@ int main(int argc, char *const argv[]) return -1; } + if (err = krun_add_virtio_console_default(ctx_id, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO)) { + errno = -err; + perror("Error configuring console"); + return -1; + } + if (err = krun_set_firmware(ctx_id, cmdline.efi_fw)) { errno = -err; perror("Error configuring EFI FW path"); diff --git a/examples/chroot_vm.c b/examples/chroot_vm.c index b0ab0a05e..9bfce23f6 100644 --- a/examples/chroot_vm.c +++ b/examples/chroot_vm.c @@ -308,6 +308,12 @@ int main(int argc, char *const argv[]) return -1; } + if (err = krun_add_virtio_console_default(ctx_id, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO)) { + errno = -err; + perror("Error configuring console"); + return -1; + } + // Configure vhost-user RNG if requested if (cmdline.vhost_user_rng_socket != NULL) { // Test sentinel-terminated array: auto-detect queue count, use custom size diff --git a/examples/external_kernel.c b/examples/external_kernel.c index ab857719d..9b2b96f6c 100644 --- a/examples/external_kernel.c +++ b/examples/external_kernel.c @@ -243,6 +243,13 @@ int main(int argc, char *const argv[]) return -1; } + if (err = krun_add_virtio_console_default(ctx_id, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO)) + { + errno = -err; + perror("Error configuring console"); + return -1; + } + if (cmdline.boot_disk) { if (err = krun_add_disk(ctx_id, "boot", cmdline.boot_disk, 0)) diff --git a/examples/gui_vm/src/main.rs b/examples/gui_vm/src/main.rs index 660a2e21a..fe230a957 100644 --- a/examples/gui_vm/src/main.rs +++ b/examples/gui_vm/src/main.rs @@ -9,9 +9,9 @@ use krun_sys::{ KRUN_LOG_LEVEL_TRACE, KRUN_LOG_LEVEL_WARN, KRUN_LOG_STYLE_ALWAYS, KRUN_LOG_TARGET_DEFAULT, VIRGLRENDERER_RENDER_SERVER, VIRGLRENDERER_THREAD_SYNC, VIRGLRENDERER_USE_ASYNC_FENCE_CB, VIRGLRENDERER_USE_EGL, VIRGLRENDERER_VENUS, krun_add_display, krun_add_input_device, - krun_add_input_device_fd, krun_create_ctx, krun_display_set_dpi, - krun_display_set_physical_size, krun_display_set_refresh_rate, krun_init_log, - krun_set_display_backend, krun_set_exec, krun_set_gpu_options2, krun_set_root, + krun_add_input_device_fd, krun_add_virtio_console_default, krun_create_ctx, + krun_display_set_dpi, krun_display_set_physical_size, krun_display_set_refresh_rate, + krun_init_log, krun_set_display_backend, krun_set_exec, krun_set_gpu_options2, krun_set_root, krun_set_vm_config, krun_start_enter, }; use log::LevelFilter; @@ -22,7 +22,7 @@ use std::fs::{File, OpenOptions}; use std::mem::size_of_val; use anyhow::Context; -use std::os::fd::IntoRawFd; +use std::os::fd::{AsRawFd, IntoRawFd}; use std::path::PathBuf; use std::process::exit; use std::ptr::null; @@ -150,6 +150,13 @@ fn krun_thread( krun_call!(krun_set_vm_config(ctx, 4, 4096))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; + krun_call!(krun_set_gpu_options2( ctx, VIRGLRENDERER_USE_EGL diff --git a/examples/launch-tee.c b/examples/launch-tee.c index df5f78f66..cc64a6c48 100644 --- a/examples/launch-tee.c +++ b/examples/launch-tee.c @@ -67,6 +67,12 @@ int main(int argc, char *const argv[]) return -1; } + if (err = krun_add_virtio_console_default(ctx_id, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO)) { + errno = -err; + perror("Error configuring console"); + return -1; + } + // Use the first command line argument as the disk image containing the root fs. if (err = krun_add_disk(ctx_id, "root", argv[1], false)) { errno = -err; diff --git a/examples/nitro.c b/examples/nitro.c index 2b4578d54..379e28d89 100644 --- a/examples/nitro.c +++ b/examples/nitro.c @@ -203,9 +203,9 @@ int main(int argc, char *const argv[]) return -1; } - if (err = krun_set_console_output(ctx_id, "/dev/stdout")) { + if (err = krun_add_virtio_console_default(ctx_id, -1, STDOUT_FILENO, -1)) { errno = -err; - perror("Error configuring the console output"); + perror("Error configuring the console"); return -1; } diff --git a/tests/test_cases/src/common_freebsd.rs b/tests/test_cases/src/common_freebsd.rs index 274806fd4..5f3cdb0e4 100644 --- a/tests/test_cases/src/common_freebsd.rs +++ b/tests/test_cases/src/common_freebsd.rs @@ -9,8 +9,8 @@ use std::process::Command; use std::time::{SystemTime, UNIX_EPOCH}; use crate::test_net::get_krun_add_net_unixgram; -use crate::test_net::gvproxy::{Gvproxy, wait_for_socket}; -use crate::{TestSetup, krun_call}; +use crate::test_net::gvproxy::{wait_for_socket, Gvproxy}; +use crate::{krun_call, TestSetup}; use krun_sys::*; pub struct FreeBsdAssets { @@ -209,7 +209,6 @@ unsafe fn do_setup_and_enter( CString::new(config_iso.as_os_str().as_bytes()).context("CString::new")?; // FreeBSD requires a serial console; virtio console is not supported. - krun_call!(krun_disable_implicit_console(ctx))?; krun_call!(krun_add_serial_console_default(ctx, serial_read_fd, 1))?; // Kernel cmdline: mount vtbd0 as root via cd9660 and hand off to init-freebsd. diff --git a/tests/test_cases/src/test_augmentfs.rs b/tests/test_cases/src/test_augmentfs.rs index a3d87c636..46643b4f3 100644 --- a/tests/test_cases/src/test_augmentfs.rs +++ b/tests/test_cases/src/test_augmentfs.rs @@ -21,6 +21,7 @@ mod host { use crate::{krun_call, krun_call_u32}; use krun_sys::*; use std::ffi::CString; + use std::os::fd::AsRawFd; use std::ptr::null_mut; impl Test for TestAugmentFs { @@ -51,6 +52,12 @@ mod host { krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; // Disable the implicit init — we'll inject it ourselves. krun_call!(krun_disable_implicit_init(ctx))?; diff --git a/tests/test_cases/src/test_net/mod.rs b/tests/test_cases/src/test_net/mod.rs index a27637e13..75cafc1a6 100644 --- a/tests/test_cases/src/test_net/mod.rs +++ b/tests/test_cases/src/test_net/mod.rs @@ -92,6 +92,7 @@ mod host { use crate::common::setup_fs_and_enter; use crate::{Test, TestOutcome, TestSetup, krun_call, krun_call_u32}; use krun_sys::*; + use std::os::fd::AsRawFd; use std::thread; impl Test for TestNet { @@ -122,13 +123,24 @@ mod host { thread::spawn(move || tcp_tester.run_server(listener)); unsafe { - krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; // Backend-specific setup (self.setup_backend)(ctx, &test_setup)?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; setup_fs_and_enter(ctx, test_setup)?; } Ok(()) diff --git a/tests/test_cases/src/test_net_perf.rs b/tests/test_cases/src/test_net_perf.rs index f43c4020a..1de42842c 100644 --- a/tests/test_cases/src/test_net_perf.rs +++ b/tests/test_cases/src/test_net_perf.rs @@ -155,6 +155,7 @@ mod host { use crate::common::setup_fs_and_enter; use crate::{Test, TestOutcome, TestSetup, krun_call, krun_call_u32}; use krun_sys::*; + use std::os::fd::AsRawFd; use std::process::{Child, Command, Stdio}; const CONTAINERFILE: &str = "\ @@ -360,6 +361,12 @@ RUN dnf install -y iperf3 && dnf clean all // Backend-specific setup (self.setup_backend)(ctx, &test_setup)?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; setup_fs_and_enter(ctx, test_setup)?; } Ok(()) diff --git a/tests/test_cases/src/test_pjdfstest.rs b/tests/test_cases/src/test_pjdfstest.rs index 5bb6cafe0..a4af584c8 100644 --- a/tests/test_cases/src/test_pjdfstest.rs +++ b/tests/test_cases/src/test_pjdfstest.rs @@ -9,6 +9,7 @@ mod host { use crate::{ShouldRun, Test, TestOutcome, TestSetup, krun_call, krun_call_u32}; use krun_sys::*; use std::ffi::CString; + use std::os::fd::AsRawFd; use macros::env_or_default; @@ -54,6 +55,12 @@ mod host { unsafe { let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 2, 1024))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; setup_fs_and_enter_with_env(ctx, test_setup, &[host_os_env.as_c_str()])?; } Ok(()) diff --git a/tests/test_cases/src/test_root_disk_remount.rs b/tests/test_cases/src/test_root_disk_remount.rs index 81c5623e4..388b68bc3 100644 --- a/tests/test_cases/src/test_root_disk_remount.rs +++ b/tests/test_cases/src/test_root_disk_remount.rs @@ -18,6 +18,7 @@ mod host { use krun_sys::*; use nix::libc; use std::ffi::CString; + use std::os::fd::AsRawFd; use std::process::Command; use std::ptr::null; @@ -106,6 +107,12 @@ mod host { ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; let argv = [test_case.as_ptr(), null()]; let envp = [null()]; diff --git a/tests/test_cases/src/test_tsi_tcp_guest_connect.rs b/tests/test_cases/src/test_tsi_tcp_guest_connect.rs index 158810c48..523447748 100644 --- a/tests/test_cases/src/test_tsi_tcp_guest_connect.rs +++ b/tests/test_cases/src/test_tsi_tcp_guest_connect.rs @@ -24,6 +24,7 @@ mod host { use crate::{Test, TestSetup}; use crate::{krun_call, krun_call_u32}; use krun_sys::*; + use std::os::fd::AsRawFd; use std::thread; impl Test for TestTsiTcpGuestConnect { @@ -31,9 +32,20 @@ mod host { let listener = self.tcp_tester.create_server_socket(); thread::spawn(move || self.tcp_tester.run_server(listener)); unsafe { - krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; setup_fs_and_enter(ctx, test_setup)?; } Ok(()) diff --git a/tests/test_cases/src/test_tsi_tcp_guest_listen.rs b/tests/test_cases/src/test_tsi_tcp_guest_listen.rs index 4a0f9fd62..adf6aa43e 100644 --- a/tests/test_cases/src/test_tsi_tcp_guest_listen.rs +++ b/tests/test_cases/src/test_tsi_tcp_guest_listen.rs @@ -23,6 +23,7 @@ mod host { use crate::{Test, TestSetup, krun_call, krun_call_u32}; use krun_sys::*; use std::ffi::CString; + use std::os::fd::AsRawFd; use std::ptr::null; use std::thread; @@ -33,7 +34,12 @@ mod host { self.tcp_tester.run_client(); }); - krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; let port_mapping = format!("{PORT}:{PORT}"); let port_mapping = CString::new(port_mapping).unwrap(); @@ -41,6 +47,12 @@ mod host { krun_call!(krun_set_port_map(ctx, port_map.as_ptr()))?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; setup_fs_and_enter(ctx, test_setup)?; println!("OK"); } diff --git a/tests/test_cases/src/test_virtiofs_misc.rs b/tests/test_cases/src/test_virtiofs_misc.rs index c59eeb8c7..af6817489 100644 --- a/tests/test_cases/src/test_virtiofs_misc.rs +++ b/tests/test_cases/src/test_virtiofs_misc.rs @@ -13,13 +13,25 @@ mod host { use crate::{krun_call, krun_call_u32}; use krun_sys::*; use std::io::Read; + use std::os::fd::AsRawFd; impl Test for TestVirtioFsMisc { fn start_vm(self: Box, test_setup: TestSetup) -> anyhow::Result<()> { unsafe { - krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 1024))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; setup_fs_and_enter(ctx, test_setup)?; } Ok(()) diff --git a/tests/test_cases/src/test_virtiofs_root_ro.rs b/tests/test_cases/src/test_virtiofs_root_ro.rs index 21332153e..8e18ac1d5 100644 --- a/tests/test_cases/src/test_virtiofs_root_ro.rs +++ b/tests/test_cases/src/test_virtiofs_root_ro.rs @@ -22,6 +22,7 @@ mod host { use krun_sys::*; use std::ffi::CString; use std::fs; + use std::os::fd::AsRawFd; use std::os::unix::ffi::OsStrExt; use std::ptr::null; @@ -50,6 +51,12 @@ mod host { ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; // Use "/dev/root" tag (KRUN_FS_ROOT_TAG) with read_only=true krun_call!(krun_add_virtiofs3( diff --git a/tests/test_cases/src/test_vm_config.rs b/tests/test_cases/src/test_vm_config.rs index bd5c9addf..a0c0d7795 100644 --- a/tests/test_cases/src/test_vm_config.rs +++ b/tests/test_cases/src/test_vm_config.rs @@ -13,13 +13,25 @@ mod host { use crate::{Test, TestSetup}; use crate::{krun_call, krun_call_u32}; use krun_sys::*; + use std::os::fd::AsRawFd; impl Test for TestVmConfig { fn start_vm(self: Box, test_setup: TestSetup) -> anyhow::Result<()> { unsafe { - krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; krun_call!(krun_set_vm_config(ctx, self.num_cpus, self.ram_mib))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; setup_fs_and_enter(ctx, test_setup)?; } Ok(()) diff --git a/tests/test_cases/src/test_vsock_guest_connect.rs b/tests/test_cases/src/test_vsock_guest_connect.rs index 84fec166d..6e1a27a3b 100644 --- a/tests/test_cases/src/test_vsock_guest_connect.rs +++ b/tests/test_cases/src/test_vsock_guest_connect.rs @@ -41,6 +41,7 @@ mod host { use krun_sys::*; use std::ffi::CString; use std::io::Write; + use std::os::fd::AsRawFd; use std::os::unix::net::UnixListener; use std::os::unix::prelude::OsStrExt; use std::{mem, thread}; @@ -73,6 +74,12 @@ mod host { sock_path_cstr.as_ptr() ))?; krun_call!(krun_set_vm_config(ctx, 1, 1024))?; + krun_call!(krun_add_virtio_console_default( + ctx, + std::io::stdin().as_raw_fd(), + std::io::stdout().as_raw_fd(), + std::io::stderr().as_raw_fd(), + ))?; setup_fs_and_enter(ctx, test_setup)?; } Ok(()) From 618b0b44f544d22fdfe43ca71610a6571105ae3e Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 18:02:16 +0200 Subject: [PATCH 09/12] lib: remove krun_disable_implicit_console, krun_set_console_output, and implicit console Console creation is now fully explicit via krun_add_virtio_console_default or krun_add_virtio_console_multiport. No console is created unless the caller requests one. Remove the disable_implicit_console field from VmResources, the implicit console and serial device creation paths in builder.rs, the console_output field and setter on VmResources, and krun_set_console_output (kept only behind cfg(aws-nitro) where NitroEnclave still needs it). Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- examples/consoles.c | 6 -- include/libkrun.h | 41 +--------- src/libkrun/src/lib.rs | 61 ++++++-------- src/vmm/src/builder.rs | 82 +++---------------- src/vmm/src/resources.rs | 17 +--- .../test_cases/src/test_multiport_console.rs | 9 +- 6 files changed, 52 insertions(+), 164 deletions(-) diff --git a/examples/consoles.c b/examples/consoles.c index fe3a98271..23ee8226f 100644 --- a/examples/consoles.c +++ b/examples/consoles.c @@ -125,12 +125,6 @@ int main(int argc, char *const argv[]) int ctx_id = krun_create_ctx(); if (ctx_id < 0) { errno = -ctx_id; perror("krun_create_ctx"); return 1; } - if ((err = krun_disable_implicit_console(ctx_id))) { - errno = -err; - perror("krun_disable_implicit_console"); - return 1; - } - int console_id = krun_add_virtio_console_multiport(ctx_id); if (console_id < 0) { errno = -console_id; diff --git a/include/libkrun.h b/include/libkrun.h index efcb2af5c..fb3e72a5f 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -911,22 +911,6 @@ int32_t krun_add_vsock(uint32_t ctx_id, uint32_t tsi_features); */ int32_t krun_get_shutdown_eventfd(uint32_t ctx_id); -/** - * Configures the console device to ignore stdin and write the output to "c_filepath". - * - * Arguments: - * "ctx_id" - the configuration context ID. - * "filepath" - a null-terminated string representing the path of the file to write the - * console output. - * - * Notes: - * This API only applies to the implicitly created console. If the implicit console is - * disabled via `krun_disable_implicit_console` the operation is a NOOP. Additionally, - * this API does not have any effect on consoles created via the `krun_add_*_console_default` - * APIs. - */ -int32_t krun_set_console_output(uint32_t ctx_id, const char *c_filepath); - /** * Configures uid which is set right before the microVM is started. * @@ -1037,19 +1021,7 @@ int32_t krun_split_irqchip(uint32_t ctx_id, bool enable); * krun_disable_implicit_* functions now to ease migration. */ -/* - * Do not create an implicit console device in the guest. By using this API, - * libkrun will create zero console devices on behalf of the user. Any - * console devices needed by the user must be added manually via other API - * calls. - * - * Arguments: - * "ctx_id" - the configuration context ID. - * - * Returns: - * Zero on success or a negative error number on failure. - */ -int32_t krun_disable_implicit_console(uint32_t ctx_id); + /** * Do not inject the default init binary (/init.krun) into the root @@ -1170,9 +1142,7 @@ int32_t krun_set_kernel_console(uint32_t ctx_id, const char *console_id); * * The function can be called multiple times for adding multiple virtio-console devices. * In the guest, the consoles will appear in the same order as they are added (that is, - * the first added console will be "hvc0", the second "hvc1", ...). However, if the - * implicit console is not disabled via `krun_disable_implicit_console`, the first - * console created with the function will occupy the "hvc1" ID. + * the first added console will be "hvc0", the second "hvc1", ...). * * This function attaches a multi port virtio-console to the guest. If the input, output and error * file descriptors are TTYs, the device will be created with just a single console port (`err_fd` @@ -1200,9 +1170,7 @@ int32_t krun_add_virtio_console_default(uint32_t ctx_id, * * The function can be called multiple times for adding multiple serial devices. * In the guest, the consoles will appear in the same order as they are added (that is, - * the first added console will be "ttyS0", the second "ttyS1", ...). However, if the - * implicit console is not disabled via `krun_disable_implicit_console` on aarch64 or macOS, - * the first console created with the function will occupy the "ttyS1" ID. + * the first added console will be "ttyS0", the second "ttyS1", ...). * * Arguments: * "ctx_id" - the configuration context ID. @@ -1225,8 +1193,7 @@ int32_t krun_add_serial_console_default(uint32_t ctx_id, * * The function can be called multiple times for adding multiple virtio-console devices. * Each device appears in the guest with port 0 accessible as /dev/hvcN (hvc0, hvc1, etc.) in the order - * devices are added. If the implicit console is not disabled via `krun_disable_implicit_console`, - * the first explicitly added device will occupy the "hvc1" ID. Additional ports within each device + * devices are added. Additional ports within each device * (port 1, 2, ...) appear as /dev/vportNpM character devices. * * Arguments: diff --git a/src/libkrun/src/lib.rs b/src/libkrun/src/lib.rs index 39309c796..50985c60a 100644 --- a/src/libkrun/src/lib.rs +++ b/src/libkrun/src/lib.rs @@ -164,6 +164,8 @@ struct ContextConfig { shutdown_efd: Option, gpu_virgl_flags: Option, gpu_shm_size: Option, + /// Console output path, only used by the aws-nitro TryFrom path. + #[cfg(feature = "aws-nitro")] console_output: Option, vmm_uid: Option, vmm_gid: Option, @@ -1732,27 +1734,12 @@ pub unsafe extern "C" fn krun_add_vhost_user_device( -libc::ENOTSUP } -#[allow(unused_assignments)] -#[unsafe(no_mangle)] -pub extern "C" fn krun_get_shutdown_eventfd(ctx_id: u32) -> i32 { - match CTX_MAP.lock().unwrap().entry(ctx_id) { - Entry::Occupied(mut ctx_cfg) => { - let cfg = ctx_cfg.get_mut(); - if let Some(efd) = cfg.shutdown_efd.as_ref() { - #[cfg(target_os = "macos")] - return efd.get_write_fd(); - #[cfg(target_os = "linux")] - return efd.as_raw_fd(); - } else { - -libc::EINVAL - } - } - Entry::Vacant(_) => -libc::ENOENT, - } -} - +// FIXME: aws-nitro builds its own NitroEnclave from ContextConfig and needs +// the console output path directly. This should be replaced with a proper +// console configuration in the nitro path. #[allow(clippy::missing_safety_doc)] #[unsafe(no_mangle)] +#[cfg(feature = "aws-nitro")] pub unsafe extern "C" fn krun_set_console_output(ctx_id: u32, c_filepath: *const c_char) -> i32 { unsafe { let filepath = match CStr::from_ptr(c_filepath).to_str() { @@ -1775,6 +1762,25 @@ pub unsafe extern "C" fn krun_set_console_output(ctx_id: u32, c_filepath: *const } } +#[allow(unused_assignments)] +#[unsafe(no_mangle)] +pub extern "C" fn krun_get_shutdown_eventfd(ctx_id: u32) -> i32 { + match CTX_MAP.lock().unwrap().entry(ctx_id) { + Entry::Occupied(mut ctx_cfg) => { + let cfg = ctx_cfg.get_mut(); + if let Some(efd) = cfg.shutdown_efd.as_ref() { + #[cfg(target_os = "macos")] + return efd.get_write_fd(); + #[cfg(target_os = "linux")] + return efd.as_raw_fd(); + } else { + -libc::EINVAL + } + } + Entry::Vacant(_) => -libc::ENOENT, + } +} + #[allow(clippy::missing_safety_doc)] #[unsafe(no_mangle)] pub unsafe extern "C" fn krun_set_nested_virt(ctx_id: u32, enabled: bool) -> i32 { @@ -2458,19 +2464,6 @@ pub unsafe extern "C" fn krun_get_default_init( KRUN_SUCCESS } -#[unsafe(no_mangle)] -pub extern "C" fn krun_disable_implicit_console(ctx_id: u32) -> i32 { - match CTX_MAP.lock().unwrap().entry(ctx_id) { - Entry::Occupied(mut ctx_cfg) => { - let cfg = ctx_cfg.get_mut(); - cfg.vmr.disable_implicit_console = true; - } - Entry::Vacant(_) => return -libc::ENOENT, - } - - KRUN_SUCCESS -} - #[unsafe(no_mangle)] pub extern "C" fn krun_disable_implicit_vsock(ctx_id: u32) -> i32 { match CTX_MAP.lock().unwrap().entry(ctx_id) { @@ -2816,10 +2809,6 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 { ctx_cfg.vmr.set_gpu_shm_size(shm_size); } - if let Some(console_output) = ctx_cfg.console_output { - ctx_cfg.vmr.set_console_output(console_output); - } - if let Some(gid) = ctx_cfg.vmm_gid && unsafe { libc::setgid(gid) } != 0 { diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index 21f5ee164..59f3ca7aa 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -14,7 +14,6 @@ use std::fs::File; use std::io::{self, IsTerminal, Read}; use std::os::fd::AsRawFd; use std::os::fd::{BorrowedFd, FromRawFd}; -use std::path::PathBuf; use std::sync::atomic::AtomicI32; use std::sync::{Arc, Mutex}; @@ -728,17 +727,6 @@ pub fn build_microvm( let mut serial_devices = Vec::new(); - // Create the legacy serial device if we're booting from a firmware - if vm_resources.firmware_config.is_some() && !vm_resources.disable_implicit_console { - serial_devices.push(setup_serial_device( - event_manager, - None, - None, - // Uncomment this to get EFI output when debugging EDK2. - //Some(Box::new(io::stdout())), - )?); - }; - // We can't call to `setup_terminal_raw_mode` until `Vmm` is created, // so let's keep track of FDs connected to legacy serial devices here // and set raw mode on them later. @@ -995,29 +983,15 @@ pub fn build_microvm( attach_rng_device(&mut vmm, event_manager, intc.clone())?; } } - let mut console_id = 0; - if !vm_resources.disable_implicit_console { - attach_console_devices( - &mut vmm, - event_manager, - intc.clone(), - vm_resources, - None, - console_id, - )?; - console_id += 1; - } - - for console_cfg in vm_resources.virtio_consoles.iter() { + for (console_id, console_cfg) in vm_resources.virtio_consoles.iter().enumerate() { attach_console_devices( &mut vmm, event_manager, intc.clone(), vm_resources, Some(console_cfg), - console_id, + console_id as u32, )?; - console_id += 1; } #[cfg(not(any(feature = "tee", feature = "aws-nitro")))] @@ -2129,40 +2103,14 @@ fn attach_fs_devices( fn autoconfigure_console_ports( vmm: &mut Vmm, - vm_resources: &VmResources, + _vm_resources: &VmResources, cfg: Option<&DefaultVirtioConsoleConfig>, - creating_implicit_console: bool, ) -> std::result::Result, StartMicrovmError> { - use self::StartMicrovmError::*; - - let mut console_output_path: Option = None; - if let Some(path) = vm_resources.console_output.clone() - && !vm_resources.disable_implicit_console - && creating_implicit_console + let (input_fd, output_fd, err_fd) = match cfg { + Some(c) => (c.input_fd, c.output_fd, c.err_fd), + None => (STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO), + }; { - console_output_path = Some(path) - } - - if let Some(console_output_path) = console_output_path { - let file = File::create(console_output_path).map_err(OpenConsoleFile)?; - // Manually emulate our Legacy behavior: In the case of output_path we have always used the - // stdin to determine the console size - let stdin_fd = unsafe { BorrowedFd::borrow_raw(STDIN_FILENO) }; - let term_fd = if isatty(stdin_fd).is_ok_and(|v| v) { - port_io::term_fd(stdin_fd.as_raw_fd()).unwrap() - } else { - port_io::term_fixed_size(0, 0) - }; - Ok(vec![PortDescription::console( - Some(port_io::input_empty().unwrap()), - Some(port_io::output_file(file).unwrap()), - term_fd, - )]) - } else { - let (input_fd, output_fd, err_fd) = match cfg { - Some(c) => (c.input_fd, c.output_fd, c.err_fd), - None => (STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO), - }; let input_is_terminal = input_fd >= 0 && isatty(unsafe { BorrowedFd::borrow_raw(input_fd) }).unwrap_or(false); let output_is_terminal = @@ -2190,7 +2138,8 @@ fn autoconfigure_console_ports( forwarding_sigint = true; let sigint_input = port_io::PortInputSigInt::new(); let sigint_input_fd = sigint_input.sigint_evt().as_raw_fd(); - register_sigint_handler(sigint_input_fd).map_err(RegisterFsSigwinch)?; + register_sigint_handler(sigint_input_fd) + .map_err(StartMicrovmError::RegisterFsSigwinch)?; Some(Box::new(sigint_input) as _) } #[cfg(not(target_os = "linux"))] @@ -2323,16 +2272,11 @@ fn attach_console_devices( ) -> std::result::Result<(), StartMicrovmError> { use self::StartMicrovmError::*; - let creating_implicit_console = cfg.is_none(); - let ports = match cfg { - None => autoconfigure_console_ports(vmm, vm_resources, None, creating_implicit_console)?, - Some(VirtioConsoleConfigMode::Autoconfigure(autocfg)) => autoconfigure_console_ports( - vmm, - vm_resources, - Some(autocfg), - creating_implicit_console, - )?, + None => autoconfigure_console_ports(vmm, vm_resources, None)?, + Some(VirtioConsoleConfigMode::Autoconfigure(autocfg)) => { + autoconfigure_console_ports(vmm, vm_resources, Some(autocfg))? + } Some(VirtioConsoleConfigMode::Explicit(ports)) => create_explicit_ports(vmm, ports)?, }; diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 4e1a4889e..4ad037687 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -8,6 +8,7 @@ use std::fs::File; #[cfg(feature = "tee")] use std::io::BufReader; use std::os::fd::RawFd; +#[cfg(feature = "tee")] use std::path::PathBuf; #[cfg(feature = "tee")] @@ -189,16 +190,13 @@ pub struct VmResources { #[cfg(feature = "vhost-user")] /// Vhost-user device configurations pub vhost_user_devices: Vec, - /// File to send console output. - pub console_output: Option, /// SMBIOS OEM Strings pub smbios_oem_strings: Option>, /// Whether to enable nested virtualization. pub nested_enabled: bool, /// Whether to enable split irqchip pub split_irqchip: bool, - /// Do not create an implicit console device in the guest - pub disable_implicit_console: bool, + /// The console id to use for console= in the kernel cmdline pub kernel_console: Option, /// Serial consoles to attach to the guest @@ -358,10 +356,6 @@ impl VmResources { self.gpu_shm_size = Some(shm_size); } - pub fn set_console_output(&mut self, console_output: PathBuf) { - self.console_output = Some(console_output); - } - /// Sets a network device to be attached when the VM starts. #[cfg(feature = "net")] pub fn add_network_interface( @@ -400,12 +394,10 @@ impl VmResources { #[cfg(test)] mod tests { - #[cfg(feature = "gpu")] - use crate::resources::DisplayBackendConfig; use crate::resources::VmResources; use crate::vmm_config::kernel_cmdline::KernelCmdlineConfig; use crate::vmm_config::machine_config::{CpuFeaturesTemplate, VmConfig, VmConfigError}; - use crate::vmm_config::vsock::tests::{TempSockFile, default_config}; + use crate::vmm_config::vsock::tests::{default_config, TempSockFile}; use crate::vstate::VcpuConfig; use utils::tempfile::TempFile; @@ -440,11 +432,10 @@ mod tests { input_backends: Vec::new(), #[cfg(feature = "vhost-user")] vhost_user_devices: Vec::new(), - console_output: None, smbios_oem_strings: None, nested_enabled: false, split_irqchip: false, - disable_implicit_console: false, + serial_consoles: Vec::new(), virtio_consoles: Vec::new(), kernel_console: None, diff --git a/tests/test_cases/src/test_multiport_console.rs b/tests/test_cases/src/test_multiport_console.rs index 2948b7369..144cee482 100644 --- a/tests/test_cases/src/test_multiport_console.rs +++ b/tests/test_cases/src/test_multiport_console.rs @@ -50,11 +50,14 @@ mod host { impl Test for TestMultiportConsole { fn start_vm(self: Box, test_setup: TestSetup) -> anyhow::Result<()> { unsafe { - krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; - krun_call!(krun_disable_implicit_console(ctx))?; - // Add a default console (as with other tests this uses stdout for writing "OK") krun_call!(krun_add_virtio_console_default( ctx, From e9f9d8d67ba6e0be1cf95ebb02c39d77a5aad13b Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 18:06:49 +0200 Subject: [PATCH 10/12] tests/examples: use explicit krun_add_vsock everywhere - test_tsi_tcp_guest_connect: add krun_add_vsock(ctx, KRUN_TSI_HIJACK_INET) - test_tsi_tcp_guest_listen: same - test_vsock_guest_connect: add krun_add_vsock(ctx, 0) - chroot_vm.c: replace krun_disable_implicit_vsock + vhost-user with explicit krun_add_vsock when not using vhost-user-vsock No test or example relies on implicit vsock creation anymore. Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- examples/chroot_vm.c | 18 ++++++++++-------- .../src/test_tsi_tcp_guest_connect.rs | 1 + .../src/test_tsi_tcp_guest_listen.rs | 1 + .../test_cases/src/test_vsock_guest_connect.rs | 12 +++++++++--- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/examples/chroot_vm.c b/examples/chroot_vm.c index 9bfce23f6..990c92e13 100644 --- a/examples/chroot_vm.c +++ b/examples/chroot_vm.c @@ -363,14 +363,8 @@ int main(int argc, char *const argv[]) printf("Using vhost-user sound backend at %s\n", cmdline.vhost_user_snd_socket); } - // Configure vhost-user vsock if requested + // Configure vsock: either vhost-user or built-in with TSI if (cmdline.vhost_user_vsock_socket != NULL) { - // Disable the implicit vsock device to avoid conflict - if (!check_krun_error(krun_disable_implicit_vsock(ctx_id), - "Error disabling implicit vsock")) { - return -1; - } - if (!check_krun_error(krun_add_vhost_user_device(ctx_id, KRUN_VIRTIO_DEVICE_VSOCK, cmdline.vhost_user_vsock_socket, NULL, KRUN_VHOST_USER_VSOCK_NUM_QUEUES, @@ -425,8 +419,16 @@ int main(int argc, char *const argv[]) return -1; } + // Add built-in vsock with TSI when not using vhost-user-vsock + if (cmdline.vhost_user_vsock_socket == NULL) { + if (err = krun_add_vsock(ctx_id, KRUN_TSI_HIJACK_INET)) { + errno = -err; + perror("Error configuring vsock"); + return -1; + } + } + // Map port 18000 in the host to 8000 in the guest (if networking uses TSI) - // Skip port mapping when using vhost-user-vsock (TSI requires built-in vsock) if (cmdline.net_mode == NET_MODE_TSI && cmdline.vhost_user_vsock_socket == NULL) { if (err = krun_set_port_map(ctx_id, &port_map[0])) { errno = -err; diff --git a/tests/test_cases/src/test_tsi_tcp_guest_connect.rs b/tests/test_cases/src/test_tsi_tcp_guest_connect.rs index 523447748..3369371e7 100644 --- a/tests/test_cases/src/test_tsi_tcp_guest_connect.rs +++ b/tests/test_cases/src/test_tsi_tcp_guest_connect.rs @@ -39,6 +39,7 @@ mod host { 0 ))?; let ctx = krun_call_u32!(krun_create_ctx())?; + krun_call!(krun_add_vsock(ctx, KRUN_TSI_HIJACK_INET))?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; krun_call!(krun_add_virtio_console_default( ctx, diff --git a/tests/test_cases/src/test_tsi_tcp_guest_listen.rs b/tests/test_cases/src/test_tsi_tcp_guest_listen.rs index adf6aa43e..61c3d9b78 100644 --- a/tests/test_cases/src/test_tsi_tcp_guest_listen.rs +++ b/tests/test_cases/src/test_tsi_tcp_guest_listen.rs @@ -45,6 +45,7 @@ mod host { let port_mapping = CString::new(port_mapping).unwrap(); let port_map = [port_mapping.as_ptr(), null()]; + krun_call!(krun_add_vsock(ctx, KRUN_TSI_HIJACK_INET))?; krun_call!(krun_set_port_map(ctx, port_map.as_ptr()))?; krun_call!(krun_set_vm_config(ctx, 1, 512))?; krun_call!(krun_add_virtio_console_default( diff --git a/tests/test_cases/src/test_vsock_guest_connect.rs b/tests/test_cases/src/test_vsock_guest_connect.rs index 6e1a27a3b..2c101b008 100644 --- a/tests/test_cases/src/test_vsock_guest_connect.rs +++ b/tests/test_cases/src/test_vsock_guest_connect.rs @@ -36,8 +36,8 @@ mod host { use super::*; use crate::common::setup_fs_and_enter; - use crate::{Test, TestSetup}; use crate::{krun_call, krun_call_u32}; + use crate::{Test, TestSetup}; use krun_sys::*; use std::ffi::CString; use std::io::Write; @@ -66,8 +66,14 @@ mod host { thread::spawn(move || server(listener)); unsafe { - krun_call!(krun_init_log(KRUN_LOG_TARGET_DEFAULT, KRUN_LOG_LEVEL_TRACE, KRUN_LOG_STYLE_AUTO, 0))?; + krun_call!(krun_init_log( + KRUN_LOG_TARGET_DEFAULT, + KRUN_LOG_LEVEL_TRACE, + KRUN_LOG_STYLE_AUTO, + 0 + ))?; let ctx = krun_call_u32!(krun_create_ctx())?; + krun_call!(krun_add_vsock(ctx, 0))?; krun_call!(krun_add_vsock_port( ctx, VSOCK_PORT, @@ -93,7 +99,7 @@ mod guest { use crate::Test; use nix::libc::VMADDR_CID_HOST; - use nix::sys::socket::{AddressFamily, SockFlag, SockType, VsockAddr, connect, socket}; + use nix::sys::socket::{connect, socket, AddressFamily, SockFlag, SockType, VsockAddr}; use std::io::Write; use std::os::fd::AsRawFd; From 3c413a19f523f800f536d906f481e8c9aba7c781 Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 18:06:57 +0200 Subject: [PATCH 11/12] lib: remove krun_disable_implicit_vsock and implicit vsock creation Vsock creation is now fully explicit via krun_add_vsock(). No vsock device is created unless the caller requests one. Remove the Implicit variant from VsockConfig, the implicit vsock creation heuristics in krun_start_enter, and krun_disable_implicit_vsock. Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- include/libkrun.h | 18 ------------------ src/libkrun/src/lib.rs | 40 ---------------------------------------- src/vmm/src/resources.rs | 8 +++----- 3 files changed, 3 insertions(+), 63 deletions(-) diff --git a/include/libkrun.h b/include/libkrun.h index fb3e72a5f..496a12a4f 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -882,10 +882,6 @@ int32_t krun_add_vsock_port2(uint32_t ctx_id, /** * Add a vsock device with specified TSI features. * - * By default, libkrun creates a vsock device implicitly with TSI hijacking - * enabled based on heuristics. To use this function, you must first call - * krun_disable_implicit_vsock() to disable the implicit vsock device. - * * Currently only one vsock device is supported. Calling this function * multiple times will return an error. * @@ -1111,20 +1107,6 @@ int32_t krun_fs_add_overlay_file(uint32_t ctx_id, const char *fs_tag, int32_t krun_fs_add_overlay_dir(uint32_t ctx_id, const char *fs_tag, const char *path, uint32_t mode); -/** - * Disable the implicit vsock device. - * - * By default, libkrun creates a vsock device automatically. This function - * disables that behavior entirely - no vsock device will be created. - * - * Arguments: - * "ctx_id" - the configuration context ID. - * - * Returns: - * Zero on success or a negative error number on failure. - */ -int32_t krun_disable_implicit_vsock(uint32_t ctx_id); - /* * Specify the value of `console=` in the kernel commandline. * diff --git a/src/libkrun/src/lib.rs b/src/libkrun/src/lib.rs index 50985c60a..1e40ec73e 100644 --- a/src/libkrun/src/lib.rs +++ b/src/libkrun/src/lib.rs @@ -2464,19 +2464,6 @@ pub unsafe extern "C" fn krun_get_default_init( KRUN_SUCCESS } -#[unsafe(no_mangle)] -pub extern "C" fn krun_disable_implicit_vsock(ctx_id: u32) -> i32 { - match CTX_MAP.lock().unwrap().entry(ctx_id) { - Entry::Occupied(mut ctx_cfg) => { - let cfg = ctx_cfg.get_mut(); - cfg.vsock_config = VsockConfig::Disabled; - } - Entry::Vacant(_) => return -libc::ENOENT, - } - - KRUN_SUCCESS -} - #[unsafe(no_mangle)] pub extern "C" fn krun_add_vsock(ctx_id: u32, tsi_features: u32) -> i32 { let tsi_flags = match TsiFlags::from_bits(tsi_features) { @@ -2773,33 +2760,6 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 { }; ctx_cfg.vmr.set_vsock_device(vsock_device_config).unwrap(); } - VsockConfig::Implicit => { - // Implicit vsock configuration - use heuristics - // Check if TSI should be enabled based on network configuration - #[cfg(feature = "net")] - let enable_tsi = ctx_cfg.vmr.net.list.is_empty(); - #[cfg(not(feature = "net"))] - let enable_tsi = true; - - let has_ipc_map = ctx_cfg.unix_ipc_port_map.is_some(); - - if enable_tsi || has_ipc_map { - let (tsi_flags, host_port_map) = if enable_tsi { - (TsiFlags::HIJACK_INET, ctx_cfg.tsi_port_map) - } else { - (TsiFlags::empty(), None) - }; - - let vsock_device_config = VsockDeviceConfig { - vsock_id: "vsock0".to_string(), - guest_cid: 3, - host_port_map, - unix_ipc_port_map: ctx_cfg.unix_ipc_port_map.clone(), - tsi_flags, - }; - ctx_cfg.vmr.set_vsock_device(vsock_device_config).unwrap(); - } - } } if let Some(virgl_flags) = ctx_cfg.gpu_virgl_flags { diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 4ad037687..639cca4b2 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -132,13 +132,11 @@ pub enum PortConfig { /// Configuration for the vsock device #[derive(Debug, Default, Clone, Eq, PartialEq)] pub enum VsockConfig { - /// Default behavior - vsock created implicitly with heuristics-based TSI + /// No vsock device #[default] - Implicit, + Disabled, /// Explicit configuration with specified TSI features Explicit { tsi_flags: TsiFlags }, - /// Vsock device disabled - Disabled, } /// A data structure that encapsulates the device configurations @@ -397,7 +395,7 @@ mod tests { use crate::resources::VmResources; use crate::vmm_config::kernel_cmdline::KernelCmdlineConfig; use crate::vmm_config::machine_config::{CpuFeaturesTemplate, VmConfig, VmConfigError}; - use crate::vmm_config::vsock::tests::{default_config, TempSockFile}; + use crate::vmm_config::vsock::tests::{TempSockFile, default_config}; use crate::vstate::VcpuConfig; use utils::tempfile::TempFile; From 35f42d9ff7777582e441491dc00e60cca1414c3e Mon Sep 17 00:00:00 2001 From: Matej Hrica Date: Wed, 20 May 2026 18:07:23 +0200 Subject: [PATCH 12/12] include: remove stale implicit resource creation comment All krun_disable_implicit_* functions are gone. The 2.0 API requires explicit resource creation. Assisted-by: OpenCode:claude-opus-4.6 Signed-off-by: Matej Hrica --- include/libkrun.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/libkrun.h b/include/libkrun.h index 496a12a4f..63e1ffb01 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -1010,15 +1010,6 @@ int32_t krun_get_max_vcpus(void); */ int32_t krun_split_irqchip(uint32_t ctx_id, bool enable); -/* - * NOTE: Implicit resource creation is a legacy convenience. The 2.0 API - * (see https://github.com/containers/libkrun/issues/634) will not create - * any implicit resources. Callers should start using the - * krun_disable_implicit_* functions now to ease migration. - */ - - - /** * Do not inject the default init binary (/init.krun) into the root * filesystem. Must be called before krun_set_root().