aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/kprobes.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2009-09-08 20:55:21 -0400
committerDan Williams <dan.j.williams@intel.com>2009-09-08 20:55:21 -0400
commitbbb20089a3275a19e475dbc21320c3742e3ca423 (patch)
tree216fdc1cbef450ca688135c5b8969169482d9a48 /arch/s390/kernel/kprobes.c
parent3e48e656903e9fd8bc805c6a2c4264d7808d315b (diff)
parent657a77fa7284d8ae28dfa48f1dc5d919bf5b2843 (diff)
Merge branch 'dmaengine' into async-tx-next
Conflicts: crypto/async_tx/async_xor.c drivers/dma/ioat/dma_v2.h drivers/dma/ioat/pci.c drivers/md/raid5.c
Diffstat (limited to 'arch/s390/kernel/kprobes.c')
-rw-r--r--arch/s390/kernel/kprobes.c47
1 files changed, 8 insertions, 39 deletions
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index a01cf0284db2..86783efa24ee 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -25,9 +25,9 @@
25#include <linux/preempt.h> 25#include <linux/preempt.h>
26#include <linux/stop_machine.h> 26#include <linux/stop_machine.h>
27#include <linux/kdebug.h> 27#include <linux/kdebug.h>
28#include <linux/uaccess.h>
28#include <asm/cacheflush.h> 29#include <asm/cacheflush.h>
29#include <asm/sections.h> 30#include <asm/sections.h>
30#include <asm/uaccess.h>
31#include <linux/module.h> 31#include <linux/module.h>
32 32
33DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; 33DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
@@ -154,66 +154,35 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
154 154
155static int __kprobes swap_instruction(void *aref) 155static int __kprobes swap_instruction(void *aref)
156{ 156{
157 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
158 unsigned long status = kcb->kprobe_status;
157 struct ins_replace_args *args = aref; 159 struct ins_replace_args *args = aref;
158 u32 *addr; 160 int rc;
159 u32 instr;
160 int err = -EFAULT;
161 161
162 /* 162 kcb->kprobe_status = KPROBE_SWAP_INST;
163 * Text segment is read-only, hence we use stura to bypass dynamic 163 rc = probe_kernel_write(args->ptr, &args->new, sizeof(args->new));
164 * address translation to exchange the instruction. Since stura 164 kcb->kprobe_status = status;
165 * always operates on four bytes, but we only want to exchange two 165 return rc;
166 * bytes do some calculations to get things right. In addition we
167 * shall not cross any page boundaries (vmalloc area!) when writing
168 * the new instruction.
169 */
170 addr = (u32 *)((unsigned long)args->ptr & -4UL);
171 if ((unsigned long)args->ptr & 2)
172 instr = ((*addr) & 0xffff0000) | args->new;
173 else
174 instr = ((*addr) & 0x0000ffff) | args->new << 16;
175
176 asm volatile(
177 " lra %1,0(%1)\n"
178 "0: stura %2,%1\n"
179 "1: la %0,0\n"
180 "2:\n"
181 EX_TABLE(0b,2b)
182 : "+d" (err)
183 : "a" (addr), "d" (instr)
184 : "memory", "cc");
185
186 return err;
187} 166}
188 167
189void __kprobes arch_arm_kprobe(struct kprobe *p) 168void __kprobes arch_arm_kprobe(struct kprobe *p)
190{ 169{
191 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
192 unsigned long status = kcb->kprobe_status;
193 struct ins_replace_args args; 170 struct ins_replace_args args;
194 171
195 args.ptr = p->addr; 172 args.ptr = p->addr;
196 args.old = p->opcode; 173 args.old = p->opcode;
197 args.new = BREAKPOINT_INSTRUCTION; 174 args.new = BREAKPOINT_INSTRUCTION;
198
199 kcb->kprobe_status = KPROBE_SWAP_INST;
200 stop_machine(swap_instruction, &args, NULL); 175 stop_machine(swap_instruction, &args, NULL);
201 kcb->kprobe_status = status;
202} 176}
203 177
204void __kprobes arch_disarm_kprobe(struct kprobe *p) 178void __kprobes arch_disarm_kprobe(struct kprobe *p)
205{ 179{
206 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
207 unsigned long status = kcb->kprobe_status;
208 struct ins_replace_args args; 180 struct ins_replace_args args;
209 181
210 args.ptr = p->addr; 182 args.ptr = p->addr;
211 args.old = BREAKPOINT_INSTRUCTION; 183 args.old = BREAKPOINT_INSTRUCTION;
212 args.new = p->opcode; 184 args.new = p->opcode;
213
214 kcb->kprobe_status = KPROBE_SWAP_INST;
215 stop_machine(swap_instruction, &args, NULL); 185 stop_machine(swap_instruction, &args, NULL);
216 kcb->kprobe_status = status;
217} 186}
218 187
219void __kprobes arch_remove_kprobe(struct kprobe *p) 188void __kprobes arch_remove_kprobe(struct kprobe *p)