sparc64: Patch sun4v code sequences properly on module load.

Some of the sun4v code patching occurs in inline functions visible
to, and usable by, modules.

Therefore we have to patch them up during module load.

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2011-11-17 22:44:58 -08:00
parent 3e37fd3153
commit 0b64120cce
3 changed files with 70 additions and 26 deletions

View file

@ -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;