All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions
@ 2012-04-23 15:31 Takuya Yoshikawa
  2012-04-23 15:33 ` [PATCH 1/4] KVM: x86 emulator: Introduce ctxt->op_prefix for 0x66 prefix Takuya Yoshikawa
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-04-23 15:31 UTC (permalink / raw)
  To: avi, mtosatti; +Cc: kvm, yoshikawa.takuya

Takuya Yoshikawa (4):
  KVM: x86 emulator: Introduce ctxt->op_prefix for 0x66 prefix
  KVM: x86 emulator: Make prefix decoding a separate function
  KVM: x86 emulator: Make opcode decoding a separate function
  KVM: x86 emulator: Avoid pushing back ModRM byte in decode_opcode()

 arch/x86/include/asm/kvm_emulate.h |    1 +
 arch/x86/kvm/emulate.c             |  124 ++++++++++++++++++++++++------------
 2 files changed, 84 insertions(+), 41 deletions(-)

-- 
1.7.5.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] KVM: x86 emulator: Introduce ctxt->op_prefix for 0x66 prefix
  2012-04-23 15:31 [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Takuya Yoshikawa
@ 2012-04-23 15:33 ` Takuya Yoshikawa
  2012-04-23 15:34 ` [PATCH 2/4] KVM: x86 emulator: Make prefix decoding a separate function Takuya Yoshikawa
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-04-23 15:33 UTC (permalink / raw)
  To: avi, mtosatti; +Cc: kvm, yoshikawa.takuya

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

This is needed to make prefix decoding a separate function.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Cc: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
---
 arch/x86/include/asm/kvm_emulate.h |    1 +
 arch/x86/kvm/emulate.c             |    7 +++----
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 1ac46c22..75783a7 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -261,6 +261,7 @@ struct x86_emulate_ctxt {
 	u8 intercept;
 	u8 lock_prefix;
 	u8 rep_prefix;
+	u8 op_prefix;
 	u8 op_bytes;
 	u8 ad_bytes;
 	u8 rex_prefix;
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index d5729a9..5a49290 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3879,7 +3879,6 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 	int rc = X86EMUL_CONTINUE;
 	int mode = ctxt->mode;
 	int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
-	bool op_prefix = false;
 	struct opcode opcode;
 
 	ctxt->memop.type = OP_NONE;
@@ -3916,7 +3915,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 	for (;;) {
 		switch (ctxt->b = insn_fetch(u8, ctxt)) {
 		case 0x66:	/* operand-size override */
-			op_prefix = true;
+			ctxt->op_prefix = ctxt->b;
 			/* switch between 2/4 bytes */
 			ctxt->op_bytes = def_op_bytes ^ 6;
 			break;
@@ -3997,9 +3996,9 @@ done_prefixes:
 			opcode = opcode.u.group[goffset];
 			break;
 		case Prefix:
-			if (ctxt->rep_prefix && op_prefix)
+			if (ctxt->rep_prefix && ctxt->op_prefix)
 				return EMULATION_FAILED;
-			simd_prefix = op_prefix ? 0x66 : ctxt->rep_prefix;
+			simd_prefix = ctxt->rep_prefix | ctxt->op_prefix;
 			switch (simd_prefix) {
 			case 0x00: opcode = opcode.u.gprefix->pfx_no; break;
 			case 0x66: opcode = opcode.u.gprefix->pfx_66; break;
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] KVM: x86 emulator: Make prefix decoding a separate function
  2012-04-23 15:31 [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Takuya Yoshikawa
  2012-04-23 15:33 ` [PATCH 1/4] KVM: x86 emulator: Introduce ctxt->op_prefix for 0x66 prefix Takuya Yoshikawa
@ 2012-04-23 15:34 ` Takuya Yoshikawa
  2012-04-23 15:35 ` [PATCH 3/4] KVM: x86 emulator: Make opcode " Takuya Yoshikawa
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-04-23 15:34 UTC (permalink / raw)
  To: avi, mtosatti; +Cc: kvm, yoshikawa.takuya

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

Instruction decoding can be split into separate parts, and this is the
first one which treats the instruction prefixes.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Cc: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
---
 arch/x86/kvm/emulate.c |   58 +++++++++++++++++++++++++++++++----------------
 1 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 5a49290..b22238b 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3874,22 +3874,21 @@ done:
 	return rc;
 }
 
