diff options
| author | Peter Zijlstra <peterz@infradead.org> | 2025-04-12 13:55:49 +0200 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2025-08-18 14:23:07 +0200 |
| commit | 0e20f1f4c2cb77130cfe903a058a08883645dc4b (patch) | |
| tree | c6214bdf7c286398ac73d05878129099edbdffe7 /arch/x86/hyperv/hv_init.c | |
| parent | a1d34a444ce8c9a6ec4376247f80f0b777c6d3fe (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.c | 20 |
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; |