Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / arch / powerpc / kernel / module_64.c
1 /*  Kernel module help for PPC64.
2     Copyright (C) 2001, 2003 Rusty Russell IBM Corporation.
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 #include <linux/module.h>
19 #include <linux/elf.h>
20 #include <linux/moduleloader.h>
21 #include <linux/err.h>
22 #include <linux/vmalloc.h>
23 #include <linux/bug.h>
24 #include <asm/module.h>
25 #include <asm/firmware.h>
26 #include <asm/code-patching.h>
27 #include <linux/sort.h>
28
29 #include "setup.h"
30
31 /* FIXME: We don't do .init separately.  To do this, we'd need to have
32    a separate r2 value in the init and core section, and stub between
33    them, too.
34
35    Using a magic allocator which places modules within 32MB solves
36    this, and makes other things simpler.  Anton?
37    --RR.  */
38 #if 0
39 #define DEBUGP printk
40 #else
41 #define DEBUGP(fmt , ...)
42 #endif
43
44 /* Like PPC32, we need little trampolines to do > 24-bit jumps (into
45    the kernel itself).  But on PPC64, these need to be used for every
46    jump, actually, to reset r2 (TOC+0x8000). */
47 struct ppc64_stub_entry
48 {
49         /* 28 byte jump instruction sequence (7 instructions) */
50         unsigned char jump[28];
51         unsigned char unused[4];
52         /* Data for the above code */
53         struct ppc64_opd_entry opd;
54 };
55
56 /* We use a stub to fix up r2 (TOC ptr) and to jump to the (external)
57    function which may be more than 24-bits away.  We could simply
58    patch the new r2 value and function pointer into the stub, but it's
59    significantly shorter to put these values at the end of the stub
60    code, and patch the stub address (32-bits relative to the TOC ptr,
61    r2) into the stub. */
62 static struct ppc64_stub_entry ppc64_stub =
63 { .jump = {
64         0x3d, 0x82, 0x00, 0x00, /* addis   r12,r2, <high> */
65         0x39, 0x8c, 0x00, 0x00, /* addi    r12,r12, <low> */
66         /* Save current r2 value in magic place on the stack. */
67         0xf8, 0x41, 0x00, 0x28, /* std     r2,40(r1) */
68         0xe9, 0x6c, 0x00, 0x20, /* ld      r11,32(r12) */
69         0xe8, 0x4c, 0x00, 0x28, /* ld      r2,40(r12) */
70         0x7d, 0x69, 0x03, 0xa6, /* mtctr   r11 */
71         0x4e, 0x80, 0x04, 0x20  /* bctr */
72 } };
73
74 /* Count how many different 24-bit relocations (different symbol,
75    different addend) */
76 static unsigned int count_relocs(const Elf64_Rela *rela, unsigned int num)
77 {
78         unsigned int i, r_info, r_addend, _count_relocs;
79
80         /* FIXME: Only count external ones --RR */
81         _count_relocs = 0;
82         r_info = 0;
83         r_addend = 0;
84         for (i = 0; i < num; i++)
85                 /* Only count 24-bit relocs, others don't need stubs */
86                 if (ELF64_R_TYPE(rela[i].r_info) == R_PPC_REL24 &&
87                     (r_info != ELF64_R_SYM(rela[i].r_info) ||
88                      r_addend != rela[i].r_addend)) {
89                         _count_relocs++;
90                         r_info = ELF64_R_SYM(rela[i].r_info);
91                         r_addend = rela[i].r_addend;
92                 }
93
94         return _count_relocs;
95 }
96
97 static int relacmp(const void *_x, const void *_y)
98 {
99         const Elf64_Rela *x, *y;
100
101         y = (Elf64_Rela *)_x;
102         x = (Elf64_Rela *)_y;
103
104         /* Compare the entire r_info (as opposed to ELF64_R_SYM(r_info) only) to
105          * make the comparison cheaper/faster. It won't affect the sorting or
106          * the counting algorithms' performance
107          */
108         if (x->r_info < y->r_info)
109                 return -1;
110         else if (x->r_info > y->r_info)
111                 return 1;
112         else if (x->r_addend < y->r_addend)
113                 return -1;
114         else if (x->r_addend > y->r_addend)
115                 return 1;
116         else
117                 return 0;
118 }
119
120 static void relaswap(void *_x, void *_y, int size)
121 {
122         uint64_t *x, *y, tmp;
123         int i;
124
125         y = (uint64_t *)_x;
126         x = (uint64_t *)_y;
127
128         for (i = 0; i < sizeof(Elf64_Rela) / sizeof(uint64_t); i++) {
129                 tmp = x[i];
130                 x[i] = y[i];
131                 y[i] = tmp;
132         }
133 }
134
135 /* Get size of potential trampolines required. */
136 static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
137                                     const Elf64_Shdr *sechdrs)
138 {
139         /* One extra reloc so it's always 0-funcaddr terminated */
140         unsigned long relocs = 1;
141         unsigned i;
142
143         /* Every relocated section... */
144         for (i = 1; i < hdr->e_shnum; i++) {
145                 if (sechdrs[i].sh_type == SHT_RELA) {
146                         DEBUGP("Found relocations in section %u\n", i);
147                         DEBUGP("Ptr: %p.  Number: %lu\n",
148                                (void *)sechdrs[i].sh_addr,
149                                sechdrs[i].sh_size / sizeof(Elf64_Rela));
150
151                         /* Sort the relocation information based on a symbol and
152                          * addend key. This is a stable O(n*log n) complexity
153                          * alogrithm but it will reduce the complexity of
154                          * count_relocs() to linear complexity O(n)
155                          */
156                         sort((void *)sechdrs[i].sh_addr,
157                              sechdrs[i].sh_size / sizeof(Elf64_Rela),
158                              sizeof(Elf64_Rela), relacmp, relaswap);
159
160                         relocs += count_relocs((void *)sechdrs[i].sh_addr,
161                                                sechdrs[i].sh_size
162                                                / sizeof(Elf64_Rela));
163                 }
164         }
165
166         DEBUGP("Looks like a total of %lu stubs, max\n", relocs);
167         return relocs * sizeof(struct ppc64_stub_entry);
168 }
169
170 static void dedotify_versions(struct modversion_info *vers,
171                               unsigned long size)
172 {
173         struct modversion_info *end;
174
175         for (end = (void *)vers + size; vers < end; vers++)
176                 if (vers->name[0] == '.')
177                         memmove(vers->name, vers->name+1, strlen(vers->name));
178 }
179
180 /* Undefined symbols which refer to .funcname, hack to funcname */
181 static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
182 {
183         unsigned int i;
184
185         for (i = 1; i < numsyms; i++) {
186                 if (syms[i].st_shndx == SHN_UNDEF) {
187                         char *name = strtab + syms[i].st_name;
188                         if (name[0] == '.')
189                                 memmove(name, name+1, strlen(name));
190                 }
191         }
192 }
193
194 int module_frob_arch_sections(Elf64_Ehdr *hdr,
195                               Elf64_Shdr *sechdrs,
196                               char *secstrings,
197                               struct module *me)
198 {
199         unsigned int i;
200
201         /* Find .toc and .stubs sections, symtab and strtab */
202         for (i = 1; i < hdr->e_shnum; i++) {
203                 char *p;
204                 if (strcmp(secstrings + sechdrs[i].sh_name, ".stubs") == 0)
205                         me->arch.stubs_section = i;
206                 else if (strcmp(secstrings + sechdrs[i].sh_name, ".toc") == 0)
207                         me->arch.toc_section = i;
208                 else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0)
209                         dedotify_versions((void *)hdr + sechdrs[i].sh_offset,
210                                           sechdrs[i].sh_size);
211
212                 /* We don't handle .init for the moment: rename to _init */
213                 while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init")))
214                         p[0] = '_';
215
216                 if (sechdrs[i].sh_type == SHT_SYMTAB)
217                         dedotify((void *)hdr + sechdrs[i].sh_offset,
218                                  sechdrs[i].sh_size / sizeof(Elf64_Sym),
219                                  (void *)hdr
220                                  + sechdrs[sechdrs[i].sh_link].sh_offset);
221         }
222
223         if (!me->arch.stubs_section) {
224                 printk("%s: doesn't contain .stubs.\n", me->name);
225                 return -ENOEXEC;
226         }
227
228         /* If we don't have a .toc, just use .stubs.  We need to set r2
229            to some reasonable value in case the module calls out to
230            other functions via a stub, or if a function pointer escapes
231            the module by some means.  */
232         if (!me->arch.toc_section)
233                 me->arch.toc_section = me->arch.stubs_section;
234
235         /* Override the stubs size */
236         sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs);
237         return 0;
238 }
239
240 int apply_relocate(Elf64_Shdr *sechdrs,
241                    const char *strtab,
242                    unsigned int symindex,
243                    unsigned int relsec,
244                    struct module *me)
245 {
246         printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", me->name);
247         return -ENOEXEC;
248 }
249
250 /* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
251    gives the value maximum span in an instruction which uses a signed
252    offset) */
253 static inline unsigned long my_r2(Elf64_Shdr *sechdrs, struct module *me)
254 {
255         return sechdrs[me->arch.toc_section].sh_addr + 0x8000;
256 }
257
258 /* Both low and high 16 bits are added as SIGNED additions, so if low
259    16 bits has high bit set, high 16 bits must be adjusted.  These
260    macros do that (stolen from binutils). */
261 #define PPC_LO(v) ((v) & 0xffff)
262 #define PPC_HI(v) (((v) >> 16) & 0xffff)
263 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
264
265 /* Patch stub to reference function and correct r2 value. */
266 static inline int create_stub(Elf64_Shdr *sechdrs,
267                               struct ppc64_stub_entry *entry,
268                               struct ppc64_opd_entry *opd,
269                               struct module *me)
270 {
271         Elf64_Half *loc1, *loc2;
272         long reladdr;
273
274         *entry = ppc64_stub;
275
276         loc1 = (Elf64_Half *)&entry->jump[2];
277         loc2 = (Elf64_Half *)&entry->jump[6];
278
279         /* Stub uses address relative to r2. */
280         reladdr = (unsigned long)entry - my_r2(sechdrs, me);
281         if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
282                 printk("%s: Address %p of stub out of range of %p.\n",
283                        me->name, (void *)reladdr, (void *)my_r2);
284                 return 0;
285         }
286         DEBUGP("Stub %p get data from reladdr %li\n", entry, reladdr);
287
288         *loc1 = PPC_HA(reladdr);
289         *loc2 = PPC_LO(reladdr);
290         entry->opd.funcaddr = opd->funcaddr;
291         entry->opd.r2 = opd->r2;
292         return 1;
293 }
294
295 /* Create stub to jump to function described in this OPD: we need the
296    stub to set up the TOC ptr (r2) for the function. */
297 static unsigned long stub_for_addr(Elf64_Shdr *sechdrs,
298                                    unsigned long opdaddr,
299                                    struct module *me)
300 {
301         struct ppc64_stub_entry *stubs;
302         struct ppc64_opd_entry *opd = (void *)opdaddr;
303         unsigned int i, num_stubs;
304
305         num_stubs = sechdrs[me->arch.stubs_section].sh_size / sizeof(*stubs);
306
307         /* Find this stub, or if that fails, the next avail. entry */
308         stubs = (void *)sechdrs[me->arch.stubs_section].sh_addr;
309         for (i = 0; stubs[i].opd.funcaddr; i++) {
310                 BUG_ON(i >= num_stubs);
311
312                 if (stubs[i].opd.funcaddr == opd->funcaddr)
313                         return (unsigned long)&stubs[i];
314         }
315
316         if (!create_stub(sechdrs, &stubs[i], opd, me))
317                 return 0;
318
319         return (unsigned long)&stubs[i];
320 }
321
322 /* We expect a noop next: if it is, replace it with instruction to
323    restore r2. */
324 static int restore_r2(u32 *instruction, struct module *me)
325 {
326         if (*instruction != PPC_NOP_INSTR) {
327                 printk("%s: Expect noop after relocate, got %08x\n",
328                        me->name, *instruction);
329                 return 0;
330         }
331         *instruction = 0xe8410028;      /* ld r2,40(r1) */
332         return 1;
333 }
334
335 int apply_relocate_add(Elf64_Shdr *sechdrs,
336                        const char *strtab,
337                        unsigned int symindex,
338                        unsigned int relsec,
339                        struct module *me)
340 {
341         unsigned int i;
342         Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
343         Elf64_Sym *sym;
344         unsigned long *location;
345         unsigned long value;
346
347         DEBUGP("Applying ADD relocate section %u to %u\n", relsec,
348                sechdrs[relsec].sh_info);
349         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
350                 /* This is where to make the change */
351                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
352                         + rela[i].r_offset;
353                 /* This is the symbol it is referring to */
354                 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
355                         + ELF64_R_SYM(rela[i].r_info);
356
357                 DEBUGP("RELOC at %p: %li-type as %s (%lu) + %li\n",
358                        location, (long)ELF64_R_TYPE(rela[i].r_info),
359                        strtab + sym->st_name, (unsigned long)sym->st_value,
360                        (long)rela[i].r_addend);
361
362                 /* `Everything is relative'. */
363                 value = sym->st_value + rela[i].r_addend;
364
365                 switch (ELF64_R_TYPE(rela[i].r_info)) {
366                 case R_PPC64_ADDR32:
367                         /* Simply set it */
368                         *(u32 *)location = value;
369                         break;
370
371                 case R_PPC64_ADDR64:
372                         /* Simply set it */
373                         *(unsigned long *)location = value;
374                         break;
375
376                 case R_PPC64_TOC:
377                         *(unsigned long *)location = my_r2(sechdrs, me);
378                         break;
379
380                 case R_PPC64_TOC16:
381                         /* Subtract TOC pointer */
382                         value -= my_r2(sechdrs, me);
383                         if (value + 0x8000 > 0xffff) {
384                                 printk("%s: bad TOC16 relocation (%lu)\n",
385                                        me->name, value);
386                                 return -ENOEXEC;
387                         }
388                         *((uint16_t *) location)
389                                 = (*((uint16_t *) location) & ~0xffff)
390                                 | (value & 0xffff);
391                         break;
392
393                 case R_PPC64_TOC16_DS:
394                         /* Subtract TOC pointer */
395                         value -= my_r2(sechdrs, me);
396                         if ((value & 3) != 0 || value + 0x8000 > 0xffff) {
397                                 printk("%s: bad TOC16_DS relocation (%lu)\n",
398                                        me->name, value);
399                                 return -ENOEXEC;
400                         }
401                         *((uint16_t *) location)
402                                 = (*((uint16_t *) location) & ~0xfffc)
403                                 | (value & 0xfffc);
404                         break;
405
406                 case R_PPC_REL24:
407                         /* FIXME: Handle weak symbols here --RR */
408                         if (sym->st_shndx == SHN_UNDEF) {
409                                 /* External: go via stub */
410                                 value = stub_for_addr(sechdrs, value, me);
411                                 if (!value)
412                                         return -ENOENT;
413                                 if (!restore_r2((u32 *)location + 1, me))
414                                         return -ENOEXEC;
415                         }
416
417                         /* Convert value to relative */
418                         value -= (unsigned long)location;
419                         if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0){
420                                 printk("%s: REL24 %li out of range!\n",
421                                        me->name, (long int)value);
422                                 return -ENOEXEC;
423                         }
424
425                         /* Only replace bits 2 through 26 */
426                         *(uint32_t *)location
427                                 = (*(uint32_t *)location & ~0x03fffffc)
428                                 | (value & 0x03fffffc);
429                         break;
430
431                 case R_PPC64_REL64:
432                         /* 64 bits relative (used by features fixups) */
433                         *location = value - (unsigned long)location;
434                         break;
435
436                 default:
437                         printk("%s: Unknown ADD relocation: %lu\n",
438                                me->name,
439                                (unsigned long)ELF64_R_TYPE(rela[i].r_info));
440                         return -ENOEXEC;
441                 }
442         }
443
444         return 0;
445 }