diff options
-rw-r--r-- | arch/arm/kernel/kprobes-common.c | 15 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes.h | 28 |
2 files changed, 43 insertions, 0 deletions
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c index 32bb0f236684..a5394fb4e4e0 100644 --- a/arch/arm/kernel/kprobes-common.c +++ b/arch/arm/kernel/kprobes-common.c | |||
@@ -59,10 +59,25 @@ void __init test_load_write_pc_interworking(void) | |||
59 | #endif /* !test_load_write_pc_interworking */ | 59 | #endif /* !test_load_write_pc_interworking */ |
60 | 60 | ||
61 | 61 | ||
62 | #ifndef test_alu_write_pc_interworking | ||
63 | |||
64 | bool alu_write_pc_interworks; | ||
65 | |||
66 | void __init test_alu_write_pc_interworking(void) | ||
67 | { | ||
68 | int arch = cpu_architecture(); | ||
69 | BUG_ON(arch == CPU_ARCH_UNKNOWN); | ||
70 | alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7; | ||
71 | } | ||
72 | |||
73 | #endif /* !test_alu_write_pc_interworking */ | ||
74 | |||
75 | |||
62 | void __init arm_kprobe_decode_init(void) | 76 | void __init arm_kprobe_decode_init(void) |
63 | { | 77 | { |
64 | find_str_pc_offset(); | 78 | find_str_pc_offset(); |
65 | test_load_write_pc_interworking(); | 79 | test_load_write_pc_interworking(); |
80 | test_alu_write_pc_interworking(); | ||
66 | } | 81 | } |
67 | 82 | ||
68 | 83 | ||
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h index c442852e65e4..a6aeda0a6c7f 100644 --- a/arch/arm/kernel/kprobes.h +++ b/arch/arm/kernel/kprobes.h | |||
@@ -133,6 +133,34 @@ static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs) | |||
133 | } | 133 | } |
134 | 134 | ||
135 | 135 | ||
136 | #if __LINUX_ARM_ARCH__ >= 7 | ||
137 | |||
138 | #define alu_write_pc_interworks true | ||
139 | #define test_alu_write_pc_interworking() | ||
140 | |||
141 | #elif __LINUX_ARM_ARCH__ <= 5 | ||
142 | |||
143 | /* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */ | ||
144 | #define alu_write_pc_interworks false | ||
145 | #define test_alu_write_pc_interworking() | ||
146 | |||
147 | #else /* __LINUX_ARM_ARCH__ == 6 */ | ||
148 | |||
149 | /* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */ | ||
150 | extern bool alu_write_pc_interworks; | ||
151 | void __init test_alu_write_pc_interworking(void); | ||
152 | |||
153 | #endif /* __LINUX_ARM_ARCH__ == 6 */ | ||
154 | |||
155 | static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs) | ||
156 | { | ||
157 | if (alu_write_pc_interworks) | ||
158 | bx_write_pc(pcv, regs); | ||
159 | else | ||
160 | regs->ARM_pc = pcv; | ||
161 | } | ||
162 | |||
163 | |||
136 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs); | 164 | void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs); |
137 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs); | 165 | void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs); |
138 | 166 | ||