• Hendrik Brueckner's avatar
    initramfs: fix initramfs size calculation · ffe8018c
    Hendrik Brueckner authored
    The size of a built-in initramfs is calculated in init/initramfs.c by
    "__initramfs_end - __initramfs_start".  Those symbols are defined in the
    linker script include/asm-generic/vmlinux.lds.h:
    
    #define INIT_RAM_FS                                                     \
            . = ALIGN(PAGE_SIZE);                                           \
            VMLINUX_SYMBOL(__initramfs_start) = .;                          \
            *(.init.ramfs)                                                  \
            VMLINUX_SYMBOL(__initramfs_end) = .;
    
    If the initramfs file has an odd number of bytes, the "__initramfs_end"
    symbol points to an odd address, for example, the symbols in the
    System.map might look like:
    
        0000000000572000 T __initramfs_start
        00000000005bcd05 T __initramfs_end	  <-- odd address
    
    At least on s390 this causes a problem:
    
    Certain s390 instructions, especially instructions for loading addresses
    (larl) or branch addresses must be on even addresses.  The compiler loads
    the symbol addresses with the "larl" instruction.  This instruction sets
    the last bit to 0 and, therefore, for odd size files, the calculated size
    is one byte less than it should be:
    
        0000000000540a9c <populate_rootfs>:
          540a9c:     eb cf f0 78 00 24       stmg    %r12,%r15,120(%r15),
          540aa2:     c0 10 00 01 8a af       larl    %r1,572000 <__initramfs_start>
          540aa8:     c0 c0 00 03 e1 2e       larl    %r12,5bcd04 <initramfs_end>
                                                      (Instead of  5bcd05)
          ...
          540abe:     1b c1                   sr      %r12,%r1
    
    To fix the problem, this patch introduces the global variable
    __initramfs_size, which is calculated in the "usr/initramfs_data.S" file.
    The populate_rootfs() function can then use the start marker of the
    .init.ramfs section and the value of __initramfs_size for loading the
    initramfs.  Because the start marker and size is sufficient, the
    __initramfs_end symbol is no longer needed and is removed.
    Signed-off-by: default avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
    Signed-off-by: default avatarHendrik Brueckner <brueckner@linux.vnet.ibm.com>
    Reviewed-by: default avatarWANG Cong <xiyou.wangcong@gmail.com>
    Acked-by: default avatarMichal Marek <mmarek@suse.cz>
    Acked-by: default avatar"H. Peter Anvin" <hpa@zytor.com>
    Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
    Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarMichal Marek <mmarek@suse.cz>
    ffe8018c
Name
Last commit
Last update
Documentation Loading commit data...
arch Loading commit data...
block Loading commit data...
crypto Loading commit data...
drivers Loading commit data...
firmware Loading commit data...
fs Loading commit data...
include Loading commit data...
init Loading commit data...
ipc Loading commit data...
kernel Loading commit data...
lib Loading commit data...
mm Loading commit data...
net Loading commit data...
samples Loading commit data...
scripts Loading commit data...
security Loading commit data...
sound Loading commit data...
tools Loading commit data...
usr Loading commit data...
virt/kvm Loading commit data...
.gitignore Loading commit data...
.mailmap Loading commit data...
COPYING Loading commit data...
CREDITS Loading commit data...
Kbuild Loading commit data...
MAINTAINERS Loading commit data...
Makefile Loading commit data...
README Loading commit data...
REPORTING-BUGS Loading commit data...