Re: [PATCH v4 07/15] x86/paravirt: switch time pvops functions to use static_call()
On Wed, Jan 20, 2021 at 02:55:47PM +0100, Juergen Gross wrote: > The time pvops functions are the only ones left which might be > used in 32-bit mode and which return a 64-bit value. > > Switch them to use the static_call() mechanism instead of pvops, as > this allows quite some simplification of the pvops implementation. > > Signed-off-by: Juergen Gross > --- > V4: > - drop paravirt_time.h again > - don't move Hyper-V code (Michael Kelley) > --- > arch/x86/Kconfig | 1 + > arch/x86/include/asm/mshyperv.h | 2 +- > arch/x86/include/asm/paravirt.h | 17 ++--- > arch/x86/include/asm/paravirt_types.h | 6 -- > arch/x86/kernel/cpu/vmware.c | 5 +++-- > arch/x86/kernel/kvm.c | 2 +- > arch/x86/kernel/kvmclock.c| 2 +- > arch/x86/kernel/paravirt.c| 16 > arch/x86/kernel/tsc.c | 2 +- > arch/x86/xen/time.c | 11 --- > drivers/clocksource/hyperv_timer.c| 5 +++-- > drivers/xen/time.c| 2 +- > 12 files changed, 42 insertions(+), 29 deletions(-) > > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig > index 21f851179ff0..7ccd4a80788c 100644 > --- a/arch/x86/Kconfig > +++ b/arch/x86/Kconfig > @@ -771,6 +771,7 @@ if HYPERVISOR_GUEST > > config PARAVIRT > bool "Enable paravirtualization code" > + depends on HAVE_STATIC_CALL > help > This changes the kernel so it can modify itself when it is run > under a hypervisor, potentially improving performance significantly > diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h > index 30f76b966857..b4ee331d29a7 100644 > --- a/arch/x86/include/asm/mshyperv.h > +++ b/arch/x86/include/asm/mshyperv.h > @@ -63,7 +63,7 @@ typedef int (*hyperv_fill_flush_list_func)( > static __always_inline void hv_setup_sched_clock(void *sched_clock) > { > #ifdef CONFIG_PARAVIRT > - pv_ops.time.sched_clock = sched_clock; > + paravirt_set_sched_clock(sched_clock); > #endif > } > > diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h > index 4abf110e2243..1e45b46fae84 100644 > --- a/arch/x86/include/asm/paravirt.h > +++ b/arch/x86/include/asm/paravirt.h > @@ -15,11 +15,22 @@ > #include > #include > #include > +#include > #include > > -static inline unsigned long long paravirt_sched_clock(void) > +u64 dummy_steal_clock(int cpu); > +u64 dummy_sched_clock(void); > + > +DECLARE_STATIC_CALL(pv_steal_clock, dummy_steal_clock); > +DECLARE_STATIC_CALL(pv_sched_clock, dummy_sched_clock); Did you build this before sending? I'm test-applying this on rc6 + tip/master so I probably am using a different tree so it looks like something has changed in the meantime. -rc6 has a couple of Xen changes which made applying those to need some wiggling in... Maybe you should redo them ontop of tip/master. That is, *if* they're going to eventually go through tip. The diffstat has Xen stuff too so we might need some synchronization here what goes where how... ./arch/x86/include/asm/paravirt.h:24:1: warning: data definition has no type or storage class 24 | DECLARE_STATIC_CALL(pv_steal_clock, dummy_steal_clock); | ^~~ ./arch/x86/include/asm/paravirt.h:24:1: error: type defaults to ‘int’ in declaration of ‘DECLARE_STATIC_CALL’ [-Werror=implicit-int] ./arch/x86/include/asm/paravirt.h:24:1: warning: parameter names (without types) in function declaration ./arch/x86/include/asm/paravirt.h:25:1: warning: data definition has no type or storage class 25 | DECLARE_STATIC_CALL(pv_sched_clock, dummy_sched_clock); | ^~~ ./arch/x86/include/asm/paravirt.h:25:1: error: type defaults to ‘int’ in declaration of ‘DECLARE_STATIC_CALL’ [-Werror=implicit-int] ./arch/x86/include/asm/paravirt.h:25:1: warning: parameter names (without types) in function declaration ./arch/x86/include/asm/paravirt.h: In function ‘paravirt_sched_clock’: ./arch/x86/include/asm/paravirt.h:33:9: error: implicit declaration of function ‘static_call’ [-Werror=implicit-function-declaration] 33 | return static_call(pv_sched_clock)(); | ^~~ ./arch/x86/include/asm/paravirt.h:33:21: error: ‘pv_sched_clock’ undeclared (first use in this function); did you mean ‘dummy_sched_clock’? 33 | return static_call(pv_sched_clock)(); | ^~ | dummy_sched_clock ./arch/x86/include/asm/paravirt.h:33:21: note: each undeclared identifier is reported only once for each function it appears in ./arch/x86/include/asm/paravirt.h: In function ‘paravirt_steal_clock’: ./arch/x86/include/asm/paravirt.h:47:21: error: ‘pv_steal_clock’ undeclared (first use in this function); did you mean ‘dummy_steal_clock’? 47 | return static_call(pv_steal_clock)(cpu); | ^~ | dummy_steal_clock cc1: some
RE: [PATCH v4 07/15] x86/paravirt: switch time pvops functions to use static_call()
From: Juergen Gross Sent: Wednesday, January 20, 2021 5:56 AM > > The time pvops functions are the only ones left which might be > used in 32-bit mode and which return a 64-bit value. > > Switch them to use the static_call() mechanism instead of pvops, as > this allows quite some simplification of the pvops implementation. > > Signed-off-by: Juergen Gross > --- > V4: > - drop paravirt_time.h again > - don't move Hyper-V code (Michael Kelley) > --- > arch/x86/Kconfig | 1 + > arch/x86/include/asm/mshyperv.h | 2 +- > arch/x86/include/asm/paravirt.h | 17 ++--- > arch/x86/include/asm/paravirt_types.h | 6 -- > arch/x86/kernel/cpu/vmware.c | 5 +++-- > arch/x86/kernel/kvm.c | 2 +- > arch/x86/kernel/kvmclock.c| 2 +- > arch/x86/kernel/paravirt.c| 16 > arch/x86/kernel/tsc.c | 2 +- > arch/x86/xen/time.c | 11 --- > drivers/clocksource/hyperv_timer.c| 5 +++-- > drivers/xen/time.c| 2 +- > 12 files changed, 42 insertions(+), 29 deletions(-) > [snip] > diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h > index 30f76b966857..b4ee331d29a7 100644 > --- a/arch/x86/include/asm/mshyperv.h > +++ b/arch/x86/include/asm/mshyperv.h > @@ -63,7 +63,7 @@ typedef int (*hyperv_fill_flush_list_func)( > static __always_inline void hv_setup_sched_clock(void *sched_clock) > { > #ifdef CONFIG_PARAVIRT > - pv_ops.time.sched_clock = sched_clock; > + paravirt_set_sched_clock(sched_clock); > #endif > } > This looks fine. [snip] > diff --git a/drivers/clocksource/hyperv_timer.c > b/drivers/clocksource/hyperv_timer.c > index ba04cb381cd3..bf3bf20bc6bd 100644 > --- a/drivers/clocksource/hyperv_timer.c > +++ b/drivers/clocksource/hyperv_timer.c > @@ -18,6 +18,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -445,7 +446,7 @@ static bool __init hv_init_tsc_clocksource(void) > clocksource_register_hz(_cs_tsc, NSEC_PER_SEC/100); > > hv_sched_clock_offset = hv_read_reference_counter(); > - hv_setup_sched_clock(read_hv_sched_clock_tsc); > + paravirt_set_sched_clock(read_hv_sched_clock_tsc); > > return true; > } > @@ -470,6 +471,6 @@ void __init hv_init_clocksource(void) > clocksource_register_hz(_cs_msr, NSEC_PER_SEC/100); > > hv_sched_clock_offset = hv_read_reference_counter(); > - hv_setup_sched_clock(read_hv_sched_clock_msr); > + static_call_update(pv_sched_clock, read_hv_sched_clock_msr); > } > EXPORT_SYMBOL_GPL(hv_init_clocksource); The changes to hyperv_timer.c aren't needed and shouldn't be there, so as to preserve hyperv_timer.c as architecture neutral. With your update to hv_setup_sched_clock() in mshyperv.h, the original code works correctly. While there are two call sites for hv_setup_sched_clock(), only one is called. And once the sched clock function is set, it is never changed or overridden. Michael ___ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization
[PATCH v4 07/15] x86/paravirt: switch time pvops functions to use static_call()
The time pvops functions are the only ones left which might be used in 32-bit mode and which return a 64-bit value. Switch them to use the static_call() mechanism instead of pvops, as this allows quite some simplification of the pvops implementation. Signed-off-by: Juergen Gross --- V4: - drop paravirt_time.h again - don't move Hyper-V code (Michael Kelley) --- arch/x86/Kconfig | 1 + arch/x86/include/asm/mshyperv.h | 2 +- arch/x86/include/asm/paravirt.h | 17 ++--- arch/x86/include/asm/paravirt_types.h | 6 -- arch/x86/kernel/cpu/vmware.c | 5 +++-- arch/x86/kernel/kvm.c | 2 +- arch/x86/kernel/kvmclock.c| 2 +- arch/x86/kernel/paravirt.c| 16 arch/x86/kernel/tsc.c | 2 +- arch/x86/xen/time.c | 11 --- drivers/clocksource/hyperv_timer.c| 5 +++-- drivers/xen/time.c| 2 +- 12 files changed, 42 insertions(+), 29 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 21f851179ff0..7ccd4a80788c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -771,6 +771,7 @@ if HYPERVISOR_GUEST config PARAVIRT bool "Enable paravirtualization code" + depends on HAVE_STATIC_CALL help This changes the kernel so it can modify itself when it is run under a hypervisor, potentially improving performance significantly diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 30f76b966857..b4ee331d29a7 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -63,7 +63,7 @@ typedef int (*hyperv_fill_flush_list_func)( static __always_inline void hv_setup_sched_clock(void *sched_clock) { #ifdef CONFIG_PARAVIRT - pv_ops.time.sched_clock = sched_clock; + paravirt_set_sched_clock(sched_clock); #endif } diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 4abf110e2243..1e45b46fae84 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -15,11 +15,22 @@ #include #include #include +#include #include -static inline unsigned long long paravirt_sched_clock(void) +u64 dummy_steal_clock(int cpu); +u64 dummy_sched_clock(void); + +DECLARE_STATIC_CALL(pv_steal_clock, dummy_steal_clock); +DECLARE_STATIC_CALL(pv_sched_clock, dummy_sched_clock); + +extern bool paravirt_using_native_sched_clock; + +void paravirt_set_sched_clock(u64 (*func)(void)); + +static inline u64 paravirt_sched_clock(void) { - return PVOP_CALL0(unsigned long long, time.sched_clock); + return static_call(pv_sched_clock)(); } struct static_key; @@ -33,7 +44,7 @@ bool pv_is_native_vcpu_is_preempted(void); static inline u64 paravirt_steal_clock(int cpu) { - return PVOP_CALL1(u64, time.steal_clock, cpu); + return static_call(pv_steal_clock)(cpu); } /* The paravirtualized I/O functions */ diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index de87087d3bde..1fff349e4792 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -95,11 +95,6 @@ struct pv_lazy_ops { } __no_randomize_layout; #endif -struct pv_time_ops { - unsigned long long (*sched_clock)(void); - unsigned long long (*steal_clock)(int cpu); -} __no_randomize_layout; - struct pv_cpu_ops { /* hooks for various privileged instructions */ void (*io_delay)(void); @@ -291,7 +286,6 @@ struct pv_lock_ops { * what to patch. */ struct paravirt_patch_template { struct pv_init_ops init; - struct pv_time_ops time; struct pv_cpu_ops cpu; struct pv_irq_ops irq; struct pv_mmu_ops mmu; diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index c6ede3b3d302..84fb8e3f3d1b 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -336,11 +337,11 @@ static void __init vmware_paravirt_ops_setup(void) vmware_cyc2ns_setup(); if (vmw_sched_clock) - pv_ops.time.sched_clock = vmware_sched_clock; + paravirt_set_sched_clock(vmware_sched_clock); if (vmware_is_stealclock_available()) { has_steal_clock = true; - pv_ops.time.steal_clock = vmware_steal_clock; + static_call_update(pv_steal_clock, vmware_steal_clock); /* We use reboot notifier only to disable steal clock */ register_reboot_notifier(_pv_reboot_nb); diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 5e78e01ca3b4..351ba99f6009 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -650,7 +650,7 @@ static void __init kvm_guest_init(void) if
[PATCH v4 07/15] x86/paravirt: switch time pvops functions to use static_call()
The time pvops functions are the only ones left which might be used in 32-bit mode and which return a 64-bit value. Switch them to use the static_call() mechanism instead of pvops, as this allows quite some simplification of the pvops implementation. Signed-off-by: Juergen Gross --- V4: - drop paravirt_time.h again - don't move Hyper-V code (Michael Kelley) --- arch/x86/Kconfig | 1 + arch/x86/include/asm/mshyperv.h | 2 +- arch/x86/include/asm/paravirt.h | 17 ++--- arch/x86/include/asm/paravirt_types.h | 6 -- arch/x86/kernel/cpu/vmware.c | 5 +++-- arch/x86/kernel/kvm.c | 2 +- arch/x86/kernel/kvmclock.c| 2 +- arch/x86/kernel/paravirt.c| 16 arch/x86/kernel/tsc.c | 2 +- arch/x86/xen/time.c | 11 --- drivers/clocksource/hyperv_timer.c| 5 +++-- drivers/xen/time.c| 2 +- 12 files changed, 42 insertions(+), 29 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 21f851179ff0..7ccd4a80788c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -771,6 +771,7 @@ if HYPERVISOR_GUEST config PARAVIRT bool "Enable paravirtualization code" + depends on HAVE_STATIC_CALL help This changes the kernel so it can modify itself when it is run under a hypervisor, potentially improving performance significantly diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 30f76b966857..b4ee331d29a7 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -63,7 +63,7 @@ typedef int (*hyperv_fill_flush_list_func)( static __always_inline void hv_setup_sched_clock(void *sched_clock) { #ifdef CONFIG_PARAVIRT - pv_ops.time.sched_clock = sched_clock; + paravirt_set_sched_clock(sched_clock); #endif } diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 4abf110e2243..1e45b46fae84 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -15,11 +15,22 @@ #include #include #include +#include #include -static inline unsigned long long paravirt_sched_clock(void) +u64 dummy_steal_clock(int cpu); +u64 dummy_sched_clock(void); + +DECLARE_STATIC_CALL(pv_steal_clock, dummy_steal_clock); +DECLARE_STATIC_CALL(pv_sched_clock, dummy_sched_clock); + +extern bool paravirt_using_native_sched_clock; + +void paravirt_set_sched_clock(u64 (*func)(void)); + +static inline u64 paravirt_sched_clock(void) { - return PVOP_CALL0(unsigned long long, time.sched_clock); + return static_call(pv_sched_clock)(); } struct static_key; @@ -33,7 +44,7 @@ bool pv_is_native_vcpu_is_preempted(void); static inline u64 paravirt_steal_clock(int cpu) { - return PVOP_CALL1(u64, time.steal_clock, cpu); + return static_call(pv_steal_clock)(cpu); } /* The paravirtualized I/O functions */ diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index de87087d3bde..1fff349e4792 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -95,11 +95,6 @@ struct pv_lazy_ops { } __no_randomize_layout; #endif -struct pv_time_ops { - unsigned long long (*sched_clock)(void); - unsigned long long (*steal_clock)(int cpu); -} __no_randomize_layout; - struct pv_cpu_ops { /* hooks for various privileged instructions */ void (*io_delay)(void); @@ -291,7 +286,6 @@ struct pv_lock_ops { * what to patch. */ struct paravirt_patch_template { struct pv_init_ops init; - struct pv_time_ops time; struct pv_cpu_ops cpu; struct pv_irq_ops irq; struct pv_mmu_ops mmu; diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index c6ede3b3d302..84fb8e3f3d1b 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -336,11 +337,11 @@ static void __init vmware_paravirt_ops_setup(void) vmware_cyc2ns_setup(); if (vmw_sched_clock) - pv_ops.time.sched_clock = vmware_sched_clock; + paravirt_set_sched_clock(vmware_sched_clock); if (vmware_is_stealclock_available()) { has_steal_clock = true; - pv_ops.time.steal_clock = vmware_steal_clock; + static_call_update(pv_steal_clock, vmware_steal_clock); /* We use reboot notifier only to disable steal clock */ register_reboot_notifier(_pv_reboot_nb); diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 5e78e01ca3b4..351ba99f6009 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -650,7 +650,7 @@ static void __init kvm_guest_init(void) if