diff options
author | Borislav Petkov <bp@suse.de> | 2013-10-29 07:54:10 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-10-30 13:54:41 -0400 |
commit | 0bc5eedb82a54ccd9cbf79825226dd068427a94a (patch) | |
tree | 82462a3c8c6e7a6d865e3ca33d6ed8cfa7ec4aa8 /arch/x86 | |
parent | b51e974fcdabd00c8f5943ee7943c4ea788f57b6 (diff) |
kvm, emulator: Add initial three-byte insns support
Add initial support for handling three-byte instructions in the
emulator.
Signed-off-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/emulate.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 541801527225..6c5cfe962b28 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -3892,6 +3892,25 @@ static const struct opcode twobyte_table[256] = { | |||
3892 | N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N | 3892 | N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N |
3893 | }; | 3893 | }; |
3894 | 3894 | ||
3895 | static const struct gprefix three_byte_0f_38_f0 = { | ||
3896 | N, N, N, N | ||
3897 | }; | ||
3898 | |||
3899 | static const struct gprefix three_byte_0f_38_f1 = { | ||
3900 | N, N, N, N | ||
3901 | }; | ||
3902 | |||
3903 | /* | ||
3904 | * Insns below are selected by the prefix which indexed by the third opcode | ||
3905 | * byte. | ||
3906 | */ | ||
3907 | static const struct opcode opcode_map_0f_38[256] = { | ||
3908 | /* 0x00 - 0x7f */ | ||
3909 | X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), | ||
3910 | /* 0x80 - 0xff */ | ||
3911 | X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N) | ||
3912 | }; | ||
3913 | |||
3895 | #undef D | 3914 | #undef D |
3896 | #undef N | 3915 | #undef N |
3897 | #undef G | 3916 | #undef G |
@@ -4212,6 +4231,13 @@ done_prefixes: | |||
4212 | ctxt->opcode_len = 2; | 4231 | ctxt->opcode_len = 2; |
4213 | ctxt->b = insn_fetch(u8, ctxt); | 4232 | ctxt->b = insn_fetch(u8, ctxt); |
4214 | opcode = twobyte_table[ctxt->b]; | 4233 | opcode = twobyte_table[ctxt->b]; |
4234 | |||
4235 | /* 0F_38 opcode map */ | ||
4236 | if (ctxt->b == 0x38) { | ||
4237 | ctxt->opcode_len = 3; | ||
4238 | ctxt->b = insn_fetch(u8, ctxt); | ||
4239 | opcode = opcode_map_0f_38[ctxt->b]; | ||
4240 | } | ||
4215 | } | 4241 | } |
4216 | ctxt->d = opcode.flags; | 4242 | ctxt->d = opcode.flags; |
4217 | 4243 | ||
@@ -4543,6 +4569,8 @@ special_insn: | |||
4543 | 4569 | ||
4544 | if (ctxt->opcode_len == 2) | 4570 | if (ctxt->opcode_len == 2) |
4545 | goto twobyte_insn; | 4571 | goto twobyte_insn; |
4572 | else if (ctxt->opcode_len == 3) | ||
4573 | goto threebyte_insn; | ||
4546 | 4574 | ||
4547 | switch (ctxt->b) { | 4575 | switch (ctxt->b) { |
4548 | case 0x63: /* movsxd */ | 4576 | case 0x63: /* movsxd */ |
@@ -4727,6 +4755,8 @@ twobyte_insn: | |||
4727 | goto cannot_emulate; | 4755 | goto cannot_emulate; |
4728 | } | 4756 | } |
4729 | 4757 | ||
4758 | threebyte_insn: | ||
4759 | |||
4730 | if (rc != X86EMUL_CONTINUE) | 4760 | if (rc != X86EMUL_CONTINUE) |
4731 | goto done; | 4761 | goto done; |
4732 | 4762 | ||