diff options
| author | Nicolas Pitre <nicolas.pitre@linaro.org> | 2011-02-21 00:53:35 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-03-10 11:43:45 -0500 |
| commit | b511d75d6150892e67c8ebfa9dc8eb37ebd02aa3 (patch) | |
| tree | 0cec12cd64edeecac2b737f2788b012eab538285 | |
| parent | 80f0aad77f3e1e9d9e518b09ac46963d628ae2be (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>
| -rw-r--r-- | arch/arm/Kconfig | 4 | ||||
| -rw-r--r-- | arch/arm/kernel/head.S | 49 |
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 | |||
| 194 | config ARM_PATCH_PHYS_VIRT | 194 | config 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 | ||
| 206 | config ARM_PATCH_PHYS_VIRT_16BIT | 206 | config 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 |
| 473 | THUMB( 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 | ||
| 500 | 1: 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 | ||
| 511 | 2: @ 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 | ||
| 521 | 3: 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] | ||
| 526 | 4: 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 | ||
| 502 | ENDPROC(__fixup_a_pv_table) | 549 | ENDPROC(__fixup_a_pv_table) |
| 503 | 550 | ||
| 504 | ENTRY(fixup_pv_table) | 551 | ENTRY(fixup_pv_table) |
