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