diff options
author | Avi Kivity <avi@redhat.com> | 2008-12-23 12:46:01 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-03-24 05:02:51 -0400 |
commit | 2b3d2a206037b1471de6a6dc51427af034cfdb47 (patch) | |
tree | e90379964dff6ff8d578b7f8401dfb3b05ff6111 /arch | |
parent | e2078318042569682d0496cfd7bd962a766e82b1 (diff) |
KVM: Fix vmload and friends misinterpreted as lidt
The AMD SVM instruction family all overload the 0f 01 /3 opcode, further
multiplexing on the three r/m bits. But the code decided that anything that
isn't a vmmcall must be an lidt (which shares the 0f 01 /3 opcode, for the
case that mod = 3).
Fix by aborting emulation if this isn't a vmmcall.
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/x86_emulate.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index d174db7a3370..54fb09889a80 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c | |||
@@ -1908,11 +1908,16 @@ twobyte_insn: | |||
1908 | c->dst.type = OP_NONE; | 1908 | c->dst.type = OP_NONE; |
1909 | break; | 1909 | break; |
1910 | case 3: /* lidt/vmmcall */ | 1910 | case 3: /* lidt/vmmcall */ |
1911 | if (c->modrm_mod == 3 && c->modrm_rm == 1) { | 1911 | if (c->modrm_mod == 3) { |
1912 | rc = kvm_fix_hypercall(ctxt->vcpu); | 1912 | switch (c->modrm_rm) { |
1913 | if (rc) | 1913 | case 1: |
1914 | goto done; | 1914 | rc = kvm_fix_hypercall(ctxt->vcpu); |
1915 | kvm_emulate_hypercall(ctxt->vcpu); | 1915 | if (rc) |
1916 | goto done; | ||
1917 | break; | ||
1918 | default: | ||
1919 | goto cannot_emulate; | ||
1920 | } | ||
1916 | } else { | 1921 | } else { |
1917 | rc = read_descriptor(ctxt, ops, c->src.ptr, | 1922 | rc = read_descriptor(ctxt, ops, c->src.ptr, |
1918 | &size, &address, | 1923 | &size, &address, |