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);
|
veprintln!(" Kernel append: {}", kernel_append);
|
||||||
|
|
||||||
// Build QEMU arguments
|
// Build QEMU arguments
|
||||||
|
// -machine virt is selected explicitly on riscv64 (see machine_for_arch)
|
||||||
// -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 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(),
|
"-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(),
|
||||||
@@ -146,7 +152,7 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
|
|||||||
"user,id=net0".to_string(),
|
"user,id=net0".to_string(),
|
||||||
"-device".to_string(),
|
"-device".to_string(),
|
||||||
"virtio-net-pci,netdev=net0".to_string(),
|
"virtio-net-pci,netdev=net0".to_string(),
|
||||||
];
|
]);
|
||||||
|
|
||||||
// Add KVM acceleration if available
|
// Add KVM acceleration if available
|
||||||
if use_kvm {
|
if use_kvm {
|
||||||
@@ -182,6 +188,19 @@ fn qemu_binary_for_arch(arch: &str) -> String {
|
|||||||
format!("qemu-system-{}", arch_enum.qemu_system_name())
|
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
|
/// Get architecture suffix for package names
|
||||||
fn get_arch_package_suffix(arch: &str) -> &'static str {
|
fn get_arch_package_suffix(arch: &str) -> &'static str {
|
||||||
crate::utils::Arch::from_str(arch).qemu_package_suffix()
|
crate::utils::Arch::from_str(arch).qemu_package_suffix()
|
||||||
@@ -601,6 +620,21 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use std::io::Read as _;
|
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
|
/// 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>)> {
|
fn parse_cpio(archive: Vec<u8>) -> Vec<(String, u32, u32, u32, u32, Vec<u8>)> {
|
||||||
let mut cursor = std::io::Cursor::new(archive);
|
let mut cursor = std::io::Cursor::new(archive);
|
||||||
|
|||||||
Reference in New Issue
Block a user