Re: [PATCH 4/6] x86,hyperv: Clean up hv_do_hypercall()

From: Uros Bizjak
Date: Mon Apr 14 2025 - 10:47:53 EST




On 14. 04. 25 13:11, Peter Zijlstra wrote:
What used to be a simple few instructions has turned into a giant mess
(for x86_64). Not only does it use static_branch wrong, it mixes it
with dynamic branches for no apparent reason.

Notably it uses static_branch through an out-of-line function call,
which completely defeats the purpose, since instead of a simple
JMP/NOP site, you get a CALL+RET+TEST+Jcc sequence in return, which is
absolutely idiotic.

Add to that a dynamic test of hyperv_paravisor_present, something
which is set once and never changed.

Replace all this idiocy with a single direct function call to the
right hypercall variant.

Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
---
arch/x86/hyperv/hv_init.c | 21 ++++++
arch/x86/hyperv/ivm.c | 14 ++++
arch/x86/include/asm/mshyperv.h | 137 +++++++++++-----------------------------
arch/x86/kernel/cpu/mshyperv.c | 18 +++--
4 files changed, 88 insertions(+), 102 deletions(-)

--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -35,7 +35,28 @@
#include <linux/highmem.h>
void *hv_hypercall_pg;
+
+#ifdef CONFIG_X86_64
+u64 hv_pg_hypercall(u64 control, u64 param1, u64 param2)
+{
+ u64 hv_status;
+
+ if (!hv_hypercall_pg)
+ return U64_MAX;
+
+ register u64 __r8 asm("r8") = param2;
+ asm volatile (CALL_NOSPEC
+ : "=a" (hv_status), ASM_CALL_CONSTRAINT,
+ "+c" (control), "+d" (param1)
+ : "r" (__r8),

r8 is call-clobbered register, so you should use "+r" (__r8) to properly clobber it:

"+c" (control), "+d" (param1), "+r" (__r8)
: THUNK_TARGET(hv_hypercall_pg)

+ : "cc", "memory", "r9", "r10", "r11");
+
+ return hv_status;
+}
+#else
EXPORT_SYMBOL_GPL(hv_hypercall_pg);
+#endif
union hv_ghcb * __percpu *hv_ghcb_pg;
--- a/arch/x86/hyperv/ivm.c
+++ b/arch/x86/hyperv/ivm.c
@@ -376,6 +376,20 @@ int hv_snp_boot_ap(u32 cpu, unsigned lon
return ret;
}
+u64 hv_snp_hypercall(u64 control, u64 param1, u64 param2)
+{
+ u64 hv_status;
+
+ register u64 __r8 asm("r8") = param2;
+ asm volatile("vmmcall"
+ : "=a" (hv_status), ASM_CALL_CONSTRAINT,
+ "+c" (control), "+d" (param1)
+ : "r" (__r8)

Also here:
"+c" (control), "+d" (param1), "+r" (__r8)
:

+ : "cc", "memory", "r9", "r10", "r11");
+
+ return hv_status;
+}

Uros.