On Fri, Jul 21, 2023 at 09:51:16PM -0700, Michael Kelley wrote: > On hardware that supports Indirect Branch Tracking (IBT), Hyper-V VMs > with ConfigVersion 9.3 or later support IBT in the guest. However, > current versions of Hyper-V have a bug in that there's not an ENDBR64 > instruction at the beginning of the hypercall page. Since hypercalls are > made with an indirect call to the hypercall page, all hypercall attempts > fail with an exception and Linux panics. > > A Hyper-V fix is in progress to add ENDBR64. But guard against the Linux > panic by clearing X86_FEATURE_IBT if the hypercall page doesn't start > with ENDBR. The VM will boot and run without IBT. > > If future Linux 32-bit kernels were to support IBT, additional hypercall > page hackery would be needed to make IBT work for such kernels in a > Hyper-V VM. > > Cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: Michael Kelley <mikelley@xxxxxxxxxxxxx> Acked-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx> > --- > > Changes in v2: > * Use pr_warn() instead of pr_info() [Peter Zijlstra] > > arch/x86/hyperv/hv_init.c | 21 +++++++++++++++++++++ > 1 file changed, 21 insertions(+) > > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c > index 6c04b52..5cbee24 100644 > --- a/arch/x86/hyperv/hv_init.c > +++ b/arch/x86/hyperv/hv_init.c > @@ -14,6 +14,7 @@ > #include <asm/apic.h> > #include <asm/desc.h> > #include <asm/sev.h> > +#include <asm/ibt.h> > #include <asm/hypervisor.h> > #include <asm/hyperv-tlfs.h> > #include <asm/mshyperv.h> > @@ -472,6 +473,26 @@ void __init hyperv_init(void) > } > > /* > + * Some versions of Hyper-V that provide IBT in guest VMs have a bug > + * in that there's no ENDBR64 instruction at the entry to the > + * hypercall page. Because hypercalls are invoked via an indirect call > + * to the hypercall page, all hypercall attempts fail when IBT is > + * enabled, and Linux panics. For such buggy versions, disable IBT. > + * > + * Fixed versions of Hyper-V always provide ENDBR64 on the hypercall > + * page, so if future Linux kernel versions enable IBT for 32-bit > + * builds, additional hypercall page hackery will be required here > + * to provide an ENDBR32. > + */ > +#ifdef CONFIG_X86_KERNEL_IBT > + if (cpu_feature_enabled(X86_FEATURE_IBT) && > + *(u32 *)hv_hypercall_pg != gen_endbr()) { > + setup_clear_cpu_cap(X86_FEATURE_IBT); > + pr_warn("Hyper-V: Disabling IBT because of Hyper-V bug\n"); > + } > +#endif > + > + /* > * hyperv_init() is called before LAPIC is initialized: see > * apic_intr_mode_init() -> x86_platform.apic_post_init() and > * apic_bsp_setup() -> setup_local_APIC(). The direct-mode STIMER > -- > 1.8.3.1 >