fix(qemu): select the virt machine for riscv64
qemu-system-riscv64's default machine is spike, not virt: spike has no PCI bus, so virtio-net-pci failed with "No 'PCI' bus found", and no 16550 UART, so console=ttyS0 output went nowhere. Pass -machine virt explicitly for riscv64; other architectures keep their emulator's default.
This commit is contained in:
@@ -125,10 +125,16 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
|
||||
veprintln!(" Kernel append: {}", kernel_append);
|
||||
|
||||
// Build QEMU arguments
|
||||
// -machine virt is selected explicitly on riscv64 (see machine_for_arch)
|
||||
// -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 mut args = vec![
|
||||
let mut args: Vec<String> = Vec::new();
|
||||
if let Some(machine) = machine_for_arch(&config.arch) {
|
||||
args.push("-machine".to_string());
|
||||
args.push(machine.to_string());
|
||||
}
|
||||
args.extend(vec![
|
||||
"-kernel".to_string(),
|
||||
config.kernel_path.to_string_lossy().to_string(),
|
||||
"-initrd".to_string(),
|
||||
@@ -146,7 +152,7 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
|
||||
"user,id=net0".to_string(),
|
||||
"-device".to_string(),
|
||||
"virtio-net-pci,netdev=net0".to_string(),
|
||||
];
|
||||
]);
|
||||
|
||||
// Add KVM acceleration if available
|
||||
if use_kvm {
|
||||
@@ -182,6 +188,19 @@ fn qemu_binary_for_arch(arch: &str) -> String {
|
||||
format!("qemu-system-{}", arch_enum.qemu_system_name())
|
||||
}
|
||||
|
||||
/// Get the QEMU machine to select for the target architecture, if any.
|
||||
///
|
||||
/// qemu-system-riscv64's default machine is `spike`, which has neither a
|
||||
/// PCI bus (virtio-net-pci fails with "No 'PCI' bus found") nor a 16550
|
||||
/// UART (console=ttyS0 output goes nowhere); the `virt` board has both,
|
||||
/// plus bundled OpenSBI firmware for -kernel boot.
|
||||
fn machine_for_arch(arch: &str) -> Option<&'static str> {
|
||||
match crate::utils::Arch::from_str(arch) {
|
||||
crate::utils::Arch::Riscv64 => Some("virt"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get architecture suffix for package names
|
||||
fn get_arch_package_suffix(arch: &str) -> &'static str {
|
||||
crate::utils::Arch::from_str(arch).qemu_package_suffix()
|
||||
@@ -601,6 +620,21 @@ mod tests {
|
||||
use super::*;
|
||||
use std::io::Read as _;
|
||||
|
||||
#[test]
|
||||
fn test_machine_for_arch() {
|
||||
// riscv64 must select the virt machine explicitly: the
|
||||
// qemu-system-riscv64 default is `spike`, which has no PCI bus and
|
||||
// no 16550 UART
|
||||
assert_eq!(machine_for_arch("riscv64"), Some("virt"));
|
||||
// Other architectures keep their emulator's default machine
|
||||
assert_eq!(machine_for_arch("amd64"), None);
|
||||
assert_eq!(machine_for_arch("x86_64"), None);
|
||||
assert_eq!(machine_for_arch("arm64"), None);
|
||||
assert_eq!(machine_for_arch("aarch64"), None);
|
||||
assert_eq!(machine_for_arch("ppc64le"), None);
|
||||
assert_eq!(machine_for_arch("s390x"), None);
|
||||
}
|
||||
|
||||
/// Parse a newc cpio archive into (name, ino, mode, nlink, file_size, data) tuples
|
||||
fn parse_cpio(archive: Vec<u8>) -> Vec<(String, u32, u32, u32, u32, Vec<u8>)> {
|
||||
let mut cursor = std::io::Cursor::new(archive);
|
||||
|
||||
Reference in New Issue
Block a user