misc: Make Bus::write() return an Option<Arc<Barrier>>

This can be uses to indicate to the caller that it should wait on the
barrier before returning as there is some asynchronous activity
triggered by the write which requires the KVM exit to block until it's
completed.

This is useful for having vCPU thread wait for the VMM thread to proceed
to activate the virtio devices.

See #1863

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford
2020-12-04 09:23:47 +00:00
parent dbf4a252ad
commit 1fc6d50f3e
14 changed files with 66 additions and 38 deletions

View File

@@ -4,7 +4,7 @@
//
use acpi_tables::{aml, aml::Aml};
use std::sync::Arc;
use std::sync::{Arc, Barrier};
use std::time::Instant;
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
@@ -36,7 +36,7 @@ impl BusDevice for AcpiShutdownDevice {
}
}
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data[0] == 1 {
debug!("ACPI Reboot signalled");
if let Err(e) = self.reset_evt.write(1) {
@@ -54,6 +54,7 @@ impl BusDevice for AcpiShutdownDevice {
error!("Error triggering ACPI shutdown event: {}", e);
}
}
None
}
}

View File

@@ -13,7 +13,7 @@ use super::interrupt_controller::{Error, InterruptController};
use anyhow::anyhow;
use byteorder::{ByteOrder, LittleEndian};
use std::result;
use std::sync::Arc;
use std::sync::{Arc, Barrier};
use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
MsiIrqGroupConfig, MsiIrqSourceConfig,
@@ -167,7 +167,7 @@ impl BusDevice for Ioapic {
LittleEndian::write_u32(data, value);
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
assert!(data.len() == 4);
debug!("IOAPIC_W @ offset 0x{:x}", offset);
@@ -181,6 +181,7 @@ impl BusDevice for Ioapic {
error!("IOAPIC: failed writing at offset {}", offset);
}
}
None
}
}

View File

@@ -5,6 +5,7 @@
use libc::{clock_gettime, gmtime_r, time_t, timespec, tm, CLOCK_REALTIME};
use std::cmp::min;
use std::mem;
use std::sync::{Arc, Barrier};
use vm_device::BusDevice;
const INDEX_MASK: u8 = 0x7f;
@@ -44,16 +45,17 @@ impl Cmos {
}
impl BusDevice for Cmos {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() != 1 {
return;
return None;
}
match offset {
INDEX_OFFSET => self.index = data[0] & INDEX_MASK,
DATA_OFFSET => self.data[self.index as usize] = data[0],
o => panic!("bad write offset on CMOS device: {}", o),
}
};
None
}
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {

View File

@@ -7,6 +7,7 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
//
use std::sync::{Arc, Barrier};
use vm_device::BusDevice;
/// Provides firmware debug output via I/O port controls
@@ -30,11 +31,13 @@ impl BusDevice for FwDebugDevice {
}
}
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() == 1 {
print!("{}", data[0] as char);
} else {
error!("Invalid write size on debug port: {}", data.len())
}
None
}
}

View File

@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-BSD-3-Clause file.
use vmm_sys_util::eventfd::EventFd;
use std::sync::{Arc, Barrier};
use vm_device::BusDevice;
use vmm_sys_util::eventfd::EventFd;
/// A i8042 PS/2 controller that emulates just enough to shutdown the machine.
pub struct I8042Device {
@@ -32,12 +32,14 @@ impl BusDevice for I8042Device {
}
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() == 1 && data[0] == 0xfe && offset == 3 {
debug!("i8042 reset signalled");
if let Err(e) = self.reset_evt.write(1) {
error!("Error triggering i8042 reset event: {}", e);
}
}
None
}
}

View File

@@ -9,7 +9,7 @@
//! a real-time clock input.
//!
use std::fmt;
use std::sync::Arc;
use std::sync::{Arc, Barrier};
use std::time::Instant;
use std::{io, result};
use vm_device::interrupt::InterruptSourceGroup;
@@ -371,7 +371,7 @@ impl BusDevice for RTC {
}
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() <= 4 {
let v = read_le_u32(&data[..]);
if let Err(e) = self.handle_write(offset, v) {
@@ -384,6 +384,8 @@ impl BusDevice for RTC {
data.len()
);
}
None
}
}

View File

@@ -7,7 +7,7 @@
use anyhow::anyhow;
use std::collections::VecDeque;
use std::sync::Arc;
use std::sync::{Arc, Barrier};
use std::{io, result};
use vm_device::interrupt::InterruptSourceGroup;
use vm_device::BusDevice;
@@ -275,12 +275,14 @@ impl BusDevice for Serial {
};
}
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
if data.len() != 1 {
return;
return None;
}
if let Err(_e) = self.handle_write(offset as u8, data[0]) {}
self.handle_write(offset as u8, data[0]).ok();
None
}
}