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