All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch 1/5] KVM: x86: provide realtime host clock via vsyscall notifiers
  2017-01-20 12:20 [patch 0/5] KVM virtual PTP driver (v3) Marcelo Tosatti
@ 2017-01-20 12:20 ` Marcelo Tosatti
  0 siblings, 0 replies; 8+ messages in thread
From: Marcelo Tosatti @ 2017-01-20 12:20 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: Paolo Bonzini, Radim Krcmar, Richard Cochran, Miroslav Lichvar,
	Marcelo Tosatti

[-- Attachment #1: kvm-do-realtime --]
[-- Type: text/plain, Size: 2012 bytes --]

Expose the realtime host clock and save the TSC value
used for the clock calculation.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

---
 arch/x86/kvm/x86.c |   36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

v2: unify nsec_base (Radim)

Index: kvm-ptpdriver/arch/x86/kvm/x86.c
===================================================================
--- kvm-ptpdriver.orig/arch/x86/kvm/x86.c	2017-01-13 16:43:15.013244682 -0200
+++ kvm-ptpdriver/arch/x86/kvm/x86.c	2017-01-20 09:56:41.404534904 -0200
@@ -1139,6 +1139,7 @@
 
 	u64		boot_ns;
 	u64		nsec_base;
+	u64		wall_time_sec;
 };
 
 static struct pvclock_gtod_data pvclock_gtod_data;
@@ -1162,6 +1163,8 @@
 	vdata->boot_ns			= boot_ns;
 	vdata->nsec_base		= tk->tkr_mono.xtime_nsec;
 
+	vdata->wall_time_sec            = tk->xtime_sec;
+
 	write_seqcount_end(&vdata->seq);
 }
 #endif
@@ -1623,6 +1626,28 @@
 	return mode;
 }
 
+static int do_realtime(struct timespec *ts, cycle_t *cycle_now)
+{
+	struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
+	unsigned long seq;
+	int mode;
+	u64 ns;
+
+	do {
+		seq = read_seqcount_begin(&gtod->seq);
+		mode = gtod->clock.vclock_mode;
+		ts->tv_sec = gtod->wall_time_sec;
+		ns = gtod->nsec_base;
+		ns += vgettsc(cycle_now);
+		ns >>= gtod->clock.shift;
+	} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
+
+	ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+	ts->tv_nsec = ns;
+
+	return mode;
+}
+
 /* returns true if host is using tsc clocksource */
 static bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now)
 {
@@ -1632,6 +1657,17 @@
 
 	return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC;
 }
+
+/* returns true if host is using tsc clocksource */
+static bool kvm_get_walltime_and_clockread(struct timespec *ts,
+					   cycle_t *cycle_now)
+{
+	/* checked again under seqlock below */
+	if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC)
+		return false;
+
+	return do_realtime(ts, cycle_now) == VCLOCK_TSC;
+}
 #endif
 
 /*



^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 0/5] KVM virtual PTP driver (v4)
@ 2017-01-20 14:51 Marcelo Tosatti
  2017-01-20 14:51 ` [patch 1/5] KVM: x86: provide realtime host clock via vsyscall notifiers Marcelo Tosatti
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Marcelo Tosatti @ 2017-01-20 14:51 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: Paolo Bonzini, Radim Krcmar, Richard Cochran, Miroslav Lichvar

This patchset implements a virtual PTP driver which allows guest to sync
its clock to the host clock with high precision
(error is < 1us on an idle guest).

Changelog from v3

Patch3:

v2: export kvmclock clocksource structure directly (Paolo)

Patch4:

v2: drop timekeeper spinlock, move back to drivers/ptp/ptp_chardev.c (Paolo)
    ptp_clock_gettime: support drivers with crosstimestamp but not
    gettime64 callbacks (Paolo)

Patch5:

v4: remove gettime64 callback (Paolo)

Changelog from v2

Cross timestamping, emulation of PTP_SYS_OFFSET with cross timestamping
(Paolo, Miroslav, Radim).

Changelog from v1

Patch1:
v2: unify nsec_base (Radim)

Patch2:
v2: improve documentation (Radim)
    change hypercall name to KVM_HC_CLOCK_PAIRING (Radim)
    increase padding size

Patch3:
v2: check for kvmclock (Radim)
    initialize global variables before device registration (Radim)



