Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=df3e0d1c69c097f54588d720d39efdcdf31e3c24
Commit:     df3e0d1c69c097f54588d720d39efdcdf31e3c24
Parent:     08ed38b68099f2a492196414b08a7f5dd8dc3537
Author:     bibo,mao <[EMAIL PROTECTED]>
AuthorDate: Tue Dec 12 12:04:42 2006 -0800
Committer:  Tony Luck <[EMAIL PROTECTED]>
CommitDate: Tue Dec 12 12:04:42 2006 -0800

    [IA64] kprobe clears qp bits for special instructions
    
    On IA64 there exists some special instructions which
    always need to be executed regradless of qp bits, such
    as com.crel.unc, tbit.trel.unc etc.
    This patch clears qp bits when inserting kprobe trap code
    and disables probepoint on slot 1 for these special
    instructions.
    
    Signed-off-by: bibo,mao <[EMAIL PROTECTED]>
    Signed-off-by: Tony Luck <[EMAIL PROTECTED]>
---
 arch/ia64/kernel/kprobes.c |  175 ++++++++++++++++++++++++++++++-------------
 1 files changed, 122 insertions(+), 53 deletions(-)

diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 8406d24..6cb56dd 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -130,48 +130,6 @@ static void __kprobes update_kprobe_inst_flag(uint 
template, uint  slot,
 
 /*
  * 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
  * on which we are inserting kprobe is cmp instruction
  * with ctype as unc.
@@ -207,26 +165,136 @@ out:
 }
 
 /*
+ * 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:
@@ -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;
@@ -436,9 +505,9 @@ 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)
@@ -446,7 +515,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        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;
 }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to