diff options
author | Joerg Roedel <jroedel@suse.de> | 2020-09-07 15:15:11 +0200 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2020-09-07 19:45:24 +0200 |
commit | 7af1bd822dd45a669fc178a35cc8183922333d56 (patch) | |
tree | 616542d0ee1299c7b4a0c79b80b5fdf5810399e5 /arch/x86/lib/insn-eval.c | |
parent | x86/umip: Factor out instruction decoding (diff) | |
download | linux-7af1bd822dd45a669fc178a35cc8183922333d56.tar.xz linux-7af1bd822dd45a669fc178a35cc8183922333d56.zip |
x86/insn: Add insn_get_modrm_reg_off()
Add a function to the instruction decoder which returns the pt_regs
offset of the register specified in the reg field of the modrm byte.
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Link: https://lkml.kernel.org/r/20200907131613.12703-11-joro@8bytes.org
Diffstat (limited to 'arch/x86/lib/insn-eval.c')
-rw-r--r-- | arch/x86/lib/insn-eval.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c index 2323c85132cf..f20942ce76c6 100644 --- a/arch/x86/lib/insn-eval.c +++ b/arch/x86/lib/insn-eval.c @@ -20,6 +20,7 @@ enum reg_type { REG_TYPE_RM = 0, + REG_TYPE_REG, REG_TYPE_INDEX, REG_TYPE_BASE, }; @@ -439,6 +440,13 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs, regno += 8; break; + case REG_TYPE_REG: + regno = X86_MODRM_REG(insn->modrm.value); + + if (X86_REX_R(insn->rex_prefix.value)) + regno += 8; + break; + case REG_TYPE_INDEX: regno = X86_SIB_INDEX(insn->sib.value); if (X86_REX_X(insn->rex_prefix.value)) @@ -808,6 +816,21 @@ int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs) } /** + * insn_get_modrm_reg_off() - Obtain register in reg part of the ModRM byte + * @insn: Instruction containing the ModRM byte + * @regs: Register values as seen when entering kernel mode + * + * Returns: + * + * The register indicated by the reg part of the ModRM byte. The + * register is obtained as an offset from the base of pt_regs. + */ +int insn_get_modrm_reg_off(struct insn *insn, struct pt_regs *regs) +{ + return get_reg_offset(insn, regs, REG_TYPE_REG); +} + +/** * get_seg_base_limit() - obtain base address and limit of a segment * @insn: Instruction. Must be valid. * @regs: Register values as seen when entering kernel mode |