Re: [PATCH] MIPS: Set ISA bit in entry-y for microMIPS kernels

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Paul,

> I originally did this [1], and wrote about it in the post-three-dashes notes 
> for this patch. To quote myself:
> 
> > I originally tried using "objdump -f" to obtain the entry address, which
> > works for microMIPS but it always outputs a 32 bit address for a 32 bit
> > ELF whilst nm will sign extend to 64 bit. That matters for systems where
> > we might want to run a MIPS32 kernel on a MIPS64 CPU & load it with a
> > MIPS64 bootloader, which would then jump to a non-canonical
> > (non-sign-extended) address.
> > 
> > This works in all cases as it only changes the behaviour for microMIPS
> > kernels, but isn't the prettiest solution. A possible alternative would
> > be to write a custom tool to just extract, sign extend & print the entry
> > point of an ELF executable. I'm open to feedback if that would be
> > preferred.
> 
> So if we were to use objdump we'd need to handle sign extending 32 bit 
> addresses to form a canonical address. Perhaps that'd be cleaner though.

 Hmm, your reasoning sounds right (and I was blind to miss it entirely, 
sorry), however reality seems to disagree.  As at 5fc9484f5e41^ I get:

make -f ./scripts/Makefile.build obj=arch/mips/boot VMLINUX=vmlinux \
		VMLINUX_LOAD_ADDRESS=0xffffffff80100000 VMLINUX_ENTRY_ADDRESS=0x804fca20 PLATFORM="generic/" ADDR_BITS=32 arch/mips/boot/vmlinux.srec

whereas at 5fc9484f5e41^ I get:

make -f ./scripts/Makefile.build obj=arch/mips/boot VMLINUX=vmlinux \
		VMLINUX_LOAD_ADDRESS=0xffffffff80100000 VMLINUX_ENTRY_ADDRESS=0x804fca21 PLATFORM="generic/" ADDR_BITS=32 arch/mips/boot/vmlinux.srec

so in both cases the entry address is 32-bit, which is why I didn't see 
any disadvantage from using `objdump -f'.  Indeed:

$ mips-linux-gnu-nm vmlinux | grep kernel_entry
80100000 T __kernel_entry
804fca20 T kernel_entry
$ mips-mti-linux-gnu-nm vmlinux | grep kernel_entry
ffffffff80100000 T __kernel_entry
ffffffff804fca20 T kernel_entry
$ 

which means you can't rely on `nm' sign-extending addresses to 64 bits 
with 32-bit binaries.  And it looks like a bug to me indeed that some 
versions of `nm' do such sign-extension, unlike `objdump' and `readelf'.  
I'll have to bisect it to see when it started happening and take it with 
upstream binutils.

 How about this version then?  It does the right thing for me:

make -f ./scripts/Makefile.build obj=arch/mips/boot VMLINUX=vmlinux \
		VMLINUX_LOAD_ADDRESS=0xffffffff80100000 VMLINUX_ENTRY_ADDRESS=0xffffffff804fca21 PLATFORM="generic/" ADDR_BITS=32 arch/mips/boot/vmlinux.srec

and given than we need to sign-extend in either case I think retrieving 
the canonical entry point rather than transforming the entry symbol is 
simpler and more reliable.

  Maciej

---
 arch/mips/Makefile |   19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

linux-mips-start-address.diff
Index: linux-sfr-usead/arch/mips/Makefile
===================================================================
--- linux-sfr-usead.orig/arch/mips/Makefile	2017-08-18 22:17:42.962681000 +0100
+++ linux-sfr-usead/arch/mips/Makefile	2017-08-18 23:01:00.997846000 +0100
@@ -244,20 +244,11 @@ ifdef CONFIG_PHYSICAL_START
 load-y					= $(CONFIG_PHYSICAL_START)
 endif
 
-entry-noisa-y				= 0x$(shell $(NM) vmlinux 2>/dev/null \
-					| grep "\bkernel_entry\b" | cut -f1 -d \ )
-ifdef CONFIG_CPU_MICROMIPS
-  #
-  # Set the ISA bit, since the kernel_entry symbol in the ELF will have it
-  # clear which would lead to images containing addresses which bootloaders may
-  # jump to as MIPS32 code.
-  #
-  entry-y = $(patsubst %0,%1,$(patsubst %2,%3,$(patsubst %4,%5, \
-              $(patsubst %6,%7,$(patsubst %8,%9,$(patsubst %a,%b, \
-              $(patsubst %c,%d,$(patsubst %e,%f,$(entry-noisa-y)))))))))
-else
-  entry-y = $(entry-noisa-y)
-endif
+# Knowing that a 32-bit kernel will be linked at a KSEG address
+# sign-extend the entry point to 64 bits if retrieved as a 32-bit
+# number by stuffing `ffffffff' after the leading `0x'.
+entry-y	= $(shell $(OBJDUMP) -f vmlinux 2>/dev/null \
+	| sed -n 's/0x\(........\)$$/0xffffffff\1/;s/start address //p')
 
 cflags-y			+= -I$(srctree)/arch/mips/include/asm/mach-generic
 drivers-$(CONFIG_PCI)		+= arch/mips/pci/




[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux