{"id":6407,"date":"2024-03-19T15:01:01","date_gmt":"2024-03-19T07:01:01","guid":{"rendered":""},"modified":"2024-03-19T15:01:01","modified_gmt":"2024-03-19T07:01:01","slug":"Virtualbox\u6e90\u7801\u5206\u679022 NEM(Hyper-V\u517c\u5bb9)3 Emulation Thread","status":"publish","type":"post","link":"https:\/\/mushiming.com\/6407.html","title":{"rendered":"Virtualbox\u6e90\u7801\u5206\u679022 NEM(Hyper-V\u517c\u5bb9)3 Emulation Thread"},"content":{"rendered":"

\n <\/path> \n<\/svg> <\/p>\n

Native execution manager \uff08Emulation Thread \uff09<\/h3>\n<\/p>\n
\n

\u6587\u7ae0\u76ee\u5f55<\/h4>\n
    \n
  • \n
      \n
    • Native execution manager \uff08Emulation Thread \uff09<\/li>\n
    • 22.1. Emulation\u5faa\u73af\u7ebf\u7a0b<\/li>\n
    • \n
        \n
      • emR3NemExecute<\/li>\n
      • nemR3NativeRunGC<\/li>\n
      • R0\u7684\u5faa\u73af<\/li>\n
      • NEMR0RunGuestCode<\/li>\n
      • emR3NemForcedActions<\/li>\n<\/ul>\n<\/li>\n
      • 22.2 \u4eceGuestOS\u91cc\u83b7\u53d6\u548c\u5199\u5165\u5bc4\u5b58\u5668\u4fe1\u606f<\/li>\n
      • \n
          \n
        • nemR0WinImportState<\/li>\n
        • nemR0WinExportState<\/li>\n<\/ul>\n<\/li>\n
        • 22.3\u4e2d\u65ad\u5904\u7406<\/li>\n
        • \n
            \n
          • nemHCWinHandleInterruptFF<\/li>\n<\/ul>\n<\/li>\n
          • <\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/div>\n

            \u672c\u7bc7\u91cd\u70b9\u4ecb\u7ecdNEM\u6a21\u5f0f\u7684\u6267\u884cGuestOS\u76f8\u5173\u7684\u51fd\u6570\uff0c\u57fa\u672c\u6846\u67b6\u548cHM\/Raw-mode\u5b8c\u5168\u4e00\u6837\uff0c\u53ea\u662f\u5177\u4f53\u5b9e\u73b0\u4ee3\u7801\uff08\u8c03\u7528\u7684API\uff09\u4e0d\u540c\u800c\u5df2\u3002 <\/p>\n

            22.1. Emulation\u5faa\u73af\u7ebf\u7a0b<\/h3>\n

            emR3NemExecute<\/h4>\n

            \u4e3b\u5faa\u73af\u51fd\u6570\uff0c\u5b9e\u73b0\u539f\u7406\u548c\u8fc7\u7a0b\u548cVMX\/Raw-mode\u51e0\u4e4e\u4e00\u6837\uff0c\u90e8\u5206\u5904\u7406action\u7684\u4ee3\u7801\u53ef\u4ee5\u53c2\u8003EM\u4e00\u7bc7<\/p>\n

            EMR3Nem.cpp<\/p>\n

            VBOXSTRICTRC emR3NemExecute<\/span>(<\/span>PVM pVM,<\/span> PVMCPU pVCpu,<\/span> bool<\/span> *<\/span>pfFFDone)<\/span>\n{ \n   <\/span>\n    \/\/\u6b7b\u5faa\u73af\u6267\u884cGuestOS\u4ee3\u7801<\/span>\n    for<\/span> (<\/span>;<\/span>;<\/span>)<\/span>\n    { \n   <\/span>\n        \/\/\u5148\u6267\u884cForce Action\uff0c\u5904\u7406pending\u7684\u4e8b\u4ef6<\/span>\n        if<\/span> (<\/span>   VM_FF_IS_ANY_SET<\/span>(<\/span>pVM,<\/span> VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)<\/span>\n            ||<\/span> VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK)<\/span>)<\/span>\n        { \n   <\/span>\n            rcStrict =<\/span> emR3NemForcedActions<\/span>(<\/span>pVM,<\/span> pVCpu)<\/span>;<\/span>\n            if<\/span> (<\/span>rcStrict !=<\/span> VINF_SUCCESS)<\/span>\n                break<\/span>;<\/span>\n        }<\/span>\n        \/\/\u6267\u884c\u4ee3\u7801<\/span>\n        if<\/span> (<\/span>RT_LIKELY<\/span>(<\/span>emR3IsExecutionAllowed<\/span>(<\/span>pVM,<\/span> pVCpu)<\/span>)<\/span>)<\/span>\n        { \n   <\/span>\n            rcStrict =<\/span> NEMR3RunGC<\/span>(<\/span>pVM,<\/span> pVCpu)<\/span>;<\/span>\n        }<\/span>\n        else<\/span>\n        { \n   <\/span>\n            \/\/\u6682\u65f6\u6ca1\u6709\u6267\u884c\u6743\u9650\uff0csleep5\u6beb\u79d2\u4e4b\u540e\u518d\u6267\u884c<\/span>\n            RTThreadSleep<\/span>(<\/span>5<\/span>)<\/span>;<\/span>\n            rcStrict =<\/span> VINF_SUCCESS;<\/span>\n        }<\/span>\n        \/\/\u5904\u7406\u9ad8\u4f18\u5148\u7ea7\u7684pending\u4e8b\u4ef6\uff0c\u8c03\u7528\u7684\u662fEM\u91cc\u7684\u51fd\u6570\uff0c\u5df2\u5728EM\u4e00\u7bc7\u91cc\u4ecb\u7ecd<\/span>\n        VMCPU_FF_CLEAR_MASK<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_RESUME_GUEST_MASK)<\/span>;<\/span>\n        if<\/span> (<\/span>   VM_FF_IS_ANY_SET<\/span>(<\/span>pVM,<\/span> VM_FF_HIGH_PRIORITY_POST_MASK)<\/span>\n            ||<\/span> VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_HIGH_PRIORITY_POST_MASK)<\/span>)<\/span>\n            rcStrict =<\/span> emR3HighPriorityPostForcedActions<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> rcStrict)<\/span>;<\/span>\n        \/\/\u8fd4\u56de\u503c\u9519\u8bef\uff0c\u9000\u51fa\u5faa\u73af<\/span>\n        if<\/span> (<\/span>rcStrict >=<\/span> VINF_EM_FIRST &&<\/span> rcStrict <=<\/span> VINF_EM_LAST)<\/span>\n            break<\/span>;<\/span>\n\t    \/\/\u5904\u7406\u8fd4\u56de\u503c\uff0c\u5176\u5b9e\u8c03\u7528\u7684\u51fd\u6570\u662femR3HmHandleRC\uff0c\u5df2\u5728EM\u4e00\u7bc7\u91cc\u4ecb\u7ecd<\/span>\n        \/\/emR3NemHandleRC \u8fd4\u56deVINF_SUCCESS\uff0c\u8868\u793a\u53ef\u4ee5\u7ee7\u7eed\u6267\u884c\uff0c\u5176\u4ed6\u503c\u9700\u8981\u9000\u51fa\u5faa\u73af\u8fd4\u56deR3\u5904\u7406<\/span>\n        rcStrict =<\/span> emR3NemHandleRC<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> VBOXSTRICTRC_TODO<\/span>(<\/span>rcStrict)<\/span>)<\/span>;<\/span>\n        if<\/span> (<\/span>rcStrict !=<\/span> VINF_SUCCESS)<\/span>\n            break<\/span>;<\/span>\n        \/\/\u5904\u7406forceaction<\/span>\n        if<\/span> (<\/span>   VM_FF_IS_ANY_SET<\/span>(<\/span>pVM,<\/span> VM_FF_ALL_MASK)<\/span>\n            ||<\/span> VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_ALL_MASK)<\/span>)<\/span>\n        { \n   <\/span>\n            \/\/\u8c03\u7528\u7684\u662fEM\u91cc\u7684\u51fd\u6570\uff0c\u5df2\u5728EM\u4e00\u7bc7\u91cc\u4ecb\u7ecd<\/span>\n            rcStrict =<\/span> emR3ForcedActions<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> VBOXSTRICTRC_TODO<\/span>(<\/span>rcStrict)<\/span>)<\/span>;<\/span>\n            VBOXVMM_EM_FF_ALL_RET<\/span>(<\/span>pVCpu,<\/span> VBOXSTRICTRC_VAL<\/span>(<\/span>rcStrict)<\/span>)<\/span>;<\/span>\n            \/\/\u5982\u679c\u8fd4\u56de\u9519\u8bef\u6216\u8005\u9700\u8981\u91cd\u65b0\u51b3\u5b9a\u8fd0\u884c\u6a21\u5f0f\uff0c\u9000\u51fa\u5faa\u73af<\/span>\n            if<\/span> (<\/span>   rcStrict !=<\/span> VINF_SUCCESS\n                &&<\/span> rcStrict !=<\/span> VINF_EM_RESCHEDULE_HM)<\/span>\n            { \n   <\/span>\n                *<\/span>pfFFDone =<\/span> true<\/span>;<\/span>\n                break<\/span>;<\/span>\n            }<\/span>\n        }<\/span>\n\t}<\/span>\/\/end of for<\/span>\n    if<\/span> (<\/span>pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn)<\/span>\n    { \n   <\/span>\n        \/\/\u6839\u636efExtrn\u91cc\u7684flags\u4eceGuestOS\u91cc\u8bfb\u53d6\u5bf9\u5e94\u5bc4\u5b58\u5668\uff0c\u65b9\u4fbf\u540e\u9762\u5904\u7406<\/span>\n        int<\/span> rcImport =<\/span> NEMImportStateOnDemand<\/span>(<\/span>pVCpu,<\/span> pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn)<\/span>;<\/span>\n    }<\/span>\n}<\/span>\n<\/code><\/pre>\n

            nemR3NativeRunGC<\/h4>\n
            VBOXSTRICTRC nemR3NativeRunGC<\/span>(<\/span>PVM pVM,<\/span> PVMCPU pVCpu)<\/span>\n{ \n   <\/span>\n    \/\/\u5f00\u542f\u4e86R0\u5faa\u73af<\/span>\n    if<\/span> (<\/span>pVM-<\/span>><\/span>nem.<\/span>s.<\/span>fUseRing0Runloop)<\/span>\n    { \n   <\/span>\n        for<\/span> (<\/span>;<\/span>;<\/span>)<\/span>\n        { \n   <\/span>\n            \/\/IOCTL\u8c03\u7528R0\u6307\u4ee4\u6267\u884cGuestOS\u4ee3\u7801<\/span>\n            VBOXSTRICTRC rcStrict =<\/span> VMMR3CallR0EmtFast<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> VMMR0_DO_NEM_RUN)<\/span>;<\/span>\n            \/\/\u4e0b\u9762\u662f\u5904\u7406\u8fd4\u56de\u503c<\/span>\n            if<\/span> (<\/span>RT_SUCCESS<\/span>(<\/span>rcStrict)<\/span>)<\/span>\n            { \n   <\/span>\n                \/\/\u5982\u679c\u6807\u8bb0\u4e86\u9700\u8981\u5237\u65b0TLB\uff0c\u5148\u6267\u884c\uff0c\u5904\u7406\u540e\u9762\u7684\u4e8b\u4ef6\uff0c\u9632\u6b62\u540e\u9762\u8bfb\u53d6\u5230\u9519\u8bef\u7684\u5185\u5b58<\/span>\n                VBOXSTRICTRC rcPending =<\/span> pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>rcPending;<\/span>\n                pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>rcPending =<\/span> VINF_SUCCESS;<\/span>\n                if<\/span> (<\/span>rcStrict ==<\/span> VINF_NEM_FLUSH_TLB ||<\/span> rcPending ==<\/span> VINF_NEM_FLUSH_TLB)<\/span>\n                { \n   <\/span>\n                    \/\/\u5237\u65b0TLB<\/span>\n                    int<\/span> rc =<\/span> PGMFlushTLB<\/span>(<\/span>pVCpu,<\/span> CPUMGetGuestCR3<\/span>(<\/span>pVCpu)<\/span>,<\/span> true<\/span>)<\/span>;<\/span>\n                    if<\/span> (<\/span>rcStrict ==<\/span> VINF_NEM_FLUSH_TLB)<\/span>\n                    { \n   <\/span>\n                        if<\/span> (<\/span>   !<\/span>VM_FF_IS_ANY_SET<\/span>(<\/span>pVM,<\/span> VM_FF_HIGH_PRIORITY_POST_MASK |<\/span> VM_FF_HP_R0_PRE_HM_MASK)<\/span>\n                            &&<\/span> !<\/span>VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span>   (<\/span>VMCPU_FF_HIGH_PRIORITY_POST_MASK |<\/span> VMCPU_FF_HP_R0_PRE_HM_MASK)<\/span>\n                                                           &<\/span> ~<\/span>VMCPU_FF_RESUME_GUEST_MASK)<\/span>)<\/span>\n                        { \n   <\/span>\n                            \/\/\u5982\u679c\u6ca1\u6709\u5176\u5b83\u9ad8\u4f18\u5148\u7ea7\u8981\u5904\u7406\u7684\u4e8b\u4ef6\uff0c\u53bb\u6389VMCPU_FF_RESUME_GUEST_MASK\uff0c\u7ee7\u7eed\u6267\u884cGutestOS\u4ee3\u7801<\/span>\n                            VMCPU_FF_CLEAR_MASK<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_RESUME_GUEST_MASK)<\/span>;<\/span>\n                            continue<\/span>;<\/span>\n                        }<\/span>\n                        rcStrict =<\/span> VINF_SUCCESS;<\/span>\n                    }<\/span>\n                }<\/span>\n            }<\/span>\n            return<\/span> rcStrict;<\/span>\n        }<\/span>\n    }<\/span>\n}<\/span>\n<\/code><\/pre>\n

            R0\u7684\u5faa\u73af<\/h4>\n

            VMMR0EntryFast IOCTl\u901a\u77e5R0\u5f00\u59cb\u5faa\u73af\u6267\u884cGuestOS\u4ee3\u7801<\/p>\n

            VMMR0DECL<\/span>(<\/span>void<\/span>)<\/span> VMMR0EntryFast<\/span>(<\/span>PGVM pGVM,<\/span> PVMCC pVMIgnored,<\/span> VMCPUID idCpu,<\/span> VMMR0OPERATION enmOperation)<\/span>\n{ \n   <\/span>\n    .<\/span>.<\/span>.<\/span>.<\/span>\n        case<\/span> VMMR0_DO_NEM_RUN:<\/span>\n        { \n   <\/span>\n            \/\/\u4f7f\u7528\u957f\u8df3\u6311\u6218\u5230NEMR0RunGuestCode\uff08R0\u5faa\u73af\uff09<\/span>\n            int<\/span> rc =<\/span> vmmR0CallRing3SetJmp2<\/span>(<\/span>&<\/span>pGVCpu-<\/span>><\/span>vmm.<\/span>s.<\/span>CallRing3JmpBufR0,<\/span> (<\/span>PFNVMMR0SETJMP2)<\/span>NEMR0RunGuestCode,<\/span> pGVM,<\/span> idCpu)<\/span>;<\/span>\n            pGVCpu-<\/span>><\/span>vmm.<\/span>s.<\/span>iLastGZRc =<\/span> rc;<\/span>\n            VBOXVMM_R0_VMM_RETURN_TO_RING3_NEM<\/span>(<\/span>pGVCpu,<\/span> CPUMQueryGuestCtxPtr<\/span>(<\/span>pGVCpu)<\/span>,<\/span> rc)<\/span>;<\/span>\n            break<\/span>;<\/span>\n        }<\/span>\n}<\/span>\n<\/code><\/pre>\n

            NEMR0RunGuestCode<\/h4>\n

            \u6700\u7ec8\u8c03\u7528\u5230nemHCWinRunGC\uff0c\u8fd9\u4e2a\u51fd\u6570\u662f\u4e2a\u5927\u6742\u70e9\uff0c3\u79cd\u4e0d\u540c\u7684\u5b9e\u73b0\u90fd\u653e\u5230\u8fd9\u4e2a\u4e00\u4e2a\u51fd\u6570\u91cc\uff0c\u4e3a\u4e86\u7b80\u5316\uff0c\u53ea\u770bR0\u5faa\u73af\u7684\u7248\u672c<\/p>\n

            NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinRunGC<\/span>(<\/span>PVMCC pVM,<\/span> PVMCPUCC pVCpu)<\/span>\n{ \n   <\/span>\n    \/\/\u8bbe\u7f6e\u5f53\u524dVCPu\u72b6\u6001\u6210EXEC_NEM<\/span>\n    if<\/span> (<\/span>VMCPU_CMPXCHG_STATE<\/span>(<\/span>pVCpu,<\/span> VMCPUSTATE_STARTED_EXEC_NEM,<\/span> VMCPUSTATE_STARTED)<\/span>)<\/span>\n    { \n   <\/span> \/* likely *\/<\/span> }<\/span>\n    else<\/span>\n    { \n   <\/span>\n        VMCPU_CMPXCHG_STATE<\/span>(<\/span>pVCpu,<\/span> VMCPUSTATE_STARTED_EXEC_NEM,<\/span> VMCPUSTATE_STARTED_EXEC_NEM_CANCELED)<\/span>;<\/span>\n        return<\/span> VINF_SUCCESS;<\/span>\n    }<\/span>\n  \t\/\/\u4ecepvMsgSlotMapping\u91cc\u83b7\u53d6\u83b7\u53d6\u4fdd\u5b58VEMxit\u7684\u53c2\u6570\u7684\u5185\u5b58\u5730\u5740<\/span>\n    VID_MESSAGE_MAPPING_HEADER volatile<\/span> *<\/span>pMappingHeader =<\/span> (<\/span>VID_MESSAGE_MAPPING_HEADER volatile<\/span> *<\/span>)<\/span>pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>pvMsgSlotMapping;<\/span>\n    \/\/\u662f\u5426\u5728\u88ab\u5355\u6b65\u8c03\u8bd5<\/span>\n    const<\/span> bool<\/span>      fSingleStepping     =<\/span> DBGFIsStepping<\/span>(<\/span>pVCpu)<\/span>;<\/span>\n    \/\/\u5faa\u73af\u6267\u884cGuestOS\u4ee3\u7801<\/span>\n    for<\/span> (<\/span>unsigned<\/span> iLoop =<\/span> 0<\/span>;<\/span>;<\/span> iLoop++<\/span>)<\/span>\n    { \n   <\/span>      \n        pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fDesiredInterruptWindows =<\/span> 0<\/span>;<\/span>\n        \/\/\u5982\u679c\u6709pending\u7684\u4e2d\u65ad<\/span>\n        if<\/span> (<\/span>VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_INTERRUPT_APIC |<\/span> VMCPU_FF_UPDATE_APIC |<\/span> VMCPU_FF_INTERRUPT_PIC\n                                     |<\/span> VMCPU_FF_INTERRUPT_NMI  |<\/span> VMCPU_FF_INTERRUPT_SMI)<\/span>)<\/span>\n        { \n   <\/span>\n            \/\/\u800c\u4e14\u6807\u8bb0\u9700\u8981\u4ecehypervisor\u91cc\u83b7\u53d6VMExit\u4fe1\u606f<\/span>\n            if<\/span> (<\/span>pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags ==<\/span> VID_MSHAGN_F_GET_NEXT_MESSAGE)<\/span>\n            { \n   <\/span>\n                pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags =<\/span> 0<\/span>;<\/span>\n                \/\/\u9000\u51faGuestOS\uff0c\u5904\u7406VMExit\uff08\u4e0b\u4e00\u7bc7\u91cc\u4ecb\u7ecd\uff09<\/span>\n                rcStrict =<\/span> nemHCWinStopCpu<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> rcStrict,<\/span> pMappingHeader)<\/span>;<\/span>\n                if<\/span> (<\/span>rcStrict ==<\/span> VINF_SUCCESS)<\/span>\n                { \n   <\/span> \/* likely *\/<\/span> }<\/span>\n                else<\/span>\n                { \n   <\/span>\n                    break<\/span>;<\/span>\n                }<\/span>\n            }<\/span>\n            \/\/\u5982\u679c\u6709pending\u7684\u4e2d\u65ad\uff0c\u5148\u6ce8\u5165\u4e2d\u65ad<\/span>\n            rcStrict =<\/span> nemHCWinHandleInterruptFF<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> &<\/span>pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fDesiredInterruptWindows)<\/span>;<\/span>\n            if<\/span> (<\/span>rcStrict ==<\/span> VINF_SUCCESS)<\/span>\n            { \n   <\/span> \/* likely *\/<\/span> }<\/span>\n            else<\/span>\n            { \n   <\/span>\n                break<\/span>;<\/span>\n            }<\/span>\n        }<\/span>\n        \/\/\u5728\u5904\u7406vmexit\u548cforceaction\u662f\u7684\u65f6\u5019\u4fee\u6539\u4e86GuestOS\u7684\u5bc4\u5b58\u5668\uff0c\u8c03\u7528hypercall\u628a\u8fd9\u4e9b\u4fee\u6539\u8fc7\u7684\u5bc4\u5b58\u5668\u5199\u5230GuestOS\u91cc<\/span>\n        if<\/span> (<\/span>(<\/span>pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn &<\/span> (<\/span>CPUMCTX_EXTRN_ALL |<\/span> CPUMCTX_EXTRN_NEM_WIN_MASK)<\/span>)<\/span>\n               !=<\/span>                              (<\/span>CPUMCTX_EXTRN_ALL |<\/span> CPUMCTX_EXTRN_NEM_WIN_MASK)<\/span>\n            ||<\/span> (<\/span>  (<\/span>   pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fDesiredInterruptWindows\n                   ||<\/span> pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fCurrentInterruptWindows !=<\/span> pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fDesiredInterruptWindows)<\/span>\n                &&<\/span> pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags !=<\/span> VID_MSHAGN_F_GET_NEXT_MESSAGE)<\/span>\n           )<\/span>\n        { \n   <\/span>\n            int<\/span> rc2 =<\/span> nemR0WinExportState<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> &<\/span>pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx)<\/span>;<\/span>\n        }<\/span>\n        \/\/\u8fd0\u884cGuestOS\u4ee3\u7801<\/span>\n        uint64_t<\/span>       offDeltaIgnored;<\/span>\n        uint64_t<\/span> const<\/span> nsNextTimerEvt =<\/span> TMTimerPollGIP<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> &<\/span>offDeltaIgnored)<\/span>;<\/span>\n        \/\/\u5982\u679c\u6709\u6807\u8bb0\u9700\u8981\u8fd4\u56deR3\uff0c\u5219\u4e0d\u80fd\u8fdb\u5165GuestOS<\/span>\n        if<\/span> (<\/span>   !<\/span>VM_FF_IS_ANY_SET<\/span>(<\/span>pVM,<\/span> VM_FF_EMT_RENDEZVOUS |<\/span> VM_FF_TM_VIRTUAL_SYNC)<\/span>\n            &&<\/span> !<\/span>VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_HM_TO_R3_MASK)<\/span>)<\/span>\n        { \n   <\/span>\n            if<\/span> (<\/span>pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags)<\/span>\n            { \n   <\/span> \n                \/\/\u662f\u5426\u6709\u6ca1\u6709\u5904\u7406\u5b8c\u7684\u65f6\u95f4\uff0c\u5982\u679c\u6709\uff0c\u4e0d\u80fd\u8fdb\u5165GuestOS\uff0c\u7ee7\u7eed\u5faa\u73af<\/span>\n            }<\/span>\n            else<\/span>\n            { \n   <\/span>\n                pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>uIoCtlBuf.<\/span>idCpu =<\/span> pVCpu-<\/span>><\/span>idCpu;<\/span>\n                \/\/\u8fd0\u884cGuestOS\u4ee3\u7801<\/span>\n                NTSTATUS rcNt =<\/span> nemR0NtPerformIoControl<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> pVM-<\/span>><\/span>nemr0.<\/span>s.<\/span>IoCtlStartVirtualProcessor.<\/span>uFunction,<\/span>\n                                                        &<\/span>pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>uIoCtlBuf.<\/span>idCpu,<\/span> sizeof<\/span>(<\/span>pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>uIoCtlBuf.<\/span>idCpu)<\/span>,<\/span>\n                                                        NULL<\/span>,<\/span> 0<\/span>)<\/span>;<\/span>\n                                      VERR_NEM_IPE_5)<\/span>;<\/span>\n                \/\/\u6709VMExit\u4e8b\u4ef6\uff0c\u6807\u8bb0\u9700\u8981\u83b7\u53d6VMExit\u4e8b\u4ef6<\/span>\n                pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags =<\/span> VID_MSHAGN_F_GET_NEXT_MESSAGE;<\/span>\n            }<\/span>\n            \/\/\u8bbe\u7f6e\u5f53\u524dVCPU\u72b6\u6001\u6210NEM WAIT\u72b6\u6001<\/span>\n            if<\/span> (<\/span>VMCPU_CMPXCHG_STATE<\/span>(<\/span>pVCpu,<\/span> VMCPUSTATE_STARTED_EXEC_NEM_WAIT,<\/span> VMCPUSTATE_STARTED_EXEC_NEM)<\/span>)<\/span>\n            { \n   <\/span>\n                \/\/\u8ba1\u7b97\u8fd0\u884c\u65f6\u95f4<\/span>\n                uint64_t<\/span> const<\/span>  nsNow           =<\/span> RTTimeNanoTS<\/span>(<\/span>)<\/span>;<\/span>\n                int64_t<\/span> const<\/span>   cNsNextTimerEvt =<\/span> nsNow -<\/span> nsNextTimerEvt;<\/span>\n                uint32_t<\/span>        cMsWait;<\/span>\n                if<\/span> (<\/span>cNsNextTimerEvt <<\/span> 100000<\/span> \/* ns *\/<\/span>)<\/span>\n                    cMsWait =<\/span> 0<\/span>;<\/span>\n                else<\/span> if<\/span> (<\/span>(<\/span>uint64_t<\/span>)<\/span>cNsNextTimerEvt <<\/span> RT_NS_1SEC)<\/span>\n                { \n   <\/span>\n                    if<\/span> (<\/span>(<\/span>uint32_t<\/span>)<\/span>cNsNextTimerEvt <<\/span> 2<\/span>*<\/span>RT_NS_1MS)<\/span>\n                        cMsWait =<\/span> 1<\/span>;<\/span>\n                    else<\/span>\n                        cMsWait =<\/span> (<\/span>(<\/span>uint32_t<\/span>)<\/span>cNsNextTimerEvt -<\/span> 100000<\/span> \/*ns*\/<\/span>)<\/span> \/<\/span> RT_NS_1MS;<\/span>\n                }<\/span>\n                else<\/span>\n                    cMsWait =<\/span> RT_MS_1SEC;<\/span>\n                \/\/\u8c03\u7528MessageSlotHandleAndGetNext\u83b7\u53d6VMExit\u4fe1\u606f<\/span>\n                pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>uIoCtlBuf.<\/span>MsgSlotHandleAndGetNext.<\/span>iCpu     =<\/span> pVCpu-<\/span>><\/span>idCpu;<\/span>\n                pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>uIoCtlBuf.<\/span>MsgSlotHandleAndGetNext.<\/span>fFlags   =<\/span> pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags;<\/span>\n                pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>uIoCtlBuf.<\/span>MsgSlotHandleAndGetNext.<\/span>cMillies =<\/span> cMsWait;<\/span>\n                NTSTATUS rcNt =<\/span> nemR0NtPerformIoControl<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> pVM-<\/span>><\/span>nemr0.<\/span>s.<\/span>IoCtlMessageSlotHandleAndGetNext.<\/span>uFunction,<\/span>\n                                                        &<\/span>pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>uIoCtlBuf.<\/span>MsgSlotHandleAndGetNext,<\/span>\n                                                        pVM-<\/span>><\/span>nemr0.<\/span>s.<\/span>IoCtlMessageSlotHandleAndGetNext.<\/span>cbInput,<\/span>\n                                                        NULL<\/span>,<\/span> 0<\/span>)<\/span>;<\/span>\n                \/\/\u8bbe\u7f6e\u5f53\u524dVCPU\u72b6\u6001\u6210NEM STARTED_EXEC \u72b6\u6001\uff0c\u51c6\u5907\u4e0b\u4e00\u4e2a\u5faa\u73af<\/span>\n                VMCPU_CMPXCHG_STATE<\/span>(<\/span>pVCpu,<\/span> VMCPUSTATE_STARTED_EXEC_NEM,<\/span> VMCPUSTATE_STARTED_EXEC_NEM_WAIT)<\/span>;<\/span>\n                if<\/span> (<\/span>rcNt ==<\/span> STATUS_SUCCESS)<\/span>\n                { \n   <\/span>\n                    \/\/\u83b7\u53d6VMExit\u4fe1\u606f\u6210\u529f\uff0c\u6ca1\u6709VMExit\u4fe1\u606f\u518d\u83b7\u53d6\u4e86<\/span>\n                    \/\/ \u5904\u7406VMExit\uff0c\u4e0b\u4e00\u7bc7\u91cc\u4ecb\u7ecd\u8fd9\u4e2a\u51fd\u6570<\/span>\n                    rcStrict =<\/span> nemHCWinHandleMessage<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> pMappingHeader)<\/span>;<\/span>\n                    \/\/\u5df2\u7ecf\u83b7\u53d6\u4e86VMExit\u4fe1\u606f\uff0c\u53bb\u6389\u8fd9\u4e2aflag<\/span>\n                    pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags |<\/span>=<\/span> VID_MSHAGN_F_HANDLE_MESSAGE;<\/span>\n                    if<\/span> (<\/span>rcStrict ==<\/span> VINF_SUCCESS)<\/span>\n                    { \n   <\/span> \/* hopefully likely *\/<\/span> }<\/span>\n                    else<\/span>\n                    { \n   <\/span>\n                        \/\/\u5904\u7406\u5931\u8d25\uff0c\u8fd4\u56deR3<\/span>\n                        break<\/span>;<\/span>\n                    }<\/span>\n                }<\/span>\n                else<\/span>\n                { \n   <\/span>\n                    \/\/\u83b7\u53d6VMExit\u4fe1\u606f\u5931\u8d25\uff0c\u6807\u8bb0\u9700\u8981\u518d\u6b21\u83b7\u53d6 \uff08\u9000\u51fa\u5faa\u73af\u4e4b\u540e\u5148\u505c\u6b62VCPU\u518d\u83b7\u53d6\u4e00\u6b21\uff09<\/span>\n                    pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags =<\/span> VID_MSHAGN_F_GET_NEXT_MESSAGE;<\/span>\n                }<\/span>\n                \/\/\u5982\u679c\u6ca1\u6709\u88ab\u8bbe\u7f6eVM_FF_HP_R0_PRE_HM_MASK\uff0c\u7ee7\u7eed\u6267\u884cGuestOS\uff0c\u5982\u679c\u6709\uff0c\u9000\u51fa\u8fd4\u56de\u5230R3\u5904\u7406<\/span>\n                \/\/TODO\uff1a\u8fd9\u4e2a\u662f\u4e2a\u4ec0\u4e48flags\uff1f<\/span>\n                if<\/span> (<\/span>   !<\/span>VM_FF_IS_ANY_SET<\/span>(<\/span>   pVM,<\/span>   !<\/span>fSingleStepping ?<\/span> VM_FF_HP_R0_PRE_HM_MASK    :<\/span> VM_FF_HP_R0_PRE_HM_STEP_MASK)<\/span>\n                    &&<\/span> !<\/span>VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> !<\/span>fSingleStepping ?<\/span> VMCPU_FF_HP_R0_PRE_HM_MASK :<\/span> VMCPU_FF_HP_R0_PRE_HM_STEP_MASK)<\/span> )<\/span>\n                    continue<\/span>;<\/span>\n\t\t  }<\/span>\n        }<\/span>    \n    }<\/span>\/\/end of for<\/span>\n    \n    if<\/span> (<\/span>pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags ==<\/span> VID_MSHAGN_F_GET_NEXT_MESSAGE)<\/span>\n    { \n   <\/span>\n        \/\/\u505c\u6b62VCPU\u5e76\u4e14\u5904\u7406VMExit\u4fe1\u606f \uff08\u4e0b\u4e00\u7bc7\u91cc\u4ecb\u7ecd\u8fd9\u4e2a\u51fd\u6570\uff09<\/span>\n        pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fHandleAndGetFlags =<\/span> 0<\/span>;<\/span>\n        rcStrict =<\/span> nemHCWinStopCpu<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> rcStrict,<\/span> pMappingHeader)<\/span>;<\/span>\n    }<\/span>\n    \/\/VCPU\u72b6\u6001\u53d8\u6210STARTED<\/span>\n    if<\/span> (<\/span>!<\/span>VMCPU_CMPXCHG_STATE<\/span>(<\/span>pVCpu,<\/span> VMCPUSTATE_STARTED,<\/span> VMCPUSTATE_STARTED_EXEC_NEM)<\/span>)<\/span>\n        VMCPU_CMPXCHG_STATE<\/span>(<\/span>pVCpu,<\/span> VMCPUSTATE_STARTED,<\/span> VMCPUSTATE_STARTED_EXEC_NEM_CANCELED)<\/span>;<\/span>\n    \/\/\u4ecehypervisor\u91cc\u83b7\u53d6GuestOS\u5bc4\u5b58\u5668\u76f8\u5173\u4fe1\u606f\uff0c\u4e3a\u8fd4\u56deR3\u4e4b\u540e\u5904\u7406\u51c6\u5907\u73af\u5883<\/span>\n    if<\/span> (<\/span>pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn &<\/span> (<\/span>CPUMCTX_EXTRN_ALL |<\/span> (<\/span>CPUMCTX_EXTRN_NEM_WIN_MASK &<\/span> ~<\/span>CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT)<\/span>)<\/span>)<\/span>\n    { \n   <\/span>\n        \/\/\u6807\u8bb0\u9700\u8981\u83b7\u53d6\u4e2d\u65ad\u76f8\u5173\u4fe1\u606f<\/span>\n        uint64_t<\/span> fImport =<\/span> IEM_CPUMCTX_EXTRN_MUST_MASK |<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT |<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_NMI;<\/span>\n        if<\/span> (<\/span>   (<\/span>rcStrict >=<\/span> VINF_EM_FIRST &&<\/span> rcStrict <=<\/span> VINF_EM_LAST)<\/span>\n            ||<\/span> RT_FAILURE<\/span>(<\/span>rcStrict)<\/span>)<\/span>\n            \/\/\u8fd0\u884c\u9519\u8bef\uff0c\u83b7\u53d6\u6240\u6709\u5bc4\u5b58\u5668<\/span>\n            fImport =<\/span> CPUMCTX_EXTRN_ALL |<\/span> (<\/span>CPUMCTX_EXTRN_NEM_WIN_MASK &<\/span> ~<\/span>CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT)<\/span>;<\/span>\n        else<\/span> if<\/span> (<\/span>   rcStrict ==<\/span> VINF_IOM_R3_IOPORT_COMMIT_WRITE\n                 ||<\/span> rcStrict ==<\/span> VINF_EM_PENDING_R3_IOPORT_WRITE)<\/span>\n            \/\/\u9700\u8981R3\u5904\u7406IO\u5199\u64cd\u4f5c\uff0c\u83b7\u53d6cs\/rip\/rflags\/\u4e2d\u65ad\u5c4f\u853d\u4f4d\u7b49\u4fe1\u606f<\/span>\n            fImport =<\/span> CPUMCTX_EXTRN_RIP |<\/span> CPUMCTX_EXTRN_CS |<\/span> CPUMCTX_EXTRN_RFLAGS |<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT;<\/span>\n        else<\/span> if<\/span> (<\/span>rcStrict ==<\/span> VINF_EM_PENDING_R3_IOPORT_READ)<\/span>\n            \/\/\u9700\u8981R3\u5904\u7406IO\u8bfb\u64cd\u4f5c\uff0c\u83b7\u53d6rax\/cs\/rip\/rflags\/\u4e2d\u65ad\u5c4f\u853d\u4f4d\u7b49\u4fe1\u606f<\/span>\n            fImport =<\/span> CPUMCTX_EXTRN_RAX |<\/span> CPUMCTX_EXTRN_RIP |<\/span> CPUMCTX_EXTRN_CS |<\/span> CPUMCTX_EXTRN_RFLAGS |<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT;<\/span>\n        else<\/span> if<\/span> (<\/span>VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_INTERRUPT_PIC |<\/span> VMCPU_FF_INTERRUPT_APIC\n                                          |<\/span> VMCPU_FF_INTERRUPT_NMI |<\/span> VMCPU_FF_INTERRUPT_SMI)<\/span>)<\/span>\n            \/\/\u6709pending\u4e2d\u65ad\uff0c\u83b7\u53d6\u4e2d\u65ad\u76f8\u5173\u4fe1\u606f<\/span>\n            fImport |<\/span>=<\/span> IEM_CPUMCTX_EXTRN_XCPT_MASK;<\/span>\n        \n        if<\/span> (<\/span>pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn &<\/span> fImport)<\/span>\n        { \n   <\/span>\n            \/\/\u8c03\u7528IOCTL<\/span>\n            int<\/span> rc2 =<\/span> nemR0WinImportState<\/span>(<\/span>pVM,<\/span> pVCpu,<\/span> &<\/span>pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx,<\/span> fImport |<\/span> CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT,<\/span>\n                                          true<\/span> \/*fCanUpdateCr3*\/<\/span>)<\/span>;<\/span>\n            if<\/span> (<\/span>RT_SUCCESS<\/span>(<\/span>rc2)<\/span>)<\/span>\n                pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn &<\/span>=<\/span> ~<\/span>fImport;<\/span>\n            else<\/span> if<\/span> (<\/span>rc2 ==<\/span> VERR_NEM_FLUSH_TLB)<\/span>\n            { \n   <\/span>\n                pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn &<\/span>=<\/span> ~<\/span>fImport;<\/span>\n                if<\/span> (<\/span>rcStrict ==<\/span> VINF_SUCCESS ||<\/span> rcStrict ==<\/span> -<\/span>rc2)<\/span>\n                    rcStrict =<\/span> -<\/span>rc2;<\/span>\n                else<\/span>\n                { \n   <\/span>\n                    pVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>rcPending =<\/span> -<\/span>rc2;<\/span>\n                }<\/span>\n            }<\/span>\n            else<\/span> if<\/span> (<\/span>RT_SUCCESS<\/span>(<\/span>rcStrict)<\/span>)<\/span>\n                rcStrict =<\/span> rc2;<\/span>\n            if<\/span> (<\/span>!<\/span>(<\/span>pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn &<\/span> (<\/span>CPUMCTX_EXTRN_ALL |<\/span> (<\/span>CPUMCTX_EXTRN_NEM_WIN_MASK &<\/span> ~<\/span>CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT)<\/span>)<\/span>)<\/span>)<\/span>\n                pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn =<\/span> 0<\/span>;<\/span>\n        }<\/span>\n    }<\/span>\n}<\/span>\n<\/code><\/pre>\n

            emR3NemForcedActions<\/h4>\n
            static<\/span> int<\/span> emR3NemForcedActions<\/span>(<\/span>PVM pVM,<\/span> PVMCPU pVCpu)<\/span>\n{ \n   <\/span>\n    \/\/\u4e0d\u5904\u7406sync cr3\u7684\u5904\u7406\uff1f<\/span>\n    if<\/span> (<\/span>VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_PGM_SYNC_CR3 |<\/span> VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL)<\/span>)<\/span>\n    { \n   <\/span>\n        VMCPU_FF_CLEAR_MASK<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_PGM_SYNC_CR3 |<\/span> VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL)<\/span>;<\/span>\n    }<\/span>\n    \/\/\u5185\u5b58\u4e0d\u591f\uff0c\u9700\u8981\u5206\u914d\u5185\u5b58<\/span>\n    if<\/span> (<\/span>VM_FF_IS_PENDING_EXCEPT<\/span>(<\/span>pVM,<\/span> VM_FF_PGM_NEED_HANDY_PAGES,<\/span> VM_FF_PGM_NO_MEMORY)<\/span>)<\/span>\n    { \n   <\/span>\n        \/\/\u5206\u914d\u5185\u5b58\uff0c\u5982\u679c\u7533\u8bf7\u6210\u529f\uff0c\u4f1aclear\u6389VM_FF_PGM_NO_MEMORY flags<\/span>\n        int<\/span> rc =<\/span> PGMR3PhysAllocateHandyPages<\/span>(<\/span>pVM)<\/span>;<\/span>\n        if<\/span> (<\/span>RT_FAILURE<\/span>(<\/span>rc)<\/span>)<\/span>\n            return<\/span> rc;<\/span>\n    }<\/span>\n    \/\/\u5982\u679c\u8fd8\u662fno memory\uff0c\u8fd4\u56de\u9519\u8bef\u7801<\/span>\n    if<\/span> (<\/span>VM_FF_IS_SET<\/span>(<\/span>pVM,<\/span> VM_FF_PGM_NO_MEMORY)<\/span>)<\/span>\n        return<\/span> VINF_EM_NO_MEMORY;<\/span>\n    return<\/span> VINF_SUCCESS;<\/span>\n}<\/span>\n<\/code><\/pre>\n

            22.2 \u4eceGuestOS\u91cc\u83b7\u53d6\u548c\u5199\u5165\u5bc4\u5b58\u5668\u4fe1\u606f<\/h3>\n

            nemR0WinImportState<\/h4>\n

            \u4eceHypervisor\u91cc\u83b7\u53d6\u5bc4\u5b58\u5668\u7684\u503c<\/p>\n

            NEM_TMPL_STATIC int<\/span> nemR0WinImportState<\/span>(<\/span>PGVM pGVM,<\/span> PGVMCPU pGVCpu,<\/span> PCPUMCTX pCtx,<\/span> uint64_t<\/span> fWhat,<\/span> bool<\/span> fCanUpdateCr3)<\/span>\n{ \n   <\/span>\n    HV_INPUT_GET_VP_REGISTERS *<\/span>pInput =<\/span> (<\/span>HV_INPUT_GET_VP_REGISTERS *<\/span>)<\/span>pGVCpu-<\/span>><\/span>nemr0.<\/span>s.<\/span>HypercallData.<\/span>pbPage;<\/span>\n    pInput-<\/span>><\/span>PartitionId =<\/span> pGVM-<\/span>><\/span>nemr0.<\/span>s.<\/span>idHvPartition;<\/span>\n    pInput-<\/span>><\/span>VpIndex     =<\/span> pGVCpu-<\/span>><\/span>idCpu;<\/span>\n    pInput-<\/span>><\/span>fFlags      =<\/span> 0<\/span>;<\/span>\n    \n    \/\/\u8bbe\u7f6e\u6bcf\u4e2aregister\u7684\u540d\u5b57<\/span>\n    uintptr_t iReg =<\/span> 0<\/span>;<\/span>\n    if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_GPRS_MASK)<\/span>\n    { \n   <\/span>\n        if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_RAX)<\/span>\n            pInput-<\/span>><\/span>Names[<\/span>iReg++<\/span>]<\/span> =<\/span> HvX64RegisterRax;<\/span>\n        if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_RCX)<\/span>\n            pInput-<\/span>><\/span>Names[<\/span>iReg++<\/span>]<\/span> =<\/span> HvX64RegisterRcx;<\/span>\n        .<\/span>.<\/span>.<\/span>\n    }<\/span>\n    \/\/\u6bb5\u5bc4\u5b58\u5668<\/span>\n    if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_SREG_MASK)<\/span>\n    { \n   <\/span>\n        if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_CS)<\/span>\n            pInput-<\/span>><\/span>Names[<\/span>iReg++<\/span>]<\/span> =<\/span> HvX64RegisterCs;<\/span>\n    }<\/span>\n    .<\/span>.<\/span>.<\/span>\n    \/\/crx<\/span>\n    if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_CR_MASK)<\/span>\n    { \n   <\/span>\n        if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_CR0)<\/span>\n            pInput-<\/span>><\/span>Names[<\/span>iReg++<\/span>]<\/span> =<\/span> HvX64RegisterCr0;<\/span>\n      \t.<\/span>.<\/span>.<\/span>\n    }<\/span>\n  \tif<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_APIC_TPR)<\/span>\n        pInput-<\/span>><\/span>Names[<\/span>iReg++<\/span>]<\/span> =<\/span> HvX64RegisterCr8;<\/span>\n    \/\/xmm<\/span>\n  \tif<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_SSE_AVX)<\/span>\n    { \n   <\/span>\n        pInput-<\/span>><\/span>Names[<\/span>iReg++<\/span>]<\/span> =<\/span> HvX64RegisterXmm0;<\/span>\n        pInput-<\/span>><\/span>Names[<\/span>iReg++<\/span>]<\/span> =<\/span> HvX64RegisterXmm1\n    }<\/span>\n    .<\/span>.<\/span>.<\/span>\n    \/\/\u8c03\u7528hypercall\uff0c\u83b7\u53d6register\u91cc\u7684\u503c<\/span>\n    uint64_t<\/span> uResult =<\/span> g_pfnHvlInvokeHypercall<\/span>(<\/span>HV_MAKE_CALL_INFO<\/span>(<\/span>HvCallGetVpRegisters,<\/span> cRegs)<\/span>,<\/span>\n                                               pGVCpu-<\/span>><\/span>nemr0.<\/span>s.<\/span>HypercallData.<\/span>HCPhysPage,<\/span>\n                                               pGVCpu-<\/span>><\/span>nemr0.<\/span>s.<\/span>HypercallData.<\/span>HCPhysPage +<\/span> cbInput)<\/span>;<\/span>\n    \/\/\u62f7\u8d1d\u83b7\u53d6\u7684\u5bc4\u5b58\u5668\u503c\u5230CPUMCTX\u7ed3\u6784\u4f53\u91cc<\/span>\n  \tif<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_GPRS_MASK)<\/span>\n    { \n   <\/span>\n        if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_RAX)<\/span>\n        { \n   <\/span>\n            pCtx-<\/span>><\/span>rax =<\/span> paValues[<\/span>iReg++<\/span>]<\/span>.<\/span>Reg64;<\/span>\n        }<\/span>\n    }<\/span>\n    .<\/span>.<\/span>.<\/span>\n    if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_CR0)<\/span>\n    { \n   <\/span>\n      \/\/\u90e8\u5206\u5bc4\u5b58\u5668\u503c\u6539\u53d8\u4f1a\u6539\u53d8CPU\u7684\u884c\u4e3a\uff0c\u6240\u4ee5\u9700\u8981\u8c03\u7528\u76f8\u5e94\u7684API\u6539\u53d8CPU\u7684\u884c\u4e3a<\/span>\n      if<\/span> (<\/span>pCtx-<\/span>><\/span>cr0 !=<\/span> paValues[<\/span>iReg]<\/span>.<\/span>Reg64)<\/span>\n      { \n   <\/span>\n        CPUMSetGuestCR0<\/span>(<\/span>pGVCpu,<\/span> paValues[<\/span>iReg]<\/span>.<\/span>Reg64)<\/span>;<\/span>\n        fMaybeChangedMode =<\/span> true<\/span>;<\/span>\n      }<\/span>\n      iReg++<\/span>;<\/span>\n    }<\/span>\n    .<\/span>.<\/span>.<\/span>\n  \tif<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_EFER)<\/span>\n    { \n   <\/span>\n      \t\/\/efer\u5bc4\u5b58\u5668\u6539\u53d8<\/span>\n        if<\/span> (<\/span>paValues[<\/span>iReg]<\/span>.<\/span>Reg64 !=<\/span> pCtx-<\/span>><\/span>msrEFER)<\/span>\n        { \n   <\/span>\n          \t\/\/\u5982\u679c\u4fee\u6539\u4e86NXE\u4f4d\uff0c\u901a\u77e5PGM NX\u72b6\u6001\u6539\u53d8<\/span>\n            if<\/span> (<\/span>(<\/span>paValues[<\/span>iReg]<\/span>.<\/span>Reg64 ^<\/span> pCtx-<\/span>><\/span>msrEFER)<\/span> &<\/span> MSR_K6_EFER_NXE)<\/span>\n                PGMNotifyNxeChanged<\/span>(<\/span>pGVCpu,<\/span> RT_BOOL<\/span>(<\/span>paValues[<\/span>iReg]<\/span>.<\/span>Reg64 &<\/span> MSR_K6_EFER_NXE)<\/span>)<\/span>;<\/span>\n            pCtx-<\/span>><\/span>msrEFER =<\/span> paValues[<\/span>iReg]<\/span>.<\/span>Reg64;<\/span>\n            fMaybeChangedMode =<\/span> true<\/span>;<\/span>\n        }<\/span>\n        iReg++<\/span>;<\/span>\n    }<\/span>\n    .<\/span>.<\/span>.<\/span>\n   \tif<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_OTHER_MSRS)<\/span>\n    { \n   <\/span>\n        \/\/APIC Base\u6539\u53d8\uff0c\u9700\u8981\u8bbe\u7f6e\u865a\u62dfAPIC\u91cc\u7684base<\/span>\n        const<\/span> uint64_t<\/span> uOldBase =<\/span> APICGetBaseMsrNoCheck<\/span>(<\/span>pGVCpu)<\/span>;<\/span>\n        if<\/span> (<\/span>paValues[<\/span>iReg]<\/span>.<\/span>Reg64 !=<\/span> uOldBase)<\/span>\n        { \n   <\/span>\n            int<\/span> rc2 =<\/span> APICSetBaseMsr<\/span>(<\/span>pGVCpu,<\/span> paValues[<\/span>iReg]<\/span>.<\/span>Reg64)<\/span>;<\/span>\n        }<\/span>\n    }<\/span>\n    .<\/span>.<\/span>.<\/span>\n    \/\/\u8bbe\u7f6e\u4e2d\u65ad\u5c4f\u853d\u6807\u8bb0\u4f4d<\/span>\n    if<\/span> (<\/span>fWhat &<\/span> (<\/span>CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT |<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_NMI)<\/span>)<\/span>\n    { \n   <\/span>\n        if<\/span> (<\/span>!<\/span>(<\/span>pCtx-<\/span>><\/span>fExtrn &<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT)<\/span>)<\/span>\n        { \n   <\/span>\n            pGVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fLastInterruptShadow =<\/span> paValues[<\/span>iReg]<\/span>.<\/span>InterruptState.<\/span>InterruptShadow;<\/span>\n            if<\/span> (<\/span>paValues[<\/span>iReg]<\/span>.<\/span>InterruptState.<\/span>InterruptShadow)<\/span>\n                EMSetInhibitInterruptsPC<\/span>(<\/span>pGVCpu,<\/span> paValues[<\/span>iReg +<\/span> 1<\/span>]<\/span>.<\/span>Reg64)<\/span>;<\/span>\n            else<\/span>\n                VMCPU_FF_CLEAR<\/span>(<\/span>pGVCpu,<\/span> VMCPU_FF_INHIBIT_INTERRUPTS)<\/span>;<\/span>\n        }<\/span>\n        if<\/span> (<\/span>!<\/span>(<\/span>pCtx-<\/span>><\/span>fExtrn &<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_NMI)<\/span>)<\/span>\n        { \n   <\/span>\n            if<\/span> (<\/span>paValues[<\/span>iReg]<\/span>.<\/span>InterruptState.<\/span>NmiMasked)<\/span>\n                VMCPU_FF_SET<\/span>(<\/span>pGVCpu,<\/span> VMCPU_FF_BLOCK_NMIS)<\/span>;<\/span>\n            else<\/span>\n                VMCPU_FF_CLEAR<\/span>(<\/span>pGVCpu,<\/span> VMCPU_FF_BLOCK_NMIS)<\/span>;<\/span>\n        }<\/span>\n        fWhat |<\/span>=<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT |<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_NMI;<\/span>\n        iReg +<\/span>=<\/span> 2<\/span>;<\/span>\n  }<\/span>\n  \/\/\u8fd0\u884c\u6a21\u5f0f\u6539\u53d8\uff0c\u901a\u77e5PGM\u505a\u51fa\u5bf9\u5e94\u6539\u53d8<\/span>\n  int<\/span> rc =<\/span> VINF_SUCCESS;<\/span>\n  if<\/span> (<\/span>fMaybeChangedMode)<\/span>\n  { \n   <\/span>\n      rc =<\/span> PGMChangeMode<\/span>(<\/span>pGVCpu,<\/span> pCtx-<\/span>><\/span>cr0,<\/span> pCtx-<\/span>><\/span>cr4,<\/span> pCtx-<\/span>><\/span>msrEFER)<\/span>;<\/span>\n  }<\/span>\n  .<\/span>.<\/span>.<\/span>\n}<\/span>\n<\/code><\/pre>\n

            nemR0WinExportState<\/h4>\n

            \u628aCPUMCTX\u91cc\u7684\u5bc4\u5b58\u5668\u5199\u5165GuestOS\u91cc\uff0c\u539f\u7406\u548c\u4e0a\u9762ImportState\u7c7b\u4f3c\uff0c\u5199\u628a\u6240\u6709\u5bc4\u5b58\u5668\u7684\u540d\u5b57\/value\u5199\u5165HypercallData.pbPage\u91cc\uff0c\u7136\u540e\u8c03\u7528HvCallSetVpRegisters hypercall\u5199\u5165GuestOS\u5bc4\u5b58\u5668\u4fe1\u606f\uff0c\u76f8\u5173\u5bc4\u5b58\u5668\u7684\u5b9a\u4e49\u53ef\u4ee5\u53c2\u8003\u4e0b\u9762\u7684\u6587\u6863\uff1a<\/p>\n

            https:\/\/docs.microsoft.com\/en-us\/virtualization\/api\/hypervisor-platform\/funcs\/whvvirtualprocessordatatypes<\/p>\n

            Virtualbox\u5bf9\u5e94\u7684\u5934\u6587\u4ef6\u5b9a\u4e49\u5728 include\\iprt\\nt\\hyperv.h\u91cc<\/p>\n

            NEM_TMPL_STATIC int<\/span> nemR0WinExportState<\/span>(<\/span>PGVM pGVM,<\/span> PGVMCPU pGVCpu,<\/span> PCPUMCTX pCtx)<\/span>\n{ \n   <\/span>\n    HV_INPUT_SET_VP_REGISTERS *<\/span>pInput =<\/span> (<\/span>HV_INPUT_SET_VP_REGISTERS *<\/span>)<\/span>pGVCpu-<\/span>><\/span>nemr0.<\/span>s.<\/span>HypercallData.<\/span>pbPage;<\/span>\n    uint64_t<\/span> const<\/span> fWhat =<\/span> ~<\/span>pCtx-<\/span>><\/span>fExtrn &<\/span> (<\/span>CPUMCTX_EXTRN_ALL |<\/span> CPUMCTX_EXTRN_NEM_WIN_MASK)<\/span>;<\/span>\n    \/\/\u6839\u636efWhat\u91cc\u7684flag\uff0c\u5199\u5165\u9700\u8981\u4fee\u6539\u7684GuestOS\u5bc4\u5b58\u5668\u540d\u5b57\u548cvalue<\/span>\n    if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_GPRS_MASK)<\/span>\n    { \n   <\/span>\n        \/\/rax<\/span>\n        if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_RAX)<\/span>\n        { \n   <\/span>\n            HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64<\/span>(<\/span>&<\/span>pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>)<\/span>;<\/span>\n            pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Name                =<\/span> HvX64RegisterRax;<\/span>\n            pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Value.<\/span>Reg64         =<\/span> pCtx-<\/span>><\/span>rax;<\/span>\n            iReg++<\/span>;<\/span>\n        }<\/span>\n        .<\/span>.<\/span>.<\/span>\n    }<\/span>\n    \/\/\u6bb5\u5bc4\u5b58\u5668<\/span>\n    if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_SREG_MASK)<\/span>\n    { \n   <\/span>\n        if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_CS)<\/span>\n        { \n   <\/span>\n            COPY_OUT_SEG<\/span>(<\/span>iReg,<\/span> HvX64RegisterCs,<\/span>   pCtx-<\/span>><\/span>cs)<\/span>;<\/span>\n            iReg++<\/span>;<\/span>\n        }<\/span>\n        .<\/span>.<\/span>.<\/span>\n    }<\/span>\n    \/\/\u6709pending\u7684event\uff0c\u9700\u8981\u83b7\u53d6pending\u4e2d\u65ad\u4fe1\u606f\u548cevent vector<\/span>\n    if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT)<\/span>\n    { \n   <\/span>\n        HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64<\/span>(<\/span>&<\/span>pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>)<\/span>;<\/span>\n        pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Name                 =<\/span> HvRegisterPendingInterruption;<\/span>\n        pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Value.<\/span>Reg64          =<\/span> 0<\/span>;<\/span>\n        iReg++<\/span>;<\/span>\n    }<\/span>\n    \n    \/\/\u5982\u679c\u5c4f\u853d\u4e86\u4e2d\u65ad\u548cnmi\uff0c\u9700\u8981\u5199\u5165WHV_X64_INTERRUPT_STATE_REGISTER\u7684\u4fe1\u606f\uff08InterruptShadow\/NmiMasked\uff09<\/span>\n    if<\/span> (<\/span>   (<\/span>fWhat &<\/span> (<\/span>CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT |<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_NMI)<\/span>)<\/span>\n        ==<\/span>          (<\/span>CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT |<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_NMI)<\/span> )<\/span>\n    { \n   <\/span>\n        HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64<\/span>(<\/span>&<\/span>pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>)<\/span>;<\/span>\n        pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Name                 =<\/span> HvRegisterInterruptState;<\/span>\n        pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Value.<\/span>Reg64          =<\/span> 0<\/span>;<\/span>\n        if<\/span> (<\/span>   VMCPU_FF_IS_SET<\/span>(<\/span>pGVCpu,<\/span> VMCPU_FF_INHIBIT_INTERRUPTS)<\/span>\n            &&<\/span> EMGetInhibitInterruptsPC<\/span>(<\/span>pGVCpu)<\/span> ==<\/span> pCtx-<\/span>><\/span>rip)<\/span>\n            pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Value.<\/span>InterruptState.<\/span>InterruptShadow =<\/span> 1<\/span>;<\/span>\n        if<\/span> (<\/span>VMCPU_FF_IS_SET<\/span>(<\/span>pGVCpu,<\/span> VMCPU_FF_BLOCK_NMIS)<\/span>)<\/span>\n            pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Value.<\/span>InterruptState.<\/span>NmiMasked =<\/span> 1<\/span>;<\/span>\n        iReg++<\/span>;<\/span>\n    }<\/span>\n    \/\/\u5982\u679c\u5c4f\u853d\u4e86\u4e2d\u65ad\uff0c\u5199\u5165InterruptShadow\u4fe1\u606f<\/span>\n    else<\/span> if<\/span> (<\/span>fWhat &<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT)<\/span>\n    { \n   <\/span>\n        if<\/span> (<\/span>   pGVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fLastInterruptShadow\n            ||<\/span> (<\/span>   VMCPU_FF_IS_SET<\/span>(<\/span>pGVCpu,<\/span> VMCPU_FF_INHIBIT_INTERRUPTS)<\/span>\n                &&<\/span> EMGetInhibitInterruptsPC<\/span>(<\/span>pGVCpu)<\/span> ==<\/span> pCtx-<\/span>><\/span>rip)<\/span>)<\/span>\n        { \n   <\/span>\n            HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64<\/span>(<\/span>&<\/span>pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>)<\/span>;<\/span>\n            pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Name                 =<\/span> HvRegisterInterruptState;<\/span>\n            pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Value.<\/span>Reg64          =<\/span> 0<\/span>;<\/span>\n            if<\/span> (<\/span>   VMCPU_FF_IS_SET<\/span>(<\/span>pGVCpu,<\/span> VMCPU_FF_INHIBIT_INTERRUPTS)<\/span>\n                &&<\/span> EMGetInhibitInterruptsPC<\/span>(<\/span>pGVCpu)<\/span> ==<\/span> pCtx-<\/span>><\/span>rip)<\/span>\n                pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Value.<\/span>InterruptState.<\/span>InterruptShadow =<\/span> 1<\/span>;<\/span>\n            iReg++<\/span>;<\/span>\n        }<\/span>\n    }<\/span>\n    \/\/\u6709\u88ab\u5c4f\u853d\u7684\u4e2d\u65ad\uff0c\u5199\u5165WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER\u544a\u8bc9Guest\u4e2d\u65ad\u88ab\u5c4f\u853d\u4e86<\/span>\n    \/\/fDesiredInterruptWindows\u5728nemHCWinHandleInterruptFF\u91cc\u88ab\u590d\u5236<\/span>\n    uint8_t<\/span> const<\/span> fDesiredIntWin =<\/span> pGVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fDesiredInterruptWindows;<\/span>\n    if<\/span> (<\/span>   fDesiredIntWin\n        ||<\/span> pGVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fCurrentInterruptWindows !=<\/span> fDesiredIntWin)<\/span>\n    { \n   <\/span>\n        pGVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fCurrentInterruptWindows =<\/span> pGVCpu-<\/span>><\/span>nem.<\/span>s.<\/span>fDesiredInterruptWindows;<\/span>\n        HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64<\/span>(<\/span>&<\/span>pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>)<\/span>;<\/span>\n        pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Name                                         =<\/span> HvX64RegisterDeliverabilityNotifications;<\/span>\n        pInput-<\/span>><\/span>Elements[<\/span>iReg]<\/span>.<\/span>Value.<\/span>DeliverabilityNotifications.<\/span>AsUINT64   =<\/span> fDesiredIntWin;<\/span>\n        iReg++<\/span>;<\/span>\n    }<\/span>\n    \/\/\u5bc4\u5b58\u5668\u8bbe\u7f6e\u5b8c\u6bd5\uff0c\u8c03\u7528HvCallSetVpRegisters hyperV\u628a\u5bc4\u5b58\u5668\u5199\u5165GuestOS\u91cc<\/span>\n    uint64_t<\/span> uResult =<\/span> g_pfnHvlInvokeHypercall<\/span>(<\/span>HV_MAKE_CALL_INFO<\/span>(<\/span>HvCallSetVpRegisters,<\/span> iReg)<\/span>,<\/span>\n                                               pGVCpu-<\/span>><\/span>nemr0.<\/span>s.<\/span>HypercallData.<\/span>HCPhysPage,<\/span> 0<\/span> \/*GCPhysOutput*\/<\/span>)<\/span>;<\/span>\n    pCtx-<\/span>><\/span>fExtrn |<\/span>=<\/span> CPUMCTX_EXTRN_ALL |<\/span> CPUMCTX_EXTRN_NEM_WIN_MASK |<\/span> CPUMCTX_EXTRN_KEEPER_NEM;<\/span>\n    return<\/span> VINF_SUCCESS;<\/span>\n}<\/span>\n<\/code><\/pre>\n

            22.3\u4e2d\u65ad\u5904\u7406<\/h3>\n

            nemHCWinHandleInterruptFF<\/h4>\n

            \u5904\u7406pending\u4e2d\u65ad<\/p>\n

            NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleInterruptFF<\/span>(<\/span>PVMCC pVM,<\/span> PVMCPUCC pVCpu,<\/span> uint8_t<\/span> *<\/span>pfInterruptWindows)<\/span>\n{ \n   <\/span>\n    \/\/\u5982\u679c\u6709pending\u4e2d\u7684\uff0c\u628a\u4e2d\u65ad\u4eceAPIC\u7684PIB\u5185\u5b58\u91cc\u66f4\u65b0\u5230IRR\u91cc\u6392\u961f<\/span>\n    if<\/span> (<\/span>VMCPU_FF_TEST_AND_CLEAR<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_UPDATE_APIC)<\/span>)<\/span>\n    { \n   <\/span>\n       \t\/\/\u5177\u4f53\u5b9e\u73b0\u89c1\u524d\u9762APIC\u4e00\u7bc7<\/span>\n        APICUpdatePendingInterrupts<\/span>(<\/span>pVCpu)<\/span>;<\/span>\n        \/\/\u5982\u679c\u6ca1\u6709\u4e2d\u65ad\u9700\u8981\u5904\u7406\uff0c\u76f4\u63a5\u8fd4\u56de<\/span>\n        if<\/span> (<\/span>!<\/span>VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_INTERRUPT_APIC |<\/span> VMCPU_FF_INTERRUPT_PIC\n                                      |<\/span> VMCPU_FF_INTERRUPT_NMI  |<\/span> VMCPU_FF_INTERRUPT_SMI)<\/span>)<\/span>\n            return<\/span> VINF_SUCCESS;<\/span>\n    }<\/span>\n   \t\/\/\u73b0\u5728\u65e0\u6cd5\u5904\u7406SMI\u4e2d\u65ad\uff0c\u8fd4\u56de\u9519\u8bef<\/span>\n    AssertReturn<\/span>(<\/span>!<\/span>VMCPU_FF_IS_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_INTERRUPT_SMI)<\/span>,<\/span> VERR_NEM_IPE_0)<\/span>;<\/span>\n    \/\/\u662f\u5426\u6709nmi\u4e2d\u65ad<\/span>\n    bool<\/span> const<\/span> fPendingNmi =<\/span> VMCPU_FF_IS_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_INTERRUPT_NMI)<\/span>;<\/span>\n    \/\/\u4ece\u8c03\u7528hypercall\u83b7\u53d6GuestOS\u76f8\u5173\u5bc4\u5b58\u5668\u503c<\/span>\n    uint64_t<\/span>   fNeedExtrn  =<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT |<\/span> CPUMCTX_EXTRN_RIP |<\/span> CPUMCTX_EXTRN_RFLAGS |<\/span> (<\/span>fPendingNmi ?<\/span> CPUMCTX_EXTRN_NEM_WIN_INHIBIT_NMI :<\/span> 0<\/span>)<\/span>;<\/span>\n    if<\/span> (<\/span>pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>fExtrn &<\/span> fNeedExtrn)<\/span>\n    { \n   <\/span>\n        VBOXSTRICTRC rcStrict =<\/span> nemHCWinImportStateIfNeededStrict<\/span>(<\/span>pVCpu,<\/span> NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM_XCPT,<\/span> \"IntFF\"<\/span>)<\/span>;<\/span>\n        if<\/span> (<\/span>rcStrict !=<\/span> VINF_SUCCESS)<\/span>\n            return<\/span> rcStrict;<\/span>\n    }<\/span>\n    \/\/\u5982\u679c\u5f00\u542f\u4e86\u5c4f\u853d\u4e2d\u65ad\u800c\u4e14\u5f53\u524drip\u662f\u53d1\u751f\u4e2d\u65ad\u7684RIP\uff08\u5f53\u524d\u53d1\u751f\u7684\u4e2d\u65ad\u88ab\u5c4f\u853d\u4e86\uff09<\/span>\n    bool<\/span> const<\/span> fInhibitInterrupts =<\/span> VMCPU_FF_IS_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_INHIBIT_INTERRUPTS)<\/span>\n                                 &&<\/span> EMGetInhibitInterruptsPC<\/span>(<\/span>pVCpu)<\/span> ==<\/span> pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>rip;<\/span>\n    \n    \/\/\u6709pending\u7684nmi\u4e2d\u65ad\uff0c\u8c03\u7528IEM\u91cc\u51fd\u6570\u6a21\u62df\u6267\u884c\u6ce8\u5165\u4e2d\u65ad<\/span>\n    if<\/span> (<\/span>fPendingNmi)<\/span>\n    { \n   <\/span>\n        if<\/span> (<\/span>   !<\/span>fInhibitInterrupts\n            &&<\/span> !<\/span>VMCPU_FF_IS_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_BLOCK_NMIS)<\/span>)<\/span>\n        { \n   <\/span>\n            VBOXSTRICTRC rcStrict =<\/span> nemHCWinImportStateIfNeededStrict<\/span>(<\/span>pVCpu,<\/span> NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM_XCPT,<\/span> \"NMI\"<\/span>)<\/span>;<\/span>\n            if<\/span> (<\/span>rcStrict ==<\/span> VINF_SUCCESS)<\/span>\n            { \n   <\/span>\n                VMCPU_FF_CLEAR<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_INTERRUPT_NMI)<\/span>;<\/span>\n                rcStrict =<\/span> IEMInjectTrap<\/span>(<\/span>pVCpu,<\/span> X86_XCPT_NMI,<\/span> TRPM_HARDWARE_INT,<\/span> 0<\/span>,<\/span> 0<\/span>,<\/span> 0<\/span>)<\/span>;<\/span>\n            }<\/span>\n            return<\/span> rcStrict;<\/span>\n        }<\/span>\n        \/\/\u4e2d\u65ad\u88ab\u5c4f\u853d\u4e86<\/span>\n        *<\/span>pfInterruptWindows |<\/span>=<\/span> NEM_WIN_INTW_F_NMI;<\/span>\n    }<\/span>\n\n    \/\/\u6709APIC\/PIC\u4e2d\u65ad<\/span>\n    if<\/span> (<\/span>VMCPU_FF_IS_ANY_SET<\/span>(<\/span>pVCpu,<\/span> VMCPU_FF_INTERRUPT_APIC |<\/span> VMCPU_FF_INTERRUPT_PIC)<\/span>)<\/span>\n    { \n   <\/span>\n        if<\/span> (<\/span>   !<\/span>fInhibitInterrupts\n            &&<\/span> pVCpu-<\/span>><\/span>cpum.<\/span>GstCtx.<\/span>rflags.<\/span>Bits.<\/span>u1IF)<\/span>\n        { \n   <\/span>\n            \/\/\u83b7\u53d6\u9700\u8981\u7684\u5bc4\u5b58\u5668\u4fe1\u606f<\/span>\n            VBOXSTRICTRC rcStrict =<\/span> nemHCWinImportStateIfNeededStrict<\/span>(<\/span>pVCpu,<\/span> NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM_XCPT,<\/span> \"NMI\"<\/span>)<\/span>;<\/span>\n            if<\/span> (<\/span>rcStrict ==<\/span> VINF_SUCCESS)<\/span>\n            { \n   <\/span>\n                \/\/\u4eceAPIC\u91cc\u83b7\u53d6\u4e00\u4e2a\u4f18\u5148\u7ea7\u6700\u9ad8\u7684\u4e2d\u65ad\uff0c\u79fb\u52a8\u5230APIC\u8bbe\u5907\u7684ISR\u961f\u5217\u4e2d<\/span>\n                uint8_t<\/span> bInterrupt;<\/span>\n                int<\/span> rc =<\/span> PDMGetInterrupt<\/span>(<\/span>pVCpu,<\/span> &<\/span>bInterrupt)<\/span>;<\/span>\n                if<\/span> (<\/span>RT_SUCCESS<\/span>(<\/span>rc)<\/span>)<\/span>\n                { \n   <\/span>\n                    \/\/\u6a21\u62df\u6267\u884c\u6ce8\u5165\u4e2d\u65ad<\/span>\n                    rcStrict =<\/span> IEMInjectTrap<\/span>(<\/span>pVCpu,<\/span> bInterrupt,<\/span> TRPM_HARDWARE_INT,<\/span> 0<\/span>,<\/span> 0<\/span>,<\/span> 0<\/span>)<\/span>;<\/span>\n                }<\/span>\n                \/\/\u4e2d\u65ad\u4f18\u5148\u7ea7\u5c0f\u4e8e\u5f53\u524dVCPU\u8fd0\u884c\u4f18\u5148\u7ea7\uff0c\u88ab\u5c4f\u853d\u4e86\uff0c\u8bb0\u5f55\u4e0b\u4fe1\u606f<\/span>\n                else<\/span> if<\/span> (<\/span>rc ==<\/span> VERR_APIC_INTR_MASKED_BY_TPR)<\/span>\n                { \n   <\/span>\n                    *<\/span>pfInterruptWindows |<\/span>=<\/span> (<\/span>bInterrupt >><\/span> 4<\/span> \/*??*\/<\/span>)<\/span> <<<\/span> NEM_WIN_INTW_F_PRIO_SHIFT;<\/span>\n                }<\/span>\n            }<\/span>\n            return<\/span> rcStrict;<\/span>\n        }<\/span>\n        \/\/\u4e2d\u65ad\u88ab\u5c4f\u853d\u4e86\uff0c\u8bb0\u5f55\u4e0b\u4fe1\u606f<\/span>\n        *<\/span>pfInterruptWindows |<\/span>=<\/span> NEM_WIN_INTW_F_REGULAR;<\/span>\n    }<\/span>\n}<\/span>\n<\/code><\/pre>\n

            <\/h3>\n","protected":false},"excerpt":{"rendered":"Virtualbox\u6e90\u7801\u5206\u679022 NEM(Hyper-V\u517c\u5bb9)3 Emulation ThreadNativeexecutionmanager\uff08EmulationThread\uff09\u6587\u7ae0\u76ee\u5f55Nativeexecuti...","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"_links":{"self":[{"href":"https:\/\/mushiming.com\/wp-json\/wp\/v2\/posts\/6407"}],"collection":[{"href":"https:\/\/mushiming.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mushiming.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mushiming.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mushiming.com\/wp-json\/wp\/v2\/comments?post=6407"}],"version-history":[{"count":0,"href":"https:\/\/mushiming.com\/wp-json\/wp\/v2\/posts\/6407\/revisions"}],"wp:attachment":[{"href":"https:\/\/mushiming.com\/wp-json\/wp\/v2\/media?parent=6407"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mushiming.com\/wp-json\/wp\/v2\/categories?post=6407"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mushiming.com\/wp-json\/wp\/v2\/tags?post=6407"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}