Skip to content

Commit 4e35293

Browse files
committed
refactor: use vm_device::Bus for IO bus
Use the vm_device::Bus bus for PortIO devices on x86. PCIe devices will use this as well. Signed-off-by: Babis Chalios <[email protected]>
1 parent 1c664e1 commit 4e35293

File tree

11 files changed

+112
-457
lines changed

11 files changed

+112
-457
lines changed

src/vmm/src/arch/x86_64/vcpu.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ pub struct KvmVcpu {
160160
#[derive(Default, Debug)]
161161
pub struct Peripherals {
162162
/// Pio bus.
163-
pub pio_bus: Option<crate::devices::Bus>,
163+
pub pio_bus: Option<Arc<vm_device::Bus>>,
164164
/// Mmio bus.
165165
pub mmio_bus: Option<Arc<vm_device::Bus>>,
166166
}
@@ -267,7 +267,7 @@ impl KvmVcpu {
267267
}
268268

269269
/// Sets a Port Mapped IO bus for this vcpu.
270-
pub fn set_pio_bus(&mut self, pio_bus: crate::devices::Bus) {
270+
pub fn set_pio_bus(&mut self, pio_bus: Arc<vm_device::Bus>) {
271271
self.peripherals.pio_bus = Some(pio_bus);
272272
}
273273

@@ -711,15 +711,19 @@ impl Peripherals {
711711
VcpuExit::IoIn(addr, data) => {
712712
if let Some(pio_bus) = &self.pio_bus {
713713
let _metric = METRICS.vcpu.exit_io_in_agg.record_latency_metrics();
714-
pio_bus.read(u64::from(addr), data);
714+
if let Err(err) = pio_bus.read(u64::from(addr), data) {
715+
warn!("vcpu: IO read @ {addr:#x}:{:#x} failed: {err}", data.len());
716+
}
715717
METRICS.vcpu.exit_io_in.inc();
716718
}
717719
Ok(VcpuEmulation::Handled)
718720
}
719721
VcpuExit::IoOut(addr, data) => {
720722
if let Some(pio_bus) = &self.pio_bus {
721723
let _metric = METRICS.vcpu.exit_io_out_agg.record_latency_metrics();
722-
pio_bus.write(u64::from(addr), data);
724+
if let Err(err) = pio_bus.write(u64::from(addr), data) {
725+
warn!("vcpu: IO write @ {addr:#x}:{:#x} failed: {err}", data.len());
726+
}
723727
METRICS.vcpu.exit_io_out.inc();
724728
}
725729
Ok(VcpuEmulation::Handled)

src/vmm/src/builder.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use event_manager::{MutEventSubscriber, SubscriberOps};
1313
use linux_loader::cmdline::Cmdline as LoaderKernelCmdline;
1414
use userfaultfd::Uffd;
1515
use utils::time::TimestampUs;
16+
#[cfg(target_arch = "x86_64")]
17+
use vmm_sys_util::eventfd::EventFd;
1618

1719
use crate::arch::{ConfigurationError, configure_system_for_boot, load_kernel};
1820
#[cfg(target_arch = "aarch64")]
@@ -28,8 +30,9 @@ use crate::device_manager::persist::{
2830
ACPIDeviceManagerConstructorArgs, ACPIDeviceManagerRestoreError, MMIODevManagerConstructorArgs,
2931
};
3032
use crate::device_manager::resources::ResourceAllocator;
31-
use crate::devices::BusDevice;
3233
use crate::devices::acpi::vmgenid::{VmGenId, VmGenIdError};
34+
#[cfg(target_arch = "x86_64")]
35+
use crate::devices::legacy::I8042Device;
3336
#[cfg(target_arch = "aarch64")]
3437
use crate::devices::legacy::RTCDevice;
3538
use crate::devices::legacy::SerialDevice;
@@ -157,10 +160,14 @@ fn create_vmm_and_vcpus(
157160

158161
// x86_64 uses the i8042 reset event as the Vmm exit event.
159162
let reset_evt = vcpus_exit_evt.try_clone().map_err(VmmError::EventFd)?;
163+
let i8042 = Arc::new(Mutex::new(I8042Device::new(
164+
reset_evt,
165+
EventFd::new(libc::EFD_NONBLOCK).map_err(VmmError::EventFd)?,
166+
)));
160167

161168
// create pio dev manager with legacy devices
162169
let mut pio_dev_mgr =
163-
PortIODeviceManager::new(serial_device, reset_evt).map_err(VmmError::LegacyIOBus)?;
170+
PortIODeviceManager::new(serial_device, i8042).map_err(VmmError::LegacyIOBus)?;
164171
pio_dev_mgr
165172
.register_devices(vm.fd())
166173
.map_err(VmmError::LegacyIOBus)?;
@@ -527,11 +534,11 @@ pub fn build_microvm_from_snapshot(
527534
/// Sets up the serial device.
528535
pub fn setup_serial_device(
529536
event_manager: &mut EventManager,
530-
) -> Result<Arc<Mutex<BusDevice>>, VmmError> {
531-
let serial = Arc::new(Mutex::new(BusDevice::Serial(
537+
) -> Result<Arc<Mutex<SerialDevice>>, VmmError> {
538+
let serial = Arc::new(Mutex::new(
532539
SerialDevice::new(Some(std::io::stdin()), SerialOut::Stdout(std::io::stdout()))
533540
.map_err(VmmError::EventFd)?,
534-
)));
541+
));
535542
event_manager.add_subscriber(serial.clone());
536543
Ok(serial)
537544
}
@@ -819,10 +826,13 @@ pub(crate) mod tests {
819826
let acpi_device_manager = ACPIDeviceManager::new();
820827
#[cfg(target_arch = "x86_64")]
821828
let pio_device_manager = PortIODeviceManager::new(
822-
Arc::new(Mutex::new(BusDevice::Serial(
829+
Arc::new(Mutex::new(
823830
SerialDevice::new(None, SerialOut::Sink(std::io::sink())).unwrap(),
831+
)),
832+
Arc::new(Mutex::new(I8042Device::new(
833+
EventFd::new(libc::EFD_NONBLOCK).unwrap(),
834+
EventFd::new(libc::EFD_NONBLOCK).unwrap(),
824835
))),
825-
EventFd::new(libc::EFD_NONBLOCK).unwrap(),
826836
)
827837
.unwrap();
828838

src/vmm/src/device_manager/legacy.rs

+25-26
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@ use libc::EFD_NONBLOCK;
1616
use vm_superio::Serial;
1717
use vmm_sys_util::eventfd::EventFd;
1818

19-
use crate::devices::bus::BusDevice;
2019
use crate::devices::legacy::serial::SerialOut;
21-
use crate::devices::legacy::{EventFdTrigger, SerialDevice, SerialEventsWrapper};
20+
use crate::devices::legacy::{EventFdTrigger, I8042Device, SerialDevice, SerialEventsWrapper};
2221

2322
/// Errors corresponding to the `PortIODeviceManager`.
2423
#[derive(Debug, derive_more::From, thiserror::Error, displaydoc::Display)]
2524
pub enum LegacyDeviceError {
2625
/// Failed to add legacy device to Bus: {0}
27-
BusError(crate::devices::BusError),
26+
BusError(vm_device::BusError),
2827
/// Failed to create EventFd: {0}
2928
EventFd(std::io::Error),
3029
}
@@ -34,11 +33,11 @@ pub enum LegacyDeviceError {
3433
/// The `LegacyDeviceManger` should be initialized only by using the constructor.
3534
#[derive(Debug)]
3635
pub struct PortIODeviceManager {
37-
pub io_bus: crate::devices::Bus,
36+
pub io_bus: Arc<vm_device::Bus>,
3837
// BusDevice::Serial
39-
pub stdio_serial: Arc<Mutex<BusDevice>>,
38+
pub stdio_serial: Arc<Mutex<SerialDevice>>,
4039
// BusDevice::I8042Device
41-
pub i8042: Arc<Mutex<BusDevice>>,
40+
pub i8042: Arc<Mutex<I8042Device>>,
4241

4342
// Communication event on ports 1 & 3.
4443
pub com_evt_1_3: EventFdTrigger,
@@ -73,29 +72,26 @@ impl PortIODeviceManager {
7372

7473
/// Create a new DeviceManager handling legacy devices (uart, i8042).
7574
pub fn new(
76-
serial: Arc<Mutex<BusDevice>>,
77-
i8042_reset_evfd: EventFd,
75+
stdio_serial: Arc<Mutex<SerialDevice>>,
76+
i8042: Arc<Mutex<I8042Device>>,
7877
) -> Result<Self, LegacyDeviceError> {
79-
debug_assert!(matches!(*serial.lock().unwrap(), BusDevice::Serial(_)));
80-
let io_bus = crate::devices::Bus::new();
81-
let com_evt_1_3 = serial
78+
let io_bus = Arc::new(vm_device::Bus::new());
79+
let com_evt_1_3 = stdio_serial
8280
.lock()
8381
.expect("Poisoned lock")
84-
.serial_mut()
85-
.unwrap()
8682
.serial
8783
.interrupt_evt()
8884
.try_clone()?;
8985
let com_evt_2_4 = EventFdTrigger::new(EventFd::new(EFD_NONBLOCK)?);
90-
let kbd_evt = EventFd::new(libc::EFD_NONBLOCK)?;
91-
92-
let i8042 = Arc::new(Mutex::new(BusDevice::I8042Device(
93-
crate::devices::legacy::I8042Device::new(i8042_reset_evfd, kbd_evt.try_clone()?),
94-
)));
86+
let kbd_evt = i8042
87+
.lock()
88+
.expect("Poisoned lock")
89+
.kbd_interrupt_evt
90+
.try_clone()?;
9591

9692
Ok(PortIODeviceManager {
9793
io_bus,
98-
stdio_serial: serial,
94+
stdio_serial,
9995
i8042,
10096
com_evt_1_3,
10197
com_evt_2_4,
@@ -105,7 +101,7 @@ impl PortIODeviceManager {
105101

106102
/// Register supported legacy devices.
107103
pub fn register_devices(&mut self, vm_fd: &VmFd) -> Result<(), LegacyDeviceError> {
108-
let serial_2_4 = Arc::new(Mutex::new(BusDevice::Serial(SerialDevice {
104+
let serial_2_4 = Arc::new(Mutex::new(SerialDevice {
109105
serial: Serial::with_events(
110106
self.com_evt_2_4.try_clone()?.try_clone()?,
111107
SerialEventsWrapper {
@@ -114,8 +110,8 @@ impl PortIODeviceManager {
114110
SerialOut::Sink(std::io::sink()),
115111
),
116112
input: None,
117-
})));
118-
let serial_1_3 = Arc::new(Mutex::new(BusDevice::Serial(SerialDevice {
113+
}));
114+
let serial_1_3 = Arc::new(Mutex::new(SerialDevice {
119115
serial: Serial::with_events(
120116
self.com_evt_1_3.try_clone()?.try_clone()?,
121117
SerialEventsWrapper {
@@ -124,7 +120,7 @@ impl PortIODeviceManager {
124120
SerialOut::Sink(std::io::sink()),
125121
),
126122
input: None,
127-
})));
123+
}));
128124
self.io_bus.insert(
129125
self.stdio_serial.clone(),
130126
Self::SERIAL_PORT_ADDRESSES[0],
@@ -251,7 +247,7 @@ mod tests {
251247
let (_, vm) = setup_vm_with_memory(0x1000);
252248
vm.setup_irqchip().unwrap();
253249
let mut ldm = PortIODeviceManager::new(
254-
Arc::new(Mutex::new(BusDevice::Serial(SerialDevice {
250+
Arc::new(Mutex::new(SerialDevice {
255251
serial: Serial::with_events(
256252
EventFdTrigger::new(EventFd::new(EFD_NONBLOCK).unwrap()),
257253
SerialEventsWrapper {
@@ -260,8 +256,11 @@ mod tests {
260256
SerialOut::Sink(std::io::sink()),
261257
),
262258
input: None,
263-
}))),
264-
EventFd::new(libc::EFD_NONBLOCK).unwrap(),
259+
})),
260+
Arc::new(Mutex::new(I8042Device::new(
261+
EventFd::new(libc::EFD_NONBLOCK).unwrap(),
262+
EventFd::new(libc::EFD_NONBLOCK).unwrap(),
263+
))),
265264
)
266265
.unwrap();
267266
ldm.register_devices(vm.fd()).unwrap();

0 commit comments

Comments
 (0)