All of lore.kernel.org
 help / color / mirror / Atom feed
From: Quan Xu <quan.xu0@gmail.com>
To: pbonzini@redhat.com, rkrcmar@redhat.com
Cc: yang.zhang.wz@gmail.com, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org, Ben Luo <bn0418@gmail.com>,
	Quan Xu <quan.xu0@gmail.com>
Subject: [PATCH RFC 7/7] kvm: guest: reprogram guest timer
Date: Fri,  8 Dec 2017 16:39:50 +0800	[thread overview]
Message-ID: <1512722390-3654-8-git-send-email-quan.xu0@gmail.com> (raw)
In-Reply-To: <1512722390-3654-1-git-send-email-quan.xu0@gmail.com>

From: Ben Luo <bn0418@gmail.com>

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 <yang.zhang.wz@gmail.com>
Signed-off-by: Quan Xu <quan.xu0@gmail.com>
Signed-off-by: Ben Luo <bn0418@gmail.com>
---
 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 <asm/processor.h>
 #include <asm/alternative.h>
 #include <uapi/asm/kvm_para.h>
+#include <linux/hrtimer.h>
 
 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

  parent reply	other threads:[~2017-12-08  8:41 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-08  8:39 [PATCH RFC 0/7] kvm pvtimer Quan Xu
2017-12-08  8:39 ` [PATCH RFC 1/7] kvm: x86: emulate MSR_KVM_PV_TIMER_EN MSR Quan Xu
2017-12-08  8:39 ` [PATCH RFC 2/7] kvm: x86: add a function to exchange value Quan Xu
2017-12-08  8:39 ` [PATCH RFC 3/7] KVM: timer: synchronize tsc-deadline timestamp for guest Quan Xu
2017-12-08 15:06   ` Konrad Rzeszutek Wilk
2017-12-14  1:54     ` Quan Xu
2017-12-08  8:39 ` [PATCH RFC 4/7] KVM: timer: program timer to a dedicated CPU Quan Xu
2017-12-08  8:39 ` [PATCH RFC 5/7] KVM: timer: ignore timer migration if pvtimer is enabled Quan Xu
2017-12-08  8:39 ` [PATCH RFC 6/7] Doc/KVM: introduce a new cpuid bit for kvm pvtimer Quan Xu
2017-12-08  8:39 ` Quan Xu [this message]
2017-12-08 15:10 ` [PATCH RFC 0/7] " Konrad Rzeszutek Wilk
     [not found]   ` <CAFv8KnF1Re7Zn2LVvqh=Sr8MmaWJJwZBB1i5ws03GvPVKXRjzA@mail.gmail.com>
2017-12-13 16:28     ` Konrad Rzeszutek Wilk
2017-12-14  2:32       ` Quan Xu
2017-12-14 11:56       ` Paolo Bonzini
2017-12-14 12:06         ` Quan Xu
2017-12-14 13:00           ` 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=1512722390-3654-8-git-send-email-quan.xu0@gmail.com \
    --to=quan.xu0@gmail.com \
    --cc=bn0418@gmail.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=rkrcmar@redhat.com \
    --cc=yang.zhang.wz@gmail.com \
    /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.