Module Name: src Committed By: reinoud Date: Fri Oct 30 21:06:13 UTC 2020
Modified Files: src/lib/libnvmm: libnvmm_x86.c Log Message: Implement missing (REPE) CMPS instruction support in NVMMs x86_decode(). In apparently rare cases the (REPE) CMPS instruction can trigger an memory assist. NVMM wouldn't recognize the instruction and thus couldn't assist and Qemu would abort. To generate a diff of this commit: cvs rdiff -u -r1.40 -r1.41 src/lib/libnvmm/libnvmm_x86.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libnvmm/libnvmm_x86.c diff -u src/lib/libnvmm/libnvmm_x86.c:1.40 src/lib/libnvmm/libnvmm_x86.c:1.41 --- src/lib/libnvmm/libnvmm_x86.c:1.40 Sat Sep 5 07:22:25 2020 +++ src/lib/libnvmm/libnvmm_x86.c Fri Oct 30 21:06:13 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: libnvmm_x86.c,v 1.40 2020/09/05 07:22:25 maxv Exp $ */ +/* $NetBSD: libnvmm_x86.c,v 1.41 2020/10/30 21:06:13 reinoud Exp $ */ /* * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net @@ -1051,6 +1051,7 @@ struct x86_opcode { bool movs:1; bool stos:1; bool lods:1; + bool cmps:1; bool szoverride:1; bool group1:1; bool group3:1; @@ -1463,6 +1464,26 @@ static const struct x86_opcode primary_o }, /* + * CMPS + */ + [0xA6] = { + /* Yb, Xb */ + .valid = true, + .cmps = true, + .szoverride = false, + .defsize = OPSIZE_BYTE, + .emul = &x86_emul_cmp + }, + [0xA7] = { + /* Yv, Xv */ + .valid = true, + .cmps = true, + .szoverride = true, + .defsize = -1, + .emul = &x86_emul_cmp + }, + + /* * STOS */ [0xAA] = { @@ -1871,6 +1892,35 @@ node_movs(struct x86_decode_fsm *fsm, st } /* + * Special node, for CMPS. Fake two displacements of zero on the source and + * destination registers. + * XXX coded as clone of movs as its similar in register usage + * XXX might be merged with node_movs() + */ +static int +node_cmps(struct x86_decode_fsm *fsm, struct x86_instr *instr) +{ + size_t adrsize; + + adrsize = instr->address_size; + + /* DS:RSI */ + instr->src.type = STORE_REG; + instr->src.u.reg = &gpr_map__special[1][2][adrsize-1]; + instr->src.disp.type = DISP_0; + + /* ES:RDI, force ES */ + instr->dst.type = STORE_REG; + instr->dst.u.reg = &gpr_map__special[1][3][adrsize-1]; + instr->dst.disp.type = DISP_0; + instr->dst.hardseg = NVMM_X64_SEG_ES; + + fsm_advance(fsm, 0, NULL); + + return 0; +} + +/* * Special node, for STOS and LODS. Fake a displacement of zero on the * destination register. */ @@ -2470,6 +2520,8 @@ node_primary_opcode(struct x86_decode_fs fsm_advance(fsm, 1, node_stlo); } else if (opcode->movs) { fsm_advance(fsm, 1, node_movs); + } else if (opcode->cmps) { + fsm_advance(fsm, 1, node_cmps); } else { return -1; } @@ -2646,8 +2698,16 @@ x86_decode(uint8_t *inst_bytes, size_t i while (fsm.fn != NULL) { ret = (*fsm.fn)(&fsm, instr); - if (ret == -1) + if (ret == -1) { + printf("\nNVMM: %s missing support for instruction " \ + "with max length %ld : [ ", __func__, + inst_len); + for (uint i = 0; i < inst_len; i++) + printf("%02x ", inst_bytes[i]); + printf("], please report to NetBSD!\n\n"); + fflush(stdout); return -1; + } } instr->len = fsm.buf - inst_bytes;