66#include <linux/nmi.h>
77#include <linux/msi.h>
88#include <linux/io.h>
9+ #include <linux/static_call.h>
910#include <asm/nospec-branch.h>
1011#include <asm/paravirt.h>
1112#include <asm/msr.h>
@@ -39,16 +40,21 @@ static inline unsigned char hv_get_nmi_reason(void)
3940 return 0 ;
4041}
4142
42- #if IS_ENABLED (CONFIG_HYPERV )
43- extern bool hyperv_paravisor_present ;
43+ extern u64 hv_tdx_hypercall (u64 control , u64 param1 , u64 param2 );
44+ extern u64 hv_snp_hypercall (u64 control , u64 param1 , u64 param2 );
45+ extern u64 hv_std_hypercall (u64 control , u64 param1 , u64 param2 );
4446
47+ #if IS_ENABLED (CONFIG_HYPERV )
4548extern void * hv_hypercall_pg ;
4649
4750extern union hv_ghcb * __percpu * hv_ghcb_pg ;
4851
4952bool hv_isolation_type_snp (void );
5053bool hv_isolation_type_tdx (void );
51- u64 hv_tdx_hypercall (u64 control , u64 param1 , u64 param2 );
54+
55+ #ifdef CONFIG_X86_64
56+ DECLARE_STATIC_CALL (hv_hypercall , hv_std_hypercall );
57+ #endif
5258
5359/*
5460 * DEFAULT INIT GPAT and SEGMENT LIMIT value in struct VMSA
@@ -65,37 +71,15 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
6571{
6672 u64 input_address = input ? virt_to_phys (input ) : 0 ;
6773 u64 output_address = output ? virt_to_phys (output ) : 0 ;
68- u64 hv_status ;
6974
7075#ifdef CONFIG_X86_64
71- if (hv_isolation_type_tdx () && !hyperv_paravisor_present )
72- return hv_tdx_hypercall (control , input_address , output_address );
73-
74- if (hv_isolation_type_snp () && !hyperv_paravisor_present ) {
75- __asm__ __volatile__("mov %[output_address], %%r8\n"
76- "vmmcall"
77- : "=a" (hv_status ), ASM_CALL_CONSTRAINT ,
78- "+c" (control ), "+d" (input_address )
79- : [output_address ] "r" (output_address )
80- : "cc" , "memory" , "r8" , "r9" , "r10" , "r11" );
81- return hv_status ;
82- }
83-
84- if (!hv_hypercall_pg )
85- return U64_MAX ;
86-
87- __asm__ __volatile__("mov %[output_address], %%r8\n"
88- CALL_NOSPEC
89- : "=a" (hv_status ), ASM_CALL_CONSTRAINT ,
90- "+c" (control ), "+d" (input_address )
91- : [output_address ] "r" (output_address ),
92- THUNK_TARGET (hv_hypercall_pg )
93- : "cc" , "memory" , "r8" , "r9" , "r10" , "r11" );
76+ return static_call_mod (hv_hypercall )(control , input_address , output_address );
9477#else
9578 u32 input_address_hi = upper_32_bits (input_address );
9679 u32 input_address_lo = lower_32_bits (input_address );
9780 u32 output_address_hi = upper_32_bits (output_address );
9881 u32 output_address_lo = lower_32_bits (output_address );
82+ u64 hv_status ;
9983
10084 if (!hv_hypercall_pg )
10185 return U64_MAX ;
@@ -108,48 +92,30 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
10892 "D" (output_address_hi ), "S" (output_address_lo ),
10993 THUNK_TARGET (hv_hypercall_pg )
11094 : "cc" , "memory" );
111- #endif /* !x86_64 */
11295 return hv_status ;
96+ #endif /* !x86_64 */
11397}
11498
11599/* Fast hypercall with 8 bytes of input and no output */
116100static inline u64 _hv_do_fast_hypercall8 (u64 control , u64 input1 )
117101{
118- u64 hv_status ;
119-
120102#ifdef CONFIG_X86_64
121- if (hv_isolation_type_tdx () && !hyperv_paravisor_present )
122- return hv_tdx_hypercall (control , input1 , 0 );
123-
124- if (hv_isolation_type_snp () && !hyperv_paravisor_present ) {
125- __asm__ __volatile__(
126- "vmmcall"
127- : "=a" (hv_status ), ASM_CALL_CONSTRAINT ,
128- "+c" (control ), "+d" (input1 )
129- :: "cc" , "r8" , "r9" , "r10" , "r11" );
130- } else {
131- __asm__ __volatile__(CALL_NOSPEC
132- : "=a" (hv_status ), ASM_CALL_CONSTRAINT ,
133- "+c" (control ), "+d" (input1 )
134- : THUNK_TARGET (hv_hypercall_pg )
135- : "cc" , "r8" , "r9" , "r10" , "r11" );
136- }
103+ return static_call_mod (hv_hypercall )(control , input1 , 0 );
137104#else
138- {
139- u32 input1_hi = upper_32_bits (input1 );
140- u32 input1_lo = lower_32_bits (input1 );
141-
142- __asm__ __volatile__ (CALL_NOSPEC
143- : "=A" (hv_status ),
144- "+c" (input1_lo ),
145- ASM_CALL_CONSTRAINT
146- : "A" (control ),
147- "b" (input1_hi ),
148- THUNK_TARGET (hv_hypercall_pg )
149- : "cc" , "edi" , "esi" );
150- }
151- #endif
105+ u32 input1_hi = upper_32_bits (input1 );
106+ u32 input1_lo = lower_32_bits (input1 );
107+ u64 hv_status ;
108+
109+ __asm__ __volatile__ (CALL_NOSPEC
110+ : "=A" (hv_status ),
111+ "+c" (input1_lo ),
112+ ASM_CALL_CONSTRAINT
113+ : "A" (control ),
114+ "b" (input1_hi ),
115+ THUNK_TARGET (hv_hypercall_pg )
116+ : "cc" , "edi" , "esi" );
152117 return hv_status ;
118+ #endif
153119}
154120
155121static inline u64 hv_do_fast_hypercall8 (u16 code , u64 input1 )
@@ -162,45 +128,24 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
162128/* Fast hypercall with 16 bytes of input */
163129static inline u64 _hv_do_fast_hypercall16 (u64 control , u64 input1 , u64 input2 )
164130{
165- u64 hv_status ;
166-
167131#ifdef CONFIG_X86_64
168- if (hv_isolation_type_tdx () && !hyperv_paravisor_present )
169- return hv_tdx_hypercall (control , input1 , input2 );
170-
171- if (hv_isolation_type_snp () && !hyperv_paravisor_present ) {
172- __asm__ __volatile__("mov %[input2], %%r8\n"
173- "vmmcall"
174- : "=a" (hv_status ), ASM_CALL_CONSTRAINT ,
175- "+c" (control ), "+d" (input1 )
176- : [input2 ] "r" (input2 )
177- : "cc" , "r8" , "r9" , "r10" , "r11" );
178- } else {
179- __asm__ __volatile__("mov %[input2], %%r8\n"
180- CALL_NOSPEC
181- : "=a" (hv_status ), ASM_CALL_CONSTRAINT ,
182- "+c" (control ), "+d" (input1 )
183- : [input2 ] "r" (input2 ),
184- THUNK_TARGET (hv_hypercall_pg )
185- : "cc" , "r8" , "r9" , "r10" , "r11" );
186- }
132+ return static_call_mod (hv_hypercall )(control , input1 , input2 );
187133#else
188- {
189- u32 input1_hi = upper_32_bits (input1 );
190- u32 input1_lo = lower_32_bits (input1 );
191- u32 input2_hi = upper_32_bits (input2 );
192- u32 input2_lo = lower_32_bits (input2 );
193-
194- __asm__ __volatile__ (CALL_NOSPEC
195- : "=A" (hv_status ),
196- "+c" (input1_lo ), ASM_CALL_CONSTRAINT
197- : "A" (control ), "b" (input1_hi ),
198- "D" (input2_hi ), "S" (input2_lo ),
199- THUNK_TARGET (hv_hypercall_pg )
200- : "cc" );
201- }
202- #endif
134+ u32 input1_hi = upper_32_bits (input1 );
135+ u32 input1_lo = lower_32_bits (input1 );
136+ u32 input2_hi = upper_32_bits (input2 );
137+ u32 input2_lo = lower_32_bits (input2 );
138+ u64 hv_status ;
139+
140+ __asm__ __volatile__ (CALL_NOSPEC
141+ : "=A" (hv_status ),
142+ "+c" (input1_lo ), ASM_CALL_CONSTRAINT
143+ : "A" (control ), "b" (input1_hi ),
144+ "D" (input2_hi ), "S" (input2_lo ),
145+ THUNK_TARGET (hv_hypercall_pg )
146+ : "cc" );
203147 return hv_status ;
148+ #endif
204149}
205150
206151static inline u64 hv_do_fast_hypercall16 (u16 code , u64 input1 , u64 input2 )
0 commit comments