summaryrefslogtreecommitdiff
path: root/arch/sparc/kernel/module.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-18 22:03:31 -0200
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-18 22:03:31 -0200
commite27fc7e476077c724f313a3ddec44ad26c49f678 (patch)
tree5d66d9694e4aa3985464e5034f1d4908ec426766 /arch/sparc/kernel/module.c
parentb6844523839779030430ff28f036f83e2a3f43e6 (diff)
parent0b64120cceb86e93cb1bda0dc055f13016646907 (diff)
downloadlwn-e27fc7e476077c724f313a3ddec44ad26c49f678.tar.gz
lwn-e27fc7e476077c724f313a3ddec44ad26c49f678.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: sparc64: Patch sun4v code sequences properly on module load. sparc: Kill custom io_remap_pfn_range(). sparc: Stash orig_i0 into %g6 instead of %g2 sparc: Fix handling of orig_i0 wrt. debugging when restarting syscalls. sparc: sigutil: Include <linux/errno.h>
Diffstat (limited to 'arch/sparc/kernel/module.c')
-rw-r--r--arch/sparc/kernel/module.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index da0c6c70ccb2..e5519870c3d9 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -17,6 +17,8 @@
#include <asm/processor.h>
#include <asm/spitfire.h>
+#include "entry.h"
+
#ifdef CONFIG_SPARC64
#include <linux/jump_label.h>
@@ -203,6 +205,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
}
#ifdef CONFIG_SPARC64
+static void do_patch_sections(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs)
+{
+ const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
+ char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+ if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
+ sun4v_1insn = s;
+ if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
+ sun4v_2insn = s;
+ }
+
+ if (sun4v_1insn && tlb_type == hypervisor) {
+ void *p = (void *) sun4v_1insn->sh_addr;
+ sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
+ }
+ if (sun4v_2insn && tlb_type == hypervisor) {
+ void *p = (void *) sun4v_2insn->sh_addr;
+ sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
+ }
+}
+
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
@@ -210,6 +235,8 @@ int module_finalize(const Elf_Ehdr *hdr,
/* make jump label nops */
jump_label_apply_nops(me);
+ do_patch_sections(hdr, sechdrs);
+
/* Cheetah's I-cache is fully coherent. */
if (tlb_type == spitfire) {
unsigned long va;