This is the backport of commit 867cefb4cb1012 ("xen: Fix x86 sched_clock() interface for xen") for stable 4.14 kernel. This series includes the upstream patches said commit depends on.
Juergen Gross (6): ptp_kvm: probe for kvm guest availability x86/pvclock: add setter for pvclock_pvti_cpu0_va x86/xen/time: set pvclock flags on xen_time_init() x86/xen/time: setup vcpu 0 time info page x86/xen/time: Output xen sched_clock time from 0 xen: Fix x86 sched_clock() interface for xen
arch/x86/entry/vdso/vma.c | 2 +- arch/x86/include/asm/pvclock.h | 19 ++++--- arch/x86/kernel/kvmclock.c | 7 +-- arch/x86/kernel/pvclock.c | 14 +++++ arch/x86/xen/suspend.c | 4 ++ arch/x86/xen/time.c | 118 ++++++++++++++++++++++++++++++++++++++- arch/x86/xen/xen-ops.h | 2 + drivers/ptp/ptp_kvm.c | 5 +- drivers/xen/events/events_base.c | 2 +- include/xen/interface/vcpu.h | 42 ++++++++++++++ 10 files changed, 194 insertions(+), 21 deletions(-)
In the event of moving pvclock_pvti_cpu0_va() definition to common pvclock code, this function would return a value on non KVM guests. Later on this would fail with a GPF on ptp_kvm_init when running on a Xen guest. Therefore, ptp_kvm_init() should check whether it is running in a KVM guest.
Signed-off-by: Joao Martins joao.m.martins@oracle.com Acked-by: Radim Krčmář rkrcmar@redhat.com Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com Signed-off-by: Juergen Gross jgross@suse.com --- This is upstream commit 001f60e1f662a6dee1630a2915401aaf5959d479. Needed for upstream commit 867cefb4cb1012f42cada1c7d1f35ac8dd276071. --- drivers/ptp/ptp_kvm.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/ptp/ptp_kvm.c b/drivers/ptp/ptp_kvm.c index 2b1b212c219e..e04d7b2ecb3a 100644 --- a/drivers/ptp/ptp_kvm.c +++ b/drivers/ptp/ptp_kvm.c @@ -178,6 +178,9 @@ static int __init ptp_kvm_init(void) { long ret;
+ if (!kvm_para_available()) + return -ENODEV; + clock_pair_gpa = slow_virt_to_phys(&clock_pair); hv_clock = pvclock_pvti_cpu0_va();
On Wed, Jan 23, 2019 at 12:56:31PM +0100, Juergen Gross wrote:
In the event of moving pvclock_pvti_cpu0_va() definition to common pvclock code, this function would return a value on non KVM guests. Later on this would fail with a GPF on ptp_kvm_init when running on a Xen guest. Therefore, ptp_kvm_init() should check whether it is running in a KVM guest.
Signed-off-by: Joao Martins joao.m.martins@oracle.com Acked-by: Radim Krčmář rkrcmar@redhat.com Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com Signed-off-by: Juergen Gross jgross@suse.com
This is upstream commit 001f60e1f662a6dee1630a2915401aaf5959d479. Needed for upstream commit 867cefb4cb1012f42cada1c7d1f35ac8dd276071.
drivers/ptp/ptp_kvm.c | 3 +++ 1 file changed, 3 insertions(+)
You lost the original authorship of all of these patches :(
I'll go dig it up, be more careful next time...
greg k-h
Right now there is only a pvclock_pvti_cpu0_va() which is defined on kvmclock since:
commit dac16fba6fc5 ("x86/vdso: Get pvclock data from the vvar VMA instead of the fixmap")
The only user of this interface so far is kvm. This commit adds a setter function for the pvti page and moves pvclock_pvti_cpu0_va to pvclock, which is a more generic place to have it; and would allow other PV clocksources to use it, such as Xen.
While moving pvclock_pvti_cpu0_va into pvclock, rename also this function to pvclock_get_pvti_cpu0_va (including its call sites) to be symmetric with the setter (pvclock_set_pvti_cpu0_va).
Signed-off-by: Joao Martins joao.m.martins@oracle.com Acked-by: Andy Lutomirski luto@kernel.org Acked-by: Paolo Bonzini pbonzini@redhat.com Acked-by: Thomas Gleixner tglx@linutronix.de Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com Signed-off-by: Juergen Gross jgross@suse.com --- This is upstream commit 9f08890ab906abaf9d4c1bad8111755cbd302260. Needed for upstream commit 867cefb4cb1012f42cada1c7d1f35ac8dd276071. --- arch/x86/entry/vdso/vma.c | 2 +- arch/x86/include/asm/pvclock.h | 19 ++++++++++--------- arch/x86/kernel/kvmclock.c | 7 +------ arch/x86/kernel/pvclock.c | 14 ++++++++++++++ drivers/ptp/ptp_kvm.c | 2 +- 5 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 1911310959f8..a77fd3c8d824 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -112,7 +112,7 @@ static int vvar_fault(const struct vm_special_mapping *sm, __pa_symbol(&__vvar_page) >> PAGE_SHIFT); } else if (sym_offset == image->sym_pvclock_page) { struct pvclock_vsyscall_time_info *pvti = - pvclock_pvti_cpu0_va(); + pvclock_get_pvti_cpu0_va(); if (pvti && vclock_was_used(VCLOCK_PVCLOCK)) { ret = vm_insert_pfn( vma, diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h index 3e4ed8fb5f91..a7471dcd2205 100644 --- a/arch/x86/include/asm/pvclock.h +++ b/arch/x86/include/asm/pvclock.h @@ -5,15 +5,6 @@ #include <linux/clocksource.h> #include <asm/pvclock-abi.h>
-#ifdef CONFIG_KVM_GUEST -extern struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void); -#else -static inline struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void) -{ - return NULL; -} -#endif - /* some helper functions for xen and kvm pv clock sources */ u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src); u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src); @@ -102,4 +93,14 @@ struct pvclock_vsyscall_time_info {
#define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
+#ifdef CONFIG_PARAVIRT_CLOCK +void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti); +struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void); +#else +static inline struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void) +{ + return NULL; +} +#endif + #endif /* _ASM_X86_PVCLOCK_H */ diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index 48703d430a2f..08806d64eacd 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -47,12 +47,6 @@ early_param("no-kvmclock", parse_no_kvmclock); static struct pvclock_vsyscall_time_info *hv_clock; static struct pvclock_wall_clock wall_clock;
-struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void) -{ - return hv_clock; -} -EXPORT_SYMBOL_GPL(pvclock_pvti_cpu0_va); - /* * The wallclock is the time of day when we booted. Since then, some time may * have elapsed since the hypervisor wrote the data. So we try to account for @@ -335,6 +329,7 @@ int __init kvm_setup_vsyscall_timeinfo(void) return 1; }
+ pvclock_set_pvti_cpu0_va(hv_clock); put_cpu();
kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK; diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c index 5c3f6d6a5078..761f6af6efa5 100644 --- a/arch/x86/kernel/pvclock.c +++ b/arch/x86/kernel/pvclock.c @@ -25,8 +25,10 @@
#include <asm/fixmap.h> #include <asm/pvclock.h> +#include <asm/vgtod.h>
static u8 valid_flags __read_mostly = 0; +static struct pvclock_vsyscall_time_info *pvti_cpu0_va __read_mostly;
void pvclock_set_flags(u8 flags) { @@ -144,3 +146,15 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
set_normalized_timespec(ts, now.tv_sec, now.tv_nsec); } + +void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti) +{ + WARN_ON(vclock_was_used(VCLOCK_PVCLOCK)); + pvti_cpu0_va = pvti; +} + +struct pvclock_vsyscall_time_info *pvclock_get_pvti_cpu0_va(void) +{ + return pvti_cpu0_va; +} +EXPORT_SYMBOL_GPL(pvclock_get_pvti_cpu0_va); diff --git a/drivers/ptp/ptp_kvm.c b/drivers/ptp/ptp_kvm.c index e04d7b2ecb3a..c67dd11e08b1 100644 --- a/drivers/ptp/ptp_kvm.c +++ b/drivers/ptp/ptp_kvm.c @@ -182,7 +182,7 @@ static int __init ptp_kvm_init(void) return -ENODEV;
clock_pair_gpa = slow_virt_to_phys(&clock_pair); - hv_clock = pvclock_pvti_cpu0_va(); + hv_clock = pvclock_get_pvti_cpu0_va();
if (!hv_clock) return -ENODEV;
Specifically check for PVCLOCK_TSC_STABLE_BIT and if this bit is set, then set it too on pvclock flags. This allows Xen clocksource to use it and thus speeding up xen_clocksource_read() callers (i.e. sched_clock())
Signed-off-by: Joao Martins joao.m.martins@oracle.com Reviewed-by: Boris Ostrovsky boris.ostrovsky@oracle.com Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com Signed-off-by: Juergen Gross jgross@suse.com --- This is upstream commit b888808093113ae7d63d213272d01fea4b8329ed. Needed for upstream commit 867cefb4cb1012f42cada1c7d1f35ac8dd276071. --- arch/x86/xen/time.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 80c2a4bdf230..5687be6f5ca5 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -373,6 +373,7 @@ static const struct pv_time_ops xen_time_ops __initconst = {
static void __init xen_time_init(void) { + struct pvclock_vcpu_time_info *pvti; int cpu = smp_processor_id(); struct timespec tp;
@@ -396,6 +397,14 @@ static void __init xen_time_init(void)
setup_force_cpu_cap(X86_FEATURE_TSC);
+ /* + * We check ahead on the primary time info if this + * bit is supported hence speeding up Xen clocksource. + */ + pvti = &__this_cpu_read(xen_vcpu)->time; + if (pvti->flags & PVCLOCK_TSC_STABLE_BIT) + pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); + xen_setup_runstate_info(cpu); xen_setup_timer(cpu); xen_setup_cpu_clockevents();
In order to support pvclock vdso on xen we need to setup the time info page for vcpu 0 and register the page with Xen using the VCPUOP_register_vcpu_time_memory_area hypercall. This hypercall will also forcefully update the pvti which will set some of the necessary flags for vdso. Afterwards we check if it supports the PVCLOCK_TSC_STABLE_BIT flag which is mandatory for having vdso/vsyscall support. And if so, it will set the cpu 0 pvti that will be later on used when mapping the vdso image.
The xen headers are also updated to include the new hypercall for registering the secondary vcpu_time_info struct.
Signed-off-by: Joao Martins joao.m.martins@oracle.com Reviewed-by: Juergen Gross jgross@suse.com Reviewed-by: Boris Ostrovsky boris.ostrovsky@oracle.com Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com Signed-off-by: Juergen Gross jgross@suse.com --- This is upstream commit 2229f70b5bbb025e1394b61007938a68060afbfb. Needed for upstream commit 867cefb4cb1012f42cada1c7d1f35ac8dd276071. --- arch/x86/xen/suspend.c | 4 ++ arch/x86/xen/time.c | 90 +++++++++++++++++++++++++++++++++++++++++++- arch/x86/xen/xen-ops.h | 2 + include/xen/interface/vcpu.h | 42 +++++++++++++++++++++ 4 files changed, 137 insertions(+), 1 deletion(-)
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c index 3e3a58ea669e..1d83152c761b 100644 --- a/arch/x86/xen/suspend.c +++ b/arch/x86/xen/suspend.c @@ -22,6 +22,8 @@ static DEFINE_PER_CPU(u64, spec_ctrl);
void xen_arch_pre_suspend(void) { + xen_save_time_memory_area(); + if (xen_pv_domain()) xen_pv_pre_suspend(); } @@ -32,6 +34,8 @@ void xen_arch_post_suspend(int cancelled) xen_pv_post_suspend(cancelled); else xen_hvm_post_suspend(cancelled); + + xen_restore_time_memory_area(); }
static void xen_vcpu_notify_restore(void *data) diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 5687be6f5ca5..efa81e736f43 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -371,6 +371,92 @@ static const struct pv_time_ops xen_time_ops __initconst = { .steal_clock = xen_steal_clock, };
+static struct pvclock_vsyscall_time_info *xen_clock __read_mostly; + +void xen_save_time_memory_area(void) +{ + struct vcpu_register_time_memory_area t; + int ret; + + if (!xen_clock) + return; + + t.addr.v = NULL; + + ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t); + if (ret != 0) + pr_notice("Cannot save secondary vcpu_time_info (err %d)", + ret); + else + clear_page(xen_clock); +} + +void xen_restore_time_memory_area(void) +{ + struct vcpu_register_time_memory_area t; + int ret; + + if (!xen_clock) + return; + + t.addr.v = &xen_clock->pvti; + + ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t); + + /* + * We don't disable VCLOCK_PVCLOCK entirely if it fails to register the + * secondary time info with Xen or if we migrated to a host without the + * necessary flags. On both of these cases what happens is either + * process seeing a zeroed out pvti or seeing no PVCLOCK_TSC_STABLE_BIT + * bit set. Userspace checks the latter and if 0, it discards the data + * in pvti and fallbacks to a system call for a reliable timestamp. + */ + if (ret != 0) + pr_notice("Cannot restore secondary vcpu_time_info (err %d)", + ret); +} + +static void xen_setup_vsyscall_time_info(void) +{ + struct vcpu_register_time_memory_area t; + struct pvclock_vsyscall_time_info *ti; + int ret; + + ti = (struct pvclock_vsyscall_time_info *)get_zeroed_page(GFP_KERNEL); + if (!ti) + return; + + t.addr.v = &ti->pvti; + + ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t); + if (ret) { + pr_notice("xen: VCLOCK_PVCLOCK not supported (err %d)\n", ret); + free_page((unsigned long)ti); + return; + } + + /* + * If primary time info had this bit set, secondary should too since + * it's the same data on both just different memory regions. But we + * still check it in case hypervisor is buggy. + */ + if (!(ti->pvti.flags & PVCLOCK_TSC_STABLE_BIT)) { + t.addr.v = NULL; + ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, + 0, &t); + if (!ret) + free_page((unsigned long)ti); + + pr_notice("xen: VCLOCK_PVCLOCK not supported (tsc unstable)\n"); + return; + } + + xen_clock = ti; + pvclock_set_pvti_cpu0_va(xen_clock); + + xen_clocksource.archdata.vclock_mode = VCLOCK_PVCLOCK; +} + static void __init xen_time_init(void) { struct pvclock_vcpu_time_info *pvti; @@ -402,8 +488,10 @@ static void __init xen_time_init(void) * bit is supported hence speeding up Xen clocksource. */ pvti = &__this_cpu_read(xen_vcpu)->time; - if (pvti->flags & PVCLOCK_TSC_STABLE_BIT) + if (pvti->flags & PVCLOCK_TSC_STABLE_BIT) { pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); + xen_setup_vsyscall_time_info(); + }
xen_setup_runstate_info(cpu); xen_setup_timer(cpu); diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index f377e1820c6c..75011b80660f 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -70,6 +70,8 @@ void xen_setup_runstate_info(int cpu); void xen_teardown_timer(int cpu); u64 xen_clocksource_read(void); void xen_setup_cpu_clockevents(void); +void xen_save_time_memory_area(void); +void xen_restore_time_memory_area(void); void __init xen_init_time_ops(void); void __init xen_hvm_init_time_ops(void);
diff --git a/include/xen/interface/vcpu.h b/include/xen/interface/vcpu.h index 98188c87f5c1..504c71601511 100644 --- a/include/xen/interface/vcpu.h +++ b/include/xen/interface/vcpu.h @@ -178,4 +178,46 @@ DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info);
/* Send an NMI to the specified VCPU. @extra_arg == NULL. */ #define VCPUOP_send_nmi 11 + +/* + * Get the physical ID information for a pinned vcpu's underlying physical + * processor. The physical ID informmation is architecture-specific. + * On x86: id[31:0]=apic_id, id[63:32]=acpi_id. + * This command returns -EINVAL if it is not a valid operation for this VCPU. + */ +#define VCPUOP_get_physid 12 /* arg == vcpu_get_physid_t */ +struct vcpu_get_physid { + uint64_t phys_id; +}; +DEFINE_GUEST_HANDLE_STRUCT(vcpu_get_physid); +#define xen_vcpu_physid_to_x86_apicid(physid) ((uint32_t)(physid)) +#define xen_vcpu_physid_to_x86_acpiid(physid) ((uint32_t)((physid) >> 32)) + +/* + * Register a memory location to get a secondary copy of the vcpu time + * parameters. The master copy still exists as part of the vcpu shared + * memory area, and this secondary copy is updated whenever the master copy + * is updated (and using the same versioning scheme for synchronisation). + * + * The intent is that this copy may be mapped (RO) into userspace so + * that usermode can compute system time using the time info and the + * tsc. Usermode will see an array of vcpu_time_info structures, one + * for each vcpu, and choose the right one by an existing mechanism + * which allows it to get the current vcpu number (such as via a + * segment limit). It can then apply the normal algorithm to compute + * system time from the tsc. + * + * @extra_arg == pointer to vcpu_register_time_info_memory_area structure. + */ +#define VCPUOP_register_vcpu_time_memory_area 13 +DEFINE_GUEST_HANDLE_STRUCT(vcpu_time_info); +struct vcpu_register_time_memory_area { + union { + GUEST_HANDLE(vcpu_time_info) h; + struct pvclock_vcpu_time_info *v; + uint64_t p; + } addr; +}; +DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_time_memory_area); + #endif /* __XEN_PUBLIC_VCPU_H__ */
It is expected for sched_clock() to output data from 0, when system boots.
Add an offset xen_sched_clock_offset (similarly how it is done in other hypervisors i.e. kvm_sched_clock_offset) to count sched_clock() from 0, when time is first initialized.
Signed-off-by: Pavel Tatashin pasha.tatashin@oracle.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Signed-off-by: Juergen Gross jgross@suse.com --- This is upstream commit 38669ba205d178d2d38bfd194a196d65a44d5af2. Needed for upstream commit 867cefb4cb1012f42cada1c7d1f35ac8dd276071. --- arch/x86/xen/time.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index efa81e736f43..8c0b2beb3f46 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -31,6 +31,8 @@ /* Xen may fire a timer up to this many ns early */ #define TIMER_SLOP 100000
+static u64 xen_sched_clock_offset __read_mostly; + /* Get the TSC speed from Xen */ static unsigned long xen_tsc_khz(void) { @@ -57,6 +59,11 @@ static u64 xen_clocksource_get_cycles(struct clocksource *cs) return xen_clocksource_read(); }
+static u64 xen_sched_clock(void) +{ + return xen_clocksource_read() - xen_sched_clock_offset; +} + static void xen_read_wallclock(struct timespec *ts) { struct shared_info *s = HYPERVISOR_shared_info; @@ -367,7 +374,7 @@ void xen_timer_resume(void) }
static const struct pv_time_ops xen_time_ops __initconst = { - .sched_clock = xen_clocksource_read, + .sched_clock = xen_sched_clock, .steal_clock = xen_steal_clock, };
@@ -505,6 +512,7 @@ static void __init xen_time_init(void)
void __ref xen_init_time_ops(void) { + xen_sched_clock_offset = xen_clocksource_read(); pv_time_ops = xen_time_ops;
x86_init.timers.timer_init = xen_time_init; @@ -547,6 +555,7 @@ void __init xen_hvm_init_time_ops(void) return; }
+ xen_sched_clock_offset = xen_clocksource_read(); pv_time_ops = xen_time_ops; x86_init.timers.setup_percpu_clockev = xen_time_init; x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents;
Commit f94c8d11699759 ("sched/clock, x86/tsc: Rework the x86 'unstable' sched_clock() interface") broke Xen guest time handling across migration:
[ 187.249951] Freezing user space processes ... (elapsed 0.001 seconds) done. [ 187.251137] OOM killer disabled. [ 187.251137] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done. [ 187.252299] suspending xenstore... [ 187.266987] xen:grant_table: Grant tables using version 1 layout [18446743811.706476] OOM killer enabled. [18446743811.706478] Restarting tasks ... done. [18446743811.720505] Setting capacity to 16777216
Fix that by setting xen_sched_clock_offset at resume time to ensure a monotonic clock value.
[boris: replaced pr_info() with pr_info_once() in xen_callback_vector() to avoid printing with incorrect timestamp during resume (as we haven't re-adjusted the clock yet)]
Fixes: f94c8d11699759 ("sched/clock, x86/tsc: Rework the x86 'unstable' sched_clock() interface") Cc: stable@vger.kernel.org # 4.11 Reported-by: Hans van Kranenburg hans.van.kranenburg@mendix.com Signed-off-by: Juergen Gross jgross@suse.com Tested-by: Hans van Kranenburg hans.van.kranenburg@mendix.com Signed-off-by: Boris Ostrovsky boris.ostrovsky@oracle.com Signed-off-by: Juergen Gross jgross@suse.com --- This is upstream commit 867cefb4cb1012f42cada1c7d1f35ac8dd276071. --- arch/x86/xen/time.c | 12 +++++++++--- drivers/xen/events/events_base.c | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 8c0b2beb3f46..03706331f567 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -361,8 +361,6 @@ void xen_timer_resume(void) { int cpu;
- pvclock_resume(); - if (xen_clockevent != &xen_vcpuop_clockevent) return;
@@ -379,12 +377,15 @@ static const struct pv_time_ops xen_time_ops __initconst = { };
static struct pvclock_vsyscall_time_info *xen_clock __read_mostly; +static u64 xen_clock_value_saved;
void xen_save_time_memory_area(void) { struct vcpu_register_time_memory_area t; int ret;
+ xen_clock_value_saved = xen_clocksource_read() - xen_sched_clock_offset; + if (!xen_clock) return;
@@ -404,7 +405,7 @@ void xen_restore_time_memory_area(void) int ret;
if (!xen_clock) - return; + goto out;
t.addr.v = &xen_clock->pvti;
@@ -421,6 +422,11 @@ void xen_restore_time_memory_area(void) if (ret != 0) pr_notice("Cannot restore secondary vcpu_time_info (err %d)", ret); + +out: + /* Need pvclock_resume() before using xen_clocksource_read(). */ + pvclock_resume(); + xen_sched_clock_offset = xen_clocksource_read() - xen_clock_value_saved; }
static void xen_setup_vsyscall_time_info(void) diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index e6c1934734b7..fe1f16351f94 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -1650,7 +1650,7 @@ void xen_callback_vector(void) xen_have_vector_callback = 0; return; } - pr_info("Xen HVM callback vector for event delivery is enabled\n"); + pr_info_once("Xen HVM callback vector for event delivery is enabled\n"); alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, xen_hvm_callback_vector); }
On Wed, Jan 23, 2019 at 12:56:30PM +0100, Juergen Gross wrote:
This is the backport of commit 867cefb4cb1012 ("xen: Fix x86 sched_clock() interface for xen") for stable 4.14 kernel. This series includes the upstream patches said commit depends on.
Juergen Gross (6): ptp_kvm: probe for kvm guest availability x86/pvclock: add setter for pvclock_pvti_cpu0_va x86/xen/time: set pvclock flags on xen_time_init() x86/xen/time: setup vcpu 0 time info page x86/xen/time: Output xen sched_clock time from 0 xen: Fix x86 sched_clock() interface for xen
Again, you didn't author all of these :(
now queued up.
greg k-h
linux-stable-mirror@lists.linaro.org