#include <asm/boot.h>
 #include <asm/asm-offsets.h>
 
+/*
+ * Adjust our own GOT
+ *
+ * The relocation base must be in %ebx
+ *
+ * It is safe to call this macro more than once, because in some of the
+ * code paths multiple invocations are inevitable, e.g. via the efi*
+ * entry points.
+ *
+ * Relocation is only performed the first time.
+ */
+.macro FIXUP_GOT
+       cmpb    $1, got_fixed(%ebx)
+       je      2f
+
+       leal    _got(%ebx), %edx
+       leal    _egot(%ebx), %ecx
+1:
+       cmpl    %ecx, %edx
+       jae     2f
+       addl    %ebx, (%edx)
+       addl    $4, %edx
+       jmp     1b
+2:
+       movb    $1, got_fixed(%ebx)
+.endm
+
        __HEAD
 ENTRY(startup_32)
 #ifdef CONFIG_EFI_STUB
        add     %esi, 88(%eax)
        pushl   %eax
 
+       movl    %esi, %ebx
+       FIXUP_GOT
+
        call    make_boot_params
        cmpl    $0, %eax
        je      fail
        leal    efi32_config(%esi), %eax
        add     %esi, 88(%eax)
        pushl   %eax
+
+       movl    %esi, %ebx
+       FIXUP_GOT
+
 2:
        call    efi_main
        cmpl    $0, %eax
        shrl    $2, %ecx
        rep     stosl
 
-/*
- * Adjust our own GOT
- */
-       leal    _got(%ebx), %edx
-       leal    _egot(%ebx), %ecx
-1:
-       cmpl    %ecx, %edx
-       jae     2f
-       addl    %ebx, (%edx)
-       addl    $4, %edx
-       jmp     1b
-2:
-
+       FIXUP_GOT
 /*
  * Do the decompression, and jump to the new kernel..
  */
        xorl    %ebx, %ebx
        jmp     *%eax
 
-#ifdef CONFIG_EFI_STUB
        .data
+/* Have we relocated the GOT? */
+got_fixed:
+       .byte 0
+
+#ifdef CONFIG_EFI_STUB
 efi32_config:
        .fill 11,8,0
        .long efi_call_phys
 
 #include <asm/processor-flags.h>
 #include <asm/asm-offsets.h>
 
+/*
+ * Adjust our own GOT
+ *
+ * The relocation base must be in %rbx
+ *
+ * It is safe to call this macro more than once, because in some of the
+ * code paths multiple invocations are inevitable, e.g. via the efi*
+ * entry points.
+ *
+ * Relocation is only performed the first time.
+ */
+.macro FIXUP_GOT
+       cmpb    $1, got_fixed(%rip)
+       je      2f
+
+       leaq    _got(%rip), %rdx
+       leaq    _egot(%rip), %rcx
+1:
+       cmpq    %rcx, %rdx
+       jae     2f
+       addq    %rbx, (%rdx)
+       addq    $8, %rdx
+       jmp     1b
+2:
+       movb    $1, got_fixed(%rip)
+.endm
+
        __HEAD
        .code32
 ENTRY(startup_32)
        subq    $1b, %rbp
 
        /*
-        * Relocate efi_config->call().
+        * Relocate efi_config->call() and the GOT entries.
         */
        addq    %rbp, efi64_config+88(%rip)
 
+       movq    %rbp, %rbx
+       FIXUP_GOT
+
        movq    %rax, %rdi
        call    make_boot_params
        cmpq    $0,%rax
        subq    $1b, %rbp
 
        /*
-        * Relocate efi_config->call().
+        * Relocate efi_config->call() and the GOT entries.
         */
        movq    efi_config(%rip), %rax
        addq    %rbp, 88(%rax)
+
+       movq    %rbp, %rbx
+       FIXUP_GOT
 2:
        movq    efi_config(%rip), %rdi
        call    efi_main
        shrq    $3, %rcx
        rep     stosq
 
-/*
- * Adjust our own GOT
- */
-       leaq    _got(%rip), %rdx
-       leaq    _egot(%rip), %rcx
-1:
-       cmpq    %rcx, %rdx
-       jae     2f
-       addq    %rbx, (%rdx)
-       addq    $8, %rdx
-       jmp     1b
-2:
-       
+       FIXUP_GOT
+
 /*
  * Do the decompression, and jump to the new kernel..
  */
        .quad   0x0000000000000000      /* TS continued */
 gdt_end:
 
+/* Have we relocated the GOT? */
+got_fixed:
+       .byte   0
+
 #ifdef CONFIG_EFI_STUB
 efi_config:
        .quad   0