hv: Support concurrent split-lock emulation on SMP.

For a SMP guest, split-lock check may happen on
multiple vCPUs simultaneously. In this case, one
vCPU at most can be allowed running in the
split-lock emulation window. And if the vCPU is
doing the emulation, it should never be blocked
in the hypervisor, it should go back to the guest
to execute the lock instruction immediately and
trap back to the hypervisor with #DB to complete the
split-lock emulation.

Tracked-On: #5605
Signed-off-by: Jie Deng <jie.deng@intel.com>
This commit is contained in:
Jie Deng 2020-11-17 16:22:48 +08:00 committed by acrnsi-robot
parent 0b18389d95
commit 6852438e3a
1 changed files with 17 additions and 0 deletions

View File

@ -492,6 +492,8 @@ static void vcpu_kick_splitlock_emulation(struct acrn_vcpu *cur_vcpu)
uint16_t i; uint16_t i;
if (cur_vcpu->vm->hw.created_vcpus > 1U) { if (cur_vcpu->vm->hw.created_vcpus > 1U) {
get_vm_lock(cur_vcpu->vm);
foreach_vcpu(i, cur_vcpu->vm, other) { foreach_vcpu(i, cur_vcpu->vm, other) {
if (other != cur_vcpu) { if (other != cur_vcpu) {
vcpu_make_request(other, ACRN_REQUEST_SPLIT_LOCK); vcpu_make_request(other, ACRN_REQUEST_SPLIT_LOCK);
@ -508,9 +510,24 @@ static void vcpu_complete_splitlock_emulation(struct acrn_vcpu *cur_vcpu)
if (cur_vcpu->vm->hw.created_vcpus > 1U) { if (cur_vcpu->vm->hw.created_vcpus > 1U) {
foreach_vcpu(i, cur_vcpu->vm, other) { foreach_vcpu(i, cur_vcpu->vm, other) {
if (other != cur_vcpu) { if (other != cur_vcpu) {
/*
* Suppose the current vcpu is 0, the other vcpus (1, 2, 3) may wait on the
* "get_vm_lock", the current vcpu need clear the ACRN_REQUEST_SPLIT_LOCK
* explicitly here after finishing the emulation. Otherwise, it make cause
* dead lock. for example:
* 1. Once vcpu 0 "put_vm_lock", let's say vcpu 1 will "get_vm_lock".
* 2. vcpu 1 call "vcpu_make_request" to pause vcpu 0, 2, 3.
* 3. vcpu 1's VCPU_EVENT_SPLIT_LOCK is still not cleared because
* the vcpu 0 called "vcpu_make_request" ever.
* 4. All vcpus will wait for VCPU_EVENT_SPLIT_LOCK in acrn_handle_pending_request.
* We should avoid this dead lock case.
*/
bitmap_clear_lock(ACRN_REQUEST_SPLIT_LOCK, &other->arch.pending_req);
signal_event(&other->events[VCPU_EVENT_SPLIT_LOCK]); signal_event(&other->events[VCPU_EVENT_SPLIT_LOCK]);
} }
} }
put_vm_lock(cur_vcpu->vm);
} }
} }