All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
To: kvm-devel <kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: virtualization <virtualization-qjLDD68F18O7TbgM5vRIOg@public.gmane.org>
Subject: [PATCH 2/5] KVM: paravirt time source
Date: Wed, 20 Jun 2007 22:06:36 -0500	[thread overview]
Message-ID: <4679EB3C.4080605@codemonkey.ws> (raw)
In-Reply-To: <4679EAAF.2060103-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 134 bytes --]

This helps a lot on modern kernels where Linux is much more finicky 
about using the TSC as a time source.

Regards,

Anthony Liguori

[-- Attachment #2: kvm-paravirt-time.diff --]
[-- Type: text/x-patch, Size: 4435 bytes --]

Subject: [PATCH] KVM: paravirt time source
Author: Anthony Liguori <aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

This patch implements a paravirtual time source based on a new field added to
the VMCA.  The host provides time in nanoseconds to the guest.

Signed-off-by: Anthony Liguori <aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

diff --git a/arch/i386/kernel/kvm.c b/arch/i386/kernel/kvm.c
index 22ea647..62c3b5b 100644
--- a/arch/i386/kernel/kvm.c
+++ b/arch/i386/kernel/kvm.c
@@ -26,6 +26,18 @@
 #include <linux/cpu.h>
 #include <linux/mm.h>
 
+#include <linux/clocksource.h>
+#include <linux/workqueue.h>
+#include <linux/cpufreq.h>
+#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/acpi_pmtmr.h>
+
+#include "mach_timer.h"
+
+#define KVM_SCALE 22
+
 struct kvm_paravirt_state
 {
 	struct kvm_vmca *vmca;
@@ -38,6 +50,7 @@ struct kvm_paravirt_state
 static DEFINE_PER_CPU(struct kvm_paravirt_state *, paravirt_state);
 
 static int do_nop_io_delay;
+static int do_paravirt_clock;
 static u64 msr_set_vmca;
 
 static long kvm_hypercall(unsigned int nr, unsigned long p1,
@@ -62,6 +75,28 @@ static long kvm_hypercall(unsigned int nr, unsigned long p1,
 	return ret;
 }
 
+static cycle_t kvm_clocksource_read(void)
+{
+	struct kvm_paravirt_state *state = get_cpu_var(paravirt_state);
+	cycle_t ret;
+
+	kvm_hypercall(KVM_HYPERCALL_UPDATE_TIME, 0, 0, 0, 0);
+	ret = state->vmca->real_nsecs;
+	put_cpu_var(paravirt_state);
+
+	return ret;
+}
+
+static struct clocksource clocksource_kvm = {
+	.name			= "kvm",
+	.rating			= 200,
+	.read			= kvm_clocksource_read,
+	.mask			= CLOCKSOURCE_MASK(64),
+	.mult			= 1 << KVM_SCALE,
+	.shift			= KVM_SCALE,
+	.flags			= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
 /*
  * No need for any "IO delay" on KVM
  */
@@ -76,6 +111,14 @@ static void paravirt_ops_setup(void)
 	if (do_nop_io_delay)
 		paravirt_ops.io_delay = kvm_io_delay;
 
+	if (do_paravirt_clock) {
+		int err;
+
+		err = clocksource_register(&clocksource_kvm);
+		WARN_ON(err);
+		printk(KERN_INFO "KVM: using paravirt clock source\n");
+	}
+
 	paravirt_ops.paravirt_enabled = 1;
 
 	apply_paravirt(__parainstructions, __parainstructions_end);
@@ -114,6 +157,9 @@ static int paravirt_initialize(void)
 	if ((edx & KVM_FEATURE_NOP_IO_DELAY))
 		do_nop_io_delay = 1;
 
+	if ((edx & KVM_FEATURE_PARAVIRT_CLOCK))
+		do_paravirt_clock = 1;
+
 	on_each_cpu(paravirt_activate, NULL, 0, 1);
 
 	return 0;
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 1369310..e455fca 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -44,6 +44,7 @@
 #include <linux/cpumask.h>
 #include <linux/smp.h>
 #include <linux/kvm_para.h>
+#include <linux/delay.h>
 
 #include "x86_emulate.h"
 #include "segment_descriptor.h"
@@ -93,7 +94,8 @@ struct vfsmount *kvmfs_mnt;
 #define EFER_RESERVED_BITS 0xfffffffffffff2fe
 
 #define KVM_PARAVIRT_FEATURES \
-	(KVM_FEATURE_VMCA | KVM_FEATURE_NOP_IO_DELAY)
+	(KVM_FEATURE_VMCA | KVM_FEATURE_NOP_IO_DELAY | \
+	 KVM_FEATURE_PARAVIRT_CLOCK)
 
 #define KVM_MSR_SET_VMCA	0x87655678
 
@@ -1346,10 +1348,34 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_halt);
 
+static int kvm_hypercall_update_time(struct kvm_vcpu *vcpu)
+{
+	struct kvm_vmca *vmca;
+	struct timespec now;
+
+	if (unlikely(!vcpu->para_state_page))
+		return -KVM_EINVAL;
+
+	ktime_get_ts(&now);
+
+	vmca = kmap(vcpu->para_state_page);
+
+	vmca->real_nsecs = now.tv_nsec + now.tv_sec * (cycles_t)1e9;
+
+	mark_page_dirty(vcpu->kvm, vcpu->para_state_gpa >> PAGE_SHIFT);
+	kunmap(vcpu->para_state_page);
+
+	return 0;
+}
+
 static int dispatch_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
 			      unsigned long p1, unsigned long p2,
 			      unsigned long p3, unsigned long p4)
 {
+	switch (nr) {
+	case KVM_HYPERCALL_UPDATE_TIME:
+		return kvm_hypercall_update_time(vcpu);
+	}
 	return -KVM_ENOSYS;
 }
 
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
index 11ebad8..4f27fb1 100644
--- a/include/linux/kvm_para.h
+++ b/include/linux/kvm_para.h
@@ -15,10 +15,12 @@
 
 #define KVM_FEATURE_VMCA		(1UL << 0)
 #define KVM_FEATURE_NOP_IO_DELAY	(1UL << 1)
+#define KVM_FEATURE_PARAVIRT_CLOCK	(1UL << 2)
 
 struct kvm_vmca
 {
 	u64 hypercall_gpa;
+	u64 real_nsecs;
 };
 
 /*
@@ -33,5 +35,8 @@ struct kvm_vmca
  */
 
 #define KVM_ENOSYS	ENOSYS
+#define KVM_EINVAL	EINVAL
+
+#define KVM_HYPERCALL_UPDATE_TIME	0
 
 #endif

[-- Attachment #3: Type: text/plain, Size: 286 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

[-- Attachment #4: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

  parent reply	other threads:[~2007-06-21  3:06 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-21  3:04 [PATCH 0/5] KVM paravirt_ops backend (v3) Anthony Liguori
     [not found] ` <4679EAAF.2060103-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-21  3:05   ` [PATCH 1/5] KVM paravirt_ops core infrastructure Anthony Liguori
2007-06-21  3:06   ` Anthony Liguori [this message]
2007-06-21  3:07   ` [PATCH 3/5] KVM: Implement CR read caching for KVM paravirt_ops Anthony Liguori
2007-06-21  3:08   ` [PATCH 4/5] KVM: Add paravirt MMU write support Anthony Liguori
2007-06-21  3:09   ` [PATCH 5/5] KVM: Add hypercall queue for paravirt_ops implementation Anthony Liguori
2007-06-21  3:16   ` [PATCH 0/5] KVM paravirt_ops backend (v3) Anthony Liguori
2007-06-21  9:18   ` Avi Kivity
     [not found]     ` <467A4280.9060503-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-21 13:19       ` Anthony Liguori
2007-06-21  9:26   ` Li, Xin B

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=4679EB3C.4080605@codemonkey.ws \
    --to=anthony-rdkfgonbjusknkdkm+me6a@public.gmane.org \
    --cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    --cc=virtualization-qjLDD68F18O7TbgM5vRIOg@public.gmane.org \
    /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.