From 53de3a727c641d167f8006dd86a42b7f68a1e6c3 Mon Sep 17 00:00:00 2001 From: Shuo A Liu Date: Fri, 14 Feb 2020 00:05:51 +0800 Subject: [PATCH] hv: reset vcpu events in reset_vcpu On UEFI UP2 board, APs might execute HLT before SOS kernel INIT them. After SOS kernel take over and will re-init the APs directly. The flows from HV perspective is like: HLT trap: wait_event(VCPU_EVENT_VIRTUAL_INTERRUPT) -> sleep_thread SOS kernel INIT, SIPI APs: pause_vcpu(ZOMBIE) -> sleep_thread -> reset_vcpu -> launch_vcpu -> wake_vcpu However, the last wake_vcpu will fail because the cpu event VCPU_EVENT_VIRTUAL_INTERRUPT had not got signaled. This patch will reset all vcpu events in reset_vcpu. If the thread was previously waiting for a event, its waiting status will be cleared and launch_vcpu will wake it to running. Tracked-On: #4402 Signed-off-by: Shuo A Liu Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/vcpu.c | 4 ++++ hypervisor/common/event.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index 616188944..df7b55434 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -220,6 +220,10 @@ static void vcpu_reset_internal(struct acrn_vcpu *vcpu, enum reset_mode mode) vlapic_reset(vlapic, apicv_ops, mode); reset_vcpu_regs(vcpu); + + for (i = 0; i < VCPU_EVENT_NUM; i++) { + reset_event(&vcpu->events[i]); + } } struct acrn_vcpu *get_running_vcpu(uint16_t pcpu_id) diff --git a/hypervisor/common/event.c b/hypervisor/common/event.c index 6c00ed83f..b98494528 100644 --- a/hypervisor/common/event.c +++ b/hypervisor/common/event.c @@ -32,8 +32,8 @@ void wait_event(struct sched_event *event) spinlock_irqsave_obtain(&event->lock, &rflag); ASSERT((event->waiting_thread == NULL), "only support exclusive waiting"); - while (!event->set) { - event->waiting_thread = sched_get_current(get_pcpu_id()); + event->waiting_thread = sched_get_current(get_pcpu_id()); + while (!event->set && (event->waiting_thread != NULL)) { sleep_thread(event->waiting_thread); spinlock_irqrestore_release(&event->lock, rflag); schedule();