linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [V2][PATCH 0/6]ARM: fix BE8 mode support
@ 2011-12-08 10:07 Junxiao Bi
  2011-12-08 10:07 ` [PATCH 1/6] ARM: fix be8 support for phys/virt address conversion Junxiao Bi
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Junxiao Bi @ 2011-12-08 10:07 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: nicolas.pitre, dwmw2, dave.martin, linux, linux-mtd


This is V2 for this series. See V1 at
http://comments.gmane.org/gmane.linux.ports.arm.kernel/140189

Changes since V1:
1. Drop the patch "ARM: gic: fix big endian support" since gic
implementation has been changed and it works well in BE mode.

2. remove "read/write_instr*" from the patch 
"ARM: support kernel modules in BE8 mode", and use new helper 
__opcode_to_mem_* and __mem_to_opcode_* to implement it. These 
new helpers come from Dave Martin's patch 
"ARM: Add generic instruction opcode manipulation helpers"

3. split the big endian fix for MTD from the original patch
"ARM: add big endian support for peripheral access" 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/6] ARM: fix be8 support for phys/virt address conversion
  2011-12-08 10:07 [V2][PATCH 0/6]ARM: fix BE8 mode support Junxiao Bi
@ 2011-12-08 10:07 ` Junxiao Bi
  2011-12-08 10:07 ` [PATCH 2/6] ARM: Atomic64: fix 64bit ops in BE mode Junxiao Bi
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Junxiao Bi @ 2011-12-08 10:07 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: nicolas.pitre, dwmw2, dave.martin, linux, linux-mtd

phys_to_virt() and virt_to_phys() is implemented by one assembler instruction,
add/sub an offset between the physical and virtual address. For some arm machines
with CONFIG_ARM_PATCH_PHYS_VIRT defined, this offset is unknown at compile time,
it is calculated dynamically at run time and then patched to the add/sub instruction.
To support BE8 mode, firstly we need to convert the instruntion to big-endian after
loading it from the memory, and then modify its offset field, at last convert it to
little-endian and write it back to the memory.

Reviewed-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Junxiao Bi <junxiao.bi@windriver.com>
---
 arch/arm/kernel/head.S |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 54fa641..a52aec7 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -565,8 +565,14 @@ __fixup_a_pv_table:
 	b	2f
 1:	add     r7, r3
 	ldrh	ip, [r7, #2]
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	rev16	ip, ip
+#endif
 	and	ip, 0x8f00
 	orr	ip, r6	@ mask in offset bits 31-24
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	rev16	ip, ip
+#endif
 	strh	ip, [r7, #2]
 2:	cmp	r4, r5
 	ldrcc	r7, [r4], #4	@ use branch for delay slot
@@ -575,8 +581,14 @@ __fixup_a_pv_table:
 #else
 	b	2f
 1:	ldr	ip, [r7, r3]
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	rev	ip, ip
+#endif
 	bic	ip, ip, #0x000000ff
 	orr	ip, ip, r6	@ mask in offset bits 31-24
+#ifdef CONFIG_CPU_ENDIAN_BE8
+	rev	ip, ip
+#endif
 	str	ip, [r7, r3]
 2:	cmp	r4, r5
 	ldrcc	r7, [r4], #4	@ use branch for delay slot
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/6] ARM: Atomic64: fix 64bit ops in BE mode
  2011-12-08 10:07 [V2][PATCH 0/6]ARM: fix BE8 mode support Junxiao Bi
  2011-12-08 10:07 ` [PATCH 1/6] ARM: fix be8 support for phys/virt address conversion Junxiao Bi
@ 2011-12-08 10:07 ` Junxiao Bi
  2011-12-08 10:07 ` [PATCH 3/6] ARM: early_printk: pl01x: fix big endian support Junxiao Bi
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Junxiao Bi @ 2011-12-08 10:07 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: nicolas.pitre, dwmw2, dave.martin, linux, linux-mtd

The add/sub ops to 64 bits double word are made by adds/subs to the least
significant 32 bits first and then adc/sbc to the most significant 32 bits.
Using %0 and %H0 can only work in LE mode. If we change them to %Q0 and %R0,
it will work in both endian modes since %Q0 always represents the least
significant 32 bits and %R0 represents the most.

Acked-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Junxiao Bi <junxiao.bi@windriver.com>
---
 arch/arm/include/asm/atomic.h |   26 +++++++++++++-------------
 1 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
index 86976d0..00fcc4f 100644
--- a/arch/arm/include/asm/atomic.h
+++ b/arch/arm/include/asm/atomic.h
@@ -275,8 +275,8 @@ static inline void atomic64_add(u64 i, atomic64_t *v)
 
 	__asm__ __volatile__("@ atomic64_add\n"
 "1:	ldrexd	%0, %H0, [%3]\n"
-"	adds	%0, %0, %4\n"
-"	adc	%H0, %H0, %H4\n"
+"	adds	%Q0, %Q0, %Q4\n"
+"	adc	%R0, %R0, %R4\n"
 "	strexd	%1, %0, %H0, [%3]\n"
 "	teq	%1, #0\n"
 "	bne	1b"
@@ -294,8 +294,8 @@ static inline u64 atomic64_add_return(u64 i, atomic64_t *v)
 
 	__asm__ __volatile__("@ atomic64_add_return\n"
 "1:	ldrexd	%0, %H0, [%3]\n"
-"	adds	%0, %0, %4\n"
-"	adc	%H0, %H0, %H4\n"
+"	adds	%Q0, %Q0, %Q4\n"
+"	adc	%R0, %R0, %R4\n"
 "	strexd	%1, %0, %H0, [%3]\n"
 "	teq	%1, #0\n"
 "	bne	1b"
@@ -315,8 +315,8 @@ static inline void atomic64_sub(u64 i, atomic64_t *v)
 
 	__asm__ __volatile__("@ atomic64_sub\n"
 "1:	ldrexd	%0, %H0, [%3]\n"
-"	subs	%0, %0, %4\n"
-"	sbc	%H0, %H0, %H4\n"
+"	subs	%Q0, %Q0, %Q4\n"
+"	sbc	%R0, %R0, %R4\n"
 "	strexd	%1, %0, %H0, [%3]\n"
 "	teq	%1, #0\n"
 "	bne	1b"
@@ -334,8 +334,8 @@ static inline u64 atomic64_sub_return(u64 i, atomic64_t *v)
 
 	__asm__ __volatile__("@ atomic64_sub_return\n"
 "1:	ldrexd	%0, %H0, [%3]\n"
-"	subs	%0, %0, %4\n"
-"	sbc	%H0, %H0, %H4\n"
+"	subs	%Q0, %Q0, %Q4\n"
+"	sbc	%R0, %R0, %R4\n"
 "	strexd	%1, %0, %H0, [%3]\n"
 "	teq	%1, #0\n"
 "	bne	1b"
@@ -402,9 +402,9 @@ static inline u64 atomic64_dec_if_positive(atomic64_t *v)
 
 	__asm__ __volatile__("@ atomic64_dec_if_positive\n"
 "1:	ldrexd	%0, %H0, [%3]\n"
-"	subs	%0, %0, #1\n"
-"	sbc	%H0, %H0, #0\n"
-"	teq	%H0, #0\n"
+"	subs	%Q0, %Q0, #1\n"
+"	sbc	%R0, %R0, #0\n"
+"	teq	%R0, #0\n"
 "	bmi	2f\n"
 "	strexd	%1, %0, %H0, [%3]\n"
 "	teq	%1, #0\n"
@@ -433,8 +433,8 @@ static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
 "	teqeq	%H0, %H5\n"
 "	moveq	%1, #0\n"
 "	beq	2f\n"
-"	adds	%0, %0, %6\n"
-"	adc	%H0, %H0, %H6\n"
+"	adds	%Q0, %Q0, %Q6\n"
+"	adc	%R0, %R0, %R6\n"
 "	strexd	%2, %0, %H0, [%4]\n"
 "	teq	%2, #0\n"
 "	bne	1b\n"
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/6] ARM: early_printk: pl01x: fix big endian support
  2011-12-08 10:07 [V2][PATCH 0/6]ARM: fix BE8 mode support Junxiao Bi
  2011-12-08 10:07 ` [PATCH 1/6] ARM: fix be8 support for phys/virt address conversion Junxiao Bi
  2011-12-08 10:07 ` [PATCH 2/6] ARM: Atomic64: fix 64bit ops in BE mode Junxiao Bi
@ 2011-12-08 10:07 ` Junxiao Bi
  2011-12-08 10:07 ` [PATCH 4/6] ARM: SMP: " Junxiao Bi
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Junxiao Bi @ 2011-12-08 10:07 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: nicolas.pitre, dwmw2, dave.martin, linux, linux-mtd

The waituart and busyuart need to get one bit flag from UART flag
register. For this, we don't need do endian conversion for the entire
flag register, providing that flag definition in big-endian mode is
enough.

Signed-off-by: Junxiao Bi <junxiao.bi@windriver.com>
---
 arch/arm/include/asm/assembler.h            |    6 ++++++
 arch/arm/include/asm/hardware/debug-pl01x.S |   12 ++++++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index b6e65de..8faed15 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -313,4 +313,10 @@
 	.size \name , . - \name
 	.endm
 
+#define asm_constant_swab32(x) \
+	((((x) & 0xff000000) >> 24) | \
+	(((x) & 0x00ff0000) >> 8) | \
+	(((x) & 0x0000ff00) << 8) | \
+	(((x) & 0x000000ff) << 24))
+
 #endif /* __ASM_ASSEMBLER_H__ */
diff --git a/arch/arm/include/asm/hardware/debug-pl01x.S b/arch/arm/include/asm/hardware/debug-pl01x.S
index f9fd083..25fa0ec 100644
--- a/arch/arm/include/asm/hardware/debug-pl01x.S
+++ b/arch/arm/include/asm/hardware/debug-pl01x.S
@@ -11,19 +11,27 @@
  *
 */
 #include <linux/amba/serial.h>
+#include <asm/assembler.h>
 
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define _UART01x_FR_TXFF asm_constant_swab32(UART01x_FR_TXFF)
+#define _UART01x_FR_BUSY asm_constant_swab32(UART01x_FR_BUSY)
+#else
+#define _UART01x_FR_TXFF UART01x_FR_TXFF
+#define _UART01x_FR_BUSY UART01x_FR_BUSY
+#endif
 		.macro	senduart,rd,rx
 		strb	\rd, [\rx, #UART01x_DR]
 		.endm
 
 		.macro	waituart,rd,rx
 1001:		ldr	\rd, [\rx, #UART01x_FR]
-		tst	\rd, #UART01x_FR_TXFF
+		tst	\rd, #_UART01x_FR_TXFF
 		bne	1001b
 		.endm
 
 		.macro	busyuart,rd,rx
 1001:		ldr	\rd, [\rx, #UART01x_FR]
-		tst	\rd, #UART01x_FR_BUSY
+		tst	\rd, #_UART01x_FR_BUSY
 		bne	1001b
 		.endm
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/6] ARM: SMP: fix big endian support
  2011-12-08 10:07 [V2][PATCH 0/6]ARM: fix BE8 mode support Junxiao Bi
                   ` (2 preceding siblings ...)
  2011-12-08 10:07 ` [PATCH 3/6] ARM: early_printk: pl01x: fix big endian support Junxiao Bi
@ 2011-12-08 10:07 ` Junxiao Bi
  2011-12-08 10:07 ` [PATCH 5/6] MTD: map: " Junxiao Bi
  2011-12-08 10:07 ` [PATCH 6/6] ARM: support kernel modules in BE8 mode Junxiao Bi
  5 siblings, 0 replies; 7+ messages in thread
From: Junxiao Bi @ 2011-12-08 10:07 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: nicolas.pitre, dwmw2, dave.martin, linux, linux-mtd

From: Xue Ying <ying.xue@windriver.com>

Since data from arm peripheral are little-endian and __raw_read*/__raw_write*
don't do any endian conversion, we should use read*/write*_relaxed to replace
them as the _relaxed version only adds endian conversion based on __raw version
which isn't like read*/write* that adds IO barriers which will affect performance.

Signed-off-by: Xue Ying <ying.xue@windriver.com>
Signed-off-by: Junxiao Bi <junxiao.bi@windriver.com>
---
 arch/arm/kernel/smp_scu.c |   10 +++++-----
 arch/arm/kernel/smp_twd.c |   20 ++++++++++----------
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
index 8f5dd79..0324435 100644
--- a/arch/arm/kernel/smp_scu.c
+++ b/arch/arm/kernel/smp_scu.c
@@ -27,7 +27,7 @@
  */
 unsigned int __init scu_get_core_count(void __iomem *scu_base)
 {
-	unsigned int ncores = __raw_readl(scu_base + SCU_CONFIG);
+	unsigned int ncores = readl_relaxed(scu_base + SCU_CONFIG);
 	return (ncores & 0x03) + 1;
 }
 
@@ -41,19 +41,19 @@ void scu_enable(void __iomem *scu_base)
 #ifdef CONFIG_ARM_ERRATA_764369
 	/* Cortex-A9 only */
 	if ((read_cpuid(CPUID_ID) & 0xff0ffff0) == 0x410fc090) {
-		scu_ctrl = __raw_readl(scu_base + 0x30);
+		scu_ctrl = readl_relaxed(scu_base + 0x30);
 		if (!(scu_ctrl & 1))
-			__raw_writel(scu_ctrl | 0x1, scu_base + 0x30);
+			writel_relaxed(scu_ctrl | 0x1, scu_base + 0x30);
 	}
 #endif
 
-	scu_ctrl = __raw_readl(scu_base + SCU_CTRL);
+	scu_ctrl = readl_relaxed(scu_base + SCU_CTRL);
 	/* already enabled? */
 	if (scu_ctrl & 1)
 		return;
 
 	scu_ctrl |= 1;
-	__raw_writel(scu_ctrl, scu_base + SCU_CTRL);
+	writel_relaxed(scu_ctrl, scu_base + SCU_CTRL);
 
 	/*
 	 * Ensure that the data accessed by CPU0 before the SCU was
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index a8a6682..0864d92 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -39,7 +39,7 @@ static void twd_set_mode(enum clock_event_mode mode,
 		/* timer load already set up */
 		ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
 			| TWD_TIMER_CONTROL_PERIODIC;
-		__raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
+		writel_relaxed(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		/* period set, and timer enabled in 'next_event' hook */
@@ -51,18 +51,18 @@ static void twd_set_mode(enum clock_event_mode mode,
 		ctrl = 0;
 	}
 
-	__raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
+	writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL);
 }
 
 static int twd_set_next_event(unsigned long evt,
 			struct clock_event_device *unused)
 {
-	unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
+	unsigned long ctrl = readl_relaxed(twd_base + TWD_TIMER_CONTROL);
 
 	ctrl |= TWD_TIMER_CONTROL_ENABLE;
 
-	__raw_writel(evt, twd_base + TWD_TIMER_COUNTER);
-	__raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
+	writel_relaxed(evt, twd_base + TWD_TIMER_COUNTER);
+	writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL);
 
 	return 0;
 }
@@ -75,8 +75,8 @@ static int twd_set_next_event(unsigned long evt,
  */
 int twd_timer_ack(void)
 {
-	if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
-		__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
+	if (readl_relaxed(twd_base + TWD_TIMER_INTSTAT)) {
+		writel_relaxed(1, twd_base + TWD_TIMER_INTSTAT);
 		return 1;
 	}
 
@@ -111,15 +111,15 @@ static void __cpuinit twd_calibrate_rate(void)
 		waitjiffies += 5;
 
 				 /* enable, no interrupt or reload */
-		__raw_writel(0x1, twd_base + TWD_TIMER_CONTROL);
+		writel_relaxed(0x1, twd_base + TWD_TIMER_CONTROL);
 
 				 /* maximum value */
-		__raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
+		writel_relaxed(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
 
 		while (get_jiffies_64() < waitjiffies)
 			udelay(10);
 
-		count = __raw_readl(twd_base + TWD_TIMER_COUNTER);
+		count = readl_relaxed(twd_base + TWD_TIMER_COUNTER);
 
 		twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/6] MTD: map: fix big endian support
  2011-12-08 10:07 [V2][PATCH 0/6]ARM: fix BE8 mode support Junxiao Bi
                   ` (3 preceding siblings ...)
  2011-12-08 10:07 ` [PATCH 4/6] ARM: SMP: " Junxiao Bi
@ 2011-12-08 10:07 ` Junxiao Bi
  2011-12-08 10:07 ` [PATCH 6/6] ARM: support kernel modules in BE8 mode Junxiao Bi
  5 siblings, 0 replies; 7+ messages in thread
From: Junxiao Bi @ 2011-12-08 10:07 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: nicolas.pitre, dwmw2, dave.martin, linux, linux-mtd

Use read*/write*_relaxed to replace __raw_read*/__raw_write*
to make it work in both endians.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org
Signed-off-by: Junxiao Bi <junxiao.bi@windriver.com>
---
 include/linux/mtd/map.h |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index a9e6ba4..74b266d 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -393,14 +393,14 @@ static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
 	map_word r;
 
 	if (map_bankwidth_is_1(map))
-		r.x[0] = __raw_readb(map->virt + ofs);
+		r.x[0] = readb_relaxed(map->virt + ofs);
 	else if (map_bankwidth_is_2(map))
-		r.x[0] = __raw_readw(map->virt + ofs);
+		r.x[0] = readw_relaxed(map->virt + ofs);
 	else if (map_bankwidth_is_4(map))
-		r.x[0] = __raw_readl(map->virt + ofs);
+		r.x[0] = readl_relaxed(map->virt + ofs);
 #if BITS_PER_LONG >= 64
 	else if (map_bankwidth_is_8(map))
-		r.x[0] = __raw_readq(map->virt + ofs);
+		r.x[0] = readq_relaxed(map->virt + ofs);
 #endif
 	else if (map_bankwidth_is_large(map))
 		memcpy_fromio(r.x, map->virt+ofs, map->bankwidth);
@@ -413,14 +413,14 @@ static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
 static inline void inline_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
 {
 	if (map_bankwidth_is_1(map))
-		__raw_writeb(datum.x[0], map->virt + ofs);
+		writeb_relaxed(datum.x[0], map->virt + ofs);
 	else if (map_bankwidth_is_2(map))
-		__raw_writew(datum.x[0], map->virt + ofs);
+		writew_relaxed(datum.x[0], map->virt + ofs);
 	else if (map_bankwidth_is_4(map))
-		__raw_writel(datum.x[0], map->virt + ofs);
+		writel_relaxed(datum.x[0], map->virt + ofs);
 #if BITS_PER_LONG >= 64
 	else if (map_bankwidth_is_8(map))
-		__raw_writeq(datum.x[0], map->virt + ofs);
+		writeq_relaxed(datum.x[0], map->virt + ofs);
 #endif
 	else if (map_bankwidth_is_large(map))
 		memcpy_toio(map->virt+ofs, datum.x, map->bankwidth);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/6] ARM: support kernel modules in BE8 mode
  2011-12-08 10:07 [V2][PATCH 0/6]ARM: fix BE8 mode support Junxiao Bi
                   ` (4 preceding siblings ...)
  2011-12-08 10:07 ` [PATCH 5/6] MTD: map: " Junxiao Bi
@ 2011-12-08 10:07 ` Junxiao Bi
  5 siblings, 0 replies; 7+ messages in thread
From: Junxiao Bi @ 2011-12-08 10:07 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: nicolas.pitre, dwmw2, dave.martin, linux, linux-mtd

From: Stanley.Miao <stanley.miao@windriver.com>

In BE8 mode, data must be manipulated in big endian format while
text must be little endian. Therefore, when relocating the text
section of module in BE8 mode, we must convert the location offset
of the text to big endian from the native little endian. After
the relocation is complete, the location offset value is re-written
as little endian.

Signed-off-by: Stanley.Miao <stanley.miao@windriver.com>
Signed-off-by: Junxiao Bi <junxiao.bi@windriver.com>
---
 arch/arm/Makefile        |    1 +
 arch/arm/kernel/module.c |   63 +++++++++++++++++++++++++++------------------
 2 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index dfcf3b0..c858184 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -13,6 +13,7 @@
 LDFLAGS_vmlinux	:=-p --no-undefined -X
 ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
 LDFLAGS_vmlinux	+= --be8
+LDFLAGS_MODULE	+= --be8
 endif
 
 OBJCOPYFLAGS	:=-O binary -R .comment -S
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 1e9be5d..9b32c8f 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -24,6 +24,7 @@
 #include <asm/sections.h>
 #include <asm/smp_plat.h>
 #include <asm/unwind.h>
+#include <asm/opcodes.h>
 
 #ifdef CONFIG_XIP_KERNEL
 /*
@@ -60,6 +61,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 		Elf32_Sym *sym;
 		const char *symname;
 		s32 offset;
+		u32 instr32;
 #ifdef CONFIG_THUMB2_KERNEL
 		u32 upper, lower, sign, j1, j2;
 #endif
@@ -95,7 +97,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 		case R_ARM_PC24:
 		case R_ARM_CALL:
 		case R_ARM_JUMP24:
-			offset = (*(u32 *)loc & 0x00ffffff) << 2;
+			instr32 = __mem_to_opcode_arm(*(u32 *)loc);
+			offset = (instr32 & 0x00ffffff) << 2;
 			if (offset & 0x02000000)
 				offset -= 0x04000000;
 
@@ -112,8 +115,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 
 			offset >>= 2;
 
-			*(u32 *)loc &= 0xff000000;
-			*(u32 *)loc |= offset & 0x00ffffff;
+			*(u32 *)loc = __opcode_to_mem_arm((instr32 & 0xff000000)
+						| (offset & 0x00ffffff));
 			break;
 
 	       case R_ARM_V4BX:
@@ -121,9 +124,9 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 			* other bits to re-code instruction as
 			* MOV PC,Rm.
 			*/
-		       *(u32 *)loc &= 0xf000000f;
-		       *(u32 *)loc |= 0x01a0f000;
-		       break;
+			instr32 = __mem_to_opcode_arm(*(u32 *)loc) & 0xf000000f;
+			*(u32 *)loc = __opcode_to_mem_arm(instr32 | 0x01a0f000);
+			break;
 
 		case R_ARM_PREL31:
 			offset = *(u32 *)loc + sym->st_value - loc;
@@ -132,7 +135,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 
 		case R_ARM_MOVW_ABS_NC:
 		case R_ARM_MOVT_ABS:
-			offset = *(u32 *)loc;
+			offset = __mem_to_opcode_arm(*(u32 *)loc);
 			offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
 			offset = (offset ^ 0x8000) - 0x8000;
 
@@ -140,16 +143,17 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 			if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS)
 				offset >>= 16;
 
-			*(u32 *)loc &= 0xfff0f000;
-			*(u32 *)loc |= ((offset & 0xf000) << 4) |
-					(offset & 0x0fff);
+			instr32 = __mem_to_opcode_arm(*(u32 *)loc) & 0xfff0f000;
+			*(u32 *)loc = __opcode_to_mem_arm(instr32 |
+					((offset & 0xf000) << 4) |
+					(offset & 0x0fff));
 			break;
 
 #ifdef CONFIG_THUMB2_KERNEL
 		case R_ARM_THM_CALL:
 		case R_ARM_THM_JUMP24:
-			upper = *(u16 *)loc;
-			lower = *(u16 *)(loc + 2);
+			upper = __mem_to_opcode_thumb16(*(u16 *)loc);
+			lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2));
 
 			/*
 			 * 25 bit signed address range (Thumb-2 BL and B.W
@@ -198,17 +202,22 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 			sign = (offset >> 24) & 1;
 			j1 = sign ^ (~(offset >> 23) & 1);
 			j2 = sign ^ (~(offset >> 22) & 1);
-			*(u16 *)loc = (u16)((upper & 0xf800) | (sign << 10) |
-					    ((offset >> 12) & 0x03ff));
-			*(u16 *)(loc + 2) = (u16)((lower & 0xd000) |
-						  (j1 << 13) | (j2 << 11) |
-						  ((offset >> 1) & 0x07ff));
+			*(u16 *)loc = __opcode_to_mem_thumb16((u16)(
+						(upper & 0xf800) |
+						(sign << 10) |
+						((offset >> 12) & 0x03ff)
+						));
+			*(u16 *)(loc + 2) = __opcode_to_mem_thumb16((u16)(
+						(lower & 0xd000) |
+						(j1 << 13) | (j2 << 11) |
+						((offset >> 1) & 0x07ff)
+						));
 			break;
 
 		case R_ARM_THM_MOVW_ABS_NC:
 		case R_ARM_THM_MOVT_ABS:
-			upper = *(u16 *)loc;
-			lower = *(u16 *)(loc + 2);
+			upper = __mem_to_opcode_thumb16(*(u16 *)loc);
+			lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2));
 
 			/*
 			 * MOVT/MOVW instructions encoding in Thumb-2:
@@ -229,12 +238,16 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 			if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS)
 				offset >>= 16;
 
-			*(u16 *)loc = (u16)((upper & 0xfbf0) |
-					    ((offset & 0xf000) >> 12) |
-					    ((offset & 0x0800) >> 1));
-			*(u16 *)(loc + 2) = (u16)((lower & 0x8f00) |
-						  ((offset & 0x0700) << 4) |
-						  (offset & 0x00ff));
+			*(u16 *)loc = __opcode_to_mem_thumb16((u16)(
+					(upper & 0xfbf0) |
+					((offset & 0xf000) >> 12) |
+					((offset & 0x0800) >> 1)
+					));
+			*(u16 *)(loc + 2) = __opcode_to_mem_thumb16((u16)(
+					(lower & 0x8f00) |
+					((offset & 0x0700) << 4) |
+					(offset & 0x00ff)
+					));
 			break;
 #endif
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-12-08 10:07 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-08 10:07 [V2][PATCH 0/6]ARM: fix BE8 mode support Junxiao Bi
2011-12-08 10:07 ` [PATCH 1/6] ARM: fix be8 support for phys/virt address conversion Junxiao Bi
2011-12-08 10:07 ` [PATCH 2/6] ARM: Atomic64: fix 64bit ops in BE mode Junxiao Bi
2011-12-08 10:07 ` [PATCH 3/6] ARM: early_printk: pl01x: fix big endian support Junxiao Bi
2011-12-08 10:07 ` [PATCH 4/6] ARM: SMP: " Junxiao Bi
2011-12-08 10:07 ` [PATCH 5/6] MTD: map: " Junxiao Bi
2011-12-08 10:07 ` [PATCH 6/6] ARM: support kernel modules in BE8 mode Junxiao Bi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).