Index: /trunk/include/VBox/em.h
===================================================================
--- /trunk/include/VBox/em.h	(revision 25815)
+++ /trunk/include/VBox/em.h	(revision 25816)
@@ -184,4 +184,5 @@
 VMMR3DECL(int)      EMR3InitCPU(PVM pVM);
 VMMR3DECL(void)     EMR3Relocate(PVM pVM);
+VMMR3DECL(void)     EMR3ResetCpu(PVMCPU pVCpu);
 VMMR3DECL(void)     EMR3Reset(PVM pVM);
 VMMR3DECL(int)      EMR3Term(PVM pVM);
Index: /trunk/include/VBox/hwaccm.h
===================================================================
--- /trunk/include/VBox/hwaccm.h	(revision 25815)
+++ /trunk/include/VBox/hwaccm.h	(revision 25816)
@@ -144,4 +144,5 @@
 VMMR3DECL(int)          HWACMMR3DisablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem);
 VMMR3DECL(int)          HWACCMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMR3DECL(void)         HWACCMR3ResetCPU(PVMCPU pVCpu);
 
 /** @} */
Index: /trunk/include/VBox/pdmapi.h
===================================================================
--- /trunk/include/VBox/pdmapi.h	(revision 25815)
+++ /trunk/include/VBox/pdmapi.h	(revision 25816)
@@ -66,4 +66,5 @@
 VMMR3DECL(int)  PDMR3Init(PVM pVM);
 VMMR3DECL(void) PDMR3PowerOn(PVM pVM);
+VMMR3DECL(void) PDMR3ResetCpu(PVMCPU pVCpu);
 VMMR3DECL(void) PDMR3Reset(PVM pVM);
 VMMR3DECL(void) PDMR3Suspend(PVM pVM);
Index: /trunk/include/VBox/pgm.h
===================================================================
--- /trunk/include/VBox/pgm.h	(revision 25815)
+++ /trunk/include/VBox/pgm.h	(revision 25816)
@@ -444,4 +444,5 @@
 VMMR3DECL(int)      PGMR3InitFinalize(PVM pVM);
 VMMR3DECL(void)     PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3DECL(void)     PGMR3ResetCpu(PVM pVM, PVMCPU pVCpu);
 VMMR3DECL(void)     PGMR3Reset(PVM pVM);
 VMMR3DECL(int)      PGMR3Term(PVM pVM);
Index: /trunk/include/VBox/trpm.h
===================================================================
--- /trunk/include/VBox/trpm.h	(revision 25815)
+++ /trunk/include/VBox/trpm.h	(revision 25816)
@@ -100,4 +100,5 @@
 VMMR3DECL(int)      TRPMR3Init(PVM pVM);
 VMMR3DECL(void)     TRPMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3DECL(void)     TRPMR3ResetCpu(PVMCPU pVCpu);
 VMMR3DECL(void)     TRPMR3Reset(PVM pVM);
 VMMR3DECL(int)      TRPMR3Term(PVM pVM);
Index: /trunk/include/VBox/vmapi.h
===================================================================
--- /trunk/include/VBox/vmapi.h	(revision 25815)
+++ /trunk/include/VBox/vmapi.h	(revision 25816)
@@ -408,4 +408,8 @@
 VMMR3DECL(RTNATIVETHREAD)   VMR3GetVMCPUNativeThreadU(PUVM pUVM);
 
+VMMR3DECL(int)              VMR3GetCPUCoreAndPackageIdFromCPUId(PVM pVM, VMCPUID idCpu, uint32_t *pidCpuCore, uint32_t *pidCpuPackage);
+VMMR3DECL(int)              VMR3HotunplugCPU(PVM pVM, VMCPUID idCpu);
+VMMR3DECL(int)              VMR3HotplugCPU(PVM pVM, VMCPUID idCpu);
+
 /** @} */
 #endif /* IN_RING3 */
Index: /trunk/src/VBox/VMM/EM.cpp
===================================================================
--- /trunk/src/VBox/VMM/EM.cpp	(revision 25815)
+++ /trunk/src/VBox/VMM/EM.cpp	(revision 25816)
@@ -437,4 +437,17 @@
 }
 
