Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[S390] initrd vs. bootmem bitmap.

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>

authored by

Heiko Carstens and committed by
Martin Schwidefsky
65912a84 4ba069b8

+48 -13
+6 -4
arch/s390/kernel/head.S
··· 272 272 # load parameter file from ipl device 273 273 # 274 274 .Lagain1: 275 - l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # ramdisk loc. is temp 275 + l %r2,.Linitrd # ramdisk loc. is temp 276 276 bas %r14,.Lloader # load parameter file 277 277 ltr %r2,%r2 # got anything ? 278 278 bz .Lnopf ··· 280 280 bnh .Lnotrunc 281 281 la %r2,895 282 282 .Lnotrunc: 283 - l %r4,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) 283 + l %r4,.Linitrd 284 284 clc 0(3,%r4),.L_hdr # if it is HDRx 285 285 bz .Lagain1 # skip dataset header 286 286 clc 0(3,%r4),.L_eof # if it is EOFx ··· 323 323 # load ramdisk from ipl device 324 324 # 325 325 .Lagain2: 326 - l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # addr of ramdisk 326 + l %r2,.Linitrd # addr of ramdisk 327 + st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) 327 328 bas %r14,.Lloader # load ramdisk 328 329 st %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk 329 330 ltr %r2,%r2 330 331 bnz .Lrdcont 331 332 st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found 332 333 .Lrdcont: 333 - l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) 334 + l %r2,.Linitrd 334 335 335 336 clc 0(3,%r2),.L_hdr # skip HDRx and EOFx 336 337 bz .Lagain2 ··· 380 379 l %r1,.Lstartup 381 380 br %r1 382 381 382 + .Linitrd:.long _end + 0x400000 # default address of initrd 383 383 .Lparm: .long PARMAREA 384 384 .Lstartup: .long startup 385 385 .Lcvtab:.long _ebcasc # ebcdic to ascii table
+2 -2
arch/s390/kernel/head31.S
··· 26 26 # 27 27 .org PARMAREA 28 28 .long 0,0 # IPL_DEVICE 29 - .long 0,RAMDISK_ORIGIN # INITRD_START 30 - .long 0,RAMDISK_SIZE # INITRD_SIZE 29 + .long 0,0 # INITRD_START 30 + .long 0,0 # INITRD_SIZE 31 31 32 32 .org COMMAND_LINE 33 33 .byte "root=/dev/ram0 ro"
+2 -2
arch/s390/kernel/head64.S
··· 26 26 # 27 27 .org PARMAREA 28 28 .quad 0 # IPL_DEVICE 29 - .quad RAMDISK_ORIGIN # INITRD_START 30 - .quad RAMDISK_SIZE # INITRD_SIZE 29 + .quad 0 # INITRD_START 30 + .quad 0 # INITRD_SIZE 31 31 32 32 .org COMMAND_LINE 33 33 .byte "root=/dev/ram0 ro"
+38 -3
arch/s390/kernel/setup.c
··· 37 37 #include <linux/kernel_stat.h> 38 38 #include <linux/device.h> 39 39 #include <linux/notifier.h> 40 + #include <linux/pfn.h> 40 41 41 42 #include <asm/uaccess.h> 42 43 #include <asm/system.h> ··· 502 501 * partially used pages are not usable - thus 503 502 * we are rounding upwards: 504 503 */ 505 - start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT; 506 - end_pfn = max_pfn = memory_end >> PAGE_SHIFT; 504 + start_pfn = PFN_UP(__pa(&_end)); 505 + end_pfn = max_pfn = PFN_DOWN(memory_end); 507 506 508 507 /* Initialize storage key for kernel pages */ 509 508 for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++) 510 509 page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); 510 + 511 + #ifdef CONFIG_BLK_DEV_INITRD 512 + /* 513 + * Move the initrd in case the bitmap of the bootmem allocater 514 + * would overwrite it. 515 + */ 516 + 517 + if (INITRD_START && INITRD_SIZE) { 518 + unsigned long bmap_size; 519 + unsigned long start; 520 + 521 + bmap_size = bootmem_bootmap_pages(end_pfn - start_pfn + 1); 522 + bmap_size = PFN_PHYS(bmap_size); 523 + 524 + if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) { 525 + start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE; 526 + 527 + if (start + INITRD_SIZE > memory_end) { 528 + printk("initrd extends beyond end of memory " 529 + "(0x%08lx > 0x%08lx)\n" 530 + "disabling initrd\n", 531 + start + INITRD_SIZE, memory_end); 532 + INITRD_START = INITRD_SIZE = 0; 533 + } else { 534 + printk("Moving initrd (0x%08lx -> 0x%08lx, " 535 + "size: %ld)\n", 536 + INITRD_START, start, INITRD_SIZE); 537 + memmove((void *) start, (void *) INITRD_START, 538 + INITRD_SIZE); 539 + INITRD_START = start; 540 + } 541 + } 542 + } 543 + #endif 511 544 512 545 /* 513 546 * Initialize the boot-time allocator (with low memory only): ··· 594 559 reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size); 595 560 596 561 #ifdef CONFIG_BLK_DEV_INITRD 597 - if (INITRD_START) { 562 + if (INITRD_START && INITRD_SIZE) { 598 563 if (INITRD_START + INITRD_SIZE <= memory_end) { 599 564 reserve_bootmem(INITRD_START, INITRD_SIZE); 600 565 initrd_start = INITRD_START;
-2
include/asm-s390/setup.h
··· 14 14 15 15 #define PARMAREA 0x10400 16 16 #define COMMAND_LINE_SIZE 896 17 - #define RAMDISK_ORIGIN 0x800000 18 - #define RAMDISK_SIZE 0x800000 19 17 #define MEMORY_CHUNKS 16 /* max 0x7fff */ 20 18 #define IPL_PARMBLOCK_ORIGIN 0x2000 21 19