-int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
+/**
+ * decode_prefixes - decode instruction prefixes
+ * @ctxt: emulation context
+ *
+ * Fetches instruction prefixes and sets some ctxt fields based on them.
+ * The byte next to the last prefix is also fetched into ctxt->b.
+ *
+ * Returns X86EMUL_CONTINUE on success.
+ */
+static int decode_prefixes(struct x86_emulate_ctxt *ctxt)
 {
 	int rc = X86EMUL_CONTINUE;
-	int mode = ctxt->mode;
-	int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
-	struct opcode opcode;
+	int def_op_bytes, def_ad_bytes;
 
-	ctxt->memop.type = OP_NONE;
-	ctxt->memopp = NULL;
-	ctxt->_eip = ctxt->eip;
-	ctxt->fetch.start = ctxt->_eip;
-	ctxt->fetch.end = ctxt->fetch.start + insn_len;
-	if (insn_len > 0)
-		memcpy(ctxt->fetch.data, insn, insn_len);
-
-	switch (mode) {
+	switch (ctxt->mode) {
 	case X86EMUL_MODE_REAL:
 	case X86EMUL_MODE_VM86:
 	case X86EMUL_MODE_PROT16:
@@ -3905,7 +3904,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 		break;
 #endif
 	default:
-		return EMULATION_FAILED;
+		return X86EMUL_UNHANDLEABLE;
 	}
 
 	ctxt->op_bytes = def_op_bytes;
@@ -3920,7 +3919,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 			ctxt->op_bytes = def_op_bytes ^ 6;
 			break;
 		case 0x67:	/* address-size override */
-			if (mode == X86EMUL_MODE_PROT64)
+			if (ctxt->mode == X86EMUL_MODE_PROT64)
 				/* switch between 4/8 bytes */
 				ctxt->ad_bytes = def_ad_bytes ^ 12;
 			else
@@ -3938,7 +3937,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 			set_seg_override(ctxt, ctxt->b & 7);
 			break;
 		case 0x40 ... 0x4f: /* REX */
-			if (mode != X86EMUL_MODE_PROT64)
+			if (ctxt->mode != X86EMUL_MODE_PROT64)
 				goto done_prefixes;
 			ctxt->rex_prefix = ctxt->b;
 			continue;
@@ -3954,15 +3953,34 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 		}
 
 		/* Any legacy prefix after a REX prefix nullifies its effect. */
-
 		ctxt->rex_prefix = 0;
 	}
 
 done_prefixes:
-
 	/* REX prefix. */
 	if (ctxt->rex_prefix & 8)
 		ctxt->op_bytes = 8;	/* REX.W */
