pub struct UserspaceIrqChip<V: VcpuX86_64> {
Show 13 fields pub vcpus: Arc<Mutex<Vec<Option<V>>>>, routes: Arc<Mutex<Routes>>, pit: Arc<Mutex<Pit>>, pic: Arc<Mutex<Pic>>, ioapic: Arc<Mutex<Ioapic>>, ioapic_pins: usize, pub apics: Vec<Arc<Mutex<Apic>>>, waiters: Vec<Arc<Waiter>>, timer_descriptors: Vec<Descriptor>, delayed_ioapic_irq_events: Arc<Mutex<DelayedIoApicIrqEvents>>, irq_events: Arc<Mutex<Vec<Option<IrqEvent>>>>, dropper: Arc<Mutex<Dropper>>, activated: bool,
}
Expand description

An IrqChip with all interrupt devices emulated in userspace. UserspaceIrqChip works with any hypervisor, but only supports x86.

Fields§

§vcpus: Arc<Mutex<Vec<Option<V>>>>§routes: Arc<Mutex<Routes>>§pit: Arc<Mutex<Pit>>§pic: Arc<Mutex<Pic>>§ioapic: Arc<Mutex<Ioapic>>§ioapic_pins: usize§apics: Vec<Arc<Mutex<Apic>>>§waiters: Vec<Arc<Waiter>>§timer_descriptors: Vec<Descriptor>§delayed_ioapic_irq_events: Arc<Mutex<DelayedIoApicIrqEvents>>

Delayed ioapic irq object, that contains the delayed events 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).

Note:

This lock may be locked by itself to access the DelayedIoApicIrqEvents. If accessed in conjunction with the irq_events field, that lock should be taken first to prevent deadlocks stemming from lock-ordering issues.

§irq_events: Arc<Mutex<Vec<Option<IrqEvent>>>>§dropper: Arc<Mutex<Dropper>>§activated: bool

Implementations§

source§

impl<V: VcpuX86_64 + 'static> UserspaceIrqChip<V>

source

pub fn new( num_vcpus: usize, irq_tube: Tube, ioapic_pins: Option<usize> ) -> Result<Self>

Constructs a new UserspaceIrqChip.

source

pub fn new_with_clock( num_vcpus: usize, irq_tube: Tube, ioapic_pins: Option<usize>, clock: Arc<Mutex<Clock>> ) -> Result<Self>

Constructs a new UserspaceIrqChip, with a clock. Used for testing.

source

fn handle_msg(&self, msg: ApicBusMsg)

Handles a message from an APIC.

source

fn send_msi(&self, addr: u32, data: u32)

Sends a Message Signaled Interrupt to one or more APICs. MSIs are a 64-bit address and 32-bit data, but in the Intel spec we’re implementing, only the low 32 bits of the address are used.

source

pub fn send_irq_to_apic(&self, id: usize, irq: &InterruptData)

source

pub fn send_irq_to_apics(&self, irq: &Interrupt)

Sends an interrupt to one or more APICs. Used for sending MSIs and IPIs.

source

fn deliver_startup(&self, vcpu: &V, vector: u8) -> Result<()>

Delivers a startup IPI to vcpu.

source

fn is_runnable(&self, vcpu_id: usize) -> bool

Checks if the specified VCPU is in a runnable state.

source§

impl<V: VcpuX86_64 + 'static> UserspaceIrqChip<V>

source

fn register_irq_event( &mut self, irq: u32, irq_event: &Event, resample_event: Option<&Event>, source: IrqEventSource ) -> Result<Option<IrqEventIndex>>

source

fn unregister_irq_event(&mut self, irq: u32, irq_event: &Event) -> Result<()>

Trait Implementations§

source§

impl<V: VcpuX86_64 + 'static> BusDevice for UserspaceIrqChip<V>

source§

fn debug_label(&self) -> String

Returns a label suitable for debug output.
source§

fn device_id(&self) -> DeviceId

Returns a unique id per device type suitable for metrics gathering.
source§

