mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-06 02:25:23 +00:00
devices: introduce IrqLevelEvent and IrqEdgeEvent
Instead of passing primary trigger and resample events separately when implementing devices using level-triggered interrupts, let's create a dedicated IrqLevelEvent, and its counterpart, IrqEdgeEvent. BUG=None TEST=CQ Change-Id: Id51dd805cf8994368fa12a6df0475e433b6f03fb Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3536893 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Dmitry Torokhov <dtor@chromium.org>
This commit is contained in:
parent
8452832b97
commit
16f37e0f65
2 changed files with 107 additions and 0 deletions
105
devices/src/irq_event.rs
Normal file
105
devices/src/irq_event.rs
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Copyright 2022 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use base::{Event, Result};
|
||||
|
||||
/// A structure suitable for implementing edge triggered interrupts in device backends.
|
||||
pub struct IrqEdgeEvent(Event);
|
||||
|
||||
impl IrqEdgeEvent {
|
||||
pub fn new() -> Result<IrqEdgeEvent> {
|
||||
Event::new().map(IrqEdgeEvent)
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> Result<IrqEdgeEvent> {
|
||||
self.0.try_clone().map(IrqEdgeEvent)
|
||||
}
|
||||
|
||||
/// Creates an instance of IrqLevelEvent from an existing event.
|
||||
pub fn from_event(trigger_evt: Event) -> IrqEdgeEvent {
|
||||
IrqEdgeEvent(trigger_evt)
|
||||
}
|
||||
|
||||
pub fn get_trigger(&self) -> &Event {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn trigger(&self) -> Result<()> {
|
||||
self.0.write(1)
|
||||
}
|
||||
|
||||
pub fn clear_trigger(&self) {
|
||||
let _ = self.0.read();
|
||||
}
|
||||
}
|
||||
|
||||
/// A structure suitable for implementing level triggered interrupts in device backends.
|
||||
pub struct IrqLevelEvent {
|
||||
/// An event used by the device backend to signal hypervisor/VM about data or new unit
|
||||
/// of work being available.
|
||||
trigger_evt: Event,
|
||||
/// An event used by the hypervisor to signal device backend that it completed processing
|
||||
/// a unit of work and that device should re-raise `trigger_evt` if there is additional
|
||||
/// work needs to be done.
|
||||
resample_evt: Event,
|
||||
}
|
||||
|
||||
impl IrqLevelEvent {
|
||||
pub fn new() -> Result<IrqLevelEvent> {
|
||||
let trigger_evt = Event::new()?;
|
||||
let resample_evt = Event::new()?;
|
||||
Ok(IrqLevelEvent {
|
||||
trigger_evt,
|
||||
resample_evt,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> Result<IrqLevelEvent> {
|
||||
let trigger_evt = self.trigger_evt.try_clone()?;
|
||||
let resample_evt = self.resample_evt.try_clone()?;
|
||||
Ok(IrqLevelEvent {
|
||||
trigger_evt,
|
||||
resample_evt,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates an instance of IrqLevelEvent from an existing pair of events.
|
||||
pub fn from_event_pair(trigger_evt: Event, resample_evt: Event) -> IrqLevelEvent {
|
||||
IrqLevelEvent {
|
||||
trigger_evt,
|
||||
resample_evt,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_trigger(&self) -> &Event {
|
||||
&self.trigger_evt
|
||||
}
|
||||
|
||||
pub fn get_resample(&self) -> &Event {
|
||||
&self.resample_evt
|
||||
}
|
||||
|
||||
/// Allows backend to inject interrupt (typically into guest).
|
||||
pub fn trigger(&self) -> Result<()> {
|
||||
self.trigger_evt.write(1)
|
||||
}
|
||||
|
||||
/// Allows code servicing interrupt to consume or clear the event.
|
||||
pub fn clear_trigger(&self) {
|
||||
let _ = self.trigger_evt.read();
|
||||
}
|
||||
|
||||
/// Allows code servicing interrupt to signal that processing is done and that the backend
|
||||
/// should go ahead and re-trigger it if there is more work needs to be done.
|
||||
/// Note that typically resampling is signalled not by individual backends, but rather
|
||||
/// by the code implementing interrupt controller.
|
||||
pub fn trigger_resample(&self) -> Result<()> {
|
||||
self.resample_evt.write(1)
|
||||
}
|
||||
|
||||
/// Allows backend to consume or clear the resample event.
|
||||
pub fn clear_resample(&self) {
|
||||
let _ = self.resample_evt.read();
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ pub mod direct_io;
|
|||
#[cfg(feature = "direct")]
|
||||
pub mod direct_irq;
|
||||
mod i8042;
|
||||
mod irq_event;
|
||||
pub mod irqchip;
|
||||
mod pci;
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
|
@ -48,6 +49,7 @@ pub use self::direct_io::{DirectIo, DirectMmio};
|
|||
#[cfg(feature = "direct")]
|
||||
pub use self::direct_irq::{DirectIrq, DirectIrqError};
|
||||
pub use self::i8042::I8042Device;
|
||||
pub use self::irq_event::{IrqEdgeEvent, IrqLevelEvent};
|
||||
pub use self::irqchip::*;
|
||||
#[cfg(feature = "audio")]
|
||||
pub use self::pci::{Ac97Backend, Ac97Dev, Ac97Parameters};
|
||||
|
|
Loading…
Reference in a new issue