diff options
Diffstat (limited to 'arch/arm/kernel/head.S')
-rw-r--r-- | arch/arm/kernel/head.S | 135 |
1 files changed, 52 insertions, 83 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 742b6108a00..239703dbdf4 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/memory.h> | 21 | #include <asm/memory.h> |
22 | #include <asm/thread_info.h> | 22 | #include <asm/thread_info.h> |
23 | #include <asm/system.h> | 23 | #include <asm/system.h> |
24 | #include <asm/pgtable.h> | ||
24 | 25 | ||
25 | #ifdef CONFIG_DEBUG_LL | 26 | #ifdef CONFIG_DEBUG_LL |
26 | #include <mach/debug-macro.S> | 27 | #include <mach/debug-macro.S> |
@@ -38,11 +39,14 @@ | |||
38 | #error KERNEL_RAM_VADDR must start at 0xXXXX8000 | 39 | #error KERNEL_RAM_VADDR must start at 0xXXXX8000 |
39 | #endif | 40 | #endif |
40 | 41 | ||
42 | #define PG_DIR_SIZE 0x4000 | ||
43 | #define PMD_ORDER 2 | ||
44 | |||
41 | .globl swapper_pg_dir | 45 | .globl swapper_pg_dir |
42 | .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 | 46 | .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE |
43 | 47 | ||
44 | .macro pgtbl, rd, phys | 48 | .macro pgtbl, rd, phys |
45 | add \rd, \phys, #TEXT_OFFSET - 0x4000 | 49 | add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE |
46 | .endm | 50 | .endm |
47 | 51 | ||
48 | #ifdef CONFIG_XIP_KERNEL | 52 | #ifdef CONFIG_XIP_KERNEL |
@@ -148,11 +152,11 @@ __create_page_tables: | |||
148 | pgtbl r4, r8 @ page table address | 152 | pgtbl r4, r8 @ page table address |
149 | 153 | ||
150 | /* | 154 | /* |
151 | * Clear the 16K level 1 swapper page table | 155 | * Clear the swapper page table |
152 | */ | 156 | */ |
153 | mov r0, r4 | 157 | mov r0, r4 |
154 | mov r3, #0 | 158 | mov r3, #0 |
155 | add r6, r0, #0x4000 | 159 | add r6, r0, #PG_DIR_SIZE |
156 | 1: str r3, [r0], #4 | 160 | 1: str r3, [r0], #4 |
157 | str r3, [r0], #4 | 161 | str r3, [r0], #4 |
158 | str r3, [r0], #4 | 162 | str r3, [r0], #4 |
@@ -171,30 +175,30 @@ __create_page_tables: | |||
171 | sub r0, r0, r3 @ virt->phys offset | 175 | sub r0, r0, r3 @ virt->phys offset |
172 | add r5, r5, r0 @ phys __enable_mmu | 176 | add r5, r5, r0 @ phys __enable_mmu |
173 | add r6, r6, r0 @ phys __enable_mmu_end | 177 | add r6, r6, r0 @ phys __enable_mmu_end |
174 | mov r5, r5, lsr #20 | 178 | mov r5, r5, lsr #SECTION_SHIFT |
175 | mov r6, r6, lsr #20 | 179 | mov r6, r6, lsr #SECTION_SHIFT |
176 | 180 | ||
177 | 1: orr r3, r7, r5, lsl #20 @ flags + kernel base | 181 | 1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base |
178 | str r3, [r4, r5, lsl #2] @ identity mapping | 182 | str r3, [r4, r5, lsl #PMD_ORDER] @ identity mapping |
179 | teq r5, r6 | 183 | cmp r5, r6 |
180 | addne r5, r5, #1 @ next section | 184 | addlo r5, r5, #1 @ next section |
181 | bne 1b | 185 | blo 1b |
182 | 186 | ||
183 | /* | 187 | /* |
184 | * Now setup the pagetables for our kernel direct | 188 | * Now setup the pagetables for our kernel direct |
185 | * mapped region. | 189 | * mapped region. |
186 | */ | 190 | */ |
187 | mov r3, pc | 191 | mov r3, pc |
188 | mov r3, r3, lsr #20 | 192 | mov r3, r3, lsr #SECTION_SHIFT |
189 | orr r3, r7, r3, lsl #20 | 193 | orr r3, r7, r3, lsl #SECTION_SHIFT |
190 | add r0, r4, #(KERNEL_START & 0xff000000) >> 18 | 194 | add r0, r4, #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) |
191 | str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! | 195 | str r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! |
192 | ldr r6, =(KERNEL_END - 1) | 196 | ldr r6, =(KERNEL_END - 1) |
193 | add r0, r0, #4 | 197 | add r0, r0, #1 << PMD_ORDER |
194 | add r6, r4, r6, lsr #18 | 198 | add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) |
195 | 1: cmp r0, r6 | 199 | 1: cmp r0, r6 |
196 | add r3, r3, #1 << 20 | 200 | add r3, r3, #1 << SECTION_SHIFT |
197 | strls r3, [r0], #4 | 201 | strls r3, [r0], #1 << PMD_ORDER |
198 | bls 1b | 202 | bls 1b |
199 | 203 | ||
200 | #ifdef CONFIG_XIP_KERNEL | 204 | #ifdef CONFIG_XIP_KERNEL |
@@ -203,11 +207,11 @@ __create_page_tables: | |||
203 | */ | 207 | */ |
204 | add r3, r8, #TEXT_OFFSET | 208 | add r3, r8, #TEXT_OFFSET |
205 | orr r3, r3, r7 | 209 | orr r3, r3, r7 |
206 | add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18 | 210 | add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) |
207 | str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! | 211 | str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]! |
208 | ldr r6, =(_end - 1) | 212 | ldr r6, =(_end - 1) |
209 | add r0, r0, #4 | 213 | add r0, r0, #4 |
210 | add r6, r4, r6, lsr #18 | 214 | add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) |
211 | 1: cmp r0, r6 | 215 | 1: cmp r0, r6 |
212 | add r3, r3, #1 << 20 | 216 | add r3, r3, #1 << 20 |
213 | strls r3, [r0], #4 | 217 | strls r3, [r0], #4 |
@@ -218,12 +222,12 @@ __create_page_tables: | |||
218 | * Then map boot params address in r2 or | 222 | * Then map boot params address in r2 or |
219 | * the first 1MB of ram if boot params address is not specified. | 223 | * the first 1MB of ram if boot params address is not specified. |
220 | */ | 224 | */ |
221 | mov r0, r2, lsr #20 | 225 | mov r0, r2, lsr #SECTION_SHIFT |
222 | movs r0, r0, lsl #20 | 226 | movs r0, r0, lsl #SECTION_SHIFT |
223 | moveq r0, r8 | 227 | moveq r0, r8 |
224 | sub r3, r0, r8 | 228 | sub r3, r0, r8 |
225 | add r3, r3, #PAGE_OFFSET | 229 | add r3, r3, #PAGE_OFFSET |
226 | add r3, r4, r3, lsr #18 | 230 | add r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) |
227 | orr r6, r7, r0 | 231 | orr r6, r7, r0 |
228 | str r6, [r3] | 232 | str r6, [r3] |
229 | 233 | ||
@@ -236,21 +240,21 @@ __create_page_tables: | |||
236 | */ | 240 | */ |
237 | addruart r7, r3 | 241 | addruart r7, r3 |
238 | 242 | ||
239 | mov r3, r3, lsr #20 | 243 | mov r3, r3, lsr #SECTION_SHIFT |
240 | mov r3, r3, lsl #2 | 244 | mov r3, r3, lsl #PMD_ORDER |
241 | 245 | ||
242 | add r0, r4, r3 | 246 | add r0, r4, r3 |
243 | rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) | 247 | rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) |
244 | cmp r3, #0x0800 @ limit to 512MB | 248 | cmp r3, #0x0800 @ limit to 512MB |
245 | movhi r3, #0x0800 | 249 | movhi r3, #0x0800 |
246 | add r6, r0, r3 | 250 | add r6, r0, r3 |
247 | mov r3, r7, lsr #20 | 251 | mov r3, r7, lsr #SECTION_SHIFT |
248 | ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags | 252 | ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags |
249 | orr r3, r7, r3, lsl #20 | 253 | orr r3, r7, r3, lsl #SECTION_SHIFT |
250 | 1: str r3, [r0], #4 | 254 | 1: str r3, [r0], #4 |
251 | add r3, r3, #1 << 20 | 255 | add r3, r3, #1 << SECTION_SHIFT |
252 | teq r0, r6 | 256 | cmp r0, r6 |
253 | bne 1b | 257 | blo 1b |
254 | 258 | ||
255 | #else /* CONFIG_DEBUG_ICEDCC */ | 259 | #else /* CONFIG_DEBUG_ICEDCC */ |
256 | /* we don't need any serial debugging mappings for ICEDCC */ | 260 | /* we don't need any serial debugging mappings for ICEDCC */ |
@@ -262,7 +266,7 @@ __create_page_tables: | |||
262 | * If we're using the NetWinder or CATS, we also need to map | 266 | * If we're using the NetWinder or CATS, we also need to map |
263 | * in the 16550-type serial port for the debug messages | 267 | * in the 16550-type serial port for the debug messages |
264 | */ | 268 | */ |
265 | add r0, r4, #0xff000000 >> 18 | 269 | add r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER) |
266 | orr r3, r7, #0x7c000000 | 270 | orr r3, r7, #0x7c000000 |
267 | str r3, [r0] | 271 | str r3, [r0] |
268 | #endif | 272 | #endif |
@@ -272,10 +276,10 @@ __create_page_tables: | |||
272 | * Similar reasons here - for debug. This is | 276 | * Similar reasons here - for debug. This is |
273 | * only for Acorn RiscPC architectures. | 277 | * only for Acorn RiscPC architectures. |
274 | */ | 278 | */ |
275 | add r0, r4, #0x02000000 >> 18 | 279 | add r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER) |
276 | orr r3, r7, #0x02000000 | 280 | orr r3, r7, #0x02000000 |
277 | str r3, [r0] | 281 | str r3, [r0] |
278 | add r0, r4, #0xd8000000 >> 18 | 282 | add r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER) |
279 | str r3, [r0] | 283 | str r3, [r0] |
280 | #endif | 284 | #endif |
281 | #endif | 285 | #endif |
@@ -488,13 +492,8 @@ __fixup_pv_table: | |||
488 | add r5, r5, r3 @ adjust table end address | 492 | add r5, r5, r3 @ adjust table end address |
489 | add r7, r7, r3 @ adjust __pv_phys_offset address | 493 | add r7, r7, r3 @ adjust __pv_phys_offset address |
490 | str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset | 494 | str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset |
491 | #ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | ||
492 | mov r6, r3, lsr #24 @ constant for add/sub instructions | 495 | mov r6, r3, lsr #24 @ constant for add/sub instructions |
493 | teq r3, r6, lsl #24 @ must be 16MiB aligned | 496 | teq r3, r6, lsl #24 @ must be 16MiB aligned |
494 | #else | ||
495 | mov r6, r3, lsr #16 @ constant for add/sub instructions | ||
496 | teq r3, r6, lsl #16 @ must be 64kiB aligned | ||
497 | #endif | ||
498 | THUMB( it ne @ cross section branch ) | 497 | THUMB( it ne @ cross section branch ) |
499 | bne __error | 498 | bne __error |
500 | str r6, [r7, #4] @ save to __pv_offset | 499 | str r6, [r7, #4] @ save to __pv_offset |
@@ -510,20 +509,8 @@ ENDPROC(__fixup_pv_table) | |||
510 | .text | 509 | .text |
511 | __fixup_a_pv_table: | 510 | __fixup_a_pv_table: |
512 | #ifdef CONFIG_THUMB2_KERNEL | 511 | #ifdef CONFIG_THUMB2_KERNEL |
513 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | 512 | lsls r6, #24 |
514 | lsls r0, r6, #24 | 513 | beq 2f |
515 | lsr r6, #8 | ||
516 | beq 1f | ||
517 | clz r7, r0 | ||
518 | lsr r0, #24 | ||
519 | lsl r0, r7 | ||
520 | bic r0, 0x0080 | ||
521 | lsrs r7, #1 | ||
522 | orrcs r0, #0x0080 | ||
523 | orr r0, r0, r7, lsl #12 | ||
524 | #endif | ||
525 | 1: lsls r6, #24 | ||
526 | beq 4f | ||
527 | clz r7, r6 | 514 | clz r7, r6 |
528 | lsr r6, #24 | 515 | lsr r6, #24 |
529 | lsl r6, r7 | 516 | lsl r6, r7 |
@@ -532,43 +519,25 @@ __fixup_a_pv_table: | |||
532 | orrcs r6, #0x0080 | 519 | orrcs r6, #0x0080 |
533 | orr r6, r6, r7, lsl #12 | 520 | orr r6, r6, r7, lsl #12 |
534 | orr r6, #0x4000 | 521 | orr r6, #0x4000 |
535 | b 4f | 522 | b 2f |
536 | 2: @ at this point the C flag is always clear | 523 | 1: add r7, r3 |
537 | add r7, r3 | 524 | ldrh ip, [r7, #2] |
538 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | ||
539 | ldrh ip, [r7] | ||
540 | tst ip, 0x0400 @ the i bit tells us LS or MS byte | ||
541 | beq 3f | ||
542 | cmp r0, #0 @ set C flag, and ... | ||
543 | biceq ip, 0x0400 @ immediate zero value has a special encoding | ||
544 | streqh ip, [r7] @ that requires the i bit cleared | ||
545 | #endif | ||
546 | 3: ldrh ip, [r7, #2] | ||
547 | and ip, 0x8f00 | 525 | and ip, 0x8f00 |
548 | orrcc ip, r6 @ mask in offset bits 31-24 | 526 | orr ip, r6 @ mask in offset bits 31-24 |
549 | orrcs ip, r0 @ mask in offset bits 23-16 | ||
550 | strh ip, [r7, #2] | 527 | strh ip, [r7, #2] |
551 | 4: cmp r4, r5 | 528 | 2: cmp r4, r5 |
552 | ldrcc r7, [r4], #4 @ use branch for delay slot | 529 | ldrcc r7, [r4], #4 @ use branch for delay slot |
553 | bcc 2b | 530 | bcc 1b |
554 | bx lr | 531 | bx lr |
555 | #else | 532 | #else |
556 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | 533 | b 2f |
557 | and r0, r6, #255 @ offset bits 23-16 | 534 | 1: ldr ip, [r7, r3] |
558 | mov r6, r6, lsr #8 @ offset bits 31-24 | ||
559 | #else | ||
560 | mov r0, #0 @ just in case... | ||
561 | #endif | ||
562 | b 3f | ||
563 | 2: ldr ip, [r7, r3] | ||
564 | bic ip, ip, #0x000000ff | 535 | bic ip, ip, #0x000000ff |
565 | tst ip, #0x400 @ rotate shift tells us LS or MS byte | 536 | orr ip, ip, r6 @ mask in offset bits 31-24 |
566 | orrne ip, ip, r6 @ mask in offset bits 31-24 | ||
567 | orreq ip, ip, r0 @ mask in offset bits 23-16 | ||
568 | str ip, [r7, r3] | 537 | str ip, [r7, r3] |
569 | 3: cmp r4, r5 | 538 | 2: cmp r4, r5 |
570 | ldrcc r7, [r4], #4 @ use branch for delay slot | 539 | ldrcc r7, [r4], #4 @ use branch for delay slot |
571 | bcc 2b | 540 | bcc 1b |
572 | mov pc, lr | 541 | mov pc, lr |
573 | #endif | 542 | #endif |
574 | ENDPROC(__fixup_a_pv_table) | 543 | ENDPROC(__fixup_a_pv_table) |