[S390] initrd vs. bootmem bitmap.
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Wed, 20 Sep 2006 13:58:41 +0000 (15:58 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 20 Sep 2006 13:58:41 +0000 (15:58 +0200)
Move initrd if the bitmap of the bootmem allocator would overwrite it.
In addition this patch sets the default size and address of the initrd to 0.
Therefore all boot loaders must set the initrd size and address correctly.
This is especially relevant for ftp boot via HMC/SE, where this change
requires a special patch file entry in the .ins file which sets these two
values contained at address 0x10408 and 0x10410.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/head.S
arch/s390/kernel/head31.S
arch/s390/kernel/head64.S
arch/s390/kernel/setup.c
include/asm-s390/setup.h

index adad886..a6e9bdb 100644 (file)
@@ -272,7 +272,7 @@ iplstart:
 # load parameter file from ipl device
 #
 .Lagain1:
-       l     %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # ramdisk loc. is temp
+       l     %r2,.Linitrd                     # ramdisk loc. is temp
         bas   %r14,.Lloader                    # load parameter file
         ltr   %r2,%r2                          # got anything ?
         bz    .Lnopf
@@ -280,7 +280,7 @@ iplstart:
        bnh   .Lnotrunc
        la    %r2,895
 .Lnotrunc:
-       l     %r4,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
+       l     %r4,.Linitrd
        clc   0(3,%r4),.L_hdr                  # if it is HDRx
        bz    .Lagain1                         # skip dataset header
        clc   0(3,%r4),.L_eof                  # if it is EOFx
@@ -323,14 +323,15 @@ iplstart:
 # load ramdisk from ipl device
 #      
 .Lagain2:
-       l     %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # addr of ramdisk
+       l     %r2,.Linitrd                     # addr of ramdisk
+       st    %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
         bas   %r14,.Lloader                    # load ramdisk
        st    %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk
         ltr   %r2,%r2
         bnz   .Lrdcont
         st    %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
 .Lrdcont:
-       l     %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
+       l     %r2,.Linitrd
 
        clc   0(3,%r2),.L_hdr                  # skip HDRx and EOFx 
        bz    .Lagain2
@@ -379,6 +380,7 @@ iplstart:
         l     %r1,.Lstartup
         br    %r1
 
+.Linitrd:.long _end + 0x400000                # default address of initrd
 .Lparm:        .long  PARMAREA
 .Lstartup: .long startup
 .Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
index a4dc61f..0e46077 100644 (file)
@@ -26,8 +26,8 @@ startup:basr  %r13,0                  # get base
 #
        .org    PARMAREA
        .long   0,0                     # IPL_DEVICE
-       .long   0,RAMDISK_ORIGIN        # INITRD_START
-       .long   0,RAMDISK_SIZE          # INITRD_SIZE
+       .long   0,0                     # INITRD_START
+       .long   0,0                     # INITRD_SIZE
 
        .org    COMMAND_LINE
        .byte   "root=/dev/ram0 ro"
index 9d80c5b..3e0341a 100644 (file)
@@ -26,8 +26,8 @@ startup:basr  %r13,0                   # get base
 #
        .org   PARMAREA
        .quad  0                        # IPL_DEVICE
-       .quad  RAMDISK_ORIGIN           # INITRD_START
-       .quad  RAMDISK_SIZE             # INITRD_SIZE
+       .quad  0                        # INITRD_START
+       .quad  0                        # INITRD_SIZE
 
        .org   COMMAND_LINE
        .byte  "root=/dev/ram0 ro"
index c902f05..89051e8 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/device.h>
 #include <linux/notifier.h>
+#include <linux/pfn.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -501,13 +502,47 @@ setup_memory(void)
         * partially used pages are not usable - thus
         * we are rounding upwards:
         */
-       start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       end_pfn = max_pfn = memory_end >> PAGE_SHIFT;
+       start_pfn = PFN_UP(__pa(&_end));
+       end_pfn = max_pfn = PFN_DOWN(memory_end);
 
        /* Initialize storage key for kernel pages */
        for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++)
                page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+       /*
+        * Move the initrd in case the bitmap of the bootmem allocater
+        * would overwrite it.
+        */
+
+       if (INITRD_START && INITRD_SIZE) {
+               unsigned long bmap_size;
+               unsigned long start;
+
+               bmap_size = bootmem_bootmap_pages(end_pfn - start_pfn + 1);
+               bmap_size = PFN_PHYS(bmap_size);
+
+               if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) {
+                       start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE;
+
+                       if (start + INITRD_SIZE > memory_end) {
+                               printk("initrd extends beyond end of memory "
+                                      "(0x%08lx > 0x%08lx)\n"
+                                      "disabling initrd\n",
+                                      start + INITRD_SIZE, memory_end);
+                               INITRD_START = INITRD_SIZE = 0;
+                       } else {
+                               printk("Moving initrd (0x%08lx -> 0x%08lx, "
+                                      "size: %ld)\n",
+                                      INITRD_START, start, INITRD_SIZE);
+                               memmove((void *) start, (void *) INITRD_START,
+                                       INITRD_SIZE);
+                               INITRD_START = start;
+                       }
+               }
+       }
+#endif
+
        /*
         * Initialize the boot-time allocator (with low memory only):
         */
@@ -559,7 +594,7 @@ setup_memory(void)
        reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);
 
 #ifdef CONFIG_BLK_DEV_INITRD
-       if (INITRD_START) {
+       if (INITRD_START && INITRD_SIZE) {
                if (INITRD_START + INITRD_SIZE <= memory_end) {
                        reserve_bootmem(INITRD_START, INITRD_SIZE);
                        initrd_start = INITRD_START;
index 19e3197..02c96d5 100644 (file)
@@ -14,8 +14,6 @@
 
 #define PARMAREA               0x10400
 #define COMMAND_LINE_SIZE      896
-#define RAMDISK_ORIGIN         0x800000
-#define RAMDISK_SIZE           0x800000
 #define MEMORY_CHUNKS          16      /* max 0x7fff */
 #define IPL_PARMBLOCK_ORIGIN   0x2000