fn read(&mut self, offset: BusAccessInfo, data: &mut [u8])

Reads at offset from this device
source§

fn write(&mut self, offset: BusAccessInfo, data: &[u8])

Writes at offset into this device
source§

fn config_register_write( &mut self, reg_idx: usize, offset: u64, data: &[u8] ) -> ConfigWriteResult

Sets a register in the configuration space. Only used by PCI. Read more
source§

fn config_register_read(&self, reg_idx: usize) -> u32

Gets a register from the configuration space. Only used by PCI. Read more
source§

fn init_pci_config_mapping( &mut self, shmem: &SharedMemory, base: usize, len: usize ) -> bool

Provides a memory region to back MMIO access to the configuration space. If the device can keep the memory region up to date, then it should return true, after which no more calls to config_register_read will be made. Otherwise the device should return false. Read more
source§

fn virtual_config_register_write(&mut self, reg_idx: usize, value: u32)

Sets a register in the virtual config space. Only used by PCI. Read more
source§

fn virtual_config_register_read(&self, reg_idx: usize) -> u32

Gets a register from the virtual config space. Only used by PCI. Read more
source§

fn on_sandboxed(&mut self)

Invoked when the device is sandboxed.
source§

fn get_ranges(&self) -> Vec<(BusRange, BusType)>

Gets a list of all ranges registered by this BusDevice.
source§

fn destroy_device(&mut self)

Invoked when the device is destroyed
source§

fn is_bridge(&self) -> Option<u8>

Returns the secondary bus number if this bus device is pci bridge
source§

impl<V: VcpuX86_64 + 'static> BusDeviceSync for UserspaceIrqChip<V>

source§

fn read(&self, info: BusAccessInfo, data: &mut [u8])

source§

fn write(&self, info: BusAccessInfo, data: &[u8])

source§

fn snapshot_sync(&self) -> Result<Value>

source§

fn restore_sync(&self, _data: Value) -> Result<()>

Load a saved snapshot of an image.
source§

fn sleep_sync(&self) -> Result<()>

Stop all threads related to the device. Sleep should be idempotent.
source§

fn wake_sync(&self) -> Result<()>

Create/Resume all threads related to the device. Wake should be idempotent.
source§

impl<V: VcpuX86_64 + 'static> IrqChip for UserspaceIrqChip<V>

source§

fn service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()>

Services 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 UserspaceIrqChip, this function identifies the destination(s) of the irq: PIC, IOAPIC, or APIC (MSI). If it’s a PIC or IOAPIC route, we attempt 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 (though we still read from the Event that triggered the irq event). If it’s an MSI route, we call send_msi to decode the MSI and send it to the destination APIC(s).

source§

fn broadcast_eoi(&self, vector: u8) -> Result<()>

Broadcasts an end of interrupt. For UserspaceIrqChip this sends the EOI to the ioapic.

source§

fn inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()>

Injects any pending interrupts for vcpu.

For UserspaceIrqChip this:

  • Injects a PIC interrupt, if vcpu_id is 0 and vcpu is ready for interrupt
  • Injects an APIC fixed interrupt, if vcpu is ready for interrupt and PIC didn’t inject
  • Injects APIC NMIs
  • Handles APIC INIT IPIs
  • Handles APIC SIPIs
  • Requests an interrupt window, if PIC or APIC still has pending interrupts for this vcpu
source§

fn halted(&self, vcpu_id: usize)

Notifies the irq chip that the specified VCPU has executed a halt instruction. For UserspaceIrqChip, it sets the APIC’s mp_state to MPState::Halted.

source§

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::Interruptedif the wait was interrupted. ForUserspaceIrqChip, if the APIC isn't MPState::Runnable`, sleep until there are new interrupts pending on the APIC, inject the interrupts, and go back to sleep if still not runnable.

source§

fn kick_halted_vcpus(&self)

