Skip to content

Commit 9df8790

Browse files
fyin1mwang106
authored andcommitted
hv: Fix two minor issues in instruction emulation code
1. The wrong operand size is assigned in instruction decode phase if the operand size is 1 byte. According to the SDM, the bit 0(w bit) of opcode should be checked first to detect whether the operand size is 1 byte. Then, check whether there is prefix to overwrite the default operand size. The original instruction decode doesn't care about the operand size. But do opsize fixup during instruction emulation phase. With ACRN we need operand size packed to ioreq and send to DM after instruction decode. 2. We should always touch the GPA by following opsize to avoid side effect (especially when GPA is for a MMIO). Tracked-On: #1337 Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
1 parent be0651a commit 9df8790

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

hypervisor/arch/x86/guest/instr_emul.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -982,16 +982,15 @@ static int get_gva_di_check(struct vcpu *vcpu, struct instr_emul_vie *vie,
982982
*/
983983
static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie)
984984
{
985-
uint64_t src_gva, gpa, val;
985+
uint64_t src_gva, gpa, val = 0UL;
986986
uint64_t *dst_hva, *src_hva;
987987
uint64_t rcx, rdi, rsi, rflags;
988988
uint32_t err_code;
989989
enum cpu_reg_name seg;
990990
int error, repeat;
991-
uint8_t opsize;
991+
uint8_t opsize = vie->opsize;
992992
bool is_mmio_write;
993993

994-
opsize = (vie->opcode == 0xA4U) ? 1U : vie->opsize;
995994
error = 0;
996995
is_mmio_write = (vcpu->req.reqs.mmio.direction == REQUEST_WRITE);
997996

@@ -1025,8 +1024,7 @@ static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie)
10251024
/* we are sure it will success */
10261025
(void)gva2gpa(vcpu, src_gva, &gpa, &err_code);
10271026
src_hva = gpa2hva(vcpu->vm, gpa);
1028-
1029-
val = *src_hva;
1027+
(void)memcpy_s(&val, opsize, src_hva, opsize);
10301028

10311029
mmio_write(vcpu, val);
10321030
} else {
@@ -1036,7 +1034,7 @@ static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie)
10361034
* decoding.
10371035
*/
10381036
dst_hva = gpa2hva(vcpu->vm, vie->dst_gpa);
1039-
memcpy_s(dst_hva, opsize, &val, opsize);
1037+
(void)memcpy_s(dst_hva, opsize, &val, opsize);
10401038
}
10411039

10421040
rsi = vm_get_register(vcpu, CPU_REG_RSI);
@@ -1072,11 +1070,10 @@ static int emulate_movs(struct vcpu *vcpu, struct instr_emul_vie *vie)
10721070
static int emulate_stos(struct vcpu *vcpu, struct instr_emul_vie *vie)
10731071
{
10741072
int error, repeat;
1075-
uint8_t opsize;
1073+
uint8_t opsize = vie->opsize;
10761074
uint64_t val;
10771075
uint64_t rcx, rdi, rflags;
10781076

1079-
opsize = (vie->opcode == 0xAAU) ? 1U : vie->opsize;
10801077
repeat = vie->repz_present | vie->repnz_present;
10811078

10821079
if (repeat != 0) {
@@ -1800,11 +1797,13 @@ static int decode_two_byte_opcode(struct instr_emul_vie *vie)
18001797
}
18011798

18021799
vie_advance(vie);
1800+
18031801
return 0;
18041802
}
18051803

18061804
static int decode_opcode(struct instr_emul_vie *vie)
18071805
{
1806+
int ret = 0;
18081807
uint8_t x;
18091808

18101809
if (vie_peek(vie, &x) != 0) {
@@ -1821,10 +1820,20 @@ static int decode_opcode(struct instr_emul_vie *vie)
18211820
vie_advance(vie);
18221821

18231822
if (vie->op.op_type == VIE_OP_TYPE_TWO_BYTE) {
1824-
return decode_two_byte_opcode(vie);
1823+
ret = decode_two_byte_opcode(vie);
18251824
}
18261825

1827-
return 0;
1826+
/* Fixup the opsize according to opcode w bit:
1827+
* If w bit of opcode is 0, the operand size is 1 byte
1828+
* If w bit of opcode is 1, the operand size is decided
1829+
* by prefix and default operand size attribute (handled
1830+
* in decode_prefixes).
1831+
*/
1832+
if ((ret == 0) && ((vie->opcode & 0x1U) == 0U)) {
1833+
vie->opsize = 1U;
1834+
}
1835+
1836+
return ret;
18281837
}
18291838

18301839
static int decode_modrm(struct instr_emul_vie *vie, enum vm_cpu_mode cpu_mode)

0 commit comments

Comments
 (0)