All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
To: avi@redhat.com, mtosatti@redhat.com
Cc: kvm@vger.kernel.org, yoshikawa.takuya@oss.ntt.co.jp, gleb@redhat.com
Subject: [RFC PATCH 2/2] KVM: x86 emulator: Cleanup emulate_push() writebacks
Date: Tue, 29 Mar 2011 01:34:07 +0900	[thread overview]
Message-ID: <20110329013407.c7bcadcc.takuya.yoshikawa@gmail.com> (raw)
In-Reply-To: <20110329013229.20e6168f.takuya.yoshikawa@gmail.com>

From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>

Recently, emulate_push family functions started to call writeback()
during their emulation.  This clearly shows that the usual writeback()
which is done at the end of x86_emulate_insn() cannot cover all cases.
Furthermore, suppressing writeback by changing dst operand's type is
not simple when conditional writeback must be taken care of.

This patch improves this situation a bit by making emulate_push()
itself do writeback and removes scattered writebacks from callers.

This is done by splitting the writeback for OP_MEM case out from
writeback() as a new helper function, writeback_to_mem(), and call it
directly from emulate_push().

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
---
 arch/x86/kvm/emulate.c |  111 ++++++++++++++++++++---------------------------
 1 files changed, 47 insertions(+), 64 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 8a73805..fe3419a 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1069,6 +1069,20 @@ static void write_register_operand(struct operand *op)
 	}
 }
 
+static int writeback_to_mem(struct x86_emulate_ctxt *ctxt,
+			    struct x86_emulate_ops *ops,
+			    struct decode_cache *c)
+{
+	if (c->lock_prefix)
+		return ops->cmpxchg_emulated(linear(ctxt, c->dst.addr.mem),
+				&c->dst.orig_val, &c->dst.val, c->dst.bytes,
+				&ctxt->exception, ctxt->vcpu);
+	else
+		return ops->write_emulated(linear(ctxt, c->dst.addr.mem),
+					&c->dst.val, c->dst.bytes,
+					&ctxt->exception, ctxt->vcpu);
+}
+
 static inline int writeback(struct x86_emulate_ctxt *ctxt,
 			    struct x86_emulate_ops *ops)
 {
@@ -1080,21 +1094,7 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt,
 		write_register_operand(&c->dst);
 		break;
 	case OP_MEM:
-		if (c->lock_prefix)
-			rc = ops->cmpxchg_emulated(
-					linear(ctxt, c->dst.addr.mem),
-					&c->dst.orig_val,
-					&c->dst.val,
-					c->dst.bytes,
-					&ctxt->exception,
-					ctxt->vcpu);
-		else
-			rc = ops->write_emulated(
-					linear(ctxt, c->dst.addr.mem),
-					&c->dst.val,
-					c->dst.bytes,
-					&ctxt->exception,
-					ctxt->vcpu);
+		rc = writeback_to_mem(ctxt, ops, c);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		break;
@@ -1107,17 +1107,21 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt,
 	return X86EMUL_CONTINUE;
 }
 
-static inline void emulate_push(struct x86_emulate_ctxt *ctxt,
-				struct x86_emulate_ops *ops)
+static inline int emulate_push(struct x86_emulate_ctxt *ctxt,
+			       struct x86_emulate_ops *ops)
 {
 	struct decode_cache *c = &ctxt->decode;
+	int rc;
 
-	c->dst.type  = OP_MEM;
 	c->dst.bytes = c->op_bytes;
 	c->dst.val = c->src.val;
 	register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes);
 	c->dst.addr.mem.ea = register_address(c, c->regs[VCPU_REGS_RSP]);
 	c->dst.addr.mem.seg = VCPU_SREG_SS;
