From patchwork Thu Nov 15 00:08:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Tosatti X-Patchwork-Id: 1744881 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id C4F5DDF264 for ; Thu, 15 Nov 2012 01:33:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2992560Ab2KOBdJ (ORCPT ); Wed, 14 Nov 2012 20:33:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:6964 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2992548Ab2KOBdH (ORCPT ); Wed, 14 Nov 2012 20:33:07 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qAF1We8B017428 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 14 Nov 2012 20:33:03 -0500 Received: from amt.cnet (vpn1-5-41.gru2.redhat.com [10.97.5.41]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id qAF08q7i008007; Wed, 14 Nov 2012 19:08:53 -0500 Received: from amt.cnet (amt.cnet [127.0.0.1]) by amt.cnet (Postfix) with ESMTP id 3005966E186; Wed, 14 Nov 2012 22:07:37 -0200 (BRST) Received: (from marcelo@localhost) by amt.cnet (8.14.5/8.14.5/Submit) id qAF07bXR001718; Wed, 14 Nov 2012 22:07:37 -0200 Message-Id: <20121115000944.589235439@redhat.com> User-Agent: quilt/0.47-1 Date: Wed, 14 Nov 2012 22:08:37 -0200 From: Marcelo Tosatti To: kvm@vger.kernel.org Cc: johnstul@us.ibm.com, jeremy@goop.org, glommer@parallels.com, zamsden@gmail.com, gleb@redhat.com, avi@redhat.com, pbonzini@redhat.com, Marcelo Tosatti Subject: [patch 14/18] KVM: x86: notifier for clocksource changes References: <20121115000823.285102321@redhat.com> Content-Disposition: inline; filename=15-add-kvm-req-pvclock-gtod-update X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Register a notifier for clocksource change event. In case the host switches to clock other than TSC, disable master clock usage. Signed-off-by: Marcelo Tosatti --- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: vsyscall/arch/x86/kvm/x86.c =================================================================== --- vsyscall.orig/arch/x86/kvm/x86.c +++ vsyscall/arch/x86/kvm/x86.c @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #define CREATE_TRACE_POINTS @@ -899,6 +901,53 @@ static int do_set_msr(struct kvm_vcpu *v return kvm_set_msr(vcpu, index, *data); } +struct pvclock_gtod_data { + seqcount_t seq; + + struct { /* extract of a clocksource struct */ + int vclock_mode; + cycle_t cycle_last; + cycle_t mask; + u32 mult; + u32 shift; + } clock; + + /* open coded 'struct timespec' */ + u64 monotonic_time_snsec; + time_t monotonic_time_sec; +}; + +static struct pvclock_gtod_data pvclock_gtod_data; + +static void update_pvclock_gtod(struct timekeeper *tk) +{ + struct pvclock_gtod_data *vdata = &pvclock_gtod_data; + + write_seqcount_begin(&vdata->seq); + + /* copy pvclock gtod data */ + vdata->clock.vclock_mode = tk->clock->archdata.vclock_mode; + vdata->clock.cycle_last = tk->clock->cycle_last; + vdata->clock.mask = tk->clock->mask; + vdata->clock.mult = tk->mult; + vdata->clock.shift = tk->shift; + + vdata->monotonic_time_sec = tk->xtime_sec + + tk->wall_to_monotonic.tv_sec; + vdata->monotonic_time_snsec = tk->xtime_nsec + + (tk->wall_to_monotonic.tv_nsec + << tk->shift); + while (vdata->monotonic_time_snsec >= + (((u64)NSEC_PER_SEC) << tk->shift)) { + vdata->monotonic_time_snsec -= + ((u64)NSEC_PER_SEC) << tk->shift; + vdata->monotonic_time_sec++; + } + + write_seqcount_end(&vdata->seq); +} + + static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock) { int version; @@ -995,6 +1044,8 @@ static inline u64 get_kernel_ns(void) return timespec_to_ns(&ts); } +static atomic_t kvm_guest_has_master_clock = ATOMIC_INIT(0); + static DEFINE_PER_CPU(unsigned long, cpu_tsc_khz); unsigned long max_tsc_khz; @@ -1227,7 +1278,6 @@ static int kvm_guest_time_update(struct vcpu->last_kernel_ns = kernel_ns; vcpu->last_guest_tsc = tsc_timestamp; - /* * The interface expects us to write an even number signaling that the * update is finished. Since the guest won't see the intermediate @@ -4894,6 +4944,37 @@ static void kvm_set_mmio_spte_mask(void) kvm_mmu_set_mmio_spte_mask(mask); } +static void pvclock_gtod_update_fn(struct work_struct *work) +{ +} + +static DECLARE_WORK(pvclock_gtod_work, pvclock_gtod_update_fn); + +/* + * Notification about pvclock gtod data update. + */ +static int pvclock_gtod_notify(struct notifier_block *nb, unsigned long unused, + void *priv) +{ + struct pvclock_gtod_data *gtod = &pvclock_gtod_data; + struct timekeeper *tk = priv; + + update_pvclock_gtod(tk); + + /* disable master clock if host does not trust, or does not + * use, TSC clocksource + */ + if (gtod->clock.vclock_mode != VCLOCK_TSC && + atomic_read(&kvm_guest_has_master_clock) != 0) + queue_work(system_long_wq, &pvclock_gtod_work); + + return 0; +} + +static struct notifier_block pvclock_gtod_notifier = { + .notifier_call = pvclock_gtod_notify, +}; + int kvm_arch_init(void *opaque) { int r; @@ -4935,6 +5016,8 @@ int kvm_arch_init(void *opaque) host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); kvm_lapic_init(); + pvclock_gtod_register_notifier(&pvclock_gtod_notifier); + return 0; out: @@ -4949,6 +5032,7 @@ void kvm_arch_exit(void) cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); unregister_hotcpu_notifier(&kvmclock_cpu_notifier_block); + pvclock_gtod_unregister_notifier(&pvclock_gtod_notifier); kvm_x86_ops = NULL; kvm_mmu_module_exit(); }