diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2008-09-26 03:30:49 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2008-12-31 09:51:40 -0500 |
commit | 33f089ca5a61f7aead26e8e1866dfc961dd88a9e (patch) | |
tree | 41b23c564a9459bbc81e426503e0dc103cf7f45a /arch/x86/kvm/vmx.c | |
parent | 448fa4a9c5dbc6941dd19ed09692c588d815bb06 (diff) |
KVM: VMX: refactor/fix IRQ and NMI injectability determination
There are currently two ways in VMX to check if an IRQ or NMI can be
injected:
- vmx_{nmi|irq}_enabled and
- vcpu.arch.{nmi|interrupt}_window_open.
Even worse, one test (at the end of vmx_vcpu_run) uses an inconsistent,
likely incorrect logic.
This patch consolidates and unifies the tests over
{nmi|interrupt}_window_open as cache + vmx_update_window_states
for updating the cache content.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 46 |
1 files changed, 21 insertions, 25 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 8d0fc68fd4ec..f0866e1d20ee 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -2362,6 +2362,21 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu) | |||
2362 | INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR); | 2362 | INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR); |
2363 | } | 2363 | } |
2364 | 2364 | ||
2365 | static void vmx_update_window_states(struct kvm_vcpu *vcpu) | ||
2366 | { | ||
2367 | u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO); | ||
2368 | |||
2369 | vcpu->arch.nmi_window_open = | ||
2370 | !(guest_intr & (GUEST_INTR_STATE_STI | | ||
2371 | GUEST_INTR_STATE_MOV_SS | | ||
2372 | GUEST_INTR_STATE_NMI)); | ||
2373 | |||
2374 | vcpu->arch.interrupt_window_open = | ||
2375 | ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) && | ||
2376 | !(guest_intr & (GUEST_INTR_STATE_STI | | ||
2377 | GUEST_INTR_STATE_MOV_SS))); | ||
2378 | } | ||
2379 | |||
2365 | static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) | 2380 | static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) |
2366 | { | 2381 | { |
2367 | int word_index = __ffs(vcpu->arch.irq_summary); | 2382 | int word_index = __ffs(vcpu->arch.irq_summary); |
@@ -2374,15 +2389,12 @@ static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) | |||
2374 | kvm_queue_interrupt(vcpu, irq); | 2389 | kvm_queue_interrupt(vcpu, irq); |
2375 | } | 2390 | } |
2376 | 2391 | ||
2377 | |||
2378 | static void do_interrupt_requests(struct kvm_vcpu *vcpu, | 2392 | static void do_interrupt_requests(struct kvm_vcpu *vcpu, |
2379 | struct kvm_run *kvm_run) | 2393 | struct kvm_run *kvm_run) |
2380 | { | 2394 | { |
2381 | u32 cpu_based_vm_exec_control; | 2395 | u32 cpu_based_vm_exec_control; |
2382 | 2396 | ||
2383 | vcpu->arch.interrupt_window_open = | 2397 | vmx_update_window_states(vcpu); |
2384 | ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) && | ||
2385 | (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0); | ||
2386 | 2398 | ||
2387 | if (vcpu->arch.interrupt_window_open && | 2399 | if (vcpu->arch.interrupt_window_open && |
2388 | vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending) | 2400 | vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending) |
@@ -3075,22 +3087,6 @@ static void enable_nmi_window(struct kvm_vcpu *vcpu) | |||
3075 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); | 3087 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); |
3076 | } | 3088 | } |
3077 | 3089 | ||
3078 | static int vmx_nmi_enabled(struct kvm_vcpu *vcpu) | ||
3079 | { | ||
3080 | u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO); | ||
3081 | return !(guest_intr & (GUEST_INTR_STATE_NMI | | ||
3082 | GUEST_INTR_STATE_MOV_SS | | ||
3083 | GUEST_INTR_STATE_STI)); | ||
3084 | } | ||
3085 | |||
3086 | static int vmx_irq_enabled(struct kvm_vcpu *vcpu) | ||
3087 | { | ||
3088 | u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO); | ||
3089 | return (!(guest_intr & (GUEST_INTR_STATE_MOV_SS | | ||
3090 | GUEST_INTR_STATE_STI)) && | ||
3091 | (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF)); | ||
3092 | } | ||
3093 | |||
3094 | static void enable_intr_window(struct kvm_vcpu *vcpu) | 3090 | static void enable_intr_window(struct kvm_vcpu *vcpu) |
3095 | { | 3091 | { |
3096 | if (vcpu->arch.nmi_pending) | 3092 | if (vcpu->arch.nmi_pending) |
@@ -3159,11 +3155,13 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu) | |||
3159 | { | 3155 | { |
3160 | update_tpr_threshold(vcpu); | 3156 | update_tpr_threshold(vcpu); |
3161 | 3157 | ||
3158 | vmx_update_window_states(vcpu); | ||
3159 | |||
3162 | if (cpu_has_virtual_nmis()) { | 3160 | if (cpu_has_virtual_nmis()) { |
3163 | if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) { | 3161 | if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) { |
3164 | if (vcpu->arch.interrupt.pending) { | 3162 | if (vcpu->arch.interrupt.pending) { |
3165 | enable_nmi_window(vcpu); | 3163 | enable_nmi_window(vcpu); |
3166 | } else if (vmx_nmi_enabled(vcpu)) { | 3164 | } else if (vcpu->arch.nmi_window_open) { |
3167 | vcpu->arch.nmi_pending = false; | 3165 | vcpu->arch.nmi_pending = false; |
3168 | vcpu->arch.nmi_injected = true; | 3166 | vcpu->arch.nmi_injected = true; |
3169 | } else { | 3167 | } else { |
@@ -3178,7 +3176,7 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu) | |||
3178 | } | 3176 | } |
3179 | } | 3177 | } |
3180 | if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) { | 3178 | if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) { |
3181 | if (vmx_irq_enabled(vcpu)) | 3179 | if (vcpu->arch.interrupt_window_open) |
3182 | kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu)); | 3180 | kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu)); |
3183 | else | 3181 | else |
3184 | enable_irq_window(vcpu); | 3182 | enable_irq_window(vcpu); |
@@ -3339,9 +3337,7 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
3339 | if (vmx->rmode.irq.pending) | 3337 | if (vmx->rmode.irq.pending) |
3340 | fixup_rmode_irq(vmx); | 3338 | fixup_rmode_irq(vmx); |
3341 | 3339 | ||
3342 | vcpu->arch.interrupt_window_open = | 3340 | vmx_update_window_states(vcpu); |
3343 | (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & | ||
3344 | (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS)) == 0; | ||
3345 | 3341 | ||
3346 | asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS)); | 3342 | asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS)); |
3347 | vmx->launched = 1; | 3343 | vmx->launched = 1; |