arch, pci, vmm: Initial switch to the hypervisor crate

Start moving the vmm, arch and pci crates to being hypervisor agnostic
by using the hypervisor trait and abstractions. This is not a complete
switch and there are still some remaining KVM dependencies.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Muminul Islam
2020-06-01 19:29:54 -07:00
committed by Samuel Ortiz
parent c48d0c1a67
commit e4dee57e81
24 changed files with 294 additions and 1023 deletions

View File

@@ -1,9 +1,9 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use std::{boxed::Box, result};
use kvm_ioctls::{DeviceFd, VmFd};
use std::sync::Arc;
use std::{boxed::Box, result};
use super::gicv2::GICv2;
use super::gicv3::GICv3;
@@ -12,7 +12,7 @@ use super::gicv3::GICv3;
#[derive(Debug)]
pub enum Error {
/// Error while calling KVM ioctl for setting up the global interrupt controller.
CreateGIC(kvm_ioctls::Error),
CreateGIC(hypervisor::HypervisorVmError),
/// Error while setting device attributes for the GIC.
SetDeviceAttribute(kvm_ioctls::Error),
}
@@ -51,7 +51,7 @@ pub trait GICDevice: Send + Sync {
Self: Sized;
/// Initialize a GIC device
fn init_device(vm: &VmFd) -> Result<DeviceFd>
fn init_device(vm: &Arc<dyn hypervisor::Vm>) -> Result<DeviceFd>
where
Self: Sized,
{
@@ -120,7 +120,7 @@ pub trait GICDevice: Send + Sync {
}
/// Method to initialize the GIC device
fn new(vm: &VmFd, vcpu_count: u64) -> Result<Box<dyn GICDevice>>
fn new(vm: &Arc<dyn hypervisor::Vm>, vcpu_count: u64) -> Result<Box<dyn GICDevice>>
where
Self: Sized,
{
@@ -140,7 +140,7 @@ pub trait GICDevice: Send + Sync {
///
/// It will try to create by default a GICv3 device. If that fails it will try
/// to fall-back to a GICv2 device.
pub fn create_gic(vm: &VmFd, vcpu_count: u64) -> Result<Box<dyn GICDevice>> {
pub fn create_gic(vm: &Arc<dyn hypervisor::Vm>, vcpu_count: u64) -> Result<Box<dyn GICDevice>> {
GICv3::new(vm, vcpu_count).or_else(|_| GICv2::new(vm, vcpu_count))
}

View File

@@ -20,6 +20,7 @@ use kvm_ioctls::*;
use std::collections::HashMap;
use std::ffi::CStr;
use std::fmt::Debug;
use std::sync::Arc;
use vm_memory::{
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap,
GuestUsize,
@@ -41,10 +42,10 @@ pub enum Error {
REGSConfiguration(regs::Error),
/// Error fetching prefered target
VcpuArmPreferredTarget(kvm_ioctls::Error),
VcpuArmPreferredTarget(hypervisor::HypervisorVmError),
/// Error doing Vcpu Init on Arm.
VcpuArmInit(kvm_ioctls::Error),
VcpuArmInit(hypervisor::HypervisorCpuError),
}
impl From<Error> for super::Error {
@@ -63,9 +64,9 @@ pub struct EntryPoint {
/// Configure the specified VCPU, and return its MPIDR.
pub fn configure_vcpu(
fd: &VcpuFd,
fd: &Arc<dyn hypervisor::Vcpu>,
id: u8,
vm_fd: &VmFd,
vm_fd: &Arc<dyn hypervisor::Vm>,
kernel_entry_point: Option<EntryPoint>,
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
) -> super::Result<u64> {
@@ -138,7 +139,7 @@ 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,
vm_fd: &Arc<dyn hypervisor::Vm>,
guest_mem: &GuestMemoryMmap,
cmdline_cstring: &CStr,
vcpu_count: u64,
@@ -200,13 +201,6 @@ pub fn get_host_cpu_phys_bits() -> u8 {
40
}
pub fn check_required_kvm_extensions(kvm: &Kvm) -> super::Result<()> {
if !kvm.check_extension(Cap::SignalMsi) {
return Err(super::Error::CapabilityMissing(Cap::SignalMsi));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -5,8 +5,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.
use std::{mem, result};
use super::get_fdt_addr;
use kvm_bindings::{
user_pt_regs, KVM_REG_ARM64, KVM_REG_ARM64_SYSREG, KVM_REG_ARM64_SYSREG_CRM_MASK,
@@ -16,16 +14,17 @@ use kvm_bindings::{
KVM_REG_ARM_CORE, KVM_REG_SIZE_U64,
};
use kvm_ioctls::VcpuFd;
use std::sync::Arc;
use std::{mem, result};
use vm_memory::GuestMemoryMmap;
/// Errors thrown while setting aarch64 registers.
#[derive(Debug)]
pub enum Error {
/// Failed to set core register (PC, PSTATE or general purpose ones).
SetCoreRegister(kvm_ioctls::Error),
SetCoreRegister(hypervisor::HypervisorCpuError),
/// Failed to get a system register.
GetSysRegister(kvm_ioctls::Error),
GetSysRegister(hypervisor::HypervisorCpuError),
}
type Result<T> = result::Result<T, Error>;
@@ -122,7 +121,12 @@ arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5);
/// * `cpu_id` - Index of current vcpu.
/// * `boot_ip` - Starting instruction pointer.
/// * `mem` - Reserved DRAM for current VM.
pub fn setup_regs(vcpu: &VcpuFd, cpu_id: u8, boot_ip: u64, mem: &GuestMemoryMmap) -> Result<()> {
pub fn setup_regs(
vcpu: &Arc<dyn hypervisor::Vcpu>,
cpu_id: u8,
boot_ip: u64,
mem: &GuestMemoryMmap,
) -> Result<()> {
// Get the register index of the PSTATE (Processor State) register.
vcpu.set_one_reg(arm64_core_reg!(pstate), PSTATE_FAULT_BITS_64)
.map_err(Error::SetCoreRegister)?;
@@ -148,7 +152,7 @@ pub fn setup_regs(vcpu: &VcpuFd, cpu_id: u8, boot_ip: u64, mem: &GuestMemoryMmap
/// # Arguments
///
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
pub fn read_mpidr(vcpu: &VcpuFd) -> Result<u64> {
pub fn read_mpidr(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<u64> {
vcpu.get_one_reg(MPIDR_EL1).map_err(Error::GetSysRegister)
}