+
+	rc = writeback_to_mem(ctxt, ops, c);
+	c->dst.type = OP_NONE;
+	return rc;
 }
 
 static int emulate_pop(struct x86_emulate_ctxt *ctxt,
@@ -1179,14 +1183,13 @@ static int emulate_popf(struct x86_emulate_ctxt *ctxt,
 	return rc;
 }
 
-static void emulate_push_sreg(struct x86_emulate_ctxt *ctxt,
-			      struct x86_emulate_ops *ops, int seg)
+static int emulate_push_sreg(struct x86_emulate_ctxt *ctxt,
+			     struct x86_emulate_ops *ops, int seg)
 {
 	struct decode_cache *c = &ctxt->decode;
 
 	c->src.val = ops->get_segment_selector(seg, ctxt->vcpu);
-
-	emulate_push(ctxt, ops);
+	return emulate_push(ctxt, ops);
 }
 
 static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt,
@@ -1216,18 +1219,13 @@ static int emulate_pusha(struct x86_emulate_ctxt *ctxt,
 		(reg == VCPU_REGS_RSP) ?
 		(c->src.val = old_esp) : (c->src.val = c->regs[reg]);
 
-		emulate_push(ctxt, ops);
-
-		rc = writeback(ctxt, ops);
+		rc = emulate_push(ctxt, ops);
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 
 		++reg;
 	}
 
-	/* Disable writeback. */
-	c->dst.type = OP_NONE;
-
 	return rc;
 }
 
@@ -1265,22 +1263,19 @@ int emulate_int_real(struct x86_emulate_ctxt *ctxt,
 
 	/* TODO: Add limit checks */
 	c->src.val = ctxt->eflags;
-	emulate_push(ctxt, ops);
-	rc = writeback(ctxt, ops);
+	rc = emulate_push(ctxt, ops);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
 	ctxt->eflags &= ~(EFLG_IF | EFLG_TF | EFLG_AC);
 
 	c->src.val = ops->get_segment_selector(VCPU_SREG_CS, ctxt->vcpu);
-	emulate_push(ctxt, ops);
-	rc = writeback(ctxt, ops);
+	rc = emulate_push(ctxt, ops);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
 	c->src.val = c->eip;
-	emulate_push(ctxt, ops);
-	rc = writeback(ctxt, ops);
+	rc = emulate_push(ctxt, ops);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
@@ -1475,6 +1470,7 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt,
 			       struct x86_emulate_ops *ops)
 {
 	struct decode_cache *c = &ctxt->decode;
+	int rc = X86EMUL_CONTINUE;
 
 	switch (c->modrm_reg) {
 	case 0:	/* inc */
@@ -1488,17 +1484,17 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt,
 		old_eip = c->eip;
 		c->eip = c->src.val;
 		c->src.val = old_eip;
-		emulate_push(ctxt, ops);
+		rc = emulate_push(ctxt, ops);
 		break;
 	}
 	case 4: /* jmp abs */
 		c->eip = c->src.val;
 		break;
 	case 6:	/* push */
-		emulate_push(ctxt, ops);
+		rc = emulate_push(ctxt, ops);
 		break;
 	}
-	return X86EMUL_CONTINUE;
+	return rc;
 }
 
 static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt,
@@ -2142,7 +2138,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 		c->op_bytes = c->ad_bytes = (next_tss_desc.type & 8) ? 4 : 2;
 		c->lock_prefix = 0;
 		c->src.val = (unsigned long) error_code;
-		emulate_push(ctxt, ops);
+		ret = emulate_push(ctxt, ops);
 	}
 
 	return ret;
@@ -2157,16 +2153,12 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
 	int rc;
 
 	c->eip = ctxt->eip;
-	c->dst.type = OP_NONE;
 
 	rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason,
 				     has_error_code, error_code);
 
-	if (rc == X86EMUL_CONTINUE) {
-		rc = writeback(ctxt, ops);
-		if (rc == X86EMUL_CONTINUE)
-			ctxt->eip = c->eip;
-	}
+	if (rc == X86EMUL_CONTINUE)
+		ctxt->eip = c->eip;
 
 	return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
 }
@@ -2184,8 +2176,7 @@ static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned seg,
 
 static int em_push(struct x86_emulate_ctxt *ctxt)
 {
-	emulate_push(ctxt, ctxt->ops);
-	return X86EMUL_CONTINUE;
+	return emulate_push(ctxt, ctxt->ops);
 }
 
 static int em_das(struct x86_emulate_ctxt *ctxt)
@@ -2245,20 +2236,12 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt)
 	memcpy(&c->eip, c->src.valptr, c->op_bytes);
 
 	c->src.val = old_cs;
-	emulate_push(ctxt, ctxt->ops);
-	rc = writeback(ctxt, ctxt->ops);
+	rc = emulate_push(ctxt, ctxt->ops);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
 	c->src.val = old_eip;
