Messages in this thread | | | From | Michael Kelley <> | Subject | RE: [RFC][PATCH] objtool,x86_64,paravirt: Add pv_ops[] support | Date | Mon, 3 Aug 2020 15:18:57 +0000 |
| |
From: peterz@infradead.org Sent: Monday, August 3, 2020 7:33 AM > > Thomas wanted paramuck vs noinstr, here goes. Very rough, very nasty, > mostly works. > > It requires call sites are the normal indirect call, and not mangled > retpoison (slow_down_io() had those), it also requires pv_ops[] > assignments are single instructions and not laundered through some > pointless intermediate helper (hyperv). > > It doesn't warn when you get any of that wrong. > > But if you have it all lined up right, it will warn about noinstr > violations due to paramuck: > > $ ./objtool check -afl ../../defconfig-build/vmlinux.o > ../../defconfig-build/vmlinux.o: warning: objtool: xen_pv_evtchn_do_upcall()+0x69: return > with instrumentation enabled > ../../defconfig-build/vmlinux.o: warning: objtool: exc_double_fault()+0x15: call pv_ops[48] > from noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: pv_op[48]: xen_read_cr2 > ../../defconfig-build/vmlinux.o: warning: objtool: exc_double_fault()+0x15: call to > {dynamic}() leaves .noinstr.text section > ../../defconfig-build/vmlinux.o: warning: objtool: exc_debug()+0x29: call pv_ops[4] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: pv_op[4]: native_get_debugreg > ../../defconfig-build/vmlinux.o: warning: objtool: exc_debug()+0x29: call to {dynamic}() > leaves .noinstr.text section > ../../defconfig-build/vmlinux.o: warning: objtool: noist_exc_debug()+0x26: call pv_ops[4] > from noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: pv_op[4]: native_get_debugreg > ../../defconfig-build/vmlinux.o: warning: objtool: noist_exc_debug()+0x26: call to > {dynamic}() leaves .noinstr.text section > ../../defconfig-build/vmlinux.o: warning: objtool: exc_nmi()+0x3a: call pv_ops[48] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: pv_op[48]: xen_read_cr2 > ../../defconfig-build/vmlinux.o: warning: objtool: exc_nmi()+0x3a: call to {dynamic}() leaves > .noinstr.text section > ../../defconfig-build/vmlinux.o: warning: objtool: mce_setup()+0x80: call pv_ops[25] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: pv_op[25]: native_cpuid > ../../defconfig-build/vmlinux.o: warning: objtool: mce_setup()+0x80: call to {dynamic}() > leaves .noinstr.text section > ../../defconfig-build/vmlinux.o: warning: objtool: do_machine_check()+0x46: call to > mce_rdmsrl() leaves .noinstr.text section > ../../defconfig-build/vmlinux.o: warning: objtool: exc_machine_check()+0x24: call > pv_ops[4] from noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: pv_op[4]: native_get_debugreg > ../../defconfig-build/vmlinux.o: warning: objtool: exc_machine_check()+0x24: call to > {dynamic}() leaves .noinstr.text section > ../../defconfig-build/vmlinux.o: warning: objtool: noist_exc_machine_check()+0x24: call > pv_ops[4] from noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: pv_op[4]: native_get_debugreg > ../../defconfig-build/vmlinux.o: warning: objtool: noist_exc_machine_check()+0x24: call to > {dynamic}() leaves .noinstr.text section > ../../defconfig-build/vmlinux.o: warning: objtool: exc_page_fault()+0xe: call pv_ops[48] > from noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: pv_op[48]: xen_read_cr2 > ../../defconfig-build/vmlinux.o: warning: objtool: exc_page_fault()+0xe: call to {dynamic}() > leaves .noinstr.text section > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0xf17: call pv_ops[32] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0x12f1: call pv_ops[35] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0xf5a: call pv_ops[32] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0x1002: call pv_ops[32] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0x1186: call pv_ops[32] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0x12ba: call pv_ops[32] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0x12a7: call pv_ops[32] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0x124c: call pv_ops[32] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0x14f0: call pv_ops[32] from > noinstr > ../../defconfig-build/vmlinux.o: warning: objtool: .entry.text+0x1683: call pv_ops[32] from > noinstr > > [ funny that, WTH does x86_64 have IRET pv_ops... ] > > Requested-by: Thomas Gleixner <tglx@linutronix.de> > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> > --- > arch/x86/include/asm/paravirt.h | 8 +-- > arch/x86/kernel/cpu/mshyperv.c | 7 --- > drivers/clocksource/hyperv_timer.c | 7 +++ > include/asm-generic/mshyperv.h | 1 - > lib/Kconfig.debug | 2 +- > tools/objtool/Makefile | 2 +- > tools/objtool/arch.h | 2 +- > tools/objtool/arch/x86/decode.c | 30 ++++++++- > tools/objtool/builtin-check.c | 10 +-- > tools/objtool/builtin-orc.c | 10 +-- > tools/objtool/check.c | 126 ++++++++++++++++++++++++++++++++++--- > tools/objtool/elf.h | 1 + > tools/objtool/objtool.c | 46 ++++++++++++++ > tools/objtool/objtool.h | 9 +++ > 14 files changed, 218 insertions(+), 43 deletions(-) > > diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h > index 3d2afecde50c..db30b35f0d59 100644 > --- a/arch/x86/include/asm/paravirt.h > +++ b/arch/x86/include/asm/paravirt.h > @@ -39,11 +39,11 @@ static inline u64 paravirt_steal_clock(int cpu) > /* The paravirtualized I/O functions */ > static inline void slow_down_io(void) > { > - pv_ops.cpu.io_delay(); > + PVOP_VCALL0(cpu.io_delay); > #ifdef REALLY_SLOW_IO > - pv_ops.cpu.io_delay(); > - pv_ops.cpu.io_delay(); > - pv_ops.cpu.io_delay(); > + PVOP_VCALL0(cpu.io_delay); > + PVOP_VCALL0(cpu.io_delay); > + PVOP_VCALL0(cpu.io_delay); > #endif > } > > diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c > index af94f05a5c66..31125448b174 100644 > --- a/arch/x86/kernel/cpu/mshyperv.c > +++ b/arch/x86/kernel/cpu/mshyperv.c > @@ -361,13 +361,6 @@ static void __init ms_hyperv_init_platform(void) > #endif > } > > -void hv_setup_sched_clock(void *sched_clock) > -{ > -#ifdef CONFIG_PARAVIRT > - pv_ops.time.sched_clock = sched_clock; > -#endif > -} > - > const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = { > .name = "Microsoft Hyper-V", > .detect = ms_hyperv_platform, > diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c > index 09aa44cb8a91..bed769a84637 100644 > --- a/drivers/clocksource/hyperv_timer.c > +++ b/drivers/clocksource/hyperv_timer.c > @@ -418,6 +418,13 @@ static struct clocksource hyperv_cs_msr = { > .flags = CLOCK_SOURCE_IS_CONTINUOUS, > }; > > +static __always_inline void hv_setup_sched_clock(void *sched_clock) > +{ > +#ifdef CONFIG_PARAVIRT > + pv_ops.time.sched_clock = sched_clock; > +#endif > +} > +
Moving this function to hyperv_timer.c is problematic because we want hyperv_timer.c to be architecture independent. We're in the process of supporting Linux guests running on Hyper-V on ARM64, and there's a different implementation of hv_setup_sched_clock() on ARM64.
Michael
> static bool __init hv_init_tsc_clocksource(void) > { > u64 tsc_msr; > diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h > index 1c4fd950f091..c5edc5e08b94 100644 > --- a/include/asm-generic/mshyperv.h > +++ b/include/asm-generic/mshyperv.h > @@ -168,7 +168,6 @@ void hyperv_report_panic_msg(phys_addr_t pa, size_t size); > bool hv_is_hyperv_initialized(void); > bool hv_is_hibernation_supported(void); > void hyperv_cleanup(void); > -void hv_setup_sched_clock(void *sched_clock); > #else /* CONFIG_HYPERV */ > static inline bool hv_is_hyperv_initialized(void) { return false; } > static inline bool hv_is_hibernation_supported(void) { return false; }
| |