+done:
+	return rc;
+}
+
+int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
+{
+	int rc = X86EMUL_CONTINUE;
+	int goffset, simd_prefix;
+	struct opcode opcode;
+
+	ctxt->memop.type = OP_NONE;
+	ctxt->memopp = NULL;
+	ctxt->_eip = ctxt->eip;
+	ctxt->fetch.start = ctxt->_eip;
+	ctxt->fetch.end = ctxt->fetch.start + insn_len;
+	if (insn_len > 0)
+		memcpy(ctxt->fetch.data, insn, insn_len);
+
+	rc = decode_prefixes(ctxt);
+	if (rc != X86EMUL_CONTINUE)
+		goto done;
 
 	/* Opcode byte(s). */
 	opcode = opcode_table[ctxt->b];
@@ -4025,11 +4043,11 @@ done_prefixes:
 	if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
 		return EMULATION_FAILED;
 
-	if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
+	if (ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
 		ctxt->op_bytes = 8;
 
 	if (ctxt->d & Op3264) {
-		if (mode == X86EMUL_MODE_PROT64)
+		if (ctxt->mode == X86EMUL_MODE_PROT64)
 			ctxt->op_bytes = 8;
 		else
 			ctxt->op_bytes = 4;
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/4] KVM: x86 emulator: Make opcode decoding a separate function
  2012-04-23 15:31 [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Takuya Yoshikawa
  2012-04-23 15:33 ` [PATCH 1/4] KVM: x86 emulator: Introduce ctxt->op_prefix for 0x66 prefix Takuya Yoshikawa
  2012-04-23 15:34 ` [PATCH 2/4] KVM: x86 emulator: Make prefix decoding a separate function Takuya Yoshikawa
@ 2012-04-23 15:35 ` Takuya Yoshikawa
  2012-04-23 15:37 ` [PATCH 4/4] KVM: x86 emulator: Avoid pushing back ModRM byte in decode_opcode() Takuya Yoshikawa
  2012-04-24 14:11 ` [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Avi Kivity
  4 siblings, 0 replies; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-04-23 15:35 UTC (permalink / raw)
  To: avi, mtosatti; +Cc: kvm, yoshikawa.takuya

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

This is the second part of the instruction decoding which treats the
opcode.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Cc: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
---
 arch/x86/kvm/emulate.c |   66 +++++++++++++++++++++++++++++++----------------
 1 files changed, 43 insertions(+), 23 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b22238b..e87570e 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3964,32 +3964,28 @@ done:
 	return rc;
 }
 
-int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
+/**
+ * decode_opcode - decode opcode
+ * @ctxt: emulation context
+ *
+ * Decodes opcode bytes and reads opcode from table.
+ *
+ * Returns X86EMUL_CONTINUE on success.
+ */
+static int decode_opcode(struct x86_emulate_ctxt *ctxt)
 {
 	int rc = X86EMUL_CONTINUE;
 	int goffset, simd_prefix;
 	struct opcode opcode;
 
-	ctxt->memop.type = OP_NONE;
-	ctxt->memopp = NULL;
-	ctxt->_eip = ctxt->eip;
-	ctxt->fetch.start = ctxt->_eip;
-	ctxt->fetch.end = ctxt->fetch.start + insn_len;
-	if (insn_len > 0)
-		memcpy(ctxt->fetch.data, insn, insn_len);
-
-	rc = decode_prefixes(ctxt);
-	if (rc != X86EMUL_CONTINUE)
-		goto done;
-
-	/* Opcode byte(s). */
-	opcode = opcode_table[ctxt->b];
 	/* Two-byte opcode? */
 	if (ctxt->b == 0x0f) {
 		ctxt->twobyte = 1;
 		ctxt->b = insn_fetch(u8, ctxt);
 		opcode = twobyte_table[ctxt->b];
-	}
+	} else
+		opcode = opcode_table[ctxt->b];
+
 	ctxt->d = opcode.flags;
 
 	while (ctxt->d & GroupMask) {
@@ -4015,7 +4011,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 			break;
 		case Prefix:
 			if (ctxt->rep_prefix && ctxt->op_prefix)
-				return EMULATION_FAILED;
+				return X86EMUL_UNHANDLEABLE;
 			simd_prefix = ctxt->rep_prefix | ctxt->op_prefix;
 			switch (simd_prefix) {
 			case 0x00: opcode = opcode.u.gprefix->pfx_no; break;
@@ -4025,23 +4021,47 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 			}
 			break;
 		default:
-			return EMULATION_FAILED;
+			return X86EMUL_UNHANDLEABLE;
 		}
 
 		ctxt->d &= ~(u64)GroupMask;
 		ctxt->d |= opcode.flags;
 	}
 
+	/* Unrecognised? */
+	if (ctxt->d == 0 || (ctxt->d & Undefined))
+		return X86EMUL_UNHANDLEABLE;
+
+	if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
+		return X86EMUL_UNHANDLEABLE;
+
 	ctxt->execute = opcode.u.execute;
 	ctxt->check_perm = opcode.check_perm;
 	ctxt->intercept = opcode.intercept;
 
-	/* Unrecognised? */
-	if (ctxt->d == 0 || (ctxt->d & Undefined))
-		return EMULATION_FAILED;
+done:
+	return rc;
+}
 
-	if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
-		return EMULATION_FAILED;
+int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
+{
+	int rc = X86EMUL_CONTINUE;
+
+	ctxt->memop.type = OP_NONE;
+	ctxt->memopp = NULL;
+	ctxt->_eip = ctxt->eip;
+	ctxt->fetch.start = ctxt->_eip;
+	ctxt->fetch.end = ctxt->fetch.start + insn_len;
+	if (insn_len > 0)
+		memcpy(ctxt->fetch.data, insn, insn_len);
+
+	rc = decode_prefixes(ctxt);
+	if (rc != X86EMUL_CONTINUE)
+		goto done;
+
+	rc = decode_opcode(ctxt);
+	if (rc != X86EMUL_CONTINUE)
+		goto done;
 
 	if (ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
 		ctxt->op_bytes = 8;
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/4] KVM: x86 emulator: Avoid pushing back ModRM byte in decode_opcode()
  2012-04-23 15:31 [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Takuya Yoshikawa
                   ` (2 preceding siblings ...)
  2012-04-23 15:35 ` [PATCH 3/4] KVM: x86 emulator: Make opcode " Takuya Yoshikawa
@ 2012-04-23 15:37 ` Takuya Yoshikawa
  2012-04-24 14:10   ` Avi Kivity
  2012-04-24 14:11 ` [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Avi Kivity
  4 siblings, 1 reply; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-04-23 15:37 UTC (permalink / raw)
  To: avi, mtosatti; +Cc: kvm, yoshikawa.takuya

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

Although ModRM byte is read for group decoding, it is soon pushed back
to make decode_modrm() fetch it later.

We should consistently read it, only once, in decode_opcode() instead.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Cc: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
---
 arch/x86/kvm/emulate.c |   19 ++++++++++++-------
 1 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index e87570e..8729773 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -972,7 +972,6 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
 		ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */
 	}
 
-	ctxt->modrm = insn_fetch(u8, ctxt);
 	ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6;
 	ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
 	ctxt->modrm_rm |= (ctxt->modrm & 0x07);
@@ -3969,6 +3968,7 @@ done:
  * @ctxt: emulation context
  *
  * Decodes opcode bytes and reads opcode from table.
+ * The ModRM byte, if exists, is also fetched into ctxt->modrm.
  *
  * Returns X86EMUL_CONTINUE on success.
  */
@@ -3977,6 +3977,8 @@ static int decode_opcode(struct x86_emulate_ctxt *ctxt)
 	int rc = X86EMUL_CONTINUE;
 	int goffset, simd_prefix;
 	struct opcode opcode;
+	bool modrm_fetched = false;
+	u64 gtype;
 
 	/* Two-byte opcode? */
 	if (ctxt->b == 0x0f) {
@@ -3988,17 +3990,18 @@ static int decode_opcode(struct x86_emulate_ctxt *ctxt)
 
 	ctxt->d = opcode.flags;
 
-	while (ctxt->d & GroupMask) {
-		switch (ctxt->d & GroupMask) {
-		case Group:
+	while ((gtype = ctxt->d & GroupMask)) {
+		if (!modrm_fetched && gtype != Prefix) {
 			ctxt->modrm = insn_fetch(u8, ctxt);
-			--ctxt->_eip;
+			modrm_fetched = true;
+		}
+
+		switch (gtype) {
+		case Group:
 			goffset = (ctxt->modrm >> 3) & 7;
 			opcode = opcode.u.group[goffset];
 			break;
 		case GroupDual:
-			ctxt->modrm = insn_fetch(u8, ctxt);
-			--ctxt->_eip;
 			goffset = (ctxt->modrm >> 3) & 7;
 			if ((ctxt->modrm >> 6) == 3)
 				opcode = opcode.u.gdual->mod3[goffset];
@@ -4039,6 +4042,8 @@ static int decode_opcode(struct x86_emulate_ctxt *ctxt)
 	ctxt->check_perm = opcode.check_perm;
 	ctxt->intercept = opcode.intercept;
 
+	if (!modrm_fetched && (ctxt->d & ModRM))
+		ctxt->modrm = insn_fetch(u8, ctxt);
 done:
 	return rc;
 }
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] KVM: x86 emulator: Avoid pushing back ModRM byte in decode_opcode()
  2012-04-23 15:37 ` [PATCH 4/4] KVM: x86 emulator: Avoid pushing back ModRM byte in decode_opcode() Takuya Yoshikawa
@ 2012-04-24 14:10   ` Avi Kivity
  2012-04-24 14:27     ` Takuya Yoshikawa
  0 siblings, 1 reply; 9+ messages in thread
From: Avi Kivity @ 2012-04-24 14:10 UTC (permalink / raw)
  To: Takuya Yoshikawa; +Cc: mtosatti, kvm, yoshikawa.takuya

On 04/23/2012 06:37 PM, Takuya Yoshikawa wrote:
> From: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
>
> Although ModRM byte is read for group decoding, it is soon pushed back
> to make decode_modrm() fetch it later.
>
> We should consistently read it, only once, in decode_opcode() instead.
>
> Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
> Cc: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
> ---
>  arch/x86/kvm/emulate.c |   19 ++++++++++++-------
>  1 files changed, 12 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index e87570e..8729773 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -972,7 +972,6 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
>  		ctxt->modrm_rm = base_reg = (ctxt->rex_prefix & 1) << 3; /* REG.B */
>  	}
>  
> -	ctxt->modrm = insn_fetch(u8, ctxt);
>  	ctxt->modrm_mod |= (ctxt->modrm & 0xc0) >> 6;
>  	ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
>  	ctxt->modrm_rm |= (ctxt->modrm & 0x07);
> @@ -3969,6 +3968,7 @@ done:
>   * @ctxt: emulation context
>   *
>   * Decodes opcode bytes and reads opcode from table.
> + * The ModRM byte, if exists, is also fetched into ctxt->modrm.
>   *
>   * Returns X86EMUL_CONTINUE on success.
>   */
> @@ -3977,6 +3977,8 @@ static int decode_opcode(struct x86_emulate_ctxt *ctxt)
>  	int rc = X86EMUL_CONTINUE;
>  	int goffset, simd_prefix;
>  	struct opcode opcode;
> +	bool modrm_fetched = false;
> +	u64 gtype;
>  
>  	/* Two-byte opcode? */
>  	if (ctxt->b == 0x0f) {
> @@ -3988,17 +3990,18 @@ static int decode_opcode(struct x86_emulate_ctxt *ctxt)
>  
>  	ctxt->d = opcode.flags;
>  
> -	while (ctxt->d & GroupMask) {
> -		switch (ctxt->d & GroupMask) {
> -		case Group:
> +	while ((gtype = ctxt->d & GroupMask)) {
> +		if (!modrm_fetched && gtype != Prefix) {
>  			ctxt->modrm = insn_fetch(u8, ctxt);
> -			--ctxt->_eip;
> +			modrm_fetched = true;
> +		}
> +
> +		switch (gtype) {
> +		case Group:
>  			goffset = (ctxt->modrm >> 3) & 7;
>  			opcode = opcode.u.group[goffset];
>  			break;
>  		case GroupDual:
> -			ctxt->modrm = insn_fetch(u8, ctxt);
> -			--ctxt->_eip;
>  			goffset = (ctxt->modrm >> 3) & 7;
>  			if ((ctxt->modrm >> 6) == 3)
>  				opcode = opcode.u.gdual->mod3[goffset];
> @@ -4039,6 +4042,8 @@ static int decode_opcode(struct x86_emulate_ctxt *ctxt)
>  	ctxt->check_perm = opcode.check_perm;
>  	ctxt->intercept = opcode.intercept;
>  
> +	if (!modrm_fetched && (ctxt->d & ModRM))
> +		ctxt->modrm = insn_fetch(u8, ctxt);

Instead of adding yet another conditional, how about doing something like

   if ((c->d & ModRM) || (gtype == Group) || (gtype == GroupDual))
          ctxt->modrm = insn_fetch(u8, ctxt);

somewhere early?

In fact even that is too much.  All groups have ModRM somewhere in their
encoding; all we have to do is move it to the main tables (opcode_table
or twobyte_table) and just move the existing modrm fetch before group
parsing.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions
  2012-04-23 15:31 [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Takuya Yoshikawa
                   ` (3 preceding siblings ...)
  2012-04-23 15:37 ` [PATCH 4/4] KVM: x86 emulator: Avoid pushing back ModRM byte in decode_opcode() Takuya Yoshikawa
@ 2012-04-24 14:11 ` Avi Kivity
  2012-04-24 14:41   ` Takuya Yoshikawa
  4 siblings, 1 reply; 9+ messages in thread
From: Avi Kivity @ 2012-04-24 14:11 UTC (permalink / raw)
  To: Takuya Yoshikawa; +Cc: mtosatti, kvm, yoshikawa.takuya

On 04/23/2012 06:31 PM, Takuya Yoshikawa wrote:
> Takuya Yoshikawa (4):
>   KVM: x86 emulator: Introduce ctxt->op_prefix for 0x66 prefix
>   KVM: x86 emulator: Make prefix decoding a separate function
>   KVM: x86 emulator: Make opcode decoding a separate function
>

I don't see the benefit for the first three patches.  They add more
state, and don't encourage any reuse.  The current code is complicated,
but just splitting it doesn't really fix that.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] KVM: x86 emulator: Avoid pushing back ModRM byte in decode_opcode()
  2012-04-24 14:10   ` Avi Kivity
@ 2012-04-24 14:27     ` Takuya Yoshikawa
  0 siblings, 0 replies; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-04-24 14:27 UTC (permalink / raw)
  To: Avi Kivity; +Cc: mtosatti, kvm, yoshikawa.takuya

On Tue, 24 Apr 2012 17:10:08 +0300
Avi Kivity <avi@redhat.com> wrote:

> > +	if (!modrm_fetched && (ctxt->d & ModRM))
> > +		ctxt->modrm = insn_fetch(u8, ctxt);
> 
> Instead of adding yet another conditional, how about doing something like
> 
>    if ((c->d & ModRM) || (gtype == Group) || (gtype == GroupDual))
>           ctxt->modrm = insn_fetch(u8, ctxt);
> 
> somewhere early?

Looks nicer than mine.

> In fact even that is too much.  All groups have ModRM somewhere in their
> encoding; all we have to do is move it to the main tables (opcode_table
> or twobyte_table) and just move the existing modrm fetch before group
> parsing.

I see.

Then, the best way to go seems to be drop patch-4 and work on the ModRM
fetch issue separately.

Modifying the tables needs some care.

Thanks,
	Takuya

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions
  2012-04-24 14:11 ` [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Avi Kivity
@ 2012-04-24 14:41   ` Takuya Yoshikawa
  0 siblings, 0 replies; 9+ messages in thread
From: Takuya Yoshikawa @ 2012-04-24 14:41 UTC (permalink / raw)
  To: Avi Kivity; +Cc: mtosatti, kvm, yoshikawa.takuya

On Tue, 24 Apr 2012 17:11:54 +0300
Avi Kivity <avi@redhat.com> wrote:

> On 04/23/2012 06:31 PM, Takuya Yoshikawa wrote:
> > Takuya Yoshikawa (4):
> >   KVM: x86 emulator: Introduce ctxt->op_prefix for 0x66 prefix
> >   KVM: x86 emulator: Make prefix decoding a separate function
> >   KVM: x86 emulator: Make opcode decoding a separate function
> >
> 
> I don't see the benefit for the first three patches.  They add more
> state, and don't encourage any reuse.  The current code is complicated,
> but just splitting it doesn't really fix that.

I thought up these when some people tried to use some opcode/prefix
bytes in wrong stages.

Although I personally like splitting a long function into named
sub-functions, it's just a matter of taste.

OK, then I will focus on modrm fetching.

Thanks,
	Takuya

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-04-24 14:41 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-23 15:31 [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Takuya Yoshikawa
2012-04-23 15:33 ` [PATCH 1/4] KVM: x86 emulator: Introduce ctxt->op_prefix for 0x66 prefix Takuya Yoshikawa
2012-04-23 15:34 ` [PATCH 2/4] KVM: x86 emulator: Make prefix decoding a separate function Takuya Yoshikawa
2012-04-23 15:35 ` [PATCH 3/4] KVM: x86 emulator: Make opcode " Takuya Yoshikawa
2012-04-23 15:37 ` [PATCH 4/4] KVM: x86 emulator: Avoid pushing back ModRM byte in decode_opcode() Takuya Yoshikawa
2012-04-24 14:10   ` Avi Kivity
2012-04-24 14:27     ` Takuya Yoshikawa
2012-04-24 14:11 ` [PATCH 0/4] KVM: x86 emulator: Split decoder into separate functions Avi Kivity
2012-04-24 14:41   ` Takuya Yoshikawa

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.