Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 47 additions & 18 deletions crates/krun/src/bin/krun.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::env;
use std::ffi::{c_char, CString};
use std::io::Write;
use std::os::fd::{IntoRawFd, OwnedFd};
use std::path::Path;
use std::{cmp, env};

use anyhow::{anyhow, Context, Result};
use krun::cli_options::options;
Expand All @@ -12,7 +12,7 @@ use krun::launch::{launch_or_lock, LaunchResult};
use krun::net::{connect_to_passt, start_passt};
use krun::types::MiB;
use krun_sys::{
krun_add_disk, krun_add_vsock_port, krun_create_ctx, krun_set_env, krun_set_gpu_options,
krun_add_disk, krun_add_vsock_port, krun_create_ctx, krun_set_env, krun_set_gpu_options2,
krun_set_log_level, krun_set_passt_fd, krun_set_root, krun_set_vm_config, krun_set_workdir,
krun_start_enter, VIRGLRENDERER_DRM, VIRGLRENDERER_THREAD_SYNC,
VIRGLRENDERER_USE_ASYNC_FENCE_CB, VIRGLRENDERER_USE_EGL,
Expand Down Expand Up @@ -120,13 +120,38 @@ fn main() -> Result<()> {
.or_else(|_err| get_fallback_cores())?
};
let num_vcpus = cpu_list.iter().fold(0, |acc, cpus| acc + cpus.len()) as u8;

let sysinfo = sysinfo().context("Failed to get system information")?;
let ram_total_mib = (sysinfo.ram_total() / (1024 * 1024)) as u32;

let ram_mib = if let Some(ram_mib) = options.mem {
ram_mib
} else {
let sysinfo = sysinfo().context("Failed to get system information")?;
let ram_total = sysinfo.ram_total() / 1024 / 1024;
cmp::min(MiB::from((ram_total as f64 * 0.8) as u32), MiB::from(32768))
// By default, set the microVM RAM to be 80% of the system's RAM.
let guest_ram = (ram_total_mib as f64 * 0.8) as u32;
// Ensure we leave 3072 MiB free for the host + VRAM to avoid
// compromising the host's stability. This mainly applies to systems
// with 8GB of RAM.
let guest_ram = if ram_total_mib
.checked_sub(guest_ram)
.context("Failed to calculate the amount of free RAM")?
< 3072
{
ram_total_mib
.checked_sub(3072)
.context("Systems with less than 3072 MiB of RAM are not supported")?
} else {
guest_ram
};
MiB::from(guest_ram)
};
// VRAM is actually the SHM window for virtio-gpu. The userspace drivers in the
// guest are expected to be conservative and tell applications that the amount
// of VRAM is just a percentage of the guest's RAM, so we can afford being more
// aggressive here and set the window to be as large as the system's RAM, leaving
// some room for dealing with potential fragmentation.
let vram_mib = options.vram.unwrap_or(MiB::from(ram_total_mib as u32));

// Bind the microVM to the specified CPU cores.
let mut cpuset = CpuSet::new();
for cpus in cpu_list {
Expand All @@ -146,6 +171,23 @@ fn main() -> Result<()> {
return Err(err)
.context("Failed to configure the number of vCPUs and/or the amount of RAM");
}

let virgl_flags = VIRGLRENDERER_USE_EGL
| VIRGLRENDERER_DRM
| VIRGLRENDERER_THREAD_SYNC
| VIRGLRENDERER_USE_ASYNC_FENCE_CB;
// SAFETY: Safe as no pointers involved.
let err = unsafe {
krun_set_gpu_options2(
ctx_id,
virgl_flags,
(u32::from(vram_mib) as u64) * 1024 * 1024,
)
};
if err < 0 {
let err = Errno::from_raw_os_error(-err);
return Err(err).context("Failed to configure gpu");
}
}

{
Expand Down Expand Up @@ -190,19 +232,6 @@ fn main() -> Result<()> {
}
}

{
let virgl_flags = VIRGLRENDERER_USE_EGL
| VIRGLRENDERER_DRM
| VIRGLRENDERER_THREAD_SYNC
| VIRGLRENDERER_USE_ASYNC_FENCE_CB;
// SAFETY: Safe as no pointers involved.
let err = unsafe { krun_set_gpu_options(ctx_id, virgl_flags) };
if err < 0 {
let err = Errno::from_raw_os_error(-err);
return Err(err).context("Failed to configure gpu");
}
}

{
let passt_fd: OwnedFd = if let Some(passt_socket) = options.passt_socket {
connect_to_passt(passt_socket)
Expand Down
13 changes: 13 additions & 0 deletions crates/krun/src/cli_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub struct Options {
pub cpu_list: Vec<Range<u16>>,
pub env: Vec<(String, Option<String>)>,
pub mem: Option<MiB>,
pub vram: Option<MiB>,
pub passt_socket: Option<PathBuf>,
pub server_port: u32,
pub fex_images: Vec<String>,
Expand Down Expand Up @@ -67,6 +68,17 @@ pub fn options() -> OptionParser<Options> {
)
.argument("MEM")
.optional();
let vram = long("vram")
.help(
"The amount of Video RAM, in MiB, that will be available to this microVM.
The memory configured for the microVM will not be reserved
immediately. Instead, it will be provided as the guest demands
it, and will be returned to the host once the guest releases
the underlying resources.
[default: same as the total amount of RAM in the system]",
)
.argument("VRAM")
.optional();
let fex_images = long("fex-image")
.short('f')
.help(
Expand Down Expand Up @@ -97,6 +109,7 @@ pub fn options() -> OptionParser<Options> {
cpu_list,
env,
mem,
vram,
passt_socket,
server_port,
fex_images,
Expand Down