xref: /aosp_15_r20/external/crosvm/devices/src/irq_event.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
6*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptors;
7*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
8*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
9*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
10*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
11*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
12*bb4ee6a4SAndroid Build Coastguard Worker 
13*bb4ee6a4SAndroid Build Coastguard Worker /// A structure suitable for implementing edge triggered interrupts in device backends.
14*bb4ee6a4SAndroid Build Coastguard Worker pub struct IrqEdgeEvent(Event);
15*bb4ee6a4SAndroid Build Coastguard Worker 
16*bb4ee6a4SAndroid Build Coastguard Worker impl IrqEdgeEvent {
new() -> Result<IrqEdgeEvent>17*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Result<IrqEdgeEvent> {
18*bb4ee6a4SAndroid Build Coastguard Worker         Event::new().map(IrqEdgeEvent)
19*bb4ee6a4SAndroid Build Coastguard Worker     }
20*bb4ee6a4SAndroid Build Coastguard Worker 
try_clone(&self) -> Result<IrqEdgeEvent>21*bb4ee6a4SAndroid Build Coastguard Worker     pub fn try_clone(&self) -> Result<IrqEdgeEvent> {
22*bb4ee6a4SAndroid Build Coastguard Worker         self.0.try_clone().map(IrqEdgeEvent)
23*bb4ee6a4SAndroid Build Coastguard Worker     }
24*bb4ee6a4SAndroid Build Coastguard Worker 
25*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates an instance of IrqLevelEvent from an existing event.
from_event(trigger_evt: Event) -> IrqEdgeEvent26*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_event(trigger_evt: Event) -> IrqEdgeEvent {
27*bb4ee6a4SAndroid Build Coastguard Worker         IrqEdgeEvent(trigger_evt)
28*bb4ee6a4SAndroid Build Coastguard Worker     }
29*bb4ee6a4SAndroid Build Coastguard Worker 
get_trigger(&self) -> &Event30*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_trigger(&self) -> &Event {
31*bb4ee6a4SAndroid Build Coastguard Worker         &self.0
32*bb4ee6a4SAndroid Build Coastguard Worker     }
33*bb4ee6a4SAndroid Build Coastguard Worker 
trigger(&self) -> Result<()>34*bb4ee6a4SAndroid Build Coastguard Worker     pub fn trigger(&self) -> Result<()> {
35*bb4ee6a4SAndroid Build Coastguard Worker         self.0.signal()
36*bb4ee6a4SAndroid Build Coastguard Worker     }
37*bb4ee6a4SAndroid Build Coastguard Worker 
clear_trigger(&self)38*bb4ee6a4SAndroid Build Coastguard Worker     pub fn clear_trigger(&self) {
39*bb4ee6a4SAndroid Build Coastguard Worker         let _ = self.0.wait();
40*bb4ee6a4SAndroid Build Coastguard Worker     }
41*bb4ee6a4SAndroid Build Coastguard Worker }
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker /// A structure suitable for implementing level triggered interrupts in device backends.
44*bb4ee6a4SAndroid Build Coastguard Worker ///
45*bb4ee6a4SAndroid Build Coastguard Worker /// Level-triggered interrupts require the device to monitor a resample event from the IRQ chip,
46*bb4ee6a4SAndroid Build Coastguard Worker /// which can be retrieved with [`IrqLevelEvent::get_resample()`]. When the guest OS acknowledges
47*bb4ee6a4SAndroid Build Coastguard Worker /// the interrupt with an End of Interrupt (EOI) command, the IRQ chip will signal the resample
48*bb4ee6a4SAndroid Build Coastguard Worker /// event. Each time the resample event is signalled, the device should re-check its state and call
49*bb4ee6a4SAndroid Build Coastguard Worker /// [`IrqLevelEvent::trigger()`] again if the interrupt should still be asserted.
50*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Serialize, Deserialize)]
51*bb4ee6a4SAndroid Build Coastguard Worker pub struct IrqLevelEvent {
52*bb4ee6a4SAndroid Build Coastguard Worker     /// An event used by the device backend to signal hypervisor/VM about data or new unit
53*bb4ee6a4SAndroid Build Coastguard Worker     /// of work being available.
54*bb4ee6a4SAndroid Build Coastguard Worker     trigger_evt: Event,
55*bb4ee6a4SAndroid Build Coastguard Worker     /// An event used by the hypervisor to signal device backend that it completed processing a
56*bb4ee6a4SAndroid Build Coastguard Worker     /// unit of work and that device should re-raise `trigger_evt` if additional work needs to
57*bb4ee6a4SAndroid Build Coastguard Worker     /// be done.
58*bb4ee6a4SAndroid Build Coastguard Worker     resample_evt: Event,
59*bb4ee6a4SAndroid Build Coastguard Worker }
60*bb4ee6a4SAndroid Build Coastguard Worker 
61*bb4ee6a4SAndroid Build Coastguard Worker impl IrqLevelEvent {
new() -> Result<IrqLevelEvent>62*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Result<IrqLevelEvent> {
63*bb4ee6a4SAndroid Build Coastguard Worker         let trigger_evt = Event::new()?;
64*bb4ee6a4SAndroid Build Coastguard Worker         let resample_evt = Event::new()?;
65*bb4ee6a4SAndroid Build Coastguard Worker         Ok(IrqLevelEvent {
66*bb4ee6a4SAndroid Build Coastguard Worker             trigger_evt,
67*bb4ee6a4SAndroid Build Coastguard Worker             resample_evt,
68*bb4ee6a4SAndroid Build Coastguard Worker         })
69*bb4ee6a4SAndroid Build Coastguard Worker     }
70*bb4ee6a4SAndroid Build Coastguard Worker 
try_clone(&self) -> Result<IrqLevelEvent>71*bb4ee6a4SAndroid Build Coastguard Worker     pub fn try_clone(&self) -> Result<IrqLevelEvent> {
72*bb4ee6a4SAndroid Build Coastguard Worker         let trigger_evt = self.trigger_evt.try_clone()?;
73*bb4ee6a4SAndroid Build Coastguard Worker         let resample_evt = self.resample_evt.try_clone()?;
74*bb4ee6a4SAndroid Build Coastguard Worker         Ok(IrqLevelEvent {
75*bb4ee6a4SAndroid Build Coastguard Worker             trigger_evt,
76*bb4ee6a4SAndroid Build Coastguard Worker             resample_evt,
77*bb4ee6a4SAndroid Build Coastguard Worker         })
78*bb4ee6a4SAndroid Build Coastguard Worker     }
79*bb4ee6a4SAndroid Build Coastguard Worker 
80*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates an instance of IrqLevelEvent from an existing pair of events.
from_event_pair(trigger_evt: Event, resample_evt: Event) -> IrqLevelEvent81*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_event_pair(trigger_evt: Event, resample_evt: Event) -> IrqLevelEvent {
82*bb4ee6a4SAndroid Build Coastguard Worker         IrqLevelEvent {
83*bb4ee6a4SAndroid Build Coastguard Worker             trigger_evt,
84*bb4ee6a4SAndroid Build Coastguard Worker             resample_evt,
85*bb4ee6a4SAndroid Build Coastguard Worker         }
86*bb4ee6a4SAndroid Build Coastguard Worker     }
87*bb4ee6a4SAndroid Build Coastguard Worker 
get_trigger(&self) -> &Event88*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_trigger(&self) -> &Event {
89*bb4ee6a4SAndroid Build Coastguard Worker         &self.trigger_evt
90*bb4ee6a4SAndroid Build Coastguard Worker     }
91*bb4ee6a4SAndroid Build Coastguard Worker 
get_resample(&self) -> &Event92*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_resample(&self) -> &Event {
93*bb4ee6a4SAndroid Build Coastguard Worker         &self.resample_evt
94*bb4ee6a4SAndroid Build Coastguard Worker     }
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker     /// Allows backend to inject interrupt (typically into guest).
trigger(&self) -> Result<()>97*bb4ee6a4SAndroid Build Coastguard Worker     pub fn trigger(&self) -> Result<()> {
98*bb4ee6a4SAndroid Build Coastguard Worker         self.trigger_evt.signal()
99*bb4ee6a4SAndroid Build Coastguard Worker     }
100*bb4ee6a4SAndroid Build Coastguard Worker 
101*bb4ee6a4SAndroid Build Coastguard Worker     /// Allows code servicing interrupt to consume or clear the event.
clear_trigger(&self)102*bb4ee6a4SAndroid Build Coastguard Worker     pub fn clear_trigger(&self) {
103*bb4ee6a4SAndroid Build Coastguard Worker         let _ = self.trigger_evt.wait();
104*bb4ee6a4SAndroid Build Coastguard Worker     }
105*bb4ee6a4SAndroid Build Coastguard Worker 
106*bb4ee6a4SAndroid Build Coastguard Worker     /// Allows code servicing interrupt to signal that processing is done and that the backend
107*bb4ee6a4SAndroid Build Coastguard Worker     /// should go ahead and re-trigger it if there is more work needs to be done.
108*bb4ee6a4SAndroid Build Coastguard Worker     /// Note that typically resampling is signalled not by individual backends, but rather
109*bb4ee6a4SAndroid Build Coastguard Worker     /// by the code implementing interrupt controller.
trigger_resample(&self) -> Result<()>110*bb4ee6a4SAndroid Build Coastguard Worker     pub fn trigger_resample(&self) -> Result<()> {
111*bb4ee6a4SAndroid Build Coastguard Worker         self.resample_evt.signal()
112*bb4ee6a4SAndroid Build Coastguard Worker     }
113*bb4ee6a4SAndroid Build Coastguard Worker 
114*bb4ee6a4SAndroid Build Coastguard Worker     /// Allows backend to consume or clear the resample event.
clear_resample(&self)115*bb4ee6a4SAndroid Build Coastguard Worker     pub fn clear_resample(&self) {
116*bb4ee6a4SAndroid Build Coastguard Worker         let _ = self.resample_evt.wait();
117*bb4ee6a4SAndroid Build Coastguard Worker     }
118*bb4ee6a4SAndroid Build Coastguard Worker }
119*bb4ee6a4SAndroid Build Coastguard Worker 
120*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptors for IrqEdgeEvent {
as_raw_descriptors(&self) -> Vec<RawDescriptor>121*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptors(&self) -> Vec<RawDescriptor> {
122*bb4ee6a4SAndroid Build Coastguard Worker         vec![self.0.as_raw_descriptor()]
123*bb4ee6a4SAndroid Build Coastguard Worker     }
124*bb4ee6a4SAndroid Build Coastguard Worker }
125*bb4ee6a4SAndroid Build Coastguard Worker 
126*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptors for IrqLevelEvent {
as_raw_descriptors(&self) -> Vec<RawDescriptor>127*bb4ee6a4SAndroid Build Coastguard Worker     fn as_raw_descriptors(&self) -> Vec<RawDescriptor> {
128*bb4ee6a4SAndroid Build Coastguard Worker         vec![
129*bb4ee6a4SAndroid Build Coastguard Worker             self.trigger_evt.as_raw_descriptor(),
130*bb4ee6a4SAndroid Build Coastguard Worker             self.resample_evt.as_raw_descriptor(),
131*bb4ee6a4SAndroid Build Coastguard Worker         ]
132*bb4ee6a4SAndroid Build Coastguard Worker     }
133*bb4ee6a4SAndroid Build Coastguard Worker }
134