From c22f899a5ed414805e113af08d31aa4ed2140404 Mon Sep 17 00:00:00 2001 From: Kaige Fu Date: Wed, 30 Oct 2019 13:54:39 +0000 Subject: [PATCH] HV: Fix poweroff issue of hard RTVM We should use INIT signal to notify the vcpu threads when powering off the hard RTVM. To achive this, we should set the vcpu->thread_obj.notify_mode as SCHED_NOTIFY_INIT. Patch (27163df9 hv: sched: add sleep/wake for thread object) tries to set the notify_mode according `is_lapic_pt_enabled(vcpu)` in function prepare_vcpu. But at this point, the is_lapic_pt_enabled(vcpu) will always return false. Consequently, it will set notify_mode as SCHED_NOTIFY_IPI. Then leads to the failure of powering off hard RTVM. This patch fixes it by: - Initialize the notify_mode as SCHED_NOTIFY_IPI in prepare_vcpu. - Set notify_mode as SCHED_NOTIFY_INIT after guest is trying to enable x2apic mode of passthru lapic. Tracked-On: #3975 Reviewed-by: Yin Fengwei Reviewed-by: Yan, Like Signed-off-by: Kaige Fu --- hypervisor/arch/x86/guest/vcpu.c | 6 ++++-- hypervisor/arch/x86/guest/vmcs.c | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index b86f53347..b207b1bd0 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -661,6 +661,9 @@ void reset_vcpu(struct acrn_vcpu *vcpu) } vcpu->arch.cur_context = NORMAL_WORLD; + /* TODO: we may need to add one scheduler->reset_data to reset the thread_obj */ + vcpu->thread_obj.notify_mode = SCHED_NOTIFY_IPI; + vlapic = vcpu_vlapic(vcpu); vlapic_reset(vlapic, apicv_ops); @@ -758,8 +761,7 @@ int32_t prepare_vcpu(struct acrn_vm *vm, uint16_t pcpu_id) vcpu->thread_obj.sched_ctl = &per_cpu(sched_ctl, pcpu_id); vcpu->thread_obj.thread_entry = vcpu_thread; vcpu->thread_obj.pcpu_id = pcpu_id; - vcpu->thread_obj.notify_mode = is_lapic_pt_enabled(vcpu) ? - SCHED_NOTIFY_INIT : SCHED_NOTIFY_IPI; + vcpu->thread_obj.notify_mode = SCHED_NOTIFY_IPI; vcpu->thread_obj.host_sp = build_stack_frame(vcpu); vcpu->thread_obj.switch_out = context_switch_out; vcpu->thread_obj.switch_in = context_switch_in; diff --git a/hypervisor/arch/x86/guest/vmcs.c b/hypervisor/arch/x86/guest/vmcs.c index 2d87a5c15..6de943448 100644 --- a/hypervisor/arch/x86/guest/vmcs.c +++ b/hypervisor/arch/x86/guest/vmcs.c @@ -599,6 +599,12 @@ void switch_apicv_mode_x2apic(struct acrn_vcpu *vcpu) exec_vmwrite32(VMX_PROC_VM_EXEC_CONTROLS2, value32); update_msr_bitmap_x2apic_passthru(vcpu); + + /* + * After passthroughing lapic to guest, we should use INIT signal to + * notify vcpu thread instead of IPI + */ + vcpu->thread_obj.notify_mode = SCHED_NOTIFY_INIT; } else { value32 = exec_vmread32(VMX_PROC_VM_EXEC_CONTROLS2); value32 &= ~VMX_PROCBASED_CTLS2_VAPIC;