From 75e22ff34ebbfbff78fec32bc6adf257ebc2070f Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Mon, 20 Jan 2020 15:28:58 +0100 Subject: [PATCH] vmm: Use LegacyUserspaceInterruptGroup for serial device This commit replaces the way legacy interrupts were handled with the brand new implementation of the legacy InterruptSourceGroup for KVM. Signed-off-by: Sebastien Boeuf --- Cargo.lock | 1 + devices/Cargo.toml | 1 + devices/src/legacy/serial.rs | 56 ++++++++++++++++++++++++------------ devices/src/lib.rs | 1 + vmm/src/device_manager.rs | 13 +++++---- 5 files changed, 48 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7efbfaecf..7ebf13585 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,6 +231,7 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vm-device 0.1.0", "vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)", "vmm-sys-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/devices/Cargo.toml b/devices/Cargo.toml index cc2972055..05ec20e84 100644 --- a/devices/Cargo.toml +++ b/devices/Cargo.toml @@ -11,6 +11,7 @@ kvm-bindings = "0.2.0" kvm-ioctls = "0.4.0" libc = "0.2.60" log = "0.4.8" +vm-device = { path = "../vm-device" } vm-memory = { git = "https://github.com/rust-vmm/vm-memory" } vmm-sys-util = ">=0.3.1" diff --git a/devices/src/legacy/serial.rs b/devices/src/legacy/serial.rs index 590b42a3d..fc86ccf3e 100644 --- a/devices/src/legacy/serial.rs +++ b/devices/src/legacy/serial.rs @@ -5,9 +5,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE-BSD-3-Clause file. -use crate::{BusDevice, Interrupt}; +use crate::BusDevice; use std::collections::VecDeque; +use std::sync::Arc; use std::{io, result}; +use vm_device::interrupt::InterruptSourceGroup; use vmm_sys_util::errno::Result; const LOOP_SIZE: usize = 0x40; @@ -55,7 +57,7 @@ const DEFAULT_BAUD_DIVISOR: u16 = 12; // 9600 bps pub struct Serial { interrupt_enable: u8, interrupt_identification: u8, - interrupt: Box, + interrupt: Arc>, line_control: u8, line_status: u8, modem_control: u8, @@ -67,7 +69,10 @@ pub struct Serial { } impl Serial { - pub fn new(interrupt: Box, out: Option>) -> Serial { + pub fn new( + interrupt: Arc>, + out: Option>, + ) -> Serial { Serial { interrupt_enable: 0, interrupt_identification: DEFAULT_INTERRUPT_IDENTIFICATION, @@ -84,12 +89,15 @@ impl Serial { } /// Constructs a Serial port ready for output. - pub fn new_out(interrupt: Box, out: Box) -> Serial { + pub fn new_out( + interrupt: Arc>, + out: Box, + ) -> Serial { Self::new(interrupt, Some(out)) } /// Constructs a Serial port with no connected output. - pub fn new_sink(interrupt: Box) -> Serial { + pub fn new_sink(interrupt: Arc>) -> Serial { Self::new(interrupt, None) } @@ -149,7 +157,7 @@ impl Serial { } fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> { - self.interrupt.deliver() + self.interrupt.trigger(0) } fn iir_reset(&mut self) { @@ -233,16 +241,24 @@ mod tests { use super::*; use std::io; use std::sync::{Arc, Mutex}; + use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig}; use vmm_sys_util::eventfd::EventFd; struct TestInterrupt { event_fd: EventFd, } - impl Interrupt for TestInterrupt { - fn deliver(&self) -> result::Result<(), std::io::Error> { + impl InterruptSourceGroup for TestInterrupt { + fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> { self.event_fd.write(1) } + fn update( + &self, + _index: InterruptIndex, + _config: InterruptSourceConfig, + ) -> result::Result<(), std::io::Error> { + Ok(()) + } } impl TestInterrupt { @@ -278,7 +294,7 @@ mod tests { let intr_evt = EventFd::new(0).unwrap(); let serial_out = SharedBuffer::new(); let mut serial = Serial::new_out( - Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), + Arc::new(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))), Box::new(serial_out.clone()), ); @@ -297,7 +313,7 @@ mod tests { let intr_evt = EventFd::new(0).unwrap(); let serial_out = SharedBuffer::new(); let mut serial = Serial::new_out( - Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), + Arc::new(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))), Box::new(serial_out.clone()), ); @@ -334,8 +350,9 @@ mod tests { #[test] fn serial_thr() { let intr_evt = EventFd::new(0).unwrap(); - let mut serial = - Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))); + let mut serial = Serial::new_sink(Arc::new(Box::new(TestInterrupt::new( + intr_evt.try_clone().unwrap(), + )))); // write 1 to the interrupt event fd, so that read doesn't block in case the event fd // counter doesn't change (for 0 it blocks) @@ -354,8 +371,9 @@ mod tests { #[test] fn serial_dlab() { let intr_evt = EventFd::new(0).unwrap(); - let mut serial = - Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))); + let mut serial = Serial::new_sink(Arc::new(Box::new(TestInterrupt::new( + intr_evt.try_clone().unwrap(), + )))); serial.write(0, LCR as u64, &[LCR_DLAB_BIT as u8]); serial.write(0, DLAB_LOW as u64, &[0x12 as u8]); @@ -373,8 +391,9 @@ mod tests { #[test] fn serial_modem() { let intr_evt = EventFd::new(0).unwrap(); - let mut serial = - Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))); + let mut serial = Serial::new_sink(Arc::new(Box::new(TestInterrupt::new( + intr_evt.try_clone().unwrap(), + )))); serial.write(0, MCR as u64, &[MCR_LOOP_BIT as u8]); serial.write(0, DATA as u64, &['a' as u8]); @@ -397,8 +416,9 @@ mod tests { #[test] fn serial_scratch() { let intr_evt = EventFd::new(0).unwrap(); - let mut serial = - Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))); + let mut serial = Serial::new_sink(Arc::new(Box::new(TestInterrupt::new( + intr_evt.try_clone().unwrap(), + )))); serial.write(0, SCR as u64, &[0x12 as u8]); diff --git a/devices/src/lib.rs b/devices/src/lib.rs index 88c92ff16..c99a4d204 100644 --- a/devices/src/lib.rs +++ b/devices/src/lib.rs @@ -15,6 +15,7 @@ extern crate kvm_ioctls; extern crate libc; #[macro_use] extern crate log; +extern crate vm_device; extern crate vm_memory; extern crate vmm_sys_util; diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index a28e8fceb..fdc1b0ad1 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -43,7 +43,6 @@ use std::sync::{Arc, Mutex}; use vfio::{VfioDevice, VfioDmaMapping, VfioPciDevice, VfioPciError}; use vm_allocator::SystemAllocator; use vm_device::interrupt::InterruptManager; -#[cfg(feature = "mmio_support")] use vm_device::interrupt::{InterruptIndex, PIN_IRQ}; use vm_device::{Migratable, MigratableError, Pausable, Snapshotable}; use vm_memory::GuestAddress; @@ -464,7 +463,7 @@ impl DeviceManager { let console = DeviceManager::add_console_device( vm_info, &address_manager, - &ioapic, + &interrupt_manager, &mut virtio_devices, )?; @@ -791,7 +790,7 @@ impl DeviceManager { fn add_console_device( vm_info: &VmInfo, address_manager: &Arc, - ioapic: &Arc>, + interrupt_manager: &Arc, virtio_devices: &mut Vec<(Arc>, bool)>, ) -> DeviceManagerResult> { let serial_config = vm_info.vm_cfg.lock().unwrap().serial.clone(); @@ -806,11 +805,13 @@ impl DeviceManager { let serial = if serial_config.mode != ConsoleOutputMode::Off { // Serial is tied to IRQ #4 let serial_irq = 4; - let interrupt: Box = - Box::new(UserIoapicIrq::new(ioapic.clone(), serial_irq)); + + let interrupt_group = interrupt_manager + .create_group(PIN_IRQ, serial_irq as InterruptIndex, 1 as InterruptIndex) + .map_err(DeviceManagerError::CreateInterruptGroup)?; let serial = Arc::new(Mutex::new(devices::legacy::Serial::new( - interrupt, + interrupt_group, serial_writer, )));