aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2011-02-21 00:53:35 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-03-10 11:43:45 -0500
commitb511d75d6150892e67c8ebfa9dc8eb37ebd02aa3 (patch)
tree0cec12cd64edeecac2b737f2788b012eab538285 /arch/arm
parent80f0aad77f3e1e9d9e518b09ac46963d628ae2be (diff)
ARM: 6747/1: P2V: Thumb2 support
Adding Thumb2 support to the runtime patching of the virt_to_phys and phys_to_virt opcodes. Tested both the 8-bit and the 16-bit fixups, using different placements in memory to exercize all code paths. Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> Reviewed-by: Dave Martin <dave.martin@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm/kernel/head.S49
2 files changed, 50 insertions, 3 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b357c29e7dfc..0233c8ff1f19 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -194,13 +194,13 @@ config VECTORS_BASE
194config ARM_PATCH_PHYS_VIRT 194config ARM_PATCH_PHYS_VIRT
195 bool "Patch physical to virtual translations at runtime (EXPERIMENTAL)" 195 bool "Patch physical to virtual translations at runtime (EXPERIMENTAL)"
196 depends on EXPERIMENTAL 196 depends on EXPERIMENTAL
197 depends on !XIP_KERNEL && !THUMB2_KERNEL && MMU 197 depends on !XIP_KERNEL && MMU
198 depends on !ARCH_REALVIEW || !SPARSEMEM 198 depends on !ARCH_REALVIEW || !SPARSEMEM
199 help 199 help
200 Patch phys-to-virt translation functions at runtime according to 200 Patch phys-to-virt translation functions at runtime according to
201 the position of the kernel in system memory. 201 the position of the kernel in system memory.
202 202
203 This can only be used with non-XIP, non-Thumb2, MMU kernels where 203 This can only be used with non-XIP with MMU kernels where
204 the base of physical memory is at a 16MB boundary. 204 the base of physical memory is at a 16MB boundary.
205 205
206config ARM_PATCH_PHYS_VIRT_16BIT 206config ARM_PATCH_PHYS_VIRT_16BIT
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 591a2ead8cef..6a87261e1b1e 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -461,7 +461,8 @@ __fixup_pv_table:
461 sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET 461 sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET
462 add r4, r4, r3 @ adjust table start address 462 add r4, r4, r3 @ adjust table start address
463 add r5, r5, r3 @ adjust table end address 463 add r5, r5, r3 @ adjust table end address
464 str r8, [r7, r3]! @ save computed PHYS_OFFSET to __pv_phys_offset 464 add r7, r7, r3 @ adjust __pv_phys_offset address
465 str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset
465#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT 466#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
466 mov r6, r3, lsr #24 @ constant for add/sub instructions 467 mov r6, r3, lsr #24 @ constant for add/sub instructions
467 teq r3, r6, lsl #24 @ must be 16MiB aligned 468 teq r3, r6, lsl #24 @ must be 16MiB aligned
@@ -469,6 +470,7 @@ __fixup_pv_table:
469 mov r6, r3, lsr #16 @ constant for add/sub instructions 470 mov r6, r3, lsr #16 @ constant for add/sub instructions
470 teq r3, r6, lsl #16 @ must be 64kiB aligned 471 teq r3, r6, lsl #16 @ must be 64kiB aligned
471#endif 472#endif
473THUMB( it ne @ cross section branch )
472 bne __error 474 bne __error
473 str r6, [r7, #4] @ save to __pv_offset 475 str r6, [r7, #4] @ save to __pv_offset
474 b __fixup_a_pv_table 476 b __fixup_a_pv_table
@@ -482,6 +484,50 @@ ENDPROC(__fixup_pv_table)
482 484
483 .text 485 .text
484__fixup_a_pv_table: 486__fixup_a_pv_table:
487#ifdef CONFIG_THUMB2_KERNEL
488#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
489 lsls r0, r6, #24
490 lsr r6, #8
491 beq 1f
492 clz r7, r0
493 lsr r0, #24
494 lsl r0, r7
495 bic r0, 0x0080
496 lsrs r7, #1
497 orrcs r0, #0x0080
498 orr r0, r0, r7, lsl #12
499#endif
5001: lsls r6, #24
501 beq 4f
502 clz r7, r6
503 lsr r6, #24
504 lsl r6, r7
505 bic r6, #0x0080
506 lsrs r7, #1
507 orrcs r6, #0x0080
508 orr r6, r6, r7, lsl #12
509 orr r6, #0x4000
510 b 4f
5112: @ at this point the C flag is always clear
512 add r7, r3
513#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
514 ldrh ip, [r7]
515 tst ip, 0x0400 @ the i bit tells us LS or MS byte
516 beq 3f
517 cmp r0, #0 @ set C flag, and ...
518 biceq ip, 0x0400 @ immediate zero value has a special encoding
519 streqh ip, [r7] @ that requires the i bit cleared
520#endif
5213: ldrh ip, [r7, #2]
522 and ip, 0x8f00
523 orrcc ip, r6 @ mask in offset bits 31-24
524 orrcs ip, r0 @ mask in offset bits 23-16
525 strh ip, [r7, #2]
5264: cmp r4, r5
527 ldrcc r7, [r4], #4 @ use branch for delay slot
528 bcc 2b
529 bx lr
530#else
485#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT 531#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
486 and r0, r6, #255 @ offset bits 23-16 532 and r0, r6, #255 @ offset bits 23-16
487 mov r6, r6, lsr #8 @ offset bits 31-24 533 mov r6, r6, lsr #8 @ offset bits 31-24
@@ -499,6 +545,7 @@ __fixup_a_pv_table:
499 ldrcc r7, [r4], #4 @ use branch for delay slot 545 ldrcc r7, [r4], #4 @ use branch for delay slot
500 bcc 2b 546 bcc 2b
501 mov pc, lr 547 mov pc, lr
548#endif
502ENDPROC(__fixup_a_pv_table) 549ENDPROC(__fixup_a_pv_table)
503 550
504ENTRY(fixup_pv_table) 551ENTRY(fixup_pv_table)