Skip to content

Commit 4fc2009

Browse files
lifeixwenlingz
authored andcommitted
hv: instr_emul: check the bit 0(w bit) of opcode when necessary
Not every instruction supports the operand-size bit (w). This patch try to correct what done in commit-id 9df8790 by setting a flag VIE_OP_F_BYTE_OP to indicate which instruction supports the operand-size bit (w). This bug is found by removing VMX_PROCBASED_CTLS2_VAPIC_REGS VMCS setting when the physical doesn't support this APICv feature. However, if emulated this in MRB board, the android can't boot because when switch to trusty world, it will check "Delivery Status" in ICR first. It turns out that this Bit Test instruction is not emulated correctly. Tracked-On: #1337 Signed-off-by: Qi Yadong <yadong.qi@intel.com> Signed-off-by: Li, Fei1 <fei1.li@intel.com> Reviewed-by: Yin Fengwei <fengwei.yin@intel.com>
1 parent 7ccb44a commit 4fc2009

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

hypervisor/arch/x86/guest/instr_emul.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,23 @@
8484
#define VIE_OP_TYPE_TEST 15U
8585

8686
/* struct vie_op.op_flags */
87-
#define VIE_OP_F_IMM (1U << 0U) /* 16/32-bit immediate operand */
88-
#define VIE_OP_F_IMM8 (1U << 1U) /* 8-bit immediate operand */
89-
#define VIE_OP_F_MOFFSET (1U << 2U) /* 16/32/64-bit immediate moffset */
90-
#define VIE_OP_F_NO_MODRM (1U << 3U)
91-
#define VIE_OP_F_CHECK_GVA_DI (1U << 4U) /* for movs, need to check DI */
87+
#define VIE_OP_F_IMM (1U << 0U) /* 16/32-bit immediate operand */
88+
#define VIE_OP_F_IMM8 (1U << 1U) /* 8-bit immediate operand */
89+
#define VIE_OP_F_MOFFSET (1U << 2U) /* 16/32/64-bit immediate moffset */
90+
#define VIE_OP_F_NO_MODRM (1U << 3U)
91+
#define VIE_OP_F_CHECK_GVA_DI (1U << 4U) /* for movs, need to check DI */
92+
/*
93+
* The VIE_OP_F_BYTE_OP only set when the instruction support
94+
* Encoding of Operand Size (w) Bit and the w bit of opcode is 0.
95+
* according B.2 GENERAL-PURPOSE INSTRUCTION FORMATS AND ENCODINGS
96+
* FOR NON-64-BIT MODES, Vol 2, Intel SDM.
97+
*/
98+
#define VIE_OP_F_BYTE_OP (1U << 5U) /* 8-bit operands. */
9299

93100
static const struct instr_emul_vie_op two_byte_opcodes[256] = {
94101
[0xB6] = {
95102
.op_type = VIE_OP_TYPE_MOVZX,
103+
.op_flags = VIE_OP_F_BYTE_OP,
96104
},
97105
[0xB7] = {
98106
.op_type = VIE_OP_TYPE_MOVZX,
@@ -103,6 +111,7 @@ static const struct instr_emul_vie_op two_byte_opcodes[256] = {
103111
},
104112
[0xBE] = {
105113
.op_type = VIE_OP_TYPE_MOVSX,
114+
.op_flags = VIE_OP_F_BYTE_OP,
106115
},
107116
};
108117

@@ -121,12 +130,14 @@ static const struct instr_emul_vie_op one_byte_opcodes[256] = {
121130
},
122131
[0x88] = {
123132
.op_type = VIE_OP_TYPE_MOV,
133+
.op_flags = VIE_OP_F_BYTE_OP,
124134
},
125135
[0x89] = {
126136
.op_type = VIE_OP_TYPE_MOV,
127137
},
128138
[0x8A] = {
129139
.op_type = VIE_OP_TYPE_MOV,
140+
.op_flags = VIE_OP_F_BYTE_OP,
130141
},
131142
[0x8B] = {
132143
.op_type = VIE_OP_TYPE_MOV,
@@ -141,15 +152,15 @@ static const struct instr_emul_vie_op one_byte_opcodes[256] = {
141152
},
142153
[0xA4] = {
143154
.op_type = VIE_OP_TYPE_MOVS,
144-
.op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_CHECK_GVA_DI
155+
.op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_CHECK_GVA_DI | VIE_OP_F_BYTE_OP,
145156
},
146157
[0xA5] = {
147158
.op_type = VIE_OP_TYPE_MOVS,
148-
.op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_CHECK_GVA_DI
159+
.op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_CHECK_GVA_DI,
149160
},
150161
[0xAA] = {
151162
.op_type = VIE_OP_TYPE_STOS,
152-
.op_flags = VIE_OP_F_NO_MODRM
163+
.op_flags = VIE_OP_F_NO_MODRM | VIE_OP_F_BYTE_OP,
153164
},
154165
[0xAB] = {
155166
.op_type = VIE_OP_TYPE_STOS,
@@ -158,7 +169,7 @@ static const struct instr_emul_vie_op one_byte_opcodes[256] = {
158169
[0xC6] = {
159170
/* XXX Group 11 extended opcode - not just MOV */
160171
.op_type = VIE_OP_TYPE_MOV,
161-
.op_flags = VIE_OP_F_IMM8,
172+
.op_flags = VIE_OP_F_IMM8 | VIE_OP_F_BYTE_OP,
162173
},
163174
[0xC7] = {
164175
.op_type = VIE_OP_TYPE_MOV,
@@ -184,12 +195,14 @@ static const struct instr_emul_vie_op one_byte_opcodes[256] = {
184195
},
185196
[0x84] = {
186197
.op_type = VIE_OP_TYPE_TEST,
198+
.op_flags = VIE_OP_F_BYTE_OP,
187199
},
188200
[0x85] = {
189201
.op_type = VIE_OP_TYPE_TEST,
190202
},
191203
[0x08] = {
192204
.op_type = VIE_OP_TYPE_OR,
205+
.op_flags = VIE_OP_F_BYTE_OP,
193206
},
194207
[0x09] = {
195208
.op_type = VIE_OP_TYPE_OR,
@@ -1892,8 +1905,10 @@ static int32_t decode_opcode(struct instr_emul_vie *vie)
18921905
* If w bit of opcode is 1, the operand size is decided
18931906
* by prefix and default operand size attribute (handled
18941907
* in decode_prefixes).
1908+
* The VIE_OP_F_BYTE_OP only set when the instruction support
1909+
* Encoding of Operand Size (w) Bit and the w bit of opcode is 0.
18951910
*/
1896-
if ((ret == 0) && ((vie->opcode & 0x1U) == 0U)) {
1911+
if ((ret == 0) && ((vie->op.op_flags & VIE_OP_F_BYTE_OP) != 0U)) {
18971912
vie->opsize = 1U;
18981913
}
18991914
}

0 commit comments

Comments
 (0)