Re: [PATCH 4/5] powerpc: Make the 64-bit kernel as a position-independent executable
On Fri, Sep 26, 2008 at 6:10 PM, Remi Machet <[EMAIL PROTECTED]> wrote: > Hi Paul, > > This patch breaks my build with the following error: > > /u1/rmachet/projects/c2k/linux-powerpc-git $ make cuImage.c2k modules > ARCH=powerpc V=1 > ... > powerpc-linux-gnu-ld -m elf32ppc -Bstatic -o .tmp_vmlinux1 -T > arch/powerpc/kernel/vmlinux.lds arch/powerpc/kernel/head_32.o > arch/powerpc/kernel/fpu.o init/built-in.o --start-group usr/built-in.o > arch/powerpc/kernel/built-in.o arch/powerpc/mm/built-in.o > arch/powerpc/lib/built-in.o arch/powerpc/sysdev/built-in.o > arch/powerpc/platforms/built-in.o kernel/built-in.o mm/built-in.o > fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o > block/built-in.o lib/lib.a lib/built-in.o drivers/built-in.o > sound/built-in.o firmware/built-in.o net/built-in.o --end-group > powerpc-linux-gnu-ld: BFD 2.16.1 internal error, aborting at > /u1/rmachet/project/crosstool/crosstool-0.43/build/powerpc-linux-gnu/gcc-4.1.1-glibc-2.3.6/binutils-2.16.1/bfd/elflink.c > line 6419 in elf_link_output_extsym > > powerpc-linux-gnu-ld: Please report this bug. I can confirm this problem. This patch breaks builds using binutils 2.16.1. It definitely looks like a binutils bug. It builds fine with 2.17. > > I isolated the problem to line 202 in arch/powerpc/kernel/vmlinux.lds.S: If I > remove that > line then the kernel builds and run fine on my board (a PowerPC 32bits c2k). > For reference the line is: > >.rela.dyn : AT(ADDR(.rela.dyn) - LOAD_OFFSET) >{ > 202-> __rela_dyn_start = .; >*(.rela*) >} There are still a lot of embedded developers using 2.16.1 binutils in their toolchains so I think that this needs to be worked around. Otherwise we'll see lots of complaints when this gets merged into mainline. However, I haven't figured out a workaround yet. Looking at the binutils sourcecode doesn't reveal anything obvious, but it's too late for my brain to work properly. Anyone else have any ideas? g. -- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH 4/5] powerpc: Make the 64-bit kernel as a position-independent executable
Hi Paul, This patch breaks my build with the following error: /u1/rmachet/projects/c2k/linux-powerpc-git $ make cuImage.c2k modules ARCH=powerpc V=1 ... powerpc-linux-gnu-ld -m elf32ppc -Bstatic -o .tmp_vmlinux1 -T arch/powerpc/kernel/vmlinux.lds arch/powerpc/kernel/head_32.o arch/powerpc/kernel/fpu.o init/built-in.o --start-group usr/built-in.o arch/powerpc/kernel/built-in.o arch/powerpc/mm/built-in.o arch/powerpc/lib/built-in.o arch/powerpc/sysdev/built-in.o arch/powerpc/platforms/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o lib/lib.a lib/built-in.o drivers/built-in.o sound/built-in.o firmware/built-in.o net/built-in.o --end-group powerpc-linux-gnu-ld: BFD 2.16.1 internal error, aborting at /u1/rmachet/project/crosstool/crosstool-0.43/build/powerpc-linux-gnu/gcc-4.1.1-glibc-2.3.6/binutils-2.16.1/bfd/elflink.c line 6419 in elf_link_output_extsym powerpc-linux-gnu-ld: Please report this bug. I isolated the problem to line 202 in arch/powerpc/kernel/vmlinux.lds.S: If I remove that line then the kernel builds and run fine on my board (a PowerPC 32bits c2k). For reference the line is: .rela.dyn : AT(ADDR(.rela.dyn) - LOAD_OFFSET) { 202-> __rela_dyn_start = .; *(.rela*) } Any idea of what cause this crash? I strongly suspect this is a binutils 2.16.1 bug that was fixed later but since it may affect other people I just wanted to let you and the list know. Remi On Sat, 2008-08-30 at 11:43 +1000, Paul Mackerras wrote: > This implements CONFIG_RELOCATABLE for 64-bit by making the kernel as > a position-independent executable (PIE) when it is set. This involves > processing the dynamic relocations in the image in the early stages of > booting, even if the kernel is being run at the address it is linked at, > since the linker does not necessarily fill in words in the image for > which there are dynamic relocations. (In fact the linker does fill in > such words for 64-bit executables, though not for 32-bit executables, > so in principle we could avoid calling relocate() entirely when we're > running a 64-bit kernel at the linked address.) > > The dynamic relocations are processed by a new function relocate(addr), > where the addr parameter is the virtual address where the image will be > run. In fact we call it twice; once before calling prom_init, and again > when starting the main kernel. This means that reloc_offset() returns > 0 in prom_init (since it has been relocated to the address it is running > at), which necessitated a few adjustments. > > This also changes __va and __pa to use an equivalent definition that is > simpler. With the relocatable kernel, PAGE_OFFSET and MEMORY_START are > constants (for 64-bit) whereas PHYSICAL_START is a variable (and > KERNELBASE ideally should be too, but isn't yet). > > With this, relocatable kernels still copy themselves down to physical > address 0 and run there. > > Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]> > --- > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > index 587da5e..17c988b 100644 > --- a/arch/powerpc/Kconfig > +++ b/arch/powerpc/Kconfig > @@ -806,6 +806,19 @@ config PIN_TLB > endmenu > > if PPC64 > +config RELOCATABLE > + bool "Build a relocatable kernel" > + help > + This builds a kernel image that is capable of running anywhere > + in the RMA (real memory area) at any 16k-aligned base address. > + The kernel is linked as a position-independent executable (PIE) > + and contains dynamic relocations which are processed early > + in the bootup process. > + > + One use is for the kexec on panic case where the recovery kernel > + must live at a different physical address than the primary > + kernel. > + > config PAGE_OFFSET > hex > default "0xc000" > diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile > index 9155c93..14c86fe 100644 > --- a/arch/powerpc/Makefile > +++ b/arch/powerpc/Makefile > @@ -63,7 +63,9 @@ override CC += -m$(CONFIG_WORD_SIZE) > override AR := GNUTARGET=elf$(CONFIG_WORD_SIZE)-powerpc $(AR) > endif > > -LDFLAGS_vmlinux := -Bstatic > +LDFLAGS_vmlinux-yy := -Bstatic > +LDFLAGS_vmlinux-$(CONFIG_PPC64)$(CONFIG_RELOCATABLE) := -pie > +LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-yy) > > CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none > -mcall-aixdesc > CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple > diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile > index 14174aa..9109e1f 100644 > --- a/arch/powerpc/boot/Makefile > +++ b/arch/powerpc/boot/Makefile > @@ -310,8 +310,11 @@ $(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb > $(obj)/vmlinux.strip: vmlinux > $(STRIP) -s -R .comment $< -o $@ > > +# The iseries hypervisor won't take an ET_DYN executable, so this > +# changes the type (byte 1
[PATCH 4/5] powerpc: Make the 64-bit kernel as a position-independent executable
This implements CONFIG_RELOCATABLE for 64-bit by making the kernel as a position-independent executable (PIE) when it is set. This involves processing the dynamic relocations in the image in the early stages of booting, even if the kernel is being run at the address it is linked at, since the linker does not necessarily fill in words in the image for which there are dynamic relocations. (In fact the linker does fill in such words for 64-bit executables, though not for 32-bit executables, so in principle we could avoid calling relocate() entirely when we're running a 64-bit kernel at the linked address.) The dynamic relocations are processed by a new function relocate(addr), where the addr parameter is the virtual address where the image will be run. In fact we call it twice; once before calling prom_init, and again when starting the main kernel. This means that reloc_offset() returns 0 in prom_init (since it has been relocated to the address it is running at), which necessitated a few adjustments. This also changes __va and __pa to use an equivalent definition that is simpler. With the relocatable kernel, PAGE_OFFSET and MEMORY_START are constants (for 64-bit) whereas PHYSICAL_START is a variable (and KERNELBASE ideally should be too, but isn't yet). With this, relocatable kernels still copy themselves down to physical address 0 and run there. Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]> --- diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 587da5e..17c988b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -806,6 +806,19 @@ config PIN_TLB endmenu if PPC64 +config RELOCATABLE + bool "Build a relocatable kernel" + help + This builds a kernel image that is capable of running anywhere + in the RMA (real memory area) at any 16k-aligned base address. + The kernel is linked as a position-independent executable (PIE) + and contains dynamic relocations which are processed early + in the bootup process. + + One use is for the kexec on panic case where the recovery kernel + must live at a different physical address than the primary + kernel. + config PAGE_OFFSET hex default "0xc000" diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 9155c93..14c86fe 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -63,7 +63,9 @@ override CC += -m$(CONFIG_WORD_SIZE) override AR:= GNUTARGET=elf$(CONFIG_WORD_SIZE)-powerpc $(AR) endif -LDFLAGS_vmlinux:= -Bstatic +LDFLAGS_vmlinux-yy := -Bstatic +LDFLAGS_vmlinux-$(CONFIG_PPC64)$(CONFIG_RELOCATABLE) := -pie +LDFLAGS_vmlinux:= $(LDFLAGS_vmlinux-yy) CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 14174aa..9109e1f 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -310,8 +310,11 @@ $(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb $(obj)/vmlinux.strip: vmlinux $(STRIP) -s -R .comment $< -o $@ +# The iseries hypervisor won't take an ET_DYN executable, so this +# changes the type (byte 17) in the file to ET_EXEC (2). $(obj)/zImage.iseries: vmlinux $(STRIP) -s -R .comment $< -o $@ + printf "\x02" | dd of=$@ conv=notrunc bs=1 seek=17 $(obj)/uImage: vmlinux $(wrapperbits) $(call if_changed,wrap,uboot) diff --git a/arch/powerpc/boot/elf_util.c b/arch/powerpc/boot/elf_util.c index 7454aa4..1567a0c 100644 --- a/arch/powerpc/boot/elf_util.c +++ b/arch/powerpc/boot/elf_util.c @@ -27,7 +27,8 @@ int parse_elf64(void *hdr, struct elf_info *info) elf64->e_ident[EI_MAG3] == ELFMAG3 && elf64->e_ident[EI_CLASS] == ELFCLASS64&& elf64->e_ident[EI_DATA] == ELFDATA2MSB && - elf64->e_type== ET_EXEC && + (elf64->e_type== ET_EXEC || + elf64->e_type== ET_DYN) && elf64->e_machine == EM_PPC64)) return 0; @@ -58,7 +59,8 @@ int parse_elf32(void *hdr, struct elf_info *info) elf32->e_ident[EI_MAG3] == ELFMAG3 && elf32->e_ident[EI_CLASS] == ELFCLASS32&& elf32->e_ident[EI_DATA] == ELFDATA2MSB && - elf32->e_type== ET_EXEC && + (elf32->e_type== ET_EXEC || + elf32->e_type== ET_DYN) && elf32->e_machine == EM_PPC)) return 0; diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index c2df53c..5a44174 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h @@ -437,7 +437,7 @@ typedef struct { }) #endif /* 1 */ -/* This is only valid for addresses >= KERNELBASE */ +/* This is
Re: [PATCH 4/5] powerpc: Make the 64-bit kernel as a position-independent executable
Geert Uytterhoeven writes: > This part broke ppc32: > > | arch/powerpc/kernel/prom.c: In function 'early_init_devtree': > | arch/powerpc/kernel/prom.c:1166: error: '__end_interrupts' undeclared > (first use in this function) > | arch/powerpc/kernel/prom.c:1166: error: (Each undeclared identifier is > reported only once > | arch/powerpc/kernel/prom.c:1166: error: for each function it appears in.) I'm not totally surprised I broke ppc32 somewhere along the line there. :) I think we will end up with having to have a #ifdef CONFIG_RELOCATABLE in there or maybe a test on PHYSICAL_START. It will depend a bit on whether we want to make relocatable 32-bit kernels as PIEs as well. Paul. ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH 4/5] powerpc: Make the 64-bit kernel as a position-independent executable
On Wed, 13 Aug 2008, Paul Mackerras wrote: > --- a/arch/powerpc/kernel/prom.c > +++ b/arch/powerpc/kernel/prom.c > @@ -1163,7 +1163,9 @@ void __init early_init_devtree(void *params) > parse_early_param(); > > /* Reserve LMB regions used by kernel, initrd, dt, etc... */ > - lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); > + lmb_reserve(0, __end_interrupts - _stext); > + lmb_reserve(__pa(__end_interrupts), > + klimit - (unsigned long)__end_interrupts); > reserve_kdump_trampoline(); > reserve_crashkernel(); > early_reserve_mem(); This part broke ppc32: | arch/powerpc/kernel/prom.c: In function 'early_init_devtree': | arch/powerpc/kernel/prom.c:1166: error: '__end_interrupts' undeclared (first use in this function) | arch/powerpc/kernel/prom.c:1166: error: (Each undeclared identifier is reported only once | arch/powerpc/kernel/prom.c:1166: error: for each function it appears in.) After applying the patch below, I was able to build and boot a kernel for the Sequoia. Signed-off-by: Geert Uytterhoeven <[EMAIL PROTECTED]> --- arch/powerpc/kernel/prom.c |4 1 file changed, 4 insertions(+) --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1163,9 +1163,13 @@ void __init early_init_devtree(void *par parse_early_param(); /* Reserve LMB regions used by kernel, initrd, dt, etc... */ +#ifdef CONFIG_PPC64 lmb_reserve(0, __end_interrupts - _stext); lmb_reserve(__pa(__end_interrupts), klimit - (unsigned long)__end_interrupts); +#else + lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); +#endif reserve_kdump_trampoline(); reserve_crashkernel(); early_reserve_mem(); With kind regards, Geert Uytterhoeven Software Architect Sony Techsoft Centre Europe The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium Phone:+32 (0)2 700 8453 Fax: +32 (0)2 700 8622 E-mail: [EMAIL PROTECTED] Internet: http://www.sony-europe.com/ A division of Sony Europe (Belgium) N.V. VAT BE 0413.825.160 · RPR Brussels Fortis · BIC GEBABEBB · IBAN BE41293037680010___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
[PATCH 4/5] powerpc: Make the 64-bit kernel as a position-independent executable
This implements CONFIG_RELOCATABLE for 64-bit by making the kernel as a position-independent executable (PIE). This involves processing the dynamic relocations in the image in the early stages of booting, even if the kernel is being run at the address it is linked at, since the linker does not necessarily fill in words in the image for which there are dynamic relocations. The dynamic relocations are processed by a new function relocate(addr), where the addr parameter is the virtual address where the image will be run. In fact we call it twice; once before calling prom_init, and again when starting the main kernel. This means that reloc_offset() returns 0 in prom_init (since it has been relocated to the address it is running at), which necessitated a few adjustments. The relocate() function currently only handles R_PPC64_RELATIVE relocs, which are very simple to process (and the linker puts them all first in the dynamic relocation section, and tells us how many of them there are). Currently we only get R_PPC64_RELATIVE relocs, plus one R_PPC64_NONE reloc which we can ignore, plus some relocs against weak undefined symbols (e.g. mach_iseries, mach_powermac) which we can also ignore. Ideally we would have a little program to check that we hadn't inadvertently ended up with any other relocs. This also changes __va and __pa to use an equivalent definition that is simpler. With the relocatable kernel, PAGE_OFFSET and MEMORY_START are constants (for 64-bit) whereas PHYSICAL_START is a variable (and KERNELBASE ideally should be too, but isn't yet). With this, relocatable kernels still copy themselves down to physical address 0 and run there. Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]> --- diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 63c9caf..5a5cf3f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -809,6 +809,19 @@ config PIN_TLB endmenu if PPC64 +config RELOCATABLE + bool "Build a relocatable kernel" + help + This builds a kernel image that is capable of running anywhere + in the RMA (real memory area) at any 16k-aligned base address. + The kernel is linked as a position-independent executable (PIE) + and contains dynamic relocations which are processed early + in the bootup process. + + One use is for the kexec on panic case where the recovery kernel + must live at a different physical address than the primary + kernel. + config PAGE_OFFSET hex default "0xc000" diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 9155c93..9e5a53f 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -63,7 +63,8 @@ override CC += -m$(CONFIG_WORD_SIZE) override AR:= GNUTARGET=elf$(CONFIG_WORD_SIZE)-powerpc $(AR) endif -LDFLAGS_vmlinux:= -Bstatic +LDFLAGS_vmlinux-$(CONFIG_PPC64)$(CONFIG_RELOCATABLE) := -pie +LDFLAGS_vmlinux:= -Bstatic $(LDFLAGS_vmlinux-yy) CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none -mcall-aixdesc CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 14174aa..9109e1f 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -310,8 +310,11 @@ $(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb $(obj)/vmlinux.strip: vmlinux $(STRIP) -s -R .comment $< -o $@ +# The iseries hypervisor won't take an ET_DYN executable, so this +# changes the type (byte 17) in the file to ET_EXEC (2). $(obj)/zImage.iseries: vmlinux $(STRIP) -s -R .comment $< -o $@ + printf "\x02" | dd of=$@ conv=notrunc bs=1 seek=17 $(obj)/uImage: vmlinux $(wrapperbits) $(call if_changed,wrap,uboot) diff --git a/arch/powerpc/boot/elf_util.c b/arch/powerpc/boot/elf_util.c index 7454aa4..1567a0c 100644 --- a/arch/powerpc/boot/elf_util.c +++ b/arch/powerpc/boot/elf_util.c @@ -27,7 +27,8 @@ int parse_elf64(void *hdr, struct elf_info *info) elf64->e_ident[EI_MAG3] == ELFMAG3 && elf64->e_ident[EI_CLASS] == ELFCLASS64&& elf64->e_ident[EI_DATA] == ELFDATA2MSB && - elf64->e_type== ET_EXEC && + (elf64->e_type== ET_EXEC || + elf64->e_type== ET_DYN) && elf64->e_machine == EM_PPC64)) return 0; @@ -58,7 +59,8 @@ int parse_elf32(void *hdr, struct elf_info *info) elf32->e_ident[EI_MAG3] == ELFMAG3 && elf32->e_ident[EI_CLASS] == ELFCLASS32&& elf32->e_ident[EI_DATA] == ELFDATA2MSB && - elf32->e_type== ET_EXEC && + (elf32->e_type== ET_EXEC || + elf32->e_type== ET_DYN) && elf32->e_machine == EM_PPC)) return 0; diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc