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>
This commit is contained in:
Xiong Zhang 2019-04-23 17:15:17 +08:00 committed by Commit Bot
parent a462f74b26
commit 1fb6c0d019

View file

@ -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"))]