diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-02-10 05:26:38 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-02-10 05:26:38 -0500 |
commit | df9ab9771c64f5229843bfe2a20fe0ee6ac59fc1 (patch) | |
tree | a091be1024bd76627f78e791e377126e47703b7b /arch | |
parent | ed8f8ce38d0f7b505d7da2d79522972e962457c2 (diff) | |
parent | 4e1c0664de11e4b5861957ab4ddff2aeeffd042f (diff) |
Merge branch 'devel-stable' into for-next
Diffstat (limited to 'arch')
65 files changed, 1331 insertions, 244 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c3a986d45125..1f5eb9aee750 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -61,6 +61,7 @@ config ARM | |||
61 | select HAVE_MEMBLOCK | 61 | select HAVE_MEMBLOCK |
62 | select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND | 62 | select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND |
63 | select HAVE_OPROFILE if (HAVE_PERF_EVENTS) | 63 | select HAVE_OPROFILE if (HAVE_PERF_EVENTS) |
64 | select HAVE_OPTPROBES if !THUMB2_KERNEL | ||
64 | select HAVE_PERF_EVENTS | 65 | select HAVE_PERF_EVENTS |
65 | select HAVE_PERF_REGS | 66 | select HAVE_PERF_REGS |
66 | select HAVE_PERF_USER_STACK_DUMP | 67 | select HAVE_PERF_USER_STACK_DUMP |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c1785eec2cf7..7f99cd652203 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -266,6 +266,7 @@ core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/ | |||
266 | 266 | ||
267 | # If we have a machine-specific directory, then include it in the build. | 267 | # If we have a machine-specific directory, then include it in the build. |
268 | core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ | 268 | core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ |
269 | core-y += arch/arm/probes/ | ||
269 | core-y += arch/arm/net/ | 270 | core-y += arch/arm/net/ |
270 | core-y += arch/arm/crypto/ | 271 | core-y += arch/arm/crypto/ |
271 | core-y += arch/arm/firmware/ | 272 | core-y += arch/arm/firmware/ |
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 1466580be295..70b1943a86b1 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts | |||
@@ -203,27 +203,3 @@ | |||
203 | compatible = "linux,spdif-dir"; | 203 | compatible = "linux,spdif-dir"; |
204 | }; | 204 | }; |
205 | }; | 205 | }; |
206 | |||
207 | &pinctrl { | ||
208 | /* | ||
209 | * These pins might be muxed as I2S by | ||
210 | * the bootloader, but it conflicts | ||
211 | * with the real I2S pins that are | ||
212 | * muxed using i2s_pins. We must mux | ||
213 | * those pins to a function other than | ||
214 | * I2S. | ||
215 | */ | ||
216 | pinctrl-0 = <&hog_pins1 &hog_pins2>; | ||
217 | pinctrl-names = "default"; | ||
218 | |||
219 | hog_pins1: hog-pins1 { | ||
220 | marvell,pins = "mpp6", "mpp8", "mpp10", | ||
221 | "mpp12", "mpp13"; | ||
222 | marvell,function = "gpio"; | ||
223 | }; | ||
224 | |||
225 | hog_pins2: hog-pins2 { | ||
226 | marvell,pins = "mpp5", "mpp7", "mpp9"; | ||
227 | marvell,function = "gpo"; | ||
228 | }; | ||
229 | }; | ||
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 2328fe752e9c..bc393b7e5ece 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig | |||
@@ -338,6 +338,7 @@ CONFIG_USB=y | |||
338 | CONFIG_USB_XHCI_HCD=y | 338 | CONFIG_USB_XHCI_HCD=y |
339 | CONFIG_USB_XHCI_MVEBU=y | 339 | CONFIG_USB_XHCI_MVEBU=y |
340 | CONFIG_USB_EHCI_HCD=y | 340 | CONFIG_USB_EHCI_HCD=y |
341 | CONFIG_USB_EHCI_EXYNOS=y | ||
341 | CONFIG_USB_EHCI_TEGRA=y | 342 | CONFIG_USB_EHCI_TEGRA=y |
342 | CONFIG_USB_EHCI_HCD_STI=y | 343 | CONFIG_USB_EHCI_HCD_STI=y |
343 | CONFIG_USB_EHCI_HCD_PLATFORM=y | 344 | CONFIG_USB_EHCI_HCD_PLATFORM=y |
diff --git a/arch/arm/kernel/insn.h b/arch/arm/include/asm/insn.h index e96065da4dae..e96065da4dae 100644 --- a/arch/arm/kernel/insn.h +++ b/arch/arm/include/asm/insn.h | |||
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index 49fa0dfaad33..3ea9be559726 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #define __ARCH_WANT_KPROBES_INSN_SLOT | 23 | #define __ARCH_WANT_KPROBES_INSN_SLOT |
24 | #define MAX_INSN_SIZE 2 | 24 | #define MAX_INSN_SIZE 2 |
25 | #define MAX_STACK_SIZE 64 /* 32 would probably be OK */ | ||
26 | 25 | ||
27 | #define flush_insn_slot(p) do { } while (0) | 26 | #define flush_insn_slot(p) do { } while (0) |
28 | #define kretprobe_blacklist_size 0 | 27 | #define kretprobe_blacklist_size 0 |
@@ -51,5 +50,37 @@ int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr); | |||
51 | int kprobe_exceptions_notify(struct notifier_block *self, | 50 | int kprobe_exceptions_notify(struct notifier_block *self, |
52 | unsigned long val, void *data); | 51 | unsigned long val, void *data); |
53 | 52 | ||
53 | /* optinsn template addresses */ | ||
54 | extern __visible kprobe_opcode_t optprobe_template_entry; | ||
55 | extern __visible kprobe_opcode_t optprobe_template_val; | ||
56 | extern __visible kprobe_opcode_t optprobe_template_call; | ||
57 | extern __visible kprobe_opcode_t optprobe_template_end; | ||
58 | extern __visible kprobe_opcode_t optprobe_template_sub_sp; | ||
59 | extern __visible kprobe_opcode_t optprobe_template_add_sp; | ||
60 | extern __visible kprobe_opcode_t optprobe_template_restore_begin; | ||
61 | extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn; | ||
62 | extern __visible kprobe_opcode_t optprobe_template_restore_end; | ||
63 | |||
64 | #define MAX_OPTIMIZED_LENGTH 4 | ||
65 | #define MAX_OPTINSN_SIZE \ | ||
66 | ((unsigned long)&optprobe_template_end - \ | ||
67 | (unsigned long)&optprobe_template_entry) | ||
68 | #define RELATIVEJUMP_SIZE 4 | ||
69 | |||
70 | struct arch_optimized_insn { | ||
71 | /* | ||
72 | * copy of the original instructions. | ||
73 | * Different from x86, ARM kprobe_opcode_t is u32. | ||
74 | */ | ||
75 | #define MAX_COPIED_INSN DIV_ROUND_UP(RELATIVEJUMP_SIZE, sizeof(kprobe_opcode_t)) | ||
76 | kprobe_opcode_t copied_insn[MAX_COPIED_INSN]; | ||
77 | /* detour code buffer */ | ||
78 | kprobe_opcode_t *insn; | ||
79 | /* | ||
80 | * We always copy one instruction on ARM, | ||
81 | * so size will always be 4, and unlike x86, there is no | ||
82 | * need for a size field. | ||
83 | */ | ||
84 | }; | ||
54 | 85 | ||
55 | #endif /* _ARM_KPROBES_H */ | 86 | #endif /* _ARM_KPROBES_H */ |
diff --git a/arch/arm/kernel/patch.h b/arch/arm/include/asm/patch.h index 77e054c2f6cd..77e054c2f6cd 100644 --- a/arch/arm/kernel/patch.h +++ b/arch/arm/include/asm/patch.h | |||
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h index 806cfe622a9e..1e5b9bb92270 100644 --- a/arch/arm/include/asm/probes.h +++ b/arch/arm/include/asm/probes.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #ifndef _ASM_PROBES_H | 19 | #ifndef _ASM_PROBES_H |
20 | #define _ASM_PROBES_H | 20 | #define _ASM_PROBES_H |
21 | 21 | ||
22 | #ifndef __ASSEMBLY__ | ||
23 | |||
22 | typedef u32 probes_opcode_t; | 24 | typedef u32 probes_opcode_t; |
23 | 25 | ||
24 | struct arch_probes_insn; | 26 | struct arch_probes_insn; |
@@ -38,6 +40,19 @@ struct arch_probes_insn { | |||
38 | probes_check_cc *insn_check_cc; | 40 | probes_check_cc *insn_check_cc; |
39 | probes_insn_singlestep_t *insn_singlestep; | 41 | probes_insn_singlestep_t *insn_singlestep; |
40 | probes_insn_fn_t *insn_fn; | 42 | probes_insn_fn_t *insn_fn; |
43 | int stack_space; | ||
44 | unsigned long register_usage_flags; | ||
45 | bool kprobe_direct_exec; | ||
41 | }; | 46 | }; |
42 | 47 | ||
48 | #endif /* __ASSEMBLY__ */ | ||
49 | |||
50 | /* | ||
51 | * We assume one instruction can consume at most 64 bytes stack, which is | ||
52 | * 'push {r0-r15}'. Instructions consume more or unknown stack space like | ||
53 | * 'str r0, [sp, #-80]' and 'str r0, [sp, r1]' should be prohibit to probe. | ||
54 | * Both kprobe and jprobe use this macro. | ||
55 | */ | ||
56 | #define MAX_STACK_SIZE 64 | ||
57 | |||
43 | #endif | 58 | #endif |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index fb2b71ebe3f2..902397dd1000 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -51,20 +51,8 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o | |||
51 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o | 51 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o |
52 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o | 52 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o |
53 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 53 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
54 | obj-$(CONFIG_UPROBES) += probes.o probes-arm.o uprobes.o uprobes-arm.o | 54 | # Main staffs in KPROBES are in arch/arm/probes/ . |
55 | obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o | 55 | obj-$(CONFIG_KPROBES) += patch.o insn.o |
56 | ifdef CONFIG_THUMB2_KERNEL | ||
57 | obj-$(CONFIG_KPROBES) += kprobes-thumb.o probes-thumb.o | ||
58 | else | ||
59 | obj-$(CONFIG_KPROBES) += kprobes-arm.o probes-arm.o | ||
60 | endif | ||
61 | obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o | ||
62 | test-kprobes-objs := kprobes-test.o | ||
63 | ifdef CONFIG_THUMB2_KERNEL | ||
64 | test-kprobes-objs += kprobes-test-thumb.o | ||
65 | else | ||
66 | test-kprobes-objs += kprobes-test-arm.o | ||
67 | endif | ||
68 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o | 56 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o |
69 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o | 57 | obj-$(CONFIG_ARM_THUMBEE) += thumbee.o |
70 | obj-$(CONFIG_KGDB) += kgdb.o patch.o | 58 | obj-$(CONFIG_KGDB) += kgdb.o patch.o |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 2f5555d307b3..672b21942fff 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include "entry-header.S" | 32 | #include "entry-header.S" |
33 | #include <asm/entry-macro-multi.S> | 33 | #include <asm/entry-macro-multi.S> |
34 | #include <asm/probes.h> | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Interrupt handling. | 37 | * Interrupt handling. |
@@ -249,7 +250,7 @@ __und_svc: | |||
249 | @ If a kprobe is about to simulate a "stmdb sp..." instruction, | 250 | @ If a kprobe is about to simulate a "stmdb sp..." instruction, |
250 | @ it obviously needs free stack space which then will belong to | 251 | @ it obviously needs free stack space which then will belong to |
251 | @ the saved context. | 252 | @ the saved context. |
252 | svc_entry 64 | 253 | svc_entry MAX_STACK_SIZE |
253 | #else | 254 | #else |
254 | svc_entry | 255 | svc_entry |
255 | #endif | 256 | #endif |
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index b8c75e45a950..709ee1d6d4df 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c | |||
@@ -20,8 +20,7 @@ | |||
20 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
21 | #include <asm/opcodes.h> | 21 | #include <asm/opcodes.h> |
22 | #include <asm/ftrace.h> | 22 | #include <asm/ftrace.h> |
23 | 23 | #include <asm/insn.h> | |
24 | #include "insn.h" | ||
25 | 24 | ||
26 | #ifdef CONFIG_THUMB2_KERNEL | 25 | #ifdef CONFIG_THUMB2_KERNEL |
27 | #define NOP 0xf85deb04 /* pop.w {lr} */ | 26 | #define NOP 0xf85deb04 /* pop.w {lr} */ |
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c index afeeb9ea6f43..e39cbf488cfe 100644 --- a/arch/arm/kernel/jump_label.c +++ b/arch/arm/kernel/jump_label.c | |||
@@ -1,8 +1,7 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/jump_label.h> | 2 | #include <linux/jump_label.h> |
3 | 3 | #include <asm/patch.h> | |
4 | #include "insn.h" | 4 | #include <asm/insn.h> |
5 | #include "patch.h" | ||
6 | 5 | ||
7 | #ifdef HAVE_JUMP_LABEL | 6 | #ifdef HAVE_JUMP_LABEL |
8 | 7 | ||
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index 07db2f8a1b45..a6ad93c9bce3 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c | |||
@@ -14,10 +14,9 @@ | |||
14 | #include <linux/kgdb.h> | 14 | #include <linux/kgdb.h> |
15 | #include <linux/uaccess.h> | 15 | #include <linux/uaccess.h> |
16 | 16 | ||
17 | #include <asm/patch.h> | ||
17 | #include <asm/traps.h> | 18 | #include <asm/traps.h> |
18 | 19 | ||
19 | #include "patch.h" | ||
20 | |||
21 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = | 20 | struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = |
22 | { | 21 | { |
23 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, | 22 | { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, |
diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c index 5038960e3c55..69bda1a5707e 100644 --- a/arch/arm/kernel/patch.c +++ b/arch/arm/kernel/patch.c | |||
@@ -8,8 +8,7 @@ | |||
8 | #include <asm/fixmap.h> | 8 | #include <asm/fixmap.h> |
9 | #include <asm/smp_plat.h> | 9 | #include <asm/smp_plat.h> |
10 | #include <asm/opcodes.h> | 10 | #include <asm/opcodes.h> |
11 | 11 | #include <asm/patch.h> | |
12 | #include "patch.h" | ||
13 | 12 | ||
14 | struct patch { | 13 | struct patch { |
15 | void *addr; | 14 | void *addr; |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index d13f185e7bd5..e55408e96559 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -1049,6 +1049,15 @@ static int c_show(struct seq_file *m, void *v) | |||
1049 | seq_printf(m, "model name\t: %s rev %d (%s)\n", | 1049 | seq_printf(m, "model name\t: %s rev %d (%s)\n", |
1050 | cpu_name, cpuid & 15, elf_platform); | 1050 | cpu_name, cpuid & 15, elf_platform); |
1051 | 1051 | ||
1052 | #if defined(CONFIG_SMP) | ||
1053 | seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", | ||
1054 | per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), | ||
1055 | (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); | ||
1056 | #else | ||
1057 | seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", | ||
1058 | loops_per_jiffy / (500000/HZ), | ||
1059 | (loops_per_jiffy / (5000/HZ)) % 100); | ||
1060 | #endif | ||
1052 | /* dump out the processor features */ | 1061 | /* dump out the processor features */ |
1053 | seq_puts(m, "Features\t: "); | 1062 | seq_puts(m, "Features\t: "); |
1054 | 1063 | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 5e6052e18850..86ef244c5a24 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -387,6 +387,18 @@ asmlinkage void secondary_start_kernel(void) | |||
387 | 387 | ||
388 | void __init smp_cpus_done(unsigned int max_cpus) | 388 | void __init smp_cpus_done(unsigned int max_cpus) |
389 | { | 389 | { |
390 | int cpu; | ||
391 | unsigned long bogosum = 0; | ||
392 | |||
393 | for_each_online_cpu(cpu) | ||
394 | bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy; | ||
395 | |||
396 | printk(KERN_INFO "SMP: Total of %d processors activated " | ||
397 | "(%lu.%02lu BogoMIPS).\n", | ||
398 | num_online_cpus(), | ||
399 | bogosum / (500000/HZ), | ||
400 | (bogosum / (5000/HZ)) % 100); | ||
401 | |||
390 | hyp_mode_check(); | 402 | hyp_mode_check(); |
391 | } | 403 | } |
392 | 404 | ||
diff --git a/arch/arm/probes/Makefile b/arch/arm/probes/Makefile new file mode 100644 index 000000000000..aa1f8590dcdd --- /dev/null +++ b/arch/arm/probes/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | obj-$(CONFIG_UPROBES) += decode.o decode-arm.o uprobes/ | ||
2 | obj-$(CONFIG_KPROBES) += decode.o kprobes/ | ||
3 | ifdef CONFIG_THUMB2_KERNEL | ||
4 | obj-$(CONFIG_KPROBES) += decode-thumb.o | ||
5 | else | ||
6 | obj-$(CONFIG_KPROBES) += decode-arm.o | ||
7 | endif | ||
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/probes/decode-arm.c index 8eaef81d8344..f72c33a2dcfb 100644 --- a/arch/arm/kernel/probes-arm.c +++ b/arch/arm/probes/decode-arm.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/probes-arm.c | 2 | * |
3 | * arch/arm/probes/decode-arm.c | ||
3 | * | 4 | * |
4 | * Some code moved here from arch/arm/kernel/kprobes-arm.c | 5 | * Some code moved here from arch/arm/kernel/kprobes-arm.c |
5 | * | 6 | * |
@@ -20,8 +21,8 @@ | |||
20 | #include <linux/stddef.h> | 21 | #include <linux/stddef.h> |
21 | #include <linux/ptrace.h> | 22 | #include <linux/ptrace.h> |
22 | 23 | ||
23 | #include "probes.h" | 24 | #include "decode.h" |
24 | #include "probes-arm.h" | 25 | #include "decode-arm.h" |
25 | 26 | ||
26 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) | 27 | #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) |
27 | 28 | ||
@@ -369,17 +370,17 @@ static const union decode_item arm_cccc_001x_table[] = { | |||
369 | 370 | ||
370 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ | 371 | /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ |
371 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ | 372 | /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ |
372 | DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_DATA_PROCESSING_IMM, | 373 | DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_MOV_HALFWORD, |
373 | REGS(0, NOPC, 0, 0, 0)), | 374 | REGS(0, NOPC, 0, 0, 0)), |
374 | 375 | ||
375 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ | 376 | /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ |
376 | DECODE_OR (0x0fff00ff, 0x03200001), | 377 | DECODE_OR (0x0fff00ff, 0x03200001), |
377 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ | 378 | /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ |
378 | DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_EMULATE_NONE), | 379 | DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_SEV), |
379 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ | 380 | /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ |
380 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ | 381 | /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ |
381 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ | 382 | /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ |
382 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_SIMULATE_NOP), | 383 | DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_WFE), |
383 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ | 384 | /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ |
384 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ | 385 | /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ |
385 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ | 386 | /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ |
@@ -725,10 +726,11 @@ static void __kprobes arm_singlestep(probes_opcode_t insn, | |||
725 | */ | 726 | */ |
726 | enum probes_insn __kprobes | 727 | enum probes_insn __kprobes |
727 | arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 728 | arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
728 | bool emulate, const union decode_action *actions) | 729 | bool emulate, const union decode_action *actions, |
730 | const struct decode_checker *checkers[]) | ||
729 | { | 731 | { |
730 | asi->insn_singlestep = arm_singlestep; | 732 | asi->insn_singlestep = arm_singlestep; |
731 | asi->insn_check_cc = probes_condition_checks[insn>>28]; | 733 | asi->insn_check_cc = probes_condition_checks[insn>>28]; |
732 | return probes_decode_insn(insn, asi, probes_decode_arm_table, false, | 734 | return probes_decode_insn(insn, asi, probes_decode_arm_table, false, |
733 | emulate, actions); | 735 | emulate, actions, checkers); |
734 | } | 736 | } |
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/probes/decode-arm.h index ace6572f6e26..b3b80f6d414b 100644 --- a/arch/arm/kernel/probes-arm.h +++ b/arch/arm/probes/decode-arm.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/probes-arm.h | 2 | * arch/arm/probes/decode-arm.h |
3 | * | 3 | * |
4 | * Copyright 2013 Linaro Ltd. | 4 | * Copyright 2013 Linaro Ltd. |
5 | * Written by: David A. Long | 5 | * Written by: David A. Long |
@@ -15,9 +15,9 @@ | |||
15 | #ifndef _ARM_KERNEL_PROBES_ARM_H | 15 | #ifndef _ARM_KERNEL_PROBES_ARM_H |
16 | #define _ARM_KERNEL_PROBES_ARM_H | 16 | #define _ARM_KERNEL_PROBES_ARM_H |
17 | 17 | ||
18 | #include "decode.h" | ||
19 | |||
18 | enum probes_arm_action { | 20 | enum probes_arm_action { |
19 | PROBES_EMULATE_NONE, | ||
20 | PROBES_SIMULATE_NOP, | ||
21 | PROBES_PRELOAD_IMM, | 21 | PROBES_PRELOAD_IMM, |
22 | PROBES_PRELOAD_REG, | 22 | PROBES_PRELOAD_REG, |
23 | PROBES_BRANCH_IMM, | 23 | PROBES_BRANCH_IMM, |
@@ -68,6 +68,7 @@ extern const union decode_item probes_decode_arm_table[]; | |||
68 | 68 | ||
69 | enum probes_insn arm_probes_decode_insn(probes_opcode_t, | 69 | enum probes_insn arm_probes_decode_insn(probes_opcode_t, |
70 | struct arch_probes_insn *, bool emulate, | 70 | struct arch_probes_insn *, bool emulate, |
71 | const union decode_action *actions); | 71 | const union decode_action *actions, |
72 | const struct decode_checker *checkers[]); | ||
72 | 73 | ||
73 | #endif | 74 | #endif |
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/probes/decode-thumb.c index 4131351e812f..985e7dd4cac6 100644 --- a/arch/arm/kernel/probes-thumb.c +++ b/arch/arm/probes/decode-thumb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/probes-thumb.c | 2 | * arch/arm/probes/decode-thumb.c |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
5 | * | 5 | * |
@@ -12,8 +12,8 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | 14 | ||
15 | #include "probes.h" | 15 | #include "decode.h" |
16 | #include "probes-thumb.h" | 16 | #include "decode-thumb.h" |
17 | 17 | ||
18 | 18 | ||
19 | static const union decode_item t32_table_1110_100x_x0xx[] = { | 19 | static const union decode_item t32_table_1110_100x_x0xx[] = { |
@@ -863,20 +863,22 @@ static void __kprobes thumb32_singlestep(probes_opcode_t opcode, | |||
863 | 863 | ||
864 | enum probes_insn __kprobes | 864 | enum probes_insn __kprobes |
865 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 865 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
866 | bool emulate, const union decode_action *actions) | 866 | bool emulate, const union decode_action *actions, |
867 | const struct decode_checker *checkers[]) | ||
867 | { | 868 | { |
868 | asi->insn_singlestep = thumb16_singlestep; | 869 | asi->insn_singlestep = thumb16_singlestep; |
869 | asi->insn_check_cc = thumb_check_cc; | 870 | asi->insn_check_cc = thumb_check_cc; |
870 | return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, | 871 | return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, |
871 | emulate, actions); | 872 | emulate, actions, checkers); |
872 | } | 873 | } |
873 | 874 | ||
874 | enum probes_insn __kprobes | 875 | enum probes_insn __kprobes |
875 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 876 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
876 | bool emulate, const union decode_action *actions) | 877 | bool emulate, const union decode_action *actions, |
878 | const struct decode_checker *checkers[]) | ||
877 | { | 879 | { |
878 | asi->insn_singlestep = thumb32_singlestep; | 880 | asi->insn_singlestep = thumb32_singlestep; |
879 | asi->insn_check_cc = thumb_check_cc; | 881 | asi->insn_check_cc = thumb_check_cc; |
880 | return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, | 882 | return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, |
881 | emulate, actions); | 883 | emulate, actions, checkers); |
882 | } | 884 | } |
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/probes/decode-thumb.h index 7c6f6ebe514f..8457add0a2d8 100644 --- a/arch/arm/kernel/probes-thumb.h +++ b/arch/arm/probes/decode-thumb.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/probes-thumb.h | 2 | * arch/arm/probes/decode-thumb.h |
3 | * | 3 | * |
4 | * Copyright 2013 Linaro Ltd. | 4 | * Copyright 2013 Linaro Ltd. |
5 | * Written by: David A. Long | 5 | * Written by: David A. Long |
@@ -15,6 +15,8 @@ | |||
15 | #ifndef _ARM_KERNEL_PROBES_THUMB_H | 15 | #ifndef _ARM_KERNEL_PROBES_THUMB_H |
16 | #define _ARM_KERNEL_PROBES_THUMB_H | 16 | #define _ARM_KERNEL_PROBES_THUMB_H |
17 | 17 | ||
18 | #include "decode.h" | ||
19 | |||
18 | /* | 20 | /* |
19 | * True if current instruction is in an IT block. | 21 | * True if current instruction is in an IT block. |
20 | */ | 22 | */ |
@@ -89,9 +91,11 @@ extern const union decode_item probes_decode_thumb16_table[]; | |||
89 | 91 | ||
90 | enum probes_insn __kprobes | 92 | enum probes_insn __kprobes |
91 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 93 | thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
92 | bool emulate, const union decode_action *actions); | 94 | bool emulate, const union decode_action *actions, |
95 | const struct decode_checker *checkers[]); | ||
93 | enum probes_insn __kprobes | 96 | enum probes_insn __kprobes |
94 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 97 | thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
95 | bool emulate, const union decode_action *actions); | 98 | bool emulate, const union decode_action *actions, |
99 | const struct decode_checker *checkers[]); | ||
96 | 100 | ||
97 | #endif | 101 | #endif |
diff --git a/arch/arm/kernel/probes.c b/arch/arm/probes/decode.c index a8ab540d7e73..880ebe0cdf19 100644 --- a/arch/arm/kernel/probes.c +++ b/arch/arm/probes/decode.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/probes.c | 2 | * arch/arm/probes/decode.c |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
5 | * | 5 | * |
@@ -17,7 +17,7 @@ | |||
17 | #include <asm/ptrace.h> | 17 | #include <asm/ptrace.h> |
18 | #include <linux/bug.h> | 18 | #include <linux/bug.h> |
19 | 19 | ||
20 | #include "probes.h" | 20 | #include "decode.h" |
21 | 21 | ||
22 | 22 | ||
23 | #ifndef find_str_pc_offset | 23 | #ifndef find_str_pc_offset |
@@ -342,6 +342,31 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | |||
342 | [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) | 342 | [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) |
343 | }; | 343 | }; |
344 | 344 | ||
345 | static int run_checkers(const struct decode_checker *checkers[], | ||
346 | int action, probes_opcode_t insn, | ||
347 | struct arch_probes_insn *asi, | ||
348 | const struct decode_header *h) | ||
349 | { | ||
350 | const struct decode_checker **p; | ||
351 | |||
352 | if (!checkers) | ||
353 | return INSN_GOOD; | ||
354 | |||
355 | p = checkers; | ||
356 | while (*p != NULL) { | ||
357 | int retval; | ||
358 | probes_check_t *checker_func = (*p)[action].checker; | ||
359 | |||
360 | retval = INSN_GOOD; | ||
361 | if (checker_func) | ||
362 | retval = checker_func(insn, asi, h); | ||
363 | if (retval == INSN_REJECTED) | ||
364 | return retval; | ||
365 | p++; | ||
366 | } | ||
367 | return INSN_GOOD; | ||
368 | } | ||
369 | |||
345 | /* | 370 | /* |
346 | * probes_decode_insn operates on data tables in order to decode an ARM | 371 | * probes_decode_insn operates on data tables in order to decode an ARM |
347 | * architecture instruction onto which a kprobe has been placed. | 372 | * architecture instruction onto which a kprobe has been placed. |
@@ -388,11 +413,34 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { | |||
388 | int __kprobes | 413 | int __kprobes |
389 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 414 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
390 | const union decode_item *table, bool thumb, | 415 | const union decode_item *table, bool thumb, |
391 | bool emulate, const union decode_action *actions) | 416 | bool emulate, const union decode_action *actions, |
417 | const struct decode_checker *checkers[]) | ||
392 | { | 418 | { |
393 | const struct decode_header *h = (struct decode_header *)table; | 419 | const struct decode_header *h = (struct decode_header *)table; |
394 | const struct decode_header *next; | 420 | const struct decode_header *next; |
395 | bool matched = false; | 421 | bool matched = false; |
422 | /* | ||
423 | * @insn can be modified by decode_regs. Save its original | ||
424 | * value for checkers. | ||
425 | */ | ||
426 | probes_opcode_t origin_insn = insn; | ||
427 | |||
428 | /* | ||
429 | * stack_space is initialized to 0 here. Checker functions | ||
430 | * should update is value if they find this is a stack store | ||
431 | * instruction: positive value means bytes of stack usage, | ||
432 | * negitive value means unable to determine stack usage | ||
433 | * statically. For instruction doesn't store to stack, checker | ||
434 | * do nothing with it. | ||
435 | */ | ||
436 | asi->stack_space = 0; | ||
437 | |||
438 | /* | ||
439 | * Similarly to stack_space, register_usage_flags is filled by | ||
440 | * checkers. Its default value is set to ~0, which is 'all | ||
441 | * registers are used', to prevent any potential optimization. | ||
442 | */ | ||
443 | asi->register_usage_flags = ~0UL; | ||
396 | 444 | ||
397 | if (emulate) | 445 | if (emulate) |
398 | insn = prepare_emulated_insn(insn, asi, thumb); | 446 | insn = prepare_emulated_insn(insn, asi, thumb); |
@@ -422,24 +470,41 @@ probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | |||
422 | } | 470 | } |
423 | 471 | ||
424 | case DECODE_TYPE_CUSTOM: { | 472 | case DECODE_TYPE_CUSTOM: { |
473 | int err; | ||
425 | struct decode_custom *d = (struct decode_custom *)h; | 474 | struct decode_custom *d = (struct decode_custom *)h; |
426 | return actions[d->decoder.action].decoder(insn, asi, h); | 475 | int action = d->decoder.action; |
476 | |||
477 | err = run_checkers(checkers, action, origin_insn, asi, h); | ||
478 | if (err == INSN_REJECTED) | ||
479 | return INSN_REJECTED; | ||
480 | return actions[action].decoder(insn, asi, h); | ||
427 | } | 481 | } |
428 | 482 | ||
429 | case DECODE_TYPE_SIMULATE: { | 483 | case DECODE_TYPE_SIMULATE: { |
484 | int err; | ||
430 | struct decode_simulate *d = (struct decode_simulate *)h; | 485 | struct decode_simulate *d = (struct decode_simulate *)h; |
431 | asi->insn_handler = actions[d->handler.action].handler; | 486 | int action = d->handler.action; |
487 | |||
488 | err = run_checkers(checkers, action, origin_insn, asi, h); | ||
489 | if (err == INSN_REJECTED) | ||
490 | return INSN_REJECTED; | ||
491 | asi->insn_handler = actions[action].handler; | ||
432 | return INSN_GOOD_NO_SLOT; | 492 | return INSN_GOOD_NO_SLOT; |
433 | } | 493 | } |
434 | 494 | ||
435 | case DECODE_TYPE_EMULATE: { | 495 | case DECODE_TYPE_EMULATE: { |
496 | int err; | ||
436 | struct decode_emulate *d = (struct decode_emulate *)h; | 497 | struct decode_emulate *d = (struct decode_emulate *)h; |
498 | int action = d->handler.action; | ||
499 | |||
500 | err = run_checkers(checkers, action, origin_insn, asi, h); | ||
501 | if (err == INSN_REJECTED) | ||
502 | return INSN_REJECTED; | ||
437 | 503 | ||
438 | if (!emulate) | 504 | if (!emulate) |
439 | return actions[d->handler.action].decoder(insn, | 505 | return actions[action].decoder(insn, asi, h); |
440 | asi, h); | ||
441 | 506 | ||
442 | asi->insn_handler = actions[d->handler.action].handler; | 507 | asi->insn_handler = actions[action].handler; |
443 | set_emulated_insn(insn, asi, thumb); | 508 | set_emulated_insn(insn, asi, thumb); |
444 | return INSN_GOOD; | 509 | return INSN_GOOD; |
445 | } | 510 | } |
diff --git a/arch/arm/kernel/probes.h b/arch/arm/probes/decode.h index dba9f2466a93..f9b08ba7fe73 100644 --- a/arch/arm/kernel/probes.h +++ b/arch/arm/probes/decode.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/probes.h | 2 | * arch/arm/probes/decode.h |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
5 | * | 5 | * |
@@ -314,6 +314,14 @@ union decode_action { | |||
314 | probes_custom_decode_t *decoder; | 314 | probes_custom_decode_t *decoder; |
315 | }; | 315 | }; |
316 | 316 | ||
317 | typedef enum probes_insn (probes_check_t)(probes_opcode_t, | ||
318 | struct arch_probes_insn *, | ||
319 | const struct decode_header *); | ||
320 | |||
321 | struct decode_checker { | ||
322 | probes_check_t *checker; | ||
323 | }; | ||
324 | |||
317 | #define DECODE_END \ | 325 | #define DECODE_END \ |
318 | {.bits = DECODE_TYPE_END} | 326 | {.bits = DECODE_TYPE_END} |
319 | 327 | ||
@@ -402,6 +410,7 @@ probes_insn_handler_t probes_emulate_none; | |||
402 | int __kprobes | 410 | int __kprobes |
403 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, | 411 | probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, |
404 | const union decode_item *table, bool thumb, bool emulate, | 412 | const union decode_item *table, bool thumb, bool emulate, |
405 | const union decode_action *actions); | 413 | const union decode_action *actions, |
414 | const struct decode_checker **checkers); | ||
406 | 415 | ||
407 | #endif | 416 | #endif |
diff --git a/arch/arm/probes/kprobes/Makefile b/arch/arm/probes/kprobes/Makefile new file mode 100644 index 000000000000..76a36bf102b7 --- /dev/null +++ b/arch/arm/probes/kprobes/Makefile | |||
@@ -0,0 +1,12 @@ | |||
1 | obj-$(CONFIG_KPROBES) += core.o actions-common.o checkers-common.o | ||
2 | obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o | ||
3 | test-kprobes-objs := test-core.o | ||
4 | |||
5 | ifdef CONFIG_THUMB2_KERNEL | ||
6 | obj-$(CONFIG_KPROBES) += actions-thumb.o checkers-thumb.o | ||
7 | test-kprobes-objs += test-thumb.o | ||
8 | else | ||
9 | obj-$(CONFIG_KPROBES) += actions-arm.o checkers-arm.o | ||
10 | obj-$(CONFIG_OPTPROBES) += opt-arm.o | ||
11 | test-kprobes-objs += test-arm.o | ||
12 | endif | ||
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/probes/kprobes/actions-arm.c index ac300c60d656..b9056d649607 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/probes/kprobes/actions-arm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/kprobes-decode.c | 2 | * arch/arm/probes/kprobes/actions-arm.c |
3 | * | 3 | * |
4 | * Copyright (C) 2006, 2007 Motorola Inc. | 4 | * Copyright (C) 2006, 2007 Motorola Inc. |
5 | * | 5 | * |
@@ -62,8 +62,9 @@ | |||
62 | #include <linux/kprobes.h> | 62 | #include <linux/kprobes.h> |
63 | #include <linux/ptrace.h> | 63 | #include <linux/ptrace.h> |
64 | 64 | ||
65 | #include "kprobes.h" | 65 | #include "../decode-arm.h" |
66 | #include "probes-arm.h" | 66 | #include "core.h" |
67 | #include "checkers.h" | ||
67 | 68 | ||
68 | #if __LINUX_ARM_ARCH__ >= 6 | 69 | #if __LINUX_ARM_ARCH__ >= 6 |
69 | #define BLX(reg) "blx "reg" \n\t" | 70 | #define BLX(reg) "blx "reg" \n\t" |
@@ -302,8 +303,6 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn, | |||
302 | } | 303 | } |
303 | 304 | ||
304 | const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { | 305 | const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { |
305 | [PROBES_EMULATE_NONE] = {.handler = probes_emulate_none}, | ||
306 | [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, | ||
307 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, | 306 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, |
308 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, | 307 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, |
309 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, | 308 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, |
@@ -341,3 +340,5 @@ const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { | |||
341 | [PROBES_BRANCH] = {.handler = simulate_bbl}, | 340 | [PROBES_BRANCH] = {.handler = simulate_bbl}, |
342 | [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} | 341 | [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} |
343 | }; | 342 | }; |
343 | |||
344 | const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL}; | ||
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/probes/kprobes/actions-common.c index 0bf5d64eba1d..bd20a71cd34a 100644 --- a/arch/arm/kernel/kprobes-common.c +++ b/arch/arm/probes/kprobes/actions-common.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/kprobes-common.c | 2 | * arch/arm/probes/kprobes/actions-common.c |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
5 | * | 5 | * |
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/kprobes.h> | 15 | #include <linux/kprobes.h> |
16 | #include <asm/opcodes.h> | 16 | #include <asm/opcodes.h> |
17 | 17 | ||
18 | #include "kprobes.h" | 18 | #include "core.h" |
19 | 19 | ||
20 | 20 | ||
21 | static void __kprobes simulate_ldm1stm1(probes_opcode_t insn, | 21 | static void __kprobes simulate_ldm1stm1(probes_opcode_t insn, |
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/probes/kprobes/actions-thumb.c index 9495d7f3516f..07cfd9bef340 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/probes/kprobes/actions-thumb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/kprobes-thumb.c | 2 | * arch/arm/probes/kprobes/actions-thumb.c |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
5 | * | 5 | * |
@@ -13,8 +13,9 @@ | |||
13 | #include <linux/ptrace.h> | 13 | #include <linux/ptrace.h> |
14 | #include <linux/kprobes.h> | 14 | #include <linux/kprobes.h> |
15 | 15 | ||
16 | #include "kprobes.h" | 16 | #include "../decode-thumb.h" |
17 | #include "probes-thumb.h" | 17 | #include "core.h" |
18 | #include "checkers.h" | ||
18 | 19 | ||
19 | /* These emulation encodings are functionally equivalent... */ | 20 | /* These emulation encodings are functionally equivalent... */ |
20 | #define t32_emulate_rd8rn16rm0ra12_noflags \ | 21 | #define t32_emulate_rd8rn16rm0ra12_noflags \ |
@@ -664,3 +665,6 @@ const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = { | |||
664 | [PROBES_T32_MUL_ADD_LONG] = { | 665 | [PROBES_T32_MUL_ADD_LONG] = { |
665 | .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, | 666 | .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, |
666 | }; | 667 | }; |
668 | |||
669 | const struct decode_checker *kprobes_t32_checkers[] = {t32_stack_checker, NULL}; | ||
670 | const struct decode_checker *kprobes_t16_checkers[] = {t16_stack_checker, NULL}; | ||
diff --git a/arch/arm/probes/kprobes/checkers-arm.c b/arch/arm/probes/kprobes/checkers-arm.c new file mode 100644 index 000000000000..7b9817333b68 --- /dev/null +++ b/arch/arm/probes/kprobes/checkers-arm.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * arch/arm/probes/kprobes/checkers-arm.c | ||
3 | * | ||
4 | * Copyright (C) 2014 Huawei Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include "../decode.h" | ||
18 | #include "../decode-arm.h" | ||
19 | #include "checkers.h" | ||
20 | |||
21 | static enum probes_insn __kprobes arm_check_stack(probes_opcode_t insn, | ||
22 | struct arch_probes_insn *asi, | ||
23 | const struct decode_header *h) | ||
24 | { | ||
25 | /* | ||
26 | * PROBES_LDRSTRD, PROBES_LDMSTM, PROBES_STORE, | ||
27 | * PROBES_STORE_EXTRA may get here. Simply mark all normal | ||
28 | * insns as STACK_USE_NONE. | ||
29 | */ | ||
30 | static const union decode_item table[] = { | ||
31 | /* | ||
32 | * 'STR{,D,B,H}, Rt, [Rn, Rm]' should be marked as UNKNOWN | ||
33 | * if Rn or Rm is SP. | ||
34 | * x | ||
35 | * STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx | ||
36 | * STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx | ||
37 | */ | ||
38 | DECODE_OR (0x0e10000f, 0x0600000d), | ||
39 | DECODE_OR (0x0e1f0000, 0x060d0000), | ||
40 | |||
41 | /* | ||
42 | * x | ||
43 | * STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx | ||
44 | * STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx | ||
45 | */ | ||
46 | DECODE_OR (0x0e5000bf, 0x000000bd), | ||
47 | DECODE_CUSTOM (0x0e5f00b0, 0x000d00b0, STACK_USE_UNKNOWN), | ||
48 | |||
49 | /* | ||
50 | * For PROBES_LDMSTM, only stmdx sp, [...] need to examine | ||
51 | * | ||
52 | * Bit B/A (bit 24) encodes arithmetic operation order. 1 means | ||
53 | * before, 0 means after. | ||
54 | * Bit I/D (bit 23) encodes arithmetic operation. 1 means | ||
55 | * increment, 0 means decrement. | ||
56 | * | ||
57 | * So: | ||
58 | * B I | ||
59 | * / / | ||
60 | * A D | Rn | | ||
61 | * STMDX SP, [...] cccc 100x 00x0 xxxx xxxx xxxx xxxx xxxx | ||
62 | */ | ||
63 | DECODE_CUSTOM (0x0edf0000, 0x080d0000, STACK_USE_STMDX), | ||
64 | |||
65 | /* P U W | Rn | Rt | imm12 |*/ | ||
66 | /* STR (immediate) cccc 010x x0x0 1101 xxxx xxxx xxxx xxxx */ | ||
67 | /* STRB (immediate) cccc 010x x1x0 1101 xxxx xxxx xxxx xxxx */ | ||
68 | /* P U W | Rn | Rt |imm4| |imm4|*/ | ||
69 | /* STRD (immediate) cccc 000x x1x0 1101 xxxx xxxx 1111 xxxx */ | ||
70 | /* STRH (immediate) cccc 000x x1x0 1101 xxxx xxxx 1011 xxxx */ | ||
71 | /* | ||
72 | * index = (P == '1'); add = (U == '1'). | ||
73 | * Above insns with: | ||
74 | * index == 0 (str{,d,h} rx, [sp], #+/-imm) or | ||
75 | * add == 1 (str{,d,h} rx, [sp, #+<imm>]) | ||
76 | * should be STACK_USE_NONE. | ||
77 | * Only str{,b,d,h} rx,[sp,#-n] (P == 1 and U == 0) are | ||
78 | * required to be examined. | ||
79 | */ | ||
80 | /* STR{,B} Rt,[SP,#-n] cccc 0101 0xx0 1101 xxxx xxxx xxxx xxxx */ | ||
81 | DECODE_CUSTOM (0x0f9f0000, 0x050d0000, STACK_USE_FIXED_XXX), | ||
82 | |||
83 | /* STR{D,H} Rt,[SP,#-n] cccc 0001 01x0 1101 xxxx xxxx 1x11 xxxx */ | ||
84 | DECODE_CUSTOM (0x0fdf00b0, 0x014d00b0, STACK_USE_FIXED_X0X), | ||
85 | |||
86 | /* fall through */ | ||
87 | DECODE_CUSTOM (0, 0, STACK_USE_NONE), | ||
88 | DECODE_END | ||
89 | }; | ||
90 | |||
91 | return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL); | ||
92 | } | ||
93 | |||
94 | const struct decode_checker arm_stack_checker[NUM_PROBES_ARM_ACTIONS] = { | ||
95 | [PROBES_LDRSTRD] = {.checker = arm_check_stack}, | ||
96 | [PROBES_STORE_EXTRA] = {.checker = arm_check_stack}, | ||
97 | [PROBES_STORE] = {.checker = arm_check_stack}, | ||
98 | [PROBES_LDMSTM] = {.checker = arm_check_stack}, | ||
99 | }; | ||
100 | |||
101 | static enum probes_insn __kprobes arm_check_regs_nouse(probes_opcode_t insn, | ||
102 | struct arch_probes_insn *asi, | ||
103 | const struct decode_header *h) | ||
104 | { | ||
105 | asi->register_usage_flags = 0; | ||
106 | return INSN_GOOD; | ||
107 | } | ||
108 | |||
109 | static enum probes_insn arm_check_regs_normal(probes_opcode_t insn, | ||
110 | struct arch_probes_insn *asi, | ||
111 | const struct decode_header *h) | ||
112 | { | ||
113 | u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; | ||
114 | int i; | ||
115 | |||
116 | asi->register_usage_flags = 0; | ||
117 | for (i = 0; i < 5; regs >>= 4, insn >>= 4, i++) | ||
118 | if (regs & 0xf) | ||
119 | asi->register_usage_flags |= 1 << (insn & 0xf); | ||
120 | |||
121 | return INSN_GOOD; | ||
122 | } | ||
123 | |||
124 | |||
125 | static enum probes_insn arm_check_regs_ldmstm(probes_opcode_t insn, | ||
126 | struct arch_probes_insn *asi, | ||
127 | const struct decode_header *h) | ||
128 | { | ||
129 | unsigned int reglist = insn & 0xffff; | ||
130 | unsigned int rn = (insn >> 16) & 0xf; | ||
131 | asi->register_usage_flags = reglist | (1 << rn); | ||
132 | return INSN_GOOD; | ||
133 | } | ||
134 | |||
135 | static enum probes_insn arm_check_regs_mov_ip_sp(probes_opcode_t insn, | ||
136 | struct arch_probes_insn *asi, | ||
137 | const struct decode_header *h) | ||
138 | { | ||
139 | /* Instruction is 'mov ip, sp' i.e. 'mov r12, r13' */ | ||
140 | asi->register_usage_flags = (1 << 12) | (1<< 13); | ||
141 | return INSN_GOOD; | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * | Rn |Rt/d| | Rm | | ||
146 | * LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx | ||
147 | * STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx | ||
148 | * | Rn |Rt/d| |imm4L| | ||
149 | * LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx | ||
150 | * STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx | ||
151 | * | ||
152 | * Such instructions access Rt/d and its next register, so different | ||
153 | * from others, a specific checker is required to handle this extra | ||
154 | * implicit register usage. | ||
155 | */ | ||
156 | static enum probes_insn arm_check_regs_ldrdstrd(probes_opcode_t insn, | ||
157 | struct arch_probes_insn *asi, | ||
158 | const struct decode_header *h) | ||
159 | { | ||
160 | int rdt = (insn >> 12) & 0xf; | ||
161 | arm_check_regs_normal(insn, asi, h); | ||
162 | asi->register_usage_flags |= 1 << (rdt + 1); | ||
163 | return INSN_GOOD; | ||
164 | } | ||
165 | |||
166 | |||
167 | const struct decode_checker arm_regs_checker[NUM_PROBES_ARM_ACTIONS] = { | ||
168 | [PROBES_MRS] = {.checker = arm_check_regs_normal}, | ||
169 | [PROBES_SATURATING_ARITHMETIC] = {.checker = arm_check_regs_normal}, | ||
170 | [PROBES_MUL1] = {.checker = arm_check_regs_normal}, | ||
171 | [PROBES_MUL2] = {.checker = arm_check_regs_normal}, | ||
172 | [PROBES_MUL_ADD_LONG] = {.checker = arm_check_regs_normal}, | ||
173 | [PROBES_MUL_ADD] = {.checker = arm_check_regs_normal}, | ||
174 | [PROBES_LOAD] = {.checker = arm_check_regs_normal}, | ||
175 | [PROBES_LOAD_EXTRA] = {.checker = arm_check_regs_normal}, | ||
176 | [PROBES_STORE] = {.checker = arm_check_regs_normal}, | ||
177 | [PROBES_STORE_EXTRA] = {.checker = arm_check_regs_normal}, | ||
178 | [PROBES_DATA_PROCESSING_REG] = {.checker = arm_check_regs_normal}, | ||
179 | [PROBES_DATA_PROCESSING_IMM] = {.checker = arm_check_regs_normal}, | ||
180 | [PROBES_SEV] = {.checker = arm_check_regs_nouse}, | ||
181 | [PROBES_WFE] = {.checker = arm_check_regs_nouse}, | ||
182 | [PROBES_SATURATE] = {.checker = arm_check_regs_normal}, | ||
183 | [PROBES_REV] = {.checker = arm_check_regs_normal}, | ||
184 | [PROBES_MMI] = {.checker = arm_check_regs_normal}, | ||
185 | [PROBES_PACK] = {.checker = arm_check_regs_normal}, | ||
186 | [PROBES_EXTEND] = {.checker = arm_check_regs_normal}, | ||
187 | [PROBES_EXTEND_ADD] = {.checker = arm_check_regs_normal}, | ||
188 | [PROBES_BITFIELD] = {.checker = arm_check_regs_normal}, | ||
189 | [PROBES_LDMSTM] = {.checker = arm_check_regs_ldmstm}, | ||
190 | [PROBES_MOV_IP_SP] = {.checker = arm_check_regs_mov_ip_sp}, | ||
191 | [PROBES_LDRSTRD] = {.checker = arm_check_regs_ldrdstrd}, | ||
192 | }; | ||
diff --git a/arch/arm/probes/kprobes/checkers-common.c b/arch/arm/probes/kprobes/checkers-common.c new file mode 100644 index 000000000000..971119c29474 --- /dev/null +++ b/arch/arm/probes/kprobes/checkers-common.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * arch/arm/probes/kprobes/checkers-common.c | ||
3 | * | ||
4 | * Copyright (C) 2014 Huawei Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include "../decode.h" | ||
18 | #include "../decode-arm.h" | ||
19 | #include "checkers.h" | ||
20 | |||
21 | enum probes_insn checker_stack_use_none(probes_opcode_t insn, | ||
22 | struct arch_probes_insn *asi, | ||
23 | const struct decode_header *h) | ||
24 | { | ||
25 | asi->stack_space = 0; | ||
26 | return INSN_GOOD_NO_SLOT; | ||
27 | } | ||
28 | |||
29 | enum probes_insn checker_stack_use_unknown(probes_opcode_t insn, | ||
30 | struct arch_probes_insn *asi, | ||
31 | const struct decode_header *h) | ||
32 | { | ||
33 | asi->stack_space = -1; | ||
34 | return INSN_GOOD_NO_SLOT; | ||
35 | } | ||
36 | |||
37 | #ifdef CONFIG_THUMB2_KERNEL | ||
38 | enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn, | ||
39 | struct arch_probes_insn *asi, | ||
40 | const struct decode_header *h) | ||
41 | { | ||
42 | int imm = insn & 0xff; | ||
43 | asi->stack_space = imm; | ||
44 | return INSN_GOOD_NO_SLOT; | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * Different from other insn uses imm8, the real addressing offset of | ||
49 | * STRD in T32 encoding should be imm8 * 4. See ARMARM description. | ||
50 | */ | ||
51 | enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, | ||
52 | struct arch_probes_insn *asi, | ||
53 | const struct decode_header *h) | ||
54 | { | ||
55 | int imm = insn & 0xff; | ||
56 | asi->stack_space = imm << 2; | ||
57 | return INSN_GOOD_NO_SLOT; | ||
58 | } | ||
59 | #else | ||
60 | enum probes_insn checker_stack_use_imm_x0x(probes_opcode_t insn, | ||
61 | struct arch_probes_insn *asi, | ||
62 | const struct decode_header *h) | ||
63 | { | ||
64 | int imm = ((insn & 0xf00) >> 4) + (insn & 0xf); | ||
65 | asi->stack_space = imm; | ||
66 | return INSN_GOOD_NO_SLOT; | ||
67 | } | ||
68 | #endif | ||
69 | |||
70 | enum probes_insn checker_stack_use_imm_xxx(probes_opcode_t insn, | ||
71 | struct arch_probes_insn *asi, | ||
72 | const struct decode_header *h) | ||
73 | { | ||
74 | int imm = insn & 0xfff; | ||
75 | asi->stack_space = imm; | ||
76 | return INSN_GOOD_NO_SLOT; | ||
77 | } | ||
78 | |||
79 | enum probes_insn checker_stack_use_stmdx(probes_opcode_t insn, | ||
80 | struct arch_probes_insn *asi, | ||
81 | const struct decode_header *h) | ||
82 | { | ||
83 | unsigned int reglist = insn & 0xffff; | ||
84 | int pbit = insn & (1 << 24); | ||
85 | asi->stack_space = (hweight32(reglist) - (!pbit ? 1 : 0)) * 4; | ||
86 | |||
87 | return INSN_GOOD_NO_SLOT; | ||
88 | } | ||
89 | |||
90 | const union decode_action stack_check_actions[] = { | ||
91 | [STACK_USE_NONE] = {.decoder = checker_stack_use_none}, | ||
92 | [STACK_USE_UNKNOWN] = {.decoder = checker_stack_use_unknown}, | ||
93 | #ifdef CONFIG_THUMB2_KERNEL | ||
94 | [STACK_USE_FIXED_0XX] = {.decoder = checker_stack_use_imm_0xx}, | ||
95 | [STACK_USE_T32STRD] = {.decoder = checker_stack_use_t32strd}, | ||
96 | #else | ||
97 | [STACK_USE_FIXED_X0X] = {.decoder = checker_stack_use_imm_x0x}, | ||
98 | #endif | ||
99 | [STACK_USE_FIXED_XXX] = {.decoder = checker_stack_use_imm_xxx}, | ||
100 | [STACK_USE_STMDX] = {.decoder = checker_stack_use_stmdx}, | ||
101 | }; | ||
diff --git a/arch/arm/probes/kprobes/checkers-thumb.c b/arch/arm/probes/kprobes/checkers-thumb.c new file mode 100644 index 000000000000..d608e3b9017a --- /dev/null +++ b/arch/arm/probes/kprobes/checkers-thumb.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * arch/arm/probes/kprobes/checkers-thumb.c | ||
3 | * | ||
4 | * Copyright (C) 2014 Huawei Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include "../decode.h" | ||
18 | #include "../decode-thumb.h" | ||
19 | #include "checkers.h" | ||
20 | |||
21 | static enum probes_insn __kprobes t32_check_stack(probes_opcode_t insn, | ||
22 | struct arch_probes_insn *asi, | ||
23 | const struct decode_header *h) | ||
24 | { | ||
25 | /* | ||
26 | * PROBES_T32_LDMSTM, PROBES_T32_LDRDSTRD and PROBES_T32_LDRSTR | ||
27 | * may get here. Simply mark all normal insns as STACK_USE_NONE. | ||
28 | */ | ||
29 | static const union decode_item table[] = { | ||
30 | |||
31 | /* | ||
32 | * First, filter out all ldr insns to make our life easier. | ||
33 | * Following load insns may come here: | ||
34 | * LDM, LDRD, LDR. | ||
35 | * In T32 encoding, bit 20 is enough for distinguishing | ||
36 | * load and store. All load insns have this bit set, when | ||
37 | * all store insns have this bit clear. | ||
38 | */ | ||
39 | DECODE_CUSTOM (0x00100000, 0x00100000, STACK_USE_NONE), | ||
40 | |||
41 | /* | ||
42 | * Mark all 'STR{,B,H}, Rt, [Rn, Rm]' as STACK_USE_UNKNOWN | ||
43 | * if Rn or Rm is SP. T32 doesn't encode STRD. | ||
44 | */ | ||
45 | /* xx | Rn | Rt | | Rm |*/ | ||
46 | /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ | ||
47 | /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */ | ||
48 | /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */ | ||
49 | /* INVALID INSN 1111 1000 0110 xxxx xxxx 0000 00xx xxxx */ | ||
50 | /* By Introducing INVALID INSN, bit 21 and 22 can be ignored. */ | ||
51 | DECODE_OR (0xff9f0fc0, 0xf80d0000), | ||
52 | DECODE_CUSTOM (0xff900fcf, 0xf800000d, STACK_USE_UNKNOWN), | ||
53 | |||
54 | |||
55 | /* xx | Rn | Rt | PUW| imm8 |*/ | ||
56 | /* STR (imm 8) 1111 1000 0100 1101 xxxx 110x xxxx xxxx */ | ||
57 | /* STRB (imm 8) 1111 1000 0000 1101 xxxx 110x xxxx xxxx */ | ||
58 | /* STRH (imm 8) 1111 1000 0010 1101 xxxx 110x xxxx xxxx */ | ||
59 | /* INVALID INSN 1111 1000 0110 1101 xxxx 110x xxxx xxxx */ | ||
60 | /* Only consider U == 0 and P == 1: strx rx, [sp, #-<imm>] */ | ||
61 | DECODE_CUSTOM (0xff9f0e00, 0xf80d0c00, STACK_USE_FIXED_0XX), | ||
62 | |||
63 | /* For STR{,B,H} (imm 12), offset is always positive, so ignore them. */ | ||
64 | |||
65 | /* P U W | Rn | Rt | Rt2| imm8 |*/ | ||
66 | /* STRD (immediate) 1110 1001 01x0 1101 xxxx xxxx xxxx xxxx */ | ||
67 | /* | ||
68 | * Only consider U == 0 and P == 1. | ||
69 | * Also note that STRD in T32 encoding is special: | ||
70 | * imm = ZeroExtend(imm8:'00', 32) | ||
71 | */ | ||
72 | DECODE_CUSTOM (0xffdf0000, 0xe94d0000, STACK_USE_T32STRD), | ||
73 | |||
74 | /* | Rn | */ | ||
75 | /* STMDB 1110 1001 00x0 1101 xxxx xxxx xxxx xxxx */ | ||
76 | DECODE_CUSTOM (0xffdf0000, 0xe90d0000, STACK_USE_STMDX), | ||
77 | |||
78 | /* fall through */ | ||
79 | DECODE_CUSTOM (0, 0, STACK_USE_NONE), | ||
80 | DECODE_END | ||
81 | }; | ||
82 | |||
83 | return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL); | ||
84 | } | ||
85 | |||
86 | const struct decode_checker t32_stack_checker[NUM_PROBES_T32_ACTIONS] = { | ||
87 | [PROBES_T32_LDMSTM] = {.checker = t32_check_stack}, | ||
88 | [PROBES_T32_LDRDSTRD] = {.checker = t32_check_stack}, | ||
89 | [PROBES_T32_LDRSTR] = {.checker = t32_check_stack}, | ||
90 | }; | ||
91 | |||
92 | /* | ||
93 | * See following comments. This insn must be 'push'. | ||
94 | */ | ||
95 | static enum probes_insn __kprobes t16_check_stack(probes_opcode_t insn, | ||
96 | struct arch_probes_insn *asi, | ||
97 | const struct decode_header *h) | ||
98 | { | ||
99 | unsigned int reglist = insn & 0x1ff; | ||
100 | asi->stack_space = hweight32(reglist) * 4; | ||
101 | return INSN_GOOD; | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * T16 encoding is simple: only the 'push' insn can need extra stack space. | ||
106 | * Other insns, like str, can only use r0-r7 as Rn. | ||
107 | */ | ||
108 | const struct decode_checker t16_stack_checker[NUM_PROBES_T16_ACTIONS] = { | ||
109 | [PROBES_T16_PUSH] = {.checker = t16_check_stack}, | ||
110 | }; | ||
diff --git a/arch/arm/probes/kprobes/checkers.h b/arch/arm/probes/kprobes/checkers.h new file mode 100644 index 000000000000..cf6c9e74d666 --- /dev/null +++ b/arch/arm/probes/kprobes/checkers.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * arch/arm/probes/kprobes/checkers.h | ||
3 | * | ||
4 | * Copyright (C) 2014 Huawei Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | #ifndef _ARM_KERNEL_PROBES_CHECKERS_H | ||
16 | #define _ARM_KERNEL_PROBES_CHECKERS_H | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/types.h> | ||
20 | #include "../decode.h" | ||
21 | |||
22 | extern probes_check_t checker_stack_use_none; | ||
23 | extern probes_check_t checker_stack_use_unknown; | ||
24 | #ifdef CONFIG_THUMB2_KERNEL | ||
25 | extern probes_check_t checker_stack_use_imm_0xx; | ||
26 | #else | ||
27 | extern probes_check_t checker_stack_use_imm_x0x; | ||
28 | #endif | ||
29 | extern probes_check_t checker_stack_use_imm_xxx; | ||
30 | extern probes_check_t checker_stack_use_stmdx; | ||
31 | |||
32 | enum { | ||
33 | STACK_USE_NONE, | ||
34 | STACK_USE_UNKNOWN, | ||
35 | #ifdef CONFIG_THUMB2_KERNEL | ||
36 | STACK_USE_FIXED_0XX, | ||
37 | STACK_USE_T32STRD, | ||
38 | #else | ||
39 | STACK_USE_FIXED_X0X, | ||
40 | #endif | ||
41 | STACK_USE_FIXED_XXX, | ||
42 | STACK_USE_STMDX, | ||
43 | NUM_STACK_USE_TYPES | ||
44 | }; | ||
45 | |||
46 | extern const union decode_action stack_check_actions[]; | ||
47 | |||
48 | #ifndef CONFIG_THUMB2_KERNEL | ||
49 | extern const struct decode_checker arm_stack_checker[]; | ||
50 | extern const struct decode_checker arm_regs_checker[]; | ||
51 | #else | ||
52 | #endif | ||
53 | extern const struct decode_checker t32_stack_checker[]; | ||
54 | extern const struct decode_checker t16_stack_checker[]; | ||
55 | #endif | ||
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/probes/kprobes/core.c index 6d644202c8dc..a4ec240ee7ba 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/probes/kprobes/core.c | |||
@@ -30,11 +30,11 @@ | |||
30 | #include <asm/cacheflush.h> | 30 | #include <asm/cacheflush.h> |
31 | #include <linux/percpu.h> | 31 | #include <linux/percpu.h> |
32 | #include <linux/bug.h> | 32 | #include <linux/bug.h> |
33 | #include <asm/patch.h> | ||
33 | 34 | ||
34 | #include "kprobes.h" | 35 | #include "../decode-arm.h" |
35 | #include "probes-arm.h" | 36 | #include "../decode-thumb.h" |
36 | #include "probes-thumb.h" | 37 | #include "core.h" |
37 | #include "patch.h" | ||
38 | 38 | ||
39 | #define MIN_STACK_SIZE(addr) \ | 39 | #define MIN_STACK_SIZE(addr) \ |
40 | min((unsigned long)MAX_STACK_SIZE, \ | 40 | min((unsigned long)MAX_STACK_SIZE, \ |
@@ -61,6 +61,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
61 | kprobe_decode_insn_t *decode_insn; | 61 | kprobe_decode_insn_t *decode_insn; |
62 | const union decode_action *actions; | 62 | const union decode_action *actions; |
63 | int is; | 63 | int is; |
64 | const struct decode_checker **checkers; | ||
64 | 65 | ||
65 | if (in_exception_text(addr)) | 66 | if (in_exception_text(addr)) |
66 | return -EINVAL; | 67 | return -EINVAL; |
@@ -74,9 +75,11 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
74 | insn = __opcode_thumb32_compose(insn, inst2); | 75 | insn = __opcode_thumb32_compose(insn, inst2); |
75 | decode_insn = thumb32_probes_decode_insn; | 76 | decode_insn = thumb32_probes_decode_insn; |
76 | actions = kprobes_t32_actions; | 77 | actions = kprobes_t32_actions; |
78 | checkers = kprobes_t32_checkers; | ||
77 | } else { | 79 | } else { |
78 | decode_insn = thumb16_probes_decode_insn; | 80 | decode_insn = thumb16_probes_decode_insn; |
79 | actions = kprobes_t16_actions; | 81 | actions = kprobes_t16_actions; |
82 | checkers = kprobes_t16_checkers; | ||
80 | } | 83 | } |
81 | #else /* !CONFIG_THUMB2_KERNEL */ | 84 | #else /* !CONFIG_THUMB2_KERNEL */ |
82 | thumb = false; | 85 | thumb = false; |
@@ -85,12 +88,13 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
85 | insn = __mem_to_opcode_arm(*p->addr); | 88 | insn = __mem_to_opcode_arm(*p->addr); |
86 | decode_insn = arm_probes_decode_insn; | 89 | decode_insn = arm_probes_decode_insn; |
87 | actions = kprobes_arm_actions; | 90 | actions = kprobes_arm_actions; |
91 | checkers = kprobes_arm_checkers; | ||
88 | #endif | 92 | #endif |
89 | 93 | ||
90 | p->opcode = insn; | 94 | p->opcode = insn; |
91 | p->ainsn.insn = tmp_insn; | 95 | p->ainsn.insn = tmp_insn; |
92 | 96 | ||
93 | switch ((*decode_insn)(insn, &p->ainsn, true, actions)) { | 97 | switch ((*decode_insn)(insn, &p->ainsn, true, actions, checkers)) { |
94 | case INSN_REJECTED: /* not supported */ | 98 | case INSN_REJECTED: /* not supported */ |
95 | return -EINVAL; | 99 | return -EINVAL; |
96 | 100 | ||
@@ -111,6 +115,15 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
111 | break; | 115 | break; |
112 | } | 116 | } |
113 | 117 | ||
118 | /* | ||
119 | * Never instrument insn like 'str r0, [sp, +/-r1]'. Also, insn likes | ||
120 | * 'str r0, [sp, #-68]' should also be prohibited. | ||
121 | * See __und_svc. | ||
122 | */ | ||
123 | if ((p->ainsn.stack_space < 0) || | ||
124 | (p->ainsn.stack_space > MAX_STACK_SIZE)) | ||
125 | return -EINVAL; | ||
126 | |||
114 | return 0; | 127 | return 0; |
115 | } | 128 | } |
116 | 129 | ||
@@ -150,19 +163,31 @@ void __kprobes arch_arm_kprobe(struct kprobe *p) | |||
150 | * memory. It is also needed to atomically set the two half-words of a 32-bit | 163 | * memory. It is also needed to atomically set the two half-words of a 32-bit |
151 | * Thumb breakpoint. | 164 | * Thumb breakpoint. |
152 | */ | 165 | */ |
153 | int __kprobes __arch_disarm_kprobe(void *p) | 166 | struct patch { |
154 | { | 167 | void *addr; |
155 | struct kprobe *kp = p; | 168 | unsigned int insn; |
156 | void *addr = (void *)((uintptr_t)kp->addr & ~1); | 169 | }; |
157 | |||
158 | __patch_text(addr, kp->opcode); | ||
159 | 170 | ||
171 | static int __kprobes_remove_breakpoint(void *data) | ||
172 | { | ||
173 | struct patch *p = data; | ||
174 | __patch_text(p->addr, p->insn); | ||
160 | return 0; | 175 | return 0; |
161 | } | 176 | } |
162 | 177 | ||
178 | void __kprobes kprobes_remove_breakpoint(void *addr, unsigned int insn) | ||
179 | { | ||
180 | struct patch p = { | ||
181 | .addr = addr, | ||
182 | .insn = insn, | ||
183 | }; | ||
184 | stop_machine(__kprobes_remove_breakpoint, &p, cpu_online_mask); | ||
185 | } | ||
186 | |||
163 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 187 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
164 | { | 188 | { |
165 | stop_machine(__arch_disarm_kprobe, p, cpu_online_mask); | 189 | kprobes_remove_breakpoint((void *)((uintptr_t)p->addr & ~1), |
190 | p->opcode); | ||
166 | } | 191 | } |
167 | 192 | ||
168 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 193 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/probes/kprobes/core.h index 9a2712ecefc3..ec5d1f20a085 100644 --- a/arch/arm/kernel/kprobes.h +++ b/arch/arm/probes/kprobes/core.h | |||
@@ -19,7 +19,8 @@ | |||
19 | #ifndef _ARM_KERNEL_KPROBES_H | 19 | #ifndef _ARM_KERNEL_KPROBES_H |
20 | #define _ARM_KERNEL_KPROBES_H | 20 | #define _ARM_KERNEL_KPROBES_H |
21 | 21 | ||
22 | #include "probes.h" | 22 | #include <asm/kprobes.h> |
23 | #include "../decode.h" | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * These undefined instructions must be unique and | 26 | * These undefined instructions must be unique and |
@@ -29,6 +30,8 @@ | |||
29 | #define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18 | 30 | #define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18 |
30 | #define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018 | 31 | #define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018 |
31 | 32 | ||
33 | extern void kprobes_remove_breakpoint(void *addr, unsigned int insn); | ||
34 | |||
32 | enum probes_insn __kprobes | 35 | enum probes_insn __kprobes |
33 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, | 36 | kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, |
34 | const struct decode_header *h); | 37 | const struct decode_header *h); |
@@ -36,16 +39,19 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, | |||
36 | typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, | 39 | typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, |
37 | struct arch_probes_insn *, | 40 | struct arch_probes_insn *, |
38 | bool, | 41 | bool, |
39 | const union decode_action *); | 42 | const union decode_action *, |
43 | const struct decode_checker *[]); | ||
40 | 44 | ||
41 | #ifdef CONFIG_THUMB2_KERNEL | 45 | #ifdef CONFIG_THUMB2_KERNEL |
42 | 46 | ||
43 | extern const union decode_action kprobes_t32_actions[]; | 47 | extern const union decode_action kprobes_t32_actions[]; |
44 | extern const union decode_action kprobes_t16_actions[]; | 48 | extern const union decode_action kprobes_t16_actions[]; |
45 | 49 | extern const struct decode_checker *kprobes_t32_checkers[]; | |
50 | extern const struct decode_checker *kprobes_t16_checkers[]; | ||
46 | #else /* !CONFIG_THUMB2_KERNEL */ | 51 | #else /* !CONFIG_THUMB2_KERNEL */ |
47 | 52 | ||
48 | extern const union decode_action kprobes_arm_actions[]; | 53 | extern const union decode_action kprobes_arm_actions[]; |
54 | extern const struct decode_checker *kprobes_arm_checkers[]; | ||
49 | 55 | ||
50 | #endif | 56 | #endif |
51 | 57 | ||
diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c new file mode 100644 index 000000000000..bcdecc25461b --- /dev/null +++ b/arch/arm/probes/kprobes/opt-arm.c | |||
@@ -0,0 +1,370 @@ | |||
1 | /* | ||
2 | * Kernel Probes Jump Optimization (Optprobes) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | * | ||
18 | * Copyright (C) IBM Corporation, 2002, 2004 | ||
19 | * Copyright (C) Hitachi Ltd., 2012 | ||
20 | * Copyright (C) Huawei Inc., 2014 | ||
21 | */ | ||
22 | |||
23 | #include <linux/kprobes.h> | ||
24 | #include <linux/jump_label.h> | ||
25 | #include <asm/kprobes.h> | ||
26 | #include <asm/cacheflush.h> | ||
27 | /* for arm_gen_branch */ | ||
28 | #include <asm/insn.h> | ||
29 | /* for patch_text */ | ||
30 | #include <asm/patch.h> | ||
31 | |||
32 | #include "core.h" | ||
33 | |||
34 | /* | ||
35 | * See register_usage_flags. If the probed instruction doesn't use PC, | ||
36 | * we can copy it into template and have it executed directly without | ||
37 | * simulation or emulation. | ||
38 | */ | ||
39 | #define ARM_REG_PC 15 | ||
40 | #define can_kprobe_direct_exec(m) (!test_bit(ARM_REG_PC, &(m))) | ||
41 | |||
42 | /* | ||
43 | * NOTE: the first sub and add instruction will be modified according | ||
44 | * to the stack cost of the instruction. | ||
45 | */ | ||
46 | asm ( | ||
47 | ".global optprobe_template_entry\n" | ||
48 | "optprobe_template_entry:\n" | ||
49 | ".global optprobe_template_sub_sp\n" | ||
50 | "optprobe_template_sub_sp:" | ||
51 | " sub sp, sp, #0xff\n" | ||
52 | " stmia sp, {r0 - r14} \n" | ||
53 | ".global optprobe_template_add_sp\n" | ||
54 | "optprobe_template_add_sp:" | ||
55 | " add r3, sp, #0xff\n" | ||
56 | " str r3, [sp, #52]\n" | ||
57 | " mrs r4, cpsr\n" | ||
58 | " str r4, [sp, #64]\n" | ||
59 | " mov r1, sp\n" | ||
60 | " ldr r0, 1f\n" | ||
61 | " ldr r2, 2f\n" | ||
62 | /* | ||
63 | * AEABI requires an 8-bytes alignment stack. If | ||
64 | * SP % 8 != 0 (SP % 4 == 0 should be ensured), | ||
65 | * alloc more bytes here. | ||
66 | */ | ||
67 | " and r4, sp, #4\n" | ||
68 | " sub sp, sp, r4\n" | ||
69 | #if __LINUX_ARM_ARCH__ >= 5 | ||
70 | " blx r2\n" | ||
71 | #else | ||
72 | " mov lr, pc\n" | ||
73 | " mov pc, r2\n" | ||
74 | #endif | ||
75 | " add sp, sp, r4\n" | ||
76 | " ldr r1, [sp, #64]\n" | ||
77 | " tst r1, #"__stringify(PSR_T_BIT)"\n" | ||
78 | " ldrne r2, [sp, #60]\n" | ||
79 | " orrne r2, #1\n" | ||
80 | " strne r2, [sp, #60] @ set bit0 of PC for thumb\n" | ||
81 | " msr cpsr_cxsf, r1\n" | ||
82 | ".global optprobe_template_restore_begin\n" | ||
83 | "optprobe_template_restore_begin:\n" | ||
84 | " ldmia sp, {r0 - r15}\n" | ||
85 | ".global optprobe_template_restore_orig_insn\n" | ||
86 | "optprobe_template_restore_orig_insn:\n" | ||
87 | " nop\n" | ||
88 | ".global optprobe_template_restore_end\n" | ||
89 | "optprobe_template_restore_end:\n" | ||
90 | " nop\n" | ||
91 | ".global optprobe_template_val\n" | ||
92 | "optprobe_template_val:\n" | ||
93 | "1: .long 0\n" | ||
94 | ".global optprobe_template_call\n" | ||
95 | "optprobe_template_call:\n" | ||
96 | "2: .long 0\n" | ||
97 | ".global optprobe_template_end\n" | ||
98 | "optprobe_template_end:\n"); | ||
99 | |||
100 | #define TMPL_VAL_IDX \ | ||
101 | ((unsigned long *)&optprobe_template_val - (unsigned long *)&optprobe_template_entry) | ||
102 | #define TMPL_CALL_IDX \ | ||
103 | ((unsigned long *)&optprobe_template_call - (unsigned long *)&optprobe_template_entry) | ||
104 | #define TMPL_END_IDX \ | ||
105 | ((unsigned long *)&optprobe_template_end - (unsigned long *)&optprobe_template_entry) | ||
106 | #define TMPL_ADD_SP \ | ||
107 | ((unsigned long *)&optprobe_template_add_sp - (unsigned long *)&optprobe_template_entry) | ||
108 | #define TMPL_SUB_SP \ | ||
109 | ((unsigned long *)&optprobe_template_sub_sp - (unsigned long *)&optprobe_template_entry) | ||
110 | #define TMPL_RESTORE_BEGIN \ | ||
111 | ((unsigned long *)&optprobe_template_restore_begin - (unsigned long *)&optprobe_template_entry) | ||
112 | #define TMPL_RESTORE_ORIGN_INSN \ | ||
113 | ((unsigned long *)&optprobe_template_restore_orig_insn - (unsigned long *)&optprobe_template_entry) | ||
114 | #define TMPL_RESTORE_END \ | ||
115 | ((unsigned long *)&optprobe_template_restore_end - (unsigned long *)&optprobe_template_entry) | ||
116 | |||
117 | /* | ||
118 | * ARM can always optimize an instruction when using ARM ISA, except | ||
119 | * instructions like 'str r0, [sp, r1]' which store to stack and unable | ||
120 | * to determine stack space consumption statically. | ||
121 | */ | ||
122 | int arch_prepared_optinsn(struct arch_optimized_insn *optinsn) | ||
123 | { | ||
124 | return optinsn->insn != NULL; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * In ARM ISA, kprobe opt always replace one instruction (4 bytes | ||
129 | * aligned and 4 bytes long). It is impossible to encounter another | ||
130 | * kprobe in the address range. So always return 0. | ||
131 | */ | ||
132 | int arch_check_optimized_kprobe(struct optimized_kprobe *op) | ||
133 | { | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* Caller must ensure addr & 3 == 0 */ | ||
138 | static int can_optimize(struct kprobe *kp) | ||
139 | { | ||
140 | if (kp->ainsn.stack_space < 0) | ||
141 | return 0; | ||
142 | /* | ||
143 | * 255 is the biggest imm can be used in 'sub r0, r0, #<imm>'. | ||
144 | * Number larger than 255 needs special encoding. | ||
145 | */ | ||
146 | if (kp->ainsn.stack_space > 255 - sizeof(struct pt_regs)) | ||
147 | return 0; | ||
148 | return 1; | ||
149 | } | ||
150 | |||
151 | /* Free optimized instruction slot */ | ||
152 | static void | ||
153 | __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty) | ||
154 | { | ||
155 | if (op->optinsn.insn) { | ||
156 | free_optinsn_slot(op->optinsn.insn, dirty); | ||
157 | op->optinsn.insn = NULL; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | extern void kprobe_handler(struct pt_regs *regs); | ||
162 | |||
163 | static void | ||
164 | optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) | ||
165 | { | ||
166 | unsigned long flags; | ||
167 | struct kprobe *p = &op->kp; | ||
168 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | ||
169 | |||
170 | /* Save skipped registers */ | ||
171 | regs->ARM_pc = (unsigned long)op->kp.addr; | ||
172 | regs->ARM_ORIG_r0 = ~0UL; | ||
173 | |||
174 | local_irq_save(flags); | ||
175 | |||
176 | if (kprobe_running()) { | ||
177 | kprobes_inc_nmissed_count(&op->kp); | ||
178 | } else { | ||
179 | __this_cpu_write(current_kprobe, &op->kp); | ||
180 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
181 | opt_pre_handler(&op->kp, regs); | ||
182 | __this_cpu_write(current_kprobe, NULL); | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * We singlestep the replaced instruction only when it can't be | ||
187 | * executed directly during restore. | ||
188 | */ | ||
189 | if (!p->ainsn.kprobe_direct_exec) | ||
190 | op->kp.ainsn.insn_singlestep(p->opcode, &p->ainsn, regs); | ||
191 | |||
192 | local_irq_restore(flags); | ||
193 | } | ||
194 | |||
195 | int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *orig) | ||
196 | { | ||
197 | kprobe_opcode_t *code; | ||
198 | unsigned long rel_chk; | ||
199 | unsigned long val; | ||
200 | unsigned long stack_protect = sizeof(struct pt_regs); | ||
201 | |||
202 | if (!can_optimize(orig)) | ||
203 | return -EILSEQ; | ||
204 | |||
205 | code = get_optinsn_slot(); | ||
206 | if (!code) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | /* | ||
210 | * Verify if the address gap is in 32MiB range, because this uses | ||
211 | * a relative jump. | ||
212 | * | ||
213 | * kprobe opt use a 'b' instruction to branch to optinsn.insn. | ||
214 | * According to ARM manual, branch instruction is: | ||
215 | * | ||
216 | * 31 28 27 24 23 0 | ||
217 | * +------+---+---+---+---+----------------+ | ||
218 | * | cond | 1 | 0 | 1 | 0 | imm24 | | ||
219 | * +------+---+---+---+---+----------------+ | ||
220 | * | ||
221 | * imm24 is a signed 24 bits integer. The real branch offset is computed | ||
222 | * by: imm32 = SignExtend(imm24:'00', 32); | ||
223 | * | ||
224 | * So the maximum forward branch should be: | ||
225 | * (0x007fffff << 2) = 0x01fffffc = 0x1fffffc | ||
226 | * The maximum backword branch should be: | ||
227 | * (0xff800000 << 2) = 0xfe000000 = -0x2000000 | ||
228 | * | ||
229 | * We can simply check (rel & 0xfe000003): | ||
230 | * if rel is positive, (rel & 0xfe000000) shoule be 0 | ||
231 | * if rel is negitive, (rel & 0xfe000000) should be 0xfe000000 | ||
232 | * the last '3' is used for alignment checking. | ||
233 | */ | ||
234 | rel_chk = (unsigned long)((long)code - | ||
235 | (long)orig->addr + 8) & 0xfe000003; | ||
236 | |||
237 | if ((rel_chk != 0) && (rel_chk != 0xfe000000)) { | ||
238 | /* | ||
239 | * Different from x86, we free code buf directly instead of | ||
240 | * calling __arch_remove_optimized_kprobe() because | ||
241 | * we have not fill any field in op. | ||
242 | */ | ||
243 | free_optinsn_slot(code, 0); | ||
244 | return -ERANGE; | ||
245 | } | ||
246 | |||
247 | /* Copy arch-dep-instance from template. */ | ||
248 | memcpy(code, &optprobe_template_entry, | ||
249 | TMPL_END_IDX * sizeof(kprobe_opcode_t)); | ||
250 | |||
251 | /* Adjust buffer according to instruction. */ | ||
252 | BUG_ON(orig->ainsn.stack_space < 0); | ||
253 | |||
254 | stack_protect += orig->ainsn.stack_space; | ||
255 | |||
256 | /* Should have been filtered by can_optimize(). */ | ||
257 | BUG_ON(stack_protect > 255); | ||
258 | |||
259 | /* Create a 'sub sp, sp, #<stack_protect>' */ | ||
260 | code[TMPL_SUB_SP] = __opcode_to_mem_arm(0xe24dd000 | stack_protect); | ||
261 | /* Create a 'add r3, sp, #<stack_protect>' */ | ||
262 | code[TMPL_ADD_SP] = __opcode_to_mem_arm(0xe28d3000 | stack_protect); | ||
263 | |||
264 | /* Set probe information */ | ||
265 | val = (unsigned long)op; | ||
266 | code[TMPL_VAL_IDX] = val; | ||
267 | |||
268 | /* Set probe function call */ | ||
269 | val = (unsigned long)optimized_callback; | ||
270 | code[TMPL_CALL_IDX] = val; | ||
271 | |||
272 | /* If possible, copy insn and have it executed during restore */ | ||
273 | orig->ainsn.kprobe_direct_exec = false; | ||
274 | if (can_kprobe_direct_exec(orig->ainsn.register_usage_flags)) { | ||
275 | kprobe_opcode_t final_branch = arm_gen_branch( | ||
276 | (unsigned long)(&code[TMPL_RESTORE_END]), | ||
277 | (unsigned long)(op->kp.addr) + 4); | ||
278 | if (final_branch != 0) { | ||
279 | /* | ||
280 | * Replace original 'ldmia sp, {r0 - r15}' with | ||
281 | * 'ldmia {r0 - r14}', restore all registers except pc. | ||
282 | */ | ||
283 | code[TMPL_RESTORE_BEGIN] = __opcode_to_mem_arm(0xe89d7fff); | ||
284 | |||
285 | /* The original probed instruction */ | ||
286 | code[TMPL_RESTORE_ORIGN_INSN] = __opcode_to_mem_arm(orig->opcode); | ||
287 | |||
288 | /* Jump back to next instruction */ | ||
289 | code[TMPL_RESTORE_END] = __opcode_to_mem_arm(final_branch); | ||
290 | orig->ainsn.kprobe_direct_exec = true; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | flush_icache_range((unsigned long)code, | ||
295 | (unsigned long)(&code[TMPL_END_IDX])); | ||
296 | |||
297 | /* Set op->optinsn.insn means prepared. */ | ||
298 | op->optinsn.insn = code; | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | void __kprobes arch_optimize_kprobes(struct list_head *oplist) | ||
303 | { | ||
304 | struct optimized_kprobe *op, *tmp; | ||
305 | |||
306 | list_for_each_entry_safe(op, tmp, oplist, list) { | ||
307 | unsigned long insn; | ||
308 | WARN_ON(kprobe_disabled(&op->kp)); | ||
309 | |||
310 | /* | ||
311 | * Backup instructions which will be replaced | ||
312 | * by jump address | ||
313 | */ | ||
314 | memcpy(op->optinsn.copied_insn, op->kp.addr, | ||
315 | RELATIVEJUMP_SIZE); | ||
316 | |||
317 | insn = arm_gen_branch((unsigned long)op->kp.addr, | ||
318 | (unsigned long)op->optinsn.insn); | ||
319 | BUG_ON(insn == 0); | ||
320 | |||
321 | /* | ||
322 | * Make it a conditional branch if replaced insn | ||
323 | * is consitional | ||
324 | */ | ||
325 | insn = (__mem_to_opcode_arm( | ||
326 | op->optinsn.copied_insn[0]) & 0xf0000000) | | ||
327 | (insn & 0x0fffffff); | ||
328 | |||
329 | /* | ||
330 | * Similar to __arch_disarm_kprobe, operations which | ||
331 | * removing breakpoints must be wrapped by stop_machine | ||
332 | * to avoid racing. | ||
333 | */ | ||
334 | kprobes_remove_breakpoint(op->kp.addr, insn); | ||
335 | |||
336 | list_del_init(&op->list); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | void arch_unoptimize_kprobe(struct optimized_kprobe *op) | ||
341 | { | ||
342 | arch_arm_kprobe(&op->kp); | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * Recover original instructions and breakpoints from relative jumps. | ||
347 | * Caller must call with locking kprobe_mutex. | ||
348 | */ | ||
349 | void arch_unoptimize_kprobes(struct list_head *oplist, | ||
350 | struct list_head *done_list) | ||
351 | { | ||
352 | struct optimized_kprobe *op, *tmp; | ||
353 | |||
354 | list_for_each_entry_safe(op, tmp, oplist, list) { | ||
355 | arch_unoptimize_kprobe(op); | ||
356 | list_move(&op->list, done_list); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | int arch_within_optimized_kprobe(struct optimized_kprobe *op, | ||
361 | unsigned long addr) | ||
362 | { | ||
363 | return ((unsigned long)op->kp.addr <= addr && | ||
364 | (unsigned long)op->kp.addr + RELATIVEJUMP_SIZE > addr); | ||
365 | } | ||
366 | |||
367 | void arch_remove_optimized_kprobe(struct optimized_kprobe *op) | ||
368 | { | ||
369 | __arch_remove_optimized_kprobe(op, 1); | ||
370 | } | ||
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/probes/kprobes/test-arm.c index cb1424240ff6..8866aedfdea2 100644 --- a/arch/arm/kernel/kprobes-test-arm.c +++ b/arch/arm/probes/kprobes/test-arm.c | |||
@@ -12,8 +12,9 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <asm/system_info.h> | 13 | #include <asm/system_info.h> |
14 | #include <asm/opcodes.h> | 14 | #include <asm/opcodes.h> |
15 | #include <asm/probes.h> | ||
15 | 16 | ||
16 | #include "kprobes-test.h" | 17 | #include "test-core.h" |
17 | 18 | ||
18 | 19 | ||
19 | #define TEST_ISA "32" | 20 | #define TEST_ISA "32" |
@@ -203,9 +204,9 @@ void kprobe_arm_test_cases(void) | |||
203 | #endif | 204 | #endif |
204 | TEST_GROUP("Miscellaneous instructions") | 205 | TEST_GROUP("Miscellaneous instructions") |
205 | 206 | ||
206 | TEST("mrs r0, cpsr") | 207 | TEST_RMASKED("mrs r",0,~PSR_IGNORE_BITS,", cpsr") |
207 | TEST("mrspl r7, cpsr") | 208 | TEST_RMASKED("mrspl r",7,~PSR_IGNORE_BITS,", cpsr") |
208 | TEST("mrs r14, cpsr") | 209 | TEST_RMASKED("mrs r",14,~PSR_IGNORE_BITS,", cpsr") |
209 | TEST_UNSUPPORTED(__inst_arm(0xe10ff000) " @ mrs r15, cpsr") | 210 | TEST_UNSUPPORTED(__inst_arm(0xe10ff000) " @ mrs r15, cpsr") |
210 | TEST_UNSUPPORTED("mrs r0, spsr") | 211 | TEST_UNSUPPORTED("mrs r0, spsr") |
211 | TEST_UNSUPPORTED("mrs lr, spsr") | 212 | TEST_UNSUPPORTED("mrs lr, spsr") |
@@ -214,9 +215,12 @@ void kprobe_arm_test_cases(void) | |||
214 | TEST_UNSUPPORTED("msr cpsr_f, lr") | 215 | TEST_UNSUPPORTED("msr cpsr_f, lr") |
215 | TEST_UNSUPPORTED("msr spsr, r0") | 216 | TEST_UNSUPPORTED("msr spsr, r0") |
216 | 217 | ||
218 | #if __LINUX_ARM_ARCH__ >= 5 || \ | ||
219 | (__LINUX_ARM_ARCH__ == 4 && !defined(CONFIG_CPU_32v4)) | ||
217 | TEST_BF_R("bx r",0,2f,"") | 220 | TEST_BF_R("bx r",0,2f,"") |
218 | TEST_BB_R("bx r",7,2f,"") | 221 | TEST_BB_R("bx r",7,2f,"") |
219 | TEST_BF_R("bxeq r",14,2f,"") | 222 | TEST_BF_R("bxeq r",14,2f,"") |
223 | #endif | ||
220 | 224 | ||
221 | #if __LINUX_ARM_ARCH__ >= 5 | 225 | #if __LINUX_ARM_ARCH__ >= 5 |
222 | TEST_R("clz r0, r",0, 0x0,"") | 226 | TEST_R("clz r0, r",0, 0x0,"") |
@@ -476,7 +480,9 @@ void kprobe_arm_test_cases(void) | |||
476 | TEST_GROUP("Extra load/store instructions") | 480 | TEST_GROUP("Extra load/store instructions") |
477 | 481 | ||
478 | TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") | 482 | TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") |
479 | TEST_RPR( "streqh r",14,VAL2,", [r",13,0, ", r",12, 48,"]") | 483 | TEST_RPR( "streqh r",14,VAL2,", [r",11,0, ", r",12, 48,"]") |
484 | TEST_UNSUPPORTED( "streqh r14, [r13, r12]") | ||
485 | TEST_UNSUPPORTED( "streqh r14, [r12, r13]") | ||
480 | TEST_RPR( "strh r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") | 486 | TEST_RPR( "strh r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") |
481 | TEST_RPR( "strneh r",12,VAL2,", [r",11,48,", -r",10,24,"]!") | 487 | TEST_RPR( "strneh r",12,VAL2,", [r",11,48,", -r",10,24,"]!") |
482 | TEST_RPR( "strh r",2, VAL1,", [r",3, 24,"], r",4, 48,"") | 488 | TEST_RPR( "strh r",2, VAL1,", [r",3, 24,"], r",4, 48,"") |
@@ -501,6 +507,9 @@ void kprobe_arm_test_cases(void) | |||
501 | TEST_RP( "strplh r",12,VAL2,", [r",11,24,", #-4]!") | 507 | TEST_RP( "strplh r",12,VAL2,", [r",11,24,", #-4]!") |
502 | TEST_RP( "strh r",2, VAL1,", [r",3, 24,"], #48") | 508 | TEST_RP( "strh r",2, VAL1,", [r",3, 24,"], #48") |
503 | TEST_RP( "strh r",10,VAL2,", [r",9, 64,"], #-48") | 509 | TEST_RP( "strh r",10,VAL2,", [r",9, 64,"], #-48") |
510 | TEST_RP( "strh r",3, VAL1,", [r",13,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") | ||
511 | TEST_UNSUPPORTED("strh r3, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
512 | TEST_RP( "strh r",4, VAL1,", [r",14,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
504 | TEST_UNSUPPORTED(__inst_arm(0xe1efc3b0) " @ strh r12, [pc, #48]!") | 513 | TEST_UNSUPPORTED(__inst_arm(0xe1efc3b0) " @ strh r12, [pc, #48]!") |
505 | TEST_UNSUPPORTED(__inst_arm(0xe0c9f3b0) " @ strh pc, [r9], #48") | 514 | TEST_UNSUPPORTED(__inst_arm(0xe0c9f3b0) " @ strh pc, [r9], #48") |
506 | 515 | ||
@@ -565,7 +574,9 @@ void kprobe_arm_test_cases(void) | |||
565 | 574 | ||
566 | #if __LINUX_ARM_ARCH__ >= 5 | 575 | #if __LINUX_ARM_ARCH__ >= 5 |
567 | TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]") | 576 | TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]") |
568 | TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]") | 577 | TEST_RPR( "strccd r",8, VAL2,", [r",11,0, ", r",12,48,"]") |
578 | TEST_UNSUPPORTED( "strccd r8, [r13, r12]") | ||
579 | TEST_UNSUPPORTED( "strccd r8, [r12, r13]") | ||
569 | TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!") | 580 | TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!") |
570 | TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!") | 581 | TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!") |
571 | TEST_RPR( "strd r",2, VAL1,", [r",5, 24,"], r",4,48,"") | 582 | TEST_RPR( "strd r",2, VAL1,", [r",5, 24,"], r",4,48,"") |
@@ -589,6 +600,9 @@ void kprobe_arm_test_cases(void) | |||
589 | TEST_RP( "strvcd r",12,VAL2,", [r",11,24,", #-16]!") | 600 | TEST_RP( "strvcd r",12,VAL2,", [r",11,24,", #-16]!") |
590 | TEST_RP( "strd r",2, VAL1,", [r",4, 24,"], #48") | 601 | TEST_RP( "strd r",2, VAL1,", [r",4, 24,"], #48") |
591 | TEST_RP( "strd r",10,VAL2,", [r",9, 64,"], #-48") | 602 | TEST_RP( "strd r",10,VAL2,", [r",9, 64,"], #-48") |
603 | TEST_RP( "strd r",6, VAL1,", [r",13,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") | ||
604 | TEST_UNSUPPORTED("strd r6, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
605 | TEST_RP( "strd r",4, VAL1,", [r",12,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
592 | TEST_UNSUPPORTED(__inst_arm(0xe1efc3f0) " @ strd r12, [pc, #48]!") | 606 | TEST_UNSUPPORTED(__inst_arm(0xe1efc3f0) " @ strd r12, [pc, #48]!") |
593 | 607 | ||
594 | TEST_P( "ldrd r0, [r",0, 24,", #-8]") | 608 | TEST_P( "ldrd r0, [r",0, 24,", #-8]") |
@@ -637,14 +651,20 @@ void kprobe_arm_test_cases(void) | |||
637 | TEST_RP( "str"byte" r",12,VAL2,", [r",11,24,", #-4]!") \ | 651 | TEST_RP( "str"byte" r",12,VAL2,", [r",11,24,", #-4]!") \ |
638 | TEST_RP( "str"byte" r",2, VAL1,", [r",3, 24,"], #48") \ | 652 | TEST_RP( "str"byte" r",2, VAL1,", [r",3, 24,"], #48") \ |
639 | TEST_RP( "str"byte" r",10,VAL2,", [r",9, 64,"], #-48") \ | 653 | TEST_RP( "str"byte" r",10,VAL2,", [r",9, 64,"], #-48") \ |
654 | TEST_RP( "str"byte" r",3, VAL1,", [r",13,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") \ | ||
655 | TEST_UNSUPPORTED("str"byte" r3, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") \ | ||
656 | TEST_RP( "str"byte" r",4, VAL1,", [r",10,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") \ | ||
640 | TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \ | 657 | TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \ |
641 | TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 48,"]") \ | 658 | TEST_RPR("str"byte" r",14,VAL2,", [r",11,0, ", r",12, 48,"]") \ |
659 | TEST_UNSUPPORTED("str"byte" r14, [r13, r12]") \ | ||
660 | TEST_UNSUPPORTED("str"byte" r14, [r12, r13]") \ | ||
642 | TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") \ | 661 | TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") \ |
643 | TEST_RPR("str"byte" r",12,VAL2,", [r",11,48,", -r",10,24,"]!") \ | 662 | TEST_RPR("str"byte" r",12,VAL2,", [r",11,48,", -r",10,24,"]!") \ |
644 | TEST_RPR("str"byte" r",2, VAL1,", [r",3, 24,"], r",4, 48,"") \ | 663 | TEST_RPR("str"byte" r",2, VAL1,", [r",3, 24,"], r",4, 48,"") \ |
645 | TEST_RPR("str"byte" r",10,VAL2,", [r",9, 48,"], -r",11,24,"") \ | 664 | TEST_RPR("str"byte" r",10,VAL2,", [r",9, 48,"], -r",11,24,"") \ |
646 | TEST_RPR("str"byte" r",0, VAL1,", [r",1, 24,", r",2, 32,", asl #1]")\ | 665 | TEST_RPR("str"byte" r",0, VAL1,", [r",1, 24,", r",2, 32,", asl #1]")\ |
647 | TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\ | 666 | TEST_RPR("str"byte" r",14,VAL2,", [r",11,0, ", r",12, 32,", lsr #2]")\ |
667 | TEST_UNSUPPORTED("str"byte" r14, [r13, r12, lsr #2]") \ | ||
648 | TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 32,", asr #3]!")\ | 668 | TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 32,", asr #3]!")\ |
649 | TEST_RPR("str"byte" r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\ | 669 | TEST_RPR("str"byte" r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\ |
650 | TEST_P( "ldr"byte" r0, [r",0, 24,", #-2]") \ | 670 | TEST_P( "ldr"byte" r0, [r",0, 24,", #-2]") \ |
@@ -668,12 +688,12 @@ void kprobe_arm_test_cases(void) | |||
668 | 688 | ||
669 | LOAD_STORE("") | 689 | LOAD_STORE("") |
670 | TEST_P( "str pc, [r",0,0,", #15*4]") | 690 | TEST_P( "str pc, [r",0,0,", #15*4]") |
671 | TEST_R( "str pc, [sp, r",2,15*4,"]") | 691 | TEST_UNSUPPORTED( "str pc, [sp, r2]") |
672 | TEST_BF( "ldr pc, [sp, #15*4]") | 692 | TEST_BF( "ldr pc, [sp, #15*4]") |
673 | TEST_BF_R("ldr pc, [sp, r",2,15*4,"]") | 693 | TEST_BF_R("ldr pc, [sp, r",2,15*4,"]") |
674 | 694 | ||
675 | TEST_P( "str sp, [r",0,0,", #13*4]") | 695 | TEST_P( "str sp, [r",0,0,", #13*4]") |
676 | TEST_R( "str sp, [sp, r",2,13*4,"]") | 696 | TEST_UNSUPPORTED( "str sp, [sp, r2]") |
677 | TEST_BF( "ldr sp, [sp, #13*4]") | 697 | TEST_BF( "ldr sp, [sp, #13*4]") |
678 | TEST_BF_R("ldr sp, [sp, r",2,13*4,"]") | 698 | TEST_BF_R("ldr sp, [sp, r",2,13*4,"]") |
679 | 699 | ||
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/probes/kprobes/test-core.c index b206d7790c77..9775de22e2ff 100644 --- a/arch/arm/kernel/kprobes-test.c +++ b/arch/arm/probes/kprobes/test-core.c | |||
@@ -209,10 +209,10 @@ | |||
209 | #include <linux/bug.h> | 209 | #include <linux/bug.h> |
210 | #include <asm/opcodes.h> | 210 | #include <asm/opcodes.h> |
211 | 211 | ||
212 | #include "kprobes.h" | 212 | #include "core.h" |
213 | #include "probes-arm.h" | 213 | #include "test-core.h" |
214 | #include "probes-thumb.h" | 214 | #include "../decode-arm.h" |
215 | #include "kprobes-test.h" | 215 | #include "../decode-thumb.h" |
216 | 216 | ||
217 | 217 | ||
218 | #define BENCHMARKING 1 | 218 | #define BENCHMARKING 1 |
@@ -236,6 +236,8 @@ static int tests_failed; | |||
236 | 236 | ||
237 | #ifndef CONFIG_THUMB2_KERNEL | 237 | #ifndef CONFIG_THUMB2_KERNEL |
238 | 238 | ||
239 | #define RET(reg) "mov pc, "#reg | ||
240 | |||
239 | long arm_func(long r0, long r1); | 241 | long arm_func(long r0, long r1); |
240 | 242 | ||
241 | static void __used __naked __arm_kprobes_test_func(void) | 243 | static void __used __naked __arm_kprobes_test_func(void) |
@@ -245,7 +247,7 @@ static void __used __naked __arm_kprobes_test_func(void) | |||
245 | ".type arm_func, %%function \n\t" | 247 | ".type arm_func, %%function \n\t" |
246 | "arm_func: \n\t" | 248 | "arm_func: \n\t" |
247 | "adds r0, r0, r1 \n\t" | 249 | "adds r0, r0, r1 \n\t" |
248 | "bx lr \n\t" | 250 | "mov pc, lr \n\t" |
249 | ".code "NORMAL_ISA /* Back to Thumb if necessary */ | 251 | ".code "NORMAL_ISA /* Back to Thumb if necessary */ |
250 | : : : "r0", "r1", "cc" | 252 | : : : "r0", "r1", "cc" |
251 | ); | 253 | ); |
@@ -253,6 +255,8 @@ static void __used __naked __arm_kprobes_test_func(void) | |||
253 | 255 | ||
254 | #else /* CONFIG_THUMB2_KERNEL */ | 256 | #else /* CONFIG_THUMB2_KERNEL */ |
255 | 257 | ||
258 | #define RET(reg) "bx "#reg | ||
259 | |||
256 | long thumb16_func(long r0, long r1); | 260 | long thumb16_func(long r0, long r1); |
257 | long thumb32even_func(long r0, long r1); | 261 | long thumb32even_func(long r0, long r1); |
258 | long thumb32odd_func(long r0, long r1); | 262 | long thumb32odd_func(long r0, long r1); |
@@ -494,7 +498,7 @@ static void __naked benchmark_nop(void) | |||
494 | { | 498 | { |
495 | __asm__ __volatile__ ( | 499 | __asm__ __volatile__ ( |
496 | "nop \n\t" | 500 | "nop \n\t" |
497 | "bx lr" | 501 | RET(lr)" \n\t" |
498 | ); | 502 | ); |
499 | } | 503 | } |
500 | 504 | ||
@@ -977,7 +981,7 @@ void __naked __kprobes_test_case_start(void) | |||
977 | "bic r0, lr, #1 @ r0 = inline data \n\t" | 981 | "bic r0, lr, #1 @ r0 = inline data \n\t" |
978 | "mov r1, sp \n\t" | 982 | "mov r1, sp \n\t" |
979 | "bl kprobes_test_case_start \n\t" | 983 | "bl kprobes_test_case_start \n\t" |
980 | "bx r0 \n\t" | 984 | RET(r0)" \n\t" |
981 | ); | 985 | ); |
982 | } | 986 | } |
983 | 987 | ||
@@ -1056,15 +1060,6 @@ static int test_case_run_count; | |||
1056 | static bool test_case_is_thumb; | 1060 | static bool test_case_is_thumb; |
1057 | static int test_instance; | 1061 | static int test_instance; |
1058 | 1062 | ||
1059 | /* | ||
1060 | * We ignore the state of the imprecise abort disable flag (CPSR.A) because this | ||
1061 | * can change randomly as the kernel doesn't take care to preserve or initialise | ||
1062 | * this across context switches. Also, with Security Extentions, the flag may | ||
1063 | * not be under control of the kernel; for this reason we ignore the state of | ||
1064 | * the FIQ disable flag CPSR.F as well. | ||
1065 | */ | ||
1066 | #define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT) | ||
1067 | |||
1068 | static unsigned long test_check_cc(int cc, unsigned long cpsr) | 1063 | static unsigned long test_check_cc(int cc, unsigned long cpsr) |
1069 | { | 1064 | { |
1070 | int ret = arm_check_condition(cc << 28, cpsr); | 1065 | int ret = arm_check_condition(cc << 28, cpsr); |
@@ -1196,6 +1191,13 @@ static void setup_test_context(struct pt_regs *regs) | |||
1196 | regs->uregs[arg->reg] = | 1191 | regs->uregs[arg->reg] = |
1197 | (unsigned long)current_stack + arg->val; | 1192 | (unsigned long)current_stack + arg->val; |
1198 | memory_needs_checking = true; | 1193 | memory_needs_checking = true; |
1194 | /* | ||
1195 | * Test memory at an address below SP is in danger of | ||
1196 | * being altered by an interrupt occurring and pushing | ||
1197 | * data onto the stack. Disable interrupts to stop this. | ||
1198 | */ | ||
1199 | if (arg->reg == 13) | ||
1200 | regs->ARM_cpsr |= PSR_I_BIT; | ||
1199 | break; | 1201 | break; |
1200 | } | 1202 | } |
1201 | case ARG_TYPE_MEM: { | 1203 | case ARG_TYPE_MEM: { |
@@ -1264,14 +1266,26 @@ test_case_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
1264 | static int __kprobes | 1266 | static int __kprobes |
1265 | test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) | 1267 | test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) |
1266 | { | 1268 | { |
1269 | struct test_arg *args; | ||
1270 | |||
1267 | if (container_of(p, struct test_probe, kprobe)->hit == test_instance) | 1271 | if (container_of(p, struct test_probe, kprobe)->hit == test_instance) |
1268 | return 0; /* Already run for this test instance */ | 1272 | return 0; /* Already run for this test instance */ |
1269 | 1273 | ||
1270 | result_regs = *regs; | 1274 | result_regs = *regs; |
1275 | |||
1276 | /* Mask out results which are indeterminate */ | ||
1271 | result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; | 1277 | result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; |
1278 | for (args = current_args; args[0].type != ARG_TYPE_END; ++args) | ||
1279 | if (args[0].type == ARG_TYPE_REG_MASKED) { | ||
1280 | struct test_arg_regptr *arg = | ||
1281 | (struct test_arg_regptr *)args; | ||
1282 | result_regs.uregs[arg->reg] &= arg->val; | ||
1283 | } | ||
1272 | 1284 | ||
1273 | /* Undo any changes done to SP by the test case */ | 1285 | /* Undo any changes done to SP by the test case */ |
1274 | regs->ARM_sp = (unsigned long)current_stack; | 1286 | regs->ARM_sp = (unsigned long)current_stack; |
1287 | /* Enable interrupts in case setup_test_context disabled them */ | ||
1288 | regs->ARM_cpsr &= ~PSR_I_BIT; | ||
1275 | 1289 | ||
1276 | container_of(p, struct test_probe, kprobe)->hit = test_instance; | 1290 | container_of(p, struct test_probe, kprobe)->hit = test_instance; |
1277 | return 0; | 1291 | return 0; |
diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/probes/kprobes/test-core.h index 4430990e90e7..94285203e9f7 100644 --- a/arch/arm/kernel/kprobes-test.h +++ b/arch/arm/probes/kprobes/test-core.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/kprobes-test.h | 2 | * arch/arm/probes/kprobes/test-core.h |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
5 | * | 5 | * |
@@ -45,10 +45,11 @@ extern int kprobe_test_cc_position; | |||
45 | * | 45 | * |
46 | */ | 46 | */ |
47 | 47 | ||
48 | #define ARG_TYPE_END 0 | 48 | #define ARG_TYPE_END 0 |
49 | #define ARG_TYPE_REG 1 | 49 | #define ARG_TYPE_REG 1 |
50 | #define ARG_TYPE_PTR 2 | 50 | #define ARG_TYPE_PTR 2 |
51 | #define ARG_TYPE_MEM 3 | 51 | #define ARG_TYPE_MEM 3 |
52 | #define ARG_TYPE_REG_MASKED 4 | ||
52 | 53 | ||
53 | #define ARG_FLAG_UNSUPPORTED 0x01 | 54 | #define ARG_FLAG_UNSUPPORTED 0x01 |
54 | #define ARG_FLAG_SUPPORTED 0x02 | 55 | #define ARG_FLAG_SUPPORTED 0x02 |
@@ -61,7 +62,7 @@ struct test_arg { | |||
61 | }; | 62 | }; |
62 | 63 | ||
63 | struct test_arg_regptr { | 64 | struct test_arg_regptr { |
64 | u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */ | 65 | u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR or ARG_TYPE_REG_MASKED */ |
65 | u8 reg; | 66 | u8 reg; |
66 | u8 _padding[2]; | 67 | u8 _padding[2]; |
67 | u32 val; | 68 | u32 val; |
@@ -138,6 +139,12 @@ struct test_arg_end { | |||
138 | ".short 0 \n\t" \ | 139 | ".short 0 \n\t" \ |
139 | ".word "#val" \n\t" | 140 | ".word "#val" \n\t" |
140 | 141 | ||
142 | #define TEST_ARG_REG_MASKED(reg, val) \ | ||
143 | ".byte "__stringify(ARG_TYPE_REG_MASKED)" \n\t" \ | ||
144 | ".byte "#reg" \n\t" \ | ||
145 | ".short 0 \n\t" \ | ||
146 | ".word "#val" \n\t" | ||
147 | |||
141 | #define TEST_ARG_END(flags) \ | 148 | #define TEST_ARG_END(flags) \ |
142 | ".byte "__stringify(ARG_TYPE_END)" \n\t" \ | 149 | ".byte "__stringify(ARG_TYPE_END)" \n\t" \ |
143 | ".byte "TEST_ISA flags" \n\t" \ | 150 | ".byte "TEST_ISA flags" \n\t" \ |
@@ -395,6 +402,22 @@ struct test_arg_end { | |||
395 | " "codex" \n\t" \ | 402 | " "codex" \n\t" \ |
396 | TESTCASE_END | 403 | TESTCASE_END |
397 | 404 | ||
405 | #define TEST_RMASKED(code1, reg, mask, code2) \ | ||
406 | TESTCASE_START(code1 #reg code2) \ | ||
407 | TEST_ARG_REG_MASKED(reg, mask) \ | ||
408 | TEST_ARG_END("") \ | ||
409 | TEST_INSTRUCTION(code1 #reg code2) \ | ||
410 | TESTCASE_END | ||
411 | |||
412 | /* | ||
413 | * We ignore the state of the imprecise abort disable flag (CPSR.A) because this | ||
414 | * can change randomly as the kernel doesn't take care to preserve or initialise | ||
415 | * this across context switches. Also, with Security Extensions, the flag may | ||
416 | * not be under control of the kernel; for this reason we ignore the state of | ||
417 | * the FIQ disable flag CPSR.F as well. | ||
418 | */ | ||
419 | #define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT) | ||
420 | |||
398 | 421 | ||
399 | /* | 422 | /* |
400 | * Macros for defining space directives spread over multiple lines. | 423 | * Macros for defining space directives spread over multiple lines. |
diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/probes/kprobes/test-thumb.c index 844dd10d8593..b683b4517458 100644 --- a/arch/arm/kernel/kprobes-test-thumb.c +++ b/arch/arm/probes/kprobes/test-thumb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/kernel/kprobes-test-thumb.c | 2 | * arch/arm/probes/kprobes/test-thumb.c |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. | 4 | * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. |
5 | * | 5 | * |
@@ -11,8 +11,9 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <asm/opcodes.h> | 13 | #include <asm/opcodes.h> |
14 | #include <asm/probes.h> | ||
14 | 15 | ||
15 | #include "kprobes-test.h" | 16 | #include "test-core.h" |
16 | 17 | ||
17 | 18 | ||
18 | #define TEST_ISA "16" | 19 | #define TEST_ISA "16" |
@@ -416,6 +417,9 @@ void kprobe_thumb32_test_cases(void) | |||
416 | TEST_RR( "strd r",14,VAL2,", r",12,VAL1,", [sp, #16]!") | 417 | TEST_RR( "strd r",14,VAL2,", r",12,VAL1,", [sp, #16]!") |
417 | TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16") | 418 | TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16") |
418 | TEST_RR( "strd r",7, VAL2,", r",8, VAL1,", [sp], #-16") | 419 | TEST_RR( "strd r",7, VAL2,", r",8, VAL1,", [sp], #-16") |
420 | TEST_RRP("strd r",6, VAL1,", r",7, VAL2,", [r",13, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") | ||
421 | TEST_UNSUPPORTED("strd r6, r7, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
422 | TEST_RRP("strd r",4, VAL1,", r",5, VAL2,", [r",14, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") | ||
419 | TEST_UNSUPPORTED(__inst_thumb32(0xe9efec04) " @ strd r14, r12, [pc, #16]!") | 423 | TEST_UNSUPPORTED(__inst_thumb32(0xe9efec04) " @ strd r14, r12, [pc, #16]!") |
420 | TEST_UNSUPPORTED(__inst_thumb32(0xe8efec04) " @ strd r14, r12, [pc], #16") | 424 | TEST_UNSUPPORTED(__inst_thumb32(0xe8efec04) " @ strd r14, r12, [pc], #16") |
421 | 425 | ||
@@ -774,8 +778,8 @@ CONDITION_INSTRUCTIONS(22, | |||
774 | 778 | ||
775 | TEST_UNSUPPORTED("subs pc, lr, #4") | 779 | TEST_UNSUPPORTED("subs pc, lr, #4") |
776 | 780 | ||
777 | TEST("mrs r0, cpsr") | 781 | TEST_RMASKED("mrs r",0,~PSR_IGNORE_BITS,", cpsr") |
778 | TEST("mrs r14, cpsr") | 782 | TEST_RMASKED("mrs r",14,~PSR_IGNORE_BITS,", cpsr") |
779 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr") | 783 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr") |
780 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr") | 784 | TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr") |
781 | TEST_UNSUPPORTED("mrs r0, spsr") | 785 | TEST_UNSUPPORTED("mrs r0, spsr") |
@@ -821,14 +825,22 @@ CONDITION_INSTRUCTIONS(22, | |||
821 | TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]!") \ | 825 | TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]!") \ |
822 | TEST_RPR("str"size".w r",0, VAL1,", [r",1, 0,", r",2, 4,"]") \ | 826 | TEST_RPR("str"size".w r",0, VAL1,", [r",1, 0,", r",2, 4,"]") \ |
823 | TEST_RPR("str"size" r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]") \ | 827 | TEST_RPR("str"size" r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]") \ |
828 | TEST_UNSUPPORTED("str"size" r0, [r13, r1]") \ | ||
824 | TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \ | 829 | TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \ |
825 | TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \ | 830 | TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \ |
831 | TEST_RP( "str"size" r",6, VAL1,", [r",13, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") \ | ||
832 | TEST_UNSUPPORTED("str"size" r6, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") \ | ||
833 | TEST_RP( "str"size" r",4, VAL2,", [r",12, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") \ | ||
826 | TEST_UNSUPPORTED("str"size"t r0, [r1, #4]") | 834 | TEST_UNSUPPORTED("str"size"t r0, [r1, #4]") |
827 | 835 | ||
828 | SINGLE_STORE("b") | 836 | SINGLE_STORE("b") |
829 | SINGLE_STORE("h") | 837 | SINGLE_STORE("h") |
830 | SINGLE_STORE("") | 838 | SINGLE_STORE("") |
831 | 839 | ||
840 | TEST_UNSUPPORTED(__inst_thumb32(0xf801000d) " @ strb r0, [r1, r13]") | ||
841 | TEST_UNSUPPORTED(__inst_thumb32(0xf821000d) " @ strh r0, [r1, r13]") | ||
842 | TEST_UNSUPPORTED(__inst_thumb32(0xf841000d) " @ str r0, [r1, r13]") | ||
843 | |||
832 | TEST("str sp, [sp]") | 844 | TEST("str sp, [sp]") |
833 | TEST_UNSUPPORTED(__inst_thumb32(0xf8cfe000) " @ str r14, [pc]") | 845 | TEST_UNSUPPORTED(__inst_thumb32(0xf8cfe000) " @ str r14, [pc]") |
834 | TEST_UNSUPPORTED(__inst_thumb32(0xf8cef000) " @ str pc, [r14]") | 846 | TEST_UNSUPPORTED(__inst_thumb32(0xf8cef000) " @ str pc, [r14]") |
diff --git a/arch/arm/probes/uprobes/Makefile b/arch/arm/probes/uprobes/Makefile new file mode 100644 index 000000000000..e1dc3d0f6d5a --- /dev/null +++ b/arch/arm/probes/uprobes/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_UPROBES) += core.o actions-arm.o | |||
diff --git a/arch/arm/kernel/uprobes-arm.c b/arch/arm/probes/uprobes/actions-arm.c index d3b655ff17da..76eb44972ebe 100644 --- a/arch/arm/kernel/uprobes-arm.c +++ b/arch/arm/probes/uprobes/actions-arm.c | |||
@@ -13,9 +13,9 @@ | |||
13 | #include <linux/uprobes.h> | 13 | #include <linux/uprobes.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | 15 | ||
16 | #include "probes.h" | 16 | #include "../decode.h" |
17 | #include "probes-arm.h" | 17 | #include "../decode-arm.h" |
18 | #include "uprobes.h" | 18 | #include "core.h" |
19 | 19 | ||
20 | static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs) | 20 | static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs) |
21 | { | 21 | { |
@@ -195,8 +195,6 @@ uprobe_decode_ldmstm(probes_opcode_t insn, | |||
195 | } | 195 | } |
196 | 196 | ||
197 | const union decode_action uprobes_probes_actions[] = { | 197 | const union decode_action uprobes_probes_actions[] = { |
198 | [PROBES_EMULATE_NONE] = {.handler = probes_simulate_nop}, | ||
199 | [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, | ||
200 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, | 198 | [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, |
201 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, | 199 | [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, |
202 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, | 200 | [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, |
diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/probes/uprobes/core.c index 56adf9c1fde0..d1329f1ba4e4 100644 --- a/arch/arm/kernel/uprobes.c +++ b/arch/arm/probes/uprobes/core.c | |||
@@ -17,9 +17,9 @@ | |||
17 | #include <asm/opcodes.h> | 17 | #include <asm/opcodes.h> |
18 | #include <asm/traps.h> | 18 | #include <asm/traps.h> |
19 | 19 | ||
20 | #include "probes.h" | 20 | #include "../decode.h" |
21 | #include "probes-arm.h" | 21 | #include "../decode-arm.h" |
22 | #include "uprobes.h" | 22 | #include "core.h" |
23 | 23 | ||
24 | #define UPROBE_TRAP_NR UINT_MAX | 24 | #define UPROBE_TRAP_NR UINT_MAX |
25 | 25 | ||
@@ -88,7 +88,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, | |||
88 | auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN); | 88 | auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN); |
89 | 89 | ||
90 | ret = arm_probes_decode_insn(insn, &auprobe->asi, false, | 90 | ret = arm_probes_decode_insn(insn, &auprobe->asi, false, |
91 | uprobes_probes_actions); | 91 | uprobes_probes_actions, NULL); |
92 | switch (ret) { | 92 | switch (ret) { |
93 | case INSN_REJECTED: | 93 | case INSN_REJECTED: |
94 | return -EINVAL; | 94 | return -EINVAL; |
diff --git a/arch/arm/kernel/uprobes.h b/arch/arm/probes/uprobes/core.h index 1d0c12dfbd03..1d0c12dfbd03 100644 --- a/arch/arm/kernel/uprobes.h +++ b/arch/arm/probes/uprobes/core.h | |||
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index dd301be89ecc..5376d908eabe 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | # CONFIG_LOCALVERSION_AUTO is not set | 1 | # CONFIG_LOCALVERSION_AUTO is not set |
2 | CONFIG_SYSVIPC=y | 2 | CONFIG_SYSVIPC=y |
3 | CONFIG_POSIX_MQUEUE=y | 3 | CONFIG_POSIX_MQUEUE=y |
4 | CONFIG_FHANDLE=y | ||
4 | CONFIG_AUDIT=y | 5 | CONFIG_AUDIT=y |
5 | CONFIG_NO_HZ_IDLE=y | 6 | CONFIG_NO_HZ_IDLE=y |
6 | CONFIG_HIGH_RES_TIMERS=y | 7 | CONFIG_HIGH_RES_TIMERS=y |
@@ -13,14 +14,12 @@ CONFIG_TASK_IO_ACCOUNTING=y | |||
13 | CONFIG_IKCONFIG=y | 14 | CONFIG_IKCONFIG=y |
14 | CONFIG_IKCONFIG_PROC=y | 15 | CONFIG_IKCONFIG_PROC=y |
15 | CONFIG_LOG_BUF_SHIFT=14 | 16 | CONFIG_LOG_BUF_SHIFT=14 |
16 | CONFIG_RESOURCE_COUNTERS=y | ||
17 | CONFIG_MEMCG=y | 17 | CONFIG_MEMCG=y |
18 | CONFIG_MEMCG_SWAP=y | 18 | CONFIG_MEMCG_SWAP=y |
19 | CONFIG_MEMCG_KMEM=y | 19 | CONFIG_MEMCG_KMEM=y |
20 | CONFIG_CGROUP_HUGETLB=y | 20 | CONFIG_CGROUP_HUGETLB=y |
21 | # CONFIG_UTS_NS is not set | 21 | # CONFIG_UTS_NS is not set |
22 | # CONFIG_IPC_NS is not set | 22 | # CONFIG_IPC_NS is not set |
23 | # CONFIG_PID_NS is not set | ||
24 | # CONFIG_NET_NS is not set | 23 | # CONFIG_NET_NS is not set |
25 | CONFIG_SCHED_AUTOGROUP=y | 24 | CONFIG_SCHED_AUTOGROUP=y |
26 | CONFIG_BLK_DEV_INITRD=y | 25 | CONFIG_BLK_DEV_INITRD=y |
@@ -92,7 +91,6 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y | |||
92 | CONFIG_SERIAL_OF_PLATFORM=y | 91 | CONFIG_SERIAL_OF_PLATFORM=y |
93 | CONFIG_VIRTIO_CONSOLE=y | 92 | CONFIG_VIRTIO_CONSOLE=y |
94 | # CONFIG_HW_RANDOM is not set | 93 | # CONFIG_HW_RANDOM is not set |
95 | # CONFIG_HMC_DRV is not set | ||
96 | CONFIG_SPI=y | 94 | CONFIG_SPI=y |
97 | CONFIG_SPI_PL022=y | 95 | CONFIG_SPI_PL022=y |
98 | CONFIG_GPIO_PL061=y | 96 | CONFIG_GPIO_PL061=y |
@@ -133,6 +131,8 @@ CONFIG_EXT3_FS=y | |||
133 | CONFIG_EXT4_FS=y | 131 | CONFIG_EXT4_FS=y |
134 | CONFIG_FANOTIFY=y | 132 | CONFIG_FANOTIFY=y |
135 | CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y | 133 | CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y |
134 | CONFIG_QUOTA=y | ||
135 | CONFIG_AUTOFS4_FS=y | ||
136 | CONFIG_FUSE_FS=y | 136 | CONFIG_FUSE_FS=y |
137 | CONFIG_CUSE=y | 137 | CONFIG_CUSE=y |
138 | CONFIG_VFAT_FS=y | 138 | CONFIG_VFAT_FS=y |
@@ -152,14 +152,15 @@ CONFIG_MAGIC_SYSRQ=y | |||
152 | CONFIG_DEBUG_KERNEL=y | 152 | CONFIG_DEBUG_KERNEL=y |
153 | CONFIG_LOCKUP_DETECTOR=y | 153 | CONFIG_LOCKUP_DETECTOR=y |
154 | # CONFIG_SCHED_DEBUG is not set | 154 | # CONFIG_SCHED_DEBUG is not set |
155 | # CONFIG_DEBUG_PREEMPT is not set | ||
155 | # CONFIG_FTRACE is not set | 156 | # CONFIG_FTRACE is not set |
157 | CONFIG_KEYS=y | ||
156 | CONFIG_SECURITY=y | 158 | CONFIG_SECURITY=y |
157 | CONFIG_CRYPTO_ANSI_CPRNG=y | 159 | CONFIG_CRYPTO_ANSI_CPRNG=y |
158 | CONFIG_ARM64_CRYPTO=y | 160 | CONFIG_ARM64_CRYPTO=y |
159 | CONFIG_CRYPTO_SHA1_ARM64_CE=y | 161 | CONFIG_CRYPTO_SHA1_ARM64_CE=y |
160 | CONFIG_CRYPTO_SHA2_ARM64_CE=y | 162 | CONFIG_CRYPTO_SHA2_ARM64_CE=y |
161 | CONFIG_CRYPTO_GHASH_ARM64_CE=y | 163 | CONFIG_CRYPTO_GHASH_ARM64_CE=y |
162 | CONFIG_CRYPTO_AES_ARM64_CE=y | ||
163 | CONFIG_CRYPTO_AES_ARM64_CE_CCM=y | 164 | CONFIG_CRYPTO_AES_ARM64_CE_CCM=y |
164 | CONFIG_CRYPTO_AES_ARM64_CE_BLK=y | 165 | CONFIG_CRYPTO_AES_ARM64_CE_BLK=y |
165 | CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y | 166 | CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y |
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h index d34189bceff7..9ce3e680ae1c 100644 --- a/arch/arm64/include/asm/dma-mapping.h +++ b/arch/arm64/include/asm/dma-mapping.h | |||
@@ -52,13 +52,14 @@ static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) | |||
52 | dev->archdata.dma_ops = ops; | 52 | dev->archdata.dma_ops = ops; |
53 | } | 53 | } |
54 | 54 | ||
55 | static inline int set_arch_dma_coherent_ops(struct device *dev) | 55 | static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, |
56 | struct iommu_ops *iommu, bool coherent) | ||
56 | { | 57 | { |
57 | dev->archdata.dma_coherent = true; | 58 | dev->archdata.dma_coherent = coherent; |
58 | set_dma_ops(dev, &coherent_swiotlb_dma_ops); | 59 | if (coherent) |
59 | return 0; | 60 | set_dma_ops(dev, &coherent_swiotlb_dma_ops); |
60 | } | 61 | } |
61 | #define set_arch_dma_coherent_ops set_arch_dma_coherent_ops | 62 | #define arch_setup_dma_ops arch_setup_dma_ops |
62 | 63 | ||
63 | /* do not use this function in a driver */ | 64 | /* do not use this function in a driver */ |
64 | static inline bool is_device_dma_coherent(struct device *dev) | 65 | static inline bool is_device_dma_coherent(struct device *dev) |
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index df22314f57cf..210d632aa5ad 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
@@ -298,7 +298,6 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address, | |||
298 | #define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) | 298 | #define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) |
299 | #define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot) | 299 | #define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot) |
300 | 300 | ||
301 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | ||
302 | #define pud_write(pud) pte_write(pud_pte(pud)) | 301 | #define pud_write(pud) pte_write(pud_pte(pud)) |
303 | #define pud_pfn(pud) (((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT) | 302 | #define pud_pfn(pud) (((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT) |
304 | 303 | ||
@@ -401,7 +400,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | |||
401 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); | 400 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); |
402 | } | 401 | } |
403 | 402 | ||
404 | #define pud_page(pud) pmd_page(pud_pmd(pud)) | 403 | #define pud_page(pud) pfn_to_page(__phys_to_pfn(pud_val(pud) & PHYS_MASK)) |
405 | 404 | ||
406 | #endif /* CONFIG_ARM64_PGTABLE_LEVELS > 2 */ | 405 | #endif /* CONFIG_ARM64_PGTABLE_LEVELS > 2 */ |
407 | 406 | ||
@@ -437,6 +436,8 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr) | |||
437 | return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr); | 436 | return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr); |
438 | } | 437 | } |
439 | 438 | ||
439 | #define pgd_page(pgd) pfn_to_page(__phys_to_pfn(pgd_val(pgd) & PHYS_MASK)) | ||
440 | |||
440 | #endif /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */ | 441 | #endif /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */ |
441 | 442 | ||
442 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) | 443 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) |
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c index 3771b72b6569..2d6b6065fe7f 100644 --- a/arch/arm64/kernel/suspend.c +++ b/arch/arm64/kernel/suspend.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <asm/debug-monitors.h> | 5 | #include <asm/debug-monitors.h> |
6 | #include <asm/pgtable.h> | 6 | #include <asm/pgtable.h> |
7 | #include <asm/memory.h> | 7 | #include <asm/memory.h> |
8 | #include <asm/mmu_context.h> | ||
8 | #include <asm/smp_plat.h> | 9 | #include <asm/smp_plat.h> |
9 | #include <asm/suspend.h> | 10 | #include <asm/suspend.h> |
10 | #include <asm/tlbflush.h> | 11 | #include <asm/tlbflush.h> |
@@ -98,7 +99,18 @@ int __cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) | |||
98 | */ | 99 | */ |
99 | ret = __cpu_suspend_enter(arg, fn); | 100 | ret = __cpu_suspend_enter(arg, fn); |
100 | if (ret == 0) { | 101 | if (ret == 0) { |
101 | cpu_switch_mm(mm->pgd, mm); | 102 | /* |
103 | * We are resuming from reset with TTBR0_EL1 set to the | ||
104 | * idmap to enable the MMU; restore the active_mm mappings in | ||
105 | * TTBR0_EL1 unless the active_mm == &init_mm, in which case | ||
106 | * the thread entered __cpu_suspend with TTBR0_EL1 set to | ||
107 | * reserved TTBR0 page tables and should be restored as such. | ||
108 | */ | ||
109 | if (mm == &init_mm) | ||
110 | cpu_set_reserved_ttbr0(); | ||
111 | else | ||
112 | cpu_switch_mm(mm->pgd, mm); | ||
113 | |||
102 | flush_tlb_all(); | 114 | flush_tlb_all(); |
103 | 115 | ||
104 | /* | 116 | /* |
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index f3b51b57740a..95c39b95e97e 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | 12 | ||
13 | 13 | ||
14 | #define NR_syscalls 318 /* length of syscall table */ | 14 | #define NR_syscalls 319 /* length of syscall table */ |
15 | 15 | ||
16 | /* | 16 | /* |
17 | * The following defines stop scripts/checksyscalls.sh from complaining about | 17 | * The following defines stop scripts/checksyscalls.sh from complaining about |
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h index 4c2240c1b0cb..461079560c78 100644 --- a/arch/ia64/include/uapi/asm/unistd.h +++ b/arch/ia64/include/uapi/asm/unistd.h | |||
@@ -331,5 +331,6 @@ | |||
331 | #define __NR_getrandom 1339 | 331 | #define __NR_getrandom 1339 |
332 | #define __NR_memfd_create 1340 | 332 | #define __NR_memfd_create 1340 |
333 | #define __NR_bpf 1341 | 333 | #define __NR_bpf 1341 |
334 | #define __NR_execveat 1342 | ||
334 | 335 | ||
335 | #endif /* _UAPI_ASM_IA64_UNISTD_H */ | 336 | #endif /* _UAPI_ASM_IA64_UNISTD_H */ |
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index f5e96dffc63c..fcf8b8cbca0b 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -1779,6 +1779,7 @@ sys_call_table: | |||
1779 | data8 sys_getrandom | 1779 | data8 sys_getrandom |
1780 | data8 sys_memfd_create // 1340 | 1780 | data8 sys_memfd_create // 1340 |
1781 | data8 sys_bpf | 1781 | data8 sys_bpf |
1782 | data8 sys_execveat | ||
1782 | 1783 | ||
1783 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls | 1784 | .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls |
1784 | #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ | 1785 | #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ |
diff --git a/arch/nios2/kernel/cpuinfo.c b/arch/nios2/kernel/cpuinfo.c index 51d5bb90d3e5..a223691dff4f 100644 --- a/arch/nios2/kernel/cpuinfo.c +++ b/arch/nios2/kernel/cpuinfo.c | |||
@@ -72,6 +72,7 @@ void __init setup_cpuinfo(void) | |||
72 | cpuinfo.has_div = fcpu_has(cpu, "altr,has-div"); | 72 | cpuinfo.has_div = fcpu_has(cpu, "altr,has-div"); |
73 | cpuinfo.has_mul = fcpu_has(cpu, "altr,has-mul"); | 73 | cpuinfo.has_mul = fcpu_has(cpu, "altr,has-mul"); |
74 | cpuinfo.has_mulx = fcpu_has(cpu, "altr,has-mulx"); | 74 | cpuinfo.has_mulx = fcpu_has(cpu, "altr,has-mulx"); |
75 | cpuinfo.mmu = fcpu_has(cpu, "altr,has-mmu"); | ||
75 | 76 | ||
76 | if (IS_ENABLED(CONFIG_NIOS2_HW_DIV_SUPPORT) && !cpuinfo.has_div) | 77 | if (IS_ENABLED(CONFIG_NIOS2_HW_DIV_SUPPORT) && !cpuinfo.has_div) |
77 | err_cpu("DIV"); | 78 | err_cpu("DIV"); |
diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S index 83bca17d1008..0bdfd13ff98b 100644 --- a/arch/nios2/kernel/entry.S +++ b/arch/nios2/kernel/entry.S | |||
@@ -365,30 +365,14 @@ ENTRY(ret_from_interrupt) | |||
365 | GET_THREAD_INFO r1 | 365 | GET_THREAD_INFO r1 |
366 | ldw r4, TI_PREEMPT_COUNT(r1) | 366 | ldw r4, TI_PREEMPT_COUNT(r1) |
367 | bne r4, r0, restore_all | 367 | bne r4, r0, restore_all |
368 | |||
369 | need_resched: | ||
370 | ldw r4, TI_FLAGS(r1) /* ? Need resched set */ | 368 | ldw r4, TI_FLAGS(r1) /* ? Need resched set */ |
371 | BTBZ r10, r4, TIF_NEED_RESCHED, restore_all | 369 | BTBZ r10, r4, TIF_NEED_RESCHED, restore_all |
372 | ldw r4, PT_ESTATUS(sp) /* ? Interrupts off */ | 370 | ldw r4, PT_ESTATUS(sp) /* ? Interrupts off */ |
373 | andi r10, r4, ESTATUS_EPIE | 371 | andi r10, r4, ESTATUS_EPIE |
374 | beq r10, r0, restore_all | 372 | beq r10, r0, restore_all |
375 | movia r4, PREEMPT_ACTIVE | 373 | call preempt_schedule_irq |
376 | stw r4, TI_PREEMPT_COUNT(r1) | ||
377 | rdctl r10, status /* enable intrs again */ | ||
378 | ori r10, r10 ,STATUS_PIE | ||
379 | wrctl status, r10 | ||
380 | PUSH r1 | ||
381 | call schedule | ||
382 | POP r1 | ||
383 | mov r4, r0 | ||
384 | stw r4, TI_PREEMPT_COUNT(r1) | ||
385 | rdctl r10, status /* disable intrs */ | ||
386 | andi r10, r10, %lo(~STATUS_PIE) | ||
387 | wrctl status, r10 | ||
388 | br need_resched | ||
389 | #else | ||
390 | br restore_all | ||
391 | #endif | 374 | #endif |
375 | br restore_all | ||
392 | 376 | ||
393 | /*********************************************************************** | 377 | /*********************************************************************** |
394 | * A few syscall wrappers | 378 | * A few syscall wrappers |
diff --git a/arch/parisc/include/asm/ldcw.h b/arch/parisc/include/asm/ldcw.h index d2d11b7055ba..8121aa6db2ff 100644 --- a/arch/parisc/include/asm/ldcw.h +++ b/arch/parisc/include/asm/ldcw.h | |||
@@ -33,11 +33,18 @@ | |||
33 | 33 | ||
34 | #endif /*!CONFIG_PA20*/ | 34 | #endif /*!CONFIG_PA20*/ |
35 | 35 | ||
36 | /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. */ | 36 | /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. |
37 | We don't explicitly expose that "*a" may be written as reload | ||
38 | fails to find a register in class R1_REGS when "a" needs to be | ||
39 | reloaded when generating 64-bit PIC code. Instead, we clobber | ||
40 | memory to indicate to the compiler that the assembly code reads | ||
41 | or writes to items other than those listed in the input and output | ||
42 | operands. This may pessimize the code somewhat but __ldcw is | ||
43 | usually used within code blocks surrounded by memory barriors. */ | ||
37 | #define __ldcw(a) ({ \ | 44 | #define __ldcw(a) ({ \ |
38 | unsigned __ret; \ | 45 | unsigned __ret; \ |
39 | __asm__ __volatile__(__LDCW " 0(%2),%0" \ | 46 | __asm__ __volatile__(__LDCW " 0(%1),%0" \ |
40 | : "=r" (__ret), "+m" (*(a)) : "r" (a)); \ | 47 | : "=r" (__ret) : "r" (a) : "memory"); \ |
41 | __ret; \ | 48 | __ret; \ |
42 | }) | 49 | }) |
43 | 50 | ||
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h index 19c36cba37c4..a46f5f45570c 100644 --- a/arch/powerpc/include/asm/kexec.h +++ b/arch/powerpc/include/asm/kexec.h | |||
@@ -86,6 +86,11 @@ extern int overlaps_crashkernel(unsigned long start, unsigned long size); | |||
86 | extern void reserve_crashkernel(void); | 86 | extern void reserve_crashkernel(void); |
87 | extern void machine_kexec_mask_interrupts(void); | 87 | extern void machine_kexec_mask_interrupts(void); |
88 | 88 | ||
89 | static inline bool kdump_in_progress(void) | ||
90 | { | ||
91 | return crashing_cpu >= 0; | ||
92 | } | ||
93 | |||
89 | #else /* !CONFIG_KEXEC */ | 94 | #else /* !CONFIG_KEXEC */ |
90 | static inline void crash_kexec_secondary(struct pt_regs *regs) { } | 95 | static inline void crash_kexec_secondary(struct pt_regs *regs) { } |
91 | 96 | ||
@@ -106,6 +111,11 @@ static inline int crash_shutdown_unregister(crash_shutdown_t handler) | |||
106 | return 0; | 111 | return 0; |
107 | } | 112 | } |
108 | 113 | ||
114 | static inline bool kdump_in_progress(void) | ||
115 | { | ||
116 | return false; | ||
117 | } | ||
118 | |||
109 | #endif /* CONFIG_KEXEC */ | 119 | #endif /* CONFIG_KEXEC */ |
110 | #endif /* ! __ASSEMBLY__ */ | 120 | #endif /* ! __ASSEMBLY__ */ |
111 | #endif /* __KERNEL__ */ | 121 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index ce9577d693be..91062eef582f 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
@@ -366,3 +366,4 @@ SYSCALL_SPU(seccomp) | |||
366 | SYSCALL_SPU(getrandom) | 366 | SYSCALL_SPU(getrandom) |
367 | SYSCALL_SPU(memfd_create) | 367 | SYSCALL_SPU(memfd_create) |
368 | SYSCALL_SPU(bpf) | 368 | SYSCALL_SPU(bpf) |
369 | COMPAT_SYS(execveat) | ||
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index e0da021caa00..36b79c31eedd 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <uapi/asm/unistd.h> | 12 | #include <uapi/asm/unistd.h> |
13 | 13 | ||
14 | 14 | ||
15 | #define __NR_syscalls 362 | 15 | #define __NR_syscalls 363 |
16 | 16 | ||
17 | #define __NR__exit __NR_exit | 17 | #define __NR__exit __NR_exit |
18 | #define NR_syscalls __NR_syscalls | 18 | #define NR_syscalls __NR_syscalls |
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h index f55351f2e66e..ef5b5b1f3123 100644 --- a/arch/powerpc/include/uapi/asm/unistd.h +++ b/arch/powerpc/include/uapi/asm/unistd.h | |||
@@ -384,5 +384,6 @@ | |||
384 | #define __NR_getrandom 359 | 384 | #define __NR_getrandom 359 |
385 | #define __NR_memfd_create 360 | 385 | #define __NR_memfd_create 360 |
386 | #define __NR_bpf 361 | 386 | #define __NR_bpf 361 |
387 | #define __NR_execveat 362 | ||
387 | 388 | ||
388 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ | 389 | #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ |
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 879b3aacac32..f96d1ec24189 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -330,7 +330,7 @@ void default_machine_kexec(struct kimage *image) | |||
330 | * using debugger IPI. | 330 | * using debugger IPI. |
331 | */ | 331 | */ |
332 | 332 | ||
333 | if (crashing_cpu == -1) | 333 | if (!kdump_in_progress()) |
334 | kexec_prepare_cpus(); | 334 | kexec_prepare_cpus(); |
335 | 335 | ||
336 | pr_debug("kexec: Starting switchover sequence.\n"); | 336 | pr_debug("kexec: Starting switchover sequence.\n"); |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 8ec017cb4446..8b2d2dc8ef10 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -700,6 +700,7 @@ void start_secondary(void *unused) | |||
700 | smp_store_cpu_info(cpu); | 700 | smp_store_cpu_info(cpu); |
701 | set_dec(tb_ticks_per_jiffy); | 701 | set_dec(tb_ticks_per_jiffy); |
702 | preempt_disable(); | 702 | preempt_disable(); |
703 | cpu_callin_map[cpu] = 1; | ||
703 | 704 | ||
704 | if (smp_ops->setup_cpu) | 705 | if (smp_ops->setup_cpu) |
705 | smp_ops->setup_cpu(cpu); | 706 | smp_ops->setup_cpu(cpu); |
@@ -738,14 +739,6 @@ void start_secondary(void *unused) | |||
738 | notify_cpu_starting(cpu); | 739 | notify_cpu_starting(cpu); |
739 | set_cpu_online(cpu, true); | 740 | set_cpu_online(cpu, true); |
740 | 741 | ||
741 | /* | ||
742 | * CPU must be marked active and online before we signal back to the | ||
743 | * master, because the scheduler needs to see the cpu_online and | ||
744 | * cpu_active bits set. | ||
745 | */ | ||
746 | smp_wmb(); | ||
747 | cpu_callin_map[cpu] = 1; | ||
748 | |||
749 | local_irq_enable(); | 742 | local_irq_enable(); |
750 | 743 | ||
751 | cpu_startup_entry(CPUHP_ONLINE); | 744 | cpu_startup_entry(CPUHP_ONLINE); |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 469751d92004..b5682fd6c984 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <asm/trace.h> | 43 | #include <asm/trace.h> |
44 | #include <asm/firmware.h> | 44 | #include <asm/firmware.h> |
45 | #include <asm/plpar_wrappers.h> | 45 | #include <asm/plpar_wrappers.h> |
46 | #include <asm/kexec.h> | ||
46 | #include <asm/fadump.h> | 47 | #include <asm/fadump.h> |
47 | 48 | ||
48 | #include "pseries.h" | 49 | #include "pseries.h" |
@@ -267,8 +268,13 @@ static void pSeries_lpar_hptab_clear(void) | |||
267 | * out to the user, but at least this will stop us from | 268 | * out to the user, but at least this will stop us from |
268 | * continuing on further and creating an even more | 269 | * continuing on further and creating an even more |
269 | * difficult to debug situation. | 270 | * difficult to debug situation. |
271 | * | ||
272 | * There is a known problem when kdump'ing, if cpus are offline | ||
273 | * the above call will fail. Rather than panicking again, keep | ||
274 | * going and hope the kdump kernel is also little endian, which | ||
275 | * it usually is. | ||
270 | */ | 276 | */ |
271 | if (rc) | 277 | if (rc && !kdump_in_progress()) |
272 | panic("Could not enable big endian exceptions"); | 278 | panic("Could not enable big endian exceptions"); |
273 | } | 279 | } |
274 | #endif | 280 | #endif |
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common index 87bc86821bc9..d195a87ca542 100644 --- a/arch/um/Kconfig.common +++ b/arch/um/Kconfig.common | |||
@@ -3,6 +3,7 @@ config UML | |||
3 | default y | 3 | default y |
4 | select HAVE_ARCH_AUDITSYSCALL | 4 | select HAVE_ARCH_AUDITSYSCALL |
5 | select HAVE_UID16 | 5 | select HAVE_UID16 |
6 | select HAVE_FUTEX_CMPXCHG if FUTEX | ||
6 | select GENERIC_IRQ_SHOW | 7 | select GENERIC_IRQ_SHOW |
7 | select GENERIC_CPU_DEVICES | 8 | select GENERIC_CPU_DEVICES |
8 | select GENERIC_IO | 9 | select GENERIC_IO |
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 7c523bbf3dc8..0dd8d089c315 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c | |||
@@ -322,7 +322,8 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) | |||
322 | * Target instructions MUST be relocatable (checked inside) | 322 | * Target instructions MUST be relocatable (checked inside) |
323 | * This is called when new aggr(opt)probe is allocated or reused. | 323 | * This is called when new aggr(opt)probe is allocated or reused. |
324 | */ | 324 | */ |
325 | int arch_prepare_optimized_kprobe(struct optimized_kprobe *op) | 325 | int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, |
326 | struct kprobe *__unused) | ||
326 | { | 327 | { |
327 | u8 *buf; | 328 | u8 *buf; |
328 | int ret; | 329 | int ret; |
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 10fbed126b11..f83fc6c5e0ba 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -4448,7 +4448,7 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm) | |||
4448 | * zap all shadow pages. | 4448 | * zap all shadow pages. |
4449 | */ | 4449 | */ |
4450 | if (unlikely(kvm_current_mmio_generation(kvm) == 0)) { | 4450 | if (unlikely(kvm_current_mmio_generation(kvm) == 0)) { |
4451 | printk_ratelimited(KERN_INFO "kvm: zapping shadow pages for mmio generation wraparound\n"); | 4451 | printk_ratelimited(KERN_DEBUG "kvm: zapping shadow pages for mmio generation wraparound\n"); |
4452 | kvm_mmu_invalidate_zap_all_pages(kvm); | 4452 | kvm_mmu_invalidate_zap_all_pages(kvm); |
4453 | } | 4453 | } |
4454 | } | 4454 | } |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index feb852b04598..d4c58d884838 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -5840,53 +5840,10 @@ static __init int hardware_setup(void) | |||
5840 | memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE); | 5840 | memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE); |
5841 | memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE); | 5841 | memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE); |
5842 | 5842 | ||
5843 | vmx_disable_intercept_for_msr(MSR_FS_BASE, false); | ||
5844 | vmx_disable_intercept_for_msr(MSR_GS_BASE, false); | ||
5845 | vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true); | ||
5846 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); | ||
5847 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); | ||
5848 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); | ||
5849 | vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true); | ||
5850 | |||
5851 | memcpy(vmx_msr_bitmap_legacy_x2apic, | ||
5852 | vmx_msr_bitmap_legacy, PAGE_SIZE); | ||
5853 | memcpy(vmx_msr_bitmap_longmode_x2apic, | ||
5854 | vmx_msr_bitmap_longmode, PAGE_SIZE); | ||
5855 | |||
5856 | if (enable_apicv) { | ||
5857 | for (msr = 0x800; msr <= 0x8ff; msr++) | ||
5858 | vmx_disable_intercept_msr_read_x2apic(msr); | ||
5859 | |||
5860 | /* According SDM, in x2apic mode, the whole id reg is used. | ||
5861 | * But in KVM, it only use the highest eight bits. Need to | ||
5862 | * intercept it */ | ||
5863 | vmx_enable_intercept_msr_read_x2apic(0x802); | ||
5864 | /* TMCCT */ | ||
5865 | vmx_enable_intercept_msr_read_x2apic(0x839); | ||
5866 | /* TPR */ | ||
5867 | vmx_disable_intercept_msr_write_x2apic(0x808); | ||
5868 | /* EOI */ | ||
5869 | vmx_disable_intercept_msr_write_x2apic(0x80b); | ||
5870 | /* SELF-IPI */ | ||
5871 | vmx_disable_intercept_msr_write_x2apic(0x83f); | ||
5872 | } | ||
5873 | |||
5874 | if (enable_ept) { | ||
5875 | kvm_mmu_set_mask_ptes(0ull, | ||
5876 | (enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull, | ||
5877 | (enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull, | ||
5878 | 0ull, VMX_EPT_EXECUTABLE_MASK); | ||
5879 | ept_set_mmio_spte_mask(); | ||
5880 | kvm_enable_tdp(); | ||
5881 | } else | ||
5882 | kvm_disable_tdp(); | ||
5883 | |||
5884 | update_ple_window_actual_max(); | ||
5885 | |||
5886 | if (setup_vmcs_config(&vmcs_config) < 0) { | 5843 | if (setup_vmcs_config(&vmcs_config) < 0) { |
5887 | r = -EIO; | 5844 | r = -EIO; |
5888 | goto out7; | 5845 | goto out7; |
5889 | } | 5846 | } |
5890 | 5847 | ||
5891 | if (boot_cpu_has(X86_FEATURE_NX)) | 5848 | if (boot_cpu_has(X86_FEATURE_NX)) |
5892 | kvm_enable_efer_bits(EFER_NX); | 5849 | kvm_enable_efer_bits(EFER_NX); |
@@ -5945,6 +5902,49 @@ static __init int hardware_setup(void) | |||
5945 | if (nested) | 5902 | if (nested) |
5946 | nested_vmx_setup_ctls_msrs(); | 5903 | nested_vmx_setup_ctls_msrs(); |
5947 | 5904 | ||
5905 | vmx_disable_intercept_for_msr(MSR_FS_BASE, false); | ||
5906 | vmx_disable_intercept_for_msr(MSR_GS_BASE, false); | ||
5907 | vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true); | ||
5908 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); | ||
5909 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); | ||
5910 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); | ||
5911 | vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true); | ||
5912 | |||
5913 | memcpy(vmx_msr_bitmap_legacy_x2apic, | ||
5914 | vmx_msr_bitmap_legacy, PAGE_SIZE); | ||
5915 | memcpy(vmx_msr_bitmap_longmode_x2apic, | ||
5916 | vmx_msr_bitmap_longmode, PAGE_SIZE); | ||
5917 | |||
5918 | if (enable_apicv) { | ||
5919 | for (msr = 0x800; msr <= 0x8ff; msr++) | ||
5920 | vmx_disable_intercept_msr_read_x2apic(msr); | ||
5921 | |||
5922 | /* According SDM, in x2apic mode, the whole id reg is used. | ||
5923 | * But in KVM, it only use the highest eight bits. Need to | ||
5924 | * intercept it */ | ||
5925 | vmx_enable_intercept_msr_read_x2apic(0x802); | ||
5926 | /* TMCCT */ | ||
5927 | vmx_enable_intercept_msr_read_x2apic(0x839); | ||
5928 | /* TPR */ | ||
5929 | vmx_disable_intercept_msr_write_x2apic(0x808); | ||
5930 | /* EOI */ | ||
5931 | vmx_disable_intercept_msr_write_x2apic(0x80b); | ||
5932 | /* SELF-IPI */ | ||
5933 | vmx_disable_intercept_msr_write_x2apic(0x83f); | ||
5934 | } | ||
5935 | |||
5936 | if (enable_ept) { | ||
5937 | kvm_mmu_set_mask_ptes(0ull, | ||
5938 | (enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull, | ||
5939 | (enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull, | ||
5940 | 0ull, VMX_EPT_EXECUTABLE_MASK); | ||
5941 | ept_set_mmio_spte_mask(); | ||
5942 | kvm_enable_tdp(); | ||
5943 | } else | ||
5944 | kvm_disable_tdp(); | ||
5945 | |||
5946 | update_ple_window_actual_max(); | ||
5947 | |||
5948 | return alloc_kvm_area(); | 5948 | return alloc_kvm_area(); |
5949 | 5949 | ||
5950 | out7: | 5950 | out7: |
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index 531d4269e2e3..bd16d6c370ec 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c | |||
@@ -34,7 +34,7 @@ typedef asmlinkage void (*sys_call_ptr_t)(void); | |||
34 | 34 | ||
35 | extern asmlinkage void sys_ni_syscall(void); | 35 | extern asmlinkage void sys_ni_syscall(void); |
36 | 36 | ||
37 | const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { | 37 | const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { |
38 | /* | 38 | /* |
39 | * Smells like a compiler bug -- it doesn't work | 39 | * Smells like a compiler bug -- it doesn't work |
40 | * when the & below is removed. | 40 | * when the & below is removed. |
diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c index 20c3649d0691..5cdfa9db2217 100644 --- a/arch/x86/um/sys_call_table_64.c +++ b/arch/x86/um/sys_call_table_64.c | |||
@@ -47,7 +47,7 @@ typedef void (*sys_call_ptr_t)(void); | |||
47 | 47 | ||
48 | extern void sys_ni_syscall(void); | 48 | extern void sys_ni_syscall(void); |
49 | 49 | ||
50 | const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { | 50 | const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { |
51 | /* | 51 | /* |
52 | * Smells like a compiler bug -- it doesn't work | 52 | * Smells like a compiler bug -- it doesn't work |
53 | * when the & below is removed. | 53 | * when the & below is removed. |