aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2008-09-26 03:30:49 -0400
committerAvi Kivity <avi@redhat.com>2008-12-31 09:51:40 -0500
commit33f089ca5a61f7aead26e8e1866dfc961dd88a9e (patch)
tree41b23c564a9459bbc81e426503e0dc103cf7f45a /arch/x86/kvm/vmx.c
parent448fa4a9c5dbc6941dd19ed09692c588d815bb06 (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.c46
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
2365static 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
2365static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) 2380static 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
2378static void do_interrupt_requests(struct kvm_vcpu *vcpu, 2392static 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
3078static 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
3086static 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
3094static void enable_intr_window(struct kvm_vcpu *vcpu) 3090static 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;