+VMMR3DECL(void) EMR3ResetCpu(PVMCPU pVCpu)
+{
+    pVCpu->em.s.fForceRAW = false;
+
+    /* VMR3Reset may return VINF_EM_RESET or VINF_EM_SUSPEND, so transition
+        out of the HALTED state here so that enmPrevState doesn't end up as
+        HALTED when EMR3Execute returns. */
+    if (pVCpu->em.s.enmState == EMSTATE_HALTED)
+    {
+        Log(("EMR3ResetCpu: Cpu#%u %s -> %s\n", pVCpu->idCpu, emR3GetStateName(pVCpu->em.s.enmState), pVCpu->idCpu == 0 ? "EMSTATE_NONE" : "EMSTATE_WAIT_SIPI"));
+        pVCpu->em.s.enmState = pVCpu->idCpu == 0 ? EMSTATE_NONE : EMSTATE_WAIT_SIPI;
+    }
+}
 
 /**
@@ -449,14 +462,5 @@
     {
         PVMCPU pVCpu = &pVM->aCpus[i];
-        pVCpu->em.s.fForceRAW = false;
-
-        /* VMR3Reset may return VINF_EM_RESET or VINF_EM_SUSPEND, so transition
-           out of the HALTED state here so that enmPrevState doesn't end up as
-           HALTED when EMR3Execute returns. */
-        if (pVCpu->em.s.enmState == EMSTATE_HALTED)
-        {
-            Log(("EMR3Reset: Cpu#%u %s -> %s\n", i, emR3GetStateName(pVCpu->em.s.enmState), i == 0 ? "EMSTATE_NONE" : "EMSTATE_WAIT_SIPI"));
-            pVCpu->em.s.enmState = i == 0 ? EMSTATE_NONE : EMSTATE_WAIT_SIPI;
-        }
+        EMR3ResetCpu(pVCpu);
     }
 }
Index: /trunk/src/VBox/VMM/HWACCM.cpp
===================================================================
--- /trunk/src/VBox/VMM/HWACCM.cpp	(revision 25815)
+++ /trunk/src/VBox/VMM/HWACCM.cpp	(revision 25816)
@@ -1458,4 +1458,37 @@
 
 /**
+ * Resets a virtual CPU.
+ *
+ * @param pVCpu    The CPu to reset.
+ */
+VMMR3DECL(void) HWACCMR3ResetCPU(PVMCPU pVCpu)
+{
+    /* On first entry we'll sync everything. */
+    pVCpu->hwaccm.s.fContextUseFlags = HWACCM_CHANGED_ALL;
+
+    pVCpu->hwaccm.s.vmx.cr0_mask = 0;
+    pVCpu->hwaccm.s.vmx.cr4_mask = 0;
+
+    pVCpu->hwaccm.s.fActive        = false;
+    pVCpu->hwaccm.s.Event.fPending = false;
+
+    /* Reset state information for real-mode emulation in VT-x. */
+    pVCpu->hwaccm.s.vmx.enmLastSeenGuestMode = PGMMODE_REAL;
+    pVCpu->hwaccm.s.vmx.enmPrevGuestMode     = PGMMODE_REAL;
+    pVCpu->hwaccm.s.vmx.enmCurrGuestMode     = PGMMODE_REAL;
+
+    /* Reset the contents of the read cache. */
+    PVMCSCACHE pCache = &pVCpu->hwaccm.s.vmx.VMCSCache;
+    for (unsigned j=0;j<pCache->Read.cValidEntries;j++)
+        pCache->Read.aFieldVal[j] = 0;
+
+#ifdef VBOX_WITH_CRASHDUMP_MAGIC
+    /* Magic marker for searching in crash dumps. */
+    strcpy((char *)pCache->aMagic, "VMCSCACHE Magic");
+    pCache->uMagic = UINT64_C(0xDEADBEEFDEADBEEF);
+#endif
+}
+
+/**
  * The VM is being reset.
  *
@@ -1476,28 +1509,5 @@
         PVMCPU pVCpu = &pVM->aCpus[i];
 
-        /* On first entry we'll sync everything. */
-        pVCpu->hwaccm.s.fContextUseFlags = HWACCM_CHANGED_ALL;
-
-        pVCpu->hwaccm.s.vmx.cr0_mask = 0;
-        pVCpu->hwaccm.s.vmx.cr4_mask = 0;
-
-        pVCpu->hwaccm.s.fActive        = false;
-        pVCpu->hwaccm.s.Event.fPending = false;
-
-        /* Reset state information for real-mode emulation in VT-x. */
-        pVCpu->hwaccm.s.vmx.enmLastSeenGuestMode = PGMMODE_REAL;
-        pVCpu->hwaccm.s.vmx.enmPrevGuestMode     = PGMMODE_REAL;
-        pVCpu->hwaccm.s.vmx.enmCurrGuestMode     = PGMMODE_REAL;
-
-        /* Reset the contents of the read cache. */
-        PVMCSCACHE pCache = &pVCpu->hwaccm.s.vmx.VMCSCache;
-        for (unsigned j=0;j<pCache->Read.cValidEntries;j++)
-            pCache->Read.aFieldVal[j] = 0;
-
-#ifdef VBOX_WITH_CRASHDUMP_MAGIC
-        /* Magic marker for searching in crash dumps. */
-        strcpy((char *)pCache->aMagic, "VMCSCACHE Magic");
-        pCache->uMagic = UINT64_C(0xDEADBEEFDEADBEEF);
-#endif
+        HWACCMR3ResetCPU(pVCpu);
     }
 
