Skip to content

Commit d661705

Browse files
slpalyssarosenzweig
authored andcommitted
krun: set the vRAM size for the microVM
Starting v1.9.5, libkrun allows configuring the size of the SHM window for virtio-gpu, which acts as a pseudo-vram (previously it was hardcoded to a conservative 8GB). Let's use that feature to configure the vRAM of the microVM to a reasonable value. Since we expect userspace drivers in the guest to be conservative for us, telling appliations that vRAM is just a percentage of the guest's RAM, let's just set vRAM to be the same as the total amount of RAM in the system, leaving some room for potential fragmentation. Also, introduce the "--vram" command flag to allow users to override the default value. While there, also remove the 32 GB limit, since libkrun does support guests larger than that. Signed-off-by: Sergio Lopez <[email protected]>
1 parent ed3681b commit d661705

2 files changed

Lines changed: 47 additions & 22 deletions

File tree

crates/krun/src/bin/krun.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
use std::env;
12
use std::ffi::{c_char, CString};
23
use std::io::Write;
34
use std::os::fd::{IntoRawFd, OwnedFd};
45
use std::path::Path;
5-
use std::{cmp, env};
66

77
use anyhow::{anyhow, Context, Result};
88
use krun::cli_options::options;
@@ -12,7 +12,7 @@ use krun::launch::{launch_or_lock, LaunchResult};
1212
use krun::net::{connect_to_passt, start_passt};
1313
use krun::types::MiB;
1414
use krun_sys::{
15-
krun_add_disk, krun_add_vsock_port, krun_create_ctx, krun_set_env, krun_set_gpu_options,
15+
krun_add_disk, krun_add_vsock_port, krun_create_ctx, krun_set_env, krun_set_gpu_options2,
1616
krun_set_log_level, krun_set_passt_fd, krun_set_root, krun_set_vm_config, krun_set_workdir,
1717
krun_start_enter, VIRGLRENDERER_DRM, VIRGLRENDERER_THREAD_SYNC,
1818
VIRGLRENDERER_USE_ASYNC_FENCE_CB, VIRGLRENDERER_USE_EGL,
@@ -120,13 +120,21 @@ fn main() -> Result<()> {
120120
.or_else(|_err| get_fallback_cores())?
121121
};
122122
let num_vcpus = cpu_list.iter().fold(0, |acc, cpus| acc + cpus.len()) as u8;
123-
let ram_mib = if let Some(ram_mib) = options.mem {
124-
ram_mib
125-
} else {
126-
let sysinfo = sysinfo().context("Failed to get system information")?;
127-
let ram_total = sysinfo.ram_total() / 1024 / 1024;
128-
cmp::min(MiB::from((ram_total as f64 * 0.8) as u32), MiB::from(32768))
129-
};
123+
124+
let sysinfo = sysinfo().context("Failed to get system information")?;
125+
let ram_total_mib = (sysinfo.ram_total() / (1024 * 1024)) as u32;
126+
127+
// By default, set the microVM RAM to be 80% of the system's RAM.
128+
let ram_mib = options
129+
.mem
130+
.unwrap_or(MiB::from((ram_total_mib as f64 * 0.8) as u32));
131+
// VRAM is actually the SHM window for virtio-gpu. The userspace drivers in the
132+
// guest are expected to be conservative and tell applications that the amount
133+
// of VRAM is just a percentage of the guest's RAM, so we can afford being more
134+
// aggressive here and set the window to be as large as the system's RAM, leaving
135+
// some room for dealing with potential fragmentation.
136+
let vram_mib = options.vram.unwrap_or(MiB::from(ram_total_mib as u32));
137+
130138
// Bind the microVM to the specified CPU cores.
131139
let mut cpuset = CpuSet::new();
132140
for cpus in cpu_list {
@@ -146,6 +154,23 @@ fn main() -> Result<()> {
146154
return Err(err)
147155
.context("Failed to configure the number of vCPUs and/or the amount of RAM");
148156
}
157+
158+
let virgl_flags = VIRGLRENDERER_USE_EGL
159+
| VIRGLRENDERER_DRM
160+
| VIRGLRENDERER_THREAD_SYNC
161+
| VIRGLRENDERER_USE_ASYNC_FENCE_CB;
162+
// SAFETY: Safe as no pointers involved.
163+
let err = unsafe {
164+
krun_set_gpu_options2(
165+
ctx_id,
166+
virgl_flags,
167+
(u32::from(vram_mib) as u64) * 1024 * 1024,
168+
)
169+
};
170+
if err < 0 {
171+
let err = Errno::from_raw_os_error(-err);
172+
return Err(err).context("Failed to configure gpu");
173+
}
149174
}
150175

151176
{
@@ -191,19 +216,6 @@ fn main() -> Result<()> {
191216
}
192217
}
193218

194-
{
195-
let virgl_flags = VIRGLRENDERER_USE_EGL
196-
| VIRGLRENDERER_DRM
197-
| VIRGLRENDERER_THREAD_SYNC
198-
| VIRGLRENDERER_USE_ASYNC_FENCE_CB;
199-
// SAFETY: Safe as no pointers involved.
200-
let err = unsafe { krun_set_gpu_options(ctx_id, virgl_flags) };
201-
if err < 0 {
202-
let err = Errno::from_raw_os_error(-err);
203-
return Err(err).context("Failed to configure gpu");
204-
}
205-
}
206-
207219
{
208220
let passt_fd: OwnedFd = if let Some(passt_socket) = options.passt_socket {
209221
connect_to_passt(passt_socket)

crates/krun/src/cli_options.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub struct Options {
1111
pub cpu_list: Vec<Range<u16>>,
1212
pub env: Vec<(String, Option<String>)>,
1313
pub mem: Option<MiB>,
14+
pub vram: Option<MiB>,
1415
pub passt_socket: Option<PathBuf>,
1516
pub server_port: u32,
1617
pub fex_images: Vec<String>,
@@ -67,6 +68,17 @@ pub fn options() -> OptionParser<Options> {
6768
)
6869
.argument("MEM")
6970
.optional();
71+
let vram = long("vram")
72+
.help(
73+
"The amount of Video RAM, in MiB, that will be available to this microVM.
74+
The memory configured for the microVM will not be reserved
75+
immediately. Instead, it will be provided as the guest demands
76+
it, and will be returned to the host once the guest releases
77+
the underlying resources.
78+
[default: same as the total amount of RAM in the system]",
79+
)
80+
.argument("VRAM")
81+
.optional();
7082
let fex_images = long("fex-image")
7183
.short('f')
7284
.help(
@@ -97,6 +109,7 @@ pub fn options() -> OptionParser<Options> {
97109
cpu_list,
98110
env,
99111
mem,
112+
vram,
100113
passt_socket,
101114
server_port,
102115
fex_images,

0 commit comments

Comments
 (0)