diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-02-25 18:56:38 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-02-25 19:10:47 -0500 |
commit | 98e12b5a6e05413420a7e3b3eca7fbfc2ff41b6d (patch) | |
tree | 0d8e2d7f6dab7baf96da5a32678bd85095778853 | |
parent | baac35c4155a8aa826c70acee6553368ca5243a2 (diff) |
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>
-rw-r--r-- | arch/arm/boot/compressed/head.S | 50 | ||||
-rw-r--r-- | arch/arm/boot/compressed/vmlinux.lds.in | 3 |
2 files changed, 26 insertions, 27 deletions
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 4fddc509e78e..6b84a0471171 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S | |||
@@ -170,8 +170,8 @@ not_angel: | |||
170 | 170 | ||
171 | .text | 171 | .text |
172 | adr r0, LC0 | 172 | adr r0, LC0 |
173 | ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} ) | 173 | ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp}) |
174 | THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, ip} ) | 174 | THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip} ) |
175 | THUMB( ldr sp, [r0, #28] ) | 175 | THUMB( ldr sp, [r0, #28] ) |
176 | subs r0, r0, r1 @ calculate the delta offset | 176 | subs r0, r0, r1 @ calculate the delta offset |
177 | 177 | ||
@@ -182,12 +182,13 @@ not_angel: | |||
182 | /* | 182 | /* |
183 | * We're running at a different address. We need to fix | 183 | * We're running at a different address. We need to fix |
184 | * up various pointers: | 184 | * up various pointers: |
185 | * r5 - zImage base address | 185 | * r5 - zImage base address (_start) |
186 | * r6 - GOT start | 186 | * r6 - size of decompressed image |
187 | * r11 - GOT start | ||
187 | * ip - GOT end | 188 | * ip - GOT end |
188 | */ | 189 | */ |
189 | add r5, r5, r0 | 190 | add r5, r5, r0 |
190 | add r6, r6, r0 | 191 | add r11, r11, r0 |
191 | add ip, ip, r0 | 192 | add ip, ip, r0 |
192 | 193 | ||
193 | #ifndef CONFIG_ZBOOT_ROM | 194 | #ifndef CONFIG_ZBOOT_ROM |
@@ -205,10 +206,10 @@ not_angel: | |||
205 | /* | 206 | /* |
206 | * Relocate all entries in the GOT table. | 207 | * Relocate all entries in the GOT table. |
207 | */ | 208 | */ |
208 | 1: ldr r1, [r6, #0] @ relocate entries in the GOT | 209 | 1: ldr r1, [r11, #0] @ relocate entries in the GOT |
209 | add r1, r1, r0 @ table. This fixes up the | 210 | add r1, r1, r0 @ table. This fixes up the |
210 | str r1, [r6], #4 @ C references. | 211 | str r1, [r11], #4 @ C references. |
211 | cmp r6, ip | 212 | cmp r11, ip |
212 | blo 1b | 213 | blo 1b |
213 | #else | 214 | #else |
214 | 215 | ||
@@ -216,12 +217,12 @@ not_angel: | |||
216 | * Relocate entries in the GOT table. We only relocate | 217 | * Relocate entries in the GOT table. We only relocate |
217 | * the entries that are outside the (relocated) BSS region. | 218 | * the entries that are outside the (relocated) BSS region. |
218 | */ | 219 | */ |
219 | 1: ldr r1, [r6, #0] @ relocate entries in the GOT | 220 | 1: ldr r1, [r11, #0] @ relocate entries in the GOT |
220 | cmp r1, r2 @ entry < bss_start || | 221 | cmp r1, r2 @ entry < bss_start || |
221 | cmphs r3, r1 @ _end < entry | 222 | cmphs r3, r1 @ _end < entry |
222 | addlo r1, r1, r0 @ table. This fixes up the | 223 | addlo r1, r1, r0 @ table. This fixes up the |
223 | str r1, [r6], #4 @ C references. | 224 | str r1, [r11], #4 @ C references. |
224 | cmp r6, ip | 225 | cmp r11, ip |
225 | blo 1b | 226 | blo 1b |
226 | #endif | 227 | #endif |
227 | 228 | ||
@@ -247,6 +248,7 @@ not_relocated: mov r0, #0 | |||
247 | * Check to see if we will overwrite ourselves. | 248 | * Check to see if we will overwrite ourselves. |
248 | * r4 = final kernel address | 249 | * r4 = final kernel address |
249 | * r5 = start of this image | 250 | * r5 = start of this image |
251 | * r6 = size of decompressed image | ||
250 | * r2 = end of malloc space (and therefore this image) | 252 | * r2 = end of malloc space (and therefore this image) |
251 | * We basically want: | 253 | * We basically want: |
252 | * r4 >= r2 -> OK | 254 | * r4 >= r2 -> OK |
@@ -254,8 +256,7 @@ not_relocated: mov r0, #0 | |||
254 | */ | 256 | */ |
255 | cmp r4, r2 | 257 | cmp r4, r2 |
256 | bhs wont_overwrite | 258 | bhs wont_overwrite |
257 | sub r3, sp, r5 @ > compressed kernel size | 259 | add r0, r4, r6 |
258 | add r0, r4, r3, lsl #2 @ allow for 4x expansion | ||
259 | cmp r0, r5 | 260 | cmp r0, r5 |
260 | bls wont_overwrite | 261 | bls wont_overwrite |
261 | 262 | ||
@@ -271,7 +272,6 @@ not_relocated: mov r0, #0 | |||
271 | * r1-r3 = unused | 272 | * r1-r3 = unused |
272 | * r4 = kernel execution address | 273 | * r4 = kernel execution address |
273 | * r5 = decompressed kernel start | 274 | * r5 = decompressed kernel start |
274 | * r6 = processor ID | ||
275 | * r7 = architecture ID | 275 | * r7 = architecture ID |
276 | * r8 = atags pointer | 276 | * r8 = atags pointer |
277 | * r9-r12,r14 = corrupted | 277 | * r9-r12,r14 = corrupted |
@@ -312,7 +312,8 @@ LC0: .word LC0 @ r1 | |||
312 | .word _end @ r3 | 312 | .word _end @ r3 |
313 | .word zreladdr @ r4 | 313 | .word zreladdr @ r4 |
314 | .word _start @ r5 | 314 | .word _start @ r5 |
315 | .word _got_start @ r6 | 315 | .word _image_size @ r6 |
316 | .word _got_start @ r11 | ||
316 | .word _got_end @ ip | 317 | .word _got_end @ ip |
317 | .word user_stack+4096 @ sp | 318 | .word user_stack+4096 @ sp |
318 | LC1: .word reloc_end - reloc_start | 319 | LC1: .word reloc_end - reloc_start |
@@ -336,7 +337,6 @@ params: ldr r0, =params_phys | |||
336 | * | 337 | * |
337 | * On entry, | 338 | * On entry, |
338 | * r4 = kernel execution address | 339 | * r4 = kernel execution address |
339 | * r6 = processor ID | ||
340 | * r7 = architecture number | 340 | * r7 = architecture number |
341 | * r8 = atags pointer | 341 | * r8 = atags pointer |
342 | * r9 = run-time address of "start" (???) | 342 | * r9 = run-time address of "start" (???) |
@@ -542,7 +542,6 @@ __common_mmu_cache_on: | |||
542 | * r1-r3 = unused | 542 | * r1-r3 = unused |
543 | * r4 = kernel execution address | 543 | * r4 = kernel execution address |
544 | * r5 = decompressed kernel start | 544 | * r5 = decompressed kernel start |
545 | * r6 = processor ID | ||
546 | * r7 = architecture ID | 545 | * r7 = architecture ID |
547 | * r8 = atags pointer | 546 | * r8 = atags pointer |
548 | * r9-r12,r14 = corrupted | 547 | * r9-r12,r14 = corrupted |
@@ -581,19 +580,19 @@ call_kernel: bl cache_clean_flush | |||
581 | * r1 = corrupted | 580 | * r1 = corrupted |
582 | * r2 = corrupted | 581 | * r2 = corrupted |
583 | * r3 = block offset | 582 | * r3 = block offset |
584 | * r6 = corrupted | 583 | * r9 = corrupted |
585 | * r12 = corrupted | 584 | * r12 = corrupted |
586 | */ | 585 | */ |
587 | 586 | ||
588 | call_cache_fn: adr r12, proc_types | 587 | call_cache_fn: adr r12, proc_types |
589 | #ifdef CONFIG_CPU_CP15 | 588 | #ifdef CONFIG_CPU_CP15 |
590 | mrc p15, 0, r6, c0, c0 @ get processor ID | 589 | mrc p15, 0, r9, c0, c0 @ get processor ID |
591 | #else | 590 | #else |
592 | ldr r6, =CONFIG_PROCESSOR_ID | 591 | ldr r9, =CONFIG_PROCESSOR_ID |
593 | #endif | 592 | #endif |
594 | 1: ldr r1, [r12, #0] @ get value | 593 | 1: ldr r1, [r12, #0] @ get value |
595 | ldr r2, [r12, #4] @ get mask | 594 | ldr r2, [r12, #4] @ get mask |
596 | eor r1, r1, r6 @ (real ^ match) | 595 | eor r1, r1, r9 @ (real ^ match) |
597 | tst r1, r2 @ & mask | 596 | tst r1, r2 @ & mask |
598 | ARM( addeq pc, r12, r3 ) @ call cache function | 597 | ARM( addeq pc, r12, r3 ) @ call cache function |
599 | THUMB( addeq r12, r3 ) | 598 | THUMB( addeq r12, r3 ) |
@@ -778,8 +777,7 @@ proc_types: | |||
778 | * Turn off the Cache and MMU. ARMv3 does not support | 777 | * Turn off the Cache and MMU. ARMv3 does not support |
779 | * reading the control register, but ARMv4 does. | 778 | * reading the control register, but ARMv4 does. |
780 | * | 779 | * |
781 | * On entry, r6 = processor ID | 780 | * On exit, r0, r1, r2, r3, r9, r12 corrupted |
782 | * On exit, r0, r1, r2, r3, r12 corrupted | ||
783 | * This routine must preserve: r4, r6, r7 | 781 | * This routine must preserve: r4, r6, r7 |
784 | */ | 782 | */ |
785 | .align 5 | 783 | .align 5 |
@@ -852,10 +850,8 @@ __armv3_mmu_cache_off: | |||
852 | /* | 850 | /* |
853 | * Clean and flush the cache to maintain consistency. | 851 | * Clean and flush the cache to maintain consistency. |
854 | * | 852 | * |
855 | * On entry, | ||
856 | * r6 = processor ID | ||
857 | * On exit, | 853 | * On exit, |
858 | * r1, r2, r3, r11, r12 corrupted | 854 | * r1, r2, r3, r9, r11, r12 corrupted |
859 | * This routine must preserve: | 855 | * This routine must preserve: |
860 | * r0, r4, r5, r6, r7 | 856 | * r0, r4, r5, r6, r7 |
861 | */ | 857 | */ |
@@ -967,7 +963,7 @@ __armv4_mmu_cache_flush: | |||
967 | mov r2, #64*1024 @ default: 32K dcache size (*2) | 963 | mov r2, #64*1024 @ default: 32K dcache size (*2) |
968 | mov r11, #32 @ default: 32 byte line size | 964 | mov r11, #32 @ default: 32 byte line size |
969 | mrc p15, 0, r3, c0, c0, 1 @ read cache type | 965 | mrc p15, 0, r3, c0, c0, 1 @ read cache type |
970 | teq r3, r6 @ cache ID register present? | 966 | teq r3, r9 @ cache ID register present? |
971 | beq no_cache_id | 967 | beq no_cache_id |
972 | mov r1, r3, lsr #18 | 968 | mov r1, r3, lsr #18 |
973 | and r1, r1, #7 | 969 | and r1, r1, #7 |
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index a5924b9b88bd..cbed030b55cf 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in | |||
@@ -36,6 +36,9 @@ SECTIONS | |||
36 | 36 | ||
37 | _etext = .; | 37 | _etext = .; |
38 | 38 | ||
39 | /* Assume size of decompressed image is 4x the compressed image */ | ||
40 | _image_size = (_etext - _text) * 4; | ||
41 | |||
39 | _got_start = .; | 42 | _got_start = .; |
40 | .got : { *(.got) } | 43 | .got : { *(.got) } |
41 | _got_end = .; | 44 | _got_end = .; |