PHC0                          0   3   377     7   -141ns[ +234ns] +/-    7ns
#* PHC0                          0   3   377     5   -197ns[ -403ns] +/-    3ns
#* PHC0                          0   3   377    11   +157ns[ +264ns] +/-    3ns
#* PHC0                          0   3   377     9    +92ns[ +304ns] +/-    2ns
#* PHC0                          0   3   377     7   -102ns[ -164ns] +/-    3ns
#* PHC0                          0   3   377     5   -157ns[ -269ns] +/-    2ns
#* PHC0                          0   3   377    10    -63ns[  -98ns] +/-    2ns
#* PHC0                          0   3   377     8   +351ns[ +399ns] +/-    2ns
#* PHC0                          0   3   377     6   +385ns[ +399ns] +/-    4ns
#* PHC0                          0   3   377     4   -133ns[ -110ns] +/-    6ns
#* PHC0                          0   3   377    10    -59ns[  -90ns] +/-    3ns
#* PHC0                          0   3   377     8    -90ns[ +381ns] +/-    9ns
#* PHC0                          0   3   377     6     +6ns[ +216ns] +/-    6ns
#* PHC0                          0   3   377     4   +166ns[ -666ns] +/-   11ns
#* PHC0                          0   3   377    10    -18ns[ +323ns] +/-   10ns
#* PHC0                          0   3   377     8    -12ns[ +121ns] +/-    5ns
#* PHC0                          0   3   377     5     +4ns[ +218ns] +/-    7ns
#* PHC0                          0   3   377     4   +162ns[ -683ns] +/-   11ns
#* PHC0                          0   3   377    10    -82ns[ +310ns] +/-   12ns
#* PHC0                          0   3   377     7     +5ns[ -320ns] +/-    9ns
#* PHC0                          0   3   377     5    -13ns[ +165ns] +/-    7ns
#* PHC0                          0   3   377     3     +6ns[ +105ns] +/-    2ns
#* PHC0                          0   3   377     9    -19ns[  -67ns] +/-    3ns
#* PHC0                          0   3   377     8    +89ns[ +181ns] +/-    3ns
#* PHC0                          0   3   377     6    +93ns[ +168ns] +/-    2ns
#* PHC0                          0   3   377     4   +100ns[ +154ns] +/-    2ns
#* PHC0                          0   3   377    10   -249ns[ +180ns] +/-    7ns
#* PHC0                          0   3   377     8   +158ns[ -582ns] +/-   22ns
#* PHC0                          0   3   377     6    +10ns[ +213ns] +/-    9ns
#* PHC0                          0   3   377     3    -35ns[ +258ns] +/-    5ns
#* PHC0                          0   3   377    10    +25ns[ -620ns] +/-    8ns
#* PHC0                          0   3   377     7    +13ns[ +153ns] +/-    2ns





^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 1/5] KVM: x86: provide realtime host clock via vsyscall notifiers
  2017-01-20 14:51 [patch 0/5] KVM virtual PTP driver (v4) Marcelo Tosatti
@ 2017-01-20 14:51 ` Marcelo Tosatti
  2017-01-20 14:51 ` [patch 2/5] KVM: x86: add KVM_HC_CLOCK_OFFSET hypercall Marcelo Tosatti
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Marcelo Tosatti @ 2017-01-20 14:51 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: Paolo Bonzini, Radim Krcmar, Richard Cochran, Miroslav Lichvar,
	Marcelo Tosatti

[-- Attachment #1: kvm-do-realtime --]
[-- Type: text/plain, Size: 2010 bytes --]

Expose the realtime host clock and save the TSC value
used for the clock calculation.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

---
 arch/x86/kvm/x86.c |   36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

v2: unify nsec_base (Radim)

Index: kvm-ptpdriver/arch/x86/kvm/x86.c
===================================================================
--- kvm-ptpdriver.orig/arch/x86/kvm/x86.c	2017-01-13 16:43:15.013244682 -0200
+++ kvm-ptpdriver/arch/x86/kvm/x86.c	2017-01-20 09:56:41.404534904 -0200
@@ -1139,6 +1139,7 @@
 
 	u64		boot_ns;
 	u64		nsec_base;
+	u64		wall_time_sec;
 };
 
 static struct pvclock_gtod_data pvclock_gtod_data;
@@ -1162,6 +1163,8 @@
 	vdata->boot_ns			= boot_ns;
 	vdata->nsec_base		= tk->tkr_mono.xtime_nsec;
 
+	vdata->wall_time_sec            = tk->xtime_sec;
+
 	write_seqcount_end(&vdata->seq);
 }
 #endif
@@ -1623,6 +1626,28 @@
 	return mode;
 }
 
+static int do_realtime(struct timespec *ts, cycle_t *cycle_now)
+{
+	struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
+	unsigned long seq;
+	int mode;
+	u64 ns;
+
+	do {
+		seq = read_seqcount_begin(&gtod->seq);
+		mode = gtod->clock.vclock_mode;
+		ts->tv_sec = gtod->wall_time_sec;
+		ns = gtod->nsec_base;
+		ns += vgettsc(cycle_now);
+		ns >>= gtod->clock.shift;
+	} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
+
+	ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+	ts->tv_nsec = ns;
+
+	return mode;
+}
+
 /* returns true if host is using tsc clocksource */
 static bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now)
 {
@@ -1632,6 +1657,17 @@
 
 	return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC;
 }
