Date: Wed, 21 Jan 2015 11:32:18 -0800 From: Nathan Whitehorn <nwhitehorn@freebsd.org> To: freebsd-arch@freebsd.org, FreeBSD PowerPC ML <freebsd-ppc@freebsd.org> Subject: Making the powerpc64 relocatable Message-ID: <54BFFEC2.5070909@freebsd.org>
index | next in thread | raw e-mail
[-- Attachment #1 --] 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 [-- Attachment #2 --] 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}.kldhelp
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?54BFFEC2.5070909>
