Skip to content
  • 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