Makes unrunnable VCPUs return immediately from wait_until_runnable. For UserspaceIrqChip, every vcpu gets kicked so its current or next call to wait_until_runnable will immediately return false. After that one kick, subsequent wait_until_runnable calls go back to waiting for runnability normally.

source§

fn process_delayed_irq_events(&mut self) -> Result<()>

The UserspaceIrqChip’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 tube 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 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>>

Register an event with edge-trigger semantic that can trigger an interrupt for a particular GSI.
source§

fn unregister_edge_irq_event( &mut self, irq: u32, irq_event: &IrqEdgeEvent ) -> Result<()>

Unregister an event with edge-trigger semantic for a particular GSI.
source§

fn register_level_irq_event( &mut self, irq: u32, irq_event: &IrqLevelEvent, source: IrqEventSource ) -> Result<Option<IrqEventIndex>>

Register an event with level-trigger semantic that can trigger an interrupt for a particular GSI.
source§

fn unregister_level_irq_event( &mut self, irq: u32, irq_event: &IrqLevelEvent ) -> Result<()>

Unregister an event with level-trigger semantic for a particular GSI.
source§

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<()>

Replace all irq routes with the supplied routes
source§

fn irq_event_tokens( &self ) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>

Return a vector of all registered irq numbers and their associated events and event sources. These should be used by the main thread to wait for irq events.
source§

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 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<()>

Set the current MP state of the specified VCPU.
source§

fn try_clone(&self) -> Result<Self>

Attempt to create a shallow clone of this IrqChip instance.
source§

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 irq_delayed_event_token(&self) -> Result<Option<Event>>

Return an event which is meant to trigger process of any irqs events that were delayed by calling process_delayed_irq_events(). This should be used by the main thread to wait for delayed irq event kick. It is process_delayed_irq_events() responsibility to read the event as long as there is no more irqs to be serviced.
source§

fn check_capability(&self, c: IrqChipCap) -> bool

Checks if a particular IrqChipCap is available.
source§

impl<V: VcpuX86_64 + 'static> IrqChipX86_64 for UserspaceIrqChip<V>

source§

fn lapic_frequency(&self) -> u32

Get the lapic frequency in Hz

source§

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.

source§

fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>>

source§

fn as_irq_chip(&self) -> &dyn IrqChip

source§

fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip

source§

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<()>

Set the current state of the PIC
source§

fn get_ioapic_state(&self) -> Result<IoapicState>

Get the current state of the IOAPIC
source§

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>

Get the current state of the specified VCPU’s local APIC
source§

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 get_pit(&self) -> Result<PitState>

Retrieves the state of the PIT.
source§

fn set_pit(&mut self, state: &PitState) -> Result<()>

Sets the state of the PIT.
source§

fn snapshot_chip_specific(&self) -> Result<Value>

Snapshot state specific to different IrqChips.
source§

fn restore_chip_specific(&mut self, _data: Value) -> Result<()>

Restore state specific to different IrqChips.
source§

fn snapshot(&self, cpus_num: usize) -> Result<Value>

Snapshot state common to IrqChips.
source§

fn restore(&mut self, data: Value, vcpus_num: usize) -> Result<()>

Restore state common to IrqChips.
source§

impl<V: VcpuX86_64 + 'static> Suspendable for UserspaceIrqChip<V>

source§

fn sleep(&mut self) -> Result<()>

Stop all threads related to the device. Sleep should be idempotent.
source§

fn wake(&mut self) -> Result<()>

Create/Resume all threads related to the device. Wake should be idempotent.
source§

fn snapshot(&mut self) -> Result<Value>

Save the device state in an image that can be restored.
source§

fn restore(&mut self, _data: Value) -> Result<()>

Load a saved snapshot of an image.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast for Twhere T: Any,

§

fn into_any(self: Box<T, Global>) -> Box<dyn Any, Global>

Convert 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, Global>) -> Rc<dyn Any, Global>

Convert 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)

Convert &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)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for Twhere T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T, Global>) -> Arc<dyn Any + Sync + Send, Global>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V