arch: Remove GICv2

Virtio-mmio is removed, now virtio-pci is the only option for virtio
transport layer. We use MSI for PCI device interrupt. While GICv2, the
legacy interrupt controller, doesn't support MSI. So GICv2 is not very
practical for Cloud-hypervisor, we can remove it.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
Michael Zhao 2020-10-17 15:16:38 +08:00 committed by Rob Bradford
parent 58474854f2
commit 2f2e10ea35
5 changed files with 12 additions and 173 deletions

View File

@ -1,140 +0,0 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
pub mod kvm {
use crate::aarch64::gic::kvm::KvmGICDevice;
use crate::aarch64::gic::{Error, GICDevice};
use std::any::Any;
use std::{boxed::Box, result};
type Result<T> = result::Result<T, Error>;
use crate::layout;
use hypervisor::kvm::kvm_bindings;
use std::convert::TryInto;
use std::sync::Arc;
/// Represent a GIC v2 device
pub struct KvmGICv2 {
/// The hypervisor agnostic device
device: Arc<dyn hypervisor::Device>,
/// Vector holding values of GICR_TYPER for each vCPU
/// As GICv2 does not have redistributor, this field is always
/// a zero vector.
gicr_typers: Vec<u64>,
/// GIC device properties, to be used for setting up the fdt entry
properties: [u64; 4],
/// Number of CPUs handled by the device
vcpu_count: u64,
}
impl KvmGICv2 {
// Unfortunately bindgen omits defines that are based on other defines.
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
const KVM_VGIC_V2_DIST_SIZE: u64 = 0x1000;
const KVM_VGIC_V2_CPU_SIZE: u64 = 0x2000;
// Device trees specific constants
const ARCH_GIC_V2_MAINT_IRQ: u32 = 8;
/// Get the address of the GICv2 distributor.
const fn get_dist_addr() -> u64 {
layout::MAPPED_IO_START - KvmGICv2::KVM_VGIC_V2_DIST_SIZE
}
/// Get the size of the GIC_v2 distributor.
const fn get_dist_size() -> u64 {
KvmGICv2::KVM_VGIC_V2_DIST_SIZE
}
/// Get the address of the GIC_v2 CPU.
const fn get_cpu_addr() -> u64 {
KvmGICv2::get_dist_addr() - KvmGICv2::KVM_VGIC_V2_CPU_SIZE
}
/// Get the size of the GIC_v2 CPU.
const fn get_cpu_size() -> u64 {
KvmGICv2::KVM_VGIC_V2_CPU_SIZE
}
}
impl GICDevice for KvmGICv2 {
fn device(&self) -> &Arc<dyn hypervisor::Device> {
&self.device
}
fn device_properties(&self) -> &[u64] {
&self.properties
}
fn fdt_compatibility(&self) -> &str {
"arm,gic-400"
}
fn fdt_maint_irq(&self) -> u32 {
KvmGICv2::ARCH_GIC_V2_MAINT_IRQ
}
fn vcpu_count(&self) -> u64 {
self.vcpu_count
}
fn set_gicr_typers(&mut self, gicr_typers: Vec<u64>) {
self.gicr_typers = gicr_typers;
}
fn as_any_concrete_mut(&mut self) -> &mut dyn Any {
self
}
}
impl KvmGICDevice for KvmGICv2 {
fn version() -> u32 {
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2
}
fn create_device(
device: Arc<dyn hypervisor::Device>,
vcpu_count: u64,
) -> Box<dyn GICDevice> {
Box::new(KvmGICv2 {
device,
gicr_typers: vec![0; vcpu_count.try_into().unwrap()],
properties: [
KvmGICv2::get_dist_addr(),
KvmGICv2::get_dist_size(),
KvmGICv2::get_cpu_addr(),
KvmGICv2::get_cpu_size(),
],
vcpu_count,
})
}
fn init_device_attributes(
_vm: &Arc<dyn hypervisor::Vm>,
gic_device: &dyn GICDevice,
) -> Result<()> {
/* Setting up the distributor attribute.
We are placing the GIC below 1GB so we need to substract the size of the distributor. */
Self::set_device_attribute(
gic_device.device(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_DIST),
&KvmGICv2::get_dist_addr() as *const u64 as u64,
0,
)?;
/* Setting up the CPU attribute. */
Self::set_device_attribute(
gic_device.device(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_CPU),
&KvmGICv2::get_cpu_addr() as *const u64 as u64,
0,
)?;
Ok(())
}
}
}

View File

