aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/head.S')
-rw-r--r--arch/arm/kernel/head.S107
1 files changed, 23 insertions, 84 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 8bac553fe21..e2bd26e5c3d 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -121,7 +121,7 @@ ENTRY(stext)
121 bl __fixup_smp 121 bl __fixup_smp
122#endif 122#endif
123#ifdef CONFIG_ARM_PATCH_PHYS_VIRT 123#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
124 bl __fixup_pv_table 124 bl __fixup_pv_offsets
125#endif 125#endif
126 bl __create_page_tables 126 bl __create_page_tables
127 127
@@ -156,7 +156,7 @@ ENDPROC(stext)
156 * 156 *
157 * Returns: 157 * Returns:
158 * r0, r3, r5-r7 corrupted 158 * r0, r3, r5-r7 corrupted
159 * r4 = physical page table address 159 * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
160 */ 160 */
161__create_page_tables: 161__create_page_tables:
162 pgtbl r4, r8 @ page table address 162 pgtbl r4, r8 @ page table address
@@ -331,6 +331,7 @@ __create_page_tables:
331#endif 331#endif
332#ifdef CONFIG_ARM_LPAE 332#ifdef CONFIG_ARM_LPAE
333 sub r4, r4, #0x1000 @ point to the PGD table 333 sub r4, r4, #0x1000 @ point to the PGD table
334 mov r4, r4, lsr #ARCH_PGD_SHIFT
334#endif 335#endif
335 mov pc, lr 336 mov pc, lr
336ENDPROC(__create_page_tables) 337ENDPROC(__create_page_tables)
@@ -408,7 +409,7 @@ __secondary_data:
408 * r0 = cp#15 control register 409 * r0 = cp#15 control register
409 * r1 = machine ID 410 * r1 = machine ID
410 * r2 = atags or dtb pointer 411 * r2 = atags or dtb pointer
411 * r4 = page table pointer 412 * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
412 * r9 = processor ID 413 * r9 = processor ID
413 * r13 = *virtual* address to jump to upon completion 414 * r13 = *virtual* address to jump to upon completion
414 */ 415 */
@@ -427,10 +428,7 @@ __enable_mmu:
427#ifdef CONFIG_CPU_ICACHE_DISABLE 428#ifdef CONFIG_CPU_ICACHE_DISABLE
428 bic r0, r0, #CR_I 429 bic r0, r0, #CR_I
429#endif 430#endif
430#ifdef CONFIG_ARM_LPAE 431#ifndef CONFIG_ARM_LPAE
431 mov r5, #0
432 mcrr p15, 0, r4, r5, c2 @ load TTBR0
433#else
434 mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ 432 mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
435 domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ 433 domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
436 domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ 434 domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
@@ -540,92 +538,33 @@ ENDPROC(fixup_smp)
540 538
541#ifdef CONFIG_ARM_PATCH_PHYS_VIRT 539#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
542 540
543/* __fixup_pv_table - patch the stub instructions with the delta between 541/*
544 * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and 542 * __fixup_pv_offsets - update __pv_offset and __pv_phys_offset based on the
545 * can be expressed by an immediate shifter operand. The stub instruction 543 * runtime location of the kernel.
546 * has a form of '(add|sub) rd, rn, #imm'.
547 */ 544 */
548 __HEAD 545 __HEAD
549__fixup_pv_table: 546__fixup_pv_offsets:
550 adr r0, 1f 547 adr r0, 1f
551 ldmia r0, {r3-r5, r7} 548 ldmia r0, {r3-r6}
552 sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET 549 sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET
553 add r4, r4, r3 @ adjust table start address 550 add r4, r4, r3 @ virt_to_phys(__pv_phys_offset)
554 add r5, r5, r3 @ adjust table end address 551 add r5, r5, r3 @ virt_to_phys(__pv_offset)
555 add r7, r7, r3 @ adjust __pv_phys_offset address 552 add r6, r6, r3 @ virt_to_phys(PAGE_OFFSET) = PHYS_OFFSET
556 str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset 553 str r6, [r4] @ save __pv_phys_offset
557 mov r6, r3, lsr #24 @ constant for add/sub instructions 554 str r3, [r5] @ save __pv_offset
558 teq r3, r6, lsl #24 @ must be 16MiB aligned 555 mov pc, lr
559THUMB( it ne @ cross section branch ) 556ENDPROC(__fixup_pv_offsets)
560 bne __error
561 str r6, [r7, #4] @ save to __pv_offset
562 b __fixup_a_pv_table
563ENDPROC(__fixup_pv_table)
564 557
565 .align 558 .align
5661: .long . 5591: .long .
567 .long __pv_table_begin 560#if defined(CONFIG_ARM_LPAE) && defined(__ARMEB__)
568 .long __pv_table_end 561 .long __pv_phys_offset + 4
5692: .long __pv_phys_offset
570
571 .text
572__fixup_a_pv_table:
573#ifdef CONFIG_THUMB2_KERNEL
574 lsls r6, #24
575 beq 2f
576 clz r7, r6
577 lsr r6, #24
578 lsl r6, r7
579 bic r6, #0x0080
580 lsrs r7, #1
581 orrcs r6, #0x0080
582 orr r6, r6, r7, lsl #12
583 orr r6, #0x4000
584 b 2f
5851: add r7, r3
586 ldrh ip, [r7, #2]
587 and ip, 0x8f00
588 orr ip, r6 @ mask in offset bits 31-24
589 strh ip, [r7, #2]
5902: cmp r4, r5
591 ldrcc r7, [r4], #4 @ use branch for delay slot
592 bcc 1b
593 bx lr
594#else 562#else
595 b 2f 563 .long __pv_phys_offset
5961: ldr ip, [r7, r3]
597 bic ip, ip, #0x000000ff
598 orr ip, ip, r6 @ mask in offset bits 31-24
599 str ip, [r7, r3]
6002: cmp r4, r5
601 ldrcc r7, [r4], #4 @ use branch for delay slot
602 bcc 1b
603 mov pc, lr
604#endif 564#endif
605ENDPROC(__fixup_a_pv_table) 565 .long __pv_offset
606 566 .long PAGE_OFFSET
607ENTRY(fixup_pv_table)
608 stmfd sp!, {r4 - r7, lr}
609 ldr r2, 2f @ get address of __pv_phys_offset
610 mov r3, #0 @ no offset
611 mov r4, r0 @ r0 = table start
612 add r5, r0, r1 @ r1 = table size
613 ldr r6, [r2, #4] @ get __pv_offset
614 bl __fixup_a_pv_table
615 ldmfd sp!, {r4 - r7, pc}
616ENDPROC(fixup_pv_table)
617
618 .align
6192: .long __pv_phys_offset
620
621 .data
622 .globl __pv_phys_offset
623 .type __pv_phys_offset, %object
624__pv_phys_offset:
625 .long 0
626 .size __pv_phys_offset, . - __pv_phys_offset
627__pv_offset:
628 .long 0
629#endif 567#endif
630 568
569
631#include "head-common.S" 570#include "head-common.S"