Skip to content

Commit fc61536

Browse files
lyan3wenlingz
authored andcommitted
hv: rework EOI_EXIT_BITMAP update logic
This commit changes the EOI_EXIT_BITMAP as follows: - add a eoi_exit_bitmap to vlapic structure; - go through all the RTEs and set eoi_exit_bitmap in the vlapic structure when related RTE fields are modified; - add ACRN_REQUEST_EOI_EXIT_UPDATE, if eoi_exit_bitmap changed, request the corresponding vcpu to write the bitmap to VMCS. Tracked-On: #2343 Signed-off-by: Yan, Like <like.yan@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent f15cc7d commit fc61536

File tree

5 files changed

+150
-10
lines changed

5 files changed

+150
-10
lines changed

hypervisor/arch/x86/guest/vcpu.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,49 @@ void vcpu_set_guest_msr(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t val)
166166
}
167167
}
168168

169+
/*
170+
* Write the eoi_exit_bitmaps to VMCS fields
171+
*/
172+
void vcpu_set_vmcs_eoi_exit(struct acrn_vcpu *vcpu)
173+
{
174+
pr_dbg("%s", __func__);
175+
176+
spinlock_obtain(&(vcpu->arch.lock));
177+
if (is_apicv_intr_delivery_supported()) {
178+
exec_vmwrite64(VMX_EOI_EXIT0_FULL, vcpu->arch.eoi_exit_bitmap[0]);
179+
exec_vmwrite64(VMX_EOI_EXIT1_FULL, vcpu->arch.eoi_exit_bitmap[1]);
180+
exec_vmwrite64(VMX_EOI_EXIT2_FULL, vcpu->arch.eoi_exit_bitmap[2]);
181+
exec_vmwrite64(VMX_EOI_EXIT3_FULL, vcpu->arch.eoi_exit_bitmap[3]);
182+
}
183+
spinlock_release(&(vcpu->arch.lock));
184+
}
185+
186+
/*
187+
* Set the eoi_exit_bitmap bit for specific vector
188+
* called with vcpu->arch.lock held
189+
* @pre vcpu != NULL && vector <= 255U
190+
*/
191+
void vcpu_set_eoi_exit(struct acrn_vcpu *vcpu, uint32_t vector)
192+
{
193+
pr_dbg("%s", __func__);
194+
195+
if (bitmap_test_and_set_nolock((uint16_t)(vector & 0x3fU),
196+
&(vcpu->arch.eoi_exit_bitmap[vector >> 6U]))) {
197+
pr_warn("Duplicated vector %u vcpu%u", vector, vcpu->vcpu_id);
198+
}
199+
}
200+
201+
/*
202+
* Reset all eoi_exit_bitmaps
203+
* called with vcpu->arch.lock held
204+
*/
205+
void vcpu_reset_eoi_exit_all(struct acrn_vcpu *vcpu)
206+
{
207+
pr_dbg("%s", __func__);
208+
209+
memset((void *)(vcpu->arch.eoi_exit_bitmap), 0U, sizeof(vcpu->arch.eoi_exit_bitmap));
210+
}
211+
169212
struct acrn_vcpu *get_ever_run_vcpu(uint16_t pcpu_id)
170213
{
171214
return per_cpu(ever_run_vcpu, pcpu_id);
@@ -379,6 +422,8 @@ int32_t create_vcpu(uint16_t pcpu_id, struct acrn_vm *vm, struct acrn_vcpu **rtn
379422
init_vmtrr(vcpu);
380423
#endif
381424

425+
spinlock_init(&(vcpu->arch.lock));
426+
382427
/* Populate the return handle */
383428
*rtn_vcpu_handle = vcpu;
384429

hypervisor/arch/x86/virq.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,10 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
409409
vioapic_update_tmr(vcpu);
410410
}
411411

412+
if (bitmap_test_and_clear_lock(ACRN_REQUEST_EOI_EXIT_UPDATE, pending_req_bits)) {
413+
vcpu_set_vmcs_eoi_exit(vcpu);
414+
}
415+
412416
/* handling cancelled event injection when vcpu is switched out */
413417
if (arch->inject_event_pending) {
414418
if ((arch->inject_info.intr_info & (EXCEPTION_ERROR_CODE_VALID << 8U)) != 0U) {

hypervisor/dm/vioapic.c

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include <hypervisor.h>
3434

3535
#define RTBL_RO_BITS (uint32_t)(IOAPIC_RTE_REM_IRR | IOAPIC_RTE_DELIVS)
36-
#define NEED_TMR_UPDATE (IOAPIC_RTE_TRGRMOD | IOAPIC_RTE_DELMOD | IOAPIC_RTE_INTVEC)
36+
#define NEED_EOI_EXIT_UPDATE (IOAPIC_RTE_TRGRMOD | IOAPIC_RTE_DELMOD | IOAPIC_RTE_DEST_MASK | IOAPIC_RTE_INTVEC)
3737

3838
#define ACRN_DBG_IOAPIC 6U
3939
#define ACRN_IOAPIC_VERSION 0x11U
@@ -171,6 +171,66 @@ vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t irqline, uint32_t op
171171
spinlock_release(&(vioapic->mtx));
172172
}
173173

174+
/*
175+
* Generate eoi_exit_bitmap and request each VCPU to update VMCS fields
176+
* To be called with vioapic->mtx
177+
* @pre vioapic != NULL
178+
*/
179+
static void
180+
vioapic_update_eoi_exit(const struct acrn_vioapic *vioapic)
181+
{
182+
struct acrn_vcpu *vcpu;
183+
union ioapic_rte rte;
184+
uint64_t mask;
185+
uint32_t vector, delmode, dest;
186+
uint32_t pin, pincount;
187+
uint16_t vcpu_id;
188+
bool level, phys;
189+
190+
dev_dbg(ACRN_DBG_IOAPIC, "%s", __func__);
191+
192+
/* clear old bitmap to generate new bitmap */
193+
foreach_vcpu(vcpu_id, vioapic->vm, vcpu) {
194+
spinlock_obtain(&(vcpu->arch.lock));
195+
vcpu_reset_eoi_exit_all(vcpu);
196+
}
197+
198+
/* go through RTEs and set corresponding bits of eoi_exit_bitmap */
199+
pincount = vioapic_pincount(vioapic->vm);
200+
for (pin = 0U; pin < pincount; pin++) {
201+
rte = vioapic->rtbl[pin];
202+
203+
level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL);
204+
vector = rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC;
205+
206+
if (level && ((vector >= 0x20U) && (vector < NR_MAX_VECTOR))) {
207+
/* if level-trigger and vector is valid */
208+
delmode = (uint32_t)(rte.full & IOAPIC_RTE_DELMOD);
209+
210+
if ((delmode != APIC_DELMODE_FIXED) && (delmode != APIC_DELMODE_LOWPRIO)) {
211+
dev_dbg(ACRN_DBG_IOAPIC,
212+
"Ignoring level trigger-mode for delivery-mode 0x%x", delmode);
213+
} else {
214+
dest = (uint32_t)((rte.full) >> IOAPIC_RTE_DEST_SHIFT);
215+
phys = ((rte.full & IOAPIC_RTE_DESTLOG) == 0UL);
216+
calcvdest(vioapic->vm, &mask, dest, phys);
217+
218+
for (vcpu_id = ffs64(mask); vcpu_id != INVALID_BIT_INDEX; vcpu_id = ffs64(mask)) {
219+
vcpu = vcpu_from_vid(vioapic->vm, vcpu_id);
220+
vcpu_set_eoi_exit(vcpu, vector);
221+
bitmap_clear_nolock(vcpu_id, &mask);
222+
}
223+
}
224+
}
225+
}
226+
227+
/* make request if eoi_exit_bitmap changed */
228+
foreach_vcpu(vcpu_id, vioapic->vm, vcpu) {
229+
spinlock_release(&(vcpu->arch.lock));
230+
vcpu_make_request(vcpu, ACRN_REQUEST_EOI_EXIT_UPDATE);
231+
}
232+
}
233+
174234
/*
175235
* Reset the vlapic's trigger-mode register to reflect the ioapic pin
176236
* configuration.
@@ -358,15 +418,9 @@ static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr,
358418
* rendezvous all the vcpus to update their vlapic
359419
* trigger-mode registers.
360420
*/
361-
if ((changed & NEED_TMR_UPDATE) != 0UL) {
362-
uint16_t i;
363-
struct acrn_vcpu *vcpu;
364-
365-
dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: recalculate vlapic trigger-mode reg", pin);
366-
367-
foreach_vcpu(i, vioapic->vm, vcpu) {
368-
vcpu_make_request(vcpu, ACRN_REQUEST_TMR_UPDATE);
369-
}
421+
if ((changed & NEED_EOI_EXIT_UPDATE) != 0UL) {
422+
dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: recalculate vlapic trigger-mode reg", pin);
423+
vioapic_update_eoi_exit(vioapic);
370424
}
371425

372426
/*

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#define ACRN_REQUEST_EPT_FLUSH 5U
4040
#define ACRN_REQUEST_TRP_FAULT 6U
4141
#define ACRN_REQUEST_VPID_FLUSH 7U /* flush vpid tlb */
42+
#define ACRN_REQUEST_EOI_EXIT_UPDATE 8U
4243

4344
#define E820_MAX_ENTRIES 32U
4445

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ struct ext_context {
169169
#define NUM_COMMON_MSRS 7U
170170
#define NUM_GUEST_MSRS (NUM_WORLD_MSRS + NUM_COMMON_MSRS)
171171

172+
#define EOI_EXIT_BITMAP_SIZE 256U
173+
172174
struct event_injection_info {
173175
uint32_t intr_info;
174176
uint32_t error_code;
@@ -247,6 +249,10 @@ struct acrn_vcpu_arch {
247249

248250
/* List of MSRS to be stored and loaded on VM exits or VM entries */
249251
struct msr_store_area msr_area;
252+
253+
/* EOI_EXIT_BITMAP buffer, for the bitmap update */
254+
uint64_t eoi_exit_bitmap[EOI_EXIT_BITMAP_SIZE >> 6U];
255+
spinlock_t lock;
250256
} __aligned(PAGE_SIZE);
251257

252258
struct acrn_vm;
@@ -498,6 +504,36 @@ uint64_t vcpu_get_guest_msr(const struct acrn_vcpu *vcpu, uint32_t msr);
498504
*/
499505
void vcpu_set_guest_msr(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t val);
500506

507+
/**
508+
* @brief write eoi_exit_bitmap to VMCS fields
509+
*
510+
* @param[in] vcpu pointer to vcpu data structure
511+
*
512+
* @return void
513+
*/
514+
void vcpu_set_vmcs_eoi_exit(struct acrn_vcpu *vcpu);
515+
516+
/**
517+
* @brief reset eoi_exit_bitmap
518+
*
519+
* @param[in] vcpu pointer to vcpu data structure
520+
*
521+
* @return void
522+
*/
523+
524+
void vcpu_reset_eoi_exit_all(struct acrn_vcpu *vcpu);
525+
526+
/**
527+
* @brief set eoi_exit_bitmap bit
528+
*
529+
* Set corresponding bit of vector in eoi_exit_bitmap
530+
*
531+
* @param[in] vcpu pointer to vcpu data structure
532+
* @param[in] vector
533+
*
534+
* @return void
535+
*/
536+
void vcpu_set_eoi_exit(struct acrn_vcpu *vcpu, uint32_t vector);
501537
/**
502538
* @brief set all the vcpu registers
503539
*

0 commit comments

Comments
 (0)