diff options
Diffstat (limited to 'arch/arm')
-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) |