pub struct KvmSplitIrqChip {
vm: KvmVm,
vcpus: Arc<Mutex<Vec<Option<KvmVcpu>>>>,
routes: Arc<Mutex<Vec<IrqRoute>>>,
pit: Arc<Mutex<Pit>>,
pic: Arc<Mutex<Pic>>,
ioapic: Arc<Mutex<Ioapic>>,
ioapic_pins: usize,
delayed_ioapic_irq_events: Arc<Mutex<Vec<usize>>>,
delayed_ioapic_irq_trigger: Event,
irq_events: Arc<Mutex<Vec<Option<IrqEvent>>>>,
}
Expand description
The KvmSplitIrqsChip supports KVM’s SPLIT_IRQCHIP feature, where the PIC and IOAPIC are emulated in userspace, while the local APICs are emulated in the kernel. The SPLIT_IRQCHIP feature only supports x86/x86_64 so we only define this IrqChip in crosvm for x86/x86_64.
Fields§
§vm: KvmVm
§vcpus: Arc<Mutex<Vec<Option<KvmVcpu>>>>
§routes: Arc<Mutex<Vec<IrqRoute>>>
§pit: Arc<Mutex<Pit>>
§pic: Arc<Mutex<Pic>>
§ioapic: Arc<Mutex<Ioapic>>
§ioapic_pins: usize
§delayed_ioapic_irq_events: Arc<Mutex<Vec<usize>>>
Vec of ioapic irq events that have been delayed because the ioapic was locked when service_irq was called on the irqchip. This prevents deadlocks when a Vcpu thread has locked the ioapic and the ioapic sends a AddMsiRoute signal to the main thread (which itself may be busy trying to call service_irq).
delayed_ioapic_irq_trigger: Event
Event which is meant to trigger process of any irqs events that were delayed.
irq_events: Arc<Mutex<Vec<Option<IrqEvent>>>>
Array of Events that devices will use to assert ioapic pins.
Implementations§
source§impl KvmSplitIrqChip
impl KvmSplitIrqChip
sourcefn routes_to_chips(&self, irq: u32) -> Vec<(IrqSourceChip, u32)>
fn routes_to_chips(&self, irq: u32) -> Vec<(IrqSourceChip, u32)>
Convenience function for determining which chips the supplied irq routes to.
sourcepub fn interrupt_requested(&self, vcpu_id: usize) -> bool
pub fn interrupt_requested(&self, vcpu_id: usize) -> bool
Return true if there is a pending interrupt for the specified vcpu. For KvmSplitIrqChip this calls interrupt_requested on the pic.
sourcepub fn get_external_interrupt(&self, vcpu_id: usize) -> Option<u8>
pub fn get_external_interrupt(&self, vcpu_id: usize) -> Option<u8>
Check if the specified vcpu has any pending interrupts. Returns None
for no interrupts,
otherwise Some::<u8>
should be the injected interrupt vector. For KvmSplitIrqChip
this calls get_external_interrupt
on the pic.
sourcefn register_irq_event(
&mut self,
irq: u32,
irq_event: &Event,
resample_event: Option<&Event>,
source: IrqEventSource
) -> Result<Option<IrqEventIndex>>
fn register_irq_event( &mut self, irq: u32, irq_event: &Event, resample_event: Option<&Event>, source: IrqEventSource ) -> Result<Option<IrqEventIndex>>
Register an event that can trigger an interrupt for a particular GSI.
Trait Implementations§
source§impl IrqChip for KvmSplitIrqChip
impl IrqChip for KvmSplitIrqChip
This IrqChip only works with Kvm so we only implement it for KvmVcpu.
source§fn add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()>
fn add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()>
Add a vcpu to the irq chip.
source§fn register_edge_irq_event(
&mut self,
irq: u32,
irq_event: &IrqEdgeEvent,
source: IrqEventSource
) -> Result<Option<IrqEventIndex>>
fn register_edge_irq_event( &mut self, irq: u32, irq_event: &IrqEdgeEvent, source: IrqEventSource ) -> Result<Option<IrqEventIndex>>
Register an event that can trigger an interrupt for a particular GSI.
source§fn route_irq(&mut self, route: IrqRoute) -> Result<()>
fn route_irq(&mut self, route: IrqRoute) -> Result<()>
Route an IRQ line to an interrupt controller, or to a particular MSI vector.
source§fn set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()>
fn set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()>
Replace all irq routes with the supplied routes
source§fn irq_event_tokens(
&self
) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>
fn irq_event_tokens( &self ) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>
Return a vector of all registered irq numbers and their associated events and event indices. These should be used by the main thread to wait for irq events.
source§fn service_irq(&mut self, irq: u32, level: bool) -> Result<()>
fn service_irq(&mut self, irq: u32, level: bool) -> Result<()>
Either assert or deassert an IRQ line. Sends to either an interrupt controller, or does a send_msi if the irq is associated with an MSI.
source§fn service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()>
fn service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()>
Service an IRQ event by asserting then deasserting an IRQ line. The associated Event that triggered the irq event will be read from. If the irq is associated with a resample Event, then the deassert will only happen after an EOI is broadcast for a vector associated with the irq line. For the KvmSplitIrqChip, this function identifies which chips the irq routes to, then attempts to call service_irq on those chips. If the ioapic is unable to be immediately locked, we add the irq to the delayed_ioapic_irq_events Vec (though we still read from the Event that triggered the irq event).
source§fn broadcast_eoi(&self, vector: u8) -> Result<()>
fn broadcast_eoi(&self, vector: u8) -> Result<()>
Broadcast an end of interrupt. For KvmSplitIrqChip this sends the EOI to the ioapic
source§fn inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()>
fn inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()>
Injects any pending interrupts for vcpu
.
For KvmSplitIrqChip this injects any PIC interrupts on vcpu_id 0.
source§fn halted(&self, _vcpu_id: usize)
fn halted(&self, _vcpu_id: usize)
Notifies the irq chip that the specified VCPU has executed a halt instruction. For KvmSplitIrqChip this is a no-op because KVM handles VCPU blocking.
source§fn wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState>
fn wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState>
Blocks until vcpu
is in a runnable state or until interrupted by
IrqChip::kick_halted_vcpus
. Returns VcpuRunState::Runnable if vcpu is runnable, or
VcpuRunState::Interrupted` if the wait was interrupted.
For KvmSplitIrqChip this is a no-op and always returns Runnable because KVM handles VCPU
blocking.
source§fn kick_halted_vcpus(&self)
fn kick_halted_vcpus(&self)
Makes unrunnable VCPUs return immediately from wait_until_runnable
.
For KvmSplitIrqChip this is a no-op because KVM handles VCPU blocking.
source§fn get_mp_state(&self, vcpu_id: usize) -> Result<MPState>
fn get_mp_state(&self, vcpu_id: usize) -> Result<MPState>
Get the current MP state of the specified VCPU.
source§fn set_mp_state(&mut self, vcpu_id: usize, state: &MPState) -> Result<()>
fn set_mp_state(&mut self, vcpu_id: usize, state: &MPState) -> Result<()>
Set the current MP state of the specified VCPU.
source§fn finalize_devices(
&mut self,
resources: &mut SystemAllocator,
io_bus: &Bus,
mmio_bus: &Bus
) -> Result<()>
fn finalize_devices( &mut self, resources: &mut SystemAllocator, io_bus: &Bus, mmio_bus: &Bus ) -> Result<()>
Finalize irqchip setup. Should be called once all devices have registered irq events and been added to the io_bus and mmio_bus.
source§fn process_delayed_irq_events(&mut self) -> Result<()>
fn process_delayed_irq_events(&mut self) -> Result<()>
The KvmSplitIrqChip’s ioapic may be locked because a vcpu thread is currently writing to the ioapic, and the ioapic may be blocking on adding MSI routes, which requires blocking socket communication back to the main thread. Thus, we do not want the main thread to block on a locked ioapic, so any irqs that could not be serviced because the ioapic could not be immediately locked are added to the delayed_ioapic_irq_events Vec. This function processes each delayed event in the vec each time it’s called. If the ioapic is still locked, we keep the queued irqs for the next time this function is called.
source§fn unregister_edge_irq_event(
&mut self,
irq: u32,
irq_event: &IrqEdgeEvent
) -> Result<()>
fn unregister_edge_irq_event( &mut self, irq: u32, irq_event: &IrqEdgeEvent ) -> Result<()>
source§fn register_level_irq_event(
&mut self,
irq: u32,
irq_event: &IrqLevelEvent,
source: IrqEventSource
) -> Result<Option<IrqEventIndex>>
fn register_level_irq_event( &mut self, irq: u32, irq_event: &IrqLevelEvent, source: IrqEventSource ) -> Result<Option<IrqEventIndex>>
source§fn unregister_level_irq_event(
&mut self,
irq: u32,
irq_event: &IrqLevelEvent
) -> Result<()>
fn unregister_level_irq_event( &mut self, irq: u32, irq_event: &IrqLevelEvent ) -> Result<()>
source§fn irq_delayed_event_token(&self) -> Result<Option<Event>>
fn irq_delayed_event_token(&self) -> Result<Option<Event>>
source§fn check_capability(&self, c: IrqChipCap) -> bool
fn check_capability(&self, c: IrqChipCap) -> bool
IrqChipCap
is available.source§impl IrqChipX86_64 for KvmSplitIrqChip
impl IrqChipX86_64 for KvmSplitIrqChip
source§fn get_pic_state(&self, select: PicSelect) -> Result<PicState>
fn get_pic_state(&self, select: PicSelect) -> Result<PicState>
Get the current state of the PIC
source§fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()>
fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()>
Set the current state of the PIC
source§fn get_ioapic_state(&self) -> Result<IoapicState>
fn get_ioapic_state(&self) -> Result<IoapicState>
Get the current state of the IOAPIC
source§fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()>
fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()>
Set the current state of the IOAPIC
source§fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>
fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>
Get the current state of the specified VCPU’s local APIC
source§fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()>
fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()>
Set the current state of the specified VCPU’s local APIC
source§fn lapic_frequency(&self) -> u32
fn lapic_frequency(&self) -> u32
Get the lapic frequency in Hz
source§fn get_pit(&self) -> Result<PitState>
fn get_pit(&self) -> Result<PitState>
Retrieves the state of the PIT. Gets the pit state via the KVM API.
source§fn set_pit(&mut self, state: &PitState) -> Result<()>
fn set_pit(&mut self, state: &PitState) -> Result<()>
Sets the state of the PIT. Sets the pit state via the KVM API.
source§fn pit_uses_speaker_port(&self) -> bool
fn pit_uses_speaker_port(&self) -> bool
Returns true if the PIT uses port 0x61 for the PC speaker, false if 0x61 is unused. devices::Pit uses 0x61.
fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>>
fn as_irq_chip(&self) -> &dyn IrqChip
fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip
source§fn snapshot_chip_specific(&self) -> Result<Value>
fn snapshot_chip_specific(&self) -> Result<Value>
Auto Trait Implementations§
impl RefUnwindSafe for KvmSplitIrqChip
impl Send for KvmSplitIrqChip
impl Sync for KvmSplitIrqChip
impl Unpin for KvmSplitIrqChip
impl UnwindSafe for KvmSplitIrqChip
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.