Skip to content

Commit 11af36c

Browse files
jgross1bp3tk0v
authored andcommitted
x86/paravirt: Convert simple paravirt functions to asm
All functions referenced via __PV_IS_CALLEE_SAVE() need to be assembler functions, as those functions calls are hidden from the compiler. In case the kernel is compiled with "-fzero-call-used-regs" the compiler will clobber caller-saved registers at the end of C functions, which will result in unexpectedly zeroed registers at the call site of the related paravirt functions. Replace the C functions with DEFINE_PARAVIRT_ASM() constructs using the same instructions as the related paravirt calls in the PVOP_ALT_[V]CALLEE*() macros. And since they're not C functions visible to the compiler anymore, latter won't do the callee-clobbered zeroing invoked by -fzero-call-used-regs and thus won't corrupt registers. [ bp: Extend commit message. ] Signed-off-by: Juergen Gross <jgross@suse.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/r/20230317063325.361-1-jgross@suse.com
1 parent c9ae1b1 commit 11af36c

2 files changed

Lines changed: 13 additions & 22 deletions

File tree

arch/x86/include/asm/paravirt_types.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,14 @@ void paravirt_flush_lazy_mmu(void);
559559

560560
void _paravirt_nop(void);
561561
void paravirt_BUG(void);
562-
u64 _paravirt_ident_64(u64);
563562
unsigned long paravirt_ret0(void);
563+
#ifdef CONFIG_PARAVIRT_XXL
564+
u64 _paravirt_ident_64(u64);
565+
unsigned long pv_native_save_fl(void);
566+
void pv_native_irq_disable(void);
567+
void pv_native_irq_enable(void);
568+
unsigned long pv_native_read_cr2(void);
569+
#endif
564570

565571
#define paravirt_nop ((void *)_paravirt_nop)
566572

arch/x86/kernel/paravirt.c

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ static unsigned paravirt_patch_call(void *insn_buff, const void *target,
6464
}
6565

6666
#ifdef CONFIG_PARAVIRT_XXL
67-
/* identity function, which can be inlined */
68-
u64 notrace _paravirt_ident_64(u64 x)
69-
{
70-
return x;
71-
}
67+
DEFINE_PARAVIRT_ASM(_paravirt_ident_64, "mov %rdi, %rax", .text);
68+
DEFINE_PARAVIRT_ASM(pv_native_save_fl, "pushf; pop %rax", .noinstr.text);
69+
DEFINE_PARAVIRT_ASM(pv_native_irq_disable, "cli", .noinstr.text);
70+
DEFINE_PARAVIRT_ASM(pv_native_irq_enable, "sti", .noinstr.text);
71+
DEFINE_PARAVIRT_ASM(pv_native_read_cr2, "mov %cr2, %rax", .noinstr.text);
7272
#endif
7373

7474
DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key);
@@ -197,11 +197,6 @@ void paravirt_end_context_switch(struct task_struct *next)
197197
arch_enter_lazy_mmu_mode();
198198
}
199199

200-
static noinstr unsigned long pv_native_read_cr2(void)
201-
{
202-
return native_read_cr2();
203-
}
204-
205200
static noinstr void pv_native_write_cr2(unsigned long val)
206201
{
207202
native_write_cr2(val);
@@ -222,16 +217,6 @@ noinstr void pv_native_wbinvd(void)
222217
native_wbinvd();
223218
}
224219

225-
static noinstr void pv_native_irq_enable(void)
226-
{
227-
native_irq_enable();
228-
}
229-
230-
static noinstr void pv_native_irq_disable(void)
231-
{
232-
native_irq_disable();
233-
}
234-
235220
static noinstr void pv_native_safe_halt(void)
236221
{
237222
native_safe_halt();
@@ -298,7 +283,7 @@ struct paravirt_patch_template pv_ops = {
298283
.cpu.end_context_switch = paravirt_nop,
299284

300285
/* Irq ops. */
301-
.irq.save_fl = __PV_IS_CALLEE_SAVE(native_save_fl),
286+
.irq.save_fl = __PV_IS_CALLEE_SAVE(pv_native_save_fl),
302287
.irq.irq_disable = __PV_IS_CALLEE_SAVE(pv_native_irq_disable),
303288
.irq.irq_enable = __PV_IS_CALLEE_SAVE(pv_native_irq_enable),
304289
.irq.safe_halt = pv_native_safe_halt,

0 commit comments

Comments
 (0)