From patchwork Fri Oct 16 04:08:49 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Tosatti X-Patchwork-Id: 54146 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n9G4MUTa022089 for ; Fri, 16 Oct 2009 04:22:31 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751432AbZJPEPt (ORCPT ); Fri, 16 Oct 2009 00:15:49 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751302AbZJPEPt (ORCPT ); Fri, 16 Oct 2009 00:15:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:5048 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751400AbZJPEPo (ORCPT ); Fri, 16 Oct 2009 00:15:44 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n9G4FI5t028744 for ; Fri, 16 Oct 2009 00:15:18 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id n9G4FH01020186; Fri, 16 Oct 2009 00:15:18 -0400 Received: from amt.cnet (vpn-10-29.str.redhat.com [10.32.10.29]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n9G4FFgp012874; Fri, 16 Oct 2009 00:15:16 -0400 Received: from amt.cnet (amt.cnet [127.0.0.1]) by amt.cnet (Postfix) with ESMTP id D2E02674345; Fri, 16 Oct 2009 01:14:59 -0300 (BRT) Received: (from marcelo@localhost) by amt.cnet (8.14.3/8.14.3/Submit) id n9G4EwZf032163; Fri, 16 Oct 2009 01:14:58 -0300 Message-Id: <20091016041415.722361144@redhat.com> User-Agent: quilt/0.47-1 Date: Fri, 16 Oct 2009 01:08:49 -0300 From: Marcelo Tosatti To: kvm@vger.kernel.org Cc: riel@redhat.com, Marcelo Tosatti Subject: [patch 3/5] kvmclock: stolen time aware sched_clock References: <20091016040845.957760057@redhat.com> Content-Disposition: inline; filename=kvm-stolen-time X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Index: kvm/arch/x86/kernel/kvmclock.c =================================================================== --- kvm.orig/arch/x86/kernel/kvmclock.c +++ kvm/arch/x86/kernel/kvmclock.c @@ -38,7 +38,16 @@ static int parse_no_kvmclock(char *arg) early_param("no-kvmclock", parse_no_kvmclock); /* The hypervisor will put information about time periodically here */ -static DEFINE_PER_CPU_SHARED_ALIGNED(struct pvclock_vcpu_time_info, hv_clock); +struct time_info { + struct pvclock_vcpu_time_info hv_clock; + struct kvm_vcpu_runtime_info run_info; +}; + +static DEFINE_PER_CPU_SHARED_ALIGNED(struct time_info, time_info); + +#define hv_clock time_info.hv_clock +#define run_info time_info.run_info + static struct pvclock_wall_clock wall_clock; /* @@ -84,6 +93,40 @@ static cycle_t kvm_clock_get_cycles(stru return kvm_clock_read(); } +cycle_t kvm_runtime_read(struct pvclock_vcpu_time_info *src, + struct kvm_vcpu_runtime_info *rinfo) +{ + struct pvclock_shadow_time shadow; + unsigned version; + cycle_t ret, offset; + unsigned long long stolen; + + do { + version = pvclock_get_time_values(&shadow, src); + barrier(); + offset = pvclock_get_nsec_offset(&shadow); + stolen = rinfo->stolen_time; + ret = shadow.system_timestamp + offset - stolen; + barrier(); + } while (version != src->version); + + return ret; +} + +static cycle_t kvm_clock_read_unstolen(void) +{ + struct pvclock_vcpu_time_info *src; + struct kvm_vcpu_runtime_info *rinfo; + cycle_t ret; + + src = &get_cpu_var(hv_clock); + rinfo = &get_cpu_var(run_info); + ret = kvm_runtime_read(src, rinfo); + put_cpu_var(run_info); + put_cpu_var(hv_clock); + return ret; +} + /* * If we don't do that, there is the possibility that the guest * will calibrate under heavy load - thus, getting a lower lpj - @@ -133,14 +176,30 @@ static int kvm_register_clock(char *txt) return native_write_msr_safe(MSR_KVM_SYSTEM_TIME, low, high); } +static int kvm_register_run_info(char *txt) +{ + int cpu = smp_processor_id(); + int low, high; + + low = (int) __pa(&per_cpu(run_info, cpu)) | 1; + high = ((u64)__pa(&per_cpu(run_info, cpu)) >> 32); + printk(KERN_INFO "kvm-runtime-info: cpu %d, msr %x:%x, %s\n", + cpu, high, low, txt); + return native_write_msr_safe(MSR_KVM_RUN_TIME, low, high); +} + #ifdef CONFIG_X86_LOCAL_APIC static void __cpuinit kvm_setup_secondary_clock(void) { + char *txt = "secondary cpu clock"; + /* * Now that the first cpu already had this clocksource initialized, * we shouldn't fail. */ - WARN_ON(kvm_register_clock("secondary cpu clock")); + WARN_ON(kvm_register_clock(txt)); + if (kvm_para_has_feature(KVM_FEATURE_RUNTIME_INFO)) + kvm_register_run_info(txt); /* ok, done with our trickery, call native */ setup_secondary_APIC_clock(); } @@ -149,7 +208,11 @@ static void __cpuinit kvm_setup_secondar #ifdef CONFIG_SMP static void __init kvm_smp_prepare_boot_cpu(void) { - WARN_ON(kvm_register_clock("primary cpu clock")); + char *txt = "primary cpu clock"; + + WARN_ON(kvm_register_clock(txt)); + if (kvm_para_has_feature(KVM_FEATURE_RUNTIME_INFO)) + kvm_register_run_info(txt); native_smp_prepare_boot_cpu(); } #endif @@ -204,4 +267,6 @@ void __init kvmclock_init(void) pv_info.paravirt_enabled = 1; pv_info.name = "KVM"; } + if (kvm_para_has_feature(KVM_FEATURE_RUNTIME_INFO)) + pv_time_ops.sched_clock = kvm_clock_read_unstolen; }