x86/boot: Remove run-time relocations from .head.text code
[linux-2.6-microblaze.git] / arch / x86 / boot / compressed / head_32.S
index 39f0bb4..8c1a4f5 100644 (file)
 #include <asm/bootparam.h>
 
 /*
- * The 32-bit x86 assembler in binutils 2.26 will generate R_386_GOT32X
- * relocation to get the symbol address in PIC.  When the compressed x86
- * kernel isn't built as PIC, the linker optimizes R_386_GOT32X
- * relocations to their fixed symbol addresses.  However, when the
- * compressed x86 kernel is loaded at a different address, it leads
- * to the following load failure:
- *
- *   Failed to allocate space for phdrs
- *
- * during the decompression stage.
- *
- * If the compressed x86 kernel is relocatable at run-time, it should be
- * compiled with -fPIE, instead of -fPIC, if possible and should be built as
- * Position Independent Executable (PIE) so that linker won't optimize
- * R_386_GOT32X relocation to its fixed symbol address.  Older
- * linkers generate R_386_32 relocations against locally defined symbols,
- * _bss, _ebss and _end, in PIE.  It isn't wrong, just less optimal than
- * R_386_RELATIVE.  But the x86 kernel fails to properly handle R_386_32
- * relocations when relocating the kernel.  To generate R_386_RELATIVE
- * relocations, we mark _bss, _ebss and _end as hidden:
+ * These symbols needed to be marked as .hidden to prevent the BFD linker from
+ * generating R_386_32 (rather than R_386_RELATIVE) relocations for them when
+ * the 32-bit compressed kernel is linked as PIE. This is no longer necessary,
+ * but it doesn't hurt to keep them .hidden.
  */
        .hidden _bss
        .hidden _ebss
@@ -74,10 +58,10 @@ SYM_FUNC_START(startup_32)
        leal    (BP_scratch+4)(%esi), %esp
        call    1f
 1:     popl    %edx
-       subl    $1b, %edx
+       addl    $_GLOBAL_OFFSET_TABLE_+(.-1b), %edx
 
        /* Load new GDT */
-       leal    gdt(%edx), %eax
+       leal    gdt@GOTOFF(%edx), %eax
        movl    %eax, 2(%eax)
        lgdt    (%eax)
 
@@ -90,14 +74,16 @@ SYM_FUNC_START(startup_32)
        movl    %eax, %ss
 
 /*
- * %edx contains the address we are loaded at by the boot loader and %ebx
- * contains the address where we should move the kernel image temporarily
- * for safe in-place decompression. %ebp contains the address that the kernel
- * will be decompressed to.
+ * %edx contains the address we are loaded at by the boot loader (plus the
+ * offset to the GOT).  The below code calculates %ebx to be the address where
+ * we should move the kernel image temporarily for safe in-place decompression
+ * (again, plus the offset to the GOT).
+ *
+ * %ebp is calculated to be the address that the kernel will be decompressed to.
  */
 
 #ifdef CONFIG_RELOCATABLE
-       movl    %edx, %ebx
+       leal    startup_32@GOTOFF(%edx), %ebx
 
 #ifdef CONFIG_EFI_STUB
 /*
@@ -108,7 +94,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(%edx), %ebx
+       subl    image_offset@GOTOFF(%edx), %ebx
 #endif
 
        movl    BP_kernel_alignment(%esi), %eax
@@ -125,10 +111,10 @@ SYM_FUNC_START(startup_32)
        movl    %ebx, %ebp      // Save the output address for later
        /* Target address to relocate to for decompression */
        addl    BP_init_size(%esi), %ebx
-       subl    $_end, %ebx
+       subl    $_end@GOTOFF, %ebx
 
        /* Set up the stack */
-       leal    boot_stack_end(%ebx), %esp
+       leal    boot_stack_end@GOTOFF(%ebx), %esp
 
        /* Zero EFLAGS */
        pushl   $0
@@ -139,8 +125,8 @@ SYM_FUNC_START(startup_32)
  * where decompression in place becomes safe.
  */
        pushl   %esi
-       leal    (_bss-4)(%edx), %esi
-       leal    (_bss-4)(%ebx), %edi
+       leal    (_bss@GOTOFF-4)(%edx), %esi
+       leal    (_bss@GOTOFF-4)(%ebx), %edi
        movl    $(_bss - startup_32), %ecx
        shrl    $2, %ecx
        std
@@ -153,14 +139,14 @@ SYM_FUNC_START(startup_32)
         * during extract_kernel below. To avoid any issues, repoint the GDTR
         * to the new copy of the GDT.
         */
-       leal    gdt(%ebx), %eax
+       leal    gdt@GOTOFF(%ebx), %eax
        movl    %eax, 2(%eax)
        lgdt    (%eax)
 
 /*
  * Jump to the relocated address.
  */
-       leal    .Lrelocated(%ebx), %eax
+       leal    .Lrelocated@GOTOFF(%ebx), %eax
        jmp     *%eax
 SYM_FUNC_END(startup_32)
 
@@ -170,7 +156,7 @@ SYM_FUNC_START_ALIAS(efi_stub_entry)
        add     $0x4, %esp
        movl    8(%esp), %esi   /* save boot_params pointer */
        call    efi_main
-       leal    startup_32(%eax), %eax
+       /* efi_main returns the possibly relocated address of startup_32 */
        jmp     *%eax
 SYM_FUNC_END(efi32_stub_entry)
 SYM_FUNC_END_ALIAS(efi_stub_entry)
@@ -183,8 +169,8 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
  * Clear BSS (stack is currently empty)
  */
        xorl    %eax, %eax
-       leal    _bss(%ebx), %edi
-       leal    _ebss(%ebx), %ecx
+       leal    _bss@GOTOFF(%ebx), %edi
+       leal    _ebss@GOTOFF(%ebx), %ecx
        subl    %edi, %ecx
        shrl    $2, %ecx
        rep     stosl
@@ -198,9 +184,9 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
        pushl   %ebp            /* output address */
 
        pushl   $z_input_len    /* input_len */
-       leal    input_data(%ebx), %eax
+       leal    input_data@GOTOFF(%ebx), %eax
        pushl   %eax            /* input_data */
-       leal    boot_heap(%ebx), %eax
+       leal    boot_heap@GOTOFF(%ebx), %eax
        pushl   %eax            /* heap area */
        pushl   %esi            /* real mode pointer */
        call    extract_kernel  /* returns kernel location in %eax */