diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-04 14:39:29 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-02-17 18:27:33 -0500 |
commit | cada3c0841e1deaec4c0f92654610b028dc683ff (patch) | |
tree | 9c6085c8b8447795ddc749315a31fd3906a6159d | |
parent | dc21af99fadcfa0ae65b52fd0895f85824f0c288 (diff) |
ARM: P2V: extend to 16-bit translation offsets
MSM's memory is aligned to 2MB, which is more than we can do with our
existing method as we're limited to the upper 8 bits. Extend this by
using two instructions to 16 bits, automatically selected when MSM is
enabled.
Acked-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Tested-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/include/asm/memory.h | 21 | ||||
-rw-r--r-- | arch/arm/include/asm/module.h | 4 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 15 |
4 files changed, 39 insertions, 6 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4147f76e7988..b357c29e7dfc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -195,7 +195,6 @@ 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 && !THUMB2_KERNEL && MMU |
198 | depends on !ARCH_MSM | ||
199 | depends on !ARCH_REALVIEW || !SPARSEMEM | 198 | depends on !ARCH_REALVIEW || !SPARSEMEM |
200 | help | 199 | help |
201 | Patch phys-to-virt translation functions at runtime according to | 200 | Patch phys-to-virt translation functions at runtime according to |
@@ -204,6 +203,10 @@ config ARM_PATCH_PHYS_VIRT | |||
204 | This can only be used with non-XIP, non-Thumb2, MMU kernels where | 203 | This can only be used with non-XIP, non-Thumb2, MMU kernels where |
205 | the base of physical memory is at a 16MB boundary. | 204 | the base of physical memory is at a 16MB boundary. |
206 | 205 | ||
206 | config ARM_PATCH_PHYS_VIRT_16BIT | ||
207 | def_bool y | ||
208 | depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM | ||
209 | |||
207 | source "init/Kconfig" | 210 | source "init/Kconfig" |
208 | 211 | ||
209 | source "kernel/Kconfig.freezer" | 212 | source "kernel/Kconfig.freezer" |
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 7197879e1cb7..2398b3fc0268 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h | |||
@@ -154,29 +154,42 @@ | |||
154 | #ifndef __virt_to_phys | 154 | #ifndef __virt_to_phys |
155 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT | 155 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT |
156 | 156 | ||
157 | /* | ||
158 | * Constants used to force the right instruction encodings and shifts | ||
159 | * so that all we need to do is modify the 8-bit constant field. | ||
160 | */ | ||
161 | #define __PV_BITS_31_24 0x81000000 | ||
162 | #define __PV_BITS_23_16 0x00810000 | ||
163 | |||
157 | extern unsigned long __pv_phys_offset; | 164 | extern unsigned long __pv_phys_offset; |
158 | #define PHYS_OFFSET __pv_phys_offset | 165 | #define PHYS_OFFSET __pv_phys_offset |
159 | 166 | ||
160 | #define __pv_stub(from,to,instr) \ | 167 | #define __pv_stub(from,to,instr,type) \ |
161 | __asm__("@ __pv_stub\n" \ | 168 | __asm__("@ __pv_stub\n" \ |
162 | "1: " instr " %0, %1, %2\n" \ | 169 | "1: " instr " %0, %1, %2\n" \ |
163 | " .pushsection .pv_table,\"a\"\n" \ | 170 | " .pushsection .pv_table,\"a\"\n" \ |
164 | " .long 1b\n" \ | 171 | " .long 1b\n" \ |
165 | " .popsection\n" \ | 172 | " .popsection\n" \ |
166 | : "=r" (to) \ | 173 | : "=r" (to) \ |
167 | : "r" (from), "I" (0x81000000)) | 174 | : "r" (from), "I" (type)) |
168 | 175 | ||
169 | static inline unsigned long __virt_to_phys(unsigned long x) | 176 | static inline unsigned long __virt_to_phys(unsigned long x) |
170 | { | 177 | { |
171 | unsigned long t; | 178 | unsigned long t; |
172 | __pv_stub(x, t, "add"); | 179 | __pv_stub(x, t, "add", __PV_BITS_31_24); |
180 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | ||
181 | __pv_stub(t, t, "add", __PV_BITS_23_16); | ||
182 | #endif | ||
173 | return t; | 183 | return t; |
174 | } | 184 | } |
175 | 185 | ||
176 | static inline unsigned long __phys_to_virt(unsigned long x) | 186 | static inline unsigned long __phys_to_virt(unsigned long x) |
177 | { | 187 | { |
178 | unsigned long t; | 188 | unsigned long t; |
179 | __pv_stub(x, t, "sub"); | 189 | __pv_stub(x, t, "sub", __PV_BITS_31_24); |
190 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | ||
191 | __pv_stub(t, t, "sub", __PV_BITS_23_16); | ||
192 | #endif | ||
180 | return t; | 193 | return t; |
181 | } | 194 | } |
182 | #else | 195 | #else |
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index d072c21332ee..a2b775b81cfa 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h | |||
@@ -31,7 +31,11 @@ struct mod_arch_specific { | |||
31 | 31 | ||
32 | /* Add __virt_to_phys patching state as well */ | 32 | /* Add __virt_to_phys patching state as well */ |
33 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT | 33 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT |
34 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | ||
35 | #define MODULE_ARCH_VERMAGIC_P2V "p2v16 " | ||
36 | #else | ||
34 | #define MODULE_ARCH_VERMAGIC_P2V "p2v8 " | 37 | #define MODULE_ARCH_VERMAGIC_P2V "p2v8 " |
38 | #endif | ||
35 | #else | 39 | #else |
36 | #define MODULE_ARCH_VERMAGIC_P2V "" | 40 | #define MODULE_ARCH_VERMAGIC_P2V "" |
37 | #endif | 41 | #endif |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 1db8ead2e331..a94dd99d54c3 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -456,8 +456,13 @@ __fixup_pv_table: | |||
456 | add r4, r4, r3 @ adjust table start address | 456 | add r4, r4, r3 @ adjust table start address |
457 | add r5, r5, r3 @ adjust table end address | 457 | add r5, r5, r3 @ adjust table end address |
458 | str r8, [r7, r3]! @ save computed PHYS_OFFSET to __pv_phys_offset | 458 | str r8, [r7, r3]! @ save computed PHYS_OFFSET to __pv_phys_offset |
459 | #ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | ||
459 | mov r6, r3, lsr #24 @ constant for add/sub instructions | 460 | mov r6, r3, lsr #24 @ constant for add/sub instructions |
460 | teq r3, r6, lsl #24 @ must be 16MiB aligned | 461 | teq r3, r6, lsl #24 @ must be 16MiB aligned |
462 | #else | ||
463 | mov r6, r3, lsr #16 @ constant for add/sub instructions | ||
464 | teq r3, r6, lsl #16 @ must be 64kiB aligned | ||
465 | #endif | ||
461 | bne __error | 466 | bne __error |
462 | str r6, [r7, #4] @ save to __pv_offset | 467 | str r6, [r7, #4] @ save to __pv_offset |
463 | b __fixup_a_pv_table | 468 | b __fixup_a_pv_table |
@@ -471,10 +476,18 @@ ENDPROC(__fixup_pv_table) | |||
471 | 476 | ||
472 | .text | 477 | .text |
473 | __fixup_a_pv_table: | 478 | __fixup_a_pv_table: |
479 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | ||
480 | and r0, r6, #255 @ offset bits 23-16 | ||
481 | mov r6, r6, lsr #8 @ offset bits 31-24 | ||
482 | #else | ||
483 | mov r0, #0 @ just in case... | ||
484 | #endif | ||
474 | b 3f | 485 | b 3f |
475 | 2: ldr ip, [r7, r3] | 486 | 2: ldr ip, [r7, r3] |
476 | bic ip, ip, #0x000000ff | 487 | bic ip, ip, #0x000000ff |
477 | orr ip, ip, r6 | 488 | tst ip, #0x400 @ rotate shift tells us LS or MS byte |
489 | orrne ip, ip, r6 @ mask in offset bits 31-24 | ||
490 | orreq ip, ip, r0 @ mask in offset bits 23-16 | ||
478 | str ip, [r7, r3] | 491 | str ip, [r7, r3] |
479 | 3: cmp r4, r5 | 492 | 3: cmp r4, r5 |
480 | ldrcc r7, [r4], #4 @ use branch for delay slot | 493 | ldrcc r7, [r4], #4 @ use branch for delay slot |