Index: /trunk/src/VBox/VMM/PDM.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDM.cpp	(revision 25815)
+++ /trunk/src/VBox/VMM/PDM.cpp	(revision 25816)
@@ -1153,4 +1153,11 @@
 }
 
+VMMR3DECL(void) PDMR3ResetCpu(PVMCPU pVCpu)
+{
+    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC);
+    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
+    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
+    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_SMI);
+}
 
 /**
@@ -1245,8 +1252,5 @@
     {
         PVMCPU pVCpu = &pVM->aCpus[idCpu];
-        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC);
-        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
-        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
-        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_SMI);
+        PDMR3ResetCpu(pVCpu);
     }
     VM_FF_CLEAR(pVM, VM_FF_PDM_DMA);
Index: /trunk/src/VBox/VMM/PGM.cpp
===================================================================
--- /trunk/src/VBox/VMM/PGM.cpp	(revision 25815)
+++ /trunk/src/VBox/VMM/PGM.cpp	(revision 25816)
@@ -2172,4 +2172,27 @@
 }
 
+VMMR3DECL(void) PGMR3ResetCpu(PVM pVM, PVMCPU pVCpu)
+{
+    int rc = PGM_GST_PFN(Exit, pVCpu)(pVCpu);
+    AssertRC(rc);
+
+    rc = PGMR3ChangeMode(pVM, pVCpu, PGMMODE_REAL);
+    AssertRC(rc);
+
+    STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cGuestModeChanges);
+
+    pgmR3PoolResetCpu(pVM, pVCpu);
+
+    /*
+     * Re-init other members.
+     */
+    pVCpu->pgm.s.fA20Enabled = true;
+
+    /*
+     * Clear the FFs PGM owns.
+     */
+    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
+    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
+}
 
 /**
Index: /trunk/src/VBox/VMM/PGMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/PGMInternal.h	(revision 25815)
+++ /trunk/src/VBox/VMM/PGMInternal.h	(revision 25816)
@@ -3285,4 +3285,5 @@
 void            pgmR3PoolRelocate(PVM pVM);
 void            pgmR3PoolReset(PVM pVM);
+void            pgmR3PoolResetCpu(PVM pVM, PVMCPU pVCpu);
 void            pgmR3PoolClearAll(PVM pVM);
 
Index: /trunk/src/VBox/VMM/TRPM.cpp
===================================================================
--- /trunk/src/VBox/VMM/TRPM.cpp	(revision 25815)
+++ /trunk/src/VBox/VMM/TRPM.cpp	(revision 25816)
@@ -713,4 +713,8 @@
 }
 
+VMMR3DECL(void) TRPMR3ResetCpu(PVMCPU pVCpu)
+{
+    pVCpu->trpm.s.uActiveVector = ~0;
+}
 
 /**
@@ -746,5 +750,5 @@
     {
         PVMCPU pVCpu = &pVM->aCpus[i];
-        pVCpu->trpm.s.uActiveVector = ~0;
+        TRPMR3ResetCpu(pVCpu);
     }
     memcpy(&pVM->trpm.s.aIdt[0], &g_aIdt[0], sizeof(pVM->trpm.s.aIdt));
Index: /trunk/src/VBox/VMM/VM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VM.cpp	(revision 25815)
+++ /trunk/src/VBox/VMM/VM.cpp	(revision 25816)
@@ -4042,2 +4042,79 @@
 }
 
+DECLCALLBACK(int) vmR3HotunplugCPU(PVM pVM, VMCPUID idCpu)
+{
+    PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
+    VMCPU_ASSERT_EMT(pVCpu);
+
+    /*
+     * Reset per CPU resources.
+     * Actually only needed for VT-x because the CPU
+     * seems to be still in some paged mode and startup
+     * fails after a new hotplug event.
+     * SVM works fine even without this.
+     */
+    Log(("vmR3HotunplugCPU for VCPU %d\n", idCpu));
+    PGMR3ResetCpu(pVM, pVCpu);
+    PDMR3ResetCpu(pVCpu);
+    TRPMR3ResetCpu(pVCpu);
+    CPUMR3ResetCpu(pVCpu);
+    EMR3ResetCpu(pVCpu);
+    HWACCMR3ResetCPU(pVCpu);
+    return VINF_EM_WAIT_SIPI;
+}
+
+/**
+ * Return the package and core id of a CPU.
+ *
+ * @returns VBOX status code.
+ * @param   pVM              The VM to operate on.
+ * @param   idCpu            Virtual CPU to get the ID from.
+ * @param   pidCpuCore       Where to store the core ID of the virtual CPU.
+ * @param   pidCpuPackage    Where to store the package ID of the virtual CPU.
+ */
+VMMR3DECL(int) VMR3GetCPUCoreAndPackageIdFromCPUId(PVM pVM, VMCPUID idCpu, uint32_t *pidCpuCore, uint32_t *pidCpuPackage)
+{
+    if (idCpu >= pVM->cCpus)
+        return VERR_INVALID_CPU_ID;
+
+#ifdef VBOX_WITH_MULTI_CORE
+    *pidCpuCore    = idCpu;
+    *pidCpuPackage = 0;
+#else
+    *pidCpuCore    = 0;
+    *pidCpuPackage = idCpu;
+#endif
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Unplugs a CPU from the guest.
+ *
+ * @returns VBox status code.
+ * @param   pVM     The VM to operate on.
+ * @param   idCpu   Virtual CPU to perform the unplug operation on.
+ */
+VMMR3DECL(int) VMR3HotunplugCPU(PVM pVM, VMCPUID idCpu)
+{
+    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
+
+    /** @todo Destroy EMT and not needed resources. */
+    return VMR3ReqCallNoWaitU(pVM->pUVM, idCpu, (PFNRT)vmR3HotunplugCPU, 2, pVM, idCpu);
+}
+
+/**
+ * Hotplugs a CPU on the guest.
+ *
+ * @returns VBox status code.
+ * @param   pVM     The VM to operate on.
+ * @param   idCpu   Virtual CPU to perform the hotplug operation on.
+ */
+VMMR3DECL(int) VMR3HotplugCPU(PVM pVM, VMCPUID idCpu)
+{
+    AssertReturn(idCpu < pVM->cCpus, VERR_INVALID_CPU_ID);
+
+    /** @todo start EMT and allocate needed resources. */
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp	(revision 25815)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp	(revision 25816)
@@ -4767,4 +4767,14 @@
 
 #ifdef IN_RING3
+
+void pgmR3PoolResetCpu(PVM pVM, PVMCPU pVCpu)
+{
+    pgmR3ExitShadowModeBeforePoolFlush(pVM, pVCpu);
+
+    pgmR3ReEnterShadowModeAfterPoolFlush(pVM, pVCpu);
+    VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
+    VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
+}
+
 /**
  * Flushes the entire cache.
