aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorAvi Kivity <avi.kivity@gmail.com>2013-02-09 04:31:44 -0500
committerGleb Natapov <gleb@redhat.com>2013-05-21 08:43:14 -0400
commitfb32b1eda29f2040148b0e172f9cbbd2f07697e4 (patch)
treece1844ae8998f70fa0bae623fd44cd793fdb28c1 /arch/x86/kvm/emulate.c
parentf8b5ff2cff232df052955ef975f7219e1faa217f (diff)
KVM: x86 emulator: add support for writing back the source operand
Some instructions write back the source operand, not just the destination. Add support for doing this via the decode flags. Gleb: add BUG_ON() to prevent source to be memory operand. Signed-off-by: Avi Kivity <avi.kivity@gmail.com> Signed-off-by: Gleb Natapov <gleb@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 8db0010ed150..a4c266e99e50 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -155,6 +155,7 @@
155#define Avx ((u64)1 << 43) /* Advanced Vector Extensions */ 155#define Avx ((u64)1 << 43) /* Advanced Vector Extensions */
156#define Fastop ((u64)1 << 44) /* Use opcode::u.fastop */ 156#define Fastop ((u64)1 << 44) /* Use opcode::u.fastop */
157#define NoWrite ((u64)1 << 45) /* No writeback */ 157#define NoWrite ((u64)1 << 45) /* No writeback */
158#define SrcWrite ((u64)1 << 46) /* Write back src operand */
158 159
159#define X2(x...) x, x 160#define X2(x...) x, x
160#define X3(x...) X2(x), x 161#define X3(x...) X2(x), x
@@ -1723,45 +1724,42 @@ static void write_register_operand(struct operand *op)
1723 } 1724 }
1724} 1725}
1725 1726
1726static int writeback(struct x86_emulate_ctxt *ctxt) 1727static int writeback(struct x86_emulate_ctxt *ctxt, struct operand *op)
1727{ 1728{
1728 int rc; 1729 int rc;
1729 1730
1730 if (ctxt->d & NoWrite) 1731 switch (op->type) {
1731 return X86EMUL_CONTINUE;
1732
1733 switch (ctxt->dst.type) {
1734 case OP_REG: 1732 case OP_REG:
1735 write_register_operand(&ctxt->dst); 1733 write_register_operand(op);
1736 break; 1734 break;
1737 case OP_MEM: 1735 case OP_MEM:
1738 if (ctxt->lock_prefix) 1736 if (ctxt->lock_prefix)
1739 rc = segmented_cmpxchg(ctxt, 1737 rc = segmented_cmpxchg(ctxt,
1740 ctxt->dst.addr.mem, 1738 op->addr.mem,
1741 &ctxt->dst.orig_val, 1739 &op->orig_val,
1742 &ctxt->dst.val, 1740 &op->val,
1743 ctxt->dst.bytes); 1741 op->bytes);
1744 else 1742 else
1745 rc = segmented_write(ctxt, 1743 rc = segmented_write(ctxt,
1746 ctxt->dst.addr.mem, 1744 op->addr.mem,
1747 &ctxt->dst.val, 1745 &op->val,
1748 ctxt->dst.bytes); 1746 op->bytes);
1749 if (rc != X86EMUL_CONTINUE) 1747 if (rc != X86EMUL_CONTINUE)
1750 return rc; 1748 return rc;
1751 break; 1749 break;
1752 case OP_MEM_STR: 1750 case OP_MEM_STR:
1753 rc = segmented_write(ctxt, 1751 rc = segmented_write(ctxt,
1754 ctxt->dst.addr.mem, 1752 op->addr.mem,
1755 ctxt->dst.data, 1753 op->data,
1756 ctxt->dst.bytes * ctxt->dst.count); 1754 op->bytes * op->count);
1757 if (rc != X86EMUL_CONTINUE) 1755 if (rc != X86EMUL_CONTINUE)
1758 return rc; 1756 return rc;
1759 break; 1757 break;
1760 case OP_XMM: 1758 case OP_XMM:
1761 write_sse_reg(ctxt, &ctxt->dst.vec_val, ctxt->dst.addr.xmm); 1759 write_sse_reg(ctxt, &op->vec_val, op->addr.xmm);
1762 break; 1760 break;
1763 case OP_MM: 1761 case OP_MM:
1764 write_mmx_reg(ctxt, &ctxt->dst.mm_val, ctxt->dst.addr.mm); 1762 write_mmx_reg(ctxt, &op->mm_val, op->addr.mm);
1765 break; 1763 break;
1766 case OP_NONE: 1764 case OP_NONE:
1767 /* no writeback */ 1765 /* no writeback */
@@ -4769,9 +4767,17 @@ special_insn:
4769 goto done; 4767 goto done;
4770 4768
4771writeback: 4769writeback:
4772 rc = writeback(ctxt); 4770 if (!(ctxt->d & NoWrite)) {
4773 if (rc != X86EMUL_CONTINUE) 4771 rc = writeback(ctxt, &ctxt->dst);
4774 goto done; 4772 if (rc != X86EMUL_CONTINUE)
4773 goto done;
4774 }
4775 if (ctxt->d & SrcWrite) {
4776 BUG_ON(ctxt->src.type == OP_MEM || ctxt->src.type == OP_MEM_STR);
4777 rc = writeback(ctxt, &ctxt->src);
4778 if (rc != X86EMUL_CONTINUE)
4779 goto done;
4780 }
4775 4781
4776 /* 4782 /*
4777 * restore dst type in case the decoding will be reused 4783 * restore dst type in case the decoding will be reused