Skip to content

Commit

Permalink
[PATCH] Kprobes IA64: cmp ctype unc support
Browse files Browse the repository at this point in the history
The current Kprobes when patching the original instruction with the break
instruction tries to retain the original qualifying predicate(qp), however
for cmp.crel.ctype where ctype == unc, which is a special instruction
always needs to be executed irrespective of qp.  Hence, if the instruction
we are patching is of this type, then we should not copy the original qp to
the break instruction, this is because we always want the break fault to
happen so that we can emulate the instruction.

This patch is based on the feedback given by David Mosberger

Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Anil S Keshavamurthy authored and Linus Torvalds committed Jun 23, 2005
1 parent a540318 commit 1674eaf
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
43 changes: 41 additions & 2 deletions arch/ia64/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,41 @@ static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode
return;
}

/*
* In this function we check to see if the instruction
* (qp) cmpx.crel.ctype p1,p2=r2,r3
* on which we are inserting kprobe is cmp instruction
* with ctype as unc.
*/
static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode,
unsigned long kprobe_inst)
{
cmp_inst_t cmp_inst;
uint ctype_unc = 0;

if (!((bundle_encoding[template][slot] == I) ||
(bundle_encoding[template][slot] == M)))
goto out;

if (!((major_opcode == 0xC) || (major_opcode == 0xD) ||
(major_opcode == 0xE)))
goto out;

cmp_inst.l = kprobe_inst;
if ((cmp_inst.f.x2 == 0) || (cmp_inst.f.x2 == 1)) {
/* Integere compare - Register Register (A6 type)*/
if ((cmp_inst.f.tb == 0) && (cmp_inst.f.ta == 0)
&&(cmp_inst.f.c == 1))
ctype_unc = 1;
} else if ((cmp_inst.f.x2 == 2)||(cmp_inst.f.x2 == 3)) {
/* Integere compare - Immediate Register (A8 type)*/
if ((cmp_inst.f.ta == 0) &&(cmp_inst.f.c == 1))
ctype_unc = 1;
}
out:
return ctype_unc;
}

/*
* In this function we override the bundle with
* the break instruction at the given slot.
Expand All @@ -131,9 +166,13 @@ static void prepare_break_inst(uint template, uint slot, uint major_opcode,

/*
* Copy the original kprobe_inst qualifying predicate(qp)
* to the break instruction
* to the break instruction iff !is_cmp_ctype_unc_inst
* because for cmp instruction with ctype equal to unc,
* which is a special instruction always needs to be
* executed regradless of qp
*/
break_inst |= (0x3f & kprobe_inst);
if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst))
break_inst |= (0x3f & kprobe_inst);

switch (slot) {
case 0:
Expand Down
17 changes: 17 additions & 0 deletions include/asm-ia64/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@

#define BREAK_INST (long)(__IA64_BREAK_KPROBE << 6)

typedef union cmp_inst {
struct {
unsigned long long qp : 6;
unsigned long long p1 : 6;
unsigned long long c : 1;
unsigned long long r2 : 7;
unsigned long long r3 : 7;
unsigned long long p2 : 6;
unsigned long long ta : 1;
unsigned long long x2 : 2;
unsigned long long tb : 1;
unsigned long long opcode : 4;
unsigned long long reserved : 23;
}f;
unsigned long long l;
} cmp_inst_t;

struct kprobe;

typedef struct _bundle {
Expand Down

0 comments on commit 1674eaf

Please sign in to comment.