diff mbox

[4/6] kvm, emulator: Add initial three-byte insns support

Message ID 1379861095-628-5-git-send-email-bp@alien8.de (mailing list archive)
State New, archived
Headers show

Commit Message

Borislav Petkov Sept. 22, 2013, 2:44 p.m. UTC
From: Borislav Petkov <bp@suse.de>

Add initial support for handling three-byte instructions in the
emulator.

Signed-off-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/kvm/emulate.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

Comments

Gleb Natapov Oct. 29, 2013, 9:50 a.m. UTC | #1
On Sun, Sep 22, 2013 at 04:44:53PM +0200, Borislav Petkov wrote:
> From: Borislav Petkov <bp@suse.de>
> 
> Add initial support for handling three-byte instructions in the
> emulator.
> 
> Signed-off-by: Borislav Petkov <bp@suse.de>
> ---
>  arch/x86/kvm/emulate.c | 30 ++++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
> 
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index 67277bcb377a..72093d76c769 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -3880,6 +3880,25 @@ static const struct opcode twobyte_table[256] = {
>  	N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N
>  };
>  
> +static const struct gprefix third_opcode_byte_0xf0 = {
> +	N, N, N, N
> +};
> +
> +static const struct gprefix third_opcode_byte_0xf1 = {
> +	N, N, N, N
> +};
There are two three opcode tables, so third_opcode_byte is ambiguous.
What about pfx_0f_38_f0 and pfx_0f_38_f1?
 
> +
> +/*
> + * Insns below are selected by the prefix which indexed by the third opcode
> + * byte.
> + */
> +static const struct opcode opcode_map_0f_38[256] = {
> +	/* 0x00 - 0x7f */
> +	X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N),
> +	/* 0x80 - 0xff */
> +	X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N)
> +};
> +
>  #undef D
>  #undef N
>  #undef G
> @@ -4200,6 +4219,13 @@ done_prefixes:
>  		ctxt->opcode_len = 2;
>  		ctxt->b = insn_fetch(u8, ctxt);
>  		opcode = twobyte_table[ctxt->b];
> +
> +		/* 0F_38 opcode map */
> +		if (ctxt->b == 0x38) {
> +			ctxt->opcode_len = 3;
> +			ctxt->b = insn_fetch(u8, ctxt);
> +			opcode = opcode_map_0f_38[ctxt->b];
> +		}
>  	}
>  	ctxt->d = opcode.flags;
>  
> @@ -4531,6 +4557,8 @@ special_insn:
>  
>  	if (ctxt->opcode_len == 2)
>  		goto twobyte_insn;
> +	else if (ctxt->opcode_len == 3)
> +		goto threebyte_insn;
>  
>  	switch (ctxt->b) {
>  	case 0x63:		/* movsxd */
> @@ -4715,6 +4743,8 @@ twobyte_insn:
>  		goto cannot_emulate;
>  	}
>  
> +threebyte_insn:
> +
>  	if (rc != X86EMUL_CONTINUE)
>  		goto done;
>  
> -- 
> 1.8.4

--
			Gleb.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Borislav Petkov Oct. 29, 2013, 10:04 a.m. UTC | #2
On Tue, Oct 29, 2013 at 11:50:43AM +0200, Gleb Natapov wrote:
> There are two three opcode tables, so third_opcode_byte is ambiguous.

Actually there's also 0F_3A and there are also other prefixes besides f0
and f1. Oh, and those tables are not completely full so I can imagine
more stuff coming in later....

I know what you're thinking by now, btw :-)

> What about pfx_0f_38_f0 and pfx_0f_38_f1?

Yeah, those make it much more explicit.

I wanted to keep the "three_byte" in the name in there somewhere,
though, so that it is clear that we're dealing with three byte opcodes
instead of requiring the onlooking innocent person to know the opcodes.

How about:

three_byte_0f_38_f0
three_byte_0f_38_f1
three_byte_0f_3a_50
...

Last one is an example only.

Btw, we might want to reconsider that whole tabular representation when
more stuff needs to be added...
Gleb Natapov Oct. 29, 2013, 10:11 a.m. UTC | #3
On Tue, Oct 29, 2013 at 11:04:57AM +0100, Borislav Petkov wrote:
> On Tue, Oct 29, 2013 at 11:50:43AM +0200, Gleb Natapov wrote:
> > There are two three opcode tables, so third_opcode_byte is ambiguous.
> 
> Actually there's also 0F_3A and there are also other prefixes besides f0
> and f1. Oh, and those tables are not completely full so I can imagine
> more stuff coming in later....
> 
> I know what you're thinking by now, btw :-)
> 
:)

> > What about pfx_0f_38_f0 and pfx_0f_38_f1?
> 
> Yeah, those make it much more explicit.
> 
> I wanted to keep the "three_byte" in the name in there somewhere,
> though, so that it is clear that we're dealing with three byte opcodes
> instead of requiring the onlooking innocent person to know the opcodes.
> 
> How about:
> 
> three_byte_0f_38_f0
> three_byte_0f_38_f1
> three_byte_0f_3a_50
> ...
> 
> Last one is an example only.
> 
Looks OK to me.

> Btw, we might want to reconsider that whole tabular representation when
> more stuff needs to be added...
> 
Of course. When tables will start to show their limitation we can always
change to something else.

--
			Gleb.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 67277bcb377a..72093d76c769 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3880,6 +3880,25 @@  static const struct opcode twobyte_table[256] = {
 	N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N
 };
 
+static const struct gprefix third_opcode_byte_0xf0 = {
+	N, N, N, N
+};
+
+static const struct gprefix third_opcode_byte_0xf1 = {
+	N, N, N, N
+};
+
+/*
+ * Insns below are selected by the prefix which indexed by the third opcode
+ * byte.
+ */
+static const struct opcode opcode_map_0f_38[256] = {
+	/* 0x00 - 0x7f */
+	X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N),
+	/* 0x80 - 0xff */
+	X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N)
+};
+
 #undef D
 #undef N
 #undef G
@@ -4200,6 +4219,13 @@  done_prefixes:
 		ctxt->opcode_len = 2;
 		ctxt->b = insn_fetch(u8, ctxt);
 		opcode = twobyte_table[ctxt->b];
+
+		/* 0F_38 opcode map */
+		if (ctxt->b == 0x38) {
+			ctxt->opcode_len = 3;
+			ctxt->b = insn_fetch(u8, ctxt);
+			opcode = opcode_map_0f_38[ctxt->b];
+		}
 	}
 	ctxt->d = opcode.flags;
 
@@ -4531,6 +4557,8 @@  special_insn:
 
 	if (ctxt->opcode_len == 2)
 		goto twobyte_insn;
+	else if (ctxt->opcode_len == 3)
+		goto threebyte_insn;
 
 	switch (ctxt->b) {
 	case 0x63:		/* movsxd */
@@ -4715,6 +4743,8 @@  twobyte_insn:
 		goto cannot_emulate;
 	}
 
+threebyte_insn:
+
 	if (rc != X86EMUL_CONTINUE)
 		goto done;