18 #include <linux/elf.h>
21 #include <linux/string.h>
22 #include <linux/kernel.h>
23 #include <asm/pgtable.h>
30 #define DEBUGP(fmt...)
51 for (; i < npages; ++
i) {
98 static int validate_hw2_last(
long value,
struct module *me)
100 if (((value << 16) >> 16) != value) {
101 pr_warning(
"module %s: Out of range HW2_LAST value %#lx\n",
111 static int validate_jumpoff(
long value)
114 int shift = __builtin_clzl(get_JumpOff_X1(create_JumpOff_X1(-1)));
117 long f = get_JumpOff_X1(create_JumpOff_X1(value));
118 f = (f << shift) >> shift;
126 unsigned int symindex,
131 Elf_Rela *rel = (
void *)sechdrs[relsec].sh_addr;
136 DEBUGP(
"Applying relocate section %u to %u\n", relsec,
137 sechdrs[relsec].sh_info);
138 for (i = 0; i < sechdrs[relsec].sh_size /
sizeof(*rel); i++) {
140 location = (
void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
146 sym = (
Elf_Sym *)sechdrs[symindex].sh_addr
148 value = sym->st_value + rel[
i].r_addend;
152 #ifdef __LITTLE_ENDIAN
153 # define MUNGE(func) \
154 (*location = ((*location & ~func(-1)) | func(value)))
160 # define MUNGE(func) \
161 (*location = swab64((swab64(*location) & ~func(-1)) | func(value)))
169 value = (value + 0x8000) >> 16;
172 MUNGE(create_Imm16_X0);
175 value = (value + 0x8000) >> 16;
178 MUNGE(create_Imm16_X1);
181 value -= (
unsigned long) location;
182 value = (
long) value >> 3;
183 MUNGE(create_JOffLong_X1);
189 case R_TILEGX_IMM16_X0_HW2_LAST:
190 if (!validate_hw2_last(value, me))
194 case R_TILEGX_IMM16_X0_HW1:
197 case R_TILEGX_IMM16_X0_HW0:
198 MUNGE(create_Imm16_X0);
200 case R_TILEGX_IMM16_X1_HW2_LAST:
201 if (!validate_hw2_last(value, me))
205 case R_TILEGX_IMM16_X1_HW1:
208 case R_TILEGX_IMM16_X1_HW0:
209 MUNGE(create_Imm16_X1);
211 case R_TILEGX_JUMPOFF_X1:
212 value -= (
unsigned long) location;
213 value = (
long) value >> 3;
214 if (!validate_jumpoff(value)) {
216 " %#llx at %#llx (%p)\n", me->
name,
217 sym->st_value + rel[i].r_addend,
218 rel[i].r_offset, location);
221 MUNGE(create_JumpOff_X1);
228 pr_err(
"module %s: Unknown relocation: %d\n",