+
+/* returns true if host is using tsc clocksource */
+static bool kvm_get_walltime_and_clockread(struct timespec *ts,
+					   cycle_t *cycle_now)
+{
+	/* checked again under seqlock below */
+	if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC)
+		return false;
+
+	return do_realtime(ts, cycle_now) == VCLOCK_TSC;
+}
 #endif
 
 /*

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 2/5] KVM: x86: add KVM_HC_CLOCK_OFFSET hypercall
  2017-01-20 14:51 [patch 0/5] KVM virtual PTP driver (v4) Marcelo Tosatti
  2017-01-20 14:51 ` [patch 1/5] KVM: x86: provide realtime host clock via vsyscall notifiers Marcelo Tosatti
@ 2017-01-20 14:51 ` Marcelo Tosatti
  2017-01-20 14:51 ` [patch 3/5] kvmclock: export kvmclock clocksource pointer Marcelo Tosatti
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Marcelo Tosatti @ 2017-01-20 14:51 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: Paolo Bonzini, Radim Krcmar, Richard Cochran, Miroslav Lichvar,
	Marcelo Tosatti

[-- Attachment #1: kvm-hv-clock-offset --]
[-- Type: text/plain, Size: 5057 bytes --]

Add a hypercall to retrieve the host realtime clock
and the TSC value used to calculate that clock read.

Used to implement clock synchronization between
host and guest.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

---
 Documentation/virtual/kvm/hypercalls.txt |   33 ++++++++++++++++++++++++
 arch/x86/include/uapi/asm/kvm_para.h     |    9 ++++++
 arch/x86/kvm/x86.c                       |   41 +++++++++++++++++++++++++++++++
 include/uapi/linux/kvm_para.h            |    3 ++
 4 files changed, 86 insertions(+)

v2: improve documentation (Radim)
    change hypercall name to KVM_HC_CLOCK_PAIRING (Radim)
    increase padding size

Index: kvm-ptpdriver/arch/x86/include/uapi/asm/kvm_para.h
===================================================================
--- kvm-ptpdriver.orig/arch/x86/include/uapi/asm/kvm_para.h	2017-01-13 16:43:11.947240575 -0200
+++ kvm-ptpdriver/arch/x86/include/uapi/asm/kvm_para.h	2017-01-13 16:43:25.038258187 -0200
@@ -50,6 +50,15 @@
 	__u32 pad[11];
 };
 
+#define KVM_CLOCK_PAIRING_WALLCLOCK 0
+struct kvm_clock_offset {
+	__s64 sec;
+	__s64 nsec;
+	__u64 tsc;
+	__u32 flags;
+	__u32 pad[9];
+};
+
 #define KVM_STEAL_ALIGNMENT_BITS 5
 #define KVM_STEAL_VALID_BITS ((-1ULL << (KVM_STEAL_ALIGNMENT_BITS + 1)))
 #define KVM_STEAL_RESERVED_MASK (((1 << KVM_STEAL_ALIGNMENT_BITS) - 1 ) << 1)
Index: kvm-ptpdriver/Documentation/virtual/kvm/hypercalls.txt
===================================================================
--- kvm-ptpdriver.orig/Documentation/virtual/kvm/hypercalls.txt	2017-01-13 16:43:11.947240575 -0200
+++ kvm-ptpdriver/Documentation/virtual/kvm/hypercalls.txt	2017-01-13 16:43:25.038258187 -0200
@@ -81,3 +81,36 @@
 same guest can wakeup the sleeping vcpu by issuing KVM_HC_KICK_CPU hypercall,
 specifying APIC ID (a1) of the vcpu to be woken up. An additional argument (a0)
 is used in the hypercall for future use.
+
+
+6. KVM_HC_CLOCK_PAIRING
+------------------------
+Architecture: x86
+Status: active
+Purpose: Hypercall used to synchronize host and guest clocks.
+Usage:
+
+a0: guest physical address where host copies
+"struct kvm_clock_offset" structure.
+
+a1: clock_type, ATM only KVM_CLOCK_PAIRING_WALLCLOCK (0)
+is supported (hosts CLOCK_REALTIME clock).
+
+		struct kvm_clock_offset {
+			__s64 sec;
+			__s64 nsec;
+			__u64 tsc;
+			__u32 flags;
+			__u32 pad[9];
+		};
+
+       Where:
+               * sec: seconds from clock_type clock.
+               * nsec: nanoseconds from clock_type clock.
+               * tsc: TSC value used to calculate sec/nsec pair
+                 (this hypercall only works when host uses TSC clocksource).
+               * flags: flags, unused (0) at the moment.
+
+Returns KVM_EOPNOTSUPP if the host does not use TSC clocksource,
+or if clock type is different than KVM_CLOCK_PAIRING_WALLCLOCK.
+
Index: kvm-ptpdriver/arch/x86/kvm/x86.c
===================================================================
--- kvm-ptpdriver.orig/arch/x86/kvm/x86.c	2017-01-13 16:43:20.898252596 -0200
+++ kvm-ptpdriver/arch/x86/kvm/x86.c	2017-01-13 16:43:25.041258191 -0200
@@ -6119,6 +6119,44 @@
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_halt);
 
+static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr,
+			       unsigned long clock_type)
+{
+	struct kvm_clock_offset *clock_offset;
+	struct timespec ts;
+	cycle_t cycle;
+	int ret;
+
+	if (clock_type != KVM_CLOCK_PAIRING_WALLCLOCK)
+		return -KVM_EOPNOTSUPP;
+
+	if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC)
+		return -KVM_EOPNOTSUPP;
+
+	clock_offset = kzalloc(sizeof(struct kvm_clock_offset), GFP_KERNEL);
+	if (clock_offset == NULL)
+		return -KVM_ENOMEM;
+
+	if (kvm_get_walltime_and_clockread(&ts, &cycle) == false) {
+		kfree(clock_offset);
+		return -KVM_EOPNOTSUPP;
+	}
+
+	clock_offset->sec = ts.tv_sec;
+	clock_offset->nsec = ts.tv_nsec;
+	clock_offset->tsc = kvm_read_l1_tsc(vcpu, cycle);
+	clock_offset->flags = 0;
+
+	ret = 0;
+	if (kvm_write_guest(vcpu->kvm, paddr, clock_offset,
+			      sizeof(struct kvm_clock_offset)))
+		ret = -KVM_EFAULT;
+
+	kfree(clock_offset);
+
+	return ret;
+}
+
 /*
  * kvm_pv_kick_cpu_op:  Kick a vcpu.
  *
@@ -6183,6 +6221,9 @@
 		kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1);
 		ret = 0;
 		break;
+	case KVM_HC_CLOCK_PAIRING:
+		ret = kvm_pv_clock_pairing(vcpu, a0, a1);
+		break;
 	default:
 		ret = -KVM_ENOSYS;
 		break;
Index: kvm-ptpdriver/include/uapi/linux/kvm_para.h
===================================================================
--- kvm-ptpdriver.orig/include/uapi/linux/kvm_para.h	2017-01-13 16:43:11.947240575 -0200
+++ kvm-ptpdriver/include/uapi/linux/kvm_para.h	2017-01-13 16:43:25.042258192 -0200
@@ -14,6 +14,8 @@
 #define KVM_EFAULT		EFAULT
 #define KVM_E2BIG		E2BIG
 #define KVM_EPERM		EPERM
+#define KVM_EOPNOTSUPP		EOPNOTSUPP
+#define KVM_ENOMEM		ENOMEM
 
 #define KVM_HC_VAPIC_POLL_IRQ		1
 #define KVM_HC_MMU_OP			2
@@ -23,6 +25,7 @@
 #define KVM_HC_MIPS_GET_CLOCK_FREQ	6
 #define KVM_HC_MIPS_EXIT_VM		7
 #define KVM_HC_MIPS_CONSOLE_OUTPUT	8
+#define KVM_HC_CLOCK_PAIRING		9
 
 /*
  * hypercalls use architecture specific

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 3/5] kvmclock: export kvmclock clocksource pointer
  2017-01-20 14:51 [patch 0/5] KVM virtual PTP driver (v4) Marcelo Tosatti
  2017-01-20 14:51 ` [patch 1/5] KVM: x86: provide realtime host clock via vsyscall notifiers Marcelo Tosatti
  2017-01-20 14:51 ` [patch 2/5] KVM: x86: add KVM_HC_CLOCK_OFFSET hypercall Marcelo Tosatti
@ 2017-01-20 14:51 ` Marcelo Tosatti
  2017-01-20 14:51 ` [patch 4/5] PTP: add PTP_SYS_OFFSET emulation via cross timestamps infrastructure Marcelo Tosatti
  2017-01-20 14:51 ` [patch 5/5] PTP: add kvm PTP driver Marcelo Tosatti
  4 siblings, 0 replies; 8+ messages in thread
From: Marcelo Tosatti @ 2017-01-20 14:51 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: Paolo Bonzini, Radim Krcmar, Richard Cochran, Miroslav Lichvar,
	Marcelo Tosatti

[-- Attachment #1: kvmclock-export-clocksource --]
[-- Type: text/plain, Size: 1367 bytes --]

To be used by KVM PTP driver.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

---
 arch/x86/include/asm/kvmclock.h |    6 ++++++
 arch/x86/kernel/kvmclock.c      |    3 ++-
 2 files changed, 8 insertions(+), 1 deletion(-)

v2: export kvmclock clocksource structure directly (Paolo)

Index: kvm-ptpdriver/arch/x86/include/asm/kvmclock.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kvm-ptpdriver/arch/x86/include/asm/kvmclock.h	2017-01-20 11:05:28.720038512 -0200
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_KVM_CLOCK_H
+#define _ASM_X86_KVM_CLOCK_H
+
+extern struct clocksource kvm_clock;
+
+#endif /* _ASM_X86_KVM_CLOCK_H */
Index: kvm-ptpdriver/arch/x86/kernel/kvmclock.c
===================================================================
--- kvm-ptpdriver.orig/arch/x86/kernel/kvmclock.c	2017-01-20 10:03:44.750489955 -0200
+++ kvm-ptpdriver/arch/x86/kernel/kvmclock.c	2017-01-20 11:05:03.137971637 -0200
@@ -28,6 +28,7 @@
 
 #include <asm/x86_init.h>
 #include <asm/reboot.h>
