Thread (19 messages) 19 messages, 3 authors, 2012-10-12

[PATCH] [ARM] Use AT() in the linker script to create correct program headers

From: Dave Martin <hidden>
Date: 2012-10-01 17:56:54
Also in: lkml

On Mon, Oct 01, 2012 at 10:06:39AM -0600, Jason Gunthorpe wrote:
On Mon, Oct 01, 2012 at 04:39:53PM +0100, Dave Martin wrote:
quoted
quoted
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x008000 0xc0008000 0x00008000 0x372244 0x3a4310 RWE 0x8000
Not related directly to your patch, but I wonder why we don't we see
separate r-x and rw- segments?
I think this is because the sections are not aligned when the
protections change, and the sections are not sorted by protection
type.

  [ 1] .head.text        PROGBITS        c0008000 008000 0001c0 00  AX  0   0 32
  [ 2] .text             PROGBITS        c00081c0 0081c0 1dc880 00  AX  0   0 32
  [ 3] .rodata           PROGBITS        c01e5000 1e5000 060a80 00   A  0   0 32
  [ 4] __bug_table       PROGBITS        c0245a80 245a80 002a78 00   A  0   0  1
  [ 5] .pci_fixup        PROGBITS        c02484f8 2484f8 000090 00   A  0   0  4
  [ 6] __param           PROGBITS        c0248588 248588 000280 00   A  0   0  4
  [ 7] __modver          PROGBITS        c0248808 248808 0007f8 00   A  0   0  4
  [ 8] .init.text        PROGBITS        c0249000 249000 01af20 00  AX  0   0 32
  [ 9] .exit.text        PROGBITS        c0263f20 263f20 000c0c 00  AX  0   0  4
  [10] .init.proc.info   PROGBITS        c0264b2c 264b2c 00009c 00  AX  0   0  1
  [11] .init.arch.info   PROGBITS        c0264bc8 264bc8 000044 00   A  0   0  4
  [12] .init.tagtable    PROGBITS        c0264c0c 264c0c 000040 00   A  0   0  4
  [13] .init.data        PROGBITS        c0264c60 264c60 0f481c 00  WA  0   0 32
  [14] .data             PROGBITS        c035a000 35a000 020220 00  WA  0   0 32
  [15] .notes            NOTE            c037a220 37a220 000024 00  AX  0   0  4
  [16] .bss              NOBITS          c037a260 37a244 0320b0 00  WA  0   0 32
  [17] .comment          PROGBITS        00000000 37a244 000021 01  MS  0   0  1

 
quoted
quoted
+/* If we have a known, fixed physical load address then set LOAD_OFFSET
+   and generate an ELF that has the physical load address in the program
+   headers. */
+#ifndef CONFIG_ARM_PATCH_PHYS_VIRT
+#define LOAD_OFFSET (PAGE_OFFSET - PHYS_OFFSET)
+#endif
+
What happens if CONFIG_ARM_PATCH_PHYS_VIRT=y?  This will be used
increasingly, especially for multiplatform kernels.
Then LOAD_OFFSET is unset and include/asm-generic/vmlinux.lds.h does:

#ifndef LOAD_OFFSET
#define LOAD_OFFSET 0
#endif
OK, good.
 
Which is exactly the same case we have today. LOAD_OFFSET is not a
name I invented, it is the standard kernel name for the functionality.
 
quoted
If the kernel is intended to be loadable at a physical address which is
not statically known, no ELF loader that does not ignore the ELF
phdr
In this case you can't really use a standard ELF loader to load the
kernel so, LOAD_OFFSET = 0 is fine. My case is using an ELF loader,
and I have set options for a static physical load address.
Generally, people should try to be compatible with the single kernel
image effort unless there's a really compelling reason not to.

Wouldn't your firmware be incapable of loading a multiplatform kernel?
quoted
quoted
 OUTPUT_ARCH(arm)
-ENTRY(stext)
+ENTRY(phys_start)
This is debatable.  In fact, stext has the property that its virtual
(runtime) and load addresses are the same.
This is what other arches using LOAD_OFFSET do (eg see ia64), and is
sensible. ENTRY is *only* used by the ELF loader and specifies where
the loader should jump. It must be a physical address since the loader
only works with physical addresse. I don't understand your comment
that .stext has the same load and virtual address, that is clearly not
true for the ELF images my build is producing:

c0008000 T _text
c0008000 T stext

The physical address of that symbol is 0x8000.
Well, that was a bit of a pedantic point I admit, but there are
conflicting definitions of what "virtual address" really means in these
situations.  The original SYSV ABI spec explicitly specifies that
e_entry is a virtual address, but is also rather vague about how the
paddr fields should be interpreted.


All that AT(ADDR(blah) - LOAD_OFFSET) stuff is cumbersome, but if it's
at least consistent with other architectures then it may not such a
disaster.  It's not universal though: less than 50% of the arches in
the kernel currently seem to use this.

An alternative, cleaner approach might be to specify segment load
addresses directly using PHDRS { }.  This should at leat allow the
load address to be specified once per phdr, rather than once per section.
quoted
To represent this correctly in the linker scripts, the
position-independent head.S code should be split out into a separate
section to which LOAD_OFFSET is not applied.
I'm not sure, the linker script should use addresses that are correct
during runtime, and if the PIC code does not care about its PC then it
is fine to keep it at the virtual address to minimize confusion once
the MMU is on.
quoted
Setting vaddr and paddr to PAGE_OFFSET (as we do now) and having the
loader choose the appropriate board-specific place to load the kernel
image makes this irrelevant, if I've understood the situation correctly.
Yes, if you use more loader stages then the load headers are ignored.
Our boot loaders on our boards boot straight ELF vmlinux.gz so they
need correct load headers.
If your image is compressed anyway though, why are you not using zImage?

Cheers
---Dave
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help