feat: enable kvm with --kernel if relevant

This commit is contained in:
2026-06-17 16:42:34 +02:00
parent 09661ec9e0
commit 6bd6f2cf77
+70 -2
View File
@@ -39,7 +39,7 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
));
}
// Create a gzipped cpio initramfs from the rootfs
// Create an uncompressed cpio initramfs from the rootfs
let initramfs = create_initramfs(&config.rootfs_path)?;
// Get QEMU binary for architecture
@@ -54,6 +54,14 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
qemu_bin, get_arch_package_suffix(&config.arch), get_arch_package_suffix(&config.arch), get_arch_package_suffix(&config.arch)
))?;
// Check if we can use KVM acceleration
let use_kvm = can_use_kvm(&config.arch);
if use_kvm {
veprintln!(" KVM: enabled (native acceleration)");
} else {
veprintln!(" KVM: disabled (using software emulation)");
}
// Detect the best available shell in the rootfs
let shell = crate::utils::detect_shell(&config.rootfs_path);
@@ -93,7 +101,7 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
// -display none suppresses VGA/BIOS output
// -serial mon:stdio connects serial console to terminal with QEMU monitor muxed
// -no-reboot makes QEMU exit when the guest requests poweroff/reboot
let args = vec![
let mut args = vec![
"-kernel".to_string(),
config.kernel_path.to_string_lossy().to_string(),
"-initrd".to_string(),
@@ -113,6 +121,13 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
"virtio-net-pci,netdev=net0".to_string(),
];
// Add KVM acceleration if available
if use_kvm {
args.push("-enable-kvm".to_string());
args.push("-cpu".to_string());
args.push("host".to_string());
}
// Execute QEMU
let status = Command::new(&qemu_bin)
.args(&args)
@@ -160,6 +175,59 @@ fn get_arch_package_suffix(arch: &str) -> &str {
}
}
/// Check if KVM acceleration can be used for the target architecture
fn can_use_kvm(target_arch: &str) -> bool {
// Normalize both to canonical form (uname -m style) and compare
let host_arch = get_host_arch();
let target_canonical = normalize_arch(target_arch);
if host_arch != target_canonical {
return false;
}
// Check if /dev/kvm exists and is accessible
std::fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/kvm")
.is_ok()
}
/// Normalize architecture name to canonical form (uname -m style)
fn normalize_arch(arch: &str) -> String {
match arch {
"amd64" => "x86_64",
"arm64" => "aarch64",
"ppc64el" => "ppc64le",
"armhf" => "armv7l",
other => other,
}.to_string()
}
/// Get the host system architecture (uname -m style)
fn get_host_arch() -> String {
// Use uname to get the machine hardware name
match std::process::Command::new("uname").arg("-m").output() {
Ok(output) => {
String::from_utf8_lossy(&output.stdout).trim().to_string()
}
Err(_) => {
// Fallback: use libc uname
let mut utsname: libc::utsname = unsafe { std::mem::zeroed() };
if unsafe { libc::uname(&mut utsname) } == 0 {
let machine: Vec<u8> = utsname.machine
.iter()
.take_while(|&&c| c != 0)
.map(|&c| c as u8)
.collect();
String::from_utf8_lossy(&machine).into_owned()
} else {
"unknown".to_string()
}
}
}
}
/// Create an uncompressed cpio initramfs from a directory
fn create_initramfs(rootfs: &PathBuf) -> Result<PathBuf> {
// Create a temporary file for the initramfs (uncompressed cpio)