mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 02:55:45 +00:00
vmm, arch: Enable KVM HyperV support
Inject CPUID leaves for advertising KVM HyperV support when the "kvm_hyperv" toggle is enabled. Currently we only enable a selection of features required to boot. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
da642fcf7f
commit
27c28fa3b0
@ -174,6 +174,9 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Missing SGX_LC CPU feature
|
/// Missing SGX_LC CPU feature
|
||||||
MissingSgxLaunchControlFeature,
|
MissingSgxLaunchControlFeature,
|
||||||
|
|
||||||
|
// Error populating Cpuid
|
||||||
|
PopulatingCpuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Error> for super::Error {
|
impl From<Error> for super::Error {
|
||||||
@ -333,13 +336,71 @@ pub fn configure_vcpu(
|
|||||||
kernel_entry_point: Option<EntryPoint>,
|
kernel_entry_point: Option<EntryPoint>,
|
||||||
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
cpuid: CpuId,
|
cpuid: CpuId,
|
||||||
|
kvm_hyperv: bool,
|
||||||
) -> super::Result<()> {
|
) -> super::Result<()> {
|
||||||
let mut cpuid = cpuid;
|
let mut cpuid = cpuid;
|
||||||
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
|
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
|
||||||
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, u32::from(id));
|
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, u32::from(id));
|
||||||
|
|
||||||
|
if kvm_hyperv {
|
||||||
|
// Remove conflicting entries
|
||||||
|
cpuid.retain(|c| c.function != 0x4000_0000);
|
||||||
|
cpuid.retain(|c| c.function != 0x4000_0001);
|
||||||
|
|
||||||
|
// See "Hypervisor Top Level Functional Specification" for details
|
||||||
|
// Compliance with "Hv#1" requires leaves up to 0x4000_000a
|
||||||
|
cpuid
|
||||||
|
.push(CpuIdEntry {
|
||||||
|
function: 0x40000000,
|
||||||
|
eax: 0x4000000a, // Maximum cpuid leaf
|
||||||
|
ebx: 0x756e694c, // "Linu"
|
||||||
|
ecx: 0x564b2078, // "x KV"
|
||||||
|
edx: 0x7648204d, // "M Hv"
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.map_err(|_| Error::PopulatingCpuid)?;
|
||||||
|
cpuid
|
||||||
|
.push(CpuIdEntry {
|
||||||
|
function: 0x40000001,
|
||||||
|
eax: 0x31237648, // "Hv#1"
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.map_err(|_| Error::PopulatingCpuid)?;
|
||||||
|
cpuid
|
||||||
|
.push(CpuIdEntry {
|
||||||
|
function: 0x40000002,
|
||||||
|
eax: 0x3839, // "Build number"
|
||||||
|
ebx: 0xa0000, // "Version"
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.map_err(|_| Error::PopulatingCpuid)?;
|
||||||
|
cpuid
|
||||||
|
.push(CpuIdEntry {
|
||||||
|
function: 0x4000_0003,
|
||||||
|
eax: 1 << 1 // AccessPartitionReferenceCounter
|
||||||
|
| 1 << 2 // AccessSynicRegs
|
||||||
|
| 1 << 3 // AccessSyntheticTimerRegs
|
||||||
|
| 1 << 9, // AccessPartitionReferenceTsc
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.map_err(|_| Error::PopulatingCpuid)?;
|
||||||
|
for i in 0x4000_0004..=0x4000_000a {
|
||||||
|
cpuid
|
||||||
|
.push(CpuIdEntry {
|
||||||
|
function: i,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.map_err(|_| Error::PopulatingCpuid)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fd.set_cpuid2(&cpuid)
|
fd.set_cpuid2(&cpuid)
|
||||||
.map_err(|e| Error::SetSupportedCpusFailed(e.into()))?;
|
.map_err(|e| Error::SetSupportedCpusFailed(e.into()))?;
|
||||||
|
|
||||||
|
if kvm_hyperv {
|
||||||
|
fd.enable_hyperv_synic().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
regs::setup_msrs(fd).map_err(Error::MSRSConfiguration)?;
|
regs::setup_msrs(fd).map_err(Error::MSRSConfiguration)?;
|
||||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||||
// Safe to unwrap because this method is called after the VM is configured
|
// Safe to unwrap because this method is called after the VM is configured
|
||||||
|
@ -299,6 +299,7 @@ impl Vcpu {
|
|||||||
kernel_entry_point: Option<EntryPoint>,
|
kernel_entry_point: Option<EntryPoint>,
|
||||||
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
|
||||||
#[cfg(target_arch = "x86_64")] cpuid: CpuId,
|
#[cfg(target_arch = "x86_64")] cpuid: CpuId,
|
||||||
|
#[cfg(target_arch = "x86_64")] kvm_hyperv: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
{
|
{
|
||||||
@ -308,8 +309,15 @@ impl Vcpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
arch::configure_vcpu(&self.vcpu, self.id, kernel_entry_point, vm_memory, cpuid)
|
arch::configure_vcpu(
|
||||||
.map_err(Error::VcpuConfiguration)?;
|
&self.vcpu,
|
||||||
|
self.id,
|
||||||
|
kernel_entry_point,
|
||||||
|
vm_memory,
|
||||||
|
cpuid,
|
||||||
|
kvm_hyperv,
|
||||||
|
)
|
||||||
|
.map_err(Error::VcpuConfiguration)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -770,7 +778,12 @@ impl CpuManager {
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
vcpu.lock()
|
vcpu.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.configure(entry_point, &vm_memory, self.cpuid.clone())
|
.configure(
|
||||||
|
entry_point,
|
||||||
|
&vm_memory,
|
||||||
|
self.cpuid.clone(),
|
||||||
|
self.config.kvm_hyperv,
|
||||||
|
)
|
||||||
.expect("Failed to configure vCPU");
|
.expect("Failed to configure vCPU");
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
Loading…
Reference in New Issue
Block a user