* [PATCH -next 1/2] riscv: implemented auipc simulate instruction
@ 2021-06-29 2:34 ` Chen Lifu
0 siblings, 0 replies; 10+ messages in thread
From: Chen Lifu @ 2021-06-29 2:34 UTC (permalink / raw)
To: paul.walmsley, palmer, aou, guoren, chenlifu, penberg, mhiramat,
me, linux-riscv, linux-kernel
To test the kprobe-based event tracing, we prepare
a kernel module 'kprobe_test.ko' to add the probes.
The assembly codes (partially) of the module are as follows:
...
0000000000000000 <kprobe_test_branch>:
...
0000000000000038 <.LVL1>:
38: 00000597 auipc a1,0x0
3c: 00058593 mv a1,a1
...
Test the kprobe-based event tracing in qemu-system-riscv64:
First, install the kprobe test module:
insmod /root/kprobe_test.ko
Then, add a probe as a new event at an 'auipc' instruction,
the following error occurs due to the instruction not allowed to probe yet:
echo "p:auipc kprobe_test:kprobe_test_branch+0x38 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
This patch implemented the 'auipc' simulate instruction and allowed to probe it.
Merge this patch and perform the test again, the test results are as follows:
First, add a probe at the 'auipc' instruction:
echo "p:auipc kprobe_test:kprobe_test_branch+0x38 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo 1 > /sys/kernel/debug/tracing/events/kprobes/auipc/enable
Then, do something to run to the probe.
After that, see the traced information:
cat /sys/kernel/debug/tracing/trace
sysctl-58 [001] d... 179.126350: auipc: (kprobe_test_branch+0x38/0x10e [kprobe_test]) epc=0xffffffff016122aa opcode=0x100073
Now we can see the traced information.
The actual address of the symbol 'kprobe_test_branch' is as follows:
cat /proc/kallsyms | grep kprobe_test_branch
ffffffff01612272 t kprobe_test_branch [kprobe_test]
Based on the traced information and the actual address of the symbol
'kprobe_test_branch', we can also see that the 'auipc' instruction
has been replaced by 'ebreak(0x100073)' instruction.
--------
Signed-off-by: Chen Lifu <chenlifu@huawei.com>
---
arch/riscv/kernel/probes/decode-insn.c | 2 +-
arch/riscv/kernel/probes/simulate-insn.c | 34 ++++++++++++++++++++++++
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
index 0ed043acc882..5eb03fb61450 100644
--- a/arch/riscv/kernel/probes/decode-insn.c
+++ b/arch/riscv/kernel/probes/decode-insn.c
@@ -38,11 +38,11 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
RISCV_INSN_REJECTED(c_ebreak, insn);
#endif
- RISCV_INSN_REJECTED(auipc, insn);
RISCV_INSN_REJECTED(branch, insn);
RISCV_INSN_SET_SIMULATE(jal, insn);
RISCV_INSN_SET_SIMULATE(jalr, insn);
+ RISCV_INSN_SET_SIMULATE(auipc, insn);
return INSN_GOOD;
}
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
index 2519ce26377d..b81719522d5c 100644
--- a/arch/riscv/kernel/probes/simulate-insn.c
+++ b/arch/riscv/kernel/probes/simulate-insn.c
@@ -83,3 +83,37 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
return ret;
}
+
+#define auipc_rd_idx(opcode) \
+ ((opcode >> 7) & 0x1f)
+
+#define auipc_imm(opcode) \
+ ((((opcode) >> 12) & 0xfffff) << 12)
+
+#if __riscv_xlen == 64
+#define auipc_offset(opcode) sign_extend64(auipc_imm(opcode), 31)
+#elif __riscv_xlen == 32
+#define auipc_offset(opcode) auipc_imm(opcode)
+#else
+#error "Unexpected __riscv_xlen"
+#endif
+
+bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *regs)
+{
+ /*
+ * auipc instruction:
+ * 31 12 11 7 6 0
+ * | imm[31:12] | rd | opcode |
+ * 20 5 7
+ */
+
+ u32 rd_idx = auipc_rd_idx(opcode);
+ unsigned long rd_val = addr + auipc_offset(opcode);
+
+ if (!rv_insn_reg_set_val(regs, rd_idx, rd_val))
+ return false;
+
+ instruction_pointer_set(regs, addr + 4);
+
+ return true;
+}
--
2.32.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH -next 1/2] riscv: implemented auipc simulate instruction
@ 2021-06-29 2:34 ` Chen Lifu
0 siblings, 0 replies; 10+ messages in thread
From: Chen Lifu @ 2021-06-29 2:34 UTC (permalink / raw)
To: paul.walmsley, palmer, aou, guoren, chenlifu, penberg, mhiramat,
me, linux-riscv, linux-kernel
To test the kprobe-based event tracing, we prepare
a kernel module 'kprobe_test.ko' to add the probes.
The assembly codes (partially) of the module are as follows:
...
0000000000000000 <kprobe_test_branch>:
...
0000000000000038 <.LVL1>:
38: 00000597 auipc a1,0x0
3c: 00058593 mv a1,a1
...
Test the kprobe-based event tracing in qemu-system-riscv64:
First, install the kprobe test module:
insmod /root/kprobe_test.ko
Then, add a probe as a new event at an 'auipc' instruction,
the following error occurs due to the instruction not allowed to probe yet:
echo "p:auipc kprobe_test:kprobe_test_branch+0x38 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
This patch implemented the 'auipc' simulate instruction and allowed to probe it.
Merge this patch and perform the test again, the test results are as follows:
First, add a probe at the 'auipc' instruction:
echo "p:auipc kprobe_test:kprobe_test_branch+0x38 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo 1 > /sys/kernel/debug/tracing/events/kprobes/auipc/enable
Then, do something to run to the probe.
After that, see the traced information:
cat /sys/kernel/debug/tracing/trace
sysctl-58 [001] d... 179.126350: auipc: (kprobe_test_branch+0x38/0x10e [kprobe_test]) epc=0xffffffff016122aa opcode=0x100073
Now we can see the traced information.
The actual address of the symbol 'kprobe_test_branch' is as follows:
cat /proc/kallsyms | grep kprobe_test_branch
ffffffff01612272 t kprobe_test_branch [kprobe_test]
Based on the traced information and the actual address of the symbol
'kprobe_test_branch', we can also see that the 'auipc' instruction
has been replaced by 'ebreak(0x100073)' instruction.
--------
Signed-off-by: Chen Lifu <chenlifu@huawei.com>
---
arch/riscv/kernel/probes/decode-insn.c | 2 +-
arch/riscv/kernel/probes/simulate-insn.c | 34 ++++++++++++++++++++++++
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
index 0ed043acc882..5eb03fb61450 100644
--- a/arch/riscv/kernel/probes/decode-insn.c
+++ b/arch/riscv/kernel/probes/decode-insn.c
@@ -38,11 +38,11 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
RISCV_INSN_REJECTED(c_ebreak, insn);
#endif
- RISCV_INSN_REJECTED(auipc, insn);
RISCV_INSN_REJECTED(branch, insn);
RISCV_INSN_SET_SIMULATE(jal, insn);
RISCV_INSN_SET_SIMULATE(jalr, insn);
+ RISCV_INSN_SET_SIMULATE(auipc, insn);
return INSN_GOOD;
}
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
index 2519ce26377d..b81719522d5c 100644
--- a/arch/riscv/kernel/probes/simulate-insn.c
+++ b/arch/riscv/kernel/probes/simulate-insn.c
@@ -83,3 +83,37 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
return ret;
}
+
+#define auipc_rd_idx(opcode) \
+ ((opcode >> 7) & 0x1f)
+
+#define auipc_imm(opcode) \
+ ((((opcode) >> 12) & 0xfffff) << 12)
+
+#if __riscv_xlen == 64
+#define auipc_offset(opcode) sign_extend64(auipc_imm(opcode), 31)
+#elif __riscv_xlen == 32
+#define auipc_offset(opcode) auipc_imm(opcode)
+#else
+#error "Unexpected __riscv_xlen"
+#endif
+
+bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *regs)
+{
+ /*
+ * auipc instruction:
+ * 31 12 11 7 6 0
+ * | imm[31:12] | rd | opcode |
+ * 20 5 7
+ */
+
+ u32 rd_idx = auipc_rd_idx(opcode);
+ unsigned long rd_val = addr + auipc_offset(opcode);
+
+ if (!rv_insn_reg_set_val(regs, rd_idx, rd_val))
+ return false;
+
+ instruction_pointer_set(regs, addr + 4);
+
+ return true;
+}
--
2.32.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH -next 2/2] riscv: implemented branch simulate instructions
2021-06-29 2:34 ` Chen Lifu
@ 2021-06-29 2:34 ` Chen Lifu
-1 siblings, 0 replies; 10+ messages in thread
From: Chen Lifu @ 2021-06-29 2:34 UTC (permalink / raw)
To: paul.walmsley, palmer, aou, guoren, chenlifu, penberg, mhiramat,
me, linux-riscv, linux-kernel
To test the kprobe-based event tracing, we prepare
a kernel module 'kprobe_test.ko' to add the probes.
The assembly codes (partially) of the module are as follows:
...
0000000000000000 <kprobe_test_branch>:
...
0000000000000080 <.L7>:
80: 414986bb subw a3,s3,s4
84: 4785 li a5,1
86: 00d7c363 blt a5,a3,8c <.L8>
8a: 2485 addiw s1,s1,1
000000000000008c <.L8>:
8c: 012987bb addw a5,s3,s2
90: 4711 li a4,4
92: 00f75363 bge a4,a5,98 <.L9>
96: 2485 addiw s1,s1,1
...
00000000000000aa <.L11>:
aa: 01299363 bne s3,s2,b0 <.L12>
ae: 2485 addiw s1,s1,1
00000000000000b0 <.L12>:
b0: 012a0363 beq s4,s2,b6 <.L13>
b4: 2485 addiw s1,s1,1
...
00000000000000c2 <.L14>:
c2: 0009861b sext.w a2,s3
c6: 013a7363 bgeu s4,s3,cc <.L15>
ca: 2485 addiw s1,s1,1
...
00000000000000d2 <.L16>:
d2: 00e7e363 bltu a5,a4,d8 <.L17>
d6: 2485 addiw s1,s1,1
...
Test the kprobe-based event tracing in qemu-system-riscv64:
First, install the kprobe test module:
insmod /root/kprobe_test.ko
Then, add probes as new events at the branch instructions,
i.e. blt, bge, bne, beq, bgeu and bltu.
The following errors occur due to the instructions not allowed to probe yet:
echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
This patch implemented the branch simulate instructions and allowed to probe them.
Merge this patch and perform the test again, the test results are as follows:
First, add probes at the branch instructions:
echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo 1 > /sys/kernel/debug/tracing/events/kprobes/blt/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/bge/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/bne/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/beq/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/bgeu/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/bltu/enable
Then, do something to run to the probes.
After that, see the traced information:
cat /sys/kernel/debug/tracing/trace
sysctl-63 [001] d... 2505.263969: blt: (kprobe_test_branch+0x86/0x10e [kprobe_test]) epc=0xffffffff016122f8 opcode=0x100073
sysctl-63 [001] d... 2505.263991: bge: (kprobe_test_branch+0x92/0x10e [kprobe_test]) epc=0xffffffff01612304 opcode=0x100073
sysctl-63 [001] d... 2505.264001: bne: (kprobe_test_branch+0xaa/0x10e [kprobe_test]) epc=0xffffffff0161231c opcode=0x100073
sysctl-63 [001] d... 2505.264011: beq: (kprobe_test_branch+0xb0/0x10e [kprobe_test]) epc=0xffffffff01612322 opcode=0x100073
sysctl-63 [001] d... 2505.264019: bgeu: (kprobe_test_branch+0xc6/0x10e [kprobe_test]) epc=0xffffffff01612338 opcode=0x100073
sysctl-63 [001] d... 2505.264027: bltu: (kprobe_test_branch+0xd2/0x10e [kprobe_test]) epc=0xffffffff01612344 opcode=0x100073
Now we can see the traced information.
The actual address of the symbol 'kprobe_test_branch' is as follows:
cat /proc/kallsyms | grep kprobe_test_branch
ffffffff01612272 t kprobe_test_branch [kprobe_test]
Based on the traced information and the actual address of the symbol
'kprobe_test_branch', we can also see that the branch instructions
have been replaced by 'ebreak(0x100073)' instructions.
The pesudoinstructions of the branch instructions,
i.e. bnez, beqz, blez, bgez, bltz, bgtz, bleu, bgtu and ble
are allowed to probe as well.
--------
Signed-off-by: Chen Lifu <chenlifu@huawei.com>
---
arch/riscv/kernel/probes/decode-insn.c | 3 +-
arch/riscv/kernel/probes/simulate-insn.c | 78 ++++++++++++++++++++++++
2 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
index 5eb03fb61450..64f6183b4717 100644
--- a/arch/riscv/kernel/probes/decode-insn.c
+++ b/arch/riscv/kernel/probes/decode-insn.c
@@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
RISCV_INSN_REJECTED(c_ebreak, insn);
#endif
- RISCV_INSN_REJECTED(branch, insn);
-
RISCV_INSN_SET_SIMULATE(jal, insn);
RISCV_INSN_SET_SIMULATE(jalr, insn);
RISCV_INSN_SET_SIMULATE(auipc, insn);
+ RISCV_INSN_SET_SIMULATE(branch, insn);
return INSN_GOOD;
}
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
index b81719522d5c..efc989b28859 100644
--- a/arch/riscv/kernel/probes/simulate-insn.c
+++ b/arch/riscv/kernel/probes/simulate-insn.c
@@ -117,3 +117,81 @@ bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *re
return true;
}
+
+#define branch_rs1_idx(opcode) \
+ (((opcode) >> 15) & 0x1f)
+
+#define branch_rs2_idx(opcode) \
+ (((opcode) >> 20) & 0x1f)
+
+#define branch_funct3(opcode) \
+ (((opcode) >> 12) & 0x7)
+
+#define branch_imm(opcode) \
+ (((((opcode) >> 8 ) & 0xf ) << 1 ) | \
+ ((((opcode) >> 25) & 0x3f) << 5 ) | \
+ ((((opcode) >> 7 ) & 0x1 ) << 11) | \
+ ((((opcode) >> 31) & 0x1 ) << 12))
+
+#define branch_offset(opcode) \
+ sign_extend32((branch_imm(opcode)), 12)
+
+#define BRANCH_BEQ 0x0
+#define BRANCH_BNE 0x1
+#define BRANCH_BLT 0x4
+#define BRANCH_BGE 0x5
+#define BRANCH_BLTU 0x6
+#define BRANCH_BGEU 0x7
+
+bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs)
+{
+ /*
+ * branch instructions:
+ * 31 30 25 24 20 19 15 14 12 11 8 7 6 0
+ * | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
+ * 1 6 5 5 3 4 1 7
+ * imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 BEQ
+ * imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 BNE
+ * imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 BLT
+ * imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 BGE
+ * imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 BLTU
+ * imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 BGEU
+ */
+
+ s32 offset;
+ s32 offset_tmp;
+ unsigned long rs1_val;
+ unsigned long rs2_val;
+
+ if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
+ !rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
+ return false;
+
+ offset_tmp = branch_offset(opcode);
+ switch (branch_funct3(opcode)) {
+ case BRANCH_BEQ:
+ offset = (rs1_val == rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BNE:
+ offset = (rs1_val != rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BLT:
+ offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BGE:
+ offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BLTU:
+ offset = (rs1_val < rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BGEU:
+ offset = (rs1_val >= rs2_val) ? offset_tmp : 4;
+ break;
+ default:
+ return false;
+ }
+
+ instruction_pointer_set(regs, addr + offset);
+
+ return true;
+}
--
2.32.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH -next 2/2] riscv: implemented branch simulate instructions
@ 2021-06-29 2:34 ` Chen Lifu
0 siblings, 0 replies; 10+ messages in thread
From: Chen Lifu @ 2021-06-29 2:34 UTC (permalink / raw)
To: paul.walmsley, palmer, aou, guoren, chenlifu, penberg, mhiramat,
me, linux-riscv, linux-kernel
To test the kprobe-based event tracing, we prepare
a kernel module 'kprobe_test.ko' to add the probes.
The assembly codes (partially) of the module are as follows:
...
0000000000000000 <kprobe_test_branch>:
...
0000000000000080 <.L7>:
80: 414986bb subw a3,s3,s4
84: 4785 li a5,1
86: 00d7c363 blt a5,a3,8c <.L8>
8a: 2485 addiw s1,s1,1
000000000000008c <.L8>:
8c: 012987bb addw a5,s3,s2
90: 4711 li a4,4
92: 00f75363 bge a4,a5,98 <.L9>
96: 2485 addiw s1,s1,1
...
00000000000000aa <.L11>:
aa: 01299363 bne s3,s2,b0 <.L12>
ae: 2485 addiw s1,s1,1
00000000000000b0 <.L12>:
b0: 012a0363 beq s4,s2,b6 <.L13>
b4: 2485 addiw s1,s1,1
...
00000000000000c2 <.L14>:
c2: 0009861b sext.w a2,s3
c6: 013a7363 bgeu s4,s3,cc <.L15>
ca: 2485 addiw s1,s1,1
...
00000000000000d2 <.L16>:
d2: 00e7e363 bltu a5,a4,d8 <.L17>
d6: 2485 addiw s1,s1,1
...
Test the kprobe-based event tracing in qemu-system-riscv64:
First, install the kprobe test module:
insmod /root/kprobe_test.ko
Then, add probes as new events at the branch instructions,
i.e. blt, bge, bne, beq, bgeu and bltu.
The following errors occur due to the instructions not allowed to probe yet:
echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
sh: write error: Invalid argument
This patch implemented the branch simulate instructions and allowed to probe them.
Merge this patch and perform the test again, the test results are as follows:
First, add probes at the branch instructions:
echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
echo 1 > /sys/kernel/debug/tracing/events/kprobes/blt/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/bge/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/bne/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/beq/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/bgeu/enable
echo 1 > /sys/kernel/debug/tracing/events/kprobes/bltu/enable
Then, do something to run to the probes.
After that, see the traced information:
cat /sys/kernel/debug/tracing/trace
sysctl-63 [001] d... 2505.263969: blt: (kprobe_test_branch+0x86/0x10e [kprobe_test]) epc=0xffffffff016122f8 opcode=0x100073
sysctl-63 [001] d... 2505.263991: bge: (kprobe_test_branch+0x92/0x10e [kprobe_test]) epc=0xffffffff01612304 opcode=0x100073
sysctl-63 [001] d... 2505.264001: bne: (kprobe_test_branch+0xaa/0x10e [kprobe_test]) epc=0xffffffff0161231c opcode=0x100073
sysctl-63 [001] d... 2505.264011: beq: (kprobe_test_branch+0xb0/0x10e [kprobe_test]) epc=0xffffffff01612322 opcode=0x100073
sysctl-63 [001] d... 2505.264019: bgeu: (kprobe_test_branch+0xc6/0x10e [kprobe_test]) epc=0xffffffff01612338 opcode=0x100073
sysctl-63 [001] d... 2505.264027: bltu: (kprobe_test_branch+0xd2/0x10e [kprobe_test]) epc=0xffffffff01612344 opcode=0x100073
Now we can see the traced information.
The actual address of the symbol 'kprobe_test_branch' is as follows:
cat /proc/kallsyms | grep kprobe_test_branch
ffffffff01612272 t kprobe_test_branch [kprobe_test]
Based on the traced information and the actual address of the symbol
'kprobe_test_branch', we can also see that the branch instructions
have been replaced by 'ebreak(0x100073)' instructions.
The pesudoinstructions of the branch instructions,
i.e. bnez, beqz, blez, bgez, bltz, bgtz, bleu, bgtu and ble
are allowed to probe as well.
--------
Signed-off-by: Chen Lifu <chenlifu@huawei.com>
---
arch/riscv/kernel/probes/decode-insn.c | 3 +-
arch/riscv/kernel/probes/simulate-insn.c | 78 ++++++++++++++++++++++++
2 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
index 5eb03fb61450..64f6183b4717 100644
--- a/arch/riscv/kernel/probes/decode-insn.c
+++ b/arch/riscv/kernel/probes/decode-insn.c
@@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
RISCV_INSN_REJECTED(c_ebreak, insn);
#endif
- RISCV_INSN_REJECTED(branch, insn);
-
RISCV_INSN_SET_SIMULATE(jal, insn);
RISCV_INSN_SET_SIMULATE(jalr, insn);
RISCV_INSN_SET_SIMULATE(auipc, insn);
+ RISCV_INSN_SET_SIMULATE(branch, insn);
return INSN_GOOD;
}
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
index b81719522d5c..efc989b28859 100644
--- a/arch/riscv/kernel/probes/simulate-insn.c
+++ b/arch/riscv/kernel/probes/simulate-insn.c
@@ -117,3 +117,81 @@ bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *re
return true;
}
+
+#define branch_rs1_idx(opcode) \
+ (((opcode) >> 15) & 0x1f)
+
+#define branch_rs2_idx(opcode) \
+ (((opcode) >> 20) & 0x1f)
+
+#define branch_funct3(opcode) \
+ (((opcode) >> 12) & 0x7)
+
+#define branch_imm(opcode) \
+ (((((opcode) >> 8 ) & 0xf ) << 1 ) | \
+ ((((opcode) >> 25) & 0x3f) << 5 ) | \
+ ((((opcode) >> 7 ) & 0x1 ) << 11) | \
+ ((((opcode) >> 31) & 0x1 ) << 12))
+
+#define branch_offset(opcode) \
+ sign_extend32((branch_imm(opcode)), 12)
+
+#define BRANCH_BEQ 0x0
+#define BRANCH_BNE 0x1
+#define BRANCH_BLT 0x4
+#define BRANCH_BGE 0x5
+#define BRANCH_BLTU 0x6
+#define BRANCH_BGEU 0x7
+
+bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs)
+{
+ /*
+ * branch instructions:
+ * 31 30 25 24 20 19 15 14 12 11 8 7 6 0
+ * | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
+ * 1 6 5 5 3 4 1 7
+ * imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 BEQ
+ * imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 BNE
+ * imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 BLT
+ * imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 BGE
+ * imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 BLTU
+ * imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 BGEU
+ */
+
+ s32 offset;
+ s32 offset_tmp;
+ unsigned long rs1_val;
+ unsigned long rs2_val;
+
+ if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
+ !rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
+ return false;
+
+ offset_tmp = branch_offset(opcode);
+ switch (branch_funct3(opcode)) {
+ case BRANCH_BEQ:
+ offset = (rs1_val == rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BNE:
+ offset = (rs1_val != rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BLT:
+ offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BGE:
+ offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BLTU:
+ offset = (rs1_val < rs2_val) ? offset_tmp : 4;
+ break;
+ case BRANCH_BGEU:
+ offset = (rs1_val >= rs2_val) ? offset_tmp : 4;
+ break;
+ default:
+ return false;
+ }
+
+ instruction_pointer_set(regs, addr + offset);
+
+ return true;
+}
--
2.32.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 10+ messages in thread
* ping//Re: [PATCH -next 2/2] riscv: implemented branch simulate instructions
2021-06-29 2:34 ` Chen Lifu
@ 2021-07-05 2:09 ` chenlifu
-1 siblings, 0 replies; 10+ messages in thread
From: chenlifu @ 2021-07-05 2:09 UTC (permalink / raw)
To: paul.walmsley, palmer, aou, guoren, penberg, mhiramat, me,
linux-riscv, linux-kernel
在 2021/6/29 10:34, Chen Lifu 写道:
> To test the kprobe-based event tracing, we prepare
> a kernel module 'kprobe_test.ko' to add the probes.
> The assembly codes (partially) of the module are as follows:
> ...
> 0000000000000000 <kprobe_test_branch>:
> ...
>
> 0000000000000080 <.L7>:
> 80: 414986bb subw a3,s3,s4
> 84: 4785 li a5,1
> 86: 00d7c363 blt a5,a3,8c <.L8>
> 8a: 2485 addiw s1,s1,1
>
> 000000000000008c <.L8>:
> 8c: 012987bb addw a5,s3,s2
> 90: 4711 li a4,4
> 92: 00f75363 bge a4,a5,98 <.L9>
> 96: 2485 addiw s1,s1,1
> ...
>
> 00000000000000aa <.L11>:
> aa: 01299363 bne s3,s2,b0 <.L12>
> ae: 2485 addiw s1,s1,1
>
> 00000000000000b0 <.L12>:
> b0: 012a0363 beq s4,s2,b6 <.L13>
> b4: 2485 addiw s1,s1,1
> ...
>
> 00000000000000c2 <.L14>:
> c2: 0009861b sext.w a2,s3
> c6: 013a7363 bgeu s4,s3,cc <.L15>
> ca: 2485 addiw s1,s1,1
> ...
>
> 00000000000000d2 <.L16>:
> d2: 00e7e363 bltu a5,a4,d8 <.L17>
> d6: 2485 addiw s1,s1,1
> ...
>
> Test the kprobe-based event tracing in qemu-system-riscv64:
> First, install the kprobe test module:
> insmod /root/kprobe_test.ko
>
> Then, add probes as new events at the branch instructions,
> i.e. blt, bge, bne, beq, bgeu and bltu.
> The following errors occur due to the instructions not allowed to probe yet:
> echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
>
> This patch implemented the branch simulate instructions and allowed to probe them.
> Merge this patch and perform the test again, the test results are as follows:
> First, add probes at the branch instructions:
> echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/blt/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bge/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bne/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/beq/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bgeu/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bltu/enable
>
> Then, do something to run to the probes.
> After that, see the traced information:
> cat /sys/kernel/debug/tracing/trace
> sysctl-63 [001] d... 2505.263969: blt: (kprobe_test_branch+0x86/0x10e [kprobe_test]) epc=0xffffffff016122f8 opcode=0x100073
> sysctl-63 [001] d... 2505.263991: bge: (kprobe_test_branch+0x92/0x10e [kprobe_test]) epc=0xffffffff01612304 opcode=0x100073
> sysctl-63 [001] d... 2505.264001: bne: (kprobe_test_branch+0xaa/0x10e [kprobe_test]) epc=0xffffffff0161231c opcode=0x100073
> sysctl-63 [001] d... 2505.264011: beq: (kprobe_test_branch+0xb0/0x10e [kprobe_test]) epc=0xffffffff01612322 opcode=0x100073
> sysctl-63 [001] d... 2505.264019: bgeu: (kprobe_test_branch+0xc6/0x10e [kprobe_test]) epc=0xffffffff01612338 opcode=0x100073
> sysctl-63 [001] d... 2505.264027: bltu: (kprobe_test_branch+0xd2/0x10e [kprobe_test]) epc=0xffffffff01612344 opcode=0x100073
>
> Now we can see the traced information.
> The actual address of the symbol 'kprobe_test_branch' is as follows:
> cat /proc/kallsyms | grep kprobe_test_branch
> ffffffff01612272 t kprobe_test_branch [kprobe_test]
>
> Based on the traced information and the actual address of the symbol
> 'kprobe_test_branch', we can also see that the branch instructions
> have been replaced by 'ebreak(0x100073)' instructions.
>
> The pesudoinstructions of the branch instructions,
> i.e. bnez, beqz, blez, bgez, bltz, bgtz, bleu, bgtu and ble
> are allowed to probe as well.
>
> --------
>
> Signed-off-by: Chen Lifu <chenlifu@huawei.com>
> ---
> arch/riscv/kernel/probes/decode-insn.c | 3 +-
> arch/riscv/kernel/probes/simulate-insn.c | 78 ++++++++++++++++++++++++
> 2 files changed, 79 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
> index 5eb03fb61450..64f6183b4717 100644
> --- a/arch/riscv/kernel/probes/decode-insn.c
> +++ b/arch/riscv/kernel/probes/decode-insn.c
> @@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
> RISCV_INSN_REJECTED(c_ebreak, insn);
> #endif
>
> - RISCV_INSN_REJECTED(branch, insn);
> -
> RISCV_INSN_SET_SIMULATE(jal, insn);
> RISCV_INSN_SET_SIMULATE(jalr, insn);
> RISCV_INSN_SET_SIMULATE(auipc, insn);
> + RISCV_INSN_SET_SIMULATE(branch, insn);
>
> return INSN_GOOD;
> }
> diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
> index b81719522d5c..efc989b28859 100644
> --- a/arch/riscv/kernel/probes/simulate-insn.c
> +++ b/arch/riscv/kernel/probes/simulate-insn.c
> @@ -117,3 +117,81 @@ bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *re
>
> return true;
> }
> +
> +#define branch_rs1_idx(opcode) \
> + (((opcode) >> 15) & 0x1f)
> +
> +#define branch_rs2_idx(opcode) \
> + (((opcode) >> 20) & 0x1f)
> +
> +#define branch_funct3(opcode) \
> + (((opcode) >> 12) & 0x7)
> +
> +#define branch_imm(opcode) \
> + (((((opcode) >> 8 ) & 0xf ) << 1 ) | \
> + ((((opcode) >> 25) & 0x3f) << 5 ) | \
> + ((((opcode) >> 7 ) & 0x1 ) << 11) | \
> + ((((opcode) >> 31) & 0x1 ) << 12))
> +
> +#define branch_offset(opcode) \
> + sign_extend32((branch_imm(opcode)), 12)
> +
> +#define BRANCH_BEQ 0x0
> +#define BRANCH_BNE 0x1
> +#define BRANCH_BLT 0x4
> +#define BRANCH_BGE 0x5
> +#define BRANCH_BLTU 0x6
> +#define BRANCH_BGEU 0x7
> +
> +bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs)
> +{
> + /*
> + * branch instructions:
> + * 31 30 25 24 20 19 15 14 12 11 8 7 6 0
> + * | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
> + * 1 6 5 5 3 4 1 7
> + * imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 BEQ
> + * imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 BNE
> + * imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 BLT
> + * imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 BGE
> + * imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 BLTU
> + * imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 BGEU
> + */
> +
> + s32 offset;
> + s32 offset_tmp;
> + unsigned long rs1_val;
> + unsigned long rs2_val;
> +
> + if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
> + !rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
> + return false;
> +
> + offset_tmp = branch_offset(opcode);
> + switch (branch_funct3(opcode)) {
> + case BRANCH_BEQ:
> + offset = (rs1_val == rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BNE:
> + offset = (rs1_val != rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BLT:
> + offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BGE:
> + offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BLTU:
> + offset = (rs1_val < rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BGEU:
> + offset = (rs1_val >= rs2_val) ? offset_tmp : 4;
> + break;
> + default:
> + return false;
> + }
> +
> + instruction_pointer_set(regs, addr + offset);
> +
> + return true;
> +}
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* ping//Re: [PATCH -next 2/2] riscv: implemented branch simulate instructions
@ 2021-07-05 2:09 ` chenlifu
0 siblings, 0 replies; 10+ messages in thread
From: chenlifu @ 2021-07-05 2:09 UTC (permalink / raw)
To: paul.walmsley, palmer, aou, guoren, penberg, mhiramat, me,
linux-riscv, linux-kernel
在 2021/6/29 10:34, Chen Lifu 写道:
> To test the kprobe-based event tracing, we prepare
> a kernel module 'kprobe_test.ko' to add the probes.
> The assembly codes (partially) of the module are as follows:
> ...
> 0000000000000000 <kprobe_test_branch>:
> ...
>
> 0000000000000080 <.L7>:
> 80: 414986bb subw a3,s3,s4
> 84: 4785 li a5,1
> 86: 00d7c363 blt a5,a3,8c <.L8>
> 8a: 2485 addiw s1,s1,1
>
> 000000000000008c <.L8>:
> 8c: 012987bb addw a5,s3,s2
> 90: 4711 li a4,4
> 92: 00f75363 bge a4,a5,98 <.L9>
> 96: 2485 addiw s1,s1,1
> ...
>
> 00000000000000aa <.L11>:
> aa: 01299363 bne s3,s2,b0 <.L12>
> ae: 2485 addiw s1,s1,1
>
> 00000000000000b0 <.L12>:
> b0: 012a0363 beq s4,s2,b6 <.L13>
> b4: 2485 addiw s1,s1,1
> ...
>
> 00000000000000c2 <.L14>:
> c2: 0009861b sext.w a2,s3
> c6: 013a7363 bgeu s4,s3,cc <.L15>
> ca: 2485 addiw s1,s1,1
> ...
>
> 00000000000000d2 <.L16>:
> d2: 00e7e363 bltu a5,a4,d8 <.L17>
> d6: 2485 addiw s1,s1,1
> ...
>
> Test the kprobe-based event tracing in qemu-system-riscv64:
> First, install the kprobe test module:
> insmod /root/kprobe_test.ko
>
> Then, add probes as new events at the branch instructions,
> i.e. blt, bge, bne, beq, bgeu and bltu.
> The following errors occur due to the instructions not allowed to probe yet:
> echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
> echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
>
> This patch implemented the branch simulate instructions and allowed to probe them.
> Merge this patch and perform the test again, the test results are as follows:
> First, add probes at the branch instructions:
> echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/blt/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bge/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bne/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/beq/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bgeu/enable
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bltu/enable
>
> Then, do something to run to the probes.
> After that, see the traced information:
> cat /sys/kernel/debug/tracing/trace
> sysctl-63 [001] d... 2505.263969: blt: (kprobe_test_branch+0x86/0x10e [kprobe_test]) epc=0xffffffff016122f8 opcode=0x100073
> sysctl-63 [001] d... 2505.263991: bge: (kprobe_test_branch+0x92/0x10e [kprobe_test]) epc=0xffffffff01612304 opcode=0x100073
> sysctl-63 [001] d... 2505.264001: bne: (kprobe_test_branch+0xaa/0x10e [kprobe_test]) epc=0xffffffff0161231c opcode=0x100073
> sysctl-63 [001] d... 2505.264011: beq: (kprobe_test_branch+0xb0/0x10e [kprobe_test]) epc=0xffffffff01612322 opcode=0x100073
> sysctl-63 [001] d... 2505.264019: bgeu: (kprobe_test_branch+0xc6/0x10e [kprobe_test]) epc=0xffffffff01612338 opcode=0x100073
> sysctl-63 [001] d... 2505.264027: bltu: (kprobe_test_branch+0xd2/0x10e [kprobe_test]) epc=0xffffffff01612344 opcode=0x100073
>
> Now we can see the traced information.
> The actual address of the symbol 'kprobe_test_branch' is as follows:
> cat /proc/kallsyms | grep kprobe_test_branch
> ffffffff01612272 t kprobe_test_branch [kprobe_test]
>
> Based on the traced information and the actual address of the symbol
> 'kprobe_test_branch', we can also see that the branch instructions
> have been replaced by 'ebreak(0x100073)' instructions.
>
> The pesudoinstructions of the branch instructions,
> i.e. bnez, beqz, blez, bgez, bltz, bgtz, bleu, bgtu and ble
> are allowed to probe as well.
>
> --------
>
> Signed-off-by: Chen Lifu <chenlifu@huawei.com>
> ---
> arch/riscv/kernel/probes/decode-insn.c | 3 +-
> arch/riscv/kernel/probes/simulate-insn.c | 78 ++++++++++++++++++++++++
> 2 files changed, 79 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
> index 5eb03fb61450..64f6183b4717 100644
> --- a/arch/riscv/kernel/probes/decode-insn.c
> +++ b/arch/riscv/kernel/probes/decode-insn.c
> @@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
> RISCV_INSN_REJECTED(c_ebreak, insn);
> #endif
>
> - RISCV_INSN_REJECTED(branch, insn);
> -
> RISCV_INSN_SET_SIMULATE(jal, insn);
> RISCV_INSN_SET_SIMULATE(jalr, insn);
> RISCV_INSN_SET_SIMULATE(auipc, insn);
> + RISCV_INSN_SET_SIMULATE(branch, insn);
>
> return INSN_GOOD;
> }
> diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
> index b81719522d5c..efc989b28859 100644
> --- a/arch/riscv/kernel/probes/simulate-insn.c
> +++ b/arch/riscv/kernel/probes/simulate-insn.c
> @@ -117,3 +117,81 @@ bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *re
>
> return true;
> }
> +
> +#define branch_rs1_idx(opcode) \
> + (((opcode) >> 15) & 0x1f)
> +
> +#define branch_rs2_idx(opcode) \
> + (((opcode) >> 20) & 0x1f)
> +
> +#define branch_funct3(opcode) \
> + (((opcode) >> 12) & 0x7)
> +
> +#define branch_imm(opcode) \
> + (((((opcode) >> 8 ) & 0xf ) << 1 ) | \
> + ((((opcode) >> 25) & 0x3f) << 5 ) | \
> + ((((opcode) >> 7 ) & 0x1 ) << 11) | \
> + ((((opcode) >> 31) & 0x1 ) << 12))
> +
> +#define branch_offset(opcode) \
> + sign_extend32((branch_imm(opcode)), 12)
> +
> +#define BRANCH_BEQ 0x0
> +#define BRANCH_BNE 0x1
> +#define BRANCH_BLT 0x4
> +#define BRANCH_BGE 0x5
> +#define BRANCH_BLTU 0x6
> +#define BRANCH_BGEU 0x7
> +
> +bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs)
> +{
> + /*
> + * branch instructions:
> + * 31 30 25 24 20 19 15 14 12 11 8 7 6 0
> + * | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
> + * 1 6 5 5 3 4 1 7
> + * imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 BEQ
> + * imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 BNE
> + * imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 BLT
> + * imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 BGE
> + * imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 BLTU
> + * imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 BGEU
> + */
> +
> + s32 offset;
> + s32 offset_tmp;
> + unsigned long rs1_val;
> + unsigned long rs2_val;
> +
> + if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
> + !rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
> + return false;
> +
> + offset_tmp = branch_offset(opcode);
> + switch (branch_funct3(opcode)) {
> + case BRANCH_BEQ:
> + offset = (rs1_val == rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BNE:
> + offset = (rs1_val != rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BLT:
> + offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BGE:
> + offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BLTU:
> + offset = (rs1_val < rs2_val) ? offset_tmp : 4;
> + break;
> + case BRANCH_BGEU:
> + offset = (rs1_val >= rs2_val) ? offset_tmp : 4;
> + break;
> + default:
> + return false;
> + }
> +
> + instruction_pointer_set(regs, addr + offset);
> +
> + return true;
> +}
>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 10+ messages in thread
* ping//Re: ping//Re: [PATCH -next 2/2] riscv: implemented branch simulate instructions
2021-07-05 2:09 ` chenlifu
@ 2021-07-22 10:15 ` chenlifu
-1 siblings, 0 replies; 10+ messages in thread
From: chenlifu @ 2021-07-22 10:15 UTC (permalink / raw)
To: paul.walmsley, palmer, aou, guoren, penberg, mhiramat, me,
linux-riscv, linux-kernel
在 2021/7/5 10:09, chenlifu 写道:
>
>
> 在 2021/6/29 10:34, Chen Lifu 写道:
>> To test the kprobe-based event tracing, we prepare
>> a kernel module 'kprobe_test.ko' to add the probes.
>> The assembly codes (partially) of the module are as follows:
>> ...
>> 0000000000000000 <kprobe_test_branch>:
>> ...
>>
>> 0000000000000080 <.L7>:
>> 80: 414986bb subw a3,s3,s4
>> 84: 4785 li a5,1
>> 86: 00d7c363 blt a5,a3,8c <.L8>
>> 8a: 2485 addiw s1,s1,1
>>
>> 000000000000008c <.L8>:
>> 8c: 012987bb addw a5,s3,s2
>> 90: 4711 li a4,4
>> 92: 00f75363 bge a4,a5,98 <.L9>
>> 96: 2485 addiw s1,s1,1
>> ...
>>
>> 00000000000000aa <.L11>:
>> aa: 01299363 bne s3,s2,b0 <.L12>
>> ae: 2485 addiw s1,s1,1
>>
>> 00000000000000b0 <.L12>:
>> b0: 012a0363 beq s4,s2,b6 <.L13>
>> b4: 2485 addiw s1,s1,1
>> ...
>>
>> 00000000000000c2 <.L14>:
>> c2: 0009861b sext.w a2,s3
>> c6: 013a7363 bgeu s4,s3,cc <.L15>
>> ca: 2485 addiw s1,s1,1
>> ...
>>
>> 00000000000000d2 <.L16>:
>> d2: 00e7e363 bltu a5,a4,d8 <.L17>
>> d6: 2485 addiw s1,s1,1
>> ...
>>
>> Test the kprobe-based event tracing in qemu-system-riscv64:
>> First, install the kprobe test module:
>> insmod /root/kprobe_test.ko
>>
>> Then, add probes as new events at the branch instructions,
>> i.e. blt, bge, bne, beq, bgeu and bltu.
>> The following errors occur due to the instructions not allowed to
>> probe yet:
>> echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>>
>> This patch implemented the branch simulate instructions and allowed to
>> probe them.
>> Merge this patch and perform the test again, the test results are as
>> follows:
>> First, add probes at the branch instructions:
>> echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/blt/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bge/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bne/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/beq/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bgeu/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bltu/enable
>>
>> Then, do something to run to the probes.
>> After that, see the traced information:
>> cat /sys/kernel/debug/tracing/trace
>> sysctl-63 [001] d... 2505.263969: blt:
>> (kprobe_test_branch+0x86/0x10e [kprobe_test]) epc=0xffffffff016122f8
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.263991: bge:
>> (kprobe_test_branch+0x92/0x10e [kprobe_test]) epc=0xffffffff01612304
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.264001: bne:
>> (kprobe_test_branch+0xaa/0x10e [kprobe_test]) epc=0xffffffff0161231c
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.264011: beq:
>> (kprobe_test_branch+0xb0/0x10e [kprobe_test]) epc=0xffffffff01612322
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.264019: bgeu:
>> (kprobe_test_branch+0xc6/0x10e [kprobe_test]) epc=0xffffffff01612338
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.264027: bltu:
>> (kprobe_test_branch+0xd2/0x10e [kprobe_test]) epc=0xffffffff01612344
>> opcode=0x100073
>>
>> Now we can see the traced information.
>> The actual address of the symbol 'kprobe_test_branch' is as follows:
>> cat /proc/kallsyms | grep kprobe_test_branch
>> ffffffff01612272 t kprobe_test_branch [kprobe_test]
>>
>> Based on the traced information and the actual address of the symbol
>> 'kprobe_test_branch', we can also see that the branch instructions
>> have been replaced by 'ebreak(0x100073)' instructions.
>>
>> The pesudoinstructions of the branch instructions,
>> i.e. bnez, beqz, blez, bgez, bltz, bgtz, bleu, bgtu and ble
>> are allowed to probe as well.
>>
>> --------
>>
>> Signed-off-by: Chen Lifu <chenlifu@huawei.com>
>> ---
>> arch/riscv/kernel/probes/decode-insn.c | 3 +-
>> arch/riscv/kernel/probes/simulate-insn.c | 78 ++++++++++++++++++++++++
>> 2 files changed, 79 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/riscv/kernel/probes/decode-insn.c
>> b/arch/riscv/kernel/probes/decode-insn.c
>> index 5eb03fb61450..64f6183b4717 100644
>> --- a/arch/riscv/kernel/probes/decode-insn.c
>> +++ b/arch/riscv/kernel/probes/decode-insn.c
>> @@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr,
>> struct arch_probe_insn *api)
>> RISCV_INSN_REJECTED(c_ebreak, insn);
>> #endif
>> - RISCV_INSN_REJECTED(branch, insn);
>> -
>> RISCV_INSN_SET_SIMULATE(jal, insn);
>> RISCV_INSN_SET_SIMULATE(jalr, insn);
>> RISCV_INSN_SET_SIMULATE(auipc, insn);
>> + RISCV_INSN_SET_SIMULATE(branch, insn);
>> return INSN_GOOD;
>> }
>> diff --git a/arch/riscv/kernel/probes/simulate-insn.c
>> b/arch/riscv/kernel/probes/simulate-insn.c
>> index b81719522d5c..efc989b28859 100644
>> --- a/arch/riscv/kernel/probes/simulate-insn.c
>> +++ b/arch/riscv/kernel/probes/simulate-insn.c
>> @@ -117,3 +117,81 @@ bool __kprobes simulate_auipc(u32 opcode,
>> unsigned long addr, struct pt_regs *re
>> return true;
>> }
>> +
>> +#define branch_rs1_idx(opcode) \
>> + (((opcode) >> 15) & 0x1f)
>> +
>> +#define branch_rs2_idx(opcode) \
>> + (((opcode) >> 20) & 0x1f)
>> +
>> +#define branch_funct3(opcode) \
>> + (((opcode) >> 12) & 0x7)
>> +
>> +#define branch_imm(opcode) \
>> + (((((opcode) >> 8 ) & 0xf ) << 1 ) | \
>> + ((((opcode) >> 25) & 0x3f) << 5 ) | \
>> + ((((opcode) >> 7 ) & 0x1 ) << 11) | \
>> + ((((opcode) >> 31) & 0x1 ) << 12))
>> +
>> +#define branch_offset(opcode) \
>> + sign_extend32((branch_imm(opcode)), 12)
>> +
>> +#define BRANCH_BEQ 0x0
>> +#define BRANCH_BNE 0x1
>> +#define BRANCH_BLT 0x4
>> +#define BRANCH_BGE 0x5
>> +#define BRANCH_BLTU 0x6
>> +#define BRANCH_BGEU 0x7
>> +
>> +bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct
>> pt_regs *regs)
>> +{
>> + /*
>> + * branch instructions:
>> + * 31 30 25 24 20 19 15 14 12 11 8
>> 7 6 0
>> + * | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] |
>> imm[11] | opcode |
>> + * 1 6 5 5 3 4
>> 1 7
>> + * imm[12|10:5] rs2 rs1 000
>> imm[4:1|11] 1100011 BEQ
>> + * imm[12|10:5] rs2 rs1 001
>> imm[4:1|11] 1100011 BNE
>> + * imm[12|10:5] rs2 rs1 100
>> imm[4:1|11] 1100011 BLT
>> + * imm[12|10:5] rs2 rs1 101
>> imm[4:1|11] 1100011 BGE
>> + * imm[12|10:5] rs2 rs1 110
>> imm[4:1|11] 1100011 BLTU
>> + * imm[12|10:5] rs2 rs1 111
>> imm[4:1|11] 1100011 BGEU
>> + */
>> +
>> + s32 offset;
>> + s32 offset_tmp;
>> + unsigned long rs1_val;
>> + unsigned long rs2_val;
>> +
>> + if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
>> + !rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
>> + return false;
>> +
>> + offset_tmp = branch_offset(opcode);
>> + switch (branch_funct3(opcode)) {
>> + case BRANCH_BEQ:
>> + offset = (rs1_val == rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BNE:
>> + offset = (rs1_val != rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BLT:
>> + offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BGE:
>> + offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BLTU:
>> + offset = (rs1_val < rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BGEU:
>> + offset = (rs1_val >= rs2_val) ? offset_tmp : 4;
>> + break;
>> + default:
>> + return false;
>> + }
>> +
>> + instruction_pointer_set(regs, addr + offset);
>> +
>> + return true;
>> +}
>>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 10+ messages in thread
* ping//Re: ping//Re: [PATCH -next 2/2] riscv: implemented branch simulate instructions
@ 2021-07-22 10:15 ` chenlifu
0 siblings, 0 replies; 10+ messages in thread
From: chenlifu @ 2021-07-22 10:15 UTC (permalink / raw)
To: paul.walmsley, palmer, aou, guoren, penberg, mhiramat, me,
linux-riscv, linux-kernel
在 2021/7/5 10:09, chenlifu 写道:
>
>
> 在 2021/6/29 10:34, Chen Lifu 写道:
>> To test the kprobe-based event tracing, we prepare
>> a kernel module 'kprobe_test.ko' to add the probes.
>> The assembly codes (partially) of the module are as follows:
>> ...
>> 0000000000000000 <kprobe_test_branch>:
>> ...
>>
>> 0000000000000080 <.L7>:
>> 80: 414986bb subw a3,s3,s4
>> 84: 4785 li a5,1
>> 86: 00d7c363 blt a5,a3,8c <.L8>
>> 8a: 2485 addiw s1,s1,1
>>
>> 000000000000008c <.L8>:
>> 8c: 012987bb addw a5,s3,s2
>> 90: 4711 li a4,4
>> 92: 00f75363 bge a4,a5,98 <.L9>
>> 96: 2485 addiw s1,s1,1
>> ...
>>
>> 00000000000000aa <.L11>:
>> aa: 01299363 bne s3,s2,b0 <.L12>
>> ae: 2485 addiw s1,s1,1
>>
>> 00000000000000b0 <.L12>:
>> b0: 012a0363 beq s4,s2,b6 <.L13>
>> b4: 2485 addiw s1,s1,1
>> ...
>>
>> 00000000000000c2 <.L14>:
>> c2: 0009861b sext.w a2,s3
>> c6: 013a7363 bgeu s4,s3,cc <.L15>
>> ca: 2485 addiw s1,s1,1
>> ...
>>
>> 00000000000000d2 <.L16>:
>> d2: 00e7e363 bltu a5,a4,d8 <.L17>
>> d6: 2485 addiw s1,s1,1
>> ...
>>
>> Test the kprobe-based event tracing in qemu-system-riscv64:
>> First, install the kprobe test module:
>> insmod /root/kprobe_test.ko
>>
>> Then, add probes as new events at the branch instructions,
>> i.e. blt, bge, bne, beq, bgeu and bltu.
>> The following errors occur due to the instructions not allowed to
>> probe yet:
>> echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>> echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> sh: write error: Invalid argument
>>
>> This patch implemented the branch simulate instructions and allowed to
>> probe them.
>> Merge this patch and perform the test again, the test results are as
>> follows:
>> First, add probes at the branch instructions:
>> echo "p:blt kprobe_test:kprobe_test_branch+0x86 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:bge kprobe_test:kprobe_test_branch+0x92 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:bne kprobe_test:kprobe_test_branch+0xaa epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:beq kprobe_test:kprobe_test_branch+0xb0 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:bgeu kprobe_test:kprobe_test_branch+0xc6 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo "p:bltu kprobe_test:kprobe_test_branch+0xd2 epc=%epc
>> opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/blt/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bge/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bne/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/beq/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bgeu/enable
>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/bltu/enable
>>
>> Then, do something to run to the probes.
>> After that, see the traced information:
>> cat /sys/kernel/debug/tracing/trace
>> sysctl-63 [001] d... 2505.263969: blt:
>> (kprobe_test_branch+0x86/0x10e [kprobe_test]) epc=0xffffffff016122f8
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.263991: bge:
>> (kprobe_test_branch+0x92/0x10e [kprobe_test]) epc=0xffffffff01612304
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.264001: bne:
>> (kprobe_test_branch+0xaa/0x10e [kprobe_test]) epc=0xffffffff0161231c
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.264011: beq:
>> (kprobe_test_branch+0xb0/0x10e [kprobe_test]) epc=0xffffffff01612322
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.264019: bgeu:
>> (kprobe_test_branch+0xc6/0x10e [kprobe_test]) epc=0xffffffff01612338
>> opcode=0x100073
>> sysctl-63 [001] d... 2505.264027: bltu:
>> (kprobe_test_branch+0xd2/0x10e [kprobe_test]) epc=0xffffffff01612344
>> opcode=0x100073
>>
>> Now we can see the traced information.
>> The actual address of the symbol 'kprobe_test_branch' is as follows:
>> cat /proc/kallsyms | grep kprobe_test_branch
>> ffffffff01612272 t kprobe_test_branch [kprobe_test]
>>
>> Based on the traced information and the actual address of the symbol
>> 'kprobe_test_branch', we can also see that the branch instructions
>> have been replaced by 'ebreak(0x100073)' instructions.
>>
>> The pesudoinstructions of the branch instructions,
>> i.e. bnez, beqz, blez, bgez, bltz, bgtz, bleu, bgtu and ble
>> are allowed to probe as well.
>>
>> --------
>>
>> Signed-off-by: Chen Lifu <chenlifu@huawei.com>
>> ---
>> arch/riscv/kernel/probes/decode-insn.c | 3 +-
>> arch/riscv/kernel/probes/simulate-insn.c | 78 ++++++++++++++++++++++++
>> 2 files changed, 79 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/riscv/kernel/probes/decode-insn.c
>> b/arch/riscv/kernel/probes/decode-insn.c
>> index 5eb03fb61450..64f6183b4717 100644
>> --- a/arch/riscv/kernel/probes/decode-insn.c
>> +++ b/arch/riscv/kernel/probes/decode-insn.c
>> @@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr,
>> struct arch_probe_insn *api)
>> RISCV_INSN_REJECTED(c_ebreak, insn);
>> #endif
>> - RISCV_INSN_REJECTED(branch, insn);
>> -
>> RISCV_INSN_SET_SIMULATE(jal, insn);
>> RISCV_INSN_SET_SIMULATE(jalr, insn);
>> RISCV_INSN_SET_SIMULATE(auipc, insn);
>> + RISCV_INSN_SET_SIMULATE(branch, insn);
>> return INSN_GOOD;
>> }
>> diff --git a/arch/riscv/kernel/probes/simulate-insn.c
>> b/arch/riscv/kernel/probes/simulate-insn.c
>> index b81719522d5c..efc989b28859 100644
>> --- a/arch/riscv/kernel/probes/simulate-insn.c
>> +++ b/arch/riscv/kernel/probes/simulate-insn.c
>> @@ -117,3 +117,81 @@ bool __kprobes simulate_auipc(u32 opcode,
>> unsigned long addr, struct pt_regs *re
>> return true;
>> }
>> +
>> +#define branch_rs1_idx(opcode) \
>> + (((opcode) >> 15) & 0x1f)
>> +
>> +#define branch_rs2_idx(opcode) \
>> + (((opcode) >> 20) & 0x1f)
>> +
>> +#define branch_funct3(opcode) \
>> + (((opcode) >> 12) & 0x7)
>> +
>> +#define branch_imm(opcode) \
>> + (((((opcode) >> 8 ) & 0xf ) << 1 ) | \
>> + ((((opcode) >> 25) & 0x3f) << 5 ) | \
>> + ((((opcode) >> 7 ) & 0x1 ) << 11) | \
>> + ((((opcode) >> 31) & 0x1 ) << 12))
>> +
>> +#define branch_offset(opcode) \
>> + sign_extend32((branch_imm(opcode)), 12)
>> +
>> +#define BRANCH_BEQ 0x0
>> +#define BRANCH_BNE 0x1
>> +#define BRANCH_BLT 0x4
>> +#define BRANCH_BGE 0x5
>> +#define BRANCH_BLTU 0x6
>> +#define BRANCH_BGEU 0x7
>> +
>> +bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct
>> pt_regs *regs)
>> +{
>> + /*
>> + * branch instructions:
>> + * 31 30 25 24 20 19 15 14 12 11 8
>> 7 6 0
>> + * | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] |
>> imm[11] | opcode |
>> + * 1 6 5 5 3 4
>> 1 7
>> + * imm[12|10:5] rs2 rs1 000
>> imm[4:1|11] 1100011 BEQ
>> + * imm[12|10:5] rs2 rs1 001
>> imm[4:1|11] 1100011 BNE
>> + * imm[12|10:5] rs2 rs1 100
>> imm[4:1|11] 1100011 BLT
>> + * imm[12|10:5] rs2 rs1 101
>> imm[4:1|11] 1100011 BGE
>> + * imm[12|10:5] rs2 rs1 110
>> imm[4:1|11] 1100011 BLTU
>> + * imm[12|10:5] rs2 rs1 111
>> imm[4:1|11] 1100011 BGEU
>> + */
>> +
>> + s32 offset;
>> + s32 offset_tmp;
>> + unsigned long rs1_val;
>> + unsigned long rs2_val;
>> +
>> + if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
>> + !rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
>> + return false;
>> +
>> + offset_tmp = branch_offset(opcode);
>> + switch (branch_funct3(opcode)) {
>> + case BRANCH_BEQ:
>> + offset = (rs1_val == rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BNE:
>> + offset = (rs1_val != rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BLT:
>> + offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BGE:
>> + offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BLTU:
>> + offset = (rs1_val < rs2_val) ? offset_tmp : 4;
>> + break;
>> + case BRANCH_BGEU:
>> + offset = (rs1_val >= rs2_val) ? offset_tmp : 4;
>> + break;
>> + default:
>> + return false;
>> + }
>> +
>> + instruction_pointer_set(regs, addr + offset);
>> +
>> + return true;
>> +}
>>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH -next 1/2] riscv: implemented auipc simulate instruction
2021-06-29 2:34 ` Chen Lifu
@ 2021-07-22 17:26 ` Palmer Dabbelt
-1 siblings, 0 replies; 10+ messages in thread
From: Palmer Dabbelt @ 2021-07-22 17:26 UTC (permalink / raw)
To: chenlifu
Cc: Paul Walmsley, aou, guoren, chenlifu, penberg, mhiramat, me,
linux-riscv, linux-kernel
On Mon, 28 Jun 2021 19:34:54 PDT (-0700), chenlifu@huawei.com wrote:
> To test the kprobe-based event tracing, we prepare
> a kernel module 'kprobe_test.ko' to add the probes.
> The assembly codes (partially) of the module are as follows:
> ...
> 0000000000000000 <kprobe_test_branch>:
> ...
> 0000000000000038 <.LVL1>:
> 38: 00000597 auipc a1,0x0
> 3c: 00058593 mv a1,a1
> ...
>
> Test the kprobe-based event tracing in qemu-system-riscv64:
> First, install the kprobe test module:
> insmod /root/kprobe_test.ko
>
> Then, add a probe as a new event at an 'auipc' instruction,
> the following error occurs due to the instruction not allowed to probe yet:
> echo "p:auipc kprobe_test:kprobe_test_branch+0x38 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
>
> This patch implemented the 'auipc' simulate instruction and allowed to probe it.
> Merge this patch and perform the test again, the test results are as follows:
> First, add a probe at the 'auipc' instruction:
> echo "p:auipc kprobe_test:kprobe_test_branch+0x38 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/auipc/enable
>
> Then, do something to run to the probe.
> After that, see the traced information:
> cat /sys/kernel/debug/tracing/trace
> sysctl-58 [001] d... 179.126350: auipc: (kprobe_test_branch+0x38/0x10e [kprobe_test]) epc=0xffffffff016122aa opcode=0x100073
>
> Now we can see the traced information.
> The actual address of the symbol 'kprobe_test_branch' is as follows:
> cat /proc/kallsyms | grep kprobe_test_branch
> ffffffff01612272 t kprobe_test_branch [kprobe_test]
>
> Based on the traced information and the actual address of the symbol
> 'kprobe_test_branch', we can also see that the 'auipc' instruction
> has been replaced by 'ebreak(0x100073)' instruction.
>
> --------
>
> Signed-off-by: Chen Lifu <chenlifu@huawei.com>
> ---
> arch/riscv/kernel/probes/decode-insn.c | 2 +-
> arch/riscv/kernel/probes/simulate-insn.c | 34 ++++++++++++++++++++++++
> 2 files changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
> index 0ed043acc882..5eb03fb61450 100644
> --- a/arch/riscv/kernel/probes/decode-insn.c
> +++ b/arch/riscv/kernel/probes/decode-insn.c
> @@ -38,11 +38,11 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
> RISCV_INSN_REJECTED(c_ebreak, insn);
> #endif
>
> - RISCV_INSN_REJECTED(auipc, insn);
> RISCV_INSN_REJECTED(branch, insn);
>
> RISCV_INSN_SET_SIMULATE(jal, insn);
> RISCV_INSN_SET_SIMULATE(jalr, insn);
> + RISCV_INSN_SET_SIMULATE(auipc, insn);
>
> return INSN_GOOD;
> }
> diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
> index 2519ce26377d..b81719522d5c 100644
> --- a/arch/riscv/kernel/probes/simulate-insn.c
> +++ b/arch/riscv/kernel/probes/simulate-insn.c
> @@ -83,3 +83,37 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
>
> return ret;
> }
> +
> +#define auipc_rd_idx(opcode) \
> + ((opcode >> 7) & 0x1f)
> +
> +#define auipc_imm(opcode) \
> + ((((opcode) >> 12) & 0xfffff) << 12)
> +
> +#if __riscv_xlen == 64
> +#define auipc_offset(opcode) sign_extend64(auipc_imm(opcode), 31)
> +#elif __riscv_xlen == 32
> +#define auipc_offset(opcode) auipc_imm(opcode)
> +#else
> +#error "Unexpected __riscv_xlen"
> +#endif
> +
> +bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *regs)
> +{
> + /*
> + * auipc instruction:
> + * 31 12 11 7 6 0
> + * | imm[31:12] | rd | opcode |
> + * 20 5 7
> + */
> +
> + u32 rd_idx = auipc_rd_idx(opcode);
> + unsigned long rd_val = addr + auipc_offset(opcode);
> +
> + if (!rv_insn_reg_set_val(regs, rd_idx, rd_val))
> + return false;
> +
> + instruction_pointer_set(regs, addr + 4);
> +
> + return true;
> +}
Thanks. These are on for-next, with the checkpatch errors fixed and the
commit messages mostly removed -- it was all pretty awkwardly phrased so
I didn't want to clean it up.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH -next 1/2] riscv: implemented auipc simulate instruction
@ 2021-07-22 17:26 ` Palmer Dabbelt
0 siblings, 0 replies; 10+ messages in thread
From: Palmer Dabbelt @ 2021-07-22 17:26 UTC (permalink / raw)
To: chenlifu
Cc: Paul Walmsley, aou, guoren, chenlifu, penberg, mhiramat, me,
linux-riscv, linux-kernel
On Mon, 28 Jun 2021 19:34:54 PDT (-0700), chenlifu@huawei.com wrote:
> To test the kprobe-based event tracing, we prepare
> a kernel module 'kprobe_test.ko' to add the probes.
> The assembly codes (partially) of the module are as follows:
> ...
> 0000000000000000 <kprobe_test_branch>:
> ...
> 0000000000000038 <.LVL1>:
> 38: 00000597 auipc a1,0x0
> 3c: 00058593 mv a1,a1
> ...
>
> Test the kprobe-based event tracing in qemu-system-riscv64:
> First, install the kprobe test module:
> insmod /root/kprobe_test.ko
>
> Then, add a probe as a new event at an 'auipc' instruction,
> the following error occurs due to the instruction not allowed to probe yet:
> echo "p:auipc kprobe_test:kprobe_test_branch+0x38 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> sh: write error: Invalid argument
>
> This patch implemented the 'auipc' simulate instruction and allowed to probe it.
> Merge this patch and perform the test again, the test results are as follows:
> First, add a probe at the 'auipc' instruction:
> echo "p:auipc kprobe_test:kprobe_test_branch+0x38 epc=%epc opcode=+0(%epc):x32" >> /sys/kernel/debug/tracing/kprobe_events
> echo 1 > /sys/kernel/debug/tracing/events/kprobes/auipc/enable
>
> Then, do something to run to the probe.
> After that, see the traced information:
> cat /sys/kernel/debug/tracing/trace
> sysctl-58 [001] d... 179.126350: auipc: (kprobe_test_branch+0x38/0x10e [kprobe_test]) epc=0xffffffff016122aa opcode=0x100073
>
> Now we can see the traced information.
> The actual address of the symbol 'kprobe_test_branch' is as follows:
> cat /proc/kallsyms | grep kprobe_test_branch
> ffffffff01612272 t kprobe_test_branch [kprobe_test]
>
> Based on the traced information and the actual address of the symbol
> 'kprobe_test_branch', we can also see that the 'auipc' instruction
> has been replaced by 'ebreak(0x100073)' instruction.
>
> --------
>
> Signed-off-by: Chen Lifu <chenlifu@huawei.com>
> ---
> arch/riscv/kernel/probes/decode-insn.c | 2 +-
> arch/riscv/kernel/probes/simulate-insn.c | 34 ++++++++++++++++++++++++
> 2 files changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
> index 0ed043acc882..5eb03fb61450 100644
> --- a/arch/riscv/kernel/probes/decode-insn.c
> +++ b/arch/riscv/kernel/probes/decode-insn.c
> @@ -38,11 +38,11 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
> RISCV_INSN_REJECTED(c_ebreak, insn);
> #endif
>
> - RISCV_INSN_REJECTED(auipc, insn);
> RISCV_INSN_REJECTED(branch, insn);
>
> RISCV_INSN_SET_SIMULATE(jal, insn);
> RISCV_INSN_SET_SIMULATE(jalr, insn);
> + RISCV_INSN_SET_SIMULATE(auipc, insn);
>
> return INSN_GOOD;
> }
> diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
> index 2519ce26377d..b81719522d5c 100644
> --- a/arch/riscv/kernel/probes/simulate-insn.c
> +++ b/arch/riscv/kernel/probes/simulate-insn.c
> @@ -83,3 +83,37 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
>
> return ret;
> }
> +
> +#define auipc_rd_idx(opcode) \
> + ((opcode >> 7) & 0x1f)
> +
> +#define auipc_imm(opcode) \
> + ((((opcode) >> 12) & 0xfffff) << 12)
> +
> +#if __riscv_xlen == 64
> +#define auipc_offset(opcode) sign_extend64(auipc_imm(opcode), 31)
> +#elif __riscv_xlen == 32
> +#define auipc_offset(opcode) auipc_imm(opcode)
> +#else
> +#error "Unexpected __riscv_xlen"
> +#endif
> +
> +bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *regs)
> +{
> + /*
> + * auipc instruction:
> + * 31 12 11 7 6 0
> + * | imm[31:12] | rd | opcode |
> + * 20 5 7
> + */
> +
> + u32 rd_idx = auipc_rd_idx(opcode);
> + unsigned long rd_val = addr + auipc_offset(opcode);
> +
> + if (!rv_insn_reg_set_val(regs, rd_idx, rd_val))
> + return false;
> +
> + instruction_pointer_set(regs, addr + 4);
> +
> + return true;
> +}
Thanks. These are on for-next, with the checkpatch errors fixed and the
commit messages mostly removed -- it was all pretty awkwardly phrased so
I didn't want to clean it up.
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2021-07-22 17:27 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-29 2:34 [PATCH -next 1/2] riscv: implemented auipc simulate instruction Chen Lifu
2021-06-29 2:34 ` Chen Lifu
2021-06-29 2:34 ` [PATCH -next 2/2] riscv: implemented branch simulate instructions Chen Lifu
2021-06-29 2:34 ` Chen Lifu
2021-07-05 2:09 ` ping//Re: " chenlifu
2021-07-05 2:09 ` chenlifu
2021-07-22 10:15 ` ping//Re: " chenlifu
2021-07-22 10:15 ` chenlifu
2021-07-22 17:26 ` [PATCH -next 1/2] riscv: implemented auipc simulate instruction Palmer Dabbelt
2021-07-22 17:26 ` Palmer Dabbelt
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.