On Thu, Jul 20, 2023 at 01:33:57PM -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. Whoops :/ > 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. There are currently no plans to add IBT support to 32bit. > Cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: Michael Kelley <mikelley@xxxxxxxxxxxxx> > --- > 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_info("Hyper-V: Disabling IBT because of Hyper-V bug\n"); > + } > +#endif pr_warn() perhaps? Other than that, this seems fairly straight forward. One thing I wondered about; wouldn't it be possible to re-write the indirect hypercall thingies to a direct call? I mean, once we have the hypercall page mapped, the address is known right?