From df678d1193055e1836611beb95c3d47fd25945ab Mon Sep 17 00:00:00 2001 From: Diana Popa Date: Fri, 8 Mar 2019 18:56:25 +0200 Subject: [PATCH 1/2] device manager: relocate x86_64 irq assignment Since the interval of allowed IRQ IDs for the device manager is x86_64 specific, it was moved in the layout for the x86_64 architecture. Signed-off-by: Diana Popa --- arch/src/lib.rs | 2 +- arch/src/x86_64/layout.rs | 6 +++++ vmm/src/device_manager/mmio.rs | 35 ++++++++++++++---------- vmm/src/lib.rs | 49 ++++++++++++++++++++++++---------- 4 files changed, 63 insertions(+), 29 deletions(-) diff --git a/arch/src/lib.rs b/arch/src/lib.rs index 52d8efee32a..a548f5ba6d6 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -37,5 +37,5 @@ pub mod x86_64; #[cfg(target_arch = "x86_64")] pub use x86_64::{ arch_memory_regions, configure_system, get_32bit_gap_start as get_reserved_mem_addr, - layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, + layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, layout::IRQ_BASE, layout::IRQ_MAX, }; diff --git a/arch/src/x86_64/layout.rs b/arch/src/x86_64/layout.rs index b080f9e0f8b..7f5d5d72592 100644 --- a/arch/src/x86_64/layout.rs +++ b/arch/src/x86_64/layout.rs @@ -16,6 +16,12 @@ pub const CMDLINE_START: usize = 0x20000; /// Kernel command line start address maximum size. pub const CMDLINE_MAX_SIZE: usize = 0x10000; +// Typically, on x86 systems 16 IRQs are used (0-15). +/// First usable IRQ ID for virtio device interrupts on x86_64. +pub const IRQ_BASE: u32 = 5; +/// Last usable IRQ ID for virtio device interrupts on x86_64. +pub const IRQ_MAX: u32 = 15; + /// Address for the TSS setup. pub const KVM_TSS_ADDRESS: usize = 0xfffb_d000; diff --git a/vmm/src/device_manager/mmio.rs b/vmm/src/device_manager/mmio.rs index e86eb0358f1..c2f6858645c 100644 --- a/vmm/src/device_manager/mmio.rs +++ b/vmm/src/device_manager/mmio.rs @@ -53,11 +53,6 @@ impl fmt::Display for Error { type Result = ::std::result::Result; -/// Typically, on x86 systems 16 IRQs are used (0-15) -/// Our device manager uses the IRQs from 5 to 16 -const MAX_IRQ: u32 = 15; -const IRQ_BASE: u32 = 5; - /// This represents the size of the mmio device specified to the kernel as a cmdline option /// It has to be larger than 0x100 (the offset where the configuration space starts from /// the beginning of the memory mapped device registers) + the size of the configuration space @@ -75,17 +70,23 @@ pub struct MMIODeviceManager { guest_mem: GuestMemory, mmio_base: u64, irq: u32, + last_irq: u32, id_to_addr_map: HashMap, } impl MMIODeviceManager { /// Create a new DeviceManager handling mmio devices (virtio net, block). - pub fn new(guest_mem: GuestMemory, mmio_base: u64) -> MMIODeviceManager { + pub fn new( + guest_mem: GuestMemory, + mmio_base: u64, + irq_interval: (u32, u32), + ) -> MMIODeviceManager { MMIODeviceManager { guest_mem, vm_requests: Vec::new(), mmio_base, - irq: IRQ_BASE, + irq: irq_interval.0, + last_irq: irq_interval.1, bus: devices::Bus::new(), id_to_addr_map: HashMap::new(), } @@ -98,7 +99,7 @@ impl MMIODeviceManager { cmdline: &mut kernel_cmdline::Cmdline, id: Option, ) -> Result { - if self.irq > MAX_IRQ { + if self.irq > self.last_irq { return Err(Error::IrqsExhausted); } @@ -180,6 +181,7 @@ impl MMIODeviceManager { #[cfg(test)] mod tests { use super::*; + use arch; use devices::virtio::{ActivateResult, VirtioDevice}; use kernel_cmdline; use memory_model::{GuestAddress, GuestMemory}; @@ -236,7 +238,8 @@ mod tests { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); let guest_mem = GuestMemory::new(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]).unwrap(); - let mut device_manager = MMIODeviceManager::new(guest_mem, 0xd000_0000); + let mut device_manager = + MMIODeviceManager::new(guest_mem, 0xd000_0000, (arch::IRQ_BASE, arch::IRQ_MAX)); let mut cmdline = kernel_cmdline::Cmdline::new(4096); let dummy_box = Box::new(DummyDevice { dummy: 0 }); @@ -251,11 +254,12 @@ mod tests { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); let guest_mem = GuestMemory::new(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]).unwrap(); - let mut device_manager = MMIODeviceManager::new(guest_mem, 0xd000_0000); + let mut device_manager = + MMIODeviceManager::new(guest_mem, 0xd000_0000, (arch::IRQ_BASE, arch::IRQ_MAX)); let mut cmdline = kernel_cmdline::Cmdline::new(4096); let dummy_box = Box::new(DummyDevice { dummy: 0 }); - for _i in IRQ_BASE..=MAX_IRQ { + for _i in arch::IRQ_BASE..=arch::IRQ_MAX { device_manager .register_device(dummy_box.clone(), &mut cmdline, None) .unwrap(); @@ -291,7 +295,8 @@ mod tests { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); let guest_mem = GuestMemory::new(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]).unwrap(); - let device_manager = MMIODeviceManager::new(guest_mem, 0xd000_0000); + let device_manager = + MMIODeviceManager::new(guest_mem, 0xd000_0000, (arch::IRQ_BASE, arch::IRQ_MAX)); let mut cmdline = kernel_cmdline::Cmdline::new(4096); let e = Error::Cmdline( cmdline @@ -332,7 +337,8 @@ mod tests { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); let guest_mem = GuestMemory::new(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]).unwrap(); - let mut device_manager = MMIODeviceManager::new(guest_mem, 0xd000_0000); + let mut device_manager = + MMIODeviceManager::new(guest_mem, 0xd000_0000, (arch::IRQ_BASE, arch::IRQ_MAX)); let mut cmdline = kernel_cmdline::Cmdline::new(4096); let dummy_box = Box::new(DummyDevice { dummy: 0 }); @@ -349,7 +355,8 @@ mod tests { let start_addr1 = GuestAddress(0x0); let start_addr2 = GuestAddress(0x1000); let guest_mem = GuestMemory::new(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]).unwrap(); - let mut device_manager = MMIODeviceManager::new(guest_mem, 0xd000_0000); + let mut device_manager = + MMIODeviceManager::new(guest_mem, 0xd000_0000, (arch::IRQ_BASE, arch::IRQ_MAX)); let mut cmdline = kernel_cmdline::Cmdline::new(4096); let dummy_box = Box::new(DummyDevice { dummy: 0 }); diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 3d2ce9b2f67..625f7d0564b 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -927,8 +927,11 @@ impl Vmm { // Instantiate the MMIO device manager. // 'mmio_base' address has to be an address which is protected by the kernel. - let mut device_manager = - MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64); + let mut device_manager = MMIODeviceManager::new( + guest_mem.clone(), + arch::get_reserved_mem_addr() as u64, + (arch::IRQ_BASE, arch::IRQ_MAX), + ); self.attach_block_devices(&mut device_manager)?; self.attach_net_devices(&mut device_manager)?; @@ -2372,8 +2375,11 @@ mod tests { vmm.init_guest_memory().unwrap(); vmm.default_kernel_config(); let guest_mem = vmm.guest_memory.clone().unwrap(); - let mut device_manager = - MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64); + let mut device_manager = MMIODeviceManager::new( + guest_mem.clone(), + arch::get_reserved_mem_addr() as u64, + (arch::IRQ_BASE, arch::IRQ_MAX), + ); vmm.attach_net_devices(&mut device_manager).unwrap(); vmm.set_instance_state(InstanceState::Running); @@ -2648,8 +2654,11 @@ mod tests { vmm.default_kernel_config(); let guest_mem = vmm.guest_memory.clone().unwrap(); - let mut device_manager = - MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64); + let mut device_manager = MMIODeviceManager::new( + guest_mem.clone(), + arch::get_reserved_mem_addr() as u64, + (arch::IRQ_BASE, arch::IRQ_MAX), + ); assert!(vmm.attach_block_devices(&mut device_manager).is_ok()); assert!(vmm.get_kernel_cmdline_str().contains("root=/dev/vda")); @@ -2672,8 +2681,11 @@ mod tests { vmm.default_kernel_config(); let guest_mem = vmm.guest_memory.clone().unwrap(); - let mut device_manager = - MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64); + let mut device_manager = MMIODeviceManager::new( + guest_mem.clone(), + arch::get_reserved_mem_addr() as u64, + (arch::IRQ_BASE, arch::IRQ_MAX), + ); assert!(vmm.attach_block_devices(&mut device_manager).is_ok()); assert!(vmm .get_kernel_cmdline_str() @@ -2700,8 +2712,11 @@ mod tests { vmm.default_kernel_config(); let guest_mem = vmm.guest_memory.clone().unwrap(); - let mut device_manager = - MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64); + let mut device_manager = MMIODeviceManager::new( + guest_mem.clone(), + arch::get_reserved_mem_addr() as u64, + (arch::IRQ_BASE, arch::IRQ_MAX), + ); assert!(vmm.attach_block_devices(&mut device_manager).is_ok()); // Test that kernel commandline does not contain either /dev/vda or PARTUUID. assert!(!vmm.get_kernel_cmdline_str().contains("root=PARTUUID=")); @@ -2734,8 +2749,11 @@ mod tests { vmm.default_kernel_config(); let guest_mem = vmm.guest_memory.clone().unwrap(); - let mut device_manager = - MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64); + let mut device_manager = MMIODeviceManager::new( + guest_mem.clone(), + arch::get_reserved_mem_addr() as u64, + (arch::IRQ_BASE, arch::IRQ_MAX), + ); // test create network interface let network_interface = NetworkInterfaceConfig { @@ -2830,8 +2848,11 @@ mod tests { assert!(vmm.guest_memory.is_some()); let guest_mem = vmm.guest_memory.clone().unwrap(); - let mut device_manager = - MMIODeviceManager::new(guest_mem.clone(), arch::get_reserved_mem_addr() as u64); + let mut device_manager = MMIODeviceManager::new( + guest_mem.clone(), + arch::get_reserved_mem_addr() as u64, + (arch::IRQ_BASE, arch::IRQ_MAX), + ); let dummy_box = Box::new(DummyDevice { dummy: 0 }); // Use a dummy command line as it is not used in this test. From b15dcf85f70a7eabf98522970c93e2b17d79b2b7 Mon Sep 17 00:00:00 2001 From: Diana Popa Date: Fri, 8 Mar 2019 19:20:13 +0200 Subject: [PATCH 2/2] arm64: add irq assignment for the mmio dev manager Signed-off-by: Diana Popa --- arch/src/aarch64/layout.rs | 12 ++++++++++++ arch/src/lib.rs | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/src/aarch64/layout.rs b/arch/src/aarch64/layout.rs index c7c319278e2..0ce0539e5bf 100644 --- a/arch/src/aarch64/layout.rs +++ b/arch/src/aarch64/layout.rs @@ -5,3 +5,15 @@ pub const CMDLINE_START: usize = 0x0; /// Kernel command line start address maximum size. pub const CMDLINE_MAX_SIZE: usize = 0x0; + +// As per virt/kvm/arm/vgic/vgic-kvm-device.c we need +// the number of interrupts our GIC will support to be: +// * bigger than 32 +// * less than 1023 and +// * a multiple of 32. +// We are setting up our interrupt controller to support a maximum of 128 interrupts. +/// First usable interrupt on aarch64. +pub const IRQ_BASE: u32 = 32; + +/// Last usable interrupt on aarch64. +pub const IRQ_MAX: u32 = 159; diff --git a/arch/src/lib.rs b/arch/src/lib.rs index a548f5ba6d6..f35597fb4fb 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -28,7 +28,7 @@ pub mod aarch64; #[cfg(target_arch = "aarch64")] pub use aarch64::{ arch_memory_regions, configure_system, get_reserved_mem_addr, layout::CMDLINE_MAX_SIZE, - layout::CMDLINE_START, + layout::CMDLINE_START, layout::IRQ_BASE, layout::IRQ_MAX, }; #[cfg(target_arch = "x86_64")]