mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-01 05:04:26 +00:00
dragonball: support pmu on aarch64
This commit adds support for pmu virtualization on aarch64. The initialization of pmu is in the following order: 1. Receive pmu parameter(vpmu_feature) from runtime-rs to determine the VpmuFeatureLevel. 2. Judge whether to initialize pmu devices and add pmu device node into fdt on aarch64, according to VpmuFeatureLevel. Fixes: #6168 Signed-off-by: xuejun-xj <jiyunxue@linux.alibaba.com>
This commit is contained in:
parent
df35f8f885
commit
760f78137d
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
//! Error codes for the virtual machine monitor subsystem.
|
//! Error codes for the virtual machine monitor subsystem.
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use dbs_arch::pmu::PmuError;
|
||||||
#[cfg(feature = "dbs-virtio-devices")]
|
#[cfg(feature = "dbs-virtio-devices")]
|
||||||
use dbs_virtio_devices::Error as VirtIoError;
|
use dbs_virtio_devices::Error as VirtIoError;
|
||||||
|
|
||||||
@ -61,6 +63,11 @@ pub enum Error {
|
|||||||
#[error("failed to write MP table to guest memory: {0}")]
|
#[error("failed to write MP table to guest memory: {0}")]
|
||||||
MpTableSetup(#[source] dbs_boot::mptable::Error),
|
MpTableSetup(#[source] dbs_boot::mptable::Error),
|
||||||
|
|
||||||
|
/// Create pmu device error
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
#[error("Create pmu device error: {0}")]
|
||||||
|
PmuDeviceError(#[source] PmuError),
|
||||||
|
|
||||||
/// Fail to boot system
|
/// Fail to boot system
|
||||||
#[error("failed to boot system: {0}")]
|
#[error("failed to boot system: {0}")]
|
||||||
BootSystem(#[source] dbs_boot::Error),
|
BootSystem(#[source] dbs_boot::Error),
|
||||||
|
@ -11,7 +11,7 @@ use std::sync::mpsc::{channel, Sender};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::IoManagerCached;
|
use crate::IoManagerCached;
|
||||||
use dbs_arch::regs;
|
use dbs_arch::{regs, VpmuFeatureLevel};
|
||||||
use dbs_boot::get_fdt_addr;
|
use dbs_boot::get_fdt_addr;
|
||||||
use dbs_utils::time::TimestampUs;
|
use dbs_utils::time::TimestampUs;
|
||||||
use kvm_ioctls::{VcpuFd, VmFd};
|
use kvm_ioctls::{VcpuFd, VmFd};
|
||||||
@ -81,7 +81,7 @@ impl Vcpu {
|
|||||||
/// * `_pgtable_addr` - pgtable address for ap vcpu (not used in aarch64)
|
/// * `_pgtable_addr` - pgtable address for ap vcpu (not used in aarch64)
|
||||||
pub fn configure(
|
pub fn configure(
|
||||||
&mut self,
|
&mut self,
|
||||||
_vcpu_config: &VcpuConfig,
|
vcpu_config: &VcpuConfig,
|
||||||
vm_fd: &VmFd,
|
vm_fd: &VmFd,
|
||||||
vm_as: &GuestAddressSpaceImpl,
|
vm_as: &GuestAddressSpaceImpl,
|
||||||
kernel_load_addr: Option<GuestAddress>,
|
kernel_load_addr: Option<GuestAddress>,
|
||||||
@ -99,6 +99,9 @@ impl Vcpu {
|
|||||||
if self.id > 0 {
|
if self.id > 0 {
|
||||||
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_POWER_OFF;
|
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_POWER_OFF;
|
||||||
}
|
}
|
||||||
|
if vcpu_config.vpmu_feature == VpmuFeatureLevel::FullyEnabled {
|
||||||
|
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_PMU_V3;
|
||||||
|
}
|
||||||
|
|
||||||
self.fd.vcpu_init(&kvi).map_err(VcpuError::VcpuArmInit)?;
|
self.fd.vcpu_init(&kvi).map_err(VcpuError::VcpuArmInit)?;
|
||||||
|
|
||||||
|
@ -7,9 +7,7 @@ mod sm;
|
|||||||
mod vcpu_impl;
|
mod vcpu_impl;
|
||||||
mod vcpu_manager;
|
mod vcpu_manager;
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
use dbs_arch::VpmuFeatureLevel;
|
||||||
use dbs_arch::cpuid::VpmuFeatureLevel;
|
|
||||||
|
|
||||||
pub use vcpu_manager::{VcpuManager, VcpuManagerError, VcpuResizeInfo};
|
pub use vcpu_manager::{VcpuManager, VcpuManagerError, VcpuResizeInfo};
|
||||||
|
|
||||||
#[cfg(feature = "hotplug")]
|
#[cfg(feature = "hotplug")]
|
||||||
@ -32,6 +30,6 @@ pub struct VcpuConfig {
|
|||||||
/// if vpmu feature is Disabled, it means vpmu feature is off (by default)
|
/// if vpmu feature is Disabled, it means vpmu feature is off (by default)
|
||||||
/// if vpmu feature is LimitedlyEnabled, it means minimal vpmu counters are supported (cycles and instructions)
|
/// if vpmu feature is LimitedlyEnabled, it means minimal vpmu counters are supported (cycles and instructions)
|
||||||
/// if vpmu feature is FullyEnabled, it means all vpmu counters are supported
|
/// if vpmu feature is FullyEnabled, it means all vpmu counters are supported
|
||||||
#[cfg(target_arch = "x86_64")]
|
/// For aarch64, VpmuFeatureLevel only supports Disabled and FullyEnabled.
|
||||||
pub vpmu_feature: VpmuFeatureLevel,
|
pub vpmu_feature: VpmuFeatureLevel,
|
||||||
}
|
}
|
||||||
|
@ -760,6 +760,11 @@ impl Vcpu {
|
|||||||
// State machine reached its end.
|
// State machine reached its end.
|
||||||
StateMachine::finish(Self::exited)
|
StateMachine::finish(Self::exited)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get vcpu file descriptor.
|
||||||
|
pub fn vcpu_fd(&self) -> &VcpuFd {
|
||||||
|
self.fd.as_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Vcpu {
|
impl Drop for Vcpu {
|
||||||
|
@ -15,6 +15,7 @@ use std::sync::mpsc::{channel, Receiver, RecvError, RecvTimeoutError, Sender};
|
|||||||
use std::sync::{Arc, Barrier, Mutex, RwLock};
|
use std::sync::{Arc, Barrier, Mutex, RwLock};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use dbs_arch::VpmuFeatureLevel;
|
||||||
#[cfg(all(feature = "hotplug", feature = "dbs-upcall"))]
|
#[cfg(all(feature = "hotplug", feature = "dbs-upcall"))]
|
||||||
use dbs_upcall::{DevMgrService, UpcallClient};
|
use dbs_upcall::{DevMgrService, UpcallClient};
|
||||||
use dbs_utils::epoll_manager::{EpollManager, EventOps, EventSet, Events, MutEventSubscriber};
|
use dbs_utils::epoll_manager::{EpollManager, EventOps, EventSet, Events, MutEventSubscriber};
|
||||||
@ -281,11 +282,20 @@ impl VcpuManager {
|
|||||||
let supported_cpuid = kvm_context
|
let supported_cpuid = kvm_context
|
||||||
.supported_cpuid(kvm_bindings::KVM_MAX_CPUID_ENTRIES)
|
.supported_cpuid(kvm_bindings::KVM_MAX_CPUID_ENTRIES)
|
||||||
.map_err(VcpuManagerError::Kvm)?;
|
.map_err(VcpuManagerError::Kvm)?;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||||
let vpmu_feature_level = match vm_config_info.vpmu_feature {
|
let vpmu_feature_level = match vm_config_info.vpmu_feature {
|
||||||
1 => dbs_arch::cpuid::VpmuFeatureLevel::LimitedlyEnabled,
|
#[cfg(target_arch = "x86_64")]
|
||||||
2 => dbs_arch::cpuid::VpmuFeatureLevel::FullyEnabled,
|
1 => VpmuFeatureLevel::LimitedlyEnabled,
|
||||||
_ => dbs_arch::cpuid::VpmuFeatureLevel::Disabled,
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
1 => {
|
||||||
|
log::warn!(
|
||||||
|
"Limitedly enabled vpmu feature isn't supported on aarch64 for now.\
|
||||||
|
This will be supported in the future. The vpmu_feature will be set disabled!"
|
||||||
|
);
|
||||||
|
VpmuFeatureLevel::Disabled
|
||||||
|
}
|
||||||
|
2 => VpmuFeatureLevel::FullyEnabled,
|
||||||
|
_ => VpmuFeatureLevel::Disabled,
|
||||||
};
|
};
|
||||||
|
|
||||||
let vcpu_manager = Arc::new(Mutex::new(VcpuManager {
|
let vcpu_manager = Arc::new(Mutex::new(VcpuManager {
|
||||||
@ -297,7 +307,6 @@ impl VcpuManager {
|
|||||||
cores_per_die: vm_config_info.cpu_topology.cores_per_die,
|
cores_per_die: vm_config_info.cpu_topology.cores_per_die,
|
||||||
dies_per_socket: vm_config_info.cpu_topology.dies_per_socket,
|
dies_per_socket: vm_config_info.cpu_topology.dies_per_socket,
|
||||||
sockets: vm_config_info.cpu_topology.sockets,
|
sockets: vm_config_info.cpu_topology.sockets,
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
vpmu_feature: vpmu_feature_level,
|
vpmu_feature: vpmu_feature_level,
|
||||||
},
|
},
|
||||||
vcpu_seccomp_filter,
|
vcpu_seccomp_filter,
|
||||||
@ -799,6 +808,11 @@ impl VcpuManager {
|
|||||||
)
|
)
|
||||||
.map_err(VcpuManagerError::Vcpu)
|
.map_err(VcpuManagerError::Vcpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get vpmu_feature config
|
||||||
|
pub fn vpmu_feature(&self) -> VpmuFeatureLevel {
|
||||||
|
self.vcpu_config.vpmu_feature
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "hotplug")]
|
#[cfg(feature = "hotplug")]
|
||||||
|
@ -11,6 +11,7 @@ use std::fmt::Debug;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use dbs_arch::gic::GICDevice;
|
use dbs_arch::gic::GICDevice;
|
||||||
|
use dbs_arch::pmu::initialize_pmu;
|
||||||
use dbs_arch::{DeviceInfoForFDT, DeviceType, VpmuFeatureLevel};
|
use dbs_arch::{DeviceInfoForFDT, DeviceType, VpmuFeatureLevel};
|
||||||
use dbs_boot::InitrdConfig;
|
use dbs_boot::InitrdConfig;
|
||||||
use dbs_utils::epoll_manager::EpollManager;
|
use dbs_utils::epoll_manager::EpollManager;
|
||||||
@ -43,6 +44,7 @@ fn configure_system<T: DeviceInfoForFDT + Clone + Debug, M: GuestMemory>(
|
|||||||
device_info: Option<&HashMap<(DeviceType, String), T>>,
|
device_info: Option<&HashMap<(DeviceType, String), T>>,
|
||||||
gic_device: &Box<dyn GICDevice>,
|
gic_device: &Box<dyn GICDevice>,
|
||||||
initrd: &Option<super::InitrdConfig>,
|
initrd: &Option<super::InitrdConfig>,
|
||||||
|
vpmu_feature: &VpmuFeatureLevel,
|
||||||
) -> super::Result<()> {
|
) -> super::Result<()> {
|
||||||
dbs_boot::fdt::create_fdt(
|
dbs_boot::fdt::create_fdt(
|
||||||
guest_mem,
|
guest_mem,
|
||||||
@ -51,8 +53,7 @@ fn configure_system<T: DeviceInfoForFDT + Clone + Debug, M: GuestMemory>(
|
|||||||
device_info,
|
device_info,
|
||||||
gic_device,
|
gic_device,
|
||||||
initrd,
|
initrd,
|
||||||
// We will add vpmu feature support in the future PRs. issue: #6168
|
vpmu_feature,
|
||||||
&VpmuFeatureLevel::Disabled,
|
|
||||||
)
|
)
|
||||||
.map_err(Error::BootSystem)?;
|
.map_err(Error::BootSystem)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -78,6 +79,23 @@ impl Vm {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Setup pmu devices for guest vm.
|
||||||
|
pub fn setup_pmu_devices(&mut self) -> std::result::Result<(), StartMicroVmError> {
|
||||||
|
let vm = self.vm_fd();
|
||||||
|
let mut vcpu_manager = self.vcpu_manager().map_err(StartMicroVmError::Vcpu)?;
|
||||||
|
let vpmu_feature = vcpu_manager.vpmu_feature();
|
||||||
|
if vpmu_feature == VpmuFeatureLevel::Disabled {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
for vcpu in vcpu_manager.vcpus_mut() {
|
||||||
|
initialize_pmu(vm, vcpu.vcpu_fd())
|
||||||
|
.map_err(|e| StartMicroVmError::ConfigureVm(VmError::SetupPmu(e)))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Initialize the virtual machine instance.
|
/// Initialize the virtual machine instance.
|
||||||
///
|
///
|
||||||
/// It initialize the virtual machine instance by:
|
/// It initialize the virtual machine instance by:
|
||||||
@ -115,6 +133,7 @@ impl Vm {
|
|||||||
.create_boot_vcpus(request_ts, kernel_loader_result.kernel_load)
|
.create_boot_vcpus(request_ts, kernel_loader_result.kernel_load)
|
||||||
.map_err(StartMicroVmError::Vcpu)?;
|
.map_err(StartMicroVmError::Vcpu)?;
|
||||||
self.setup_interrupt_controller()?;
|
self.setup_interrupt_controller()?;
|
||||||
|
self.setup_pmu_devices()?;
|
||||||
self.init_devices(epoll_mgr)?;
|
self.init_devices(epoll_mgr)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -131,6 +150,7 @@ impl Vm {
|
|||||||
initrd: Option<InitrdConfig>,
|
initrd: Option<InitrdConfig>,
|
||||||
) -> std::result::Result<(), StartMicroVmError> {
|
) -> std::result::Result<(), StartMicroVmError> {
|
||||||
let vcpu_manager = self.vcpu_manager().map_err(StartMicroVmError::Vcpu)?;
|
let vcpu_manager = self.vcpu_manager().map_err(StartMicroVmError::Vcpu)?;
|
||||||
|
let vpmu_feature = vcpu_manager.vpmu_feature();
|
||||||
let vcpu_mpidr = vcpu_manager
|
let vcpu_mpidr = vcpu_manager
|
||||||
.vcpus()
|
.vcpus()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -145,6 +165,7 @@ impl Vm {
|
|||||||
self.device_manager.get_mmio_device_info(),
|
self.device_manager.get_mmio_device_info(),
|
||||||
self.get_irqchip(),
|
self.get_irqchip(),
|
||||||
&initrd,
|
&initrd,
|
||||||
|
&vpmu_feature,
|
||||||
)
|
)
|
||||||
.map_err(StartMicroVmError::ConfigureSystem)
|
.map_err(StartMicroVmError::ConfigureSystem)
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ use std::sync::{Arc, Mutex, RwLock};
|
|||||||
use dbs_address_space::AddressSpace;
|
use dbs_address_space::AddressSpace;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use dbs_arch::gic::GICDevice;
|
use dbs_arch::gic::GICDevice;
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use dbs_arch::pmu::PmuError;
|
||||||
use dbs_boot::InitrdConfig;
|
use dbs_boot::InitrdConfig;
|
||||||
use dbs_utils::epoll_manager::EpollManager;
|
use dbs_utils::epoll_manager::EpollManager;
|
||||||
use dbs_utils::time::TimestampUs;
|
use dbs_utils::time::TimestampUs;
|
||||||
@ -69,6 +71,11 @@ pub enum VmError {
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
#[error("failed to configure GIC")]
|
#[error("failed to configure GIC")]
|
||||||
SetupGIC(GICError),
|
SetupGIC(GICError),
|
||||||
|
|
||||||
|
/// Cannot setup pmu device
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
#[error("failed to setup pmu device")]
|
||||||
|
SetupPmu(#[source] PmuError),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration information for user defined NUMA nodes.
|
/// Configuration information for user defined NUMA nodes.
|
||||||
|
Loading…
Reference in New Issue
Block a user