diff options
author | Avi Kivity <avi@redhat.com> | 2010-06-10 10:02:14 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 03:46:32 -0400 |
commit | 49a9b07edcf4aff159c1f3d3a27e58cf38bc27cd (patch) | |
tree | 750ff11b09e7baa3f4c811ce7c85bf7546b051ae /arch/x86/kvm/vmx.c | |
parent | 2acf923e38fb6a4ce0c57115decbb38d334902ac (diff) |
KVM: Fix mov cr0 #GP at wrong instruction
On Intel, we call skip_emulated_instruction() even if we injected a #GP,
resulting in the #GP pointing at the wrong address.
Fix by injecting the exception and skipping the instruction at the same place,
so we can do just one or the other.
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 864a1b6d155a..1baf4b2d98ee 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -3157,11 +3157,20 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall) | |||
3157 | hypercall[2] = 0xc1; | 3157 | hypercall[2] = 0xc1; |
3158 | } | 3158 | } |
3159 | 3159 | ||
3160 | static void complete_insn_gp(struct kvm_vcpu *vcpu, int err) | ||
3161 | { | ||
3162 | if (err) | ||
3163 | kvm_inject_gp(vcpu, 0); | ||
3164 | else | ||
3165 | skip_emulated_instruction(vcpu); | ||
3166 | } | ||
3167 | |||
3160 | static int handle_cr(struct kvm_vcpu *vcpu) | 3168 | static int handle_cr(struct kvm_vcpu *vcpu) |
3161 | { | 3169 | { |
3162 | unsigned long exit_qualification, val; | 3170 | unsigned long exit_qualification, val; |
3163 | int cr; | 3171 | int cr; |
3164 | int reg; | 3172 | int reg; |
3173 | int err; | ||
3165 | 3174 | ||
3166 | exit_qualification = vmcs_readl(EXIT_QUALIFICATION); | 3175 | exit_qualification = vmcs_readl(EXIT_QUALIFICATION); |
3167 | cr = exit_qualification & 15; | 3176 | cr = exit_qualification & 15; |
@@ -3172,8 +3181,8 @@ static int handle_cr(struct kvm_vcpu *vcpu) | |||
3172 | trace_kvm_cr_write(cr, val); | 3181 | trace_kvm_cr_write(cr, val); |
3173 | switch (cr) { | 3182 | switch (cr) { |
3174 | case 0: | 3183 | case 0: |
3175 | kvm_set_cr0(vcpu, val); | 3184 | err = kvm_set_cr0(vcpu, val); |
3176 | skip_emulated_instruction(vcpu); | 3185 | complete_insn_gp(vcpu, err); |
3177 | return 1; | 3186 | return 1; |
3178 | case 3: | 3187 | case 3: |
3179 | kvm_set_cr3(vcpu, val); | 3188 | kvm_set_cr3(vcpu, val); |