Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 02c03a32 authored by Luca Tettamanti's avatar Luca Tettamanti Committed by Avi Kivity
Browse files

KVM: Fix x86 emulator writeback



When the old value and new one are the same the emulator skips the
write; this is undesirable when the destination is a MMIO area and the
write shall be performed regardless of the previous value. This
optimization breaks e.g. a Linux guest APIC compiled without
X86_GOOD_APIC.

Remove the check and perform the writeback stage in the emulation unless
it's explicitly disabled (currently push and some 2 bytes instructions
may disable the writeback).

Signed-Off-By: default avatarLuca Tettamanti <kronos.it@gmail.com>
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent 74906345
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -485,6 +485,7 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
	int mode = ctxt->mode;
	unsigned long modrm_ea;
	int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0;
	int no_wb = 0;

	/* Shadow copy of register state. Committed on successful emulation. */
	unsigned long _regs[NR_VCPU_REGS];
@@ -1051,7 +1052,7 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
						      _regs[VCPU_REGS_RSP]),
				     &dst.val, dst.bytes, ctxt)) != 0)
				goto done;
			dst.val = dst.orig_val;	/* skanky: disable writeback */
			no_wb = 1;
			break;
		default:
			goto cannot_emulate;
@@ -1060,7 +1061,7 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
	}

writeback:
	if ((d & Mov) || (dst.orig_val != dst.val)) {
	if (!no_wb) {
		switch (dst.type) {
		case OP_REG:
			/* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
@@ -1168,7 +1169,7 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
			goto done;

		register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
		dst.orig_val = dst.val; /* Disable writeback. */
		no_wb = 1; /* Disable writeback. */
		break;
	}
	goto writeback;
@@ -1323,7 +1324,7 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)

twobyte_special_insn:
	/* Disable writeback. */
	dst.orig_val = dst.val;
	no_wb = 1;
	switch (b) {
	case 0x09:		/* wbinvd */
		break;