diff --git a/src/devices/src/fdt/aarch64.rs b/src/devices/src/fdt/aarch64.rs index 8ef879fb7..3fe9609a0 100644 --- a/src/devices/src/fdt/aarch64.rs +++ b/src/devices/src/fdt/aarch64.rs @@ -98,7 +98,7 @@ pub fn create_fdt( fdt.property_u32("interrupt-parent", GIC_PHANDLE)?; create_cpu_nodes(&mut fdt, &vcpu_mpidr)?; create_memory_node(&mut fdt, guest_mem, arch_memory_info)?; - create_chosen_node(&mut fdt, cmdline, initrd)?; + create_chosen_node(&mut fdt, cmdline, initrd, device_info)?; create_gic_node(&mut fdt, gic_device)?; create_timer_node(&mut fdt)?; create_clock_node(&mut fdt)?; @@ -189,14 +189,24 @@ fn create_memory_node( Ok(()) } -fn create_chosen_node( +fn create_chosen_node( fdt: &mut FdtWriter, cmdline: &str, initrd: &Option, + dev_info: &HashMap<(DeviceType, String), T>, ) -> Result<()> { let chosen_node = fdt.begin_node("chosen")?; fdt.property_string("bootargs", cmdline)?; + // If we have a legacy serial device, tell the guest this is the default console. + // Clever guests will still switch to a better console (like virtio-console) if + // it becomes available later, and this gives us a good fallback. + for ((device_type, _device_id), info) in dev_info { + if device_type == &DeviceType::Serial { + fdt.property_string("stdout-path", &format!("/uart@{:x}", info.addr()))?; + } + } + if let Some(initrd_config) = initrd { fdt.property_u64("linux,initrd-start", initrd_config.address.raw_value())?; fdt.property_u64( @@ -324,7 +334,14 @@ fn create_serial_node( dev_info: &T, ) -> Result<()> { let serial_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]); + #[cfg(target_os = "linux")] let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]); + #[cfg(target_os = "macos")] + let irq = generate_prop32(&[ + GIC_FDT_IRQ_TYPE_SPI, + dev_info.irq() - 32, + IRQ_TYPE_EDGE_RISING, + ]); let node = fdt.begin_node(&format!("uart@{:x}", dev_info.addr()))?; fdt.property_string("compatible", "arm,pl011")?; diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index c9f5ec64d..fee24ed01 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -870,6 +870,7 @@ pub fn build_microvm( &vm, &mut mmio_device_manager, &mut kernel_cmdline, + intc.clone(), serial_devices, )?; } @@ -1623,11 +1624,12 @@ fn attach_legacy_devices( vm: &Vm, mmio_device_manager: &mut MMIODeviceManager, kernel_cmdline: &mut kernel::cmdline::Cmdline, + intc: IrqChip, serial: Vec>>, ) -> std::result::Result<(), StartMicrovmError> { for s in serial { mmio_device_manager - .register_mmio_serial(vm.fd(), kernel_cmdline, s) + .register_mmio_serial(vm.fd(), kernel_cmdline, intc.clone(), s) .map_err(Error::RegisterMMIODevice) .map_err(StartMicrovmError::Internal)?; } diff --git a/src/vmm/src/device_manager/kvm/mmio.rs b/src/vmm/src/device_manager/kvm/mmio.rs index 56d1ae05b..eef147c2f 100644 --- a/src/vmm/src/device_manager/kvm/mmio.rs +++ b/src/vmm/src/device_manager/kvm/mmio.rs @@ -11,6 +11,8 @@ use std::{fmt, io}; #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] use devices::fdt::DeviceInfoForFDT; +#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] +use devices::legacy::IrqChip; use devices::{BusDevice, DeviceType}; use kernel::cmdline as kernel_cmdline; use kvm_ioctls::{IoEventAddress, VmFd}; @@ -192,6 +194,7 @@ impl MMIODeviceManager { &mut self, vm: &VmFd, cmdline: &mut kernel_cmdline::Cmdline, + intc: IrqChip, serial: Arc>, ) -> Result<()> { if self.irq > self.last_irq { @@ -201,6 +204,8 @@ impl MMIODeviceManager { vm.register_irqfd(serial.lock().unwrap().interrupt_evt(), self.irq) .map_err(Error::RegisterIrqFd)?; + serial.lock().unwrap().set_intc(intc); + self.bus .insert(serial, self.mmio_base, MMIO_LEN) .map_err(Error::BusError)?;