From 1918627791363aca96c89b0df831813a5c7fc50e Mon Sep 17 00:00:00 2001 From: Zhuocheng Ding Date: Thu, 5 Dec 2019 13:25:40 +0800 Subject: [PATCH] x86_64: add tsc_deadline_timer support Support TSC deadline mode of LAPIC timer, this can potentially increase the precision of guest timer. BUG=None TEST=launch linux guest and run `lscpu`, tsc_deadline_timer is present in the output. Change-Id: I7adc87827a51ba8d1866ebee201759f2769ba664 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1951429 Reviewed-by: Daniel Verkamp Tested-by: kokoro Commit-Queue: Zhuocheng Ding --- x86_64/src/cpuid.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/x86_64/src/cpuid.rs b/x86_64/src/cpuid.rs index 5710120995..a42b6622da 100644 --- a/x86_64/src/cpuid.rs +++ b/x86_64/src/cpuid.rs @@ -47,10 +47,16 @@ const EBX_CLFLUSH_SIZE_SHIFT: u32 = 8; // Bytes flushed when executing CLFLUSH. const EBX_CPU_COUNT_SHIFT: u32 = 16; // Index of this CPU. const EBX_CPUID_SHIFT: u32 = 24; // Index of this CPU. const ECX_EPB_SHIFT: u32 = 3; // "Energy Performance Bias" bit. +const ECX_TSC_DEADLINE_TIMER_SHIFT: u32 = 24; // TSC deadline mode of APIC timer const ECX_HYPERVISOR_SHIFT: u32 = 31; // Flag to be set when the cpu is running on a hypervisor. const EDX_HTT_SHIFT: u32 = 28; // Hyper Threading Enabled. -fn filter_cpuid(cpu_id: u64, cpu_count: u64, kvm_cpuid: &mut kvm::CpuId) -> Result<()> { +fn filter_cpuid( + cpu_id: u64, + cpu_count: u64, + kvm_cpuid: &mut kvm::CpuId, + kvm: &kvm::Kvm, +) -> Result<()> { let entries = kvm_cpuid.mut_entries_slice(); for entry in entries { @@ -60,6 +66,9 @@ fn filter_cpuid(cpu_id: u64, cpu_count: u64, kvm_cpuid: &mut kvm::CpuId) -> Resu if entry.index == 0 { entry.ecx |= 1 << ECX_HYPERVISOR_SHIFT; } + if kvm.check_extension(kvm::Cap::TscDeadlineTimer) { + entry.ecx |= 1 << ECX_TSC_DEADLINE_TIMER_SHIFT; + } entry.ebx = (cpu_id << EBX_CPUID_SHIFT) as u32 | (EBX_CLFLUSH_CACHELINE << EBX_CLFLUSH_SIZE_SHIFT); if cpu_count > 1 { @@ -115,7 +124,7 @@ pub fn setup_cpuid(kvm: &kvm::Kvm, vcpu: &kvm::Vcpu, cpu_id: u64, nrcpus: u64) - .get_supported_cpuid() .map_err(Error::GetSupportedCpusFailed)?; - filter_cpuid(cpu_id, nrcpus, &mut kvm_cpuid)?; + filter_cpuid(cpu_id, nrcpus, &mut kvm_cpuid, kvm)?; vcpu.set_cpuid2(&kvm_cpuid) .map_err(Error::SetSupportedCpusFailed) @@ -163,13 +172,14 @@ mod tests { #[test] fn feature_and_vendor_name() { let mut cpuid = kvm::CpuId::new(2); + let kvm = kvm::Kvm::new().unwrap(); let entries = cpuid.mut_entries_slice(); entries[0].function = 0; entries[1].function = 1; entries[1].ecx = 0x10; entries[1].edx = 0; - assert_eq!(Ok(()), filter_cpuid(1, 2, &mut cpuid)); + assert_eq!(Ok(()), filter_cpuid(1, 2, &mut cpuid, &kvm)); let entries = cpuid.mut_entries_slice(); assert_eq!(entries[0].function, 0);