aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/head.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/head.S')
-rw-r--r--arch/arm/kernel/head.S68
1 files changed, 68 insertions, 0 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 03a588b6e15c..1db8ead2e331 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -98,6 +98,9 @@ ENTRY(stext)
98#ifdef CONFIG_SMP_ON_UP 98#ifdef CONFIG_SMP_ON_UP
99 bl __fixup_smp 99 bl __fixup_smp
100#endif 100#endif
101#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
102 bl __fixup_pv_table
103#endif
101 bl __create_page_tables 104 bl __create_page_tables
102 105
103 /* 106 /*
@@ -438,4 +441,69 @@ smp_on_up:
438 441
439#endif 442#endif
440 443
444#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
445
446/* __fixup_pv_table - patch the stub instructions with the delta between
447 * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and
448 * can be expressed by an immediate shifter operand. The stub instruction
449 * has a form of '(add|sub) rd, rn, #imm'.
450 */
451 __HEAD
452__fixup_pv_table:
453 adr r0, 1f
454 ldmia r0, {r3-r5, r7}
455 sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET
456 add r4, r4, r3 @ adjust table start address
457 add r5, r5, r3 @ adjust table end address
458 str r8, [r7, r3]! @ save computed PHYS_OFFSET to __pv_phys_offset
459 mov r6, r3, lsr #24 @ constant for add/sub instructions
460 teq r3, r6, lsl #24 @ must be 16MiB aligned
461 bne __error
462 str r6, [r7, #4] @ save to __pv_offset
463 b __fixup_a_pv_table
464ENDPROC(__fixup_pv_table)
465
466 .align
4671: .long .
468 .long __pv_table_begin
469 .long __pv_table_end
4702: .long __pv_phys_offset
471
472 .text
473__fixup_a_pv_table:
474 b 3f
4752: ldr ip, [r7, r3]
476 bic ip, ip, #0x000000ff
477 orr ip, ip, r6
478 str ip, [r7, r3]
4793: cmp r4, r5
480 ldrcc r7, [r4], #4 @ use branch for delay slot
481 bcc 2b
482 mov pc, lr
483ENDPROC(__fixup_a_pv_table)
484
485ENTRY(fixup_pv_table)
486 stmfd sp!, {r4 - r7, lr}
487 ldr r2, 2f @ get address of __pv_phys_offset
488 mov r3, #0 @ no offset
489 mov r4, r0 @ r0 = table start
490 add r5, r0, r1 @ r1 = table size
491 ldr r6, [r2, #4] @ get __pv_offset
492 bl __fixup_a_pv_table
493 ldmfd sp!, {r4 - r7, pc}
494ENDPROC(fixup_pv_table)
495
496 .align
4972: .long __pv_phys_offset
498
499 .data
500 .globl __pv_phys_offset
501 .type __pv_phys_offset, %object
502__pv_phys_offset:
503 .long 0
504 .size __pv_phys_offset, . - __pv_phys_offset
505__pv_offset:
506 .long 0
507#endif
508
441#include "head-common.S" 509#include "head-common.S"