• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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