x86/head_64: Store boot_params pointer in callee save register
authorArd Biesheuvel <ardb@kernel.org>
Mon, 7 Aug 2023 16:26:59 +0000 (18:26 +0200)
committerBorislav Petkov (AMD) <bp@alien8.de>
Mon, 7 Aug 2023 17:20:32 +0000 (19:20 +0200)
Instead of pushing/popping %RSI to/from the stack every time a function
is called from startup_64(), store it in a callee preserved register
and grab it from there when its value is actually needed.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230807162720.545787-3-ardb@kernel.org
arch/x86/kernel/head_64.S

index c5b9289..ea69959 100644 (file)
@@ -51,7 +51,9 @@ SYM_CODE_START_NOALIGN(startup_64)
         * for us.  These identity mapped page tables map all of the
         * kernel pages and possibly all of memory.
         *
-        * %rsi holds a physical pointer to real_mode_data.
+        * %RSI holds the physical address of the boot_params structure
+        * provided by the bootloader. Preserve it in %R15 so C function calls
+        * will not clobber it.
         *
         * We come here either directly from a 64bit bootloader, or from
         * arch/x86/boot/compressed/head_64.S.
@@ -62,6 +64,7 @@ SYM_CODE_START_NOALIGN(startup_64)
         * compiled to run at we first fixup the physical addresses in our page
         * tables and then reload them.
         */
+       mov     %rsi, %r15
 
        /* Set up the stack for verify_cpu() */
        leaq    (__end_init_task - PTREGS_SIZE)(%rip), %rsp
@@ -75,9 +78,7 @@ SYM_CODE_START_NOALIGN(startup_64)
        shrq    $32,  %rdx
        wrmsr
 
-       pushq   %rsi
        call    startup_64_setup_env
-       popq    %rsi
 
        /* Now switch to __KERNEL_CS so IRET works reliably */
        pushq   $__KERNEL_CS
@@ -93,12 +94,10 @@ SYM_CODE_START_NOALIGN(startup_64)
         * Activate SEV/SME memory encryption if supported/enabled. This needs to
         * be done now, since this also includes setup of the SEV-SNP CPUID table,
         * which needs to be done before any CPUID instructions are executed in
-        * subsequent code.
+        * subsequent code. Pass the boot_params pointer as the first argument.
         */
-       movq    %rsi, %rdi
-       pushq   %rsi
+       movq    %r15, %rdi
        call    sme_enable
-       popq    %rsi
 #endif
 
        /* Sanitize CPU configuration */
@@ -111,9 +110,8 @@ SYM_CODE_START_NOALIGN(startup_64)
         * programmed into CR3.
         */
        leaq    _text(%rip), %rdi
-       pushq   %rsi
+       movq    %r15, %rsi
        call    __startup_64
-       popq    %rsi
 
        /* Form the CR3 value being sure to include the CR3 modifier */
        addq    $(early_top_pgt - __START_KERNEL_map), %rax
@@ -127,8 +125,6 @@ SYM_CODE_START(secondary_startup_64)
         * At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0,
         * and someone has loaded a mapped page table.
         *
-        * %rsi holds a physical pointer to real_mode_data.
-        *
         * We come here either from startup_64 (using physical addresses)
         * or from trampoline.S (using virtual addresses).
         *
@@ -153,6 +149,9 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
        UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR
 
+       /* Clear %R15 which holds the boot_params pointer on the boot CPU */
+       xorq    %r15, %r15
+
        /*
         * Retrieve the modifier (SME encryption mask if SME is active) to be
         * added to the initial pgdir entry that will be programmed into CR3.
@@ -199,13 +198,9 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
         * hypervisor could lie about the C-bit position to perform a ROP
         * attack on the guest by writing to the unencrypted stack and wait for
         * the next RET instruction.
-        * %rsi carries pointer to realmode data and is callee-clobbered. Save
-        * and restore it.
         */
-       pushq   %rsi
        movq    %rax, %rdi
        call    sev_verify_cbit
-       popq    %rsi
 
        /*
         * Switch to new page-table
@@ -365,9 +360,7 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
        wrmsr
 
        /* Setup and Load IDT */
-       pushq   %rsi
        call    early_setup_idt
-       popq    %rsi
 
        /* Check if nx is implemented */
        movl    $0x80000001, %eax
@@ -403,9 +396,8 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
        pushq $0
        popfq
 
-       /* rsi is pointer to real mode structure with interesting info.
-          pass it to C */
-       movq    %rsi, %rdi
+       /* Pass the boot_params pointer as first argument */
+       movq    %r15, %rdi
 
 .Ljump_to_C_code:
        /*