diff options
Diffstat (limited to 'arch/x86/boot/compressed/head_64.S')
-rw-r--r-- | arch/x86/boot/compressed/head_64.S | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 2884e0c3e8a5..50f69c7eaaf4 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -32,6 +32,33 @@ #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) @@ -252,10 +279,13 @@ ENTRY(efi_pe_entry) 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 @@ -271,10 +301,13 @@ handover_entry: 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 @@ -385,19 +418,8 @@ relocated: 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.. */ @@ -437,6 +459,10 @@ gdt: .quad 0x0000000000000000 /* TS continued */ gdt_end: +/* Have we relocated the GOT? */ +got_fixed: + .byte 0 + #ifdef CONFIG_EFI_STUB efi_config: .quad 0 |