mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-08-22 07:51:16 +00:00
arch: Refactor GIC code to seperate KVM specific code
Shrink GICDevice trait to contain hypervisor agnostic API's only, which are used in generating FDT. Move all KVM specific logic into KvmGICDevice trait. Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
parent
6e8c8991d9
commit
e3e771727a
@ -1,12 +1,8 @@
|
|||||||
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::gicv2::GICv2;
|
|
||||||
use super::gicv3::GICv3;
|
|
||||||
use super::gicv3_its::GICv3ITS;
|
|
||||||
use kvm_ioctls::DeviceFd;
|
use kvm_ioctls::DeviceFd;
|
||||||
use std::sync::Arc;
|
use std::result;
|
||||||
use std::{boxed::Box, result};
|
|
||||||
|
|
||||||
/// Errors thrown while setting up the GIC.
|
/// Errors thrown while setting up the GIC.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -14,31 +10,25 @@ pub enum Error {
|
|||||||
/// Error while calling KVM ioctl for setting up the global interrupt controller.
|
/// Error while calling KVM ioctl for setting up the global interrupt controller.
|
||||||
CreateGIC(hypervisor::HypervisorVmError),
|
CreateGIC(hypervisor::HypervisorVmError),
|
||||||
/// Error while setting device attributes for the GIC.
|
/// Error while setting device attributes for the GIC.
|
||||||
SetDeviceAttribute(kvm_ioctls::Error),
|
SetDeviceAttribute(hypervisor::kvm_ioctls::Error),
|
||||||
}
|
}
|
||||||
type Result<T> = result::Result<T, Error>;
|
type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
/// Trait for GIC devices.
|
pub trait GICDevice {
|
||||||
pub trait GICDevice: Send + Sync {
|
|
||||||
/// Returns the file descriptor of the GIC device
|
/// Returns the file descriptor of the GIC device
|
||||||
fn device_fd(&self) -> &DeviceFd;
|
fn device_fd(&self) -> &DeviceFd;
|
||||||
|
|
||||||
/// Returns an array with GIC device properties
|
|
||||||
fn device_properties(&self) -> &[u64];
|
|
||||||
|
|
||||||
/// Returns the number of vCPUs this GIC handles
|
|
||||||
fn vcpu_count(&self) -> u64;
|
|
||||||
|
|
||||||
/// Returns the fdt compatibility property of the device
|
/// Returns the fdt compatibility property of the device
|
||||||
fn fdt_compatibility(&self) -> &str;
|
fn fdt_compatibility(&self) -> &str;
|
||||||
|
|
||||||
/// Returns the maint_irq fdt property of the device
|
/// Returns the maint_irq fdt property of the device
|
||||||
fn fdt_maint_irq(&self) -> u32;
|
fn fdt_maint_irq(&self) -> u32;
|
||||||
|
|
||||||
/// Returns the GIC version of the device
|
/// Returns an array with GIC device properties
|
||||||
fn version() -> u32
|
fn device_properties(&self) -> &[u64];
|
||||||
where
|
|
||||||
Self: Sized;
|
/// Returns the number of vCPUs this GIC handles
|
||||||
|
fn vcpu_count(&self) -> u64;
|
||||||
|
|
||||||
/// Returns whether the GIC device is MSI compatible or not
|
/// Returns whether the GIC device is MSI compatible or not
|
||||||
fn msi_compatible(&self) -> bool {
|
fn msi_compatible(&self) -> bool {
|
||||||
@ -54,6 +44,25 @@ pub trait GICDevice: Send + Sync {
|
|||||||
fn msi_properties(&self) -> &[u64] {
|
fn msi_properties(&self) -> &[u64] {
|
||||||
&[]
|
&[]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod kvm {
|
||||||
|
use super::super::gicv2::kvm::KvmGICv2;
|
||||||
|
use super::super::gicv3::kvm::KvmGICv3;
|
||||||
|
use super::super::gicv3_its::kvm::KvmGICv3ITS;
|
||||||
|
use super::super::layout;
|
||||||
|
use super::GICDevice;
|
||||||
|
use super::Result;
|
||||||
|
use kvm_ioctls::DeviceFd;
|
||||||
|
use std::boxed::Box;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// Trait for GIC devices.
|
||||||
|
pub trait KvmGICDevice: Send + Sync + GICDevice {
|
||||||
|
/// Returns the GIC version of the device
|
||||||
|
fn version() -> u32
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
|
||||||
/// Create the GIC device object
|
/// Create the GIC device object
|
||||||
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice>
|
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice>
|
||||||
@ -79,7 +88,8 @@ pub trait GICDevice: Send + Sync {
|
|||||||
flags: 0,
|
flags: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.create_device(&mut gic_device).map_err(Error::CreateGIC)
|
vm.create_device(&mut gic_device)
|
||||||
|
.map_err(super::Error::CreateGIC)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a GIC device attribute
|
/// Set a GIC device attribute
|
||||||
@ -100,7 +110,7 @@ pub trait GICDevice: Send + Sync {
|
|||||||
flags: flags,
|
flags: flags,
|
||||||
};
|
};
|
||||||
fd.set_device_attr(&attr)
|
fd.set_device_attr(&attr)
|
||||||
.map_err(Error::SetDeviceAttribute)?;
|
.map_err(super::Error::SetDeviceAttribute)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -113,7 +123,7 @@ pub trait GICDevice: Send + Sync {
|
|||||||
/* We need to tell the kernel how many irqs to support with this vgic.
|
/* We need to tell the kernel how many irqs to support with this vgic.
|
||||||
* See the `layout` module for details.
|
* See the `layout` module for details.
|
||||||
*/
|
*/
|
||||||
let nr_irqs: u32 = super::layout::IRQ_MAX - super::layout::IRQ_BASE + 1;
|
let nr_irqs: u32 = layout::IRQ_MAX - layout::IRQ_BASE + 1;
|
||||||
let nr_irqs_ptr = &nr_irqs as *const u32;
|
let nr_irqs_ptr = &nr_irqs as *const u32;
|
||||||
Self::set_device_attribute(
|
Self::set_device_attribute(
|
||||||
gic_device.device_fd(),
|
gic_device.device_fd(),
|
||||||
@ -152,26 +162,27 @@ pub trait GICDevice: Send + Sync {
|
|||||||
|
|
||||||
Ok(device)
|
Ok(device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a GIC device.
|
/// Create a GIC device.
|
||||||
///
|
///
|
||||||
/// It will try to create by default a GICv3 device. If that fails it will try
|
/// It will try to create by default a GICv3 device. If that fails it will try
|
||||||
/// to fall-back to a GICv2 device.
|
/// to fall-back to a GICv2 device.
|
||||||
pub fn create_gic(
|
pub fn create_gic(
|
||||||
vm: &Arc<dyn hypervisor::Vm>,
|
vm: &Arc<dyn hypervisor::Vm>,
|
||||||
vcpu_count: u64,
|
vcpu_count: u64,
|
||||||
its_required: bool,
|
its_required: bool,
|
||||||
) -> Result<Box<dyn GICDevice>> {
|
) -> Result<Box<dyn GICDevice>> {
|
||||||
if its_required {
|
if its_required {
|
||||||
GICv3ITS::new(vm, vcpu_count)
|
KvmGICv3ITS::new(vm, vcpu_count)
|
||||||
} else {
|
} else {
|
||||||
GICv3ITS::new(vm, vcpu_count).or_else(|_| {
|
KvmGICv3ITS::new(vm, vcpu_count).or_else(|_| {
|
||||||
debug!("Failed to create GICv3-ITS, will try GICv3 instead.");
|
debug!("Failed to create GICv3-ITS, will try GICv3 instead.");
|
||||||
GICv3::new(vm, vcpu_count).or_else(|_| {
|
KvmGICv3::new(vm, vcpu_count).or_else(|_| {
|
||||||
debug!("Failed to create GICv3, will try GICv2 instead.");
|
debug!("Failed to create GICv3, will try GICv2 instead.");
|
||||||
GICv2::new(vm, vcpu_count)
|
KvmGICv2::new(vm, vcpu_count)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::gic::{Error, GICDevice};
|
pub mod kvm {
|
||||||
use kvm_ioctls::DeviceFd;
|
use super::super::gic::{Error, GICDevice};
|
||||||
use std::sync::Arc;
|
use std::{boxed::Box, result};
|
||||||
use std::{boxed::Box, result};
|
type Result<T> = result::Result<T, Error>;
|
||||||
|
use super::super::gic::kvm::KvmGICDevice;
|
||||||
|
use super::super::layout;
|
||||||
|
use kvm_ioctls::DeviceFd;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
type Result<T> = result::Result<T, Error>;
|
/// Represent a GIC v2 device
|
||||||
|
pub struct KvmGICv2 {
|
||||||
/// Represent a GIC v2 device
|
|
||||||
pub struct GICv2 {
|
|
||||||
/// The file descriptor for the KVM device
|
/// The file descriptor for the KVM device
|
||||||
fd: DeviceFd,
|
fd: DeviceFd,
|
||||||
|
|
||||||
@ -18,9 +20,9 @@ pub struct GICv2 {
|
|||||||
|
|
||||||
/// Number of CPUs handled by the device
|
/// Number of CPUs handled by the device
|
||||||
vcpu_count: u64,
|
vcpu_count: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GICv2 {
|
impl KvmGICv2 {
|
||||||
// Unfortunately bindgen omits defines that are based on other defines.
|
// Unfortunately bindgen omits defines that are based on other defines.
|
||||||
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
|
// 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_DIST_SIZE: u64 = 0x1000;
|
||||||
@ -31,30 +33,26 @@ impl GICv2 {
|
|||||||
|
|
||||||
/// Get the address of the GICv2 distributor.
|
/// Get the address of the GICv2 distributor.
|
||||||
const fn get_dist_addr() -> u64 {
|
const fn get_dist_addr() -> u64 {
|
||||||
super::layout::MAPPED_IO_START - GICv2::KVM_VGIC_V2_DIST_SIZE
|
layout::MAPPED_IO_START - KvmGICv2::KVM_VGIC_V2_DIST_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the size of the GIC_v2 distributor.
|
/// Get the size of the GIC_v2 distributor.
|
||||||
const fn get_dist_size() -> u64 {
|
const fn get_dist_size() -> u64 {
|
||||||
GICv2::KVM_VGIC_V2_DIST_SIZE
|
KvmGICv2::KVM_VGIC_V2_DIST_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the address of the GIC_v2 CPU.
|
/// Get the address of the GIC_v2 CPU.
|
||||||
const fn get_cpu_addr() -> u64 {
|
const fn get_cpu_addr() -> u64 {
|
||||||
GICv2::get_dist_addr() - GICv2::KVM_VGIC_V2_CPU_SIZE
|
KvmGICv2::get_dist_addr() - KvmGICv2::KVM_VGIC_V2_CPU_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the size of the GIC_v2 CPU.
|
/// Get the size of the GIC_v2 CPU.
|
||||||
const fn get_cpu_size() -> u64 {
|
const fn get_cpu_size() -> u64 {
|
||||||
GICv2::KVM_VGIC_V2_CPU_SIZE
|
KvmGICv2::KVM_VGIC_V2_CPU_SIZE
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl GICDevice for GICv2 {
|
|
||||||
fn version() -> u32 {
|
|
||||||
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GICDevice for KvmGICv2 {
|
||||||
fn device_fd(&self) -> &DeviceFd {
|
fn device_fd(&self) -> &DeviceFd {
|
||||||
&self.fd
|
&self.fd
|
||||||
}
|
}
|
||||||
@ -63,26 +61,32 @@ impl GICDevice for GICv2 {
|
|||||||
&self.properties
|
&self.properties
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vcpu_count(&self) -> u64 {
|
|
||||||
self.vcpu_count
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fdt_compatibility(&self) -> &str {
|
fn fdt_compatibility(&self) -> &str {
|
||||||
"arm,gic-400"
|
"arm,gic-400"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fdt_maint_irq(&self) -> u32 {
|
fn fdt_maint_irq(&self) -> u32 {
|
||||||
GICv2::ARCH_GIC_V2_MAINT_IRQ
|
KvmGICv2::ARCH_GIC_V2_MAINT_IRQ
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vcpu_count(&self) -> u64 {
|
||||||
|
self.vcpu_count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KvmGICDevice for KvmGICv2 {
|
||||||
|
fn version() -> u32 {
|
||||||
|
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice> {
|
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice> {
|
||||||
Box::new(GICv2 {
|
Box::new(KvmGICv2 {
|
||||||
fd: fd,
|
fd: fd,
|
||||||
properties: [
|
properties: [
|
||||||
GICv2::get_dist_addr(),
|
KvmGICv2::get_dist_addr(),
|
||||||
GICv2::get_dist_size(),
|
KvmGICv2::get_dist_size(),
|
||||||
GICv2::get_cpu_addr(),
|
KvmGICv2::get_cpu_addr(),
|
||||||
GICv2::get_cpu_size(),
|
KvmGICv2::get_cpu_size(),
|
||||||
],
|
],
|
||||||
vcpu_count: vcpu_count,
|
vcpu_count: vcpu_count,
|
||||||
})
|
})
|
||||||
@ -98,7 +102,7 @@ impl GICDevice for GICv2 {
|
|||||||
&gic_device.device_fd(),
|
&gic_device.device_fd(),
|
||||||
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
||||||
u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_DIST),
|
u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_DIST),
|
||||||
&GICv2::get_dist_addr() as *const u64 as u64,
|
&KvmGICv2::get_dist_addr() as *const u64 as u64,
|
||||||
0,
|
0,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -107,10 +111,11 @@ impl GICDevice for GICv2 {
|
|||||||
&gic_device.device_fd(),
|
&gic_device.device_fd(),
|
||||||
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
||||||
u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_CPU),
|
u64::from(kvm_bindings::KVM_VGIC_V2_ADDR_TYPE_CPU),
|
||||||
&GICv2::get_cpu_addr() as *const u64 as u64,
|
&KvmGICv2::get_cpu_addr() as *const u64 as u64,
|
||||||
0,
|
0,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::gic::{Error, GICDevice};
|
pub mod kvm {
|
||||||
use kvm_ioctls::DeviceFd;
|
use super::super::gic::kvm::KvmGICDevice;
|
||||||
use std::sync::Arc;
|
use super::super::gic::{Error, GICDevice};
|
||||||
use std::{boxed::Box, result};
|
use super::super::layout;
|
||||||
|
use kvm_ioctls::DeviceFd;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::{boxed::Box, result};
|
||||||
|
type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
type Result<T> = result::Result<T, Error>;
|
pub struct KvmGICv3 {
|
||||||
|
|
||||||
pub struct GICv3 {
|
|
||||||
/// The file descriptor for the KVM device
|
/// The file descriptor for the KVM device
|
||||||
fd: DeviceFd,
|
fd: DeviceFd,
|
||||||
|
|
||||||
@ -17,48 +19,52 @@ pub struct GICv3 {
|
|||||||
|
|
||||||
/// Number of CPUs handled by the device
|
/// Number of CPUs handled by the device
|
||||||
vcpu_count: u64,
|
vcpu_count: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GICv3 {
|
impl KvmGICv3 {
|
||||||
// Unfortunately bindgen omits defines that are based on other defines.
|
// Unfortunately bindgen omits defines that are based on other defines.
|
||||||
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
|
// See arch/arm64/include/uapi/asm/kvm.h file from the linux kernel.
|
||||||
pub const SZ_64K: u64 = 0x0001_0000;
|
pub const SZ_64K: u64 = 0x0001_0000;
|
||||||
const KVM_VGIC_V3_DIST_SIZE: u64 = GICv3::SZ_64K;
|
const KVM_VGIC_V3_DIST_SIZE: u64 = KvmGICv3::SZ_64K;
|
||||||
const KVM_VGIC_V3_REDIST_SIZE: u64 = (2 * GICv3::SZ_64K);
|
const KVM_VGIC_V3_REDIST_SIZE: u64 = (2 * KvmGICv3::SZ_64K);
|
||||||
|
|
||||||
// Device trees specific constants
|
// Device trees specific constants
|
||||||
pub const ARCH_GIC_V3_MAINT_IRQ: u32 = 9;
|
pub const ARCH_GIC_V3_MAINT_IRQ: u32 = 9;
|
||||||
|
|
||||||
/// Get the address of the GIC distributor.
|
/// Get the address of the GIC distributor.
|
||||||
pub fn get_dist_addr() -> u64 {
|
pub fn get_dist_addr() -> u64 {
|
||||||
super::layout::MAPPED_IO_START - GICv3::KVM_VGIC_V3_DIST_SIZE
|
layout::MAPPED_IO_START - KvmGICv3::KVM_VGIC_V3_DIST_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the size of the GIC distributor.
|
/// Get the size of the GIC distributor.
|
||||||
pub fn get_dist_size() -> u64 {
|
pub fn get_dist_size() -> u64 {
|
||||||
GICv3::KVM_VGIC_V3_DIST_SIZE
|
KvmGICv3::KVM_VGIC_V3_DIST_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the address of the GIC redistributors.
|
/// Get the address of the GIC redistributors.
|
||||||
pub fn get_redists_addr(vcpu_count: u64) -> u64 {
|
pub fn get_redists_addr(vcpu_count: u64) -> u64 {
|
||||||
GICv3::get_dist_addr() - GICv3::get_redists_size(vcpu_count)
|
KvmGICv3::get_dist_addr() - KvmGICv3::get_redists_size(vcpu_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the size of the GIC redistributors.
|
/// Get the size of the GIC redistributors.
|
||||||
pub fn get_redists_size(vcpu_count: u64) -> u64 {
|
pub fn get_redists_size(vcpu_count: u64) -> u64 {
|
||||||
vcpu_count * GICv3::KVM_VGIC_V3_REDIST_SIZE
|
vcpu_count * KvmGICv3::KVM_VGIC_V3_REDIST_SIZE
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl GICDevice for GICv3 {
|
|
||||||
fn version() -> u32 {
|
|
||||||
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GICDevice for KvmGICv3 {
|
||||||
fn device_fd(&self) -> &DeviceFd {
|
fn device_fd(&self) -> &DeviceFd {
|
||||||
&self.fd
|
&self.fd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fdt_compatibility(&self) -> &str {
|
||||||
|
"arm,gic-v3"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fdt_maint_irq(&self) -> u32 {
|
||||||
|
KvmGICv3::ARCH_GIC_V3_MAINT_IRQ
|
||||||
|
}
|
||||||
|
|
||||||
fn device_properties(&self) -> &[u64] {
|
fn device_properties(&self) -> &[u64] {
|
||||||
&self.properties
|
&self.properties
|
||||||
}
|
}
|
||||||
@ -66,23 +72,21 @@ impl GICDevice for GICv3 {
|
|||||||
fn vcpu_count(&self) -> u64 {
|
fn vcpu_count(&self) -> u64 {
|
||||||
self.vcpu_count
|
self.vcpu_count
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fdt_compatibility(&self) -> &str {
|
|
||||||
"arm,gic-v3"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fdt_maint_irq(&self) -> u32 {
|
impl KvmGICDevice for KvmGICv3 {
|
||||||
GICv3::ARCH_GIC_V3_MAINT_IRQ
|
fn version() -> u32 {
|
||||||
|
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice> {
|
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice> {
|
||||||
Box::new(GICv3 {
|
Box::new(KvmGICv3 {
|
||||||
fd: fd,
|
fd: fd,
|
||||||
properties: [
|
properties: [
|
||||||
GICv3::get_dist_addr(),
|
KvmGICv3::get_dist_addr(),
|
||||||
GICv3::get_dist_size(),
|
KvmGICv3::get_dist_size(),
|
||||||
GICv3::get_redists_addr(vcpu_count),
|
KvmGICv3::get_redists_addr(vcpu_count),
|
||||||
GICv3::get_redists_size(vcpu_count),
|
KvmGICv3::get_redists_size(vcpu_count),
|
||||||
],
|
],
|
||||||
vcpu_count: vcpu_count,
|
vcpu_count: vcpu_count,
|
||||||
})
|
})
|
||||||
@ -99,7 +103,7 @@ impl GICDevice for GICv3 {
|
|||||||
&gic_device.device_fd(),
|
&gic_device.device_fd(),
|
||||||
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
||||||
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_DIST),
|
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_DIST),
|
||||||
&GICv3::get_dist_addr() as *const u64 as u64,
|
&KvmGICv3::get_dist_addr() as *const u64 as u64,
|
||||||
0,
|
0,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -110,10 +114,12 @@ impl GICDevice for GICv3 {
|
|||||||
&gic_device.device_fd(),
|
&gic_device.device_fd(),
|
||||||
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
||||||
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_REDIST),
|
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_REDIST),
|
||||||
&GICv3::get_redists_addr(u64::from(gic_device.vcpu_count())) as *const u64 as u64,
|
&KvmGICv3::get_redists_addr(u64::from(gic_device.vcpu_count())) as *const u64
|
||||||
|
as u64,
|
||||||
0,
|
0,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
// Copyright 2020 ARM Limited
|
// Copyright 2020 ARM Limited
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
use super::gic::{Error, GICDevice};
|
pub mod kvm {
|
||||||
use super::gicv3::GICv3;
|
use std::sync::Arc;
|
||||||
use kvm_ioctls::DeviceFd;
|
use std::{boxed::Box, result};
|
||||||
use std::sync::Arc;
|
type Result<T> = result::Result<T, Error>;
|
||||||
use std::{boxed::Box, result};
|
use super::super::gic::kvm::KvmGICDevice;
|
||||||
|
use super::super::gic::{Error, GICDevice};
|
||||||
|
use super::super::gicv3::kvm::KvmGICv3;
|
||||||
|
use kvm_ioctls::DeviceFd;
|
||||||
|
|
||||||
type Result<T> = result::Result<T, Error>;
|
pub struct KvmGICv3ITS {
|
||||||
|
|
||||||
pub struct GICv3ITS {
|
|
||||||
/// The file descriptor for the KVM device
|
/// The file descriptor for the KVM device
|
||||||
fd: DeviceFd,
|
fd: DeviceFd,
|
||||||
|
|
||||||
@ -21,41 +22,25 @@ pub struct GICv3ITS {
|
|||||||
|
|
||||||
/// Number of CPUs handled by the device
|
/// Number of CPUs handled by the device
|
||||||
vcpu_count: u64,
|
vcpu_count: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GICv3ITS {
|
impl KvmGICv3ITS {
|
||||||
const KVM_VGIC_V3_ITS_SIZE: u64 = (2 * GICv3::SZ_64K);
|
const KVM_VGIC_V3_ITS_SIZE: u64 = (2 * KvmGICv3::SZ_64K);
|
||||||
|
|
||||||
fn get_msi_size() -> u64 {
|
fn get_msi_size() -> u64 {
|
||||||
GICv3ITS::KVM_VGIC_V3_ITS_SIZE
|
KvmGICv3ITS::KVM_VGIC_V3_ITS_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_msi_addr(vcpu_count: u64) -> u64 {
|
fn get_msi_addr(vcpu_count: u64) -> u64 {
|
||||||
GICv3::get_redists_addr(vcpu_count) - GICv3ITS::get_msi_size()
|
KvmGICv3::get_redists_addr(vcpu_count) - KvmGICv3ITS::get_msi_size()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl GICDevice for GICv3ITS {
|
|
||||||
fn version() -> u32 {
|
|
||||||
GICv3::version()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GICDevice for KvmGICv3ITS {
|
||||||
fn device_fd(&self) -> &DeviceFd {
|
fn device_fd(&self) -> &DeviceFd {
|
||||||
&self.fd
|
&self.fd
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_properties(&self) -> &[u64] {
|
|
||||||
&self.gic_properties
|
|
||||||
}
|
|
||||||
|
|
||||||
fn msi_properties(&self) -> &[u64] {
|
|
||||||
&self.msi_properties
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vcpu_count(&self) -> u64 {
|
|
||||||
self.vcpu_count
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fdt_compatibility(&self) -> &str {
|
fn fdt_compatibility(&self) -> &str {
|
||||||
"arm,gic-v3"
|
"arm,gic-v3"
|
||||||
}
|
}
|
||||||
@ -69,19 +54,40 @@ impl GICDevice for GICv3ITS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fdt_maint_irq(&self) -> u32 {
|
fn fdt_maint_irq(&self) -> u32 {
|
||||||
GICv3::ARCH_GIC_V3_MAINT_IRQ
|
KvmGICv3::ARCH_GIC_V3_MAINT_IRQ
|
||||||
|
}
|
||||||
|
|
||||||
|
fn msi_properties(&self) -> &[u64] {
|
||||||
|
&self.msi_properties
|
||||||
|
}
|
||||||
|
|
||||||
|
fn device_properties(&self) -> &[u64] {
|
||||||
|
&self.gic_properties
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vcpu_count(&self) -> u64 {
|
||||||
|
self.vcpu_count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KvmGICDevice for KvmGICv3ITS {
|
||||||
|
fn version() -> u32 {
|
||||||
|
KvmGICv3::version()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice> {
|
fn create_device(fd: DeviceFd, vcpu_count: u64) -> Box<dyn GICDevice> {
|
||||||
Box::new(GICv3ITS {
|
Box::new(KvmGICv3ITS {
|
||||||
fd: fd,
|
fd: fd,
|
||||||
gic_properties: [
|
gic_properties: [
|
||||||
GICv3::get_dist_addr(),
|
KvmGICv3::get_dist_addr(),
|
||||||
GICv3::get_dist_size(),
|
KvmGICv3::get_dist_size(),
|
||||||
GICv3::get_redists_addr(vcpu_count),
|
KvmGICv3::get_redists_addr(vcpu_count),
|
||||||
GICv3::get_redists_size(vcpu_count),
|
KvmGICv3::get_redists_size(vcpu_count),
|
||||||
|
],
|
||||||
|
msi_properties: [
|
||||||
|
KvmGICv3ITS::get_msi_addr(vcpu_count),
|
||||||
|
KvmGICv3ITS::get_msi_size(),
|
||||||
],
|
],
|
||||||
msi_properties: [GICv3ITS::get_msi_addr(vcpu_count), GICv3ITS::get_msi_size()],
|
|
||||||
vcpu_count: vcpu_count,
|
vcpu_count: vcpu_count,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -90,7 +96,7 @@ impl GICDevice for GICv3ITS {
|
|||||||
vm: &Arc<dyn hypervisor::Vm>,
|
vm: &Arc<dyn hypervisor::Vm>,
|
||||||
gic_device: &Box<dyn GICDevice>,
|
gic_device: &Box<dyn GICDevice>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
GICv3::init_device_attributes(vm, gic_device)?;
|
KvmGICv3::init_device_attributes(vm, gic_device)?;
|
||||||
|
|
||||||
let mut its_device = kvm_bindings::kvm_create_device {
|
let mut its_device = kvm_bindings::kvm_create_device {
|
||||||
type_: kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_ITS,
|
type_: kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_ITS,
|
||||||
@ -106,7 +112,7 @@ impl GICDevice for GICv3ITS {
|
|||||||
&its_fd,
|
&its_fd,
|
||||||
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
|
||||||
u64::from(kvm_bindings::KVM_VGIC_ITS_ADDR_TYPE),
|
u64::from(kvm_bindings::KVM_VGIC_ITS_ADDR_TYPE),
|
||||||
&GICv3ITS::get_msi_addr(u64::from(gic_device.vcpu_count())) as *const u64 as u64,
|
&KvmGICv3ITS::get_msi_addr(u64::from(gic_device.vcpu_count())) as *const u64 as u64,
|
||||||
0,
|
0,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -120,4 +126,5 @@ impl GICDevice for GICv3ITS {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,8 +148,8 @@ pub fn configure_system<T: DeviceInfoForFDT + Clone + Debug>(
|
|||||||
// If pci_space_address is present, it means PCI devices are used ("pci" feature enabled).
|
// If pci_space_address is present, it means PCI devices are used ("pci" feature enabled).
|
||||||
// Then GITv3-ITS is required for MSI messaging.
|
// Then GITv3-ITS is required for MSI messaging.
|
||||||
// Otherwise ("mmio" feature enabled), any version of GIC is OK.
|
// Otherwise ("mmio" feature enabled), any version of GIC is OK.
|
||||||
let gic_device =
|
let gic_device = gic::kvm::create_gic(vm, vcpu_count, pci_space_address.is_some())
|
||||||
gic::create_gic(vm, vcpu_count, pci_space_address.is_some()).map_err(Error::SetupGIC)?;
|
.map_err(Error::SetupGIC)?;
|
||||||
|
|
||||||
fdt::create_fdt(
|
fdt::create_fdt(
|
||||||
guest_mem,
|
guest_mem,
|
||||||
|
@ -395,7 +395,7 @@ pub mod kvm {
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use arch::aarch64::gic::create_gic;
|
use arch::aarch64::gic::kvm::create_gic;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_gic() {
|
fn test_create_gic() {
|
||||||
|
@ -1493,7 +1493,7 @@ mod tests {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use arch::aarch64::fdt::create_fdt;
|
use arch::aarch64::fdt::create_fdt;
|
||||||
use arch::aarch64::gic::create_gic;
|
use arch::aarch64::gic::kvm::create_gic;
|
||||||
use arch::aarch64::{layout, DeviceInfoForFDT};
|
use arch::aarch64::{layout, DeviceInfoForFDT};
|
||||||
use arch::DeviceType;
|
use arch::DeviceType;
|
||||||
use vm_memory::{GuestAddress, GuestMemoryMmap};
|
use vm_memory::{GuestAddress, GuestMemoryMmap};
|
||||||
|
Loading…
Reference in New Issue
Block a user