1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 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::error; 6*bb4ee6a4SAndroid Build Coastguard Worker use base::Error; 7*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 8*bb4ee6a4SAndroid Build Coastguard Worker use base::Result; 9*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::kvm::KvmVcpu; 10*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::HypervisorCap; 11*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::IrqRoute; 12*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MPState; 13*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::Vcpu; 14*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 15*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VmAArch64; 16*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "riscv64")] 17*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VmRiscv64; 18*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 19*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VmX86_64; 20*bb4ee6a4SAndroid Build Coastguard Worker use kvm_sys::kvm_mp_state; 21*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator; 22*bb4ee6a4SAndroid Build Coastguard Worker 23*bb4ee6a4SAndroid Build Coastguard Worker use crate::Bus; 24*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEdgeEvent; 25*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEventSource; 26*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqLevelEvent; 27*bb4ee6a4SAndroid Build Coastguard Worker 28*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 29*bb4ee6a4SAndroid Build Coastguard Worker mod x86_64; 30*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "x86_64")] 31*bb4ee6a4SAndroid Build Coastguard Worker pub use x86_64::*; 32*bb4ee6a4SAndroid Build Coastguard Worker 33*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 34*bb4ee6a4SAndroid Build Coastguard Worker mod aarch64; 35*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 36*bb4ee6a4SAndroid Build Coastguard Worker pub use aarch64::*; 37*bb4ee6a4SAndroid Build Coastguard Worker 38*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "riscv64")] 39*bb4ee6a4SAndroid Build Coastguard Worker mod riscv64; 40*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(target_arch = "riscv64")] 41*bb4ee6a4SAndroid Build Coastguard Worker pub use riscv64::*; 42*bb4ee6a4SAndroid Build Coastguard Worker 43*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChip; 44*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqChipCap; 45*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqEventIndex; 46*bb4ee6a4SAndroid Build Coastguard Worker use crate::VcpuRunState; 47*bb4ee6a4SAndroid Build Coastguard Worker 48*bb4ee6a4SAndroid Build Coastguard Worker /// This IrqChip only works with Kvm so we only implement it for KvmVcpu. 49*bb4ee6a4SAndroid Build Coastguard Worker impl IrqChip for KvmKernelIrqChip { 50*bb4ee6a4SAndroid Build Coastguard Worker /// Add a vcpu to the irq chip. add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()>51*bb4ee6a4SAndroid Build Coastguard Worker fn add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()> { 52*bb4ee6a4SAndroid Build Coastguard Worker let vcpu: &KvmVcpu = vcpu 53*bb4ee6a4SAndroid Build Coastguard Worker .downcast_ref() 54*bb4ee6a4SAndroid Build Coastguard Worker .expect("KvmKernelIrqChip::add_vcpu called with non-KvmVcpu"); 55*bb4ee6a4SAndroid Build Coastguard Worker self.vcpus.lock()[vcpu_id] = Some(vcpu.try_clone()?); 56*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 57*bb4ee6a4SAndroid Build Coastguard Worker } 58*bb4ee6a4SAndroid Build Coastguard Worker 59*bb4ee6a4SAndroid Build Coastguard Worker /// Register an event with edge-trigger semantic that can trigger an interrupt 60*bb4ee6a4SAndroid Build Coastguard Worker /// for a particular GSI. register_edge_irq_event( &mut self, irq: u32, irq_event: &IrqEdgeEvent, _source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>61*bb4ee6a4SAndroid Build Coastguard Worker fn register_edge_irq_event( 62*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 63*bb4ee6a4SAndroid Build Coastguard Worker irq: u32, 64*bb4ee6a4SAndroid Build Coastguard Worker irq_event: &IrqEdgeEvent, 65*bb4ee6a4SAndroid Build Coastguard Worker _source: IrqEventSource, 66*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Option<IrqEventIndex>> { 67*bb4ee6a4SAndroid Build Coastguard Worker self.vm.register_irqfd(irq, irq_event.get_trigger(), None)?; 68*bb4ee6a4SAndroid Build Coastguard Worker Ok(None) 69*bb4ee6a4SAndroid Build Coastguard Worker } 70*bb4ee6a4SAndroid Build Coastguard Worker 71*bb4ee6a4SAndroid Build Coastguard Worker /// Unregister an event with edge-trigger semantic for a particular GSI. unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()>72*bb4ee6a4SAndroid Build Coastguard Worker fn unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()> { 73*bb4ee6a4SAndroid Build Coastguard Worker self.vm.unregister_irqfd(irq, irq_event.get_trigger()) 74*bb4ee6a4SAndroid Build Coastguard Worker } 75*bb4ee6a4SAndroid Build Coastguard Worker 76*bb4ee6a4SAndroid Build Coastguard Worker /// Register an event with level-trigger semantic that can trigger an interrupt 77*bb4ee6a4SAndroid Build Coastguard Worker /// for a particular GSI. register_level_irq_event( &mut self, irq: u32, irq_event: &IrqLevelEvent, _source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>78*bb4ee6a4SAndroid Build Coastguard Worker fn register_level_irq_event( 79*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 80*bb4ee6a4SAndroid Build Coastguard Worker irq: u32, 81*bb4ee6a4SAndroid Build Coastguard Worker irq_event: &IrqLevelEvent, 82*bb4ee6a4SAndroid Build Coastguard Worker _source: IrqEventSource, 83*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Option<IrqEventIndex>> { 84*bb4ee6a4SAndroid Build Coastguard Worker self.vm 85*bb4ee6a4SAndroid Build Coastguard Worker .register_irqfd(irq, irq_event.get_trigger(), Some(irq_event.get_resample()))?; 86*bb4ee6a4SAndroid Build Coastguard Worker Ok(None) 87*bb4ee6a4SAndroid Build Coastguard Worker } 88*bb4ee6a4SAndroid Build Coastguard Worker 89*bb4ee6a4SAndroid Build Coastguard Worker /// Unregister an event with level-trigger semantic for a particular GSI. unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()>90*bb4ee6a4SAndroid Build Coastguard Worker fn unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()> { 91*bb4ee6a4SAndroid Build Coastguard Worker self.vm.unregister_irqfd(irq, irq_event.get_trigger()) 92*bb4ee6a4SAndroid Build Coastguard Worker } 93*bb4ee6a4SAndroid Build Coastguard Worker 94*bb4ee6a4SAndroid Build Coastguard Worker /// Route an IRQ line to an interrupt controller, or to a particular MSI vector. route_irq(&mut self, route: IrqRoute) -> Result<()>95*bb4ee6a4SAndroid Build Coastguard Worker fn route_irq(&mut self, route: IrqRoute) -> Result<()> { 96*bb4ee6a4SAndroid Build Coastguard Worker let mut routes = self.routes.lock(); 97*bb4ee6a4SAndroid Build Coastguard Worker routes.retain(|r| r.gsi != route.gsi); 98*bb4ee6a4SAndroid Build Coastguard Worker 99*bb4ee6a4SAndroid Build Coastguard Worker routes.push(route); 100*bb4ee6a4SAndroid Build Coastguard Worker 101*bb4ee6a4SAndroid Build Coastguard Worker self.vm.set_gsi_routing(&routes) 102*bb4ee6a4SAndroid Build Coastguard Worker } 103*bb4ee6a4SAndroid Build Coastguard Worker 104*bb4ee6a4SAndroid Build Coastguard Worker /// Replace all irq routes with the supplied routes set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()>105*bb4ee6a4SAndroid Build Coastguard Worker fn set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()> { 106*bb4ee6a4SAndroid Build Coastguard Worker let mut current_routes = self.routes.lock(); 107*bb4ee6a4SAndroid Build Coastguard Worker *current_routes = routes.to_vec(); 108*bb4ee6a4SAndroid Build Coastguard Worker 109*bb4ee6a4SAndroid Build Coastguard Worker self.vm.set_gsi_routing(¤t_routes) 110*bb4ee6a4SAndroid Build Coastguard Worker } 111*bb4ee6a4SAndroid Build Coastguard Worker 112*bb4ee6a4SAndroid Build Coastguard Worker /// Return a vector of all registered irq numbers and their associated events and event 113*bb4ee6a4SAndroid Build Coastguard Worker /// indices. These should be used by the main thread to wait for irq events. 114*bb4ee6a4SAndroid Build Coastguard Worker /// For the KvmKernelIrqChip, the kernel handles listening to irq events being triggered by 115*bb4ee6a4SAndroid Build Coastguard Worker /// devices, so this function always returns an empty Vec. irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>116*bb4ee6a4SAndroid Build Coastguard Worker fn irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>> { 117*bb4ee6a4SAndroid Build Coastguard Worker Ok(Vec::new()) 118*bb4ee6a4SAndroid Build Coastguard Worker } 119*bb4ee6a4SAndroid Build Coastguard Worker 120*bb4ee6a4SAndroid Build Coastguard Worker /// Either assert or deassert an IRQ line. Sends to either an interrupt controller, or does 121*bb4ee6a4SAndroid Build Coastguard Worker /// a send_msi if the irq is associated with an MSI. 122*bb4ee6a4SAndroid Build Coastguard Worker /// For the KvmKernelIrqChip this simply calls the KVM_SET_IRQ_LINE ioctl. service_irq(&mut self, irq: u32, level: bool) -> Result<()>123*bb4ee6a4SAndroid Build Coastguard Worker fn service_irq(&mut self, irq: u32, level: bool) -> Result<()> { 124*bb4ee6a4SAndroid Build Coastguard Worker self.vm.set_irq_line(irq, level) 125*bb4ee6a4SAndroid Build Coastguard Worker } 126*bb4ee6a4SAndroid Build Coastguard Worker 127*bb4ee6a4SAndroid Build Coastguard Worker /// Service an IRQ event by asserting then deasserting an IRQ line. The associated Event 128*bb4ee6a4SAndroid Build Coastguard Worker /// that triggered the irq event will be read from. If the irq is associated with a resample 129*bb4ee6a4SAndroid Build Coastguard Worker /// Event, then the deassert will only happen after an EOI is broadcast for a vector 130*bb4ee6a4SAndroid Build Coastguard Worker /// associated with the irq line. 131*bb4ee6a4SAndroid Build Coastguard Worker /// This function should never be called on KvmKernelIrqChip. service_irq_event(&mut self, _event_index: IrqEventIndex) -> Result<()>132*bb4ee6a4SAndroid Build Coastguard Worker fn service_irq_event(&mut self, _event_index: IrqEventIndex) -> Result<()> { 133*bb4ee6a4SAndroid Build Coastguard Worker error!("service_irq_event should never be called for KvmKernelIrqChip"); 134*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 135*bb4ee6a4SAndroid Build Coastguard Worker } 136*bb4ee6a4SAndroid Build Coastguard Worker 137*bb4ee6a4SAndroid Build Coastguard Worker /// Broadcast an end of interrupt. 138*bb4ee6a4SAndroid Build Coastguard Worker /// This should never be called on a KvmKernelIrqChip because a KVM vcpu should never exit 139*bb4ee6a4SAndroid Build Coastguard Worker /// with the KVM_EXIT_EOI_BROADCAST reason when an in-kernel irqchip exists. broadcast_eoi(&self, _vector: u8) -> Result<()>140*bb4ee6a4SAndroid Build Coastguard Worker fn broadcast_eoi(&self, _vector: u8) -> Result<()> { 141*bb4ee6a4SAndroid Build Coastguard Worker error!("broadcast_eoi should never be called for KvmKernelIrqChip"); 142*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 143*bb4ee6a4SAndroid Build Coastguard Worker } 144*bb4ee6a4SAndroid Build Coastguard Worker 145*bb4ee6a4SAndroid Build Coastguard Worker /// Injects any pending interrupts for `vcpu`. 146*bb4ee6a4SAndroid Build Coastguard Worker /// For KvmKernelIrqChip this is a no-op because KVM is responsible for injecting all 147*bb4ee6a4SAndroid Build Coastguard Worker /// interrupts. inject_interrupts(&self, _vcpu: &dyn Vcpu) -> Result<()>148*bb4ee6a4SAndroid Build Coastguard Worker fn inject_interrupts(&self, _vcpu: &dyn Vcpu) -> Result<()> { 149*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 150*bb4ee6a4SAndroid Build Coastguard Worker } 151*bb4ee6a4SAndroid Build Coastguard Worker 152*bb4ee6a4SAndroid Build Coastguard Worker /// Notifies the irq chip that the specified VCPU has executed a halt instruction. 153*bb4ee6a4SAndroid Build Coastguard Worker /// For KvmKernelIrqChip this is a no-op because KVM handles VCPU blocking. halted(&self, _vcpu_id: usize)154*bb4ee6a4SAndroid Build Coastguard Worker fn halted(&self, _vcpu_id: usize) {} 155*bb4ee6a4SAndroid Build Coastguard Worker 156*bb4ee6a4SAndroid Build Coastguard Worker /// Blocks until `vcpu` is in a runnable state or until interrupted by 157*bb4ee6a4SAndroid Build Coastguard Worker /// `IrqChip::kick_halted_vcpus`. Returns `VcpuRunState::Runnable if vcpu is runnable, or 158*bb4ee6a4SAndroid Build Coastguard Worker /// `VcpuRunState::Interrupted` if the wait was interrupted. 159*bb4ee6a4SAndroid Build Coastguard Worker /// For KvmKernelIrqChip this is a no-op and always returns Runnable because KVM handles VCPU 160*bb4ee6a4SAndroid Build Coastguard Worker /// blocking. wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState>161*bb4ee6a4SAndroid Build Coastguard Worker fn wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState> { 162*bb4ee6a4SAndroid Build Coastguard Worker Ok(VcpuRunState::Runnable) 163*bb4ee6a4SAndroid Build Coastguard Worker } 164*bb4ee6a4SAndroid Build Coastguard Worker 165*bb4ee6a4SAndroid Build Coastguard Worker /// Makes unrunnable VCPUs return immediately from `wait_until_runnable`. 166*bb4ee6a4SAndroid Build Coastguard Worker /// For KvmKernelIrqChip this is a no-op because KVM handles VCPU blocking. kick_halted_vcpus(&self)167*bb4ee6a4SAndroid Build Coastguard Worker fn kick_halted_vcpus(&self) {} 168*bb4ee6a4SAndroid Build Coastguard Worker 169*bb4ee6a4SAndroid Build Coastguard Worker /// Get the current MP state of the specified VCPU. get_mp_state(&self, vcpu_id: usize) -> Result<MPState>170*bb4ee6a4SAndroid Build Coastguard Worker fn get_mp_state(&self, vcpu_id: usize) -> Result<MPState> { 171*bb4ee6a4SAndroid Build Coastguard Worker match self.vcpus.lock().get(vcpu_id) { 172*bb4ee6a4SAndroid Build Coastguard Worker Some(Some(vcpu)) => Ok(MPState::from(&vcpu.get_mp_state()?)), 173*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(Error::new(libc::ENOENT)), 174*bb4ee6a4SAndroid Build Coastguard Worker } 175*bb4ee6a4SAndroid Build Coastguard Worker } 176*bb4ee6a4SAndroid Build Coastguard Worker 177*bb4ee6a4SAndroid Build Coastguard Worker /// Set the current MP state of the specified VCPU. set_mp_state(&mut self, vcpu_id: usize, state: &MPState) -> Result<()>178*bb4ee6a4SAndroid Build Coastguard Worker fn set_mp_state(&mut self, vcpu_id: usize, state: &MPState) -> Result<()> { 179*bb4ee6a4SAndroid Build Coastguard Worker match self.vcpus.lock().get(vcpu_id) { 180*bb4ee6a4SAndroid Build Coastguard Worker Some(Some(vcpu)) => vcpu.set_mp_state(&kvm_mp_state::from(state)), 181*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(Error::new(libc::ENOENT)), 182*bb4ee6a4SAndroid Build Coastguard Worker } 183*bb4ee6a4SAndroid Build Coastguard Worker } 184*bb4ee6a4SAndroid Build Coastguard Worker 185*bb4ee6a4SAndroid Build Coastguard Worker /// Attempt to clone this IrqChip instance. try_clone(&self) -> Result<Self>186*bb4ee6a4SAndroid Build Coastguard Worker fn try_clone(&self) -> Result<Self> { 187*bb4ee6a4SAndroid Build Coastguard Worker // Because the KvmKernelIrqchip struct contains arch-specific fields we leave the 188*bb4ee6a4SAndroid Build Coastguard Worker // cloning to arch-specific implementations 189*bb4ee6a4SAndroid Build Coastguard Worker self.arch_try_clone() 190*bb4ee6a4SAndroid Build Coastguard Worker } 191*bb4ee6a4SAndroid Build Coastguard Worker 192*bb4ee6a4SAndroid Build Coastguard Worker /// Finalize irqchip setup. Should be called once all devices have registered irq events and 193*bb4ee6a4SAndroid Build Coastguard Worker /// been added to the io_bus and mmio_bus. 194*bb4ee6a4SAndroid Build Coastguard Worker /// KvmKernelIrqChip does not need to do anything here. finalize_devices( &mut self, _resources: &mut SystemAllocator, _io_bus: &Bus, _mmio_bus: &Bus, ) -> Result<()>195*bb4ee6a4SAndroid Build Coastguard Worker fn finalize_devices( 196*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 197*bb4ee6a4SAndroid Build Coastguard Worker _resources: &mut SystemAllocator, 198*bb4ee6a4SAndroid Build Coastguard Worker _io_bus: &Bus, 199*bb4ee6a4SAndroid Build Coastguard Worker _mmio_bus: &Bus, 200*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> { 201*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 202*bb4ee6a4SAndroid Build Coastguard Worker } 203*bb4ee6a4SAndroid Build Coastguard Worker 204*bb4ee6a4SAndroid Build Coastguard Worker /// The KvmKernelIrqChip doesn't process irq events itself so this function does nothing. process_delayed_irq_events(&mut self) -> Result<()>205*bb4ee6a4SAndroid Build Coastguard Worker fn process_delayed_irq_events(&mut self) -> Result<()> { 206*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 207*bb4ee6a4SAndroid Build Coastguard Worker } 208*bb4ee6a4SAndroid Build Coastguard Worker irq_delayed_event_token(&self) -> Result<Option<Event>>209*bb4ee6a4SAndroid Build Coastguard Worker fn irq_delayed_event_token(&self) -> Result<Option<Event>> { 210*bb4ee6a4SAndroid Build Coastguard Worker Ok(None) 211*bb4ee6a4SAndroid Build Coastguard Worker } 212*bb4ee6a4SAndroid Build Coastguard Worker check_capability(&self, c: IrqChipCap) -> bool213*bb4ee6a4SAndroid Build Coastguard Worker fn check_capability(&self, c: IrqChipCap) -> bool { 214*bb4ee6a4SAndroid Build Coastguard Worker match c { 215*bb4ee6a4SAndroid Build Coastguard Worker IrqChipCap::TscDeadlineTimer => self 216*bb4ee6a4SAndroid Build Coastguard Worker .vm 217*bb4ee6a4SAndroid Build Coastguard Worker .get_hypervisor() 218*bb4ee6a4SAndroid Build Coastguard Worker .check_capability(HypervisorCap::TscDeadlineTimer), 219*bb4ee6a4SAndroid Build Coastguard Worker IrqChipCap::X2Apic => true, 220*bb4ee6a4SAndroid Build Coastguard Worker IrqChipCap::MpStateGetSet => true, 221*bb4ee6a4SAndroid Build Coastguard Worker } 222*bb4ee6a4SAndroid Build Coastguard Worker } 223*bb4ee6a4SAndroid Build Coastguard Worker } 224