On Wed, Dec 18, 2024 at 10:44:25AM +0100, David Woodhouse wrote:
> > At some point we had discussed placing the code in .rodata, was it the
> > alternative preventing that?
> 
> No, the alternative seems to be fine, and it's all in the .data section
> now (since the kernel does write some variables there which are then
> accessed %rip-relative from the code itself).

The linker script does place it in .data, but objtool runs on the object
file before linking, where it's still in an executable section
(.text..relocate_kernel).

How about something like below?

  - move text to .data..relocate_kernel
  - remove objtool annotations
  - replace the alternative with a runtime check

diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index 5081d0b9e290..126d777a5695 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -61,6 +61,7 @@ struct kimage;
 extern unsigned long kexec_va_control_page;
 extern unsigned long kexec_pa_table_page;
 extern unsigned long kexec_pa_swap_page;
+extern unsigned int kexec_preserve_mce;
 extern gate_desc kexec_debug_idt[];
 extern unsigned char kexec_debug_exc_vectors[];
 extern uint16_t kexec_debug_8250_port;
diff --git a/arch/x86/kernel/machine_kexec_64.c 
b/arch/x86/kernel/machine_kexec_64.c
index 853f3cdc7c75..751adeea0db8 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -363,6 +363,8 @@ int machine_kexec_prepare(struct kimage *image)
        if (image->type == KEXEC_TYPE_DEFAULT)
                kexec_pa_swap_page = page_to_pfn(image->swap_page) << 
PAGE_SHIFT;
 
+       kexec_preserve_mce = boot_cpu_has(X86_FEATURE_TDX_GUEST);
+
        prepare_debug_idt((unsigned long)__pa(control_page),
                          (unsigned long)kexec_debug_exc_vectors - reloc_start);
 
diff --git a/arch/x86/kernel/relocate_kernel_64.S 
b/arch/x86/kernel/relocate_kernel_64.S
index 4dca50141586..04b7a9f11e98 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -24,8 +24,8 @@
 #define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
 
 /*
- * The .text..relocate_kernel and .data..relocate_kernel sections are copied
- * into the control page, and the remainder of the page is used as the stack.
+ * The .data..relocate_kernel section is copied into the control page, and the
+ * remainder of the page is used as the stack.
  */
 
        .section .data..relocate_kernel,"a";
@@ -41,6 +41,7 @@ SYM_DATA(kexec_pa_swap_page, .quad 0)
 SYM_DATA_LOCAL(pa_backup_pages_map, .quad 0)
 SYM_DATA(kexec_debug_8250_mmio32, .quad 0)
 SYM_DATA(kexec_debug_8250_port, .word 0)
+SYM_DATA(kexec_preserve_mce, .word 0)
 
 #ifdef CONFIG_KEXEC_DEBUG
        .balign 16
@@ -60,12 +61,14 @@ SYM_DATA_END(kexec_debug_idt)
 
 #endif /* CONFIG_KEXEC_DEBUG */
 
-       .section .text..relocate_kernel,"ax";
+/*
+ * This code is copied rather than called in place.  It's free to use indirect
+ * branches and bare returns, and doesn't need ORC unwinding data.  Keep it in
+ * a data section so objtool doesn't see it.
+ */
+
        .code64
 SYM_TYPED_FUNC_START(relocate_kernel)
-       UNWIND_HINT_END_OF_STACK
-       UNWIND_HINT_FUNC
-       ANNOTATE_NOENDBR
        /*
         * %rdi indirection_page
         * %rsi pa_control_page
@@ -124,12 +127,10 @@ SYM_TYPED_FUNC_START(relocate_kernel)
        /* jump to identity mapped page */
        addq    $identity_mapped, %rsi
        subq    $__relocate_kernel_start, %rsi
-       ANNOTATE_RETPOLINE_SAFE
        jmp     *%rsi
 SYM_CODE_END(relocate_kernel)
 
 SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
-       UNWIND_HINT_END_OF_STACK
        /*
         * %rdi indirection page
         * %rdx start address
@@ -199,7 +200,11 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
         * PAE is always set in the original CR4.
         */
        andl    $(X86_CR4_PAE | X86_CR4_LA57), %r13d
-       ALTERNATIVE "", __stringify(orl $X86_CR4_MCE, %r13d), 
X86_FEATURE_TDX_GUEST
+       movw    kexec_preserve_mce(%rip), %ax
+       testw   %ax, %ax
+       jz      .Lwrite_cr4
+       orl     $X86_CR4_MCE, %r13d
+.Lwrite_cr4:
        movq    %r13, %cr4
 
        /* Flush the TLB (needed?) */
@@ -250,7 +255,6 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
        xorl    %r14d, %r14d
        xorl    %r15d, %r15d
 
-       ANNOTATE_UNRET_SAFE
        ret
        int3
 
@@ -264,7 +268,6 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
        /* push the existing entry point onto the callee's stack */
        pushq   %rdx
 
-       ANNOTATE_RETPOLINE_SAFE
        call    *%rdx
 
        /* get the re-entry point of the peer system */
@@ -276,7 +279,6 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
 
        /* Find start (and end) of this physical mapping of control page */
        leaq    (%rip), %r8
-       ANNOTATE_NOENDBR
        andq    $PAGE_MASK, %r8
        lea     PAGE_SIZE(%r8), %rsp
        movq    $1, %r11        /* Ensure preserve_context flag is set */
@@ -285,14 +287,11 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
        addq    $virtual_mapped, %rax
        subq    $__relocate_kernel_start, %rax
        pushq   %rax
