Skip to content

Commit 46f5cfc

Browse files
author
Ingo Molnar
committed
Merge branch 'core/kprobes' into perf/core, to pick up a completed branch
Signed-off-by: Ingo Molnar <[email protected]>
2 parents 46cf053 + 2040cf9 commit 46f5cfc

File tree

38 files changed

+604
-1131
lines changed

38 files changed

+604
-1131
lines changed

arch/arm/kernel/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
5353
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
5454
obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
5555
obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o
56-
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
57-
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
56+
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o patch.o
57+
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o patch.o
5858
obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
5959
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
6060
# Main staffs in KPROBES are in arch/arm/probes/ .

arch/arm/kernel/ftrace.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <asm/ftrace.h>
2323
#include <asm/insn.h>
2424
#include <asm/set_memory.h>
25+
#include <asm/patch.h>
2526

2627
#ifdef CONFIG_THUMB2_KERNEL
2728
#define NOP 0xf85deb04 /* pop.w {lr} */
@@ -35,9 +36,7 @@ static int __ftrace_modify_code(void *data)
3536
{
3637
int *command = data;
3738

38-
set_kernel_text_rw();
3939
ftrace_modify_all_code(*command);
40-
set_kernel_text_ro();
4140

4241
return 0;
4342
}
@@ -59,13 +58,11 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
5958

6059
int ftrace_arch_code_modify_prepare(void)
6160
{
62-
set_all_modules_text_rw();
6361
return 0;
6462
}
6563

6664
int ftrace_arch_code_modify_post_process(void)
6765
{
68-
set_all_modules_text_ro();
6966
/* Make sure any TLB misses during machine stop are cleared. */
7067
flush_tlb_all();
7168
return 0;
@@ -97,10 +94,7 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old,
9794
return -EINVAL;
9895
}
9996

100-
if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
101-
return -EPERM;
102-
103-
flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
97+
__patch_text((void *)pc, new);
10498

10599
return 0;
106100
}

arch/nds32/kernel/ftrace.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,6 @@ int __init ftrace_dyn_arch_init(void)
8989
return 0;
9090
}
9191

92-
int ftrace_arch_code_modify_prepare(void)
93-
{
94-
set_all_modules_text_rw();
95-
return 0;
96-
}
97-
98-
int ftrace_arch_code_modify_post_process(void)
99-
{
100-
set_all_modules_text_ro();
101-
return 0;
102-
}
103-
10492
static unsigned long gen_sethi_insn(unsigned long addr)
10593
{
10694
unsigned long opcode = 0x46000000;

arch/x86/include/asm/ftrace.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ struct dyn_arch_ftrace {
4747
/* No extra data needed for x86 */
4848
};
4949

50-
int ftrace_int3_handler(struct pt_regs *regs);
51-
5250
#define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR
5351

5452
#endif /* CONFIG_DYNAMIC_FTRACE */

arch/x86/include/asm/kprobes.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@
1111

1212
#include <asm-generic/kprobes.h>
1313

14-
#define BREAKPOINT_INSTRUCTION 0xcc
15-
1614
#ifdef CONFIG_KPROBES
1715
#include <linux/types.h>
1816
#include <linux/ptrace.h>
1917
#include <linux/percpu.h>
18+
#include <asm/text-patching.h>
2019
#include <asm/insn.h>
2120

2221
#define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -25,10 +24,7 @@ struct pt_regs;
2524
struct kprobe;
2625

2726
typedef u8 kprobe_opcode_t;
28-
#define RELATIVEJUMP_OPCODE 0xe9
29-
#define RELATIVEJUMP_SIZE 5
30-
#define RELATIVECALL_OPCODE 0xe8
31-
#define RELATIVE_ADDR_SIZE 4
27+
3228
#define MAX_STACK_SIZE 64
3329
#define CUR_STACK_SIZE(ADDR) \
3430
(current_top_of_stack() - (unsigned long)(ADDR))
@@ -43,11 +39,11 @@ extern __visible kprobe_opcode_t optprobe_template_entry[];
4339
extern __visible kprobe_opcode_t optprobe_template_val[];
4440
extern __visible kprobe_opcode_t optprobe_template_call[];
4541
extern __visible kprobe_opcode_t optprobe_template_end[];
46-
#define MAX_OPTIMIZED_LENGTH (MAX_INSN_SIZE + RELATIVE_ADDR_SIZE)
42+
#define MAX_OPTIMIZED_LENGTH (MAX_INSN_SIZE + DISP32_SIZE)
4743
#define MAX_OPTINSN_SIZE \
4844
(((unsigned long)optprobe_template_end - \
4945
(unsigned long)optprobe_template_entry) + \
50-
MAX_OPTIMIZED_LENGTH + RELATIVEJUMP_SIZE)
46+
MAX_OPTIMIZED_LENGTH + JMP32_INSN_SIZE)
5147

5248
extern const int kretprobe_blacklist_size;
5349