-	emulate_push(ctxt, ctxt->ops);
-	rc = writeback(ctxt, ctxt->ops);
-	if (rc != X86EMUL_CONTINUE)
-		return rc;
-
-	c->dst.type = OP_NONE;
-
-	return X86EMUL_CONTINUE;
+	return emulate_push(ctxt, ctxt->ops);
 }
 
 static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
@@ -3039,7 +3022,7 @@ special_insn:
 		emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags);
 		break;
 	case 0x06:		/* push es */
-		emulate_push_sreg(ctxt, ops, VCPU_SREG_ES);
+		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_ES);
 		break;
 	case 0x07:		/* pop es */
 		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_ES);
@@ -3049,14 +3032,14 @@ special_insn:
 		emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags);
 		break;
 	case 0x0e:		/* push cs */
-		emulate_push_sreg(ctxt, ops, VCPU_SREG_CS);
+		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_CS);
 		break;
 	case 0x10 ... 0x15:
 	      adc:		/* adc */
 		emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags);
 		break;
 	case 0x16:		/* push ss */
-		emulate_push_sreg(ctxt, ops, VCPU_SREG_SS);
+		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_SS);
 		break;
 	case 0x17:		/* pop ss */
 		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_SS);
@@ -3066,7 +3049,7 @@ special_insn:
 		emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags);
 		break;
 	case 0x1e:		/* push ds */
-		emulate_push_sreg(ctxt, ops, VCPU_SREG_DS);
+		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_DS);
 		break;
 	case 0x1f:		/* pop ds */
 		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_DS);
@@ -3204,7 +3187,7 @@ special_insn:
 		break;
 	case 0x9c: /* pushf */
 		c->src.val =  (unsigned long) ctxt->eflags;
-		emulate_push(ctxt, ops);
+		rc = emulate_push(ctxt, ops);
 		break;
 	case 0x9d: /* popf */
 		c->dst.type = OP_REG;
@@ -3280,7 +3263,7 @@ special_insn:
 		long int rel = c->src.val;
 		c->src.val = (unsigned long) c->eip;
 		jmp_rel(c, rel);
-		emulate_push(ctxt, ops);
+		rc = emulate_push(ctxt, ops);
 		break;
 	}
 	case 0xe9: /* jmp rel */
@@ -3605,7 +3588,7 @@ twobyte_insn:
 		c->dst.val = test_cc(c->b, ctxt->eflags);
 		break;
 	case 0xa0:	  /* push fs */
-		emulate_push_sreg(ctxt, ops, VCPU_SREG_FS);
+		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_FS);
 		break;
 	case 0xa1:	 /* pop fs */
 		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_FS);
@@ -3622,7 +3605,7 @@ twobyte_insn:
 		emulate_2op_cl("shld", c->src2, c->src, c->dst, ctxt->eflags);
 		break;
 	case 0xa8:	/* push gs */
-		emulate_push_sreg(ctxt, ops, VCPU_SREG_GS);
+		rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_GS);
 		break;
 	case 0xa9:	/* pop gs */
 		rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_GS);
-- 
1.7.1


  reply	other threads:[~2011-03-28 16:34 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-28 16:32 [PATCH 1/2] KVM: x86 emulator: Disable writeback for CMP emulation Takuya Yoshikawa
2011-03-28 16:34 ` Takuya Yoshikawa [this message]
2011-03-30  6:51   ` [RFC PATCH 2/2] KVM: x86 emulator: Cleanup emulate_push() writebacks Takuya Yoshikawa
2011-04-03 14:50   ` Avi Kivity
2011-04-03 15:59     ` Takuya Yoshikawa
2011-04-03 16:04       ` Avi Kivity
2011-04-03 16:09         ` Takuya Yoshikawa
2011-04-03 16:11           ` Avi Kivity
2011-04-03 14:42 ` [PATCH 1/2] KVM: x86 emulator: Disable writeback for CMP emulation Avi Kivity

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110329013407.c7bcadcc.takuya.yoshikawa@gmail.com \
    --to=takuya.yoshikawa@gmail.com \
    --cc=avi@redhat.com \
    --cc=gleb@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    --cc=yoshikawa.takuya@oss.ntt.co.jp \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.