-       ANNOTATE_UNRET_SAFE
        ret
        int3
 SYM_CODE_END(identity_mapped)
 
 SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
-       UNWIND_HINT_END_OF_STACK
-       ANNOTATE_NOENDBR // RET target, above
        movq    saved_rsp(%rip), %rsp
        movq    saved_cr4(%rip), %rax
        movq    %rax, %cr4
@@ -317,14 +316,12 @@ SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
        popq    %r12
        popq    %rbp
        popq    %rbx
-       ANNOTATE_UNRET_SAFE
        ret
        int3
 SYM_CODE_END(virtual_mapped)
 
        /* Do the copies */
 SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
-       UNWIND_HINT_END_OF_STACK
        /*
         * %rdi indirection page
         * %r11 preserve_context
@@ -387,7 +384,6 @@ SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
        lea     PAGE_SIZE(%rax), %rsi
        jmp     .Lloop
 .Ldone:
-       ANNOTATE_UNRET_SAFE
        ret
        int3
 SYM_CODE_END(swap_pages)
@@ -404,8 +400,6 @@ SYM_CODE_END(swap_pages)
 #define LSR             5       /*  Line Status               */
 
 SYM_CODE_START_LOCAL_NOALIGN(pr_char_8250)
-       UNWIND_HINT_FUNC
-       ANNOTATE_NOENDBR
        addw    $LSR, %dx
        xchg    %al, %ah
 .Lxmtrdy_loop:
@@ -420,15 +414,11 @@ SYM_CODE_START_LOCAL_NOALIGN(pr_char_8250)
        xchg    %al, %ah
        outb    %al, %dx
 pr_char_null:
-       ANNOTATE_NOENDBR
 
-       ANNOTATE_UNRET_SAFE
        ret
 SYM_CODE_END(pr_char_8250)
 
 SYM_CODE_START_LOCAL_NOALIGN(pr_char_8250_mmio32)
-       UNWIND_HINT_FUNC
-       ANNOTATE_NOENDBR
 .Lxmtrdy_loop_mmio:
        movb    (LSR*4)(%rdx), %ah
        testb   $XMTRDY, %ah
@@ -438,7 +428,6 @@ SYM_CODE_START_LOCAL_NOALIGN(pr_char_8250_mmio32)
 
 .Lready_mmio:
        movb    %al, (%rdx)
-       ANNOTATE_UNRET_SAFE
        ret
 SYM_CODE_END(pr_char_8250_mmio32)
 
@@ -463,7 +452,6 @@ SYM_CODE_END(pr_char_8250_mmio32)
 
 /* Print the nybble in %bl, clobber %rax */
 SYM_CODE_START_LOCAL_NOALIGN(pr_nybble)
-       UNWIND_HINT_FUNC
        movb    %bl, %al
        nop
        andb    $0x0f, %al
@@ -471,33 +459,26 @@ SYM_CODE_START_LOCAL_NOALIGN(pr_nybble)
        cmpb    $0x3a, %al
        jb      1f
        addb    $('a' - '0' - 10), %al
-       ANNOTATE_RETPOLINE_SAFE
 1:     jmp     *%rsi
 SYM_CODE_END(pr_nybble)
 
 SYM_CODE_START_LOCAL_NOALIGN(pr_qword)
-       UNWIND_HINT_FUNC
        movq    $16, %rcx
 1:     rolq    $4, %rbx
        call    pr_nybble
        loop    1b
        movb    $'\n', %al
-       ANNOTATE_RETPOLINE_SAFE
        jmp     *%rsi
 SYM_CODE_END(pr_qword)
 
 .macro print_reg a, b, c, d, r
        movb    $\a, %al
-       ANNOTATE_RETPOLINE_SAFE
        call    *%rsi
        movb    $\b, %al
-       ANNOTATE_RETPOLINE_SAFE
        call    *%rsi
        movb    $\c, %al
-       ANNOTATE_RETPOLINE_SAFE
        call    *%rsi
        movb    $\d, %al
-       ANNOTATE_RETPOLINE_SAFE
        call    *%rsi
        movq    \r, %rbx
        call    pr_qword
@@ -506,7 +487,6 @@ SYM_CODE_END(pr_qword)
 SYM_CODE_START_NOALIGN(kexec_debug_exc_vectors)
        /* Each of these is 6 bytes. */
 .macro vec_err exc
-       UNWIND_HINT_ENTRY
        . = kexec_debug_exc_vectors + (\exc * KEXEC_DEBUG_EXC_HANDLER_SIZE)
        nop
        nop
@@ -515,14 +495,12 @@ SYM_CODE_START_NOALIGN(kexec_debug_exc_vectors)
 .endm
 
 .macro vec_noerr exc
-       UNWIND_HINT_ENTRY
        . = kexec_debug_exc_vectors + (\exc * KEXEC_DEBUG_EXC_HANDLER_SIZE)
        pushq   $0
        pushq   $\exc
        jmp     exc_handler
 .endm
 
-       ANNOTATE_NOENDBR
        vec_noerr 0 // #DE
        vec_noerr 1 // #DB
        vec_noerr 2 // #NMI
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 63ff60a11be5..9c2abfd6ea26 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -100,7 +100,6 @@ const_pcpu_hot = pcpu_hot;
 #define KEXEC_RELOCATE_KERNEL                                  \
        . = ALIGN(0x100);                                       \
        __relocate_kernel_start = .;                            \
-       *(.text..relocate_kernel);                              \
        *(.data..relocate_kernel);                              \
        __relocate_kernel_end = .;
 

Reply via email to