summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--x86_64/src/cpuid.rs16
1 files changed, 13 insertions, 3 deletions
diff --git a/x86_64/src/cpuid.rs b/x86_64/src/cpuid.rs
index 5710120..a42b662 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);