GNU Linux-libre 4.19.207-gnu1
[releases.git] / arch / riscv / kernel / module.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU General Public License for more details.
11  *
12  *  Copyright (C) 2017 Zihao Yu
13  */
14
15 #include <linux/elf.h>
16 #include <linux/err.h>
17 #include <linux/errno.h>
18 #include <linux/moduleloader.h>
19 #include <linux/vmalloc.h>
20 #include <linux/sizes.h>
21 #include <asm/pgtable.h>
22 #include <asm/sections.h>
23
24 static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v)
25 {
26         if (v != (u32)v) {
27                 pr_err("%s: value %016llx out of range for 32-bit field\n",
28                        me->name, (long long)v);
29                 return -EINVAL;
30         }
31         *location = v;
32         return 0;
33 }
34
35 static int apply_r_riscv_64_rela(struct module *me, u32 *location, Elf_Addr v)
36 {
37         *(u64 *)location = v;
38         return 0;
39 }
40
41 static int apply_r_riscv_branch_rela(struct module *me, u32 *location,
42                                      Elf_Addr v)
43 {
44         ptrdiff_t offset = (void *)v - (void *)location;
45         u32 imm12 = (offset & 0x1000) << (31 - 12);
46         u32 imm11 = (offset & 0x800) >> (11 - 7);
47         u32 imm10_5 = (offset & 0x7e0) << (30 - 10);
48         u32 imm4_1 = (offset & 0x1e) << (11 - 4);
49
50         *location = (*location & 0x1fff07f) | imm12 | imm11 | imm10_5 | imm4_1;
51         return 0;
52 }
53
54 static int apply_r_riscv_jal_rela(struct module *me, u32 *location,
55                                   Elf_Addr v)
56 {
57         ptrdiff_t offset = (void *)v - (void *)location;
58         u32 imm20 = (offset & 0x100000) << (31 - 20);
59         u32 imm19_12 = (offset & 0xff000);
60         u32 imm11 = (offset & 0x800) << (20 - 11);
61         u32 imm10_1 = (offset & 0x7fe) << (30 - 10);
62
63         *location = (*location & 0xfff) | imm20 | imm19_12 | imm11 | imm10_1;
64         return 0;
65 }
66
67 static int apply_r_riscv_rcv_branch_rela(struct module *me, u32 *location,
68                                          Elf_Addr v)
69 {
70         ptrdiff_t offset = (void *)v - (void *)location;
71         u16 imm8 = (offset & 0x100) << (12 - 8);
72         u16 imm7_6 = (offset & 0xc0) >> (6 - 5);
73         u16 imm5 = (offset & 0x20) >> (5 - 2);
74         u16 imm4_3 = (offset & 0x18) << (12 - 5);
75         u16 imm2_1 = (offset & 0x6) << (12 - 10);
76
77         *(u16 *)location = (*(u16 *)location & 0xe383) |
78                     imm8 | imm7_6 | imm5 | imm4_3 | imm2_1;
79         return 0;
80 }
81
82 static int apply_r_riscv_rvc_jump_rela(struct module *me, u32 *location,
83                                        Elf_Addr v)
84 {
85         ptrdiff_t offset = (void *)v - (void *)location;
86         u16 imm11 = (offset & 0x800) << (12 - 11);
87         u16 imm10 = (offset & 0x400) >> (10 - 8);
88         u16 imm9_8 = (offset & 0x300) << (12 - 11);
89         u16 imm7 = (offset & 0x80) >> (7 - 6);
90         u16 imm6 = (offset & 0x40) << (12 - 11);
91         u16 imm5 = (offset & 0x20) >> (5 - 2);
92         u16 imm4 = (offset & 0x10) << (12 - 5);
93         u16 imm3_1 = (offset & 0xe) << (12 - 10);
94
95         *(u16 *)location = (*(u16 *)location & 0xe003) |
96                     imm11 | imm10 | imm9_8 | imm7 | imm6 | imm5 | imm4 | imm3_1;
97         return 0;
98 }
99
100 static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location,
101                                          Elf_Addr v)
102 {
103         ptrdiff_t offset = (void *)v - (void *)location;
104         s32 hi20;
105
106         if (offset != (s32)offset) {
107                 pr_err(
108                   "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
109                   me->name, (long long)v, location);
110                 return -EINVAL;
111         }
112
113         hi20 = (offset + 0x800) & 0xfffff000;
114         *location = (*location & 0xfff) | hi20;
115         return 0;
116 }
117
118 static int apply_r_riscv_pcrel_lo12_i_rela(struct module *me, u32 *location,
119                                            Elf_Addr v)
120 {
121         /*
122          * v is the lo12 value to fill. It is calculated before calling this
123          * handler.
124          */
125         *location = (*location & 0xfffff) | ((v & 0xfff) << 20);
126         return 0;
127 }
128
129 static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, u32 *location,
130                                            Elf_Addr v)
131 {
132         /*
133          * v is the lo12 value to fill. It is calculated before calling this
134          * handler.
135          */
136         u32 imm11_5 = (v & 0xfe0) << (31 - 11);
137         u32 imm4_0 = (v & 0x1f) << (11 - 4);
138
139         *location = (*location & 0x1fff07f) | imm11_5 | imm4_0;
140         return 0;
141 }
142
143 static int apply_r_riscv_hi20_rela(struct module *me, u32 *location,
144                                    Elf_Addr v)
145 {
146         s32 hi20;
147
148         if (IS_ENABLED(CMODEL_MEDLOW)) {
149                 pr_err(
150                   "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
151                   me->name, (long long)v, location);
152                 return -EINVAL;
153         }
154
155         hi20 = ((s32)v + 0x800) & 0xfffff000;
156         *location = (*location & 0xfff) | hi20;
157         return 0;
158 }
159
160 static int apply_r_riscv_lo12_i_rela(struct module *me, u32 *location,
161                                      Elf_Addr v)
162 {
163         /* Skip medlow checking because of filtering by HI20 already */
164         s32 hi20 = ((s32)v + 0x800) & 0xfffff000;
165         s32 lo12 = ((s32)v - hi20);
166         *location = (*location & 0xfffff) | ((lo12 & 0xfff) << 20);
167         return 0;
168 }
169
170 static int apply_r_riscv_lo12_s_rela(struct module *me, u32 *location,
171                                      Elf_Addr v)
172 {
173         /* Skip medlow checking because of filtering by HI20 already */
174         s32 hi20 = ((s32)v + 0x800) & 0xfffff000;
175         s32 lo12 = ((s32)v - hi20);
176         u32 imm11_5 = (lo12 & 0xfe0) << (31 - 11);
177         u32 imm4_0 = (lo12 & 0x1f) << (11 - 4);
178         *location = (*location & 0x1fff07f) | imm11_5 | imm4_0;
179         return 0;
180 }
181
182 static int apply_r_riscv_got_hi20_rela(struct module *me, u32 *location,
183                                        Elf_Addr v)
184 {
185         ptrdiff_t offset = (void *)v - (void *)location;
186         s32 hi20;
187
188         /* Always emit the got entry */
189         if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) {
190                 offset = module_emit_got_entry(me, v);
191                 offset = (void *)offset - (void *)location;
192         } else {
193                 pr_err(
194                   "%s: can not generate the GOT entry for symbol = %016llx from PC = %p\n",
195                   me->name, (long long)v, location);
196                 return -EINVAL;
197         }
198
199         hi20 = (offset + 0x800) & 0xfffff000;
200         *location = (*location & 0xfff) | hi20;
201         return 0;
202 }
203
204 static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location,
205                                        Elf_Addr v)
206 {
207         ptrdiff_t offset = (void *)v - (void *)location;
208         s32 fill_v = offset;
209         u32 hi20, lo12;
210
211         if (offset != fill_v) {
212                 /* Only emit the plt entry if offset over 32-bit range */
213                 if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) {
214                         offset = module_emit_plt_entry(me, v);
215                         offset = (void *)offset - (void *)location;
216                 } else {
217                         pr_err(
218                           "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
219                           me->name, (long long)v, location);
220                         return -EINVAL;
221                 }
222         }
223
224         hi20 = (offset + 0x800) & 0xfffff000;
225         lo12 = (offset - hi20) & 0xfff;
226         *location = (*location & 0xfff) | hi20;
227         *(location + 1) = (*(location + 1) & 0xfffff) | (lo12 << 20);
228         return 0;
229 }
230
231 static int apply_r_riscv_call_rela(struct module *me, u32 *location,
232                                    Elf_Addr v)
233 {
234         ptrdiff_t offset = (void *)v - (void *)location;
235         s32 fill_v = offset;
236         u32 hi20, lo12;
237
238         if (offset != fill_v) {
239                 pr_err(
240                   "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
241                   me->name, (long long)v, location);
242                 return -EINVAL;
243         }
244
245         hi20 = (offset + 0x800) & 0xfffff000;
246         lo12 = (offset - hi20) & 0xfff;
247         *location = (*location & 0xfff) | hi20;
248         *(location + 1) = (*(location + 1) & 0xfffff) | (lo12 << 20);
249         return 0;
250 }
251
252 static int apply_r_riscv_relax_rela(struct module *me, u32 *location,
253                                     Elf_Addr v)
254 {
255         return 0;
256 }
257
258 static int apply_r_riscv_align_rela(struct module *me, u32 *location,
259                                     Elf_Addr v)
260 {
261         pr_err(
262           "%s: The unexpected relocation type 'R_RISCV_ALIGN' from PC = %p\n",
263           me->name, location);
264         return -EINVAL;
265 }
266
267 static int apply_r_riscv_add32_rela(struct module *me, u32 *location,
268                                     Elf_Addr v)
269 {
270         *(u32 *)location += (u32)v;
271         return 0;
272 }
273
274 static int apply_r_riscv_sub32_rela(struct module *me, u32 *location,
275                                     Elf_Addr v)
276 {
277         *(u32 *)location -= (u32)v;
278         return 0;
279 }
280
281 static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
282                                 Elf_Addr v) = {
283         [R_RISCV_32]                    = apply_r_riscv_32_rela,
284         [R_RISCV_64]                    = apply_r_riscv_64_rela,
285         [R_RISCV_BRANCH]                = apply_r_riscv_branch_rela,
286         [R_RISCV_JAL]                   = apply_r_riscv_jal_rela,
287         [R_RISCV_RVC_BRANCH]            = apply_r_riscv_rcv_branch_rela,
288         [R_RISCV_RVC_JUMP]              = apply_r_riscv_rvc_jump_rela,
289         [R_RISCV_PCREL_HI20]            = apply_r_riscv_pcrel_hi20_rela,
290         [R_RISCV_PCREL_LO12_I]          = apply_r_riscv_pcrel_lo12_i_rela,
291         [R_RISCV_PCREL_LO12_S]          = apply_r_riscv_pcrel_lo12_s_rela,
292         [R_RISCV_HI20]                  = apply_r_riscv_hi20_rela,
293         [R_RISCV_LO12_I]                = apply_r_riscv_lo12_i_rela,
294         [R_RISCV_LO12_S]                = apply_r_riscv_lo12_s_rela,
295         [R_RISCV_GOT_HI20]              = apply_r_riscv_got_hi20_rela,
296         [R_RISCV_CALL_PLT]              = apply_r_riscv_call_plt_rela,
297         [R_RISCV_CALL]                  = apply_r_riscv_call_rela,
298         [R_RISCV_RELAX]                 = apply_r_riscv_relax_rela,
299         [R_RISCV_ALIGN]                 = apply_r_riscv_align_rela,
300         [R_RISCV_ADD32]                 = apply_r_riscv_add32_rela,
301         [R_RISCV_SUB32]                 = apply_r_riscv_sub32_rela,
302 };
303
304 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
305                        unsigned int symindex, unsigned int relsec,
306                        struct module *me)
307 {
308         Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr;
309         int (*handler)(struct module *me, u32 *location, Elf_Addr v);
310         Elf_Sym *sym;
311         u32 *location;
312         unsigned int i, type;
313         Elf_Addr v;
314         int res;
315
316         pr_debug("Applying relocate section %u to %u\n", relsec,
317                sechdrs[relsec].sh_info);
318
319         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
320                 /* This is where to make the change */
321                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
322                         + rel[i].r_offset;
323                 /* This is the symbol it is referring to */
324                 sym = (Elf_Sym *)sechdrs[symindex].sh_addr
325                         + ELF_RISCV_R_SYM(rel[i].r_info);
326                 if (IS_ERR_VALUE(sym->st_value)) {
327                         /* Ignore unresolved weak symbol */
328                         if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
329                                 continue;
330                         pr_warning("%s: Unknown symbol %s\n",
331                                    me->name, strtab + sym->st_name);
332                         return -ENOENT;
333                 }
334
335                 type = ELF_RISCV_R_TYPE(rel[i].r_info);
336
337                 if (type < ARRAY_SIZE(reloc_handlers_rela))
338                         handler = reloc_handlers_rela[type];
339                 else
340                         handler = NULL;
341
342                 if (!handler) {
343                         pr_err("%s: Unknown relocation type %u\n",
344                                me->name, type);
345                         return -EINVAL;
346                 }
347
348                 v = sym->st_value + rel[i].r_addend;
349
350                 if (type == R_RISCV_PCREL_LO12_I || type == R_RISCV_PCREL_LO12_S) {
351                         unsigned int j;
352
353                         for (j = 0; j < sechdrs[relsec].sh_size / sizeof(*rel); j++) {
354                                 unsigned long hi20_loc =
355                                         sechdrs[sechdrs[relsec].sh_info].sh_addr
356                                         + rel[j].r_offset;
357                                 u32 hi20_type = ELF_RISCV_R_TYPE(rel[j].r_info);
358
359                                 /* Find the corresponding HI20 relocation entry */
360                                 if (hi20_loc == sym->st_value
361                                     && (hi20_type == R_RISCV_PCREL_HI20
362                                         || hi20_type == R_RISCV_GOT_HI20)) {
363                                         s32 hi20, lo12;
364                                         Elf_Sym *hi20_sym =
365                                                 (Elf_Sym *)sechdrs[symindex].sh_addr
366                                                 + ELF_RISCV_R_SYM(rel[j].r_info);
367                                         unsigned long hi20_sym_val =
368                                                 hi20_sym->st_value
369                                                 + rel[j].r_addend;
370
371                                         /* Calculate lo12 */
372                                         size_t offset = hi20_sym_val - hi20_loc;
373                                         if (IS_ENABLED(CONFIG_MODULE_SECTIONS)
374                                             && hi20_type == R_RISCV_GOT_HI20) {
375                                                 offset = module_emit_got_entry(
376                                                          me, hi20_sym_val);
377                                                 offset = offset - hi20_loc;
378                                         }
379                                         hi20 = (offset + 0x800) & 0xfffff000;
380                                         lo12 = offset - hi20;
381                                         v = lo12;
382
383                                         break;
384                                 }
385                         }
386                         if (j == sechdrs[relsec].sh_size / sizeof(*rel)) {
387                                 pr_err(
388                                   "%s: Can not find HI20 relocation information\n",
389                                   me->name);
390                                 return -EINVAL;
391                         }
392                 }
393
394                 res = handler(me, location, v);
395                 if (res)
396                         return res;
397         }
398
399         return 0;
400 }
401
402 #if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
403 #define VMALLOC_MODULE_START \
404          max(PFN_ALIGN((unsigned long)&_end - SZ_2G), VMALLOC_START)
405 void *module_alloc(unsigned long size)
406 {
407         return __vmalloc_node_range(size, 1, VMALLOC_MODULE_START,
408                                     VMALLOC_END, GFP_KERNEL,
409                                     PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
410                                     __builtin_return_address(0));
411 }
412 #endif