Skip to content

Commit

Permalink
powerpc: Fix -mcmodel=medium breakage in prom_init.c
Browse files Browse the repository at this point in the history
Commit 5ac47f7 (powerpc: Relocate prom_init.c on 64bit) made
prom_init.c position independent by manually relocating its entries
in the TOC.

We get the address of the TOC entries with the __prom_init_toc_start
linker symbol. If __prom_init_toc_start ends up as an entry in the
TOC then we need to add an offset to get the current address. This is
the case for older toolchains.

On the other hand, if we have a newer toolchain that supports
-mcmodel=medium then __prom_init_toc_start will be created by a
relative offset from r2 (the TOC pointer). Since r2 has already been
relocated, nothing more needs to be done.  Adding an offset in this
case is wrong and Aaro Koskinen and Alexander Graf have noticed noticed
G5 and OpenBIOS breakage.

Alan Modra suggested we just use r2 to get at the TOC which is simpler
and works with both old and new toolchains.

Reported-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Anton Blanchard <anton@samba.org>
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
antonblanchard authored and ozbenh committed Mar 12, 2013
1 parent ff2d758 commit 1674400
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions arch/powerpc/kernel/prom_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -2832,11 +2832,13 @@ static void unreloc_toc(void)
{
}
#else
static void __reloc_toc(void *tocstart, unsigned long offset,
unsigned long nr_entries)
static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
{
unsigned long i;
unsigned long *toc_entry = (unsigned long *)tocstart;
unsigned long *toc_entry;

/* Get the start of the TOC by using r2 directly. */
asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));

for (i = 0; i < nr_entries; i++) {
*toc_entry = *toc_entry + offset;
Expand All @@ -2850,8 +2852,7 @@ static void reloc_toc(void)
unsigned long nr_entries =
(__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);

/* Need to add offset to get at __prom_init_toc_start */
__reloc_toc(__prom_init_toc_start + offset, offset, nr_entries);
__reloc_toc(offset, nr_entries);

mb();
}
Expand All @@ -2864,8 +2865,7 @@ static void unreloc_toc(void)

mb();

/* __prom_init_toc_start has been relocated, no need to add offset */
__reloc_toc(__prom_init_toc_start, -offset, nr_entries);
__reloc_toc(-offset, nr_entries);
}
#endif
#endif
Expand Down

0 comments on commit 1674400

Please sign in to comment.