From patchwork Wed Jan 18 14:24:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Dennis-Jordan X-Patchwork-Id: 9524007 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 078EF601B7 for ; Wed, 18 Jan 2017 14:25:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EC07C285F4 for ; Wed, 18 Jan 2017 14:25:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DDFFC285F3; Wed, 18 Jan 2017 14:25:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BA896285F3 for ; Wed, 18 Jan 2017 14:25:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752026AbdAROZC (ORCPT ); Wed, 18 Jan 2017 09:25:02 -0500 Received: from mail-wm0-f54.google.com ([74.125.82.54]:36924 "EHLO mail-wm0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751458AbdAROZB (ORCPT ); Wed, 18 Jan 2017 09:25:01 -0500 Received: by mail-wm0-f54.google.com with SMTP id c206so27649352wme.0 for ; Wed, 18 Jan 2017 06:25:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=philjordan-eu.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=aj4lvF3bkDud1uKXMMsKptAv0H3f3fpWp81/28qyaSI=; b=ZgTUbO3h51OpL6JN6bb+zsqSf6D255KjachCnrmfAaF3cz4bUF0ElEBLzUxoU7NDWV rXpa3zrKjRlsjCjSxWO8KnMrqHonGPLEMKjxhEiPLcl15YDH+uv4LftfK6hLQMyyV9lG FKWh1nWRZhVQru1mAtxfnSc8SaTIFxzAZEtnJ4PIr4YsEYo1o5i7xkWpMy6pbh8/Opxm c4fbf71n3lc6LmFbWJWJp2Vs3G2AEx4ZPEgvNAUnmjF8f/AHKSUI1lAGme71TYqxckWU jXNZF19n+X8UJ5gbpirW5kXnI6WV0DOuVWsgYj2/QZCxr388bP7Zi0k5cKoZobhPUg3Z cYlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=aj4lvF3bkDud1uKXMMsKptAv0H3f3fpWp81/28qyaSI=; b=gcyeTWaF11ho3HSlmuFd8F+JGU3rWbMnF1EwDoHHL3+sBUv7/LYxnGSNlLfOYJWn0N vNmBjUX4wQbWQjqyz7xDlIMsg24qlibx6c2NifYyhQDBp9C3N0TNQmKrGpclqBCP9H7H ZUuKVcugv48xiSwFtvFhik7D7LxC1R3hvSB320zgkMxpIiXsTpIF4bI7hEOz7sOLKMss r3qWoy9ckK+bEfzl50590Jh81yE8Jyc0RhwAlvG4Zm1GBKGwrPgZqqLPy41dwI2VuLnT 0ot2bJ1sjUf4Q5hJdn8P7+wQ6Mg2qLE4dfY0B28r6RgfJ/g2LZ38x2eonIZugrQQHS1G 6l4A== X-Gm-Message-State: AIkVDXLy8bFnWWkqP+S5vPwJs7eO8T/vGZN6KbzS4ONba/suTpIMIU5byvo0ABU1Iksf8A== X-Received: by 10.28.22.146 with SMTP id 140mr2968270wmw.22.1484749499907; Wed, 18 Jan 2017 06:24:59 -0800 (PST) Received: from Phils-MacBook-Pro-57025.local.eu (37-186-10-86.ip.as39912.net. [37.186.10.86]) by smtp.gmail.com with ESMTPSA id l74sm5283587wmg.2.2017.01.18.06.24.57 (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 18 Jan 2017 06:24:58 -0800 (PST) From: Phil Dennis-Jordan To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Richard Henderson , Eduardo Habkost , Marcelo Tosatti , kvm@vger.kernel.org, Phil Dennis-Jordan Subject: [PATCH] x86-KVM: Supply TSC and APIC clock rates to guest like VMWare Date: Wed, 18 Jan 2017 15:24:17 +0100 Message-Id: <1484749457-87117-1-git-send-email-phil@philjordan.eu> X-Mailer: git-send-email 2.3.2 (Apple Git-55) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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-tsc-apic-clocks" to enable the same behaviour when running Qemu with KVM acceleration, if the KVM TSC frequency can be established. 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 --- target/i386/cpu.c | 1 + target/i386/cpu.h | 4 ++++ target/i386/kvm.c | 40 ++++++++++++++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index aba11ae..e5523d4 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-tsc-apic-clocks", X86CPU, vmware_clock_rates, false), DEFINE_PROP_END_OF_LIST() }; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 6c1902b..1d8590b 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_clock_rates; + /* 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 10a9cd8..7830b3a 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -778,10 +778,14 @@ int kvm_arch_init_vcpu(CPUState *cs) } if (cpu->expose_kvm) { + uint32_t kvm_max_page = KVM_CPUID_FEATURES | kvm_base; + if (cpu->vmware_clock_rates && kvm_base == KVM_CPUID_SIGNATURE) { + kvm_max_page = MAX(kvm_max_page, KVM_CPUID_SIGNATURE | 0x10); + } memcpy(signature, "KVMKVMKVM\0\0\0", 12); c = &cpuid_data.entries[cpuid_i++]; c->function = KVM_CPUID_SIGNATURE | kvm_base; - c->eax = KVM_CPUID_FEATURES | kvm_base; + c->eax = kvm_max_page; c->ebx = signature[0]; c->ecx = signature[1]; c->edx = signature[2]; @@ -910,7 +914,6 @@ int kvm_arch_init_vcpu(CPUState *cs) } } - cpuid_data.cpuid.nent = cpuid_i; if (((env->cpuid_version >> 8)&0xF) >= 6 && (env->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) == @@ -973,12 +976,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; @@ -998,6 +995,33 @@ int kvm_arch_init_vcpu(CPUState *cs) } } + if (cpu->vmware_clock_rates) { + if (cpu->expose_kvm + && kvm_base == KVM_CPUID_SIGNATURE + && env->tsc_khz != 0) { + /* Publish TSC and LAPIC resolution on CPUID page 0x40000010 + * like VMWare for benefit of Darwin guests. */ + 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; + } else { + error_report( + "Warning: VMWare-style TSC/LAPIC clock reporting impossible."); + } + } + + 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)); }