Discussion:
[PATCH] powerpc: Fix kernel-jump address for ppc64 wrapper boot
He Ying
2021-06-04 09:22:28 UTC
Permalink
From "64-bit PowerPC ELF Application Binary Interface Supplement 1.9",
we know that the value of a function pointer in a language like C is
the address of the function descriptor and the first doubleword
of the function descriptor contains the address of the entry point
of the function.

So, when we want to jump to an address (e.g. addr) to execute for
PPC-elf64abi, we should assign the address of addr *NOT* addr itself
to the function pointer or system will jump to the wrong address.

Link: https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-DES
Signed-off-by: He Ying <***@huawei.com>
---
arch/powerpc/boot/main.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index cae31a6e8f02..50fd7f11b642 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -268,7 +268,16 @@ void start(void)
if (console_ops.close)
console_ops.close();

+#ifdef CONFIG_PPC64_BOOT_WRAPPER
+ /*
+ * For PPC-elf64abi, the value of a function pointer is the address
+ * of the function descriptor. And the first doubleword of a function
+ * descriptor contains the address of the entry point of the function.
+ */
+ kentry = (kernel_entry_t) &vmlinux.addr;
+#else
kentry = (kernel_entry_t) vmlinux.addr;
+#endif
if (ft_addr) {
if(platform_ops.kentry)
platform_ops.kentry(ft_addr, vmlinux.addr);
--
2.17.1
Christophe Leroy
2021-06-08 04:55:35 UTC
Permalink
Post by He Ying
From "64-bit PowerPC ELF Application Binary Interface Supplement 1.9",
we know that the value of a function pointer in a language like C is
the address of the function descriptor and the first doubleword
of the function descriptor contains the address of the entry point
of the function.
So, when we want to jump to an address (e.g. addr) to execute for
PPC-elf64abi, we should assign the address of addr *NOT* addr itself
to the function pointer or system will jump to the wrong address.
Link: https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-DES
---
arch/powerpc/boot/main.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index cae31a6e8f02..50fd7f11b642 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -268,7 +268,16 @@ void start(void)
if (console_ops.close)
console_ops.close();
+#ifdef CONFIG_PPC64_BOOT_WRAPPER
This kind of need doesn't desserve a #ifdef, see
https://www.kernel.org/doc/html/latest/process/coding-style.html#conditional-compilation

You can do:


kentry = (kernel_entry_t)(IS_ENABLED(CONFIG_PPC64_BOOT_WRAPPER) ? &vmlinux.addr : vmlinux.addr);


Or, if you prefer something less compact:


if (IS_ENABLED(CONFIG_PPC64_BOOT_WRAPPER))
kentry = (kernel_entry_t) &vmlinux.addr;
else
kentry = (kernel_entry_t) vmlinux.addr;
Post by He Ying
+ /*
+ * For PPC-elf64abi, the value of a function pointer is the address
+ * of the function descriptor. And the first doubleword of a function
+ * descriptor contains the address of the entry point of the function.
+ */
+ kentry = (kernel_entry_t) &vmlinux.addr;
+#else
kentry = (kernel_entry_t) vmlinux.addr;
+#endif
if (ft_addr) {
if(platform_ops.kentry)
platform_ops.kentry(ft_addr, vmlinux.addr);
Oliver O'Halloran
2021-06-08 05:26:41 UTC
Permalink
Post by He Ying
From "64-bit PowerPC ELF Application Binary Interface Supplement 1.9",
we know that the value of a function pointer in a language like C is
the address of the function descriptor and the first doubleword
of the function descriptor contains the address of the entry point
of the function.
So, when we want to jump to an address (e.g. addr) to execute for
PPC-elf64abi, we should assign the address of addr *NOT* addr itself
to the function pointer or system will jump to the wrong address.
How have you tested this?

IIRC the 64bit wrapper is only used for ppc64le builds. For that case
the current code is work because the LE ABI (ABIv2) doesn't use
function descriptors. I think even for a BE kernel we need the current
behaviour because the vmlinux's entry point is screwed up (i.e.
doesn't point a descriptor) and tools in the wild (probably kexec)
expect it to be screwed up.

ABIv2 (LE) reference:
https://openpowerfoundation.org/?resource_lib=64-bit-elf-v2-abi-specification-power-architecture
Loading...