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 <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Zhuocheng Ding <zhuocheng.ding@intel.corp-partner.google.com>
This commit is contained in:
Zhuocheng Ding 2019-12-05 13:25:40 +08:00 committed by Commit Bot
parent eaff194759
commit 1918627791

View file

@ -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);