diff --git a/arch/src/aarch64/mod.rs b/arch/src/aarch64/mod.rs index 248240bd8..e4b4eba68 100644 --- a/arch/src/aarch64/mod.rs +++ b/arch/src/aarch64/mod.rs @@ -16,7 +16,6 @@ pub mod regs; pub use self::fdt::DeviceInfoForFDT; use crate::DeviceType; use crate::RegionType; -use aarch64::gic::GICDevice; use kvm_ioctls::*; use std::collections::HashMap; use std::ffi::CStr; @@ -29,9 +28,12 @@ use vm_memory::{ /// Errors thrown while configuring aarch64 system. #[derive(Debug)] pub enum Error { - /// Failed to create a Flattened Device Tree for this aarch64 VM. + /// Failed to create a FDT. SetupFDT(fdt::Error), + /// Failed to create a GIC. + SetupGIC(gic::Error), + /// Failed to compute the initrd address. InitrdAddress, @@ -136,19 +138,22 @@ pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, Region #[allow(clippy::too_many_arguments)] #[allow(unused_variables)] pub fn configure_system( + vm_fd: &VmFd, guest_mem: &GuestMemoryMmap, cmdline_cstring: &CStr, + vcpu_count: u64, vcpu_mpidr: Vec, device_info: &HashMap<(DeviceType, String), T>, - gic_device: &Box, initrd: &Option, ) -> super::Result<()> { + let gic_device = gic::create_gic(vm_fd, vcpu_count).map_err(Error::SetupGIC)?; + let dtb = fdt::create_fdt( guest_mem, cmdline_cstring, vcpu_mpidr, device_info, - gic_device, + &gic_device, initrd, ) .map_err(Error::SetupFDT)?; diff --git a/vmm/Cargo.toml b/vmm/Cargo.toml index 9ee7fbb6b..58cde6158 100644 --- a/vmm/Cargo.toml +++ b/vmm/Cargo.toml @@ -46,7 +46,7 @@ tempfile = "3.1.0" [dependencies.linux-loader] git = "https://github.com/rust-vmm/linux-loader" -features = ["elf", "bzimage"] +features = ["elf", "bzimage", "pe"] [dev-dependencies] credibility = "0.1.3" diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 8e806a3c3..a3ee18daa 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -1000,13 +1000,13 @@ impl CpuManager { } #[cfg(target_arch = "aarch64")] - pub fn get_mpidr(&self) -> Vec { - let vcpu_mpidr = self + pub fn get_mpidrs(&self) -> Vec { + let vcpu_mpidrs = self .vcpus .iter() .map(|cpu| cpu.lock().unwrap().get_mpidr()) .collect(); - vcpu_mpidr + vcpu_mpidrs } #[cfg(feature = "acpi")] diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 6f551881b..fde999f02 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1092,6 +1092,14 @@ impl DeviceManager { Ok(interrupt_controller) } + #[cfg(target_arch = "aarch64")] + pub fn enable_interrupt_controller(&self) -> DeviceManagerResult<()> { + if let Some(interrupt_controller) = &self.interrupt_controller { + interrupt_controller.lock().unwrap().enable().unwrap(); + } + Ok(()) + } + #[cfg(target_arch = "x86_64")] fn add_interrupt_controller( &mut self, diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index eeef234db..e64236b8f 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -56,7 +56,7 @@ pub struct MemoryManager { next_kvm_memory_slot: u32, start_of_device_area: GuestAddress, end_of_device_area: GuestAddress, - fd: Arc, + pub fd: Arc, hotplug_slots: Vec, selected_slot: usize, backing_file: Option, diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 8259ec5f3..0b1b0155a 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -29,7 +29,7 @@ use crate::config::{ VmConfig, VsockConfig, }; use crate::cpu; -use crate::device_manager::{get_win_size, Console, DeviceManager, DeviceManagerError}; +use crate::device_manager::{self, get_win_size, Console, DeviceManager, DeviceManagerError}; use crate::memory_manager::{Error as MemoryManagerError, MemoryManager}; use crate::migration::{url_to_path, vm_config_from_snapshot, VM_SNAPSHOT_FILE}; use crate::{CPU_MANAGER_SNAPSHOT_ID, DEVICE_MANAGER_SNAPSHOT_ID, MEMORY_MANAGER_SNAPSHOT_ID}; @@ -46,7 +46,6 @@ use kvm_ioctls::*; use linux_loader::cmdline::Cmdline; #[cfg(target_arch = "x86_64")] use linux_loader::loader::elf::Error::InvalidElfMagicNumber; -#[cfg(target_arch = "x86_64")] use linux_loader::loader::KernelLoader; use signal_hook::{iterator::Signals, SIGINT, SIGTERM, SIGWINCH}; #[cfg(target_arch = "x86_64")] @@ -56,17 +55,14 @@ use std::fs::{File, OpenOptions}; use std::io::{self, Write}; #[cfg(target_arch = "x86_64")] use std::io::{Seek, SeekFrom}; -#[cfg(target_arch = "x86_64")] use std::ops::Deref; use std::path::PathBuf; use std::sync::{Arc, Mutex, RwLock}; use std::{result, str, thread}; use url::Url; #[cfg(target_arch = "x86_64")] -use vm_memory::{ - Address, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryMmap, - GuestMemoryRegion, -}; +use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryMmap, GuestMemoryRegion}; +use vm_memory::{GuestAddress, GuestAddressSpace}; use vm_migration::{ Migratable, MigratableError, Pausable, Snapshot, SnapshotDataSection, Snapshottable, Transportable, @@ -114,6 +110,9 @@ pub enum Error { /// Cannot configure system ConfigureSystem(arch::Error), + /// Cannot enable interrupt controller + EnableInterruptController(device_manager::DeviceManagerError), + PoisonedState, /// Cannot create a device manager. @@ -254,7 +253,6 @@ impl VmState { } pub struct Vm { - #[cfg_attr(target_arch = "aarch64", allow(dead_code))] kernel: File, #[cfg_attr(target_arch = "aarch64", allow(dead_code))] initramfs: Option, @@ -485,7 +483,25 @@ impl Vm { #[cfg(target_arch = "aarch64")] fn load_kernel(&mut self) -> Result { - unimplemented!(); + let guest_memory = self.memory_manager.lock().as_ref().unwrap().guest_memory(); + let mem = guest_memory.memory(); + let entry_addr = match linux_loader::loader::pe::PE::load( + mem.deref(), + Some(GuestAddress(arch::get_kernel_start())), + &mut self.kernel, + None, + ) { + Ok(entry_addr) => entry_addr, + Err(e) => { + return Err(Error::KernelLoad(e)); + } + }; + + let entry_point_addr: GuestAddress = entry_addr.kernel_load; + + Ok(EntryPoint { + entry_addr: entry_point_addr, + }) } #[cfg(target_arch = "x86_64")] @@ -614,11 +630,36 @@ impl Vm { #[cfg(target_arch = "aarch64")] fn configure_system(&mut self, _entry_addr: EntryPoint) -> Result<()> { - let _cmdline_cstring = self.get_cmdline()?; - // What to do on AArch64 is: - // - Setup GIC - // - Generate FDT - unimplemented!(); + let cmdline_cstring = self.get_cmdline()?; + let vcpu_mpidrs = self.cpu_manager.lock().unwrap().get_mpidrs(); + let guest_memory = self.memory_manager.lock().as_ref().unwrap().guest_memory(); + let mem = guest_memory.memory(); + + let device_info = &self + .device_manager + .lock() + .unwrap() + .get_device_info() + .clone(); + + arch::configure_system( + &self.memory_manager.lock().as_ref().unwrap().fd, + &mem, + &cmdline_cstring, + self.cpu_manager.lock().unwrap().boot_vcpus() as u64, + vcpu_mpidrs, + device_info, + &None, + ) + .map_err(Error::ConfigureSystem)?; + + self.device_manager + .lock() + .unwrap() + .enable_interrupt_controller() + .map_err(Error::EnableInterruptController)?; + + Ok(()) } pub fn shutdown(&mut self) -> Result<()> {