From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753063AbdLHIl2 (ORCPT ); Fri, 8 Dec 2017 03:41:28 -0500 Received: from mail-ot0-f194.google.com ([74.125.82.194]:40892 "EHLO mail-ot0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753023AbdLHIl0 (ORCPT ); Fri, 8 Dec 2017 03:41:26 -0500 X-Google-Smtp-Source: AGs4zMY1EfLEcwxnasB0rorpGjhBGMtCRqBoFlHL57oAiCkwDXpm82jg8Lu9ULsQyC6ndfMFo9Z6Hw== From: Quan Xu X-Google-Original-From: Quan Xu To: pbonzini@redhat.com, rkrcmar@redhat.com Cc: yang.zhang.wz@gmail.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Ben Luo , Quan Xu Subject: [PATCH RFC 7/7] kvm: guest: reprogram guest timer Date: Fri, 8 Dec 2017 16:39:50 +0800 Message-Id: <1512722390-3654-8-git-send-email-quan.xu0@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1512722390-3654-1-git-send-email-quan.xu0@gmail.com> References: <1512722390-3654-1-git-send-email-quan.xu0@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ben Luo In general, KVM guest programs tsc-deadline timestamp to MSR_IA32_TSC_DEADLINE MSR. When pvtimer is enabled, we introduce a new mechanism to reprogram KVM guest timer. A periodically working kthread scans share page and synchronize timer setting for guest on a dedicated CPU. The next time event of the periodically working kthread is a threshold to decide whether to program tsc-deadline timestamp to MSR_IA32_TSC_DEADLINE MSR, or to share page. Signed-off-by: Yang Zhang Signed-off-by: Quan Xu Signed-off-by: Ben Luo --- arch/x86/include/asm/kvm_para.h | 9 +++++++++ arch/x86/kernel/apic/apic.c | 9 ++++++--- arch/x86/kernel/kvm.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h index c373e44..109e706 100644 --- a/arch/x86/include/asm/kvm_para.h +++ b/arch/x86/include/asm/kvm_para.h @@ -5,6 +5,7 @@ #include #include #include +#include extern void kvmclock_init(void); extern int kvm_register_clock(char *txt); @@ -92,6 +93,8 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1, void kvm_async_pf_task_wait(u32 token, int interrupt_kernel); void kvm_async_pf_task_wake(u32 token); u32 kvm_read_and_reset_pf_reason(void); +int kvm_pv_timer_next_event(unsigned long tsc, + struct clock_event_device *evt); extern void kvm_disable_steal_time(void); #ifdef CONFIG_PARAVIRT_SPINLOCKS @@ -126,6 +129,12 @@ static inline void kvm_disable_steal_time(void) { return; } + +static inline int kvm_pv_timer_next_event(unsigned long tsc, + struct clock_event_device *evt) +{ + return 0; +} #endif #endif /* _ASM_X86_KVM_PARA_H */ diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index ff89177..286c1b3 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -471,10 +471,13 @@ static int lapic_next_event(unsigned long delta, static int lapic_next_deadline(unsigned long delta, struct clock_event_device *evt) { - u64 tsc; + u64 tsc = rdtsc() + (((u64) delta) * TSC_DIVISOR); - tsc = rdtsc(); - wrmsrl(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR)); + /* TODO: undisciplined function call */ + if (kvm_pv_timer_next_event(tsc, evt)) + return 0; + + wrmsrl(MSR_IA32_TSC_DEADLINE, tsc); return 0; } diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 8bb9594..ec7aff1 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -328,6 +328,35 @@ static notrace void kvm_guest_apic_eoi_write(u32 reg, u32 val) apic->native_eoi_write(APIC_EOI, APIC_EOI_ACK); } +static DEFINE_PER_CPU(int, pvtimer_enabled); +static DEFINE_PER_CPU(struct pvtimer_vcpu_event_info, + pvtimer_shared_buf) = {0}; +#define PVTIMER_PADDING 25000 +int kvm_pv_timer_next_event(unsigned long tsc, + struct clock_event_device *evt) +{ + struct pvtimer_vcpu_event_info *src; + u64 now; + + if (!this_cpu_read(pvtimer_enabled)) + return false; + + src = this_cpu_ptr(&pvtimer_shared_buf); + xchg((u64 *)&src->expire_tsc, tsc); + + barrier(); + + if (tsc < src->next_sync_tsc) + return false; + + rdtscll(now); + if (tsc < now || tsc - now < PVTIMER_PADDING) + return false; + + return true; +} +EXPORT_SYMBOL_GPL(kvm_pv_timer_next_event); + static void kvm_guest_cpu_init(void) { if (!kvm_para_available()) @@ -362,6 +391,15 @@ static void kvm_guest_cpu_init(void) if (has_steal_clock) kvm_register_steal_time(); + + if (kvm_para_has_feature(KVM_FEATURE_PV_TIMER)) { + unsigned long data; + + data = slow_virt_to_phys(this_cpu_ptr(&pvtimer_shared_buf)) + | KVM_MSR_ENABLED; + wrmsrl(MSR_KVM_PV_TIMER_EN, data); + this_cpu_write(pvtimer_enabled, 1); + } } static void kvm_pv_disable_apf(void) -- 1.7.1