aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-10-19 21:47:19 -0400
committerPaul Mackerras <paulus@samba.org>2006-10-24 21:54:13 -0400
commit21c4ff80cba5e24932f3ef79c8482c0491630b2b (patch)
treedf44027a8f419057039f1709371b85cd57b52804 /arch/powerpc
parent0909c8c2d547e45ca50e2492b08ec93a37b35237 (diff)
[POWERPC] Support feature fixups in modules
This patch adds support for feature fixups in modules. This involves adding support for R_PPC64_REL64 relocs to the 64 bits module loader. It also modifies modpost.c to ignore the powerpc fixup sections (or it would warn when used in .init.text). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/module_32.c39
-rw-r--r--arch/powerpc/kernel/module_64.c49
2 files changed, 69 insertions, 19 deletions
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index 92f4e5f64f02..e2c3c6a85f33 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -24,6 +24,8 @@
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/cache.h> 25#include <linux/cache.h>
26 26
27#include "setup.h"
28
27#if 0 29#if 0
28#define DEBUGP printk 30#define DEBUGP printk
29#else 31#else
@@ -269,33 +271,50 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
269 return 0; 271 return 0;
270} 272}
271 273
274static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
275 const Elf_Shdr *sechdrs,
276 const char *name)
277{
278 char *secstrings;
279 unsigned int i;
280
281 secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
282 for (i = 1; i < hdr->e_shnum; i++)
283 if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0)
284 return &sechdrs[i];
285 return NULL;
286}
287
272int module_finalize(const Elf_Ehdr *hdr, 288int module_finalize(const Elf_Ehdr *hdr,
273 const Elf_Shdr *sechdrs, 289 const Elf_Shdr *sechdrs,
274 struct module *me) 290 struct module *me)
275{ 291{
276 char *secstrings; 292 const Elf_Shdr *sect;
277 unsigned int i;
278 293
279 me->arch.bug_table = NULL; 294 me->arch.bug_table = NULL;
280 me->arch.num_bugs = 0; 295 me->arch.num_bugs = 0;
281 296
282 /* Find the __bug_table section, if present */ 297 /* Find the __bug_table section, if present */
283 secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 298 sect = find_section(hdr, sechdrs, "__bug_table");
284 for (i = 1; i < hdr->e_shnum; i++) { 299 if (sect != NULL) {
285 if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) 300 me->arch.bug_table = (void *) sect->sh_addr;
286 continue; 301 me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
287 me->arch.bug_table = (void *) sechdrs[i].sh_addr;
288 me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
289 break;
290 } 302 }
291 303
292 /* 304 /*
293 * Strictly speaking this should have a spinlock to protect against 305 * Strictly speaking this should have a spinlock to protect against
294 * traversals, but since we only traverse on BUG()s, a spinlock 306 * traversals, but since we only traverse on BUG()s, a spinlock
295 * could potentially lead to deadlock and thus be counter-productive. 307 * could potentially lead to deadlock and thus be counter-productive.
296 */ 308 */
297 list_add(&me->arch.bug_list, &module_bug_list); 309 list_add(&me->arch.bug_list, &module_bug_list);
298 310
311 /* Apply feature fixups */
312 sect = find_section(hdr, sechdrs, "__ftr_fixup");
313 if (sect != NULL)
314 do_feature_fixups(cur_cpu_spec->cpu_features,
315 (void *)sect->sh_addr,
316 (void *)sect->sh_addr + sect->sh_size);
317
299 return 0; 318 return 0;
300} 319}
301 320
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index ba34001fca8e..8dd1f0aae5d6 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -22,6 +22,9 @@
22#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
23#include <asm/module.h> 23#include <asm/module.h>
24#include <asm/uaccess.h> 24#include <asm/uaccess.h>
25#include <asm/firmware.h>
26
27#include "setup.h"
25 28
26/* FIXME: We don't do .init separately. To do this, we'd need to have 29/* FIXME: We don't do .init separately. To do this, we'd need to have
27 a separate r2 value in the init and core section, and stub between 30 a separate r2 value in the init and core section, and stub between
@@ -400,6 +403,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
400 | (value & 0x03fffffc); 403 | (value & 0x03fffffc);
401 break; 404 break;
402 405
406 case R_PPC64_REL64:
407 /* 64 bits relative (used by features fixups) */
408 *location = value - (unsigned long)location;
409 break;
410
403 default: 411 default:
404 printk("%s: Unknown ADD relocation: %lu\n", 412 printk("%s: Unknown ADD relocation: %lu\n",
405 me->name, 413 me->name,
@@ -413,23 +421,33 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
413 421
414LIST_HEAD(module_bug_list); 422LIST_HEAD(module_bug_list);
415 423
416int module_finalize(const Elf_Ehdr *hdr, 424static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
417 const Elf_Shdr *sechdrs, struct module *me) 425 const Elf_Shdr *sechdrs,
426 const char *name)
418{ 427{
419 char *secstrings; 428 char *secstrings;
420 unsigned int i; 429 unsigned int i;
421 430
431 secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
432 for (i = 1; i < hdr->e_shnum; i++)
433 if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0)
434 return &sechdrs[i];
435 return NULL;
436}
437
438int module_finalize(const Elf_Ehdr *hdr,
439 const Elf_Shdr *sechdrs, struct module *me)
440{
441 const Elf_Shdr *sect;
442
422 me->arch.bug_table = NULL; 443 me->arch.bug_table = NULL;
423 me->arch.num_bugs = 0; 444 me->arch.num_bugs = 0;
424 445
425 /* Find the __bug_table section, if present */ 446 /* Find the __bug_table section, if present */
426 secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 447 sect = find_section(hdr, sechdrs, "__bug_table");
427 for (i = 1; i < hdr->e_shnum; i++) { 448 if (sect != NULL) {
428 if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) 449 me->arch.bug_table = (void *) sect->sh_addr;
429 continue; 450 me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry);
430 me->arch.bug_table = (void *) sechdrs[i].sh_addr;
431 me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
432 break;
433 } 451 }
434 452
435 /* 453 /*
@@ -439,6 +457,19 @@ int module_finalize(const Elf_Ehdr *hdr,
439 */ 457 */
440 list_add(&me->arch.bug_list, &module_bug_list); 458 list_add(&me->arch.bug_list, &module_bug_list);
441 459
460 /* Apply feature fixups */
461 sect = find_section(hdr, sechdrs, "__ftr_fixup");
462 if (sect != NULL)
463 do_feature_fixups(cur_cpu_spec->cpu_features,
464 (void *)sect->sh_addr,
465 (void *)sect->sh_addr + sect->sh_size);
466
467 sect = find_section(hdr, sechdrs, "__fw_ftr_fixup");
468 if (sect != NULL)
469 do_feature_fixups(powerpc_firmware_features,
470 (void *)sect->sh_addr,
471 (void *)sect->sh_addr + sect->sh_size);
472
442 return 0; 473 return 0;
443} 474}
444 475