xref: /aosp_15_r20/external/crosvm/devices/src/irqchip/gunyah.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 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::Event;
6*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
7*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::gunyah::GunyahVm;
8*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::DeviceKind;
9*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqRoute;
10*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MPState;
11*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vcpu;
12*bb4ee6a4SAndroid Build Coastguard Worker 
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChip;
14*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChipAArch64;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChipCap;
17*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEdgeEvent;
18*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEventIndex;
19*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEventSource;
20*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqLevelEvent;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuRunState;
22*bb4ee6a4SAndroid Build Coastguard Worker 
23*bb4ee6a4SAndroid Build Coastguard Worker pub struct GunyahIrqChip {
24*bb4ee6a4SAndroid Build Coastguard Worker     vm: GunyahVm,
25*bb4ee6a4SAndroid Build Coastguard Worker }
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker impl GunyahIrqChip {
new(vm: GunyahVm) -> Result<GunyahIrqChip>28*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(vm: GunyahVm) -> Result<GunyahIrqChip> {
29*bb4ee6a4SAndroid Build Coastguard Worker         Ok(GunyahIrqChip { vm })
30*bb4ee6a4SAndroid Build Coastguard Worker     }
31*bb4ee6a4SAndroid Build Coastguard Worker }
32*bb4ee6a4SAndroid Build Coastguard Worker 
33*bb4ee6a4SAndroid Build Coastguard Worker impl IrqChip for GunyahIrqChip {
34*bb4ee6a4SAndroid Build Coastguard Worker     // GunyahIrqChip doesn't need to track VCPUs.
add_vcpu(&mut self, _vcpu_id: usize, _vcpu: &dyn Vcpu) -> Result<()>35*bb4ee6a4SAndroid Build Coastguard Worker     fn add_vcpu(&mut self, _vcpu_id: usize, _vcpu: &dyn Vcpu) -> Result<()> {
36*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
37*bb4ee6a4SAndroid Build Coastguard Worker     }
38*bb4ee6a4SAndroid Build Coastguard Worker 
register_edge_irq_event( &mut self, irq: u32, irq_event: &IrqEdgeEvent, _source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>39*bb4ee6a4SAndroid Build Coastguard Worker     fn register_edge_irq_event(
40*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
41*bb4ee6a4SAndroid Build Coastguard Worker         irq: u32,
42*bb4ee6a4SAndroid Build Coastguard Worker         irq_event: &IrqEdgeEvent,
43*bb4ee6a4SAndroid Build Coastguard Worker         _source: IrqEventSource,
44*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Option<IrqEventIndex>> {
45*bb4ee6a4SAndroid Build Coastguard Worker         self.vm
46*bb4ee6a4SAndroid Build Coastguard Worker             .register_irqfd(irq, irq_event.get_trigger(), false)?;
47*bb4ee6a4SAndroid Build Coastguard Worker         Ok(None)
48*bb4ee6a4SAndroid Build Coastguard Worker     }
49*bb4ee6a4SAndroid Build Coastguard Worker 
unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()>50*bb4ee6a4SAndroid Build Coastguard Worker     fn unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()> {
51*bb4ee6a4SAndroid Build Coastguard Worker         self.vm.unregister_irqfd(irq, irq_event.get_trigger())?;
52*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
53*bb4ee6a4SAndroid Build Coastguard Worker     }
54*bb4ee6a4SAndroid Build Coastguard Worker 
register_level_irq_event( &mut self, irq: u32, irq_event: &IrqLevelEvent, _source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>55*bb4ee6a4SAndroid Build Coastguard Worker     fn register_level_irq_event(
56*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
57*bb4ee6a4SAndroid Build Coastguard Worker         irq: u32,
58*bb4ee6a4SAndroid Build Coastguard Worker         irq_event: &IrqLevelEvent,
59*bb4ee6a4SAndroid Build Coastguard Worker         _source: IrqEventSource,
60*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Option<IrqEventIndex>> {
61*bb4ee6a4SAndroid Build Coastguard Worker         self.vm.register_irqfd(irq, irq_event.get_trigger(), true)?;
62*bb4ee6a4SAndroid Build Coastguard Worker         Ok(None)
63*bb4ee6a4SAndroid Build Coastguard Worker     }
64*bb4ee6a4SAndroid Build Coastguard Worker 
unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()>65*bb4ee6a4SAndroid Build Coastguard Worker     fn unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()> {
66*bb4ee6a4SAndroid Build Coastguard Worker         self.vm.unregister_irqfd(irq, irq_event.get_trigger())?;
67*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
68*bb4ee6a4SAndroid Build Coastguard Worker     }
69*bb4ee6a4SAndroid Build Coastguard Worker 
route_irq(&mut self, _route: IrqRoute) -> Result<()>70*bb4ee6a4SAndroid Build Coastguard Worker     fn route_irq(&mut self, _route: IrqRoute) -> Result<()> {
71*bb4ee6a4SAndroid Build Coastguard Worker         unimplemented!()
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker 
set_irq_routes(&mut self, _routes: &[IrqRoute]) -> Result<()>74*bb4ee6a4SAndroid Build Coastguard Worker     fn set_irq_routes(&mut self, _routes: &[IrqRoute]) -> Result<()> {
75*bb4ee6a4SAndroid Build Coastguard Worker         unimplemented!()
76*bb4ee6a4SAndroid Build Coastguard Worker     }
77*bb4ee6a4SAndroid Build Coastguard Worker 
78*bb4ee6a4SAndroid Build Coastguard Worker     /// Return a vector of all registered irq numbers and their associated events and event
79*bb4ee6a4SAndroid Build Coastguard Worker     /// indices. These should be used by the main thread to wait for irq events.
80*bb4ee6a4SAndroid Build Coastguard Worker     /// For the GunyahIrqChip, the kernel handles listening to irq events being triggered by
81*bb4ee6a4SAndroid Build Coastguard Worker     /// devices, so this function always returns an empty Vec.
irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>82*bb4ee6a4SAndroid Build Coastguard Worker     fn irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>> {
83*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Vec::new())
84*bb4ee6a4SAndroid Build Coastguard Worker     }
85*bb4ee6a4SAndroid Build Coastguard Worker 
service_irq(&mut self, _irq: u32, _level: bool) -> Result<()>86*bb4ee6a4SAndroid Build Coastguard Worker     fn service_irq(&mut self, _irq: u32, _level: bool) -> Result<()> {
87*bb4ee6a4SAndroid Build Coastguard Worker         unimplemented!()
88*bb4ee6a4SAndroid Build Coastguard Worker     }
89*bb4ee6a4SAndroid Build Coastguard Worker 
90*bb4ee6a4SAndroid Build Coastguard Worker     /// Service an IRQ event by asserting then deasserting an IRQ line. The associated Event
91*bb4ee6a4SAndroid Build Coastguard Worker     /// that triggered the irq event will be read from. If the irq is associated with a resample
92*bb4ee6a4SAndroid Build Coastguard Worker     /// Event, then the deassert will only happen after an EOI is broadcast for a vector
93*bb4ee6a4SAndroid Build Coastguard Worker     /// associated with the irq line.
94*bb4ee6a4SAndroid Build Coastguard Worker     /// This function should never be called on GunyahIrqChip.
service_irq_event(&mut self, _event_index: IrqEventIndex) -> Result<()>95*bb4ee6a4SAndroid Build Coastguard Worker     fn service_irq_event(&mut self, _event_index: IrqEventIndex) -> Result<()> {
96*bb4ee6a4SAndroid Build Coastguard Worker         unreachable!();
97*bb4ee6a4SAndroid Build Coastguard Worker     }
98*bb4ee6a4SAndroid Build Coastguard Worker 
99*bb4ee6a4SAndroid Build Coastguard Worker     /// Broadcast an end of interrupt.
100*bb4ee6a4SAndroid Build Coastguard Worker     /// This should never be called on a GunyahIrqChip because a Gunyah vcpu should never exit
101*bb4ee6a4SAndroid Build Coastguard Worker     /// with VcpuExit::IoapicEoi.
broadcast_eoi(&self, _vector: u8) -> Result<()>102*bb4ee6a4SAndroid Build Coastguard Worker     fn broadcast_eoi(&self, _vector: u8) -> Result<()> {
103*bb4ee6a4SAndroid Build Coastguard Worker         unreachable!();
104*bb4ee6a4SAndroid Build Coastguard Worker     }
105*bb4ee6a4SAndroid Build Coastguard Worker 
106*bb4ee6a4SAndroid Build Coastguard Worker     /// Injects any pending interrupts for `vcpu`.
107*bb4ee6a4SAndroid Build Coastguard Worker     /// For GunyahIrqChip this is a no-op because Gunyah is responsible for injecting all
108*bb4ee6a4SAndroid Build Coastguard Worker     /// interrupts.
inject_interrupts(&self, _vcpu: &dyn Vcpu) -> Result<()>109*bb4ee6a4SAndroid Build Coastguard Worker     fn inject_interrupts(&self, _vcpu: &dyn Vcpu) -> Result<()> {
110*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
111*bb4ee6a4SAndroid Build Coastguard Worker     }
112*bb4ee6a4SAndroid Build Coastguard Worker 
113*bb4ee6a4SAndroid Build Coastguard Worker     /// Notifies the irq chip that the specified VCPU has executed a halt instruction.
114*bb4ee6a4SAndroid Build Coastguard Worker     /// For GunyahIrqChip this is a no-op because Gunyah handles VCPU blocking.
halted(&self, _vcpu_id: usize)115*bb4ee6a4SAndroid Build Coastguard Worker     fn halted(&self, _vcpu_id: usize) {}
116*bb4ee6a4SAndroid Build Coastguard Worker 
wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState>117*bb4ee6a4SAndroid Build Coastguard Worker     fn wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState> {
118*bb4ee6a4SAndroid Build Coastguard Worker         // Gunyah handles vCPU blocking. From userspace perspective, vCPU is always runnable.
119*bb4ee6a4SAndroid Build Coastguard Worker         Ok(VcpuRunState::Runnable)
120*bb4ee6a4SAndroid Build Coastguard Worker     }
121*bb4ee6a4SAndroid Build Coastguard Worker 
122*bb4ee6a4SAndroid Build Coastguard Worker     /// Makes unrunnable VCPUs return immediately from `wait_until_runnable`.
123*bb4ee6a4SAndroid Build Coastguard Worker     /// For GunyahIrqChip this is a no-op because Gunyah handles VCPU blocking.
kick_halted_vcpus(&self)124*bb4ee6a4SAndroid Build Coastguard Worker     fn kick_halted_vcpus(&self) {}
125*bb4ee6a4SAndroid Build Coastguard Worker 
get_mp_state(&self, _vcpu_id: usize) -> Result<MPState>126*bb4ee6a4SAndroid Build Coastguard Worker     fn get_mp_state(&self, _vcpu_id: usize) -> Result<MPState> {
127*bb4ee6a4SAndroid Build Coastguard Worker         unimplemented!()
128*bb4ee6a4SAndroid Build Coastguard Worker     }
129*bb4ee6a4SAndroid Build Coastguard Worker 
set_mp_state(&mut self, _vcpu_id: usize, _state: &MPState) -> Result<()>130*bb4ee6a4SAndroid Build Coastguard Worker     fn set_mp_state(&mut self, _vcpu_id: usize, _state: &MPState) -> Result<()> {
131*bb4ee6a4SAndroid Build Coastguard Worker         unimplemented!()
132*bb4ee6a4SAndroid Build Coastguard Worker     }
133*bb4ee6a4SAndroid Build Coastguard Worker 
try_clone(&self) -> Result<Self> where Self: Sized,134*bb4ee6a4SAndroid Build Coastguard Worker     fn try_clone(&self) -> Result<Self>
135*bb4ee6a4SAndroid Build Coastguard Worker     where
136*bb4ee6a4SAndroid Build Coastguard Worker         Self: Sized,
137*bb4ee6a4SAndroid Build Coastguard Worker     {
138*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Self {
139*bb4ee6a4SAndroid Build Coastguard Worker             vm: self.vm.try_clone()?,
140*bb4ee6a4SAndroid Build Coastguard Worker         })
141*bb4ee6a4SAndroid Build Coastguard Worker     }
142*bb4ee6a4SAndroid Build Coastguard Worker 
finalize_devices( &mut self, _resources: &mut resources::SystemAllocator, _io_bus: &crate::Bus, _mmio_bus: &crate::Bus, ) -> Result<()>143*bb4ee6a4SAndroid Build Coastguard Worker     fn finalize_devices(
144*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
145*bb4ee6a4SAndroid Build Coastguard Worker         _resources: &mut resources::SystemAllocator,
146*bb4ee6a4SAndroid Build Coastguard Worker         _io_bus: &crate::Bus,
147*bb4ee6a4SAndroid Build Coastguard Worker         _mmio_bus: &crate::Bus,
148*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<()> {
149*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
150*bb4ee6a4SAndroid Build Coastguard Worker     }
151*bb4ee6a4SAndroid Build Coastguard Worker 
152*bb4ee6a4SAndroid Build Coastguard Worker     /// The GunyahIrqChip doesn't process irq events itself so this function does nothing.
process_delayed_irq_events(&mut self) -> Result<()>153*bb4ee6a4SAndroid Build Coastguard Worker     fn process_delayed_irq_events(&mut self) -> Result<()> {
154*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
155*bb4ee6a4SAndroid Build Coastguard Worker     }
156*bb4ee6a4SAndroid Build Coastguard Worker 
irq_delayed_event_token(&self) -> Result<Option<Event>>157*bb4ee6a4SAndroid Build Coastguard Worker     fn irq_delayed_event_token(&self) -> Result<Option<Event>> {
158*bb4ee6a4SAndroid Build Coastguard Worker         Ok(None)
159*bb4ee6a4SAndroid Build Coastguard Worker     }
160*bb4ee6a4SAndroid Build Coastguard Worker 
check_capability(&self, _c: IrqChipCap) -> bool161*bb4ee6a4SAndroid Build Coastguard Worker     fn check_capability(&self, _c: IrqChipCap) -> bool {
162*bb4ee6a4SAndroid Build Coastguard Worker         false
163*bb4ee6a4SAndroid Build Coastguard Worker     }
164*bb4ee6a4SAndroid Build Coastguard Worker }
165*bb4ee6a4SAndroid Build Coastguard Worker 
166*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
167*bb4ee6a4SAndroid Build Coastguard Worker impl IrqChipAArch64 for GunyahIrqChip {
try_box_clone(&self) -> Result<Box<dyn IrqChipAArch64>>168*bb4ee6a4SAndroid Build Coastguard Worker     fn try_box_clone(&self) -> Result<Box<dyn IrqChipAArch64>> {
169*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Box::new(self.try_clone()?))
170*bb4ee6a4SAndroid Build Coastguard Worker     }
171*bb4ee6a4SAndroid Build Coastguard Worker 
as_irq_chip(&self) -> &dyn IrqChip172*bb4ee6a4SAndroid Build Coastguard Worker     fn as_irq_chip(&self) -> &dyn IrqChip {
173*bb4ee6a4SAndroid Build Coastguard Worker         self
174*bb4ee6a4SAndroid Build Coastguard Worker     }
175*bb4ee6a4SAndroid Build Coastguard Worker 
as_irq_chip_mut(&mut self) -> &mut dyn IrqChip176*bb4ee6a4SAndroid Build Coastguard Worker     fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip {
177*bb4ee6a4SAndroid Build Coastguard Worker         self
178*bb4ee6a4SAndroid Build Coastguard Worker     }
179*bb4ee6a4SAndroid Build Coastguard Worker 
get_vgic_version(&self) -> DeviceKind180*bb4ee6a4SAndroid Build Coastguard Worker     fn get_vgic_version(&self) -> DeviceKind {
181*bb4ee6a4SAndroid Build Coastguard Worker         DeviceKind::ArmVgicV3
182*bb4ee6a4SAndroid Build Coastguard Worker     }
183*bb4ee6a4SAndroid Build Coastguard Worker 
finalize(&self) -> Result<()>184*bb4ee6a4SAndroid Build Coastguard Worker     fn finalize(&self) -> Result<()> {
185*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker }
188