mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-22 05:30:24 +00:00
hv: pause all other vCPUs in same VM when do wbinvd emulation
Invalidate cache by scanning and flushing the whole guest memory is inefficient which might cause long execution time for WBINVD emulation. A long execution in hypervisor might cause a vCPU stuck phenomenon what impact Windows Guest booting. This patch introduce a workaround method that pausing all other vCPUs in the same VM when do wbinvd emulation. Tracked-On: #4703 Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
a335679ce9
commit
9a15ea82ee
@ -241,6 +241,17 @@ void walk_ept_table(struct acrn_vm *vm, pge_handler cb)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Walk through the whole page tables of one VM is a time-consuming
|
||||
* operation. Preemption is not support by hypervisor scheduling
|
||||
* currently, so the walk through page tables operation might occupy
|
||||
* CPU for long time what starve other threads.
|
||||
*
|
||||
* Give chance to release CPU to make other threads happy.
|
||||
*/
|
||||
if (need_reschedule(get_pcpu_id())) {
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,6 +374,9 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
|
||||
pr_fatal("Triple fault happen -> shutdown!");
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_WAIT_WBINVD, pending_req_bits)) {
|
||||
wait_event(&vcpu->events[VCPU_EVENT_SYNC_WBINVD]);
|
||||
}
|
||||
|
||||
if (bitmap_test_and_clear_lock(ACRN_REQUEST_EPT_FLUSH, pending_req_bits)) {
|
||||
invept(vcpu->vm->arch_vm.nworld_eptp);
|
||||
|
@ -379,10 +379,30 @@ static int32_t xsetbv_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
|
||||
static int32_t wbinvd_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
{
|
||||
uint16_t i;
|
||||
struct acrn_vcpu *other;
|
||||
|
||||
if (has_rt_vm() == false) {
|
||||
cache_flush_invalidate_all();
|
||||
} else {
|
||||
if (is_rt_vm(vcpu->vm)) {
|
||||
walk_ept_table(vcpu->vm, ept_flush_leaf_page);
|
||||
} else {
|
||||
/* Pause other vcpus and let them wait for the wbinvd completion */
|
||||
foreach_vcpu(i, vcpu->vm, other) {
|
||||
if (other != vcpu) {
|
||||
vcpu_make_request(other, ACRN_REQUEST_WAIT_WBINVD);
|
||||
}
|
||||
}
|
||||
|
||||
walk_ept_table(vcpu->vm, ept_flush_leaf_page);
|
||||
|
||||
foreach_vcpu(i, vcpu->vm, other) {
|
||||
if (other != vcpu) {
|
||||
signal_event(&other->events[VCPU_EVENT_SYNC_WBINVD]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -93,6 +93,11 @@
|
||||
*/
|
||||
#define ACRN_REQUEST_INIT_VMCS 8U
|
||||
|
||||
/**
|
||||
* @brief Request for sync waiting WBINVD
|
||||
*/
|
||||
#define ACRN_REQUEST_WAIT_WBINVD 9U
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@ -148,7 +153,8 @@ enum vm_cpu_mode {
|
||||
|
||||
#define VCPU_EVENT_IOREQ 0
|
||||
#define VCPU_EVENT_VIRTUAL_INTERRUPT 1
|
||||
#define VCPU_EVENT_NUM 2
|
||||
#define VCPU_EVENT_SYNC_WBINVD 2
|
||||
#define VCPU_EVENT_NUM 3
|
||||
|
||||
enum reset_mode;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user