vmm: Configure VM on AArch64

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
Michael Zhao 2020-06-09 18:28:02 +08:00 committed by Rob Bradford
parent 917219fa92
commit 5cd1730bc4
6 changed files with 77 additions and 23 deletions

View File

@ -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<T: DeviceInfoForFDT + Clone + Debug>(
vm_fd: &VmFd,
guest_mem: &GuestMemoryMmap,
cmdline_cstring: &CStr,
vcpu_count: u64,
vcpu_mpidr: Vec<u64>,
device_info: &HashMap<(DeviceType, String), T>,
gic_device: &Box<dyn GICDevice>,
initrd: &Option<super::InitramfsConfig>,
) -> 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)?;

View File

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

View File

@ -1000,13 +1000,13 @@ impl CpuManager {
}
#[cfg(target_arch = "aarch64")]
pub fn get_mpidr(&self) -> Vec<u64> {
let vcpu_mpidr = self
pub fn get_mpidrs(&self) -> Vec<u64> {
let vcpu_mpidrs = self
.vcpus
.iter()
.map(|cpu| cpu.lock().unwrap().get_mpidr())
.collect();
vcpu_mpidr
vcpu_mpidrs
}
#[cfg(feature = "acpi")]

View File

@ -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,

View File

@ -56,7 +56,7 @@ pub struct MemoryManager {
next_kvm_memory_slot: u32,
start_of_device_area: GuestAddress,
end_of_device_area: GuestAddress,
fd: Arc<VmFd>,
pub fd: Arc<VmFd>,
hotplug_slots: Vec<HotPlugState>,
selected_slot: usize,
backing_file: Option<PathBuf>,

View File

@ -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<File>,
@ -485,7 +483,25 @@ impl Vm {
#[cfg(target_arch = "aarch64")]
fn load_kernel(&mut self) -> Result<EntryPoint> {
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<()> {