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