Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 36333
b: refs/heads/master
c: 214ddde
h: refs/heads/master
i:
  36331: 0542fab
v: v3
  • Loading branch information
bibo mao authored and Tony Luck committed Sep 26, 2006
1 parent fa3996c commit 5170acd
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a4b47ab9464a8200528fad3101668abdd7379cf9
refs/heads/master: 214ddde2f95037e129eff7e895869771719c7c1b
55 changes: 29 additions & 26 deletions trunk/arch/ia64/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,8 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
static int __kprobes unsupported_inst(uint template, uint slot,
uint major_opcode,
unsigned long kprobe_inst,
struct kprobe *p)
unsigned long addr)
{
unsigned long addr = (unsigned long)p->addr;

if (bundle_encoding[template][slot] == I) {
switch (major_opcode) {
case 0x0: //I_UNIT_MISC_OPCODE:
Expand Down Expand Up @@ -217,7 +215,7 @@ static void __kprobes prepare_break_inst(uint template, uint slot,
struct kprobe *p)
{
unsigned long break_inst = BREAK_INST;
bundle_t *bundle = &p->ainsn.insn.bundle;
bundle_t *bundle = &p->opcode.bundle;

/*
* Copy the original kprobe_inst qualifying predicate(qp)
Expand Down Expand Up @@ -423,11 +421,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
unsigned long kprobe_inst=0;
unsigned int slot = addr & 0xf, template, major_opcode = 0;
bundle_t *bundle = &p->ainsn.insn.bundle;

memcpy(&p->opcode.bundle, kprobe_addr, sizeof(bundle_t));
memcpy(&p->ainsn.insn.bundle, kprobe_addr, sizeof(bundle_t));
bundle_t *bundle;

bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
template = bundle->quad0.template;

if(valid_kprobe_addr(template, slot, addr))
Expand All @@ -440,42 +436,49 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
/* Get kprobe_inst and major_opcode from the bundle */
get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);

if (unsupported_inst(template, slot, major_opcode, kprobe_inst, p))
if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr))
return -EINVAL;

prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);

return 0;
}
p->ainsn.insn = get_insn_slot();
if (!p->ainsn.insn)
return -ENOMEM;
memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));

void __kprobes flush_insn_slot(struct kprobe *p)
{
unsigned long arm_addr;
prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);

arm_addr = ((unsigned long)&p->opcode.bundle) & ~0xFULL;
flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
return 0;
}

void __kprobes arch_arm_kprobe(struct kprobe *p)
{
unsigned long addr = (unsigned long)p->addr;
unsigned long arm_addr = addr & ~0xFULL;

flush_insn_slot(p);
memcpy((char *)arm_addr, &p->ainsn.insn.bundle, sizeof(bundle_t));
flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
flush_icache_range((unsigned long)p->ainsn.insn,
(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
memcpy((char *)arm_addr, &p->opcode, sizeof(kprobe_opcode_t));
flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
}

void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
unsigned long addr = (unsigned long)p->addr;
unsigned long arm_addr = addr & ~0xFULL;

/* p->opcode contains the original unaltered bundle */
memcpy((char *) arm_addr, (char *) &p->opcode.bundle, sizeof(bundle_t));
flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
/* p->ainsn.insn contains the original unaltered kprobe_opcode_t */
memcpy((char *) arm_addr, (char *) p->ainsn.insn,
sizeof(kprobe_opcode_t));
flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
}

void __kprobes arch_remove_kprobe(struct kprobe *p)
{
mutex_lock(&kprobe_mutex);
free_insn_slot(p->ainsn.insn);
mutex_unlock(&kprobe_mutex);
}
/*
* We are resuming execution after a single step fault, so the pt_regs
* structure reflects the register state after we executed the instruction
Expand All @@ -486,12 +489,12 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
*/
static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
{
unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle);
unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
unsigned long template;
int slot = ((unsigned long)p->addr & 0xf);

template = p->opcode.bundle.quad0.template;
template = p->ainsn.insn->bundle.quad0.template;

if (slot == 1 && bundle_encoding[template][1] == L)
slot = 2;
Expand Down Expand Up @@ -553,7 +556,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)

static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
{
unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
unsigned long bundle_addr = (unsigned long) &p->ainsn.insn->bundle;
unsigned long slot = (unsigned long)p->addr & 0xf;

/* single step inline if break instruction */
Expand Down
9 changes: 5 additions & 4 deletions trunk/include/asm-ia64/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
#include <linux/percpu.h>
#include <asm/break.h>

#define MAX_INSN_SIZE 16
#define __ARCH_WANT_KPROBES_INSN_SLOT
#define MAX_INSN_SIZE 1
#define BREAK_INST (long)(__IA64_BREAK_KPROBE << 6)

typedef union cmp_inst {
Expand Down Expand Up @@ -94,7 +95,7 @@ struct kprobe_ctlblk {
#define IP_RELATIVE_PREDICT_OPCODE (7)
#define LONG_BRANCH_OPCODE (0xC)
#define LONG_CALL_OPCODE (0xD)
#define arch_remove_kprobe(p) do {} while (0)
#define flush_insn_slot(p) do { } while (0)

typedef struct kprobe_opcode {
bundle_t bundle;
Expand All @@ -108,7 +109,7 @@ struct fnptr {
/* Architecture specific copy of original instruction*/
struct arch_specific_insn {
/* copy of the instruction to be emulated */
kprobe_opcode_t insn;
kprobe_opcode_t *insn;
#define INST_FLAG_FIX_RELATIVE_IP_ADDR 1
#define INST_FLAG_FIX_BRANCH_REG 2
#define INST_FLAG_BREAK_INST 4
Expand All @@ -125,6 +126,6 @@ static inline void jprobe_return(void)
}
extern void invalidate_stacked_regs(void);
extern void flush_register_stack(void);
extern void flush_insn_slot(struct kprobe *p);
extern void arch_remove_kprobe(struct kprobe *p);

#endif /* _ASM_KPROBES_H */

0 comments on commit 5170acd

Please sign in to comment.