[PATCH v5 3/3] kprobes: arm: enable OPTPROBES for ARM 32
From: Masami Hiramatsu <hidden>
Date: 2014-08-28 10:20:22
Also in:
lkml
(2014/08/27 22:02), Wang Nan wrote:
+/* + * ARM can always optimize an instruction when using ARM ISA. + */
Hmm, this comment looks not correct anymore :)
+int arch_prepared_optinsn(struct arch_optimized_insn *optinsn)
+{
+ return optinsn->prepared;
+}BTW, why don't you check optinsn->insn != NULL ? If it is not prepared for optimizing, optinsn->insn always be NULL. [...]
+int arch_prepare_optimized_kprobe(struct optimized_kprobe *op)
+{
+ u8 *buf;
+ unsigned long rel_chk;
+ unsigned long val;
+
+ if (!can_optimize(op))
+ return -EILSEQ;
+
+ op->optinsn.insn = get_optinsn_slot();
+ if (!op->optinsn.insn)
+ return -ENOMEM;
+
+ /*
+ * Verify if the address gap is in 32MiB range, because this uses
+ * a relative jump.
+ *
+ * kprobe opt use a 'b' instruction to branch to optinsn.insn.
+ * According to ARM manual, branch instruction is:
+ *
+ * 31 28 27 24 23 0
+ * +------+---+---+---+---+----------------+
+ * | cond | 1 | 0 | 1 | 0 | imm24 |
+ * +------+---+---+---+---+----------------+
+ *
+ * imm24 is a signed 24 bits integer. The real branch offset is computed
+ * by: imm32 = SignExtend(imm24:'00', 32);
+ *
+ * So the maximum forward branch should be:
+ * (0x007fffff << 2) = 0x01fffffc = 0x1fffffc
+ * The maximum backword branch should be:
+ * (0xff800000 << 2) = 0xfe000000 = -0x2000000
+ *
+ * We can simply check (rel & 0xfe000003):
+ * if rel is positive, (rel & 0xfe000000) shoule be 0
+ * if rel is negitive, (rel & 0xfe000000) should be 0xfe000000
+ * the last '3' is used for alignment checking.
+ */
+ rel_chk = (unsigned long)((long)op->optinsn.insn -
+ (long)op->kp.addr + 8) & 0xfe000003;
+
+ if ((rel_chk != 0) && (rel_chk != 0xfe000000)) {
+ __arch_remove_optimized_kprobe(op, 0);
+ return -ERANGE;
+ }
+
+ buf = (u8 *)op->optinsn.insn;
+
+ /* Copy arch-dep-instance from template */
+ memcpy(buf, &optprobe_template_entry, TMPL_END_IDX);
+
+ /* Set probe information */
+ val = (unsigned long)op;
+ memcpy(buf + TMPL_VAL_IDX, &val, sizeof(val));
+
+ /* Set probe function call */
+ val = (unsigned long)optimized_callback;
+ memcpy(buf + TMPL_CALL_IDX, &val, sizeof(val));
+
+ flush_icache_range((unsigned long)buf,
+ (unsigned long)buf + TMPL_END_IDX);
+
+ op->optinsn.prepared = true;
+ return 0;
+}
+Thank you, -- Masami HIRAMATSU Software Platform Research Dept. Linux Technology Research Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: masami.hiramatsu.pt at hitachi.com