From 1fb6c0d01969ef9d2bd8785e4ad41d56d611fda1 Mon Sep 17 00:00:00 2001 From: Xiong Zhang Date: Tue, 23 Apr 2019 17:15:17 +0800 Subject: [PATCH] kvm: Let device could modify its irq routing Current all devices use kvm default irq routing table, but when MSI or MSI-x are enabled, they have their own irq routing, here add_irq_route_entry() is added into vm's function, then device could add its irq routing into VM's irq routing table and replace the default kvm irq routing info. BUG=chromium:992270 TEST=none Change-Id: I111f9c3c09ef66b08c6f0432e936ec7e4fd6d270 Signed-off-by: Xiong Zhang Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1581145 Reviewed-by: Zach Reizner Reviewed-by: Daniel Verkamp Tested-by: kokoro --- kvm/src/lib.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs index 60ec2d1600..bafc79dbfe 100644 --- a/kvm/src/lib.rs +++ b/kvm/src/lib.rs @@ -269,6 +269,49 @@ pub enum PicId { /// Number of pins on the IOAPIC. pub const NUM_IOAPIC_PINS: usize = 24; +impl IrqRoute { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn ioapic_irq_route(irq_num: u32) -> IrqRoute { + IrqRoute { + gsi: irq_num, + source: IrqSource::Irqchip { + chip: KVM_IRQCHIP_IOAPIC, + pin: irq_num, + }, + } + } + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn pic_irq_route(id: PicId, irq_num: u32) -> IrqRoute { + IrqRoute { + gsi: irq_num, + source: IrqSource::Irqchip { + chip: id as u32, + pin: irq_num % 8, + }, + } + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn kvm_default_irq_routing_table() -> Vec { + let mut routes: Vec = Vec::new(); + + for i in 0..8 { + routes.push(IrqRoute::pic_irq_route(PicId::Primary, i)); + routes.push(IrqRoute::ioapic_irq_route(i)); + } + for i in 8..16 { + routes.push(IrqRoute::pic_irq_route(PicId::Secondary, i)); + routes.push(IrqRoute::ioapic_irq_route(i)); + } + for i in 16..NUM_IOAPIC_PINS as u32 { + routes.push(IrqRoute::ioapic_irq_route(i)); + } + + routes +} + // Used to invert the order when stored in a max-heap. #[derive(Copy, Clone, Eq, PartialEq)] struct MemSlot(u32); @@ -294,6 +337,8 @@ pub struct Vm { device_memory: HashMap, mmap_arenas: HashMap, mem_slot_gaps: BinaryHeap, + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + routes: Vec, } impl Vm { @@ -326,6 +371,8 @@ impl Vm { device_memory: HashMap::new(), mmap_arenas: HashMap::new(), mem_slot_gaps: BinaryHeap::new(), + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + routes: kvm_default_irq_routing_table(), }) } else { errno_result() @@ -948,6 +995,21 @@ impl Vm { } } + /// Add one IrqRoute into vm's irq routing table + /// Note that any routes added using set_gsi_routing instead of this function will be dropped. + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + pub fn add_irq_route_entry(&mut self, route: IrqRoute) -> Result<()> { + self.routes.retain(|r| r.gsi != route.gsi); + + self.routes.push(route); + + self.set_gsi_routing(&self.routes) + } + #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] + pub fn add_irq_route_entry(&mut self, _route: IrqRoute) -> Result<()> { + Err(Error::new(EINVAL)) + } + /// Sets the GSI routing table, replacing any table set with previous calls to /// `set_gsi_routing`. #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]