|
55 | 55 | #define VIE_OP_F_IMM8 (1U << 1) /* 8-bit immediate operand */
|
56 | 56 | #define VIE_OP_F_MOFFSET (1U << 2) /* 16/32/64-bit immediate moffset */
|
57 | 57 | #define VIE_OP_F_NO_MODRM (1U << 3)
|
58 |
| -#define VIE_OP_F_NO_GLA_VERIFICATION (1U << 4) |
| 58 | +#define VIE_OP_F_CHECK_GVA_DI (1U << 4) /* for movs, need to check DI */ |
59 | 59 |
|
60 | 60 | static const struct instr_emul_vie_op two_byte_opcodes[256] = {
|
61 | 61 | [0xB6] = {
|
@@ -108,19 +108,19 @@ static const struct instr_emul_vie_op one_byte_opcodes[256] = {
|
108 | 108 | },
|
109 | 109 | [0xA4] = {
|
110 | 110 | .op_type = VIE_OP_TYPE_MOVS,
|
111 |
| - .op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_NO_GLA_VERIFICATION |
| 111 | + .op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_CHECK_GVA_DI |
112 | 112 | },
|
113 | 113 | [0xA5] = {
|
114 | 114 | .op_type = VIE_OP_TYPE_MOVS,
|
115 |
| - .op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_NO_GLA_VERIFICATION |
| 115 | + .op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_CHECK_GVA_DI |
116 | 116 | },
|
117 | 117 | [0xAA] = {
|
118 | 118 | .op_type = VIE_OP_TYPE_STOS,
|
119 |
| - .op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_NO_GLA_VERIFICATION |
| 119 | + .op_flags = VIE_OP_F_NO_MODRM |
120 | 120 | },
|
121 | 121 | [0xAB] = {
|
122 | 122 | .op_type = VIE_OP_TYPE_STOS,
|
123 |
| - .op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_NO_GLA_VERIFICATION |
| 123 | + .op_flags = VIE_OP_F_NO_MODRM |
124 | 124 | },
|
125 | 125 | [0xC6] = {
|
126 | 126 | /* XXX Group 11 extended opcode - not just MOV */
|
@@ -953,7 +953,7 @@ static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
953 | 953 | {
|
954 | 954 | uint64_t dstaddr, srcaddr;
|
955 | 955 | uint64_t rcx, rdi, rsi, rflags;
|
956 |
| - int error, fault, repeat; |
| 956 | + int error, repeat; |
957 | 957 | uint8_t opsize;
|
958 | 958 | enum cpu_reg_name seg;
|
959 | 959 |
|
@@ -1533,7 +1533,6 @@ static int emulate_bittest(struct vcpu *vcpu, struct instr_emul_vie *vie)
|
1533 | 1533 |
|
1534 | 1534 | static int vmm_emulate_instruction(struct instr_emul_ctxt *ctxt)
|
1535 | 1535 | {
|
1536 |
| - struct vm_guest_paging *paging = &ctxt->paging; |
1537 | 1536 | struct instr_emul_vie *vie = &ctxt->vie;
|
1538 | 1537 | struct vcpu *vcpu = ctxt->vcpu;
|
1539 | 1538 | int error;
|
@@ -2123,6 +2122,22 @@ static int local_decode_instruction(enum vm_cpu_mode cpu_mode,
|
2123 | 2122 | return 0;
|
2124 | 2123 | }
|
2125 | 2124 |
|
| 2125 | +/* for instruction MOVS/STO, check the gva gotten from DI/SI. */ |
| 2126 | +static int instr_check_di(struct vcpu *vcpu, struct instr_emul_ctxt *emul_ctxt) |
| 2127 | +{ |
| 2128 | + int ret; |
| 2129 | + struct instr_emul_vie *vie = &emul_ctxt->vie; |
| 2130 | + uint64_t gva; |
| 2131 | + enum cpu_reg_name seg; |
| 2132 | + |
| 2133 | + ret = get_gva_di_si_check(vcpu, vie->addrsize, PROT_WRITE, |
| 2134 | + CPU_REG_ES, CPU_REG_RDI, &gva); |
| 2135 | + |
| 2136 | + if (ret < 0) { |
| 2137 | + return -EFAULT; |
| 2138 | + } |
| 2139 | +} |
| 2140 | + |
2126 | 2141 | int decode_instruction(struct vcpu *vcpu)
|
2127 | 2142 | {
|
2128 | 2143 | struct instr_emul_ctxt *emul_ctxt;
|
@@ -2160,6 +2175,23 @@ int decode_instruction(struct vcpu *vcpu)
|
2160 | 2175 | return -EFAULT;
|
2161 | 2176 | }
|
2162 | 2177 |
|
| 2178 | + /* |
| 2179 | + * We do operand check in instruction decode phase and |
| 2180 | + * inject exception accordingly. In late instruction |
| 2181 | + * emulation, it will always sucess. |
| 2182 | + * |
| 2183 | + * We only need to do dst check for movs. For other instructions, |
| 2184 | + * they always has one register and one mmio which trigger EPT |
| 2185 | + * by access mmio. With VMX enabled, the related check is done |
| 2186 | + * by VMX itself before hit EPT violation. |
| 2187 | + * |
| 2188 | + */ |
| 2189 | + if (emul_ctxt->vie.op.op_flags & VIE_OP_F_CHECK_GVA_DI) { |
| 2190 | + retval = instr_check_di(vcpu, emul_ctxt); |
| 2191 | + if (retval < 0) |
| 2192 | + return retval; |
| 2193 | + } |
| 2194 | + |
2163 | 2195 | return emul_ctxt->vie.opsize;
|
2164 | 2196 | }
|
2165 | 2197 |
|
|
0 commit comments