@@ -71,6 +71,8 @@ MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
71
71
#define SVM_FEATURE_DECODE_ASSIST (1 << 7)
72
72
#define SVM_FEATURE_PAUSE_FILTER (1 << 10)
73
73
74
+ #define SVM_AVIC_DOORBELL 0xc001011b
75
+
74
76
#define NESTED_EXIT_HOST 0 /* Exit handled on host level */
75
77
#define NESTED_EXIT_DONE 1 /* Exit caused nested vmexit */
76
78
#define NESTED_EXIT_CONTINUE 2 /* Further checks needed */
@@ -293,6 +295,17 @@ static inline void avic_update_vapic_bar(struct vcpu_svm *svm, u64 data)
293
295
mark_dirty (svm -> vmcb , VMCB_AVIC );
294
296
}
295
297
298
+ static inline bool avic_vcpu_is_running (struct kvm_vcpu * vcpu )
299
+ {
300
+ struct vcpu_svm * svm = to_svm (vcpu );
301
+ u64 * entry = svm -> avic_physical_id_cache ;
302
+
303
+ if (!entry )
304
+ return false;
305
+
306
+ return (READ_ONCE (* entry ) & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK );
307
+ }
308
+
296
309
static void recalc_intercepts (struct vcpu_svm * svm )
297
310
{
298
311
struct vmcb_control_area * c , * h ;
@@ -2866,10 +2879,11 @@ static int clgi_interception(struct vcpu_svm *svm)
2866
2879
disable_gif (svm );
2867
2880
2868
2881
/* After a CLGI no interrupts should come */
2869
- svm_clear_vintr (svm );
2870
- svm -> vmcb -> control .int_ctl &= ~V_IRQ_MASK ;
2871
-
2872
- mark_dirty (svm -> vmcb , VMCB_INTR );
2882
+ if (!kvm_vcpu_apicv_active (& svm -> vcpu )) {
2883
+ svm_clear_vintr (svm );
2884
+ svm -> vmcb -> control .int_ctl &= ~V_IRQ_MASK ;
2885
+ mark_dirty (svm -> vmcb , VMCB_INTR );
2886
+ }
2873
2887
2874
2888
return 1 ;
2875
2889
}
@@ -3763,6 +3777,7 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
3763
3777
{
3764
3778
struct vmcb_control_area * control ;
3765
3779
3780
+ /* The following fields are ignored when AVIC is enabled */
3766
3781
control = & svm -> vmcb -> control ;
3767
3782
control -> int_vector = irq ;
3768
3783
control -> int_ctl &= ~V_INTR_PRIO_MASK ;
@@ -3841,6 +3856,18 @@ static void svm_sync_pir_to_irr(struct kvm_vcpu *vcpu)
3841
3856
return ;
3842
3857
}
3843
3858
3859
+ static void svm_deliver_avic_intr (struct kvm_vcpu * vcpu , int vec )
3860
+ {
3861
+ kvm_lapic_set_irr (vec , vcpu -> arch .apic );
3862
+ smp_mb__after_atomic ();
3863
+
3864
+ if (avic_vcpu_is_running (vcpu ))
3865
+ wrmsrl (SVM_AVIC_DOORBELL ,
3866
+ __default_cpu_present_to_apicid (vcpu -> cpu ));
3867
+ else
3868
+ kvm_vcpu_wake_up (vcpu );
3869
+ }
3870
+
3844
3871
static int svm_nmi_allowed (struct kvm_vcpu * vcpu )
3845
3872
{
3846
3873
struct vcpu_svm * svm = to_svm (vcpu );
@@ -3895,6 +3922,9 @@ static void enable_irq_window(struct kvm_vcpu *vcpu)
3895
3922
{
3896
3923
struct vcpu_svm * svm = to_svm (vcpu );
3897
3924
3925
+ if (kvm_vcpu_apicv_active (vcpu ))
3926
+ return ;
3927
+
3898
3928
/*
3899
3929
* In case GIF=0 we can't rely on the CPU to tell us when GIF becomes
3900
3930
* 1, because that's a separate STGI/VMRUN intercept. The next time we
@@ -4638,6 +4668,7 @@ static struct kvm_x86_ops svm_x86_ops = {
4638
4668
.sched_in = svm_sched_in ,
4639
4669
4640
4670
.pmu_ops = & amd_pmu_ops ,
4671
+ .deliver_posted_interrupt = svm_deliver_avic_intr ,
4641
4672
};
4642
4673
4643
4674
static int __init svm_init (void )
0 commit comments