mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-21 20:15:21 +00:00
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 <sebastien.boeuf@intel.com>
This commit is contained in:
parent
8d7c4ea334
commit
75e22ff34e
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -231,6 +231,7 @@ dependencies = [
|
|||||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"vmm-sys-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -11,6 +11,7 @@ kvm-bindings = "0.2.0"
|
|||||||
kvm-ioctls = "0.4.0"
|
kvm-ioctls = "0.4.0"
|
||||||
libc = "0.2.60"
|
libc = "0.2.60"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = { git = "https://github.com/rust-vmm/vm-memory" }
|
vm-memory = { git = "https://github.com/rust-vmm/vm-memory" }
|
||||||
vmm-sys-util = ">=0.3.1"
|
vmm-sys-util = ">=0.3.1"
|
||||||
|
|
||||||
|
@ -5,9 +5,11 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE-BSD-3-Clause file.
|
// found in the LICENSE-BSD-3-Clause file.
|
||||||
|
|
||||||
use crate::{BusDevice, Interrupt};
|
use crate::BusDevice;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::{io, result};
|
use std::{io, result};
|
||||||
|
use vm_device::interrupt::InterruptSourceGroup;
|
||||||
use vmm_sys_util::errno::Result;
|
use vmm_sys_util::errno::Result;
|
||||||
|
|
||||||
const LOOP_SIZE: usize = 0x40;
|
const LOOP_SIZE: usize = 0x40;
|
||||||
@ -55,7 +57,7 @@ const DEFAULT_BAUD_DIVISOR: u16 = 12; // 9600 bps
|
|||||||
pub struct Serial {
|
pub struct Serial {
|
||||||
interrupt_enable: u8,
|
interrupt_enable: u8,
|
||||||
interrupt_identification: u8,
|
interrupt_identification: u8,
|
||||||
interrupt: Box<dyn Interrupt>,
|
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
|
||||||
line_control: u8,
|
line_control: u8,
|
||||||
line_status: u8,
|
line_status: u8,
|
||||||
modem_control: u8,
|
modem_control: u8,
|
||||||
@ -67,7 +69,10 @@ pub struct Serial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Serial {
|
impl Serial {
|
||||||
pub fn new(interrupt: Box<dyn Interrupt>, out: Option<Box<dyn io::Write + Send>>) -> Serial {
|
pub fn new(
|
||||||
|
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
|
||||||
|
out: Option<Box<dyn io::Write + Send>>,
|
||||||
|
) -> Serial {
|
||||||
Serial {
|
Serial {
|
||||||
interrupt_enable: 0,
|
interrupt_enable: 0,
|
||||||
interrupt_identification: DEFAULT_INTERRUPT_IDENTIFICATION,
|
interrupt_identification: DEFAULT_INTERRUPT_IDENTIFICATION,
|
||||||
@ -84,12 +89,15 @@ impl Serial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a Serial port ready for output.
|
/// Constructs a Serial port ready for output.
|
||||||
pub fn new_out(interrupt: Box<dyn Interrupt>, out: Box<dyn io::Write + Send>) -> Serial {
|
pub fn new_out(
|
||||||
|
interrupt: Arc<Box<dyn InterruptSourceGroup>>,
|
||||||
|
out: Box<dyn io::Write + Send>,
|
||||||
|
) -> Serial {
|
||||||
Self::new(interrupt, Some(out))
|
Self::new(interrupt, Some(out))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a Serial port with no connected output.
|
/// Constructs a Serial port with no connected output.
|
||||||
pub fn new_sink(interrupt: Box<dyn Interrupt>) -> Serial {
|
pub fn new_sink(interrupt: Arc<Box<dyn InterruptSourceGroup>>) -> Serial {
|
||||||
Self::new(interrupt, None)
|
Self::new(interrupt, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +157,7 @@ impl Serial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> {
|
fn trigger_interrupt(&mut self) -> result::Result<(), io::Error> {
|
||||||
self.interrupt.deliver()
|
self.interrupt.trigger(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iir_reset(&mut self) {
|
fn iir_reset(&mut self) {
|
||||||
@ -233,16 +241,24 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
struct TestInterrupt {
|
struct TestInterrupt {
|
||||||
event_fd: EventFd,
|
event_fd: EventFd,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interrupt for TestInterrupt {
|
impl InterruptSourceGroup for TestInterrupt {
|
||||||
fn deliver(&self) -> result::Result<(), std::io::Error> {
|
fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> {
|
||||||
self.event_fd.write(1)
|
self.event_fd.write(1)
|
||||||
}
|
}
|
||||||
|
fn update(
|
||||||
|
&self,
|
||||||
|
_index: InterruptIndex,
|
||||||
|
_config: InterruptSourceConfig,
|
||||||
|
) -> result::Result<(), std::io::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestInterrupt {
|
impl TestInterrupt {
|
||||||
@ -278,7 +294,7 @@ mod tests {
|
|||||||
let intr_evt = EventFd::new(0).unwrap();
|
let intr_evt = EventFd::new(0).unwrap();
|
||||||
let serial_out = SharedBuffer::new();
|
let serial_out = SharedBuffer::new();
|
||||||
let mut serial = Serial::new_out(
|
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()),
|
Box::new(serial_out.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -297,7 +313,7 @@ mod tests {
|
|||||||
let intr_evt = EventFd::new(0).unwrap();
|
let intr_evt = EventFd::new(0).unwrap();
|
||||||
let serial_out = SharedBuffer::new();
|
let serial_out = SharedBuffer::new();
|
||||||
let mut serial = Serial::new_out(
|
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()),
|
Box::new(serial_out.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -334,8 +350,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn serial_thr() {
|
fn serial_thr() {
|
||||||
let intr_evt = EventFd::new(0).unwrap();
|
let intr_evt = EventFd::new(0).unwrap();
|
||||||
let mut serial =
|
let mut serial = Serial::new_sink(Arc::new(Box::new(TestInterrupt::new(
|
||||||
Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
|
intr_evt.try_clone().unwrap(),
|
||||||
|
))));
|
||||||
|
|
||||||
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
|
// 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)
|
// counter doesn't change (for 0 it blocks)
|
||||||
@ -354,8 +371,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn serial_dlab() {
|
fn serial_dlab() {
|
||||||
let intr_evt = EventFd::new(0).unwrap();
|
let intr_evt = EventFd::new(0).unwrap();
|
||||||
let mut serial =
|
let mut serial = Serial::new_sink(Arc::new(Box::new(TestInterrupt::new(
|
||||||
Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
|
intr_evt.try_clone().unwrap(),
|
||||||
|
))));
|
||||||
|
|
||||||
serial.write(0, LCR as u64, &[LCR_DLAB_BIT as u8]);
|
serial.write(0, LCR as u64, &[LCR_DLAB_BIT as u8]);
|
||||||
serial.write(0, DLAB_LOW as u64, &[0x12 as u8]);
|
serial.write(0, DLAB_LOW as u64, &[0x12 as u8]);
|
||||||
@ -373,8 +391,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn serial_modem() {
|
fn serial_modem() {
|
||||||
let intr_evt = EventFd::new(0).unwrap();
|
let intr_evt = EventFd::new(0).unwrap();
|
||||||
let mut serial =
|
let mut serial = Serial::new_sink(Arc::new(Box::new(TestInterrupt::new(
|
||||||
Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
|
intr_evt.try_clone().unwrap(),
|
||||||
|
))));
|
||||||
|
|
||||||
serial.write(0, MCR as u64, &[MCR_LOOP_BIT as u8]);
|
serial.write(0, MCR as u64, &[MCR_LOOP_BIT as u8]);
|
||||||
serial.write(0, DATA as u64, &['a' as u8]);
|
serial.write(0, DATA as u64, &['a' as u8]);
|
||||||
@ -397,8 +416,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn serial_scratch() {
|
fn serial_scratch() {
|
||||||
let intr_evt = EventFd::new(0).unwrap();
|
let intr_evt = EventFd::new(0).unwrap();
|
||||||
let mut serial =
|
let mut serial = Serial::new_sink(Arc::new(Box::new(TestInterrupt::new(
|
||||||
Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
|
intr_evt.try_clone().unwrap(),
|
||||||
|
))));
|
||||||
|
|
||||||
serial.write(0, SCR as u64, &[0x12 as u8]);
|
serial.write(0, SCR as u64, &[0x12 as u8]);
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ extern crate kvm_ioctls;
|
|||||||
extern crate libc;
|
extern crate libc;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
extern crate vm_device;
|
||||||
extern crate vm_memory;
|
extern crate vm_memory;
|
||||||
extern crate vmm_sys_util;
|
extern crate vmm_sys_util;
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ use std::sync::{Arc, Mutex};
|
|||||||
use vfio::{VfioDevice, VfioDmaMapping, VfioPciDevice, VfioPciError};
|
use vfio::{VfioDevice, VfioDmaMapping, VfioPciDevice, VfioPciError};
|
||||||
use vm_allocator::SystemAllocator;
|
use vm_allocator::SystemAllocator;
|
||||||
use vm_device::interrupt::InterruptManager;
|
use vm_device::interrupt::InterruptManager;
|
||||||
#[cfg(feature = "mmio_support")]
|
|
||||||
use vm_device::interrupt::{InterruptIndex, PIN_IRQ};
|
use vm_device::interrupt::{InterruptIndex, PIN_IRQ};
|
||||||
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
|
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
|
||||||
use vm_memory::GuestAddress;
|
use vm_memory::GuestAddress;
|
||||||
@ -464,7 +463,7 @@ impl DeviceManager {
|
|||||||
let console = DeviceManager::add_console_device(
|
let console = DeviceManager::add_console_device(
|
||||||
vm_info,
|
vm_info,
|
||||||
&address_manager,
|
&address_manager,
|
||||||
&ioapic,
|
&interrupt_manager,
|
||||||
&mut virtio_devices,
|
&mut virtio_devices,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -791,7 +790,7 @@ impl DeviceManager {
|
|||||||
fn add_console_device(
|
fn add_console_device(
|
||||||
vm_info: &VmInfo,
|
vm_info: &VmInfo,
|
||||||
address_manager: &Arc<AddressManager>,
|
address_manager: &Arc<AddressManager>,
|
||||||
ioapic: &Arc<Mutex<ioapic::Ioapic>>,
|
interrupt_manager: &Arc<dyn InterruptManager>,
|
||||||
virtio_devices: &mut Vec<(Arc<Mutex<dyn vm_virtio::VirtioDevice>>, bool)>,
|
virtio_devices: &mut Vec<(Arc<Mutex<dyn vm_virtio::VirtioDevice>>, bool)>,
|
||||||
) -> DeviceManagerResult<Arc<Console>> {
|
) -> DeviceManagerResult<Arc<Console>> {
|
||||||
let serial_config = vm_info.vm_cfg.lock().unwrap().serial.clone();
|
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 {
|
let serial = if serial_config.mode != ConsoleOutputMode::Off {
|
||||||
// Serial is tied to IRQ #4
|
// Serial is tied to IRQ #4
|
||||||
let serial_irq = 4;
|
let serial_irq = 4;
|
||||||
let interrupt: Box<dyn devices::Interrupt> =
|
|
||||||
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(
|
let serial = Arc::new(Mutex::new(devices::legacy::Serial::new(
|
||||||
interrupt,
|
interrupt_group,
|
||||||
serial_writer,
|
serial_writer,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user