diff options
author | Andre Przywara <andre.przywara@amd.com> | 2009-06-17 09:50:31 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-09-10 01:32:59 -0400 |
commit | 0cb5762ed2b3113b3b8aa84d1d26b815aea71787 (patch) | |
tree | 72fa0759911a0433bb5cc9f238bc0226bd9748b6 /arch/x86/kvm/x86.c | |
parent | 229456fc34b1c9031b04f7581e7b755d1cebfe9c (diff) |
KVM: Allow emulation of syscalls instructions on #UD
Add the opcodes for syscall, sysenter and sysexit to the list of instructions
handled by the undefined opcode handler.
Signed-off-by: Christoph Egger <christoph.egger@amd.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Andre Przywara <andre.przywara@amd.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 892a7a60c815..57e76b37242f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -2667,14 +2667,33 @@ int emulate_instruction(struct kvm_vcpu *vcpu, | |||
2667 | 2667 | ||
2668 | r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); | 2668 | r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); |
2669 | 2669 | ||
2670 | /* Reject the instructions other than VMCALL/VMMCALL when | 2670 | /* Only allow emulation of specific instructions on #UD |
2671 | * try to emulate invalid opcode */ | 2671 | * (namely VMMCALL, sysenter, sysexit, syscall)*/ |
2672 | c = &vcpu->arch.emulate_ctxt.decode; | 2672 | c = &vcpu->arch.emulate_ctxt.decode; |
2673 | if ((emulation_type & EMULTYPE_TRAP_UD) && | 2673 | if (emulation_type & EMULTYPE_TRAP_UD) { |
2674 | (!(c->twobyte && c->b == 0x01 && | 2674 | if (!c->twobyte) |
2675 | (c->modrm_reg == 0 || c->modrm_reg == 3) && | 2675 | return EMULATE_FAIL; |
2676 | c->modrm_mod == 3 && c->modrm_rm == 1))) | 2676 | switch (c->b) { |
2677 | return EMULATE_FAIL; | 2677 | case 0x01: /* VMMCALL */ |
2678 | if (c->modrm_mod != 3 || c->modrm_rm != 1) | ||
2679 | return EMULATE_FAIL; | ||
2680 | break; | ||
2681 | case 0x34: /* sysenter */ | ||
2682 | case 0x35: /* sysexit */ | ||
2683 | if (c->modrm_mod != 0 || c->modrm_rm != 0) | ||
2684 | return EMULATE_FAIL; | ||
2685 | break; | ||
2686 | case 0x05: /* syscall */ | ||
2687 | if (c->modrm_mod != 0 || c->modrm_rm != 0) | ||
2688 | return EMULATE_FAIL; | ||
2689 | break; | ||
2690 | default: | ||
2691 | return EMULATE_FAIL; | ||
2692 | } | ||
2693 | |||
2694 | if (!(c->modrm_reg == 0 || c->modrm_reg == 3)) | ||
2695 | return EMULATE_FAIL; | ||
2696 | } | ||
2678 | 2697 | ||
2679 | ++vcpu->stat.insn_emulation; | 2698 | ++vcpu->stat.insn_emulation; |
2680 | if (r) { | 2699 | if (r) { |