diff options
author | Chen Lifu <chenlifu@huawei.com> | 2021-06-29 10:34:54 +0800 |
---|---|---|
committer | Chen Guokai <chenguokai17@mails.ucas.ac.cn> | 2022-10-09 12:54:08 +0800 |
commit | 07b412124b4f44238219994b994ece434f624a61 (patch) | |
tree | df8f06cbe01f09b97629fbb0dfc3edd1cc1a8879 | |
parent | d216e40d1f44f2451d874f5f09d177a51b5ac037 (diff) | |
download | openEuler-kernel-07b412124b4f44238219994b994ece434f624a61.tar.gz |
riscv: kprobes: implement the auipc instruction
mainline inclusion
from mainline-v5.19
commit b7d2be48cc08a9d42e347d944efa9f37ab9b83d2
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5QM0N
CVE: NA
-------------------------------------------------
This has been tested by probing a module that contains an auipc
instruction.
Signed-off-by: Chen Lifu <chenlifu@huawei.com>
[Palmer: commit message]
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
-rw-r--r-- | arch/riscv/kernel/probes/decode-insn.c | 2 | ||||
-rw-r--r-- | arch/riscv/kernel/probes/simulate-insn.c | 34 |
2 files changed, 35 insertions, 1 deletions
diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c index 0ed043acc882cd..5eb03fb6145018 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 2519ce26377d15..b81719522d5c98 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; +} |