ARM: Fix decompressor's kernel size estimation for ROM=y

Commit 2552fc2 changed the way the decompressor decides if it is safe
to decompress the kernel directly to its final location.  Unfortunately,
it took the top of the compressed data as being the stack pointer,
which it is for ROM=n cases.  However, for ROM=y, the stack pointer
is not relevant, and results in the wrong answer.

Fix this by explicitly storing the end of the biggybacked data in the
decompressor, and use that to calculate the compressed image size.

CC: <stable@kernel.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
Russell King 2010-02-25 23:56:38 +00:00
parent baac35c415
commit 98e12b5a6e
2 changed files with 26 additions and 27 deletions

View file

@ -170,8 +170,8 @@ not_angel:
.text .text
adr r0, LC0 adr r0, LC0
ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} ) ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp})
THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, ip} ) THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip} )
THUMB( ldr sp, [r0, #28] ) THUMB( ldr sp, [r0, #28] )
subs r0, r0, r1 @ calculate the delta offset subs r0, r0, r1 @ calculate the delta offset
@ -182,12 +182,13 @@ not_angel:
/* /*
* We're running at a different address. We need to fix * We're running at a different address. We need to fix
* up various pointers: * up various pointers:
* r5 - zImage base address * r5 - zImage base address (_start)
* r6 - GOT start * r6 - size of decompressed image
* r11 - GOT start
* ip - GOT end * ip - GOT end
*/ */
add r5, r5, r0 add r5, r5, r0
add r6, r6, r0 add r11, r11, r0
add ip, ip, r0 add ip, ip, r0
#ifndef CONFIG_ZBOOT_ROM #ifndef CONFIG_ZBOOT_ROM
@ -205,10 +206,10 @@ not_angel:
/* /*
* Relocate all entries in the GOT table. * Relocate all entries in the GOT table.
*/ */
1: ldr r1, [r6, #0] @ relocate entries in the GOT 1: ldr r1, [r11, #0] @ relocate entries in the GOT
add r1, r1, r0 @ table. This fixes up the add r1, r1, r0 @ table. This fixes up the
str r1, [r6], #4 @ C references. str r1, [r11], #4 @ C references.
cmp r6, ip cmp r11, ip
blo 1b blo 1b
#else #else
@ -216,12 +217,12 @@ not_angel:
* Relocate entries in the GOT table. We only relocate * Relocate entries in the GOT table. We only relocate
* the entries that are outside the (relocated) BSS region. * the entries that are outside the (relocated) BSS region.
*/ */
1: ldr r1, [r6, #0] @ relocate entries in the GOT 1: ldr r1, [r11, #0] @ relocate entries in the GOT
cmp r1, r2 @ entry < bss_start || cmp r1, r2 @ entry < bss_start ||
cmphs r3, r1 @ _end < entry cmphs r3, r1 @ _end < entry
addlo r1, r1, r0 @ table. This fixes up the addlo r1, r1, r0 @ table. This fixes up the
str r1, [r6], #4 @ C references. str r1, [r11], #4 @ C references.
cmp r6, ip cmp r11, ip
blo 1b blo 1b
#endif #endif
@ -247,6 +248,7 @@ not_relocated: mov r0, #0
* Check to see if we will overwrite ourselves. * Check to see if we will overwrite ourselves.
* r4 = final kernel address * r4 = final kernel address
* r5 = start of this image * r5 = start of this image
* r6 = size of decompressed image
* r2 = end of malloc space (and therefore this image) * r2 = end of malloc space (and therefore this image)
* We basically want: * We basically want:
* r4 >= r2 -> OK * r4 >= r2 -> OK
@ -254,8 +256,7 @@ not_relocated: mov r0, #0
*/ */
cmp r4, r2 cmp r4, r2
bhs wont_overwrite bhs wont_overwrite
sub r3, sp, r5 @ > compressed kernel size add r0, r4, r6
add r0, r4, r3, lsl #2 @ allow for 4x expansion
cmp r0, r5 cmp r0, r5
bls wont_overwrite bls wont_overwrite
@ -271,7 +272,6 @@ not_relocated: mov r0, #0
* r1-r3 = unused * r1-r3 = unused
* r4 = kernel execution address * r4 = kernel execution address
* r5 = decompressed kernel start * r5 = decompressed kernel start
* r6 = processor ID
* r7 = architecture ID * r7 = architecture ID
* r8 = atags pointer * r8 = atags pointer
* r9-r12,r14 = corrupted * r9-r12,r14 = corrupted
@ -312,7 +312,8 @@ LC0: .word LC0 @ r1
.word _end @ r3 .word _end @ r3
.word zreladdr @ r4 .word zreladdr @ r4
.word _start @ r5 .word _start @ r5
.word _got_start @ r6 .word _image_size @ r6
.word _got_start @ r11
.word _got_end @ ip .word _got_end @ ip
.word user_stack+4096 @ sp .word user_stack+4096 @ sp
LC1: .word reloc_end - reloc_start LC1: .word reloc_end - reloc_start
@ -336,7 +337,6 @@ params: ldr r0, =params_phys
* *
* On entry, * On entry,
* r4 = kernel execution address * r4 = kernel execution address
* r6 = processor ID
* r7 = architecture number * r7 = architecture number
* r8 = atags pointer * r8 = atags pointer
* r9 = run-time address of "start" (???) * r9 = run-time address of "start" (???)
@ -542,7 +542,6 @@ __common_mmu_cache_on:
* r1-r3 = unused * r1-r3 = unused
* r4 = kernel execution address * r4 = kernel execution address
* r5 = decompressed kernel start * r5 = decompressed kernel start
* r6 = processor ID
* r7 = architecture ID * r7 = architecture ID
* r8 = atags pointer * r8 = atags pointer
* r9-r12,r14 = corrupted * r9-r12,r14 = corrupted
@ -581,19 +580,19 @@ call_kernel: bl cache_clean_flush
* r1 = corrupted * r1 = corrupted
* r2 = corrupted * r2 = corrupted
* r3 = block offset * r3 = block offset
* r6 = corrupted * r9 = corrupted
* r12 = corrupted * r12 = corrupted
*/ */
call_cache_fn: adr r12, proc_types call_cache_fn: adr r12, proc_types
#ifdef CONFIG_CPU_CP15 #ifdef CONFIG_CPU_CP15
mrc p15, 0, r6, c0, c0 @ get processor ID mrc p15, 0, r9, c0, c0 @ get processor ID
#else #else
ldr r6, =CONFIG_PROCESSOR_ID ldr r9, =CONFIG_PROCESSOR_ID
#endif #endif
1: ldr r1, [r12, #0] @ get value 1: ldr r1, [r12, #0] @ get value
ldr r2, [r12, #4] @ get mask ldr r2, [r12, #4] @ get mask
eor r1, r1, r6 @ (real ^ match) eor r1, r1, r9 @ (real ^ match)
tst r1, r2 @ & mask tst r1, r2 @ & mask
ARM( addeq pc, r12, r3 ) @ call cache function ARM( addeq pc, r12, r3 ) @ call cache function
THUMB( addeq r12, r3 ) THUMB( addeq r12, r3 )
@ -778,8 +777,7 @@ proc_types:
* Turn off the Cache and MMU. ARMv3 does not support * Turn off the Cache and MMU. ARMv3 does not support
* reading the control register, but ARMv4 does. * reading the control register, but ARMv4 does.
* *
* On entry, r6 = processor ID * On exit, r0, r1, r2, r3, r9, r12 corrupted
* On exit, r0, r1, r2, r3, r12 corrupted
* This routine must preserve: r4, r6, r7 * This routine must preserve: r4, r6, r7
*/ */
.align 5 .align 5
@ -852,10 +850,8 @@ __armv3_mmu_cache_off:
/* /*
* Clean and flush the cache to maintain consistency. * Clean and flush the cache to maintain consistency.
* *
* On entry,
* r6 = processor ID
* On exit, * On exit,
* r1, r2, r3, r11, r12 corrupted * r1, r2, r3, r9, r11, r12 corrupted
* This routine must preserve: * This routine must preserve:
* r0, r4, r5, r6, r7 * r0, r4, r5, r6, r7
*/ */
@ -967,7 +963,7 @@ __armv4_mmu_cache_flush:
mov r2, #64*1024 @ default: 32K dcache size (*2) mov r2, #64*1024 @ default: 32K dcache size (*2)
mov r11, #32 @ default: 32 byte line size mov r11, #32 @ default: 32 byte line size
mrc p15, 0, r3, c0, c0, 1 @ read cache type mrc p15, 0, r3, c0, c0, 1 @ read cache type
teq r3, r6 @ cache ID register present? teq r3, r9 @ cache ID register present?
beq no_cache_id beq no_cache_id
mov r1, r3, lsr #18 mov r1, r3, lsr #18
and r1, r1, #7 and r1, r1, #7

View file

@ -36,6 +36,9 @@ SECTIONS
_etext = .; _etext = .;
/* Assume size of decompressed image is 4x the compressed image */
_image_size = (_etext - _text) * 4;
_got_start = .; _got_start = .;
.got : { *(.got) } .got : { *(.got) }
_got_end = .; _got_end = .;