+#include <asm/kvmclock.h>
 
 static int kvmclock __ro_after_init = 1;
 static int msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
@@ -174,7 +175,7 @@
 	return ret;
 }
 
-static struct clocksource kvm_clock = {
+struct clocksource kvm_clock = {
 	.name = "kvm-clock",
 	.read = kvm_clock_get_cycles,
 	.rating = 400,

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 4/5] PTP: add PTP_SYS_OFFSET emulation via cross timestamps infrastructure
  2017-01-20 14:51 [patch 0/5] KVM virtual PTP driver (v4) Marcelo Tosatti
                   ` (2 preceding siblings ...)
  2017-01-20 14:51 ` [patch 3/5] kvmclock: export kvmclock clocksource pointer Marcelo Tosatti
@ 2017-01-20 14:51 ` Marcelo Tosatti
  2017-01-20 14:51 ` [patch 5/5] PTP: add kvm PTP driver Marcelo Tosatti
  4 siblings, 0 replies; 8+ messages in thread
From: Marcelo Tosatti @ 2017-01-20 14:51 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: Paolo Bonzini, Radim Krcmar, Richard Cochran, Miroslav Lichvar,
	Marcelo Tosatti

[-- Attachment #1: ptp-add-sysoffset-callback --]
[-- Type: text/plain, Size: 3825 bytes --]

Emulate PTP_SYS_OFFSET by using an arithmetic mean of the
realtime samples from ->getcrosststamp callback.

Note: if the realtime clock changes during cross timestamp sampling,
then the mean will return a value that does not exist. Given the
nature of PTP_SYS_OFFSET users (time synchronization), 
that should not be a problem.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

---
 drivers/ptp/ptp_chardev.c |   73 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/ptp/ptp_clock.c   |   10 ++++++
 2 files changed, 83 insertions(+)

v2: drop timekeeper spinlock, move back to drivers/ptp/ptp_chardev.c (Paolo)
    ptp_clock_gettime: support drivers with crosstimestamp but not
    gettime64 callbacks

Index: kvm-ptpdriver/drivers/ptp/ptp_chardev.c
===================================================================
--- kvm-ptpdriver.orig/drivers/ptp/ptp_chardev.c	2017-01-20 12:48:14.201126341 -0200
+++ kvm-ptpdriver/drivers/ptp/ptp_chardev.c	2017-01-20 12:48:45.270207972 -0200
@@ -116,6 +116,74 @@
 	return 0;
 }
 
+static void mean_sys_realtime(struct system_device_crosststamp *xtstamp,
+			      struct system_device_crosststamp *n_xtstamp,
+			      struct ptp_clock_time *pct)
+{
+	ktime_t sys_realtime, n_sys_realtime;
+	struct timespec ts;
+	u64 ns;
+
+	/* estimate realtime with arithmetic mean of two crosststamp samples */
+	sys_realtime = xtstamp->sys_realtime;
+	n_sys_realtime = n_xtstamp->sys_realtime;
+	ns = ktime_divns(ktime_add(sys_realtime, n_sys_realtime), 2);
+	ts = ktime_to_timespec(ns_to_ktime(ns));
+	pct->sec = ts.tv_sec;
+	pct->nsec = ts.tv_nsec;
+}
+
+static int emulate_ptp_sys_offset(struct ptp_clock_info *info,
+				  struct ptp_sys_offset *sysoff,
+				  unsigned long arg)
+{
+	int i, err, len;
+	int n_samples;
+	struct system_device_crosststamp *xtstamps, *xtstamp, *n_xtstamp;
+	struct ptp_clock_time *pct;
+
+	n_samples = sysoff->n_samples + 2;
+
+	len = sizeof(struct system_device_crosststamp);
+	xtstamps = kzalloc(len * n_samples, GFP_KERNEL);
+	if (xtstamps == NULL)
+		return -ENOMEM;
+
+	xtstamp = xtstamps;
+	for (i = 0; i < n_samples; i++) {
+		err = info->getcrosststamp(info, xtstamp);
+		if (err) {
+			kfree(xtstamps);
+			return err;
+		}
+		xtstamp++;
+	}
+
+	pct = &sysoff->ts[0];
+	xtstamp = n_xtstamp = xtstamps;
+	n_xtstamp++;
+	for (i = 0; i < sysoff->n_samples; i++) {
+		struct timespec ts;
+
+		mean_sys_realtime(xtstamp, n_xtstamp, pct);
+		pct++;
+
+		ts = ktime_to_timespec(n_xtstamp->device);
+		pct->sec = ts.tv_sec;
+		pct->nsec = ts.tv_nsec;
+		pct++;
+		xtstamp++;
+		n_xtstamp++;
+	}
+
+	mean_sys_realtime(xtstamp, n_xtstamp, pct);
+	kfree(xtstamps);
+	if (copy_to_user((void __user *)arg, sysoff, sizeof(*sysoff)))
+		return -EFAULT;
+
+	return 0;
+}
+
 long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 {
 	struct ptp_clock_caps caps;
@@ -219,6 +287,11 @@
 			err = -EINVAL;
 			break;
 		}
+
+		if (!ptp->info->gettime64 && ptp->info->getcrosststamp) {
+			err = emulate_ptp_sys_offset(ptp->info, sysoff, arg);
+			break;
+		}
 		pct = &sysoff->ts[0];
 		for (i = 0; i < sysoff->n_samples; i++) {
 			getnstimeofday64(&ts);
Index: kvm-ptpdriver/drivers/ptp/ptp_clock.c
===================================================================
--- kvm-ptpdriver.orig/drivers/ptp/ptp_clock.c	2017-01-20 12:48:14.201126341 -0200
+++ kvm-ptpdriver/drivers/ptp/ptp_clock.c	2017-01-20 12:48:45.271207975 -0200
@@ -118,6 +118,16 @@
 	struct timespec64 ts;
 	int err;
 
+	if (!ptp->info->gettime64 && ptp->info->getcrosststamp) {
+		struct system_device_crosststamp xtstamp;
+
+		err = ptp->info->getcrosststamp(ptp->info, &xtstamp);
+		if (err)
+			return err;
+		*tp = ktime_to_timespec(xtstamp.device);
+		return err;
+	}
+
 	err = ptp->info->gettime64(ptp->info, &ts);
 	if (!err)
 		*tp = timespec64_to_timespec(ts);

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 5/5] PTP: add kvm PTP driver
  2017-01-20 14:51 [patch 0/5] KVM virtual PTP driver (v4) Marcelo Tosatti
                   ` (3 preceding siblings ...)
  2017-01-20 14:51 ` [patch 4/5] PTP: add PTP_SYS_OFFSET emulation via cross timestamps infrastructure Marcelo Tosatti
@ 2017-01-20 14:51 ` Marcelo Tosatti
  2017-01-20 15:03   ` [patch 5/5] PTP: add kvm PTP driver (v2) Marcelo Tosatti
  4 siblings, 1 reply; 8+ messages in thread
From: Marcelo Tosatti @ 2017-01-20 14:51 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: Paolo Bonzini, Radim Krcmar, Richard Cochran, Miroslav Lichvar,
	Marcelo Tosatti

[-- Attachment #1: kvm-ptpdriver --]
[-- Type: text/plain, Size: 6844 bytes --]

Add a driver with gettime method returning hosts realtime clock.
This allows Chrony to synchronize host and guest clocks with 
high precision (see results below).

chronyc> sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
#* PHC0                          0   3   377     4   +162ns[ -683ns] +/-   11ns

To configure Chronyd to use PHC refclock, add the 
following line to its configuration file:

refclock PHC /dev/ptpX poll 3 dpoll -2 offset 0

Where /dev/ptpX is the kvmclock PTP clock.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

---
 drivers/ptp/Kconfig   |   12 +++
 drivers/ptp/Makefile  |    1 
 drivers/ptp/ptp_kvm.c |  179 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 192 insertions(+)

v2: check for kvmclock (Radim)
    initialize global variables before device registration (Radim)
v3: use cross timestamps callback (Paolo, Miroslav, Radim)
v4: remove gettime64 callback (Paolo)

Index: kvm-ptpdriver/drivers/ptp/Kconfig
===================================================================
--- kvm-ptpdriver.orig/drivers/ptp/Kconfig	2017-01-20 12:16:32.071150523 -0200
+++ kvm-ptpdriver/drivers/ptp/Kconfig	2017-01-20 12:20:13.862727779 -0200
@@ -90,4 +90,16 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called ptp_pch.
 
+config PTP_1588_CLOCK_KVM
+	tristate "KVM virtual PTP clock"
+	depends on PTP_1588_CLOCK
+	depends on KVM_GUEST
+	default y
+	help
+	  This driver adds support for using kvm infrastructure as a PTP
+	  clock. This clock is only useful if you are using KVM guests.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called ptp_kvm.
+
 endmenu
Index: kvm-ptpdriver/drivers/ptp/Makefile
===================================================================
--- kvm-ptpdriver.orig/drivers/ptp/Makefile	2017-01-20 12:16:32.071150523 -0200
+++ kvm-ptpdriver/drivers/ptp/Makefile	2017-01-20 12:20:13.862727779 -0200
@@ -6,3 +6,4 @@
 obj-$(CONFIG_PTP_1588_CLOCK)		+= ptp.o
 obj-$(CONFIG_PTP_1588_CLOCK_IXP46X)	+= ptp_ixp46x.o
 obj-$(CONFIG_PTP_1588_CLOCK_PCH)	+= ptp_pch.o
+obj-$(CONFIG_PTP_1588_CLOCK_KVM)	+= ptp_kvm.o
Index: kvm-ptpdriver/drivers/ptp/ptp_kvm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kvm-ptpdriver/drivers/ptp/ptp_kvm.c	2017-01-20 12:20:13.863727782 -0200
@@ -0,0 +1,179 @@
+/*
+ * Virtual PTP 1588 clock for use with KVM guests
+ *
+ * Copyright (C) 2017 Red Hat Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <uapi/linux/kvm_para.h>
+#include <asm/kvm_para.h>
+#include <asm/pvclock.h>
+#include <asm/kvmclock.h>
+#include <uapi/asm/kvm_para.h>
+
+#include <linux/ptp_clock_kernel.h>
+
+struct kvm_ptp_clock {
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info caps;
+};
+
+DEFINE_SPINLOCK(kvm_ptp_lock);
+
+static struct pvclock_vsyscall_time_info *hv_clock;
+
+static struct kvm_clock_offset clock_off;
+static phys_addr_t clock_off_gpa;
+
+static int ptp_kvm_get_time_fn(ktime_t *device_time,
+			       struct system_counterval_t *system_counter,
+			       void *ctx)
+{
+	unsigned long ret;
+	struct timespec64 tspec;
+	unsigned version;
+	u8 flags;
+	int cpu;
+	struct pvclock_vcpu_time_info *src;
+
+	preempt_disable_notrace();
+	cpu = smp_processor_id();
+	src = &hv_clock[cpu].pvti;
+
+	spin_lock(&kvm_ptp_lock);
+
+	do {
+		/*
+		 * We are using a TSC value read in the hosts
+		 * kvm_hc_clock_pairing handling.
+		 * So any changes to tsc_to_system_mul
+		 * and tsc_shift or any other pvclock
+		 * data invalidate that measurement.
+		 */
+		version = pvclock_read_begin(src);
+
+		ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING,
+				     clock_off_gpa,
+				     KVM_CLOCK_PAIRING_WALLCLOCK);
+		if (ret != 0) {
+			pr_err("clock offset hypercall ret %lu\n", ret);
+			spin_unlock(&kvm_ptp_lock);
+			preempt_enable_notrace();
+			return -EOPNOTSUPP;
+		}
+
+		tspec.tv_sec = clock_off.sec;
+		tspec.tv_nsec = clock_off.nsec;
+		ret = __pvclock_read_cycles(src, clock_off.tsc);
+		flags = src->flags;
+	} while (pvclock_read_retry(src, version));
+
+	preempt_enable_notrace();
+
+	system_counter->cycles = ret;
+	system_counter->cs = &kvm_clock;
+
+	tspec.tv_nsec = tspec.tv_nsec;
+
+	*device_time = timespec_to_ktime(tspec);
+
+	spin_unlock(&kvm_ptp_lock);
+
+	return 0;
+}
+
+static int ptp_kvm_getcrosststamp(struct ptp_clock_info *ptp,
+				  struct system_device_crosststamp *xtstamp)
+{
+	return get_device_system_crosststamp(ptp_kvm_get_time_fn, NULL,
+					     NULL, xtstamp);
+}
+
+/*
+ * PTP clock operations
+ */
+
+static int ptp_kvm_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	return -EOPNOTSUPP;
+}
+
+static int ptp_kvm_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	return -EOPNOTSUPP;
+}
+
+static int ptp_kvm_settime(struct ptp_clock_info *ptp,
+			   const struct timespec64 *ts)
+{
+	return -EOPNOTSUPP;
+}
+
+static int ptp_kvm_enable(struct ptp_clock_info *ptp,
+			  struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info ptp_kvm_caps = {
+	.owner		= THIS_MODULE,
+	.name		= "KVM virtual PTP",
+	.max_adj	= 0,
+	.n_ext_ts	= 0,
+	.n_pins		= 0,
+	.pps		= 0,
+	.adjfreq	= ptp_kvm_adjfreq,
+	.adjtime	= ptp_kvm_adjtime,
+	.gettime64	= NULL,
+	.settime64	= ptp_kvm_settime,
+	.enable		= ptp_kvm_enable,
+	.getcrosststamp = ptp_kvm_getcrosststamp,
+};
+
+/* module operations */
+
+static struct kvm_ptp_clock kvm_ptp_clock;
+
+static void __exit ptp_kvm_exit(void)
+{
+	ptp_clock_unregister(kvm_ptp_clock.ptp_clock);
+}
+
+static int __init ptp_kvm_init(void)
+{
+	clock_off_gpa = slow_virt_to_phys(&clock_off);
+	hv_clock = pvclock_pvti_cpu0_va();
+
+	if (!hv_clock)
+		return -ENODEV;
+
+	kvm_ptp_clock.caps = ptp_kvm_caps;
+
+	kvm_ptp_clock.ptp_clock = ptp_clock_register(&kvm_ptp_clock.caps, NULL);
+
+	if (IS_ERR(kvm_ptp_clock.ptp_clock))
+		return PTR_ERR(kvm_ptp_clock.ptp_clock);
+
+	return 0;
+}
+
+module_init(ptp_kvm_init);
+module_exit(ptp_kvm_exit);
+
+MODULE_AUTHOR("Marcelo Tosatti <mtosatti@redhat.com>");
+MODULE_DESCRIPTION("PTP clock using KVMCLOCK");
+MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 5/5] PTP: add kvm PTP driver (v2)
  2017-01-20 14:51 ` [patch 5/5] PTP: add kvm PTP driver Marcelo Tosatti
@ 2017-01-20 15:03   ` Marcelo Tosatti
  0 siblings, 0 replies; 8+ messages in thread