@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
pub mod dist_regs;
pub mod gicv2;
pub mod gicv3;
pub mod gicv3_its;
pub mod icc_regs;
@ -68,8 +67,6 @@ pub trait GICDevice: Send {
pub mod kvm {
use super::GICDevice;
use super::Result;
use crate::aarch64::gic::gicv2::kvm::KvmGICv2;
use crate::aarch64::gic::gicv3::kvm::KvmGICv3;
use crate::aarch64::gic::gicv3_its::kvm::KvmGICv3ITS;
use crate::layout;
use hypervisor::kvm::kvm_bindings;
@ -190,25 +187,11 @@ pub mod kvm {
}
}
/// Create a GIC device.
/// Create a GICv3-ITS device.
///
/// 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: &Arc<dyn hypervisor::Vm>,
vcpu_count: u64,
its_required: bool,
) -> Result<Box<dyn GICDevice>> {
if its_required {
debug!("GICv3-ITS is required, creating a GICv3-ITS here.");
KvmGICv3ITS::new(vm, vcpu_count)
} else {
debug!("GICv3-ITS is not required, will try GICv3 instead.");
KvmGICv3::new(vm, vcpu_count).or_else(|_| {
debug!("Failed to create GICv3, will try GICv2 instead.");
KvmGICv2::new(vm, vcpu_count)
})
}
pub fn create_gic(vm: &Arc<dyn hypervisor::Vm>, vcpu_count: u64) -> Result<Box<dyn GICDevice>> {
debug!("creating a GICv3-ITS");
KvmGICv3ITS::new(vm, vcpu_count)
}
/// Function that saves RDIST pending tables into guest RAM.

View File

@ -128,11 +128,7 @@ pub fn configure_system<T: DeviceInfoForFDT + Clone + Debug, S: ::std::hash::Bui
initrd: &Option<super::InitramfsConfig>,
pci_space_address: &Option<(u64, u64)>,
) -> super::Result<Box<dyn GICDevice>> {
// If pci_space_address is present, it means PCI devices are used ("pci" feature enabled).
// Then GITv3-ITS is required for MSI messaging.
// Otherwise ("mmio" feature enabled), any version of GIC is OK.
let gic_device = gic::kvm::create_gic(vm, vcpu_count, pci_space_address.is_some())
.map_err(Error::SetupGIC)?;
let gic_device = gic::kvm::create_gic(vm, vcpu_count).map_err(Error::SetupGIC)?;
fdt::create_fdt(
guest_mem,

View File

@ -408,7 +408,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
assert!(create_gic(&vm, 1, false).is_ok());
assert!(create_gic(&vm, 1).is_ok());
}
#[test]
@ -416,7 +416,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let _ = vm.create_vcpu(0).unwrap();
let gic = create_gic(&vm, 1, false).expect("Cannot create gic");
let gic = create_gic(&vm, 1).expect("Cannot create gic");
let res = get_dist_regs(gic.device());
assert!(res.is_ok());
@ -432,7 +432,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let _ = vm.create_vcpu(0).unwrap();
let gic = create_gic(&vm, 1, false).expect("Cannot create gic");
let gic = create_gic(&vm, 1).expect("Cannot create gic");
let mut gicr_typer = Vec::new();
gicr_typer.push(123);
@ -450,7 +450,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let _ = vm.create_vcpu(0).unwrap();
let gic = create_gic(&vm, 1, false).expect("Cannot create gic");
let gic = create_gic(&vm, 1).expect("Cannot create gic");
let mut gicr_typer = Vec::new();
gicr_typer.push(123);
@ -468,7 +468,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let _ = vm.create_vcpu(0).unwrap();
let gic = create_gic(&vm, 1, false).expect("Cannot create gic");
let gic = create_gic(&vm, 1).expect("Cannot create gic");
assert!(save_pending_tables(gic.device()).is_ok());
}

View File

@ -1560,7 +1560,7 @@ impl Vm {
// Creating a GIC device here, as the GIC will not be created when
// restoring the device manager. Note that currently only the bare GICv3
// without ITS is supported.
let gic_device = create_gic(&self.vm, vcpu_numbers.try_into().unwrap(), false)
let gic_device = create_gic(&self.vm, vcpu_numbers.try_into().unwrap())
.map_err(|e| MigratableError::Restore(anyhow!("Could not create GIC: {:#?}", e)))?;
// Update the GIC entity in device manager
@ -2027,7 +2027,7 @@ mod tests {
let hv = hypervisor::new().unwrap();
let vm = hv.create_vm().unwrap();
let gic = create_gic(&vm, 1, false).unwrap();
let gic = create_gic(&vm, 1).unwrap();
assert!(create_fdt(
&mem,
&CString::new("console=tty0").unwrap(),