@@ -73,7 +69,7 @@ struct arch_specific_insn {
7369

7470
struct arch_optimized_insn {
7571
/* copy of the original instructions */
76-
kprobe_opcode_t copied_insn[RELATIVE_ADDR_SIZE];
72+
kprobe_opcode_t copied_insn[DISP32_SIZE];
7773
/* detour code buffer */
7874
kprobe_opcode_t *insn;
7975
/* the size of instructions copied to detour code buffer */

arch/x86/include/asm/set_memory.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ int set_direct_map_invalid_noflush(struct page *page);
8181
int set_direct_map_default_noflush(struct page *page);
8282

8383
extern int kernel_set_to_readonly;
84-
void set_kernel_text_rw(void);
85-
void set_kernel_text_ro(void);
8684

8785
#ifdef CONFIG_X86_64
8886
static inline int set_mce_nospec(unsigned long pfn)

arch/x86/include/asm/text-patching.h

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,6 @@ static inline void apply_paravirt(struct paravirt_patch_site *start,
2525
*/
2626
#define POKE_MAX_OPCODE_SIZE 5
2727

28-
struct text_poke_loc {
29-
void *addr;
30-
int len;
31-
s32 rel32;
32-
u8 opcode;
33-
const u8 text[POKE_MAX_OPCODE_SIZE];
34-
};
35-
3628
extern void text_poke_early(void *addr, const void *opcode, size_t len);
3729

3830
/*
@@ -50,21 +42,13 @@ extern void text_poke_early(void *addr, const void *opcode, size_t len);
5042
* an inconsistent instruction while you patch.
5143
*/
5244
extern void *text_poke(void *addr, const void *opcode, size_t len);
45+
extern void text_poke_sync(void);
5346
extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
5447
extern int poke_int3_handler(struct pt_regs *regs);
5548
extern void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate);
56-
extern void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries);
57-
extern void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
58-
const void *opcode, size_t len, const void *emulate);
59-
extern int after_bootmem;
60-
extern __ro_after_init struct mm_struct *poking_mm;
61-
extern __ro_after_init unsigned long poking_addr;
6249

63-
#ifndef CONFIG_UML_X86
64-
static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
65-
{
66-
regs->ip = ip;
67-
}
50+
extern void text_poke_queue(void *addr, const void *opcode, size_t len, const void *emulate);
51+
extern void text_poke_finish(void);
6852

6953
#define INT3_INSN_SIZE 1
7054
#define INT3_INSN_OPCODE 0xCC
@@ -78,13 +62,77 @@ static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
7862
#define JMP8_INSN_SIZE 2
7963
#define JMP8_INSN_OPCODE 0xEB
8064

65+
#define DISP32_SIZE 4
66+
67+
static inline int text_opcode_size(u8 opcode)
68+
{
69+
int size = 0;
70+
71+
#define __CASE(insn) \
72+
case insn##_INSN_OPCODE: size = insn##_INSN_SIZE; break
73+
74+
switch(opcode) {
75+
__CASE(INT3);
76+
__CASE(CALL);
77+
__CASE(JMP32);
78+
__CASE(JMP8);
79+
}
80+
81+
#undef __CASE
82+
83+
return size;
84+
}
85+
86+
union text_poke_insn {
87+
u8 text[POKE_MAX_OPCODE_SIZE];
88+
struct {
89+
u8 opcode;
90+
s32 disp;
91+
} __attribute__((packed));
92+
};
93+
94+
static __always_inline
95+
void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
96+
{
97+
static union text_poke_insn insn; /* per instance */
98+
int size = text_opcode_size(opcode);
99+
100+
insn.opcode = opcode;
101+
102+
if (size > 1) {
103+
insn.disp = (long)dest - (long)(addr + size);
104+
if (size == 2) {
105+
/*
106+
* Ensure that for JMP9 the displacement
107+
* actually fits the signed byte.
108+
*/
109+
BUG_ON((insn.disp >> 31) != (insn.disp >> 7));
110+
}
111+
}
112+
113+
return &insn.text;
114+
}
115+
116+
extern int after_bootmem;
117+
extern __ro_after_init struct mm_struct *poking_mm;
118+
extern __ro_after_init unsigned long poking_addr;
119+
120+
#ifndef CONFIG_UML_X86
121+
static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
122+
{
123+
regs->ip = ip;
124+
}
125+
81126
static inline void int3_emulate_push(struct pt_regs *regs, unsigned long val)
82127
{
83128
/*
84129
* The int3 handler in entry_64.S adds a gap between the
85130
* stack where the break point happened, and the saving of
86131
* pt_regs. We can extend the original stack because of
87132
* this gap. See the idtentry macro's create_gap option.
133+
*
134+
* Similarly entry_32.S will have a gap on the stack for (any) hardware
135+
* exception and pt_regs; see FIXUP_FRAME.
88136
*/
89137
regs->sp -= sizeof(unsigned long);
90138
*(unsigned long *)regs->sp = val;

0 commit comments

Comments
 (0)