@@ -1612,7 +1612,8 @@ static int nested_svm_vmexit_real(struct vcpu_svm *svm, void *arg1,
1612
1612
/* Kill any pending exceptions */
1613
1613
if (svm -> vcpu .arch .exception .pending == true)
1614
1614
nsvm_printk ("WARNING: Pending Exception\n" );
1615
- svm -> vcpu .arch .exception .pending = false;
1615
+ kvm_clear_exception_queue (& svm -> vcpu );
1616
+ kvm_clear_interrupt_queue (& svm -> vcpu );
1616
1617
1617
1618
/* Restore selected save entries */
1618
1619
svm -> vmcb -> save .es = hsave -> save .es ;
@@ -1680,7 +1681,8 @@ static int nested_svm_vmrun(struct vcpu_svm *svm, void *arg1,
1680
1681
svm -> nested_vmcb = svm -> vmcb -> save .rax ;
1681
1682
1682
1683
/* Clear internal status */
1683
- svm -> vcpu .arch .exception .pending = false;
1684
+ kvm_clear_exception_queue (& svm -> vcpu );
1685
+ kvm_clear_interrupt_queue (& svm -> vcpu );
1684
1686
1685
1687
/* Save the old vmcb, so we don't need to pick what we save, but
1686
1688
can restore everything when a VMEXIT occurs */
@@ -2362,21 +2364,14 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
2362
2364
((/*control->int_vector >> 4*/ 0xf ) << V_INTR_PRIO_SHIFT );
2363
2365
}
2364
2366
2365
- static void svm_queue_irq (struct kvm_vcpu * vcpu , unsigned nr )
2366
- {
2367
- struct vcpu_svm * svm = to_svm (vcpu );
2368
-
2369
- svm -> vmcb -> control .event_inj = nr |
2370
- SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR ;
2371
- }
2372
-
2373
2367
static void svm_set_irq (struct kvm_vcpu * vcpu )
2374
2368
{
2375
2369
struct vcpu_svm * svm = to_svm (vcpu );
2376
2370
2377
- nested_svm_intr ( svm );
2371
+ BUG_ON (!( svm -> vcpu . arch . hflags & HF_GIF_MASK ) );
2378
2372
2379
- svm_queue_irq (vcpu , vcpu -> arch .interrupt .nr );
2373
+ svm -> vmcb -> control .event_inj = vcpu -> arch .interrupt .nr |
2374
+ SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR ;
2380
2375
}
2381
2376
2382
2377
static void update_cr8_intercept (struct kvm_vcpu * vcpu , int tpr , int irr )
@@ -2404,13 +2399,25 @@ static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)
2404
2399
struct vmcb * vmcb = svm -> vmcb ;
2405
2400
return (vmcb -> save .rflags & X86_EFLAGS_IF ) &&
2406
2401
!(vmcb -> control .int_state & SVM_INTERRUPT_SHADOW_MASK ) &&
2407
- (svm -> vcpu .arch .hflags & HF_GIF_MASK );
2402
+ (svm -> vcpu .arch .hflags & HF_GIF_MASK ) &&
2403
+ !is_nested (svm );
2408
2404
}
2409
2405
2410
2406
static void enable_irq_window (struct kvm_vcpu * vcpu )
2411
2407
{
2412
- svm_set_vintr (to_svm (vcpu ));
2413
- svm_inject_irq (to_svm (vcpu ), 0x0 );
2408
+ struct vcpu_svm * svm = to_svm (vcpu );
2409
+ nsvm_printk ("Trying to open IRQ window\n" );
2410
+
2411
+ nested_svm_intr (svm );
2412
+
2413
+ /* In case GIF=0 we can't rely on the CPU to tell us when
2414
+ * GIF becomes 1, because that's a separate STGI/VMRUN intercept.
2415
+ * The next time we get that intercept, this function will be
2416
+ * called again though and we'll get the vintr intercept. */
2417
+ if (svm -> vcpu .arch .hflags & HF_GIF_MASK ) {
2418
+ svm_set_vintr (svm );
2419
+ svm_inject_irq (svm , 0x0 );
2420
+ }
2414
2421
}
2415
2422
2416
2423
static void enable_nmi_window (struct kvm_vcpu * vcpu )
@@ -2489,6 +2496,8 @@ static void svm_complete_interrupts(struct vcpu_svm *svm)
2489
2496
case SVM_EXITINTINFO_TYPE_EXEPT :
2490
2497
/* In case of software exception do not reinject an exception
2491
2498
vector, but re-execute and instruction instead */
2499
+ if (is_nested (svm ))
2500
+ break ;
2492
2501
if (kvm_exception_is_soft (vector ))
2493
2502
break ;
2494
2503
if (exitintinfo & SVM_EXITINTINFO_VALID_ERR ) {
0 commit comments