devices, vmm: Use a bit field for ACPI GED interrupt type

Use independent bits for storing whether there is a CPU or memory device
changed when reporting changes via ACPI GED interrupt. This prevents a
later notification squashing an earlier one and ensure that hotplugging
both CPU and memory at the same time succeeds.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford
2020-01-14 10:17:23 +00:00
committed by Samuel Ortiz
parent d2d1248342
commit 7310ab6fa7
6 changed files with 27 additions and 19 deletions

View File

@@ -5,7 +5,7 @@
use vmm_sys_util::eventfd::EventFd;
use BusDevice;
use HotPlugNotificationType;
use HotPlugNotificationFlags;
use Interrupt;
/// A device for handling ACPI shutdown and reboot
@@ -46,6 +46,7 @@ impl BusDevice for AcpiShutdownDevice {
const SLEEP_VALUE_BIT: u8 = 2;
if data[0] == (S5_SLEEP_VALUE << SLEEP_VALUE_BIT) | (1 << SLEEP_STATUS_EN_BIT) {
debug!("ACPI Shutdown signalled");
extern crate bitflags;
if let Err(e) = self.exit_evt.write(1) {
error!("Error triggering ACPI shutdown event: {}", e);
}
@@ -56,7 +57,7 @@ impl BusDevice for AcpiShutdownDevice {
/// A device for handling ACPI GED event generation
pub struct AcpiGEDDevice {
interrupt: Box<dyn Interrupt>,
notification_type: HotPlugNotificationType,
notification_type: HotPlugNotificationFlags,
ged_irq: u32,
}
@@ -64,16 +65,16 @@ impl AcpiGEDDevice {
pub fn new(interrupt: Box<dyn Interrupt>, ged_irq: u32) -> AcpiGEDDevice {
AcpiGEDDevice {
interrupt,
notification_type: HotPlugNotificationType::NoDevicesChanged,
notification_type: HotPlugNotificationFlags::NO_DEVICES_CHANGED,
ged_irq,
}
}
pub fn notify(
&mut self,
notification_type: HotPlugNotificationType,
notification_type: HotPlugNotificationFlags,
) -> Result<(), std::io::Error> {
self.notification_type = notification_type;
self.notification_type |= notification_type;
self.interrupt.deliver()
}
@@ -86,8 +87,8 @@ impl AcpiGEDDevice {
impl BusDevice for AcpiGEDDevice {
// Spec has all fields as zero
fn read(&mut self, _base: u64, _offset: u64, data: &mut [u8]) {
data[0] = self.notification_type as u8;
self.notification_type = HotPlugNotificationType::NoDevicesChanged;
data[0] = self.notification_type.bits();
self.notification_type = HotPlugNotificationFlags::NO_DEVICES_CHANGED;
}
fn write(&mut self, _base: u64, _offset: u64, _data: &[u8]) {}

View File

@@ -6,6 +6,8 @@
// found in the LICENSE-BSD-3-Clause file.
//! Emulates virtual and hardware devices.
#[macro_use]
extern crate bitflags;
extern crate byteorder;
extern crate epoll;
extern crate kvm_bindings;
@@ -71,9 +73,10 @@ pub trait Interrupt: Send + Sync {
fn deliver(&self) -> result::Result<(), std::io::Error>;
}
#[derive(Clone, Copy)]
pub enum HotPlugNotificationType {
NoDevicesChanged,
CPUDevicesChanged,
MemoryDevicesChanged,
bitflags! {
pub struct HotPlugNotificationFlags: u8 {
const NO_DEVICES_CHANGED = 0;
const CPU_DEVICES_CHANGED = 0b1;
const MEMORY_DEVICES_CHANGED = 0b10;
}
}