Making the powerpc64 relocatable
Nathan Whitehorn
nwhitehorn at freebsd.org
Wed Jan 21 19:32:26 UTC 2015
In order to run natively on POWER8 hardware, the 64-bit PPC kernel needs
to be relocatable. Some architectures do this by executing the kernel at
a fixed virtual address with varying physical addresses. For PPC64, the
kernel has a 1:1 direct map and the ABI is always PIC, so it's easier
just to keep the 1:1 mapping and make both the kernel physical and
virtual address range float (patch attached and at
http://people.freebsd.org/~nwhitehorn/ppc64-pie-kernel.diff in case it
gets stripped).
This is the first architecture to have a PIE kernel, however, so I'd
like some feedback on the approach. The major immediate difficulty is
that PIE kernels are ET_DYN ELF executables. loader, however, thinks the
kernel must be ET_EXEC and that anything that is ET_DYN is a loadable
module. I have a somewhat hacky workaround in the patches to loader and
kmod.mk, which uses the ELF entrypoint to decide whether something is a
kernel or not (setting it to zero for modules). It's the simplest
approach but I'm not sure the best one.
-Nathan
-------------- next part --------------
Index: boot/common/load_elf.c
===================================================================
--- boot/common/load_elf.c (revision 277438)
+++ boot/common/load_elf.c (working copy)
@@ -175,7 +175,11 @@
* Check to see what sort of module we are.
*/
kfp = file_findfile(NULL, __elfN(kerneltype));
+#if defined(__powerpc__) && __ELF_WORD_SIZE == 64
+ if (ehdr->e_type == ET_DYN && ehdr->e_entry == 0) {
+#else
if (ehdr->e_type == ET_DYN) {
+#endif
/* Looks like a kld module */
if (multiboot != 0) {
printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n");
@@ -195,7 +199,12 @@
/* Looks OK, got ahead */
ef.kernel = 0;
+#if defined(__powerpc__) && __ELF_WORD_SIZE == 64
+ } else if (ehdr->e_type == ET_EXEC ||
+ (ehdr->e_type == ET_DYN && ehdr->e_entry != 0)) {
+#else
} else if (ehdr->e_type == ET_EXEC) {
+#endif
/* Looks like a kernel */
if (kfp != NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n");
Index: conf/Makefile.powerpc
===================================================================
--- conf/Makefile.powerpc (revision 277438)
+++ conf/Makefile.powerpc (working copy)
@@ -37,6 +37,11 @@
CFLAGS+= -msoft-float -Wa,-many
+.if ${MACHINE_ARCH} == "powerpc64"
+CFLAGS+= -fPIC
+LDFLAGS+= -pie
+.endif
+
.if !empty(DDB_ENABLED)
CFLAGS+= -fno-omit-frame-pointer
.endif
Index: conf/kmod.mk
===================================================================
--- conf/kmod.mk (revision 277438)
+++ conf/kmod.mk (working copy)
@@ -179,6 +179,9 @@
${OBJCOPY} --only-keep-debug ${FULLPROG} ${.TARGET}
.endif
+# Don't add a fake entry point to modules
+_LDFLAGS+= -e 0
+
.if ${__KLD_SHARED} == yes
${FULLPROG}: ${KMOD}.kld
${LD} -Bshareable ${_LDFLAGS} -o ${.TARGET} ${KMOD}.kld
More information about the freebsd-ppc
mailing list