mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-01 17:35:19 +00:00
vmm: Enable VCPU for AArch64
Added MPIDR which is needed in system configuration. Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
parent
b5f1c912d6
commit
917219fa92
@ -13,6 +13,8 @@ pub mod layout;
|
||||
/// Logic for configuring aarch64 registers.
|
||||
pub mod regs;
|
||||
|
||||
pub use self::fdt::DeviceInfoForFDT;
|
||||
use crate::DeviceType;
|
||||
use crate::RegionType;
|
||||
use aarch64::gic::GICDevice;
|
||||
use kvm_ioctls::*;
|
||||
@ -20,9 +22,35 @@ use std::collections::HashMap;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt::Debug;
|
||||
use vm_memory::{
|
||||
Address, GuestAddress, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap, GuestUsize,
|
||||
Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, GuestMemoryMmap,
|
||||
GuestUsize,
|
||||
};
|
||||
|
||||
/// Errors thrown while configuring aarch64 system.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Failed to create a Flattened Device Tree for this aarch64 VM.
|
||||
SetupFDT(fdt::Error),
|
||||
|
||||
/// Failed to compute the initrd address.
|
||||
InitrdAddress,
|
||||
|
||||
/// Error configuring the general purpose registers
|
||||
REGSConfiguration(regs::Error),
|
||||
|
||||
/// Error fetching prefered target
|
||||
VcpuArmPreferredTarget(kvm_ioctls::Error),
|
||||
|
||||
/// Error doing Vcpu Init on Arm.
|
||||
VcpuArmInit(kvm_ioctls::Error),
|
||||
}
|
||||
|
||||
impl From<Error> for super::Error {
|
||||
fn from(e: Error) -> super::Error {
|
||||
super::Error::AArch64Setup(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
/// Specifies the entry point address where the guest must start
|
||||
/// executing code.
|
||||
@ -31,32 +59,41 @@ pub struct EntryPoint {
|
||||
pub entry_addr: GuestAddress,
|
||||
}
|
||||
|
||||
/// Configure the specified VCPU, and return its MPIDR.
|
||||
pub fn configure_vcpu(
|
||||
_fd: &VcpuFd,
|
||||
_id: u8,
|
||||
_kernel_entry_point: Option<EntryPoint>,
|
||||
_vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
) -> super::Result<()> {
|
||||
unimplemented!();
|
||||
}
|
||||
fd: &VcpuFd,
|
||||
id: u8,
|
||||
vm_fd: &VmFd,
|
||||
kernel_entry_point: Option<EntryPoint>,
|
||||
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
) -> super::Result<u64> {
|
||||
let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default();
|
||||
|
||||
/// Errors thrown while configuring aarch64 system.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Failed to create a Flattened Device Tree for this aarch64 VM.
|
||||
SetupFDT(fdt::Error),
|
||||
/// Failed to compute the initrd address.
|
||||
InitrdAddress,
|
||||
}
|
||||
|
||||
impl From<Error> for super::Error {
|
||||
fn from(e: Error) -> super::Error {
|
||||
super::Error::AArch64Setup(e)
|
||||
// This reads back the kernel's preferred target type.
|
||||
vm_fd
|
||||
.get_preferred_target(&mut kvi)
|
||||
.map_err(Error::VcpuArmPreferredTarget)?;
|
||||
// We already checked that the capability is supported.
|
||||
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_PSCI_0_2;
|
||||
// Non-boot cpus are powered off initially.
|
||||
if id > 0 {
|
||||
kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_POWER_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
pub use self::fdt::DeviceInfoForFDT;
|
||||
use crate::DeviceType;
|
||||
fd.vcpu_init(&kvi).map_err(Error::VcpuArmInit)?;
|
||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||
regs::setup_regs(
|
||||
fd,
|
||||
id,
|
||||
kernel_entry_point.entry_addr.raw_value(),
|
||||
&vm_memory.memory(),
|
||||
)
|
||||
.map_err(Error::REGSConfiguration)?;
|
||||
}
|
||||
|
||||
let mpidr = regs::read_mpidr(fd).map_err(Error::REGSConfiguration)?;
|
||||
Ok(mpidr)
|
||||
}
|
||||
|
||||
pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, RegionType)> {
|
||||
let mut regions = Vec::new();
|
||||
|
@ -239,6 +239,8 @@ pub struct Vcpu {
|
||||
interrupt_controller: Option<Arc<Mutex<dyn InterruptController>>>,
|
||||
#[cfg_attr(target_arch = "aarch64", allow(dead_code))]
|
||||
vm_ts: std::time::Instant,
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
mpidr: u64,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@ -284,6 +286,8 @@ impl Vcpu {
|
||||
mmio_bus,
|
||||
interrupt_controller,
|
||||
vm_ts: creation_ts,
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
mpidr: 0,
|
||||
})))
|
||||
}
|
||||
|
||||
@ -296,14 +300,18 @@ impl Vcpu {
|
||||
/// * `vm_memory` - Guest memory.
|
||||
/// * `cpuid` - (x86_64) CpuId, wrapper over the `kvm_cpuid2` structure.
|
||||
pub fn configure(
|
||||
&self,
|
||||
&mut self,
|
||||
#[cfg(target_arch = "aarch64")] vm_fd: &VmFd,
|
||||
kernel_entry_point: Option<EntryPoint>,
|
||||
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
#[cfg(target_arch = "x86_64")] cpuid: CpuId,
|
||||
) -> Result<()> {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
arch::configure_vcpu(&self.fd, self.id, kernel_entry_point, vm_memory)
|
||||
.map_err(Error::VcpuConfiguration)?;
|
||||
{
|
||||
self.mpidr =
|
||||
arch::configure_vcpu(&self.fd, self.id, vm_fd, kernel_entry_point, vm_memory)
|
||||
.map_err(Error::VcpuConfiguration)?;
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
arch::configure_vcpu(&self.fd, self.id, kernel_entry_point, vm_memory, cpuid)
|
||||
@ -312,6 +320,12 @@ impl Vcpu {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the MPIDR register value.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub fn get_mpidr(&self) -> u64 {
|
||||
self.mpidr
|
||||
}
|
||||
|
||||
/// Runs the VCPU until it exits, returning the reason.
|
||||
///
|
||||
/// Note that the state of the VCPU and associated VM must be setup first for this to do
|
||||
@ -784,7 +798,7 @@ impl CpuManager {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
vcpu.lock()
|
||||
.unwrap()
|
||||
.configure(entry_point, &vm_memory)
|
||||
.configure(&self.fd, entry_point, &vm_memory)
|
||||
.expect("Failed to configure vCPU");
|
||||
}
|
||||
|
||||
@ -985,6 +999,16 @@ impl CpuManager {
|
||||
.fold(0, |acc, state| acc + state.active() as u8)
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub fn get_mpidr(&self) -> Vec<u64> {
|
||||
let vcpu_mpidr = self
|
||||
.vcpus
|
||||
.iter()
|
||||
.map(|cpu| cpu.lock().unwrap().get_mpidr())
|
||||
.collect();
|
||||
vcpu_mpidr
|
||||
}
|
||||
|
||||
#[cfg(feature = "acpi")]
|
||||
pub fn create_madt(&self) -> SDT {
|
||||
// This is also checked in the commandline parsing.
|
||||
|
Loading…
x
Reference in New Issue
Block a user