diff options
author | Nicolas Pitre <nico@cam.org> | 2007-02-22 10:18:09 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-02-25 11:41:38 -0500 |
commit | e98ff7f6d8164c5636538998fb7d1e08b1fbbddd (patch) | |
tree | aa5448d3b8c293e7e0df786669092e6cac55c068 | |
parent | 0ebffe39f8ec8b5b126d9505852a396371014555 (diff) |
[ARM] 4224/2: allow XIP kernel to boot again
Since commit 2552fc27ff79b10b9678d92bcaef21df38bb7bb6 XIP kernels failed
to boot because (_end - PAGE_OFFSET - 1) is much smaller than the size
of the kernel text and data in the XIP case, causing the kernel not to
be entirely mapped.
Even in the non-XIP case, the use of (_end - PAGE_OFFSET - 1) is wrong
because it produces a too large value if TEXT_OFFSET is larger than 1MB.
Finally the original code was performing one loop too many.
Let's break the loop when the section pointer has passed the last byte
of the kernel instead.
Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/kernel/head.S | 25 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 1 |
2 files changed, 14 insertions, 12 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index cf495a3084b3..c5f0c52660b2 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -48,9 +48,11 @@ | |||
48 | .endm | 48 | .endm |
49 | 49 | ||
50 | #ifdef CONFIG_XIP_KERNEL | 50 | #ifdef CONFIG_XIP_KERNEL |
51 | #define TEXTADDR XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) | 51 | #define KERNEL_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) |
52 | #define KERNEL_END _edata_loc | ||
52 | #else | 53 | #else |
53 | #define TEXTADDR KERNEL_RAM_VADDR | 54 | #define KERNEL_START KERNEL_RAM_VADDR |
55 | #define KERNEL_END _end | ||
54 | #endif | 56 | #endif |
55 | 57 | ||
56 | /* | 58 | /* |
@@ -240,16 +242,15 @@ __create_page_tables: | |||
240 | * Now setup the pagetables for our kernel direct | 242 | * Now setup the pagetables for our kernel direct |
241 | * mapped region. | 243 | * mapped region. |
242 | */ | 244 | */ |
243 | add r0, r4, #(TEXTADDR & 0xff000000) >> 18 @ start of kernel | 245 | add r0, r4, #(KERNEL_START & 0xff000000) >> 18 |
244 | str r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]! | 246 | str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! |
245 | 247 | ldr r6, =(KERNEL_END - 1) | |
246 | ldr r6, =(_end - PAGE_OFFSET - 1) @ r6 = number of sections | 248 | add r0, r0, #4 |
247 | mov r6, r6, lsr #20 @ needed for kernel minus 1 | 249 | add r6, r4, r6, lsr #18 |
248 | 250 | 1: cmp r0, r6 | |
249 | 1: add r3, r3, #1 << 20 | 251 | add r3, r3, #1 << 20 |
250 | str r3, [r0, #4]! | 252 | strls r3, [r0], #4 |
251 | subs r6, r6, #1 | 253 | bls 1b |
252 | bgt 1b | ||
253 | 254 | ||
254 | /* | 255 | /* |
255 | * Then map first 1MB of ram in case it contains our boot params. | 256 | * Then map first 1MB of ram in case it contains our boot params. |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index b929a60f7547..ddbdad48f5b2 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -156,6 +156,7 @@ SECTIONS | |||
156 | 156 | ||
157 | _edata = .; | 157 | _edata = .; |
158 | } | 158 | } |
159 | _edata_loc = __data_loc + SIZEOF(.data); | ||
159 | 160 | ||
160 | .bss : { | 161 | .bss : { |
161 | __bss_start = .; /* BSS */ | 162 | __bss_start = .; /* BSS */ |