Skip to content

Commit 24d33ac

Browse files
committed
powerpc/64s: Make prom_init require RELOCATABLE
When we boot from open firmware (OF) using PPC_OF_BOOT_TRAMPOLINE, aka. prom_init, we run parts of the kernel at an address other than the link address. That happens because OF loads the kernel above zero (OF is at zero) and we run prom_init before copying the kernel down to zero. Currently that works even for non-relocatable kernels, because we do various fixups to the prom_init code to make it run where it's loaded. However those fixups are not sufficient if the kernel becomes large enough. In that case prom_init()'s final call to __start() can end up generating a plt branch: bl c000000002000018 <00000078.plt_branch.__start> That results in the kernel jumping to the linked address of __start, 0xc000000000000000, when really it needs to jump to the 0xc000000000000000 + the runtime address because the kernel is still running at the load address. We could do further shenanigans to handle that, see Jordan's patch for example: https://lore.kernel.org/linuxppc-dev/[email protected] However it is much simpler to just require a kernel with prom_init() to be built relocatable. The result works in all configurations without further work, and requires less code. This should have no effect on most people, as our defconfigs and essentially all distro configs already have RELOCATABLE enabled. Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent c6c27e3 commit 24d33ac

File tree

2 files changed

+3
-56
lines changed

2 files changed

+3
-56
lines changed

arch/powerpc/kernel/prom_init.c

Lines changed: 2 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,54 +3243,6 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
32433243
#endif /* CONFIG_BLK_DEV_INITRD */
32443244
}
32453245

3246-
#ifdef CONFIG_PPC64
3247-
#ifdef CONFIG_RELOCATABLE
3248-
static void reloc_toc(void)
3249-
{
3250-
}
3251-
3252-
static void unreloc_toc(void)
3253-
{
3254-
}
3255-
#else
3256-
static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
3257-
{
3258-
unsigned long i;
3259-
unsigned long *toc_entry;
3260-
3261-
/* Get the start of the TOC by using r2 directly. */
3262-
asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
3263-
3264-
for (i = 0; i < nr_entries; i++) {
3265-
*toc_entry = *toc_entry + offset;
3266-
toc_entry++;
3267-
}
3268-
}
3269-
3270-
static void reloc_toc(void)
3271-
{
3272-
unsigned long offset = reloc_offset();
3273-
unsigned long nr_entries =
3274-
(__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3275-
3276-
__reloc_toc(offset, nr_entries);
3277-
3278-
mb();
3279-
}
3280-
3281-
static void unreloc_toc(void)
3282-
{
3283-
unsigned long offset = reloc_offset();
3284-
unsigned long nr_entries =
3285-
(__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3286-
3287-
mb();
3288-
3289-
__reloc_toc(-offset, nr_entries);
3290-
}
3291-
#endif
3292-
#endif
3293-
32943246
#ifdef CONFIG_PPC_SVM
32953247
/*
32963248
* Perform the Enter Secure Mode ultracall.
@@ -3324,14 +3276,12 @@ static void __init setup_secure_guest(unsigned long kbase, unsigned long fdt)
33243276
* relocated it so the check will fail. Restore the original image by
33253277
* relocating it back to the kernel virtual base address.
33263278
*/
3327-
if (IS_ENABLED(CONFIG_RELOCATABLE))
3328-
relocate(KERNELBASE);
3279+
relocate(KERNELBASE);
33293280

33303281
ret = enter_secure_mode(kbase, fdt);
33313282

33323283
/* Relocate the kernel again. */
3333-
if (IS_ENABLED(CONFIG_RELOCATABLE))
3334-
relocate(kbase);
3284+
relocate(kbase);
33353285

33363286
if (ret != U_SUCCESS) {
33373287
prom_printf("Returned %d from switching to secure mode.\n", ret);
@@ -3359,8 +3309,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
33593309
#ifdef CONFIG_PPC32
33603310
unsigned long offset = reloc_offset();
33613311
reloc_got2(offset);
3362-
#else
3363-
reloc_toc();
33643312
#endif
33653313

33663314
/*
@@ -3537,8 +3485,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
35373485

35383486
#ifdef CONFIG_PPC32
35393487
reloc_got2(-offset);
3540-
#else
3541-
unreloc_toc();
35423488
#endif
35433489

35443490
/* Move to secure memory if we're supposed to be secure guests. */

arch/powerpc/platforms/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ config PPC_NATIVE
5151
config PPC_OF_BOOT_TRAMPOLINE
5252
bool "Support booting from Open Firmware or yaboot"
5353
depends on PPC_BOOK3S_32 || PPC64
54+
select RELOCATABLE if PPC64
5455
default y
5556
help
5657
Support from booting from Open Firmware or yaboot using an

0 commit comments

Comments
 (0)