Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 44418
b: refs/heads/master
c: df3e0d1
h: refs/heads/master
v: v3
  • Loading branch information
bibo,mao authored and Tony Luck committed Dec 12, 2006
1 parent 7c99ce2 commit 4781691
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 54 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: 08ed38b68099f2a492196414b08a7f5dd8dc3537
refs/heads/master: df3e0d1c69c097f54588d720d39efdcdf31e3c24
175 changes: 122 additions & 53 deletions trunk/arch/ia64/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,48 +128,6 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
return;
}

/*
* In this function we check to see if the instruction
* on which we are inserting kprobe is supported.
* Returns 0 if supported
* Returns -EINVAL if unsupported
*/
static int __kprobes unsupported_inst(uint template, uint slot,
uint major_opcode,
unsigned long kprobe_inst,
unsigned long addr)
{
if (bundle_encoding[template][slot] == I) {
switch (major_opcode) {
case 0x0: //I_UNIT_MISC_OPCODE:
/*
* Check for Integer speculation instruction
* - Bit 33-35 to be equal to 0x1
*/
if (((kprobe_inst >> 33) & 0x7) == 1) {
printk(KERN_WARNING
"Kprobes on speculation inst at <0x%lx> not supported\n",
addr);
return -EINVAL;
}

/*
* IP relative mov instruction
* - Bit 27-35 to be equal to 0x30
*/
if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
printk(KERN_WARNING
"Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
addr);
return -EINVAL;

}
}
}
return 0;
}


/*
* In this function we check to see if the instruction
* (qp) cmpx.crel.ctype p1,p2=r2,r3
Expand Down Expand Up @@ -206,27 +164,137 @@ static uint __kprobes is_cmp_ctype_unc_inst(uint template, uint slot,
return ctype_unc;
}

/*
* In this function we check to see if the instruction
* on which we are inserting kprobe is supported.
* Returns qp value if supported
* Returns -EINVAL if unsupported
*/
static int __kprobes unsupported_inst(uint template, uint slot,
uint major_opcode,
unsigned long kprobe_inst,
unsigned long addr)
{
int qp;

qp = kprobe_inst & 0x3f;
if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) {
if (slot == 1 && qp) {
printk(KERN_WARNING "Kprobes on cmp unc"
"instruction on slot 1 at <0x%lx>"
"is not supported\n", addr);
return -EINVAL;

}
qp = 0;
}
else if (bundle_encoding[template][slot] == I) {
if (major_opcode == 0) {
/*
* Check for Integer speculation instruction
* - Bit 33-35 to be equal to 0x1
*/
if (((kprobe_inst >> 33) & 0x7) == 1) {
printk(KERN_WARNING
"Kprobes on speculation inst at <0x%lx> not supported\n",
addr);
return -EINVAL;
}
/*
* IP relative mov instruction
* - Bit 27-35 to be equal to 0x30
*/
if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
printk(KERN_WARNING
"Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
addr);
return -EINVAL;

}
}
else if ((major_opcode == 5) && !(kprobe_inst & (0xFUl << 33)) &&
(kprobe_inst & (0x1UL << 12))) {
/* test bit instructions, tbit,tnat,tf
* bit 33-36 to be equal to 0
* bit 12 to be equal to 1
*/
if (slot == 1 && qp) {
printk(KERN_WARNING "Kprobes on test bit"
"instruction on slot at <0x%lx>"
"is not supported\n", addr);
return -EINVAL;
}
qp = 0;
}
}
else if (bundle_encoding[template][slot] == B) {
if (major_opcode == 7) {
/* IP-Relative Predict major code is 7 */
printk(KERN_WARNING "Kprobes on IP-Relative"
"Predict is not supported\n");
return -EINVAL;
}
else if (major_opcode == 2) {
/* Indirect Predict, major code is 2
* bit 27-32 to be equal to 10 or 11
*/
int x6=(kprobe_inst >> 27) & 0x3F;
if ((x6 == 0x10) || (x6 == 0x11)) {
printk(KERN_WARNING "Kprobes on"
"Indirect Predict is not supported\n");
return -EINVAL;
}
}
}
/* kernel does not use float instruction, here for safety kprobe
* will judge whether it is fcmp/flass/float approximation instruction
*/
else if (unlikely(bundle_encoding[template][slot] == F)) {
if ((major_opcode == 4 || major_opcode == 5) &&
(kprobe_inst & (0x1 << 12))) {
/* fcmp/fclass unc instruction */
if (slot == 1 && qp) {
printk(KERN_WARNING "Kprobes on fcmp/fclass "
"instruction on slot at <0x%lx> "
"is not supported\n", addr);
return -EINVAL;

}
qp = 0;
}
if ((major_opcode == 0 || major_opcode == 1) &&
(kprobe_inst & (0x1UL << 33))) {
/* float Approximation instruction */
if (slot == 1 && qp) {
printk(KERN_WARNING "Kprobes on float Approx "
"instr at <0x%lx> is not supported\n",
addr);
return -EINVAL;
}
qp = 0;
}
}
return qp;
}

/*
* In this function we override the bundle with
* the break instruction at the given slot.
*/
static void __kprobes prepare_break_inst(uint template, uint slot,
uint major_opcode,
unsigned long kprobe_inst,
struct kprobe *p)
struct kprobe *p,
int qp)
{
unsigned long break_inst = BREAK_INST;
bundle_t *bundle = &p->opcode.bundle;

/*
* Copy the original kprobe_inst qualifying predicate(qp)
* 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
* to the break instruction
*/
if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst))
break_inst |= (0x3f & kprobe_inst);
break_inst |= qp;

switch (slot) {
case 0:
Expand Down Expand Up @@ -422,6 +490,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
unsigned long kprobe_inst=0;
unsigned int slot = addr & 0xf, template, major_opcode = 0;
bundle_t *bundle;
int qp;

bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
template = bundle->quad0.template;
Expand All @@ -436,17 +505,17 @@ 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, addr))
return -EINVAL;

qp = unsupported_inst(template, slot, major_opcode, kprobe_inst, addr);
if (qp < 0)
return -EINVAL;

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));

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

return 0;
}
Expand Down

0 comments on commit 4781691

Please sign in to comment.