@@ -87,6 +87,8 @@ static inline void vlapic_dump_irr(__unused const struct acrn_vlapic *vlapic, __
87
87
static inline void vlapic_dump_isr (__unused const struct acrn_vlapic * vlapic , __unused const char * msg ) {}
88
88
#endif
89
89
90
+ static const struct acrn_apicv_ops * apicv_ops ;
91
+
90
92
static int32_t
91
93
apicv_set_intr_ready (struct acrn_vlapic * vlapic , uint32_t vector );
92
94
@@ -489,62 +491,63 @@ vlapic_reset_tmr(struct acrn_vlapic *vlapic)
489
491
vcpu_reset_eoi_exit_bitmaps (vlapic -> vcpu );
490
492
}
491
493
492
- /*
493
- * Returns 1 if the vcpu needs to be notified of the interrupt and 0 otherwise.
494
- * @pre vector >= 16
495
- */
496
- static bool
497
- vlapic_accept_intr (struct acrn_vlapic * vlapic , uint32_t vector , bool level )
494
+ static void apicv_basic_accept_intr (struct acrn_vlapic * vlapic , uint32_t vector , bool level )
498
495
{
499
496
struct lapic_regs * lapic ;
500
497
struct lapic_reg * irrptr ;
501
498
uint32_t idx ;
502
- int32_t pending_intr ;
503
- bool ret = true;
504
-
505
- ASSERT (vector <= NR_MAX_VECTOR ,
506
- "invalid vector %u" , vector );
507
499
508
500
lapic = & (vlapic -> apic_page );
509
- if ((lapic -> svr .v & APIC_SVR_ENABLE ) == 0U ) {
510
- dev_dbg (ACRN_DBG_LAPIC , "vlapic is software disabled, ignoring interrupt %u" , vector );
511
- ret = false;
512
- } else if (is_apicv_advanced_feature_supported ()) {
513
- pending_intr = apicv_set_intr_ready (vlapic , vector );
501
+ idx = vector >> 5U ;
502
+ irrptr = & lapic -> irr [0 ];
514
503
504
+ /* If the interrupt is set, don't try to do it again */
505
+ if (!bitmap32_test_and_set_lock ((uint16_t )(vector & 0x1fU ), & irrptr [idx ].v )) {
506
+ /* set tmr if corresponding irr bit changes from 0 to 1 */
515
507
vlapic_set_tmr (vlapic , vector , level );
508
+ vcpu_make_request (vlapic -> vcpu , ACRN_REQUEST_EVENT );
509
+ }
510
+ }
516
511
517
- if ((pending_intr != 0 ) && (get_cpu_id () != vlapic -> vcpu -> pcpu_id )) {
518
- /*
519
- * Send interrupt to vCPU via posted interrupt way:
520
- * 1. If target vCPU is in non-root mode(running),
521
- * send PI notification to vCPU and hardware will
522
- * sync PIR to vIRR automatically.
523
- * 2. If target vCPU is in root mode(isn't running),
524
- * record this request as ACRN_REQUEST_EVENT,then
525
- * will pick up the interrupt from PIR and inject
526
- * it to vCPU in next vmentry.
527
- */
528
- bitmap_set_lock (ACRN_REQUEST_EVENT , & vlapic -> vcpu -> arch .pending_req );
529
- apicv_post_intr (vlapic -> vcpu -> pcpu_id );
530
- ret = false;
531
- } else {
532
- ret = (pending_intr != 0 );
533
- }
534
- } else {
535
- idx = vector >> 5U ;
512
+ static void apicv_advanced_accept_intr (struct acrn_vlapic * vlapic , uint32_t vector , bool level )
513
+ {
514
+ int32_t pending_intr = apicv_set_intr_ready (vlapic , vector );
536
515
537
- irrptr = & lapic -> irr [0 ];
538
- /* If the interrupt is set, don't try to do it again */
539
- if (bitmap32_test_and_set_lock ((uint16_t )(vector & 0x1fU ), & irrptr [idx ].v )) {
540
- ret = false;
541
- } else {
542
- /* set tmr if corresponding irr bit changes from 0 to 1 */
543
- vlapic_set_tmr (vlapic , vector , level );
516
+ vlapic_set_tmr (vlapic , vector , level );
517
+
518
+ if (pending_intr != 0 ) {
519
+ /*
520
+ * Send interrupt to vCPU via posted interrupt way:
521
+ * 1. If target vCPU is in root mode(isn't running),
522
+ * record this request as ACRN_REQUEST_EVENT,then
523
+ * will pick up the interrupt from PIR and inject
524
+ * it to vCPU in next vmentry.
525
+ * 2. If target vCPU is in non-root mode(running),
526
+ * send PI notification to vCPU and hardware will
527
+ * sync PIR to vIRR automatically.
528
+ */
529
+ bitmap_set_lock (ACRN_REQUEST_EVENT , & vlapic -> vcpu -> arch .pending_req );
530
+
531
+ if (get_cpu_id () != vlapic -> vcpu -> pcpu_id ) {
532
+ apicv_post_intr (vlapic -> vcpu -> pcpu_id );
544
533
}
545
534
}
535
+ }
546
536
547
- return ret ;
537
+ /*
538
+ * @pre vector >= 16
539
+ */
540
+ static void vlapic_accept_intr (struct acrn_vlapic * vlapic , uint32_t vector , bool level )
541
+ {
542
+ struct lapic_regs * lapic ;
543
+ ASSERT (vector <= NR_MAX_VECTOR , "invalid vector %u" , vector );
544
+
545
+ lapic = & (vlapic -> apic_page );
546
+ if ((lapic -> svr .v & APIC_SVR_ENABLE ) == 0U ) {
547
+ dev_dbg (ACRN_DBG_LAPIC , "vlapic is software disabled, ignoring interrupt %u" , vector );
548
+ } else {
549
+ apicv_ops -> accept_intr (vlapic , vector , level );
550
+ }
548
551
}
549
552
550
553
/**
@@ -947,9 +950,7 @@ vlapic_set_error(struct acrn_vlapic *vlapic, uint32_t mask)
947
950
if ((lvt & APIC_LVT_M ) == 0U ) {
948
951
vec = lvt & APIC_LVT_VECTOR ;
949
952
if (vec >= 16U ) {
950
- if (vlapic_accept_intr (vlapic , vec , LAPIC_TRIG_EDGE )) {
951
- vcpu_make_request (vlapic -> vcpu , ACRN_REQUEST_EVENT );
952
- }
953
+ vlapic_accept_intr (vlapic , vec , LAPIC_TRIG_EDGE );
953
954
}
954
955
}
955
956
vlapic -> esr_firing = 0 ;
@@ -1858,9 +1859,7 @@ vlapic_set_intr(struct acrn_vcpu *vcpu, uint32_t vector, bool level)
1858
1859
dev_dbg (ACRN_DBG_LAPIC ,
1859
1860
"vlapic ignoring interrupt to vector %u" , vector );
1860
1861
} else {
1861
- if (vlapic_accept_intr (vlapic , vector , level )) {
1862
- vcpu_make_request (vcpu , ACRN_REQUEST_EVENT );
1863
- }
1862
+ vlapic_accept_intr (vlapic , vector , level );
1864
1863
}
1865
1864
}
1866
1865
@@ -2459,3 +2458,23 @@ int32_t tpr_below_threshold_vmexit_handler(struct acrn_vcpu *vcpu)
2459
2458
2460
2459
return 0 ;
2461
2460
}
2461
+
2462
+ static const struct acrn_apicv_ops apicv_basic_ops = {
2463
+ .accept_intr = apicv_basic_accept_intr ,
2464
+ };
2465
+
2466
+ static const struct acrn_apicv_ops apicv_advanced_ops = {
2467
+ .accept_intr = apicv_advanced_accept_intr ,
2468
+ };
2469
+
2470
+ /*
2471
+ * set apicv ops for apicv basic mode or apicv advenced mode.
2472
+ */
2473
+ void vlapic_set_apicv_ops (void )
2474
+ {
2475
+ if (is_apicv_advanced_feature_supported ()) {
2476
+ apicv_ops = & apicv_advanced_ops ;
2477
+ } else {
2478
+ apicv_ops = & apicv_basic_ops ;
2479
+ }
2480
+ }
0 commit comments