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)?;
|
let initramfs = create_initramfs(&config.rootfs_path)?;
|
||||||
|
|
||||||
// Get QEMU binary for architecture
|
// 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)
|
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
|
// Detect the best available shell in the rootfs
|
||||||
let shell = crate::utils::detect_shell(&config.rootfs_path);
|
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
|
// -display none suppresses VGA/BIOS output
|
||||||
// -serial mon:stdio connects serial console to terminal with QEMU monitor muxed
|
// -serial mon:stdio connects serial console to terminal with QEMU monitor muxed
|
||||||
// -no-reboot makes QEMU exit when the guest requests poweroff/reboot
|
// -no-reboot makes QEMU exit when the guest requests poweroff/reboot
|
||||||
let args = vec![
|
let mut args = vec![
|
||||||
"-kernel".to_string(),
|
"-kernel".to_string(),
|
||||||
config.kernel_path.to_string_lossy().to_string(),
|
config.kernel_path.to_string_lossy().to_string(),
|
||||||
"-initrd".to_string(),
|
"-initrd".to_string(),
|
||||||
@@ -113,6 +121,13 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
|
|||||||
"virtio-net-pci,netdev=net0".to_string(),
|
"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
|
// Execute QEMU
|
||||||
let status = Command::new(&qemu_bin)
|
let status = Command::new(&qemu_bin)
|
||||||
.args(&args)
|
.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
|
/// Create an uncompressed cpio initramfs from a directory
|
||||||
fn create_initramfs(rootfs: &PathBuf) -> Result<PathBuf> {
|
fn create_initramfs(rootfs: &PathBuf) -> Result<PathBuf> {
|
||||||
// Create a temporary file for the initramfs (uncompressed cpio)
|
// Create a temporary file for the initramfs (uncompressed cpio)
|
||||||
|
|||||||
Reference in New Issue
Block a user