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

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

 



On 18 August 2017 23:13:39 BST, "Maciej W. Rozycki" <macro@xxxxxxxxxx> wrote:
>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

thats not true with CONFIG_KVM_GUEST kernels, which use a separate set of emulated guest kernel segments in useg, i.e. at 0x40000000. I've also seen EVA kernels linked at low addresses like around 0x20000000, though entry gets a bit fiddly for EVA depending on whether bootloader already has the chosen segment configuration set up.

Cheers
James

>+# 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/


--
James Hogan




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

  Powered by Linux