Merge tag 'x86_seves_for_v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / arch / x86 / boot / compressed / head_64.S
index 42190c0..1c80f17 100644 (file)
  */
        .hidden _bss
        .hidden _ebss
-       .hidden _got
-       .hidden _egot
        .hidden _end
 
        __HEAD
+
+/*
+ * This macro gives the relative virtual address of X, i.e. the offset of X
+ * from startup_32. This is the same as the link-time virtual address of X,
+ * since startup_32 is at 0, but defining it this way tells the
+ * assembler/linker that we do not want the actual run-time address of X. This
+ * prevents the linker from trying to create unwanted run-time relocation
+ * entries for the reference when the compressed kernel is linked as PIE.
+ *
+ * A reference X(%reg) will result in the link-time VA of X being stored with
+ * the instruction, and a run-time R_X86_64_RELATIVE relocation entry that
+ * adds the 64-bit base address where the kernel is loaded.
+ *
+ * Replacing it with (X-startup_32)(%reg) results in the offset being stored,
+ * and no run-time relocation.
+ *
+ * The macro should be used as a displacement with a base register containing
+ * the run-time address of startup_32 [i.e. rva(X)(%reg)], or as an immediate
+ * [$ rva(X)].
+ *
+ * This macro can only be used from within the .head.text section, since the
+ * expression requires startup_32 to be in the same section as the code being
+ * assembled.
+ */
+#define rva(X) ((X) - startup_32)
+
        .code32
 SYM_FUNC_START(startup_32)
        /*
@@ -68,10 +92,10 @@ SYM_FUNC_START(startup_32)
        leal    (BP_scratch+4)(%esi), %esp
        call    1f
 1:     popl    %ebp
-       subl    $1b, %ebp
+       subl    $ rva(1b), %ebp
 
        /* Load new GDT with the 64bit segments using 32bit descriptor */
-       leal    gdt(%ebp), %eax
+       leal    rva(gdt)(%ebp), %eax
        movl    %eax, 2(%eax)
        lgdt    (%eax)
 
@@ -84,7 +108,7 @@ SYM_FUNC_START(startup_32)
        movl    %eax, %ss
 
 /* setup a stack and make sure cpu supports long mode. */
-       leal    boot_stack_end(%ebp), %esp
+       leal    rva(boot_stack_end)(%ebp), %esp
 
        call    verify_cpu
        testl   %eax, %eax
@@ -111,7 +135,7 @@ SYM_FUNC_START(startup_32)
  *     image_offset = startup_32 - image_base
  * Otherwise image_offset will be zero and has no effect on the calculations.
  */
-       subl    image_offset(%ebp), %ebx
+       subl    rva(image_offset)(%ebp), %ebx
 #endif
 
        movl    BP_kernel_alignment(%esi), %eax
@@ -127,7 +151,7 @@ SYM_FUNC_START(startup_32)
 
        /* Target address to relocate to for decompression */
        addl    BP_init_size(%esi), %ebx
-       subl    $_end, %ebx
+       subl    $ rva(_end), %ebx
 
 /*
  * Prepare for entering 64 bit mode
@@ -155,19 +179,19 @@ SYM_FUNC_START(startup_32)
 1:
 
        /* Initialize Page tables to 0 */
-       leal    pgtable(%ebx), %edi
+       leal    rva(pgtable)(%ebx), %edi
        xorl    %eax, %eax
        movl    $(BOOT_INIT_PGT_SIZE/4), %ecx
        rep     stosl
 
        /* Build Level 4 */
-       leal    pgtable + 0(%ebx), %edi
+       leal    rva(pgtable + 0)(%ebx), %edi
        leal    0x1007 (%edi), %eax
        movl    %eax, 0(%edi)
        addl    %edx, 4(%edi)
 
        /* Build Level 3 */
-       leal    pgtable + 0x1000(%ebx), %edi
+       leal    rva(pgtable + 0x1000)(%ebx), %edi
        leal    0x1007(%edi), %eax
        movl    $4, %ecx
 1:     movl    %eax, 0x00(%edi)
@@ -178,7 +202,7 @@ SYM_FUNC_START(startup_32)
        jnz     1b
 
        /* Build Level 2 */
-       leal    pgtable + 0x2000(%ebx), %edi
+       leal    rva(pgtable + 0x2000)(%ebx), %edi
        movl    $0x00000183, %eax
        movl    $2048, %ecx
 1:     movl    %eax, 0(%edi)
@@ -189,7 +213,7 @@ SYM_FUNC_START(startup_32)
        jnz     1b
 
        /* Enable the boot page tables */
-       leal    pgtable(%ebx), %eax
+       leal    rva(pgtable)(%ebx), %eax
        movl    %eax, %cr3
 
        /* Enable Long mode in EFER (Extended Feature Enable Register) */
@@ -214,14 +238,14 @@ SYM_FUNC_START(startup_32)
         * We place all of the values on our mini stack so lret can
         * used to perform that far jump.
         */
-       leal    startup_64(%ebp), %eax
+       leal    rva(startup_64)(%ebp), %eax
 #ifdef CONFIG_EFI_MIXED
-       movl    efi32_boot_args(%ebp), %edi
+       movl    rva(efi32_boot_args)(%ebp), %edi
        cmp     $0, %edi
        jz      1f
-       leal    efi64_stub_entry(%ebp), %eax
-       movl    efi32_boot_args+4(%ebp), %esi
-       movl    efi32_boot_args+8(%ebp), %edx   // saved bootparams pointer
+       leal    rva(efi64_stub_entry)(%ebp), %eax
+       movl    rva(efi32_boot_args+4)(%ebp), %esi
+       movl    rva(efi32_boot_args+8)(%ebp), %edx      // saved bootparams pointer
        cmpl    $0, %edx
        jnz     1f
        /*
@@ -232,7 +256,7 @@ SYM_FUNC_START(startup_32)
         * the correct stack alignment for entry.
         */
        subl    $40, %esp
-       leal    efi_pe_entry(%ebp), %eax
+       leal    rva(efi_pe_entry)(%ebp), %eax
        movl    %edi, %ecx                      // MS calling convention
        movl    %esi, %edx
 1:
@@ -258,18 +282,18 @@ SYM_FUNC_START(efi32_stub_entry)
 
        call    1f
 1:     pop     %ebp
-       subl    $1b, %ebp
+       subl    $ rva(1b), %ebp
 
-       movl    %esi, efi32_boot_args+8(%ebp)
+       movl    %esi, rva(efi32_boot_args+8)(%ebp)
 SYM_INNER_LABEL(efi32_pe_stub_entry, SYM_L_LOCAL)
-       movl    %ecx, efi32_boot_args(%ebp)
-       movl    %edx, efi32_boot_args+4(%ebp)
-       movb    $0, efi_is64(%ebp)
+       movl    %ecx, rva(efi32_boot_args)(%ebp)
+       movl    %edx, rva(efi32_boot_args+4)(%ebp)
+       movb    $0, rva(efi_is64)(%ebp)
 
        /* Save firmware GDTR and code/data selectors */
-       sgdtl   efi32_boot_gdt(%ebp)
-       movw    %cs, efi32_boot_cs(%ebp)
-       movw    %ds, efi32_boot_ds(%ebp)
+       sgdtl   rva(efi32_boot_gdt)(%ebp)
+       movw    %cs, rva(efi32_boot_cs)(%ebp)
+       movw    %ds, rva(efi32_boot_ds)(%ebp)
 
        /* Disable paging */
        movl    %cr0, %eax
@@ -348,30 +372,11 @@ SYM_CODE_START(startup_64)
 
        /* Target address to relocate to for decompression */
        movl    BP_init_size(%rsi), %ebx
-       subl    $_end, %ebx
+       subl    $ rva(_end), %ebx
        addq    %rbp, %rbx
 
        /* Set up the stack */
-       leaq    boot_stack_end(%rbx), %rsp
-
-       /*
-        * paging_prepare() and cleanup_trampoline() below can have GOT
-        * references. Adjust the table with address we are running at.
-        *
-        * Zero RAX for adjust_got: the GOT was not adjusted before;
-        * there's no adjustment to undo.
-        */
-       xorq    %rax, %rax
-
-       /*
-        * Calculate the address the binary is loaded at and use it as
-        * a GOT adjustment.
-        */
-       call    1f
-1:     popq    %rdi
-       subq    $1b, %rdi
-
-       call    .Ladjust_got
+       leaq    rva(boot_stack_end)(%rbx), %rsp
 
        /*
         * At this point we are in long mode with 4-level paging enabled,
@@ -449,7 +454,7 @@ SYM_CODE_START(startup_64)
        lretq
 trampoline_return:
        /* Restore the stack, the 32-bit trampoline uses its own stack */
-       leaq    boot_stack_end(%rbx), %rsp
+       leaq    rva(boot_stack_end)(%rbx), %rsp
 
        /*
         * cleanup_trampoline() would restore trampoline memory.
@@ -461,7 +466,7 @@ trampoline_return:
         * this function call.
         */
        pushq   %rsi
-       leaq    top_pgtable(%rbx), %rdi
+       leaq    rva(top_pgtable)(%rbx), %rdi
        call    cleanup_trampoline
        popq    %rsi
 
@@ -469,30 +474,15 @@ trampoline_return:
        pushq   $0
        popfq
 
-       /*
-        * Previously we've adjusted the GOT with address the binary was
-        * loaded at. Now we need to re-adjust for relocation address.
-        *
-        * Calculate the address the binary is loaded at, so that we can
-        * undo the previous GOT adjustment.
-        */
-       call    1f
-1:     popq    %rax
-       subq    $1b, %rax
-
-       /* The new adjustment is the relocation address */
-       movq    %rbx, %rdi
-       call    .Ladjust_got
-
 /*
  * Copy the compressed kernel to the end of our buffer
  * where decompression in place becomes safe.
  */
        pushq   %rsi
        leaq    (_bss-8)(%rip), %rsi
-       leaq    (_bss-8)(%rbx), %rdi
-       movq    $_bss /* - $startup_32 */, %rcx
-       shrq    $3, %rcx
+       leaq    rva(_bss-8)(%rbx), %rdi
+       movl    $(_bss - startup_32), %ecx
+       shrl    $3, %ecx
        std
        rep     movsq
        cld
@@ -503,15 +493,15 @@ trampoline_return:
         * during extract_kernel below. To avoid any issues, repoint the GDTR
         * to the new copy of the GDT.
         */
-       leaq    gdt64(%rbx), %rax
-       leaq    gdt(%rbx), %rdx
+       leaq    rva(gdt64)(%rbx), %rax
+       leaq    rva(gdt)(%rbx), %rdx
        movq    %rdx, 2(%rax)
        lgdt    (%rax)
 
 /*
  * Jump to the relocated address.
  */
-       leaq    .Lrelocated(%rbx), %rax
+       leaq    rva(.Lrelocated)(%rbx), %rax
        jmp     *%rax
 SYM_CODE_END(startup_64)
 
@@ -523,7 +513,7 @@ SYM_FUNC_START_ALIAS(efi_stub_entry)
        movq    %rdx, %rbx                      /* save boot_params pointer */
        call    efi_main
        movq    %rbx,%rsi
-       leaq    startup_64(%rax), %rax
+       leaq    rva(startup_64)(%rax), %rax
        jmp     *%rax
 SYM_FUNC_END(efi64_stub_entry)
 SYM_FUNC_END_ALIAS(efi_stub_entry)
@@ -564,9 +554,9 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
        movq    %rsi, %rdi              /* real mode address */
        leaq    boot_heap(%rip), %rsi   /* malloc area for uncompression */
        leaq    input_data(%rip), %rdx  /* input_data */
-       movl    $z_input_len, %ecx      /* input_len */
+       movl    input_len(%rip), %ecx   /* input_len */
        movq    %rbp, %r8               /* output target address */
-       movl    $z_output_len, %r9d     /* decompressed length, end of relocs */
+       movl    output_len(%rip), %r9d  /* decompressed length, end of relocs */
        call    extract_kernel          /* returns kernel location in %rax */
        popq    %rsi
 
@@ -576,27 +566,6 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
        jmp     *%rax
 SYM_FUNC_END(.Lrelocated)
 
-/*
- * Adjust the global offset table
- *
- * RAX is the previous adjustment of the table to undo (use 0 if it's the
- * first time we touch GOT).
- * RDI is the new adjustment to apply.
- */
-.Ladjust_got:
-       /* Walk through the GOT adding the address to the entries */
-       leaq    _got(%rip), %rdx
-       leaq    _egot(%rip), %rcx
-1:
-       cmpq    %rcx, %rdx
-       jae     2f
-       subq    %rax, (%rdx)    /* Undo previous adjustment */
-       addq    %rdi, (%rdx)    /* Apply the new adjustment */
-       addq    $8, %rdx
-       jmp     1b
-2:
-       ret
-
        .code32
 /*
  * This is the 32-bit trampoline that will be copied over to low memory.
@@ -733,7 +702,7 @@ SYM_DATA(efi_is64, .byte 1)
 #define BS32_handle_protocol   88 // offsetof(efi_boot_services_32_t, handle_protocol)
 #define LI32_image_base                32 // offsetof(efi_loaded_image_32_t, image_base)
 
-       .text
+       __HEAD
        .code32
 SYM_FUNC_START(efi32_pe_entry)
 /*
@@ -755,12 +724,12 @@ SYM_FUNC_START(efi32_pe_entry)
 
        call    1f
 1:     pop     %ebx
-       subl    $1b, %ebx
+       subl    $ rva(1b), %ebx
 
        /* Get the loaded image protocol pointer from the image handle */
        leal    -4(%ebp), %eax
        pushl   %eax                            // &loaded_image
-       leal    loaded_image_proto(%ebx), %eax
+       leal    rva(loaded_image_proto)(%ebx), %eax
        pushl   %eax                            // pass the GUID address
        pushl   8(%ebp)                         // pass the image handle
 
@@ -795,7 +764,7 @@ SYM_FUNC_START(efi32_pe_entry)
         * use it before we get to the 64-bit efi_pe_entry() in C code.
         */
        subl    %esi, %ebx
-       movl    %ebx, image_offset(%ebp)        // save image_offset
+       movl    %ebx, rva(image_offset)(%ebp)   // save image_offset
        jmp     efi32_pe_stub_entry
 
 2:     popl    %edi                            // restore callee-save registers