diff options
Diffstat (limited to 'arch/arm/kernel/head.S')
-rw-r--r-- | arch/arm/kernel/head.S | 107 |
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 |
336 | ENDPROC(__create_page_tables) | 337 | ENDPROC(__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 |
559 | THUMB( it ne @ cross section branch ) | 556 | ENDPROC(__fixup_pv_offsets) |
560 | bne __error | ||
561 | str r6, [r7, #4] @ save to __pv_offset | ||
562 | b __fixup_a_pv_table | ||
563 | ENDPROC(__fixup_pv_table) | ||
564 | 557 | ||
565 | .align | 558 | .align |
566 | 1: .long . | 559 | 1: .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 |
569 | 2: .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 | ||
585 | 1: 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] | ||
590 | 2: 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 |
596 | 1: 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] | ||
600 | 2: cmp r4, r5 | ||
601 | ldrcc r7, [r4], #4 @ use branch for delay slot | ||
602 | bcc 1b | ||
603 | mov pc, lr | ||
604 | #endif | 564 | #endif |
605 | ENDPROC(__fixup_a_pv_table) | 565 | .long __pv_offset |
606 | 566 | .long PAGE_OFFSET | |
607 | ENTRY(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} | ||
616 | ENDPROC(fixup_pv_table) | ||
617 | |||
618 | .align | ||
619 | 2: .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" |