linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Junxiao Bi <junxiao.bi@windriver.com>
To: <linux-arm-kernel@lists.infradead.org>
Cc: nicolas.pitre@linaro.org, dwmw2@infradead.org,
	dave.martin@linaro.org, linux@arm.linux.org.uk,
	linux-mtd@lists.infradead.org
Subject: [PATCH 6/6] ARM: support kernel modules in BE8 mode
Date: Thu, 8 Dec 2011 18:07:52 +0800	[thread overview]
Message-ID: <1323338872-24716-7-git-send-email-junxiao.bi@windriver.com> (raw)
In-Reply-To: <1323338872-24716-1-git-send-email-junxiao.bi@windriver.com>

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

      parent reply	other threads:[~2011-12-08 10:07 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` Junxiao Bi [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1323338872-24716-7-git-send-email-junxiao.bi@windriver.com \
    --to=junxiao.bi@windriver.com \
    --cc=dave.martin@linaro.org \
    --cc=dwmw2@infradead.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linux@arm.linux.org.uk \
    --cc=nicolas.pitre@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).