diff options
Diffstat (limited to 'arch/arm/kernel/module.c')
| -rw-r--r-- | arch/arm/kernel/module.c | 59 | 
1 files changed, 35 insertions, 24 deletions
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 084dc889698..45e47815727 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  /* @@ -40,7 +41,7 @@  void *module_alloc(unsigned long size)  {  	return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, -				GFP_KERNEL, PAGE_KERNEL_EXEC, -1, +				GFP_KERNEL, PAGE_KERNEL_EXEC, NUMA_NO_NODE,  				__builtin_return_address(0));  }  #endif @@ -60,6 +61,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,  		Elf32_Sym *sym;  		const char *symname;  		s32 offset; +		u32 tmp;  #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; +			offset = __mem_to_opcode_arm(*(u32 *)loc); +			offset = (offset & 0x00ffffff) << 2;  			if (offset & 0x02000000)  				offset -= 0x04000000; @@ -111,9 +114,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,  			}  			offset >>= 2; +			offset &= 0x00ffffff; -			*(u32 *)loc &= 0xff000000; -			*(u32 *)loc |= offset & 0x00ffffff; +			*(u32 *)loc &= __opcode_to_mem_arm(0xff000000); +			*(u32 *)loc |= __opcode_to_mem_arm(offset);  			break;  	       case R_ARM_V4BX: @@ -121,8 +125,8 @@ 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; +		       *(u32 *)loc &= __opcode_to_mem_arm(0xf000000f); +		       *(u32 *)loc |= __opcode_to_mem_arm(0x01a0f000);  		       break;  		case R_ARM_PREL31: @@ -132,7 +136,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 = tmp = __mem_to_opcode_arm(*(u32 *)loc);  			offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);  			offset = (offset ^ 0x8000) - 0x8000; @@ -140,16 +144,18 @@ 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); +			tmp &= 0xfff0f000; +			tmp |= ((offset & 0xf000) << 4) | +				(offset & 0x0fff); + +			*(u32 *)loc = __opcode_to_mem_arm(tmp);  			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 +204,20 @@ 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) | +			upper = (u16)((upper & 0xf800) | (sign << 10) |  					    ((offset >> 12) & 0x03ff)); -			*(u16 *)(loc + 2) = (u16)((lower & 0xd000) | -						  (j1 << 13) | (j2 << 11) | -						  ((offset >> 1) & 0x07ff)); +			lower = (u16)((lower & 0xd000) | +				      (j1 << 13) | (j2 << 11) | +				      ((offset >> 1) & 0x07ff)); + +			*(u16 *)loc = __opcode_to_mem_thumb16(upper); +			*(u16 *)(loc + 2) = __opcode_to_mem_thumb16(lower);  			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,14 @@ 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)); +			upper = (u16)((upper & 0xfbf0) | +				      ((offset & 0xf000) >> 12) | +				      ((offset & 0x0800) >> 1)); +			lower = (u16)((lower & 0x8f00) | +				      ((offset & 0x0700) << 4) | +				      (offset & 0x00ff)); +			*(u16 *)loc = __opcode_to_mem_thumb16(upper); +			*(u16 *)(loc + 2) = __opcode_to_mem_thumb16(lower);  			break;  #endif  | 
