]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
x86/boot/64: Remove inverse relocations
authorBrian Gerst <brgerst@gmail.com>
Thu, 23 Jan 2025 19:07:42 +0000 (14:07 -0500)
committerIngo Molnar <mingo@kernel.org>
Tue, 18 Feb 2025 09:15:47 +0000 (10:15 +0100)
Inverse relocations were needed to offset the effects of relocation for
RIP-relative accesses to zero-based percpu data.  Now that the percpu
section is linked normally as part of the kernel image, they are no
longer needed.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/20250123190747.745588-11-brgerst@gmail.com
arch/x86/boot/compressed/misc.c
arch/x86/tools/relocs.c

index 0d37420cad0259554f8160dea0c502cb7e2fc6cd..1cdcd4aaf39555dc1701ec60f8251ed33eeeba89 100644 (file)
@@ -235,7 +235,7 @@ static void handle_relocations(void *output, unsigned long output_len,
 
        /*
         * Process relocations: 32 bit relocations first then 64 bit after.
-        * Three sets of binary relocations are added to the end of the kernel
+        * Two sets of binary relocations are added to the end of the kernel
         * before compression. Each relocation table entry is the kernel
         * address of the location which needs to be updated stored as a
         * 32-bit value which is sign extended to 64 bits.
@@ -245,8 +245,6 @@ static void handle_relocations(void *output, unsigned long output_len,
         * kernel bits...
         * 0 - zero terminator for 64 bit relocations
         * 64 bit relocation repeated
-        * 0 - zero terminator for inverse 32 bit relocations
-        * 32 bit inverse relocation repeated
         * 0 - zero terminator for 32 bit relocations
         * 32 bit relocation repeated
         *
@@ -263,16 +261,6 @@ static void handle_relocations(void *output, unsigned long output_len,
                *(uint32_t *)ptr += delta;
        }
 #ifdef CONFIG_X86_64
-       while (*--reloc) {
-               long extended = *reloc;
-               extended += map;
-
-               ptr = (unsigned long)extended;
-               if (ptr < min_addr || ptr > max_addr)
-                       error("inverse 32-bit relocation outside of kernel!\n");
-
-               *(int32_t *)ptr -= delta;
-       }
        for (reloc--; *reloc; reloc--) {
                long extended = *reloc;
                extended += map;
index b5e3695a06158f27faafc6d288b99ab0b4abfe79..ae6962665b351ab1cdbf5e453a895fd7cec53b12 100644 (file)
@@ -29,7 +29,6 @@ static struct relocs          relocs16;
 static struct relocs           relocs32;
 
 #if ELF_BITS == 64
-static struct relocs           relocs32neg;
 static struct relocs           relocs64;
 # define FMT PRIu64
 
@@ -91,7 +90,6 @@ static const char * const     sym_regex_kernel[S_NSYMTYPES] = {
        "__initramfs_start|"
        "(jiffies|jiffies_64)|"
 #if ELF_BITS == 64
-       "__per_cpu_load|"
        "init_per_cpu__.*|"
        "__end_rodata_hpage_align|"
 #endif
@@ -290,34 +288,6 @@ static const char *sym_name(const char *sym_strtab, Elf_Sym *sym)
        return name;
 }
 
-static Elf_Sym *sym_lookup(const char *symname)
-{
-       int i;
-
-       for (i = 0; i < shnum; i++) {
-               struct section *sec = &secs[i];
-               long nsyms;
-               char *strtab;
-               Elf_Sym *symtab;
-               Elf_Sym *sym;
-
-               if (sec->shdr.sh_type != SHT_SYMTAB)
-                       continue;
-
-               nsyms = sec->shdr.sh_size/sizeof(Elf_Sym);
-               symtab = sec->symtab;
-               strtab = sec->link->strtab;
-
-               for (sym = symtab; --nsyms >= 0; sym++) {
-                       if (!sym->st_name)
-                               continue;
-                       if (strcmp(symname, strtab + sym->st_name) == 0)
-                               return sym;
-               }
-       }
-       return 0;
-}
-
 #if BYTE_ORDER == LITTLE_ENDIAN
 # define le16_to_cpu(val)      (val)
 # define le32_to_cpu(val)      (val)
@@ -766,78 +736,8 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel,
        }
 }
 
-/*
- * The .data..percpu section is a special case for x86_64 SMP kernels.
- * It is used to initialize the actual per_cpu areas and to provide
- * definitions for the per_cpu variables that correspond to their offsets
- * within the percpu area. Since the values of all of the symbols need
- * to be offsets from the start of the per_cpu area the virtual address
- * (sh_addr) of .data..percpu is 0 in SMP kernels.
- *
- * This means that:
- *
- *     Relocations that reference symbols in the per_cpu area do not
- *     need further relocation (since the value is an offset relative
- *     to the start of the per_cpu area that does not change).
- *
- *     Relocations that apply to the per_cpu area need to have their
- *     offset adjusted by by the value of __per_cpu_load to make them
- *     point to the correct place in the loaded image (because the
- *     virtual address of .data..percpu is 0).
- *
- * For non SMP kernels .data..percpu is linked as part of the normal
- * kernel data and does not require special treatment.
- *
- */
-static int per_cpu_shndx = -1;
-static Elf_Addr per_cpu_load_addr;
-
-static void percpu_init(void)
-{
-       int i;
-
-       for (i = 0; i < shnum; i++) {
-               ElfW(Sym) *sym;
-
-               if (strcmp(sec_name(i), ".data..percpu"))
-                       continue;
-
-               if (secs[i].shdr.sh_addr != 0)  /* non SMP kernel */
-                       return;
-
-               sym = sym_lookup("__per_cpu_load");
-               if (!sym)
-                       die("can't find __per_cpu_load\n");
-
-               per_cpu_shndx = i;
-               per_cpu_load_addr = sym->st_value;
-
-               return;
-       }
-}
-
 #if ELF_BITS == 64
 
-/*
- * Check to see if a symbol lies in the .data..percpu section.
- *
- * The linker incorrectly associates some symbols with the
- * .data..percpu section so we also need to check the symbol
- * name to make sure that we classify the symbol correctly.
- *
- * The GNU linker incorrectly associates:
- *     __init_begin
- *     __per_cpu_load
- *
- * The "gold" linker incorrectly associates:
- *     init_per_cpu__gdt_page
- */
-static int is_percpu_sym(ElfW(Sym) *sym, const char *symname)
-{
-       return 0;
-}
-
-
 static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
                      const char *symname)
 {
@@ -848,12 +748,6 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
        if (sym->st_shndx == SHN_UNDEF)
                return 0;
 
-       /*
-        * Adjust the offset if this reloc applies to the percpu section.
-        */
-       if (sec->shdr.sh_info == per_cpu_shndx)
-               offset += per_cpu_load_addr;
-
        switch (r_type) {
        case R_X86_64_NONE:
                /* NONE can be ignored. */
@@ -863,32 +757,21 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
        case R_X86_64_PLT32:
        case R_X86_64_REX_GOTPCRELX:
                /*
-                * PC relative relocations don't need to be adjusted unless
-                * referencing a percpu symbol.
+                * PC relative relocations don't need to be adjusted.
                 *
                 * NB: R_X86_64_PLT32 can be treated as R_X86_64_PC32.
                 */
-               if (is_percpu_sym(sym, symname))
-                       add_reloc(&relocs32neg, offset);
                break;
 
        case R_X86_64_PC64:
                /*
                 * Only used by jump labels
                 */
-               if (is_percpu_sym(sym, symname))
-                       die("Invalid R_X86_64_PC64 relocation against per-CPU symbol %s\n", symname);
                break;
 
        case R_X86_64_32:
        case R_X86_64_32S:
        case R_X86_64_64:
-               /*
-                * References to the percpu area don't need to be adjusted.
-                */
-               if (is_percpu_sym(sym, symname))
-                       break;
-
                if (shn_abs) {
                        /*
                         * Whitelisted absolute symbols do not require
@@ -1101,7 +984,6 @@ static void emit_relocs(int as_text, int use_real_mode)
        /* Order the relocations for more efficient processing */
        sort_relocs(&relocs32);
 #if ELF_BITS == 64
-       sort_relocs(&relocs32neg);
        sort_relocs(&relocs64);
 #else
        sort_relocs(&relocs16);
@@ -1133,13 +1015,6 @@ static void emit_relocs(int as_text, int use_real_mode)
                /* Now print each relocation */
                for (i = 0; i < relocs64.count; i++)
                        write_reloc(relocs64.offset[i], stdout);
-
-               /* Print a stop */
-               write_reloc(0, stdout);
-
-               /* Now print each inverse 32-bit relocation */
-               for (i = 0; i < relocs32neg.count; i++)
-                       write_reloc(relocs32neg.offset[i], stdout);
 #endif
 
                /* Print a stop */
@@ -1192,9 +1067,6 @@ void process(FILE *fp, int use_real_mode, int as_text,
        read_symtabs(fp);
        read_relocs(fp);
 
-       if (ELF_BITS == 64)
-               percpu_init();
-
        if (show_absolute_syms) {
                print_absolute_symbols();
                return;