mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-01 05:03:55 +00:00
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 <shuo.a.liu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
58 lines
1.4 KiB
C
58 lines
1.4 KiB
C
/*
|
|
* Copyright (C) 2018 Intel Corporation. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
#include <cpu.h>
|
|
#include <schedule.h>
|
|
#include <event.h>
|
|
#include <logmsg.h>
|
|
|
|
void init_event(struct sched_event *event)
|
|
{
|
|
spinlock_init(&event->lock);
|
|
event->set = false;
|
|
event->waiting_thread = NULL;
|
|
}
|
|
|
|
void reset_event(struct sched_event *event)
|
|
{
|
|
uint64_t rflag;
|
|
|
|
spinlock_irqsave_obtain(&event->lock, &rflag);
|
|
event->set = false;
|
|
event->waiting_thread = NULL;
|
|
spinlock_irqrestore_release(&event->lock, rflag);
|
|
}
|
|
|
|
/* support exclusive waiting only */
|
|
void wait_event(struct sched_event *event)
|
|
{
|
|
uint64_t rflag;
|
|
|
|
spinlock_irqsave_obtain(&event->lock, &rflag);
|
|
ASSERT((event->waiting_thread == NULL), "only support exclusive waiting");
|
|
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();
|
|
spinlock_irqsave_obtain(&event->lock, &rflag);
|
|
}
|
|
event->set = false;
|
|
event->waiting_thread = NULL;
|
|
spinlock_irqrestore_release(&event->lock, rflag);
|
|
}
|
|
|
|
void signal_event(struct sched_event *event)
|
|
{
|
|
uint64_t rflag;
|
|
|
|
spinlock_irqsave_obtain(&event->lock, &rflag);
|
|
event->set = true;
|
|
if (event->waiting_thread != NULL) {
|
|
wake_thread(event->waiting_thread);
|
|
}
|
|
spinlock_irqrestore_release(&event->lock, rflag);
|
|
}
|