aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-04-21 10:45:08 -0400
committerAvi Kivity <avi@redhat.com>2009-06-10 04:48:48 -0400
commit95ba82731374eb1c2af4dd442526c4b314f0e8b6 (patch)
treea8b8e23285686761694ee214c6de85e83f52652b /arch/x86/kvm/x86.c
parentc4282df98ae0993983924c00ed76428a6609d68b (diff)
KVM: SVM: Add NMI injection support
Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c71
1 files changed, 69 insertions, 2 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0890df9e88ff..96e995c1dd76 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3114,6 +3114,68 @@ static void vapic_exit(struct kvm_vcpu *vcpu)
3114 up_read(&vcpu->kvm->slots_lock); 3114 up_read(&vcpu->kvm->slots_lock);
3115} 3115}
3116 3116
3117static void update_cr8_intercept(struct kvm_vcpu *vcpu)
3118{
3119 int max_irr, tpr;
3120
3121 if (!kvm_x86_ops->update_cr8_intercept)
3122 return;
3123
3124 max_irr = kvm_lapic_find_highest_irr(vcpu);
3125
3126 if (max_irr != -1)
3127 max_irr >>= 4;
3128
3129 tpr = kvm_lapic_get_cr8(vcpu);
3130
3131 kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr);
3132}
3133
3134static void inject_irq(struct kvm_vcpu *vcpu)
3135{
3136 /* try to reinject previous events if any */
3137 if (vcpu->arch.nmi_injected) {
3138 kvm_x86_ops->set_nmi(vcpu);
3139 return;
3140 }
3141
3142 if (vcpu->arch.interrupt.pending) {
3143 kvm_x86_ops->set_irq(vcpu, vcpu->arch.interrupt.nr);
3144 return;
3145 }
3146
3147 /* try to inject new event if pending */
3148 if (vcpu->arch.nmi_pending) {
3149 if (kvm_x86_ops->nmi_allowed(vcpu)) {
3150 vcpu->arch.nmi_pending = false;
3151 vcpu->arch.nmi_injected = true;
3152 kvm_x86_ops->set_nmi(vcpu);
3153 }
3154 } else if (kvm_cpu_has_interrupt(vcpu)) {
3155 if (kvm_x86_ops->interrupt_allowed(vcpu)) {
3156 kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
3157 kvm_x86_ops->set_irq(vcpu, vcpu->arch.interrupt.nr);
3158 }
3159 }
3160}
3161
3162static void inject_pending_irq(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3163{
3164 bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
3165 kvm_run->request_interrupt_window;
3166
3167 if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
3168 kvm_x86_ops->drop_interrupt_shadow(vcpu);
3169
3170 inject_irq(vcpu);
3171
3172 /* enable NMI/IRQ window open exits if needed */
3173 if (vcpu->arch.nmi_pending)
3174 kvm_x86_ops->enable_nmi_window(vcpu);
3175 else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
3176 kvm_x86_ops->enable_irq_window(vcpu);
3177}
3178
3117static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 3179static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3118{ 3180{
3119 int r; 3181 int r;
@@ -3172,9 +3234,14 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3172 if (vcpu->arch.exception.pending) 3234 if (vcpu->arch.exception.pending)
3173 __queue_exception(vcpu); 3235 __queue_exception(vcpu);
3174 else 3236 else
3175 kvm_x86_ops->inject_pending_irq(vcpu, kvm_run); 3237 inject_pending_irq(vcpu, kvm_run);
3176 3238
3177 kvm_lapic_sync_to_vapic(vcpu); 3239 if (kvm_lapic_enabled(vcpu)) {
3240 if (!vcpu->arch.apic->vapic_addr)
3241 update_cr8_intercept(vcpu);
3242 else
3243 kvm_lapic_sync_to_vapic(vcpu);
3244 }
3178 3245
3179 up_read(&vcpu->kvm->slots_lock); 3246 up_read(&vcpu->kvm->slots_lock);
3180 3247