1 // Copyright 2022 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use base::{AsRawDescriptor, AsRawDescriptors, Event, RawDescriptor, Result}; 6 7 /// A structure suitable for implementing edge triggered interrupts in device backends. 8 pub struct IrqEdgeEvent(Event); 9 10 impl IrqEdgeEvent { new() -> Result<IrqEdgeEvent>11 pub fn new() -> Result<IrqEdgeEvent> { 12 Event::new().map(IrqEdgeEvent) 13 } 14 try_clone(&self) -> Result<IrqEdgeEvent>15 pub fn try_clone(&self) -> Result<IrqEdgeEvent> { 16 self.0.try_clone().map(IrqEdgeEvent) 17 } 18 19 /// Creates an instance of IrqLevelEvent from an existing event. from_event(trigger_evt: Event) -> IrqEdgeEvent20 pub fn from_event(trigger_evt: Event) -> IrqEdgeEvent { 21 IrqEdgeEvent(trigger_evt) 22 } 23 get_trigger(&self) -> &Event24 pub fn get_trigger(&self) -> &Event { 25 &self.0 26 } 27 trigger(&self) -> Result<()>28 pub fn trigger(&self) -> Result<()> { 29 self.0.write(1) 30 } 31 clear_trigger(&self)32 pub fn clear_trigger(&self) { 33 let _ = self.0.read(); 34 } 35 } 36 37 /// A structure suitable for implementing level triggered interrupts in device backends. 38 pub struct IrqLevelEvent { 39 /// An event used by the device backend to signal hypervisor/VM about data or new unit 40 /// of work being available. 41 trigger_evt: Event, 42 /// An event used by the hypervisor to signal device backend that it completed processing 43 /// a unit of work and that device should re-raise `trigger_evt` if there is additional 44 /// work needs to be done. 45 resample_evt: Event, 46 } 47 48 impl IrqLevelEvent { new() -> Result<IrqLevelEvent>49 pub fn new() -> Result<IrqLevelEvent> { 50 let trigger_evt = Event::new()?; 51 let resample_evt = Event::new()?; 52 Ok(IrqLevelEvent { 53 trigger_evt, 54 resample_evt, 55 }) 56 } 57 try_clone(&self) -> Result<IrqLevelEvent>58 pub fn try_clone(&self) -> Result<IrqLevelEvent> { 59 let trigger_evt = self.trigger_evt.try_clone()?; 60 let resample_evt = self.resample_evt.try_clone()?; 61 Ok(IrqLevelEvent { 62 trigger_evt, 63 resample_evt, 64 }) 65 } 66 67 /// Creates an instance of IrqLevelEvent from an existing pair of events. from_event_pair(trigger_evt: Event, resample_evt: Event) -> IrqLevelEvent68 pub fn from_event_pair(trigger_evt: Event, resample_evt: Event) -> IrqLevelEvent { 69 IrqLevelEvent { 70 trigger_evt, 71 resample_evt, 72 } 73 } 74 get_trigger(&self) -> &Event75 pub fn get_trigger(&self) -> &Event { 76 &self.trigger_evt 77 } 78 get_resample(&self) -> &Event79 pub fn get_resample(&self) -> &Event { 80 &self.resample_evt 81 } 82 83 /// Allows backend to inject interrupt (typically into guest). trigger(&self) -> Result<()>84 pub fn trigger(&self) -> Result<()> { 85 self.trigger_evt.write(1) 86 } 87 88 /// Allows code servicing interrupt to consume or clear the event. clear_trigger(&self)89 pub fn clear_trigger(&self) { 90 let _ = self.trigger_evt.read(); 91 } 92 93 /// Allows code servicing interrupt to signal that processing is done and that the backend 94 /// should go ahead and re-trigger it if there is more work needs to be done. 95 /// Note that typically resampling is signalled not by individual backends, but rather 96 /// by the code implementing interrupt controller. trigger_resample(&self) -> Result<()>97 pub fn trigger_resample(&self) -> Result<()> { 98 self.resample_evt.write(1) 99 } 100 101 /// Allows backend to consume or clear the resample event. clear_resample(&self)102 pub fn clear_resample(&self) { 103 let _ = self.resample_evt.read(); 104 } 105 } 106 107 impl AsRawDescriptors for IrqEdgeEvent { as_raw_descriptors(&self) -> Vec<RawDescriptor>108 fn as_raw_descriptors(&self) -> Vec<RawDescriptor> { 109 vec![self.0.as_raw_descriptor()] 110 } 111 } 112 113 impl AsRawDescriptors for IrqLevelEvent { as_raw_descriptors(&self) -> Vec<RawDescriptor>114 fn as_raw_descriptors(&self) -> Vec<RawDescriptor> { 115 vec![ 116 self.trigger_evt.as_raw_descriptor(), 117 self.resample_evt.as_raw_descriptor(), 118 ] 119 } 120 } 121