SMSW instruction on long-mode is performed according to the operand size, if the destination operand is a register. This patch tests whether it is performed correctly instead of always using two-bytes operands (as KVM previously did). Note that when a dword destination operand is used, the result is zero-extended to qword on long-mode. Signed-off-by: Nadav Amit <namit@xxxxxxxxxxxxxxxxx> --- x86/emulator.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/x86/emulator.c b/x86/emulator.c index 033f246..f653127 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -825,6 +825,26 @@ static void test_movabs(uint64_t *mem, uint8_t *insn_page, report("64-bit mov imm2", outregs.rcx == 0x9090909090909090); } +static void test_smsw_reg(uint64_t *mem, uint8_t *insn_page, + uint8_t *alt_insn_page, void *insn_ram) +{ + unsigned long cr0 = read_cr0(); + inregs = (struct regs){ .rax = 0x1234567890abcdeful }; + + MK_INSN(smsww, "smsww %ax\n\t"); + trap_emulator(mem, alt_insn_page, &insn_smsww); + report("16-bit smsw reg", (u16)outregs.rax == (u16)cr0 && + outregs.rax >> 16 == inregs.rax >> 16); + + MK_INSN(smswl, "smswl %eax\n\t"); + trap_emulator(mem, alt_insn_page, &insn_smswl); + report("32-bit smsw reg", outregs.rax == (u32)cr0); + + MK_INSN(smswq, "smswq %rax\n\t"); + trap_emulator(mem, alt_insn_page, &insn_smswq); + report("64-bit smsw reg", outregs.rax == cr0); +} + static void test_crosspage_mmio(volatile uint8_t *mem) { volatile uint16_t w, *pw; @@ -1024,6 +1044,7 @@ int main() test_mmx_movq_mf(mem, insn_page, alt_insn_page, insn_ram); test_movabs(mem, insn_page, alt_insn_page, insn_ram); + test_smsw_reg(mem, insn_page, alt_insn_page, insn_ram); test_crosspage_mmio(mem); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html