Skip to content

Commit 846b5cf

Browse files
lifeixwenlingz
authored andcommitted
hv: vlapic: wrap APICv accept interrupt API
The APICv ops is decided once the APICv feature on the physical platform is detected. We will use apicv_advanced_ops if the physical platform support fully APICv feature; otherwise, we will use apicv_basic_ops. This patch only wrap the accept interrupt API for them. Tracked-On: #1842 Signed-off-by: Li, Fei1 <fei1.li@intel.com>
1 parent 7852719 commit 846b5cf

File tree

4 files changed

+75
-49
lines changed

4 files changed

+75
-49
lines changed

hypervisor/arch/x86/cpu_caps.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ static void detect_apicv_cap(void)
165165
}
166166

167167
cpu_caps.apicv_features = features;
168+
169+
vlapic_set_apicv_ops();
168170
}
169171

170172
static void detect_vmx_mmu_cap(void)

hypervisor/arch/x86/guest/vlapic.c

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ static inline void vlapic_dump_irr(__unused const struct acrn_vlapic *vlapic, __
8787
static inline void vlapic_dump_isr(__unused const struct acrn_vlapic *vlapic, __unused const char *msg) {}
8888
#endif
8989

90+
static const struct acrn_apicv_ops *apicv_ops;
91+
9092
static int32_t
9193
apicv_set_intr_ready(struct acrn_vlapic *vlapic, uint32_t vector);
9294

@@ -489,62 +491,63 @@ vlapic_reset_tmr(struct acrn_vlapic *vlapic)
489491
vcpu_reset_eoi_exit_bitmaps(vlapic->vcpu);
490492
}
491493

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)
498495
{
499496
struct lapic_regs *lapic;
500497
struct lapic_reg *irrptr;
501498
uint32_t idx;
502-
int32_t pending_intr;
503-
bool ret = true;
504-
505-
ASSERT(vector <= NR_MAX_VECTOR,
506-
"invalid vector %u", vector);
507499

508500
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];
514503

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 */
515507
vlapic_set_tmr(vlapic, vector, level);
508+
vcpu_make_request(vlapic->vcpu, ACRN_REQUEST_EVENT);
509+
}
510+
}
516511

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);
536515

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);
544533
}
545534
}
535+
}
546536

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+
}
548551
}
549552

550553
/**
@@ -947,9 +950,7 @@ vlapic_set_error(struct acrn_vlapic *vlapic, uint32_t mask)
947950
if ((lvt & APIC_LVT_M) == 0U) {
948951
vec = lvt & APIC_LVT_VECTOR;
949952
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);
953954
}
954955
}
955956
vlapic->esr_firing = 0;
@@ -1858,9 +1859,7 @@ vlapic_set_intr(struct acrn_vcpu *vcpu, uint32_t vector, bool level)
18581859
dev_dbg(ACRN_DBG_LAPIC,
18591860
"vlapic ignoring interrupt to vector %u", vector);
18601861
} 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);
18641863
}
18651864
}
18661865

@@ -2459,3 +2458,23 @@ int32_t tpr_below_threshold_vmexit_handler(struct acrn_vcpu *vcpu)
24592458

24602459
return 0;
24612460
}
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+
}

hypervisor/arch/x86/guest/vlapic_priv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,8 @@
8282
#define APIC_OFFSET_TIMER_DCR 0x3E0U /* Timer's Divide Configuration */
8383
#define APIC_OFFSET_SELF_IPI 0x3F0U /* Self IPI Register */
8484

85+
struct acrn_apicv_ops {
86+
void (*accept_intr)(struct acrn_vlapic *vlapic, uint32_t vector, bool level);
87+
};
88+
8589
#endif /* VLAPIC_PRIV_H */

hypervisor/include/arch/x86/guest/vlapic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct acrn_vlapic {
110110
uint32_t lvt_last[VLAPIC_MAXLVT_INDEX + 1];
111111
} __aligned(PAGE_SIZE);
112112

113+
void vlapic_set_apicv_ops(void);
113114

114115
/**
115116
* @brief virtual LAPIC

0 commit comments

Comments
 (0)