summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2013-11-04 20:27:13 +0100
committerOleg Nesterov <oleg@redhat.com>2013-11-06 20:00:05 +0100
commit8a8de66c4f6ebd0f6d3da026ec24339aa5d1db12 (patch)
tree8e8ac183b41f6b1249e819017c93fc24e332a1dd
parent736e89d9f782a7dd9a38ecda13b2db916fa72f33 (diff)
downloadlinux-stable-8a8de66c4f6ebd0f6d3da026ec24339aa5d1db12.tar.gz
linux-stable-8a8de66c4f6ebd0f6d3da026ec24339aa5d1db12.tar.bz2
linux-stable-8a8de66c4f6ebd0f6d3da026ec24339aa5d1db12.zip
uprobes: Introduce arch_uprobe->ixol
Currently xol_get_insn_slot() assumes that we should simply copy arch_uprobe->insn[] which is (ignoring arch_uprobe_analyze_insn) just the copy of the original insn. This is not true for arm which needs to create another insn to execute it out-of-line. So this patch simply adds the new member, ->ixol into the union. This doesn't make any difference for x86 and powerpc, but arm can divorce insn/ixol and initialize the correct xol insn in arch_uprobe_analyze_insn(). Signed-off-by: Oleg Nesterov <oleg@redhat.com>
-rw-r--r--arch/powerpc/include/asm/uprobes.h1
-rw-r--r--arch/x86/include/asm/uprobes.h5
-rw-r--r--kernel/events/uprobes.c3
3 files changed, 7 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h
index b6fc3178372a..75c6ecdb8f37 100644
--- a/arch/powerpc/include/asm/uprobes.h
+++ b/arch/powerpc/include/asm/uprobes.h
@@ -37,6 +37,7 @@ typedef ppc_opcode_t uprobe_opcode_t;
struct arch_uprobe {
union {
u8 insn[MAX_UINSN_BYTES];
+ u8 ixol[MAX_UINSN_BYTES];
u32 ainsn;
};
};
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index b20b4d68b934..3087ea9c5f2e 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -35,7 +35,10 @@ typedef u8 uprobe_opcode_t;
struct arch_uprobe {
u16 fixups;
- u8 insn[MAX_UINSN_BYTES];
+ union {
+ u8 insn[MAX_UINSN_BYTES];
+ u8 ixol[MAX_UINSN_BYTES];
+ };
#ifdef CONFIG_X86_64
unsigned long rip_rela_target_address;
#endif
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 0012c8ebb098..fbcff61b5099 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1264,7 +1264,8 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
return 0;
/* Initialize the slot */
- copy_to_page(area->page, xol_vaddr, uprobe->arch.insn, MAX_UINSN_BYTES);
+ copy_to_page(area->page, xol_vaddr,
+ uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
/*
* We probably need flush_icache_user_range() but it needs vma.
* This should work on supported architectures too.