ping//Re: ping//Re: [PATCH -next 2/2] riscv: implemented branch simulate instructions

chenlifu chenlifu at huawei.com
Thu Jul 22 03:15:18 PDT 2021



在 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 at 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 at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv



More information about the linux-riscv mailing list