summary refs log tree commit diff
diff options
context:
space:
mode:
authorXiong Zhang <xiong.y.zhang@intel.corp-partner.google.com>2019-04-23 17:15:17 +0800
committerCommit Bot <commit-bot@chromium.org>2019-10-14 03:54:47 +0000
commit1fb6c0d01969ef9d2bd8785e4ad41d56d611fda1 (patch)
treeb06d2eb5726d72e95407c64731377998e7d245a0
parenta462f74b2688379d04d4acf4337d07df58fc08e6 (diff)
downloadcrosvm-1fb6c0d01969ef9d2bd8785e4ad41d56d611fda1.tar
crosvm-1fb6c0d01969ef9d2bd8785e4ad41d56d611fda1.tar.gz
crosvm-1fb6c0d01969ef9d2bd8785e4ad41d56d611fda1.tar.bz2
crosvm-1fb6c0d01969ef9d2bd8785e4ad41d56d611fda1.tar.lz
crosvm-1fb6c0d01969ef9d2bd8785e4ad41d56d611fda1.tar.xz
crosvm-1fb6c0d01969ef9d2bd8785e4ad41d56d611fda1.tar.zst
crosvm-1fb6c0d01969ef9d2bd8785e4ad41d56d611fda1.zip
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 <xiong.y.zhang@intel.corp-partner.google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1581145
Reviewed-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
-rw-r--r--kvm/src/lib.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs
index 60ec2d1..bafc79d 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<IrqRoute> {
+    let mut routes: Vec<IrqRoute> = 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<u32, MemoryMapping>,
     mmap_arenas: HashMap<u32, MemoryMappingArena>,
     mem_slot_gaps: BinaryHeap<MemSlot>,
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    routes: Vec<IrqRoute>,
 }
 
 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"))]