From: Marcelo Tosatti @ 2017-01-20 15:03 UTC (permalink / raw)
  To: kvm, linux-kernel
  Cc: Paolo Bonzini, Radim Krcmar, Richard Cochran, Miroslav Lichvar


Add a driver with gettime method returning hosts realtime clock.
This allows Chrony to synchronize host and guest clocks with 
high precision (see results below).

chronyc> sources
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
#* PHC0                          0   3   377     4   +162ns[ -683ns] +/-   11ns

To configure Chronyd to use PHC refclock, add the 
following line to its configuration file:

refclock PHC /dev/ptpX poll 3 dpoll -2 offset 0

Where /dev/ptpX is the kvmclock PTP clock.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

---
 drivers/ptp/Kconfig   |   12 +++
 drivers/ptp/Makefile  |    1 
 drivers/ptp/ptp_kvm.c |  177 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 190 insertions(+)

v2: check for kvmclock (Radim)
    initialize global variables before device registration (Radim)
v3: use cross timestamps callback (Paolo, Miroslav, Radim)
v4: remove gettime64 callback (Paolo)
v5: drop useless nsec assignment (Radim)

Index: kvm-ptpdriver/drivers/ptp/Kconfig
===================================================================
--- kvm-ptpdriver.orig/drivers/ptp/Kconfig	2017-01-20 12:48:10.221115884 -0200
+++ kvm-ptpdriver/drivers/ptp/Kconfig	2017-01-20 12:50:35.076496551 -0200
@@ -90,4 +90,16 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called ptp_pch.
 
+config PTP_1588_CLOCK_KVM
+	tristate "KVM virtual PTP clock"
+	depends on PTP_1588_CLOCK
+	depends on KVM_GUEST
+	default y
+	help
+	  This driver adds support for using kvm infrastructure as a PTP
+	  clock. This clock is only useful if you are using KVM guests.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called ptp_kvm.
+
 endmenu
Index: kvm-ptpdriver/drivers/ptp/Makefile
===================================================================
--- kvm-ptpdriver.orig/drivers/ptp/Makefile	2017-01-20 12:48:10.221115884 -0200
+++ kvm-ptpdriver/drivers/ptp/Makefile	2017-01-20 12:50:35.076496551 -0200
@@ -6,3 +6,4 @@
 obj-$(CONFIG_PTP_1588_CLOCK)		+= ptp.o
 obj-$(CONFIG_PTP_1588_CLOCK_IXP46X)	+= ptp_ixp46x.o
 obj-$(CONFIG_PTP_1588_CLOCK_PCH)	+= ptp_pch.o
+obj-$(CONFIG_PTP_1588_CLOCK_KVM)	+= ptp_kvm.o
Index: kvm-ptpdriver/drivers/ptp/ptp_kvm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ kvm-ptpdriver/drivers/ptp/ptp_kvm.c	2017-01-20 12:59:28.176898867 -0200
@@ -0,0 +1,177 @@
+/*
+ * Virtual PTP 1588 clock for use with KVM guests
+ *
+ * Copyright (C) 2017 Red Hat Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <uapi/linux/kvm_para.h>
+#include <asm/kvm_para.h>
+#include <asm/pvclock.h>
+#include <asm/kvmclock.h>
+#include <uapi/asm/kvm_para.h>
+
+#include <linux/ptp_clock_kernel.h>
+
+struct kvm_ptp_clock {
+	struct ptp_clock *ptp_clock;
+	struct ptp_clock_info caps;
+};
+
+DEFINE_SPINLOCK(kvm_ptp_lock);
+
+static struct pvclock_vsyscall_time_info *hv_clock;
+
+static struct kvm_clock_offset clock_off;
+static phys_addr_t clock_off_gpa;
+
+static int ptp_kvm_get_time_fn(ktime_t *device_time,
+			       struct system_counterval_t *system_counter,
+			       void *ctx)
+{
+	unsigned long ret;
+	struct timespec64 tspec;
+	unsigned version;
+	u8 flags;
+	int cpu;
+	struct pvclock_vcpu_time_info *src;
+
+	preempt_disable_notrace();
+	cpu = smp_processor_id();
+	src = &hv_clock[cpu].pvti;
+
+	spin_lock(&kvm_ptp_lock);
+
+	do {
+		/*
+		 * We are using a TSC value read in the hosts
+		 * kvm_hc_clock_pairing handling.
+		 * So any changes to tsc_to_system_mul
+		 * and tsc_shift or any other pvclock
+		 * data invalidate that measurement.
+		 */
+		version = pvclock_read_begin(src);
+
+		ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING,
+				     clock_off_gpa,
+				     KVM_CLOCK_PAIRING_WALLCLOCK);
+		if (ret != 0) {
+			pr_err("clock offset hypercall ret %lu\n", ret);
+			spin_unlock(&kvm_ptp_lock);
+			preempt_enable_notrace();
+			return -EOPNOTSUPP;
+		}
+
+		tspec.tv_sec = clock_off.sec;
+		tspec.tv_nsec = clock_off.nsec;
+		ret = __pvclock_read_cycles(src, clock_off.tsc);
+		flags = src->flags;
+	} while (pvclock_read_retry(src, version));
+
+	preempt_enable_notrace();
+
+	system_counter->cycles = ret;
+	system_counter->cs = &kvm_clock;
+
+	*device_time = timespec_to_ktime(tspec);
+
+	spin_unlock(&kvm_ptp_lock);
+
+	return 0;
+}
+
+static int ptp_kvm_getcrosststamp(struct ptp_clock_info *ptp,
+				  struct system_device_crosststamp *xtstamp)
+{
+	return get_device_system_crosststamp(ptp_kvm_get_time_fn, NULL,
+					     NULL, xtstamp);
+}
+
+/*
+ * PTP clock operations
+ */
+
+static int ptp_kvm_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	return -EOPNOTSUPP;
+}
+
+static int ptp_kvm_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	return -EOPNOTSUPP;
+}
+
+static int ptp_kvm_settime(struct ptp_clock_info *ptp,
+			   const struct timespec64 *ts)
+{
+	return -EOPNOTSUPP;
+}
+
+static int ptp_kvm_enable(struct ptp_clock_info *ptp,
+			  struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info ptp_kvm_caps = {
+	.owner		= THIS_MODULE,
+	.name		= "KVM virtual PTP",
+	.max_adj	= 0,
+	.n_ext_ts	= 0,
+	.n_pins		= 0,
+	.pps		= 0,
+	.adjfreq	= ptp_kvm_adjfreq,
+	.adjtime	= ptp_kvm_adjtime,
+	.gettime64	= NULL,
+	.settime64	= ptp_kvm_settime,
+	.enable		= ptp_kvm_enable,
+	.getcrosststamp = ptp_kvm_getcrosststamp,
+};
+
+/* module operations */
+
+static struct kvm_ptp_clock kvm_ptp_clock;
+
+static void __exit ptp_kvm_exit(void)
+{
+	ptp_clock_unregister(kvm_ptp_clock.ptp_clock);
+}
+
+static int __init ptp_kvm_init(void)
+{
+	clock_off_gpa = slow_virt_to_phys(&clock_off);
+	hv_clock = pvclock_pvti_cpu0_va();
+
+	if (!hv_clock)
+		return -ENODEV;
+
+	kvm_ptp_clock.caps = ptp_kvm_caps;
+
+	kvm_ptp_clock.ptp_clock = ptp_clock_register(&kvm_ptp_clock.caps, NULL);
+
+	if (IS_ERR(kvm_ptp_clock.ptp_clock))
+		return PTR_ERR(kvm_ptp_clock.ptp_clock);
+
+	return 0;
+}
+
+module_init(ptp_kvm_init);
+module_exit(ptp_kvm_exit);
+
+MODULE_AUTHOR("Marcelo Tosatti <mtosatti@redhat.com>");
+MODULE_DESCRIPTION("PTP clock using KVMCLOCK");
+MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-01-20 15:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-20 14:51 [patch 0/5] KVM virtual PTP driver (v4) Marcelo Tosatti
2017-01-20 14:51 ` [patch 1/5] KVM: x86: provide realtime host clock via vsyscall notifiers Marcelo Tosatti
2017-01-20 14:51 ` [patch 2/5] KVM: x86: add KVM_HC_CLOCK_OFFSET hypercall Marcelo Tosatti
2017-01-20 14:51 ` [patch 3/5] kvmclock: export kvmclock clocksource pointer Marcelo Tosatti
2017-01-20 14:51 ` [patch 4/5] PTP: add PTP_SYS_OFFSET emulation via cross timestamps infrastructure Marcelo Tosatti
2017-01-20 14:51 ` [patch 5/5] PTP: add kvm PTP driver Marcelo Tosatti
2017-01-20 15:03   ` [patch 5/5] PTP: add kvm PTP driver (v2) Marcelo Tosatti
  -- strict thread matches above, loose matches on Subject: below --
2017-01-20 12:20 [patch 0/5] KVM virtual PTP driver (v3) Marcelo Tosatti
2017-01-20 12:20 ` [patch 1/5] KVM: x86: provide realtime host clock via vsyscall notifiers Marcelo Tosatti

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.