x86-64: Handle PC-relative relocations on per-CPU data
This is in preparation of using RIP-relative addressing in many of the per-CPU accesses. Signed-off-by: Jan Beulich <jbeulich@suse.com> Link: http://lkml.kernel.org/r/5458A15A0200007800044A9A@mail.emea.novell.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
2c773dd31f
commit
6d24c5f72d
|
@ -260,7 +260,7 @@ static void handle_relocations(void *output, unsigned long output_len)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process relocations: 32 bit relocations first then 64 bit after.
|
* Process relocations: 32 bit relocations first then 64 bit after.
|
||||||
* Two sets of binary relocations are added to the end of the kernel
|
* Three sets of binary relocations are added to the end of the kernel
|
||||||
* before compression. Each relocation table entry is the kernel
|
* before compression. Each relocation table entry is the kernel
|
||||||
* address of the location which needs to be updated stored as a
|
* address of the location which needs to be updated stored as a
|
||||||
* 32-bit value which is sign extended to 64 bits.
|
* 32-bit value which is sign extended to 64 bits.
|
||||||
|
@ -270,6 +270,8 @@ static void handle_relocations(void *output, unsigned long output_len)
|
||||||
* kernel bits...
|
* kernel bits...
|
||||||
* 0 - zero terminator for 64 bit relocations
|
* 0 - zero terminator for 64 bit relocations
|
||||||
* 64 bit relocation repeated
|
* 64 bit relocation repeated
|
||||||
|
* 0 - zero terminator for inverse 32 bit relocations
|
||||||
|
* 32 bit inverse relocation repeated
|
||||||
* 0 - zero terminator for 32 bit relocations
|
* 0 - zero terminator for 32 bit relocations
|
||||||
* 32 bit relocation repeated
|
* 32 bit relocation repeated
|
||||||
*
|
*
|
||||||
|
@ -286,6 +288,16 @@ static void handle_relocations(void *output, unsigned long output_len)
|
||||||
*(uint32_t *)ptr += delta;
|
*(uint32_t *)ptr += delta;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_X86_64
|
#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--) {
|
for (reloc--; *reloc; reloc--) {
|
||||||
long extended = *reloc;
|
long extended = *reloc;
|
||||||
extended += map;
|
extended += map;
|
||||||
|
|
|
@ -20,7 +20,10 @@ struct relocs {
|
||||||
|
|
||||||
static struct relocs relocs16;
|
static struct relocs relocs16;
|
||||||
static struct relocs relocs32;
|
static struct relocs relocs32;
|
||||||
|
#if ELF_BITS == 64
|
||||||
|
static struct relocs relocs32neg;
|
||||||
static struct relocs relocs64;
|
static struct relocs relocs64;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct section {
|
struct section {
|
||||||
Elf_Shdr shdr;
|
Elf_Shdr shdr;
|
||||||
|
@ -762,11 +765,16 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
|
||||||
|
|
||||||
switch (r_type) {
|
switch (r_type) {
|
||||||
case R_X86_64_NONE:
|
case R_X86_64_NONE:
|
||||||
|
/* NONE can be ignored. */
|
||||||
|
break;
|
||||||
|
|
||||||
case R_X86_64_PC32:
|
case R_X86_64_PC32:
|
||||||
/*
|
/*
|
||||||
* NONE can be ignored and PC relative relocations don't
|
* PC relative relocations don't need to be adjusted unless
|
||||||
* need to be adjusted.
|
* referencing a percpu symbol.
|
||||||
*/
|
*/
|
||||||
|
if (is_percpu_sym(sym, symname))
|
||||||
|
add_reloc(&relocs32neg, offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_X86_64_32:
|
case R_X86_64_32:
|
||||||
|
@ -986,7 +994,10 @@ static void emit_relocs(int as_text, int use_real_mode)
|
||||||
/* Order the relocations for more efficient processing */
|
/* Order the relocations for more efficient processing */
|
||||||
sort_relocs(&relocs16);
|
sort_relocs(&relocs16);
|
||||||
sort_relocs(&relocs32);
|
sort_relocs(&relocs32);
|
||||||
|
#if ELF_BITS == 64
|
||||||
|
sort_relocs(&relocs32neg);
|
||||||
sort_relocs(&relocs64);
|
sort_relocs(&relocs64);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Print the relocations */
|
/* Print the relocations */
|
||||||
if (as_text) {
|
if (as_text) {
|
||||||
|
@ -1007,14 +1018,21 @@ static void emit_relocs(int as_text, int use_real_mode)
|
||||||
for (i = 0; i < relocs32.count; i++)
|
for (i = 0; i < relocs32.count; i++)
|
||||||
write_reloc(relocs32.offset[i], stdout);
|
write_reloc(relocs32.offset[i], stdout);
|
||||||
} else {
|
} else {
|
||||||
if (ELF_BITS == 64) {
|
#if ELF_BITS == 64
|
||||||
/* Print a stop */
|
/* Print a stop */
|
||||||
write_reloc(0, stdout);
|
write_reloc(0, stdout);
|
||||||
|
|
||||||
/* Now print each relocation */
|
/* Now print each relocation */
|
||||||
for (i = 0; i < relocs64.count; i++)
|
for (i = 0; i < relocs64.count; i++)
|
||||||
write_reloc(relocs64.offset[i], stdout);
|
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 */
|
/* Print a stop */
|
||||||
write_reloc(0, stdout);
|
write_reloc(0, stdout);
|
||||||
|
|
Loading…
Reference in New Issue