vmm: cpu: Set CPU physical bits based on user input

If the user specified a maximum physical bits value through the
`max_phys_bits` option from `--cpus` parameter, the guest CPUID
will be patched accordingly to ensure the guest will find the
right amount of physical bits.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2020-10-13 10:22:44 +02:00
parent aec88e20d7
commit 1b9890b807
4 changed files with 25 additions and 4 deletions

View File

@ -63,6 +63,7 @@ pub fn configure_vcpu(
id: u8,
kernel_entry_point: Option<EntryPoint>,
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
_phys_bits: u8,
) -> super::Result<u64> {
if let Some(kernel_entry_point) = kernel_entry_point {
regs::setup_regs(

View File

@ -337,6 +337,7 @@ pub fn configure_vcpu(
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
cpuid: CpuId,
kvm_hyperv: bool,
phys_bits: u8,
) -> super::Result<()> {
let mut cpuid = cpuid;
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
@ -410,6 +411,13 @@ pub fn configure_vcpu(
.map_err(|_| Error::PopulatingCpuid)?;
}
// Set CPU physical bits
for entry in cpuid.as_mut_slice().iter_mut() {
if entry.function == 0x8000_0008 {
entry.eax = (entry.eax & 0xffff_ff00) | (phys_bits as u32 & 0xff);
}
}
fd.set_cpuid2(&cpuid)
.map_err(|e| Error::SetSupportedCpusFailed(e.into()))?;

View File

@ -17,6 +17,7 @@ use crate::config::CpusConfig;
use crate::device_manager::DeviceManager;
use crate::memory_manager::MemoryManager;
use crate::seccomp_filters::{get_seccomp_filter, Thread};
use crate::vm::physical_bits;
use crate::CPU_MANAGER_SNAPSHOT_ID;
#[cfg(feature = "acpi")]
use acpi_tables::{aml, aml::Aml, sdt::SDT};
@ -259,12 +260,19 @@ impl Vcpu {
vm_memory: &GuestMemoryAtomic<GuestMemoryMmap>,
#[cfg(target_arch = "x86_64")] cpuid: CpuId,
#[cfg(target_arch = "x86_64")] kvm_hyperv: bool,
phys_bits: u8,
) -> Result<()> {
#[cfg(target_arch = "aarch64")]
{
self.init(vm)?;
self.mpidr = arch::configure_vcpu(&self.vcpu, self.id, kernel_entry_point, vm_memory)
.map_err(Error::VcpuConfiguration)?;
self.mpidr = arch::configure_vcpu(
&self.vcpu,
self.id,
kernel_entry_point,
vm_memory,
phys_bits,
)
.map_err(Error::VcpuConfiguration)?;
}
#[cfg(target_arch = "x86_64")]
@ -275,6 +283,7 @@ impl Vcpu {
vm_memory,
cpuid,
kvm_hyperv,
phys_bits,
)
.map_err(Error::VcpuConfiguration)?;
@ -703,6 +712,8 @@ impl CpuManager {
} else {
let vm_memory = self.vm_memory.clone();
let phys_bits = physical_bits(self.config.max_phys_bits);
#[cfg(target_arch = "x86_64")]
vcpu.lock()
.unwrap()
@ -711,13 +722,14 @@ impl CpuManager {
&vm_memory,
self.cpuid.clone(),
self.config.kvm_hyperv,
phys_bits,
)
.expect("Failed to configure vCPU");
#[cfg(target_arch = "aarch64")]
vcpu.lock()
.unwrap()
.configure(&self.vm, entry_point, &vm_memory)
.configure(&self.vm, entry_point, &vm_memory, phys_bits)
.expect("Failed to configure vCPU");
}

View File

@ -433,7 +433,7 @@ impl VmmOps for VmOps {
}
}
fn physical_bits(max_phys_bits: Option<u8>) -> u8 {
pub fn physical_bits(max_phys_bits: Option<u8>) -> u8 {
let host_phys_bits = get_host_cpu_phys_bits();
cmp::min(host_phys_bits, max_phys_bits.unwrap_or(host_phys_bits))
}