All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: Phil Dennis-Jordan <phil@philjordan.eu>
Subject: [Qemu-devel] [PULL 18/41] x86-KVM: Supply TSC and APIC clock rates to guest like VMWare
Date: Fri, 27 Jan 2017 14:45:26 +0100	[thread overview]
Message-ID: <1485524749-118532-19-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1485524749-118532-1-git-send-email-pbonzini@redhat.com>

From: Phil Dennis-Jordan <phil@philjordan.eu>

This fixes timekeeping of x86-64 Darwin/OS X/macOS guests when using KVM.

Darwin/OS X/macOS for x86-64 uses the TSC for timekeeping; it normally calibrates this by querying various clock frequency scaling MSRs. Details depend on the exact CPU model detected. The local APIC timer frequency is extracted from (EFI) firmware.

This is problematic in the presence of virtualisation, as the MSRs in question are typically not handled by the hypervisor. VMWare (Fusion) advertises TSC and APIC frequency via a custom 0x40000010 CPUID leaf, in the eax and ebx registers respectively. This is documented at https://lwn.net/Articles/301888/ among other places.

Darwin/OS X/macOS looks for the generic 0x40000000 hypervisor leaf, and if this indicates via eax that leaf 0x40000010 might be available, that is in turn queried for the two frequencies.

This adds a CPU option "vmware-cpuid-freq" to enable the same behaviour when running Qemu with KVM acceleration, if the KVM TSC frequency can be determined, and it is stable. (invtsc or user-specified) The virtualised APIC bus cycle is hardcoded to 1GHz in KVM, so ebx of the CPUID leaf is also hardcoded to this value.

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Message-Id: <1484921496-11257-2-git-send-email-phil@philjordan.eu>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target/i386/cpu.c |  1 +
 target/i386/cpu.h |  4 ++++
 target/i386/kvm.c | 36 ++++++++++++++++++++++++++++++------
 3 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index aba11ae..dabad37 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -3677,6 +3677,7 @@ static Property x86_cpu_properties[] = {
     DEFINE_PROP_BOOL("cpuid-0xb", X86CPU, enable_cpuid_0xb, true),
     DEFINE_PROP_BOOL("lmce", X86CPU, enable_lmce, false),
     DEFINE_PROP_BOOL("l3-cache", X86CPU, enable_l3_cache, true),
+    DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, false),
     DEFINE_PROP_END_OF_LIST()
 };
 
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 6c1902b..d51b892 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1213,6 +1213,10 @@ struct X86CPU {
     bool host_features;
     uint32_t apic_id;
 
+    /* Enables publishing of TSC increment and Local APIC bus frequencies to
+     * the guest OS in CPUID page 0x40000010, the same way that VMWare does. */
+    bool vmware_cpuid_freq;
+
     /* if true the CPUID code directly forward host cache leaves to the guest */
     bool cache_info_passthrough;
 
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index e6c4f75..00e9080 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -974,12 +974,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
         vmstate_x86_cpu.unmigratable = 1;
     }
 
-    cpuid_data.cpuid.padding = 0;
-    r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data);
-    if (r) {
-        return r;
-    }
-
     r = kvm_arch_set_tsc_khz(cs);
     if (r < 0) {
         return r;
@@ -999,6 +993,36 @@ int kvm_arch_init_vcpu(CPUState *cs)
         }
     }
 
+    if (cpu->vmware_cpuid_freq
+        /* Guests depend on 0x40000000 to detect this feature, so only expose
+         * it if KVM exposes leaf 0x40000000. (Conflicts with Hyper-V) */
+        && cpu->expose_kvm
+        && kvm_base == KVM_CPUID_SIGNATURE
+        /* TSC clock must be stable and known for this feature. */
+        && ((env->features[FEAT_8000_0007_EDX] & CPUID_APM_INVTSC)
+            || env->user_tsc_khz != 0)
+        && env->tsc_khz != 0) {
+
+        c = &cpuid_data.entries[cpuid_i++];
+        c->function = KVM_CPUID_SIGNATURE | 0x10;
+        c->eax = env->tsc_khz;
+        /* LAPIC resolution of 1ns (freq: 1GHz) is hardcoded in KVM's
+         * APIC_BUS_CYCLE_NS */
+        c->ebx = 1000000;
+        c->ecx = c->edx = 0;
+
+        c = cpuid_find_entry(&cpuid_data.cpuid, kvm_base, 0);
+        c->eax = MAX(c->eax, KVM_CPUID_SIGNATURE | 0x10);
+    }
+
+    cpuid_data.cpuid.nent = cpuid_i;
+
+    cpuid_data.cpuid.padding = 0;
+    r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data);
+    if (r) {
+        return r;
+    }
+
     if (has_xsave) {
         env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave));
     }
-- 
1.8.3.1

  parent reply	other threads:[~2017-01-27 13:46 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-27 13:45 [Qemu-devel] [PULL 00/41] Misc changes for 2017-01-27 Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 01/41] icount: update instruction counter on apic patching Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 02/41] replay: improve interrupt handling Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 03/41] replay: don't use rtc clock on loadvm phase Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 04/41] savevm: add public save_vmstate function Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 05/41] replay: save/load initial state Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 06/41] replay: exception replay fix Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 07/41] apic: save apic_delivered flag Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 08/41] memory: tune mtree_print_mr() to dump mr type Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 09/41] memory: hmp: add "-f" for "info mtree" Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 10/41] hw/isa/lpc_ich9: add SMI feature negotiation via fw_cfg Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 11/41] hw/isa/lpc_ich9: add broadcast SMI feature Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 12/41] hw/isa/lpc_ich9: negotiate SMI broadcast on pc-q35-2.9+ machine types Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 13/41] block/iscsi: avoid data corruption with cache=writeback Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 14/41] Introduce DEVICE_CATEGORY_CPU for CPU devices Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 15/41] hw/scsi: Fix debug message of cdb structure in scsi-generic Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 16/41] block: Fix target variable of BLKSECTGET ioctl Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 17/41] block: get max_transfer limit for char (scsi-generic) devices Paolo Bonzini
2017-01-27 13:45 ` Paolo Bonzini [this message]
2017-01-27 13:45 ` [Qemu-devel] [PULL 19/41] pc: Enable vmware-cpuid-freq CPU option for 2.9+ machine types Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 20/41] block/iscsi: statically link qemu_iscsi_opts Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 21/41] tests: fix linking test-char on win32 Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 22/41] qemu-options: stdio is available " Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 23/41] char: add qemu_chr_fe_add_watch() Returns description Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 24/41] doc: fix spelling Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 25/41] char: use a const CharDriver Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 26/41] char: use a static array for backends Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 27/41] char: move callbacks in CharDriver Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 28/41] char: fold single-user functions in caller Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 29/41] char: introduce generic qemu_chr_get_kind() Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 30/41] char: use a feature bit for replay Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 31/41] char: allocate CharDriverState as a single object Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 32/41] bt: use qemu_chr_alloc() Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 33/41] char: rename CharDriverState Chardev Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 34/41] char: rename TCPChardev and NetChardev Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 35/41] spice-char: improve error reporting Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 36/41] char: use error_report() Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 37/41] gtk: overwrite the console.c char driver Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 38/41] baum: use a common prefix for chr callbacks Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 39/41] vc: " Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 40/41] chardev: qom-ify Paolo Bonzini
2017-01-27 13:45 ` [Qemu-devel] [PULL 41/41] memory: don't sign-extend 32-bit writes Paolo Bonzini
2017-01-27 16:58 ` [Qemu-devel] [PULL 00/41] Misc changes for 2017-01-27 Peter Maydell
2017-01-27 19:35 [Qemu-devel] [PULL v2 00/41] Misc patches " Paolo Bonzini
2017-01-27 19:35 ` [Qemu-devel] [PULL 18/41] x86-KVM: Supply TSC and APIC clock rates to guest like VMWare Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1485524749-118532-19-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=phil@philjordan.eu \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.