Skip to content

Commit

Permalink
x86/hyperv: Disable IBT when hypercall page lacks ENDBR instruction
Browse files Browse the repository at this point in the history
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@vger.kernel.org
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
Link: https://lore.kernel.org/r/1690001476-98594-1-git-send-email-mikelley@microsoft.com
Signed-off-by: Wei Liu <wei.liu@kernel.org>
  • Loading branch information
kelleymh authored and pull[bot] committed Aug 5, 2023
1 parent adcb6d6 commit 1051609
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions arch/x86/hyperv/hv_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -471,6 +472,26 @@ void __init hyperv_init(void)
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
}

/*
* 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
Expand Down

0 comments on commit 1051609

Please sign in to comment.