VirtualBox

2 年 前 建立

19 月 前 更新

#21353 new defect

apic timer does not trigger in time

回報者: liowmark 負責人:
元件: VMM 版本: VirtualBox 6.1.40
關鍵字: apic timer 副本:
Guest type: Linux Host type: Windows

描述

Rencently,I found a bug of APIC timer.Since the vbox set the last VCPU thread as the thread to wakeup all the timer and other VCPU threads will sleep 500ms until the Last VCPU thread wakeup them. If the last VCPU thread sleep a long time firstly,other VCPU thread's apic timer will not able to trigger in timer.This make other VCPU thread sleep at least 500ms.

here is may patch to the funtion apicSetTimerIcr in VMM/VMMALL/APICAll.cpp to fix the bug

#include "TMInternal.h"
static VBOXSTRICTRC apicSetTimerIcr(PPDMDEVINS pDevIns, PVMCPUCC pVCpu, int rcBusy, uint32_t uInitialCount)
{
    VMCPU_ASSERT_EMT(pVCpu);

    PAPIC      pApic      = VM_TO_APIC(pVCpu->CTX_SUFF(pVM));
    PAPICCPU   pApicCpu   = VMCPU_TO_APICCPU(pVCpu);
    PXAPICPAGE pXApicPage = VMCPU_TO_XAPICPAGE(pVCpu);

    Log2(("APIC%u: apicSetTimerIcr: uInitialCount=%#RX32\n", pVCpu->idCpu, uInitialCount));
    STAM_COUNTER_INC(&pApicCpu->StatTimerIcrWrite);

    /* In TSC-deadline mode, timer ICR writes are ignored, see Intel spec. 10.5.4.1 "TSC-Deadline Mode". */
    if (   pApic->fSupportsTscDeadline
        && pXApicPage->lvt_timer.u.u2TimerMode == XAPIC_TIMER_MODE_TSC_DEADLINE)
        return VINF_SUCCESS;

    /*
     * The timer CCR may be modified by apicR3TimerCallback() in parallel,
     * so obtain the lock -before- updating it here to be consistent with the
     * timer ICR. We rely on CCR being consistent in apicGetTimerCcr().
     */
    TMTIMERHANDLE hTimer = pApicCpu->hTimer;
    VBOXSTRICTRC rc = PDMDevHlpTimerLockClock(pDevIns, hTimer, rcBusy);
    if (rc == VINF_SUCCESS)
    {
        pXApicPage->timer_icr.u32InitialCount = uInitialCount;
        pXApicPage->timer_ccr.u32CurrentCount = uInitialCount;
        if (uInitialCount)
            apicStartTimer(pVCpu, uInitialCount);
        else
            apicStopTimer(pVCpu);


        PVMCC pVM   = pVCpu->CTX_SUFF(pVM);
        PVMCPUCC pVCpuDst = VMCC_GET_CPU(pVM, pVM->tm.s.idTimerCpu);

        #ifdef IN_RING3
            VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM | VMNOTIFYFF_FLAGS_POKE);
        #elif defined(IN_RING0)

           if (VMMGetCpu(pVM) != pVCpuDst)
            {
                switch (VMCPU_GET_STATE(pVCpuDst))
                {
                    case VMCPUSTATE_STARTED_EXEC:
                        GVMMR0SchedPokeNoGVMNoLock(pVM, pVM->tm.s.idTimerCpu);
                        break;

                    case VMCPUSTATE_STARTED_HALTED:
                        GVMMR0SchedWakeUpNoGVMNoLock(pVM, pVM->tm.s.idTimerCpu);
                        break;

                    default:
                        break; /* nothing to do in other states. */
                }
            }
        #endif

        PDMDevHlpTimerUnlockClock(pDevIns, hTimer);
    }
    return rc;
}

更動歷史 (1)

comment:1 19 月 前riverskyfang 編輯

Is there a testcase that can reproduce this issue?

最後由 riverskyfang 編輯於 19 月 前 (上一筆) (差異)
注意: 瀏覽 TracTickets 來幫助您使用待辦事項功能

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette