| From 3010a0663fd949d122eca0561b06b0a9453f7866 Mon Sep 17 00:00:00 2001 |
| From: Peter Zijlstra <peterz@infradead.org> |
| Date: Wed, 17 Jan 2018 16:58:11 +0100 |
| Subject: x86/paravirt, objtool: Annotate indirect calls |
| |
| From: Peter Zijlstra <peterz@infradead.org> |
| |
| commit 3010a0663fd949d122eca0561b06b0a9453f7866 upstream. |
| |
| Paravirt emits indirect calls which get flagged by objtool retpoline |
| checks, annotate it away because all these indirect calls will be |
| patched out before we start userspace. |
| |
| This patching happens through alternative_instructions() -> |
| apply_paravirt() -> pv_init_ops.patch() which will eventually end up |
| in paravirt_patch_default(). This function _will_ write direct |
| alternatives. |
| |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Reviewed-by: David Woodhouse <dwmw@amazon.co.uk> |
| Acked-by: Thomas Gleixner <tglx@linutronix.de> |
| Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> |
| Cc: Andy Lutomirski <luto@kernel.org> |
| Cc: Arjan van de Ven <arjan@linux.intel.com> |
| Cc: Borislav Petkov <bp@alien8.de> |
| Cc: Dan Williams <dan.j.williams@intel.com> |
| Cc: Dave Hansen <dave.hansen@linux.intel.com> |
| Cc: David Woodhouse <dwmw2@infradead.org> |
| Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/include/asm/paravirt.h | 17 +++++++++++++---- |
| arch/x86/include/asm/paravirt_types.h | 5 ++++- |
| 2 files changed, 17 insertions(+), 5 deletions(-) |
| |
| --- a/arch/x86/include/asm/paravirt.h |
| +++ b/arch/x86/include/asm/paravirt.h |
| @@ -7,6 +7,7 @@ |
| #ifdef CONFIG_PARAVIRT |
| #include <asm/pgtable_types.h> |
| #include <asm/asm.h> |
| +#include <asm/nospec-branch.h> |
| |
| #include <asm/paravirt_types.h> |
| |
| @@ -879,23 +880,27 @@ extern void default_banner(void); |
| |
| #define INTERRUPT_RETURN \ |
| PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_iret), CLBR_NONE, \ |
| - jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_iret)) |
| + ANNOTATE_RETPOLINE_SAFE; \ |
| + jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_iret);) |
| |
| #define DISABLE_INTERRUPTS(clobbers) \ |
| PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_disable), clobbers, \ |
| PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ |
| + ANNOTATE_RETPOLINE_SAFE; \ |
| call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_disable); \ |
| PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) |
| |
| #define ENABLE_INTERRUPTS(clobbers) \ |
| PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_irq_enable), clobbers, \ |
| PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ |
| + ANNOTATE_RETPOLINE_SAFE; \ |
| call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable); \ |
| PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) |
| |
| #ifdef CONFIG_X86_32 |
| #define GET_CR0_INTO_EAX \ |
| push %ecx; push %edx; \ |
| + ANNOTATE_RETPOLINE_SAFE; \ |
| call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0); \ |
| pop %edx; pop %ecx |
| #else /* !CONFIG_X86_32 */ |
| @@ -917,21 +922,25 @@ extern void default_banner(void); |
| */ |
| #define SWAPGS \ |
| PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_swapgs), CLBR_NONE, \ |
| - call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs) \ |
| + ANNOTATE_RETPOLINE_SAFE; \ |
| + call PARA_INDIRECT(pv_cpu_ops+PV_CPU_swapgs); \ |
| ) |
| |
| #define GET_CR2_INTO_RAX \ |
| - call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2) |
| + ANNOTATE_RETPOLINE_SAFE; \ |
| + call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2); |
| |
| #define USERGS_SYSRET64 \ |
| PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \ |
| CLBR_NONE, \ |
| - jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret64)) |
| + ANNOTATE_RETPOLINE_SAFE; \ |
| + jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret64);) |
| |
| #ifdef CONFIG_DEBUG_ENTRY |
| #define SAVE_FLAGS(clobbers) \ |
| PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_save_fl), clobbers, \ |
| PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ |
| + ANNOTATE_RETPOLINE_SAFE; \ |
| call PARA_INDIRECT(pv_irq_ops+PV_IRQ_save_fl); \ |
| PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) |
| #endif |
| --- a/arch/x86/include/asm/paravirt_types.h |
| +++ b/arch/x86/include/asm/paravirt_types.h |
| @@ -43,6 +43,7 @@ |
| #include <asm/desc_defs.h> |
| #include <asm/kmap_types.h> |
| #include <asm/pgtable_types.h> |
| +#include <asm/nospec-branch.h> |
| |
| struct page; |
| struct thread_struct; |
| @@ -392,7 +393,9 @@ int paravirt_disable_iospace(void); |
| * offset into the paravirt_patch_template structure, and can therefore be |
| * freely converted back into a structure offset. |
| */ |
| -#define PARAVIRT_CALL "call *%c[paravirt_opptr];" |
| +#define PARAVIRT_CALL \ |
| + ANNOTATE_RETPOLINE_SAFE \ |
| + "call *%c[paravirt_opptr];" |
| |
| /* |
| * These macros are intended to wrap calls through one of the paravirt |