feat: enable kvm with --kernel if relevant
This commit is contained in:
+70
-2
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user