1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/module.h>
22#include <linux/elf.h>
23#include <linux/moduleloader.h>
24#include <linux/err.h>
25#include <linux/vmalloc.h>
26#include <linux/ftrace.h>
27#include <linux/bug.h>
28#include <linux/uaccess.h>
29#include <asm/module.h>
30#include <asm/firmware.h>
31#include <asm/code-patching.h>
32#include <linux/sort.h>
33#include <asm/setup.h>
34#include <asm/sections.h>
35
36
37
38
39
40
41
42
43
44#if defined(_CALL_ELF) && _CALL_ELF == 2
45
46
47typedef unsigned long func_desc_t;
48
49static func_desc_t func_desc(unsigned long addr)
50{
51 return addr;
52}
53static unsigned long func_addr(unsigned long addr)
54{
55 return addr;
56}
57static unsigned long stub_func_addr(func_desc_t func)
58{
59 return func;
60}
61
62
63#define STO_PPC64_LOCAL_BIT 5
64#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
65#define PPC64_LOCAL_ENTRY_OFFSET(other) \
66 (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2)
67
68static unsigned int local_entry_offset(const Elf64_Sym *sym)
69{
70
71
72
73 return PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
74}
75#else
76
77
78typedef struct ppc64_opd_entry func_desc_t;
79
80static func_desc_t func_desc(unsigned long addr)
81{
82 return *(struct ppc64_opd_entry *)addr;
83}
84static unsigned long func_addr(unsigned long addr)
85{
86 return func_desc(addr).funcaddr;
87}
88static unsigned long stub_func_addr(func_desc_t func)
89{
90 return func.funcaddr;
91}
92static unsigned int local_entry_offset(const Elf64_Sym *sym)
93{
94 return 0;
95}
96#endif
97
98#define STUB_MAGIC 0x73747562
99
100
101
102
103struct ppc64_stub_entry
104{
105
106
107
108 u32 jump[7];
109
110 u32 magic;
111
112 func_desc_t funcdata;
113};
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129static u32 ppc64_stub_insns[] = {
130 0x3d620000,
131 0x396b0000,
132
133 0xf8410000|R2_STACK_OFFSET,
134 0xe98b0020,
135#if !defined(_CALL_ELF) || _CALL_ELF != 2
136
137 0xe84b0028,
138#endif
139 0x7d8903a6,
140 0x4e800420
141};
142
143#ifdef CONFIG_DYNAMIC_FTRACE
144int module_trampoline_target(struct module *mod, unsigned long addr,
145 unsigned long *target)
146{
147 struct ppc64_stub_entry *stub;
148 func_desc_t funcdata;
149 u32 magic;
150
151 if (!within_module_core(addr, mod)) {
152 pr_err("%s: stub %lx not in module %s\n", __func__, addr, mod->name);
153 return -EFAULT;
154 }
155
156 stub = (struct ppc64_stub_entry *)addr;
157
158 if (probe_kernel_read(&magic, &stub->magic, sizeof(magic))) {
159 pr_err("%s: fault reading magic for stub %lx for %s\n", __func__, addr, mod->name);
160 return -EFAULT;
161 }
162
163 if (magic != STUB_MAGIC) {
164 pr_err("%s: bad magic for stub %lx for %s\n", __func__, addr, mod->name);
165 return -EFAULT;
166 }
167
168 if (probe_kernel_read(&funcdata, &stub->funcdata, sizeof(funcdata))) {
169 pr_err("%s: fault reading funcdata for stub %lx for %s\n", __func__, addr, mod->name);
170 return -EFAULT;
171 }
172
173 *target = stub_func_addr(funcdata);
174
175 return 0;
176}
177#endif
178
179
180
181static unsigned int count_relocs(const Elf64_Rela *rela, unsigned int num)
182{
183 unsigned int i, r_info, r_addend, _count_relocs;
184
185
186 _count_relocs = 0;
187 r_info = 0;
188 r_addend = 0;
189 for (i = 0; i < num; i++)
190
191 if (ELF64_R_TYPE(rela[i].r_info) == R_PPC_REL24 &&
192 (r_info != ELF64_R_SYM(rela[i].r_info) ||
193 r_addend != rela[i].r_addend)) {
194 _count_relocs++;
195 r_info = ELF64_R_SYM(rela[i].r_info);
196 r_addend = rela[i].r_addend;
197 }
198
199 return _count_relocs;
200}
201
202static int relacmp(const void *_x, const void *_y)
203{
204 const Elf64_Rela *x, *y;
205
206 y = (Elf64_Rela *)_x;
207 x = (Elf64_Rela *)_y;
208
209
210
211
212
213 if (x->r_info < y->r_info)
214 return -1;
215 else if (x->r_info > y->r_info)
216 return 1;
217 else if (x->r_addend < y->r_addend)
218 return -1;
219 else if (x->r_addend > y->r_addend)
220 return 1;
221 else
222 return 0;
223}
224
225static void relaswap(void *_x, void *_y, int size)
226{
227 uint64_t *x, *y, tmp;
228 int i;
229
230 y = (uint64_t *)_x;
231 x = (uint64_t *)_y;
232
233 for (i = 0; i < sizeof(Elf64_Rela) / sizeof(uint64_t); i++) {
234 tmp = x[i];
235 x[i] = y[i];
236 y[i] = tmp;
237 }
238}
239
240
241static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
242 const Elf64_Shdr *sechdrs)
243{
244
245 unsigned long relocs = 1;
246 unsigned i;
247
248
249 for (i = 1; i < hdr->e_shnum; i++) {
250 if (sechdrs[i].sh_type == SHT_RELA) {
251 pr_debug("Found relocations in section %u\n", i);
252 pr_debug("Ptr: %p. Number: %Lu\n",
253 (void *)sechdrs[i].sh_addr,
254 sechdrs[i].sh_size / sizeof(Elf64_Rela));
255
256
257
258
259
260
261 sort((void *)sechdrs[i].sh_addr,
262 sechdrs[i].sh_size / sizeof(Elf64_Rela),
263 sizeof(Elf64_Rela), relacmp, relaswap);
264
265 relocs += count_relocs((void *)sechdrs[i].sh_addr,
266 sechdrs[i].sh_size
267 / sizeof(Elf64_Rela));
268 }
269 }
270
271#ifdef CONFIG_DYNAMIC_FTRACE
272
273 relocs++;
274#endif
275
276 pr_debug("Looks like a total of %lu stubs, max\n", relocs);
277 return relocs * sizeof(struct ppc64_stub_entry);
278}
279
280
281static void dedotify_versions(struct modversion_info *vers,
282 unsigned long size)
283{
284 struct modversion_info *end;
285
286 for (end = (void *)vers + size; vers < end; vers++)
287 if (vers->name[0] == '.') {
288 memmove(vers->name, vers->name+1, strlen(vers->name));
289#ifdef ARCH_RELOCATES_KCRCTAB
290
291
292
293
294 if (!strcmp(vers->name, "TOC."))
295 vers->crc = -(unsigned long)reloc_start;
296#endif
297 }
298}
299
300
301
302
303
304static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
305{
306 unsigned int i;
307
308 for (i = 1; i < numsyms; i++) {
309 if (syms[i].st_shndx == SHN_UNDEF) {
310 char *name = strtab + syms[i].st_name;
311 if (name[0] == '.') {
312 if (strcmp(name+1, "TOC.") == 0)
313 syms[i].st_shndx = SHN_ABS;
314 syms[i].st_name++;
315 }
316 }
317 }
318}
319
320static Elf64_Sym *find_dot_toc(Elf64_Shdr *sechdrs,
321 const char *strtab,
322 unsigned int symindex)
323{
324 unsigned int i, numsyms;
325 Elf64_Sym *syms;
326
327 syms = (Elf64_Sym *)sechdrs[symindex].sh_addr;
328 numsyms = sechdrs[symindex].sh_size / sizeof(Elf64_Sym);
329
330 for (i = 1; i < numsyms; i++) {
331 if (syms[i].st_shndx == SHN_ABS
332 && strcmp(strtab + syms[i].st_name, "TOC.") == 0)
333 return &syms[i];
334 }
335 return NULL;
336}
337
338int module_frob_arch_sections(Elf64_Ehdr *hdr,
339 Elf64_Shdr *sechdrs,
340 char *secstrings,
341 struct module *me)
342{
343 unsigned int i;
344
345
346 for (i = 1; i < hdr->e_shnum; i++) {
347 char *p;
348 if (strcmp(secstrings + sechdrs[i].sh_name, ".stubs") == 0)
349 me->arch.stubs_section = i;
350 else if (strcmp(secstrings + sechdrs[i].sh_name, ".toc") == 0)
351 me->arch.toc_section = i;
352 else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0)
353 dedotify_versions((void *)hdr + sechdrs[i].sh_offset,
354 sechdrs[i].sh_size);
355
356
357 while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init")))
358 p[0] = '_';
359
360 if (sechdrs[i].sh_type == SHT_SYMTAB)
361 dedotify((void *)hdr + sechdrs[i].sh_offset,
362 sechdrs[i].sh_size / sizeof(Elf64_Sym),
363 (void *)hdr
364 + sechdrs[sechdrs[i].sh_link].sh_offset);
365 }
366
367 if (!me->arch.stubs_section) {
368 pr_err("%s: doesn't contain .stubs.\n", me->name);
369 return -ENOEXEC;
370 }
371
372
373
374
375
376 if (!me->arch.toc_section)
377 me->arch.toc_section = me->arch.stubs_section;
378
379
380 sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs);
381 return 0;
382}
383
384
385
386
387static inline unsigned long my_r2(const Elf64_Shdr *sechdrs, struct module *me)
388{
389 return sechdrs[me->arch.toc_section].sh_addr + 0x8000;
390}
391
392
393
394
395#define PPC_LO(v) ((v) & 0xffff)
396#define PPC_HI(v) (((v) >> 16) & 0xffff)
397#define PPC_HA(v) PPC_HI ((v) + 0x8000)
398
399
400static inline int create_stub(const Elf64_Shdr *sechdrs,
401 struct ppc64_stub_entry *entry,
402 unsigned long addr,
403 struct module *me)
404{
405 long reladdr;
406
407 memcpy(entry->jump, ppc64_stub_insns, sizeof(ppc64_stub_insns));
408
409
410 reladdr = (unsigned long)entry - my_r2(sechdrs, me);
411 if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
412 pr_err("%s: Address %p of stub out of range of %p.\n",
413 me->name, (void *)reladdr, (void *)my_r2);
414 return 0;
415 }
416 pr_debug("Stub %p get data from reladdr %li\n", entry, reladdr);
417
418 entry->jump[0] |= PPC_HA(reladdr);
419 entry->jump[1] |= PPC_LO(reladdr);
420 entry->funcdata = func_desc(addr);
421 entry->magic = STUB_MAGIC;
422
423 return 1;
424}
425
426
427
428static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs,
429 unsigned long addr,
430 struct module *me)
431{
432 struct ppc64_stub_entry *stubs;
433 unsigned int i, num_stubs;
434
435 num_stubs = sechdrs[me->arch.stubs_section].sh_size / sizeof(*stubs);
436
437
438 stubs = (void *)sechdrs[me->arch.stubs_section].sh_addr;
439 for (i = 0; stub_func_addr(stubs[i].funcdata); i++) {
440 BUG_ON(i >= num_stubs);
441
442 if (stub_func_addr(stubs[i].funcdata) == func_addr(addr))
443 return (unsigned long)&stubs[i];
444 }
445
446 if (!create_stub(sechdrs, &stubs[i], addr, me))
447 return 0;
448
449 return (unsigned long)&stubs[i];
450}
451
452#ifdef CC_USING_MPROFILE_KERNEL
453static bool is_early_mcount_callsite(u32 *instruction)
454{
455
456
457
458 if (instruction[-1] == PPC_INST_STD_LR &&
459 instruction[-2] == PPC_INST_MFLR)
460 return true;
461
462 if (instruction[-1] == PPC_INST_MFLR)
463 return true;
464
465 return false;
466}
467
468
469
470
471
472
473static void squash_toc_save_inst(const char *name, unsigned long addr)
474{
475 struct ppc64_stub_entry *stub = (struct ppc64_stub_entry *)addr;
476
477
478 if (strcmp("_mcount", name) != 0)
479 return;
480
481 stub->jump[2] = PPC_INST_NOP;
482}
483#else
484static void squash_toc_save_inst(const char *name, unsigned long addr) { }
485
486
487static bool is_early_mcount_callsite(u32 *instruction)
488{
489 return false;
490}
491#endif
492
493
494
495static int restore_r2(u32 *instruction, struct module *me)
496{
497 if (*instruction != PPC_INST_NOP) {
498 if (is_early_mcount_callsite(instruction - 1))
499 return 1;
500 pr_err("%s: Expect noop after relocate, got %08x\n",
501 me->name, *instruction);
502 return 0;
503 }
504
505 *instruction = PPC_INST_LD_TOC;
506 return 1;
507}
508
509int apply_relocate_add(Elf64_Shdr *sechdrs,
510 const char *strtab,
511 unsigned int symindex,
512 unsigned int relsec,
513 struct module *me)
514{
515 unsigned int i;
516 Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
517 Elf64_Sym *sym;
518 unsigned long *location;
519 unsigned long value;
520
521 pr_debug("Applying ADD relocate section %u to %u\n", relsec,
522 sechdrs[relsec].sh_info);
523
524
525 if (!me->arch.toc_fixed) {
526 sym = find_dot_toc(sechdrs, strtab, symindex);
527
528
529 if (sym)
530 sym->st_value = my_r2(sechdrs, me);
531 me->arch.toc_fixed = true;
532 }
533
534 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
535
536 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
537 + rela[i].r_offset;
538
539 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
540 + ELF64_R_SYM(rela[i].r_info);
541
542 pr_debug("RELOC at %p: %li-type as %s (0x%lx) + %li\n",
543 location, (long)ELF64_R_TYPE(rela[i].r_info),
544 strtab + sym->st_name, (unsigned long)sym->st_value,
545 (long)rela[i].r_addend);
546
547
548 value = sym->st_value + rela[i].r_addend;
549
550 switch (ELF64_R_TYPE(rela[i].r_info)) {
551 case R_PPC64_ADDR32:
552
553 *(u32 *)location = value;
554 break;
555
556 case R_PPC64_ADDR64:
557
558 *(unsigned long *)location = value;
559 break;
560
561 case R_PPC64_TOC:
562 *(unsigned long *)location = my_r2(sechdrs, me);
563 break;
564
565 case R_PPC64_TOC16:
566
567 value -= my_r2(sechdrs, me);
568 if (value + 0x8000 > 0xffff) {
569 pr_err("%s: bad TOC16 relocation (0x%lx)\n",
570 me->name, value);
571 return -ENOEXEC;
572 }
573 *((uint16_t *) location)
574 = (*((uint16_t *) location) & ~0xffff)
575 | (value & 0xffff);
576 break;
577
578 case R_PPC64_TOC16_LO:
579
580 value -= my_r2(sechdrs, me);
581 *((uint16_t *) location)
582 = (*((uint16_t *) location) & ~0xffff)
583 | (value & 0xffff);
584 break;
585
586 case R_PPC64_TOC16_DS:
587
588 value -= my_r2(sechdrs, me);
589 if ((value & 3) != 0 || value + 0x8000 > 0xffff) {
590 pr_err("%s: bad TOC16_DS relocation (0x%lx)\n",
591 me->name, value);
592 return -ENOEXEC;
593 }
594 *((uint16_t *) location)
595 = (*((uint16_t *) location) & ~0xfffc)
596 | (value & 0xfffc);
597 break;
598
599 case R_PPC64_TOC16_LO_DS:
600
601 value -= my_r2(sechdrs, me);
602 if ((value & 3) != 0) {
603 pr_err("%s: bad TOC16_LO_DS relocation (0x%lx)\n",
604 me->name, value);
605 return -ENOEXEC;
606 }
607 *((uint16_t *) location)
608 = (*((uint16_t *) location) & ~0xfffc)
609 | (value & 0xfffc);
610 break;
611
612 case R_PPC64_TOC16_HA:
613
614 value -= my_r2(sechdrs, me);
615 value = ((value + 0x8000) >> 16);
616 *((uint16_t *) location)
617 = (*((uint16_t *) location) & ~0xffff)
618 | (value & 0xffff);
619 break;
620
621 case R_PPC_REL24:
622
623 if (sym->st_shndx == SHN_UNDEF) {
624
625 value = stub_for_addr(sechdrs, value, me);
626 if (!value)
627 return -ENOENT;
628 if (!restore_r2((u32 *)location + 1, me))
629 return -ENOEXEC;
630
631 squash_toc_save_inst(strtab + sym->st_name, value);
632 } else
633 value += local_entry_offset(sym);
634
635
636 value -= (unsigned long)location;
637 if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0){
638 pr_err("%s: REL24 %li out of range!\n",
639 me->name, (long int)value);
640 return -ENOEXEC;
641 }
642
643
644 *(uint32_t *)location
645 = (*(uint32_t *)location & ~0x03fffffc)
646 | (value & 0x03fffffc);
647 break;
648
649 case R_PPC64_REL64:
650
651 *location = value - (unsigned long)location;
652 break;
653
654 case R_PPC64_TOCSAVE:
655
656
657
658
659
660 break;
661
662 case R_PPC64_ENTRY:
663
664
665
666
667 value = my_r2(sechdrs, me) - (unsigned long)location;
668 if (value + 0x80008000 > 0xffffffff)
669 break;
670
671
672
673
674
675 if ((((uint32_t *)location)[0] & ~0xfffc)
676 != 0xe84c0000)
677 break;
678 if (((uint32_t *)location)[1] != 0x7c426214)
679 break;
680
681
682
683
684
685 ((uint32_t *)location)[0] = 0x3c4c0000 + PPC_HA(value);
686 ((uint32_t *)location)[1] = 0x38420000 + PPC_LO(value);
687 break;
688
689 case R_PPC64_REL16_HA:
690
691 value -= (unsigned long)location;
692 value = ((value + 0x8000) >> 16);
693 *((uint16_t *) location)
694 = (*((uint16_t *) location) & ~0xffff)
695 | (value & 0xffff);
696 break;
697
698 case R_PPC64_REL16_LO:
699
700 value -= (unsigned long)location;
701 *((uint16_t *) location)
702 = (*((uint16_t *) location) & ~0xffff)
703 | (value & 0xffff);
704 break;
705
706 default:
707 pr_err("%s: Unknown ADD relocation: %lu\n",
708 me->name,
709 (unsigned long)ELF64_R_TYPE(rela[i].r_info));
710 return -ENOEXEC;
711 }
712 }
713
714 return 0;
715}
716
717#ifdef CONFIG_DYNAMIC_FTRACE
718
719#ifdef CC_USING_MPROFILE_KERNEL
720
721#define PACATOC offsetof(struct paca_struct, kernel_toc)
722
723
724
725
726
727
728
729
730
731
732
733
734
735static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me)
736{
737 struct ppc64_stub_entry *entry;
738 unsigned int i, num_stubs;
739 static u32 stub_insns[] = {
740 0xe98d0000 | PACATOC,
741 0x3d8c0000,
742 0x398c0000,
743 0x7d8903a6,
744 0x4e800420,
745 };
746 long reladdr;
747
748 num_stubs = sechdrs[me->arch.stubs_section].sh_size / sizeof(*entry);
749
750
751 entry = (void *)sechdrs[me->arch.stubs_section].sh_addr;
752 for (i = 0; i < num_stubs && stub_func_addr(entry->funcdata); i++, entry++);
753
754 if (i >= num_stubs) {
755 pr_err("%s: Unable to find a free slot for ftrace stub.\n", me->name);
756 return 0;
757 }
758
759 memcpy(entry->jump, stub_insns, sizeof(stub_insns));
760
761
762 reladdr = (unsigned long)ftrace_caller - kernel_toc_addr();
763 if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
764 pr_err("%s: Address of ftrace_caller out of range of kernel_toc.\n", me->name);
765 return 0;
766 }
767
768 entry->jump[1] |= PPC_HA(reladdr);
769 entry->jump[2] |= PPC_LO(reladdr);
770
771
772 entry->funcdata = func_desc((unsigned long)ftrace_caller);
773 entry->magic = STUB_MAGIC;
774
775 return (unsigned long)entry;
776}
777#else
778static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me)
779{
780 return stub_for_addr(sechdrs, (unsigned long)ftrace_caller, me);
781}
782#endif
783
784int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
785{
786 mod->arch.toc = my_r2(sechdrs, mod);
787 mod->arch.tramp = create_ftrace_stub(sechdrs, mod);
788
789 if (!mod->arch.tramp)
790 return -ENOENT;
791
792 return 0;
793}
794#endif
795