diff options
author | Zach Reizner <zachr@google.com> | 2018-01-09 10:41:10 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-01-25 19:23:42 -0800 |
commit | 086922c222a856252e46b35c912b435635ea0682 (patch) | |
tree | 5d3f0b3a7befdba6dcac409ad60e1d047090ae9c /kvm/src/lib.rs | |
parent | 0ba70d8d3c69a4fa8853d317e2dc1f45dd25acd8 (diff) | |
download | crosvm-086922c222a856252e46b35c912b435635ea0682.tar crosvm-086922c222a856252e46b35c912b435635ea0682.tar.gz crosvm-086922c222a856252e46b35c912b435635ea0682.tar.bz2 crosvm-086922c222a856252e46b35c912b435635ea0682.tar.lz crosvm-086922c222a856252e46b35c912b435635ea0682.tar.xz crosvm-086922c222a856252e46b35c912b435635ea0682.tar.zst crosvm-086922c222a856252e46b35c912b435635ea0682.zip |
kvm: add set_irq_routing method
This is used by the plugin process API, which may register an IRQ routing table. TEST=./build_test BUG=chromium:800626 Change-Id: If40965e8abfb0c9074c90b5fc77f9042f06499e0 Reviewed-on: https://chromium-review.googlesource.com/857910 Commit-Ready: Zach Reizner <zachr@chromium.org> Tested-by: Zach Reizner <zachr@chromium.org> Reviewed-by: Dmitry Torokhov <dtor@chromium.org> Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'kvm/src/lib.rs')
-rw-r--r-- | kvm/src/lib.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs index 3dee94c..be1feec 100644 --- a/kvm/src/lib.rs +++ b/kvm/src/lib.rs @@ -14,6 +14,7 @@ mod cap; use std::fs::File; use std::collections::{BinaryHeap, HashMap}; use std::collections::hash_map::Entry; +use std::mem::size_of; use std::os::raw::*; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; @@ -168,6 +169,18 @@ impl Into<u64> for NoDatamatch { } } +/// A source of IRQs in an `IrqRoute`. +pub enum IrqSource { + Irqchip { chip: u32, pin: u32 }, + Msi { address: u64, data: u32 }, +} + +/// A single route for an IRQ. +pub struct IrqRoute { + pub gsi: u32, + pub source: IrqSource, +} + /// A wrapper around creating and using a VM. pub struct Vm { vm: File, @@ -473,6 +486,55 @@ impl Vm { errno_result() } } + + /// 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"))] + pub fn set_gsi_routing(&self, routes: &[IrqRoute]) -> Result<()> { + let vec_size_bytes = size_of::<kvm_irq_routing>() + + (routes.len() * size_of::<kvm_irq_routing_entry>()); + let bytes: Vec<u8> = vec![0; vec_size_bytes]; + let irq_routing: &mut kvm_irq_routing = unsafe { + // We have ensured in new that there is enough space for the structure so this + // conversion is safe. + &mut *(bytes.as_ptr() as *mut kvm_irq_routing) + }; + irq_routing.nr = routes.len() as u32; + + { + // Safe because we ensured there is enough space in irq_routing to hold the number of + // route entries. + let irq_routes = unsafe { irq_routing.entries.as_mut_slice(routes.len()) }; + for (route, irq_route) in routes.iter().zip(irq_routes.iter_mut()) { + irq_route.gsi = route.gsi; + match route.source { + IrqSource::Irqchip { chip, pin } => { + irq_route.type_ = KVM_IRQ_ROUTING_IRQCHIP; + irq_route.u.irqchip = kvm_irq_routing_irqchip { + irqchip: chip, + pin, + } + } + IrqSource::Msi { address, data } => { + irq_route.type_ = KVM_IRQ_ROUTING_MSI; + irq_route.u.msi = kvm_irq_routing_msi { + address_lo: address as u32, + address_hi: (address >> 32) as u32, + data: data, + ..Default::default() + } + } + } + } + } + + let ret = unsafe { ioctl_with_ref(self, KVM_SET_GSI_ROUTING(), irq_routing) }; + if ret == 0 { + Ok(()) + } else { + errno_result() + } + } } impl AsRawFd for Vm { @@ -982,6 +1044,44 @@ mod tests { } #[test] + fn set_gsi_routing() { + let kvm = Kvm::new().unwrap(); + let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap(); + let vm = Vm::new(&kvm, gm).unwrap(); + vm.set_gsi_routing(&[]).unwrap(); + vm.set_gsi_routing(&[IrqRoute { + gsi: 1, + source: IrqSource::Irqchip { + chip: KVM_IRQCHIP_IOAPIC, + pin: 3, + }, + }]).unwrap(); + vm.set_gsi_routing(&[IrqRoute { + gsi: 1, + source: IrqSource::Msi { + address: 0xf000000, + data: 0xa0, + }, + }]).unwrap(); + vm.set_gsi_routing(&[ + IrqRoute { + gsi: 1, + source: IrqSource::Irqchip { + chip: KVM_IRQCHIP_IOAPIC, + pin: 3, + }, + }, + IrqRoute { + gsi: 2, + source: IrqSource::Msi { + address: 0xf000000, + data: 0xa0, + }, + }, + ]).unwrap(); + } + + #[test] fn create_vcpu() { let kvm = Kvm::new().unwrap(); let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap(); |