diff options
author | Guillaume Thouvenin <guillaume.thouvenin@ext.bull.net> | 2008-10-29 04:39:42 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2008-12-31 09:51:48 -0500 |
commit | 1d5a4d9b92028d9fe77da34037bd5a1ebfecc733 (patch) | |
tree | 5e8725c9af5b206f49936a327f116eec858b6bd9 /arch/x86/kvm | |
parent | e93f36bcfaa9e899c595e1c446c784a69021854a (diff) |
KVM: VMX: Handle mmio emulation when guest state is invalid
If emulate_invalid_guest_state is enabled, the emulator is called
when guest state is invalid. Until now, we reported an mmio failure
when emulate_instruction() returned EMULATE_DO_MMIO. This patch adds
the case where emulate_instruction() failed and an MMIO emulation
is needed.
Signed-off-by: Guillaume Thouvenin <guillaume.thouvenin@ext.bull.net>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/vmx.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 816d23185fb8..427dbc14fae9 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -3052,16 +3052,12 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu, | |||
3052 | while (!guest_state_valid(vcpu)) { | 3052 | while (!guest_state_valid(vcpu)) { |
3053 | err = emulate_instruction(vcpu, kvm_run, 0, 0, 0); | 3053 | err = emulate_instruction(vcpu, kvm_run, 0, 0, 0); |
3054 | 3054 | ||
3055 | switch (err) { | 3055 | if (err == EMULATE_DO_MMIO) |
3056 | case EMULATE_DONE: | 3056 | break; |
3057 | break; | 3057 | |
3058 | case EMULATE_DO_MMIO: | 3058 | if (err != EMULATE_DONE) { |
3059 | kvm_report_emulation_failure(vcpu, "mmio"); | 3059 | kvm_report_emulation_failure(vcpu, "emulation failure"); |
3060 | /* TODO: Handle MMIO */ | 3060 | return; |
3061 | return; | ||
3062 | default: | ||
3063 | kvm_report_emulation_failure(vcpu, "emulation failure"); | ||
3064 | return; | ||
3065 | } | 3061 | } |
3066 | 3062 | ||
3067 | if (signal_pending(current)) | 3063 | if (signal_pending(current)) |
@@ -3073,8 +3069,10 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu, | |||
3073 | local_irq_disable(); | 3069 | local_irq_disable(); |
3074 | preempt_disable(); | 3070 | preempt_disable(); |
3075 | 3071 | ||
3076 | /* Guest state should be valid now, no more emulation should be needed */ | 3072 | /* Guest state should be valid now except if we need to |
3077 | vmx->emulation_required = 0; | 3073 | * emulate an MMIO */ |
3074 | if (guest_state_valid(vcpu)) | ||
3075 | vmx->emulation_required = 0; | ||
3078 | } | 3076 | } |
3079 | 3077 | ||
3080 | /* | 3078 | /* |
@@ -3121,6 +3119,11 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
3121 | KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)kvm_rip_read(vcpu), | 3119 | KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)kvm_rip_read(vcpu), |
3122 | (u32)((u64)kvm_rip_read(vcpu) >> 32), entryexit); | 3120 | (u32)((u64)kvm_rip_read(vcpu) >> 32), entryexit); |
3123 | 3121 | ||
3122 | /* If we need to emulate an MMIO from handle_invalid_guest_state | ||
3123 | * we just return 0 */ | ||
3124 | if (vmx->emulation_required && emulate_invalid_guest_state) | ||
3125 | return 0; | ||
3126 | |||
3124 | /* Access CR3 don't cause VMExit in paging mode, so we need | 3127 | /* Access CR3 don't cause VMExit in paging mode, so we need |
3125 | * to sync with guest real CR3. */ | 3128 | * to sync with guest real CR3. */ |
3126 | if (vm_need_ept() && is_paging(vcpu)) { | 3129 | if (vm_need_ept() && is_paging(vcpu)) { |