[PATCH 4/4] ARM: support for Thumb-2 instructions with CONFIG_ARM_PATCH_PHYS_VIRT

Nicolas Pitre nico at fluxnic.net
Tue Jan 4 03:20:08 EST 2011


Signed-off-by: Nicolas Pitre <nicolas.pitre at linaro.org>
---
 arch/arm/Kconfig              |    3 +--
 arch/arm/include/asm/memory.h |    5 +++--
 arch/arm/kernel/head.S        |   31 +++++++++++++++++++++++++++----
 3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 136ed9b..feb374a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -189,8 +189,7 @@ config VECTORS_BASE
 
 config ARM_PATCH_PHYS_VIRT
 	bool
-	depends on EXPERIMENTAL
-	depends on !XIP && !THUMB2_KERNEL
+	depends on !XIP && EXPERIMENTAL
 
 source "init/Kconfig"
 
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index f83be97..80a939d 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -157,14 +157,15 @@
 #error "this machine configuration uses complex __virt_to_phys/__phys_to_virt and cannot use CONFIG_ARM_PATCH_PHYS_VIRT"
 #endif
 
+/* the stub constant 0xff000000 is used to force the required insn encoding */
 #define __pv_stub(from,to,instr)			\
 	__asm__(					\
-	"1:	" instr "\t%0, %1, %2\n"		\
+	"1:	" instr "\t%0, %1, #0xff000000\n"	\
 	"	.pushsection .pv_table,\"a\"\n"		\
 	"	.long	1b\n"				\
 	"	.popsection"				\
 	: "=r" (to)					\
-	: "r" (from), "I" (1))
+	: "r" (from))
 
 static inline unsigned long __virt_to_phys(unsigned long x)
 {
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 621c792..397271d 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -447,11 +447,11 @@ __fixup_pv_table:
 	adr	r0, 1f
 	ldmia	r0, {r3-r5}
 	sub	r3, r0, r3	@ PHYS_OFFSET - PAGE_OFFSET
+	movs	r6, r3, lsl #8	@ must be 16MiB aligned
+	bne	__error
 	add	r4, r4, r3
 	add	r5, r5, r3
-	mov	r6, r3, lsr #24	@ constant for add/sub instructions
-	teq	r3, r6, lsl #24 @ must be 16MiB aligned
-	bne	__error
+	mov	r6, r3
 	b	__fixup_pv_table_loop
 ENDPROC(__fixup_phys_virt)
 
@@ -462,6 +462,8 @@ ENDPROC(__fixup_phys_virt)
 	.pushsection .text
 
 ENTRY(__fixup_pv_table_loop)
+#ifndef CONFIG_THUMB2_KERNEL
+	mov	r6, r6, lsr #24	@ constant for add/sub instructions
 	orr	r6, r6, #0x400	@ mask in rotate right 8 bits
 2:	cmp	r4, r5
 	ldrlo	r7, [r4], #4
@@ -471,6 +473,27 @@ ENTRY(__fixup_pv_table_loop)
 	strlo	ip, [r7, r3]
 	blo	2b
 	mov	pc, lr
+#else
+	teq	r6, #0
+	beq	2f
+	clz	r7, r6
+	lsr	r6, #24
+	lsl	r6, r7
+	bic	r6, r6, #0x3080
+	lsrs	r7, #1
+	orrcs	r6, r6, #0x80
+	orr	r6, r6, r7, lsl #12
+	orr	r6, r6, #0x4000
+2:	cmp	r4, r5
+	bxhs	lr
+	ldr	r7, [r4], #4
+	add	r7, r3
+	ldr	ip, [r7, #2]
+	and	ip, ip, #0x0f00
+	orr	ip, ip, r6
+	str	ip, [r7, #2]
+	b	2b
+#endif
 ENDPROC(__fixup_phys_virt_loop)
 
 /*
@@ -482,7 +505,7 @@ ENTRY(fixup_pv_table)
 	mov	r3, #0		@ offset (zero as we're in virtual space)
 	mov	r4, r0		@ loop start
 	mov	r5, r1		@ loop end
-	mov     r6, r2, lsr #24	@ constant for add/sub instructions		
+	mov     r6, r2		@ PHYS_OFFSET - PAGE_OFFSET
 	bl      __fixup_pv_table_loop
 	ldmfd	sp!, {r4 - r7, pc}
 ENDPROC(fixup_pv_table)
-- 
1.7.3.2.193.g78bbb




More information about the linux-arm-kernel mailing list