summaryrefslogtreecommitdiff
path: root/arch/x86/hyperv/hv_init.c
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2025-04-12 13:55:49 +0200
committerPeter Zijlstra <peterz@infradead.org>2025-08-18 14:23:07 +0200
commit0e20f1f4c2cb77130cfe903a058a08883645dc4b (patch)
treec6214bdf7c286398ac73d05878129099edbdffe7 /arch/x86/hyperv/hv_init.c
parenta1d34a444ce8c9a6ec4376247f80f0b777c6d3fe (diff)
x86/hyperv: Clean up hv_do_hypercall()
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@infradead.org> Reviewed-by: Michael Kelley <mhklinux@outlook.com> Tested-by: Michael Kelley <mhklinux@outlook.com> Acked-by: Sean Christopherson <seanjc@google.com> Link: https://lkml.kernel.org/r/20250714103440.897136093@infradead.org
Diffstat (limited to 'arch/x86/hyperv/hv_init.c')
-rw-r--r--arch/x86/hyperv/hv_init.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index afdbda2dd7b7..5ef1e647ebc0 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -37,7 +37,27 @@
#include <linux/export.h>
void *hv_hypercall_pg;
+
+#ifdef CONFIG_X86_64
+u64 hv_std_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)
+ : 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;