qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

disas/riscv: Disassemble reserved compressed encodings as illegal

Due to the design of the disassembler, the immediate is not
known during decoding of the opcode; so to handle compressed
encodings with reserved immediate values (non-zero), we need
to add an additional check during decompression to match
reserved encodings with zero immediates and translate them
into the illegal instruction.

The following compressed opcodes have reserved encodings with
zero immediates: c.addi4spn, c.addi, c.lui, c.addi16sp, c.srli,
c.srai, c.andi and c.slli

Signed-off-by: Michael Clark <mjc@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
[Palmer: Broke long lines]
Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
Signed-off-by: Palmer Dabbelt <palmer@sifive.com>

authored by

Michael Clark and committed by
Palmer Dabbelt
f88222da 28a4df97

+45 -17
+45 -17
disas/riscv.c
··· 504 504 const rvc_constraint *constraints; 505 505 } rv_comp_data; 506 506 507 + enum { 508 + rvcd_imm_nz = 0x1 509 + }; 510 + 507 511 typedef struct { 508 512 const char * const name; 509 513 const rv_codec codec; 510 514 const char * const format; 511 515 const rv_comp_data *pseudo; 512 - const int decomp_rv32; 513 - const int decomp_rv64; 514 - const int decomp_rv128; 516 + const short decomp_rv32; 517 + const short decomp_rv64; 518 + const short decomp_rv128; 519 + const short decomp_data; 515 520 } rv_opcode_data; 516 521 517 522 /* register names */ ··· 1011 1016 { "fcvt.q.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 1012 1017 { "fmv.x.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 }, 1013 1018 { "fmv.q.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 }, 1014 - { "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, 1019 + { "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, 1020 + rv_op_addi, rv_op_addi, rvcd_imm_nz }, 1015 1021 { "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, 0 }, 1016 1022 { "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw }, 1017 1023 { "c.flw", rv_codec_cl_lw, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 }, ··· 1019 1025 { "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw }, 1020 1026 { "c.fsw", rv_codec_cs_sw, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 }, 1021 1027 { "c.nop", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, 1022 - { "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, 1028 + { "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, 1029 + rv_op_addi, rvcd_imm_nz }, 1023 1030 { "c.jal", rv_codec_cj_jal, rv_fmt_rd_offset, NULL, rv_op_jal, 0, 0 }, 1024 1031 { "c.li", rv_codec_ci_li, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, 1025 - { "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, 1026 - { "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui, rv_op_lui }, 1027 - { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli, rv_op_srli, rv_op_srli }, 1028 - { "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai, rv_op_srai, rv_op_srai }, 1029 - { "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi, rv_op_andi, rv_op_andi }, 1032 + { "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, 1033 + rv_op_addi, rv_op_addi, rvcd_imm_nz }, 1034 + { "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui, 1035 + rv_op_lui, rvcd_imm_nz }, 1036 + { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli, 1037 + rv_op_srli, rv_op_srli, rvcd_imm_nz }, 1038 + { "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai, 1039 + rv_op_srai, rv_op_srai, rvcd_imm_nz }, 1040 + { "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi, 1041 + rv_op_andi, rv_op_andi, rvcd_imm_nz }, 1030 1042 { "c.sub", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_sub, rv_op_sub, rv_op_sub }, 1031 1043 { "c.xor", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_xor, rv_op_xor, rv_op_xor }, 1032 1044 { "c.or", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_or, rv_op_or, rv_op_or }, ··· 1036 1048 { "c.j", rv_codec_cj, rv_fmt_rd_offset, NULL, rv_op_jal, rv_op_jal, rv_op_jal }, 1037 1049 { "c.beqz", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_beq, rv_op_beq, rv_op_beq }, 1038 1050 { "c.bnez", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_bne, rv_op_bne, rv_op_bne }, 1039 - { "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli, rv_op_slli, rv_op_slli }, 1051 + { "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli, 1052 + rv_op_slli, rv_op_slli, rvcd_imm_nz }, 1040 1053 { "c.fldsp", rv_codec_ci_ldsp, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, rv_op_fld }, 1041 1054 { "c.lwsp", rv_codec_ci_lwsp, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw }, 1042 1055 { "c.flwsp", rv_codec_ci_lwsp, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 }, ··· 2795 2808 { 2796 2809 int decomp_op = opcode_data[dec->op].decomp_rv32; 2797 2810 if (decomp_op != rv_op_illegal) { 2798 - dec->op = decomp_op; 2799 - dec->codec = opcode_data[decomp_op].codec; 2811 + if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz) 2812 + && dec->imm == 0) { 2813 + dec->op = rv_op_illegal; 2814 + } else { 2815 + dec->op = decomp_op; 2816 + dec->codec = opcode_data[decomp_op].codec; 2817 + } 2800 2818 } 2801 2819 } 2802 2820 ··· 2804 2822 { 2805 2823 int decomp_op = opcode_data[dec->op].decomp_rv64; 2806 2824 if (decomp_op != rv_op_illegal) { 2807 - dec->op = decomp_op; 2808 - dec->codec = opcode_data[decomp_op].codec; 2825 + if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz) 2826 + && dec->imm == 0) { 2827 + dec->op = rv_op_illegal; 2828 + } else { 2829 + dec->op = decomp_op; 2830 + dec->codec = opcode_data[decomp_op].codec; 2831 + } 2809 2832 } 2810 2833 } 2811 2834 ··· 2813 2836 { 2814 2837 int decomp_op = opcode_data[dec->op].decomp_rv128; 2815 2838 if (decomp_op != rv_op_illegal) { 2816 - dec->op = decomp_op; 2817 - dec->codec = opcode_data[decomp_op].codec; 2839 + if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz) 2840 + && dec->imm == 0) { 2841 + dec->op = rv_op_illegal; 2842 + } else { 2843 + dec->op = decomp_op; 2844 + dec->codec = opcode_data[decomp_op].codec; 2845 + } 2818 2846 } 2819 2847 } 2820 2848