1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2005-2017 Andes Technology Corporation
4 #include <linux/module.h>
6 #include <linux/vmalloc.h>
7 #include <linux/moduleloader.h>
8 #include <asm/pgtable.h>
10 void *module_alloc(unsigned long size
)
12 return __vmalloc_node_range(size
, 1, MODULES_VADDR
, MODULES_END
,
13 GFP_KERNEL
, PAGE_KERNEL
, 0, NUMA_NO_NODE
,
14 __builtin_return_address(0));
17 void module_free(struct module
*module
, void *region
)
22 int module_frob_arch_sections(Elf_Ehdr
* hdr
,
24 char *secstrings
, struct module
*mod
)
29 void do_reloc16(unsigned int val
, unsigned int *loc
, unsigned int val_mask
,
30 unsigned int val_shift
, unsigned int loc_mask
,
31 unsigned int partial_in_place
, unsigned int swap
)
33 unsigned int tmp
= 0, tmp2
= 0;
35 __asm__
__volatile__("\tlhi.bi\t%0, [%2], 0\n"
38 "1:\n":"=r"(tmp
):"0"(tmp
), "r"(loc
), "r"(swap
)
41 tmp2
= tmp
& loc_mask
;
42 if (partial_in_place
) {
45 tmp2
| ((tmp
+ ((val
& val_mask
) >> val_shift
)) & val_mask
);
47 tmp
= tmp2
| ((val
& val_mask
) >> val_shift
);
50 __asm__
__volatile__("\tbeqz\t%3, 2f\n"
53 "\tshi.bi\t%0, [%2], 0\n":"=r"(tmp
):"0"(tmp
),
58 void do_reloc32(unsigned int val
, unsigned int *loc
, unsigned int val_mask
,
59 unsigned int val_shift
, unsigned int loc_mask
,
60 unsigned int partial_in_place
, unsigned int swap
)
62 unsigned int tmp
= 0, tmp2
= 0;
64 __asm__
__volatile__("\tlmw.bi\t%0, [%2], %0, 0\n"
67 "\trotri\t%0, %1, 16\n"
68 "1:\n":"=r"(tmp
):"0"(tmp
), "r"(loc
), "r"(swap
)
71 tmp2
= tmp
& loc_mask
;
72 if (partial_in_place
) {
75 tmp2
| ((tmp
+ ((val
& val_mask
) >> val_shift
)) & val_mask
);
77 tmp
= tmp2
| ((val
& val_mask
) >> val_shift
);
80 __asm__
__volatile__("\tbeqz\t%3, 2f\n"
82 "\trotri\t%0, %1, 16\n"
84 "\tsmw.bi\t%0, [%2], %0, 0\n":"=r"(tmp
):"0"(tmp
),
89 static inline int exceed_limit(int offset
, unsigned int val_mask
,
90 struct module
*module
, Elf32_Rela
* rel
,
91 unsigned int relindex
, unsigned int reloc_order
)
93 int abs_off
= offset
< 0 ? ~offset
: offset
;
95 if (abs_off
& (~val_mask
)) {
96 pr_err("\n%s: relocation type %d out of range.\n"
97 "please rebuild the kernel module with gcc option \"-Wa,-mno-small-text\".\n",
98 module
->name
, ELF32_R_TYPE(rel
->r_info
));
99 pr_err("section %d reloc %d offset 0x%x relative 0x%x.\n",
100 relindex
, reloc_order
, rel
->r_offset
, offset
);
113 apply_relocate_add(Elf32_Shdr
* sechdrs
, const char *strtab
,
114 unsigned int symindex
, unsigned int relindex
,
115 struct module
*module
)
117 Elf32_Shdr
*symsec
= sechdrs
+ symindex
;
118 Elf32_Shdr
*relsec
= sechdrs
+ relindex
;
119 Elf32_Shdr
*dstsec
= sechdrs
+ relsec
->sh_info
;
120 Elf32_Rela
*rel
= (void *)relsec
->sh_addr
;
123 for (i
= 0; i
< relsec
->sh_size
/ sizeof(Elf32_Rela
); i
++, rel
++) {
129 offset
= ELF32_R_SYM(rel
->r_info
);
131 || offset
> (symsec
->sh_size
/ sizeof(Elf32_Sym
))) {
132 pr_err("%s: bad relocation\n", module
->name
);
133 pr_err("section %d reloc %d\n", relindex
, i
);
137 sym
= ((Elf32_Sym
*) symsec
->sh_addr
) + offset
;
139 if (rel
->r_offset
< 0
140 || rel
->r_offset
> dstsec
->sh_size
- sizeof(u16
)) {
141 pr_err("%s: out of bounds relocation\n", module
->name
);
142 pr_err("section %d reloc %d offset 0x%0x size %d\n",
143 relindex
, i
, rel
->r_offset
, dstsec
->sh_size
);
147 loc
= (Elf32_Addr
*) (dstsec
->sh_addr
+ rel
->r_offset
);
148 v
= sym
->st_value
+ rel
->r_addend
;
150 switch (ELF32_R_TYPE(rel
->r_info
)) {
154 case R_NDS32_LONGCALL1
:
155 case R_NDS32_LONGCALL2
:
156 case R_NDS32_LONGCALL3
:
157 case R_NDS32_LONGCALL4
:
158 case R_NDS32_LONGJUMP1
:
159 case R_NDS32_LONGJUMP2
:
160 case R_NDS32_LONGJUMP3
:
161 case R_NDS32_9_FIXED_RELA
:
162 case R_NDS32_15_FIXED_RELA
:
163 case R_NDS32_17_FIXED_RELA
:
164 case R_NDS32_25_FIXED_RELA
:
165 case R_NDS32_LOADSTORE
:
166 case R_NDS32_DWARF2_OP1_RELA
:
167 case R_NDS32_DWARF2_OP2_RELA
:
168 case R_NDS32_DWARF2_LEB_RELA
:
169 case R_NDS32_RELA_NOP_MIX
... R_NDS32_RELA_NOP_MAX
:
172 case R_NDS32_32_RELA
:
173 do_reloc32(v
, loc
, 0xffffffff, 0, 0, 0, 0);
176 case R_NDS32_HI20_RELA
:
177 do_reloc32(v
, loc
, 0xfffff000, 12, 0xfff00000, 0,
181 case R_NDS32_LO12S3_RELA
:
182 do_reloc32(v
, loc
, 0x00000fff, 3, 0xfffff000, 0,
186 case R_NDS32_LO12S2_RELA
:
187 do_reloc32(v
, loc
, 0x00000fff, 2, 0xfffff000, 0,
191 case R_NDS32_LO12S1_RELA
:
192 do_reloc32(v
, loc
, 0x00000fff, 1, 0xfffff000, 0,
196 case R_NDS32_LO12S0_RELA
:
197 case R_NDS32_LO12S0_ORI_RELA
:
198 do_reloc32(v
, loc
, 0x00000fff, 0, 0xfffff000, 0,
202 case R_NDS32_9_PCREL_RELA
:
204 ((v
- (Elf32_Addr
) loc
), 0x000000ff, module
, rel
,
207 do_reloc16(v
- (Elf32_Addr
) loc
, loc
, 0x000001ff, 1,
208 0xffffff00, 0, NEED_SWAP
);
211 case R_NDS32_15_PCREL_RELA
:
213 ((v
- (Elf32_Addr
) loc
), 0x00003fff, module
, rel
,
216 do_reloc32(v
- (Elf32_Addr
) loc
, loc
, 0x00007fff, 1,
217 0xffffc000, 0, NEED_SWAP
);
220 case R_NDS32_17_PCREL_RELA
:
222 ((v
- (Elf32_Addr
) loc
), 0x0000ffff, module
, rel
,
225 do_reloc32(v
- (Elf32_Addr
) loc
, loc
, 0x0001ffff, 1,
226 0xffff0000, 0, NEED_SWAP
);
229 case R_NDS32_25_PCREL_RELA
:
231 ((v
- (Elf32_Addr
) loc
), 0x00ffffff, module
, rel
,
234 do_reloc32(v
- (Elf32_Addr
) loc
, loc
, 0x01ffffff, 1,
235 0xff000000, 0, NEED_SWAP
);
237 case R_NDS32_WORD_9_PCREL_RELA
:
239 ((v
- (Elf32_Addr
) loc
), 0x000000ff, module
, rel
,
242 do_reloc32(v
- (Elf32_Addr
) loc
, loc
, 0x000001ff, 1,
243 0xffffff00, 0, NEED_SWAP
);
246 case R_NDS32_SDA15S3_RELA
:
247 case R_NDS32_SDA15S2_RELA
:
248 case R_NDS32_SDA15S1_RELA
:
249 case R_NDS32_SDA15S0_RELA
:
250 pr_err("%s: unsupported relocation type %d.\n",
251 module
->name
, ELF32_R_TYPE(rel
->r_info
));
253 ("Small data section access doesn't work in the kernel space; "
254 "please rebuild the kernel module with gcc option -mcmodel=large.\n");
255 pr_err("section %d reloc %d offset 0x%x size %d\n",
256 relindex
, i
, rel
->r_offset
, dstsec
->sh_size
);
260 pr_err("%s: unsupported relocation type %d.\n",
261 module
->name
, ELF32_R_TYPE(rel
->r_info
));
262 pr_err("section %d reloc %d offset 0x%x size %d\n",
263 relindex
, i
, rel
->r_offset
, dstsec
->sh_size
);
270 module_finalize(const Elf32_Ehdr
* hdr
, const Elf_Shdr
* sechdrs
,
271 struct module
*module
)
276 void module_arch_cleanup(struct module
*mod
)