hv: instr_emul: fix operand size decode

1) For some instructions (like movsx, movzx which we support), there're two operands
and the source operand size is not equal to the dest operand size. In this case,
if we update the memory operand size according to the bit 0(w bit) of opcode,
we will lost the register operand size. This patch tries to fix this by calculating
memory operand size when we want to use it.
2) Calculate memory operand size form operand size and the bit 0(w bit) of opcode
when we want to operate on memory operand.

Tracked-On: #1337
Signed-off-by: Li, Fei1 <fei1.li@intel.com>
Reviewed-by: Yin Fengwei <fengwei.yin@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Li, Fei1 2019-04-24 21:38:31 +08:00 committed by ACRN System Integration
parent 4bbf946fdd
commit 536bc5bd12
1 changed files with 9 additions and 15 deletions

View File

@ -1084,9 +1084,11 @@ static int32_t emulate_movs(struct acrn_vcpu *vcpu, const struct instr_emul_vie
uint64_t rcx = 0U, rdi, rsi, rflags;
uint32_t err_code;
enum cpu_reg_name seg;
uint8_t repeat, opsize = vie->opsize;
uint8_t repeat, opsize;
bool is_mmio_write, done = false;
/* update the Memory Operand byte size if necessary */
opsize = ((vie->op.op_flags & VIE_OP_F_BYTE_OP) != 0U) ? 1U : vie->opsize;
is_mmio_write = (vcpu->req.reqs.mmio.direction == REQUEST_WRITE);
/*
@ -1163,10 +1165,12 @@ static int32_t emulate_movs(struct acrn_vcpu *vcpu, const struct instr_emul_vie
static int32_t emulate_stos(struct acrn_vcpu *vcpu, const struct instr_emul_vie *vie)
{
bool done = false;
uint8_t repeat, opsize = vie->opsize;
uint8_t repeat, opsize;
uint64_t val;
uint64_t rcx = 0U, rdi, rflags;
/* update the Memory Operand byte size if necessary */
opsize = ((vie->op.op_flags & VIE_OP_F_BYTE_OP) != 0U) ? 1U : vie->opsize;
repeat = vie->repz_present | vie->repnz_present;
if (repeat != 0U) {
@ -1899,18 +1903,6 @@ static int32_t decode_opcode(struct instr_emul_vie *vie)
if (vie->op.op_type == VIE_OP_TYPE_TWO_BYTE) {
ret = decode_two_byte_opcode(vie);
}
/* Fixup the opsize according to opcode w bit:
* If w bit of opcode is 0, the operand size is 1 byte
* If w bit of opcode is 1, the operand size is decided
* by prefix and default operand size attribute (handled
* in decode_prefixes).
* The VIE_OP_F_BYTE_OP only set when the instruction support
* Encoding of Operand Size (w) Bit and the w bit of opcode is 0.
*/
if ((ret == 0) && ((vie->op.op_flags & VIE_OP_F_BYTE_OP) != 0U)) {
vie->opsize = 1U;
}
}
}
@ -2405,7 +2397,9 @@ int32_t decode_instruction(struct acrn_vcpu *vcpu)
}
if (retval >= 0) {
retval = (int32_t)(emul_ctxt->vie.opsize);
/* return the Memory Operand byte size */
retval = ((emul_ctxt->vie.op.op_flags & VIE_OP_F_BYTE_OP) != 0U) ?
1 : (int32_t)emul_ctxt->vie.opsize;
}
}
}