Changeset 25901 in vbox for trunk/src/VBox/Main/ConsoleImpl.cpp
- Timestamp:
- Jan 18, 2010 4:52:21 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl.cpp
r25893 r25901 1730 1730 } 1731 1731 1732 DECLCALLBACK(int) Console::unplugCpu(Console *pThis, unsigned uCpu) 1733 { 1734 LogFlowFunc(("pThis=%p uCpu=%u\n", pThis, uCpu)); 1735 1736 AssertReturn(pThis, VERR_INVALID_PARAMETER); 1737 1738 int vrc = PDMR3DeviceDetach(pThis->mpVM, "acpi", 0, uCpu, 0); 1739 Log(("UnplugCpu: rc=%Rrc\n", vrc)); 1740 1741 return vrc; 1742 } 1743 1744 STDMETHODIMP Console::doCPURemove(ULONG aCpu) 1745 { 1746 HRESULT rc = S_OK; 1747 1748 LogFlowThisFuncEnter(); 1749 LogFlowThisFunc(("mMachineState=%d\n", mMachineState)); 1750 1751 AutoCaller autoCaller(this); 1752 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1753 1754 AutoWriteLock alock(this); 1755 1756 if ( mMachineState != MachineState_Running 1757 && mMachineState != MachineState_Teleporting 1758 && mMachineState != MachineState_LiveSnapshotting 1759 ) 1760 return setError(VBOX_E_INVALID_VM_STATE, 1761 tr("Invalid machine state: %s"), 1762 Global::stringifyMachineState(mMachineState)); 1763 1764 /* protect mpVM */ 1765 AutoVMCaller autoVMCaller(this); 1766 if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc(); 1767 1768 /* Check if the CPU is present */ 1769 BOOL fCpuAttached; 1770 rc = mMachine->GetCPUStatus(aCpu, &fCpuAttached); 1771 if (FAILED(rc)) return rc; 1772 1773 if (!fCpuAttached) 1774 return setError(E_FAIL, 1775 tr("CPU %d is not attached"), aCpu); 1776 1777 /* Check if the CPU is unlocked */ 1778 PPDMIBASE pBase; 1779 int vrc = PDMR3QueryDeviceLun(mpVM, "acpi", 0, aCpu, &pBase); 1780 bool fLocked = true; 1781 if (RT_SUCCESS(vrc)) 1782 { 1783 uint32_t idCpuCore, idCpuPackage; 1784 1785 /* Notify the guest if possible. */ 1786 vrc = VMR3GetCpuCoreAndPackageIdFromCpuId(mpVM, aCpu, &idCpuCore, &idCpuPackage); 1787 AssertRC(vrc); 1788 1789 Assert(pBase); 1790 1791 PPDMIACPIPORT pPort = 1792 (PPDMIACPIPORT) pBase->pfnQueryInterface(pBase, PDMINTERFACE_ACPI_PORT); 1793 1794 vrc = getVMMDev()->getVMMDevPort()->pfnCpuHotUnplug(getVMMDev()->getVMMDevPort(), idCpuCore, idCpuPackage); 1795 if (RT_SUCCESS(vrc)) 1796 { 1797 unsigned cTries = 10; 1798 1799 do 1800 { 1801 /* It will take some time until the event is processed in the guest. Wait */ 1802 vrc = pPort ? pPort->pfnGetCpuStatus(pPort, aCpu, &fLocked) : VERR_INVALID_POINTER; 1803 1804 if (RT_SUCCESS(vrc) && !fLocked) 1805 break; 1806 1807 /* Sleep a bit */ 1808 RTThreadSleep(100); 1809 } while (cTries-- > 0); 1810 } 1811 else if (vrc == VERR_CPU_HOTPLUG_NOT_MONITORED_BY_GUEST) 1812 { 1813 /* Query one time. It is possible that the user ejected the CPU. */ 1814 vrc = pPort ? pPort->pfnGetCpuStatus(pPort, aCpu, &fLocked) : VERR_INVALID_POINTER; 1815 } 1816 } 1817 1818 /* If the CPU was unlocked we can detach it now. */ 1819 if (RT_SUCCESS(vrc) && !fLocked) 1820 { 1821 /* 1822 * Call worker in EMT, that's faster and safer than doing everything 1823 * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait 1824 * here to make requests from under the lock in order to serialize them. 1825 */ 1826 PVMREQ pReq; 1827 vrc = VMR3ReqCall(mpVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 1828 (PFNRT)Console::unplugCpu, 2, 1829 this, aCpu); 1830 1831 /* leave the lock before a VMR3* call (EMT will call us back)! */ 1832 alock.leave(); 1833 1834 if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc)) 1835 { 1836 vrc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT); 1837 AssertRC(vrc); 1838 if (RT_SUCCESS(vrc)) 1839 vrc = pReq->iStatus; 1840 } 1841 VMR3ReqFree(pReq); 1842 1843 if (RT_SUCCESS(vrc)) 1844 { 1845 /* Detach it from the VM */ 1846 vrc = VMR3HotUnplugCpu(mpVM, aCpu); 1847 AssertRC(vrc); 1848 } 1849 else 1850 rc = setError(VBOX_E_VM_ERROR, 1851 tr("Hot-Remove failed (rc=%Rrc)"), vrc); 1852 } 1853 else 1854 rc = setError(VBOX_E_VM_ERROR, 1855 tr("Hot-Remove was aborted because the CPU may still be used by the guest"), VERR_RESOURCE_BUSY); 1856 1857 LogFlowThisFunc(("mMachineState=%d, rc=%08X\n", mMachineState, rc)); 1858 LogFlowThisFuncLeave(); 1859 return rc; 1860 } 1861 1862 DECLCALLBACK(int) Console::plugCpu(Console *pThis, unsigned uCpu) 1863 { 1864 LogFlowFunc(("pThis=%p uCpu=%u\n", pThis, uCpu)); 1865 1866 AssertReturn(pThis, VERR_INVALID_PARAMETER); 1867 1868 int rc = VMR3HotPlugCpu(pThis->mpVM, uCpu); 1869 AssertRC(rc); 1870 1871 PCFGMNODE pInst = CFGMR3GetChild(CFGMR3GetRoot(pThis->mpVM), "Devices/acpi/0/"); 1872 AssertRelease(pInst); 1873 /* nuke anything which might have been left behind. */ 1874 CFGMR3RemoveNode(CFGMR3GetChildF(pInst, "LUN#%d", uCpu)); 1875 1876 #define RC_CHECK() do { if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; } } while (0) 1877 1878 PCFGMNODE pLunL0; 1879 PCFGMNODE pCfg; 1880 rc = CFGMR3InsertNodeF(pInst, &pLunL0, "LUN#%d", uCpu); RC_CHECK(); 1881 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPICpu"); RC_CHECK(); 1882 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1883 1884 /* 1885 * Attach the driver. 1886 */ 1887 PPDMIBASE pBase; 1888 rc = PDMR3DeviceAttach(pThis->mpVM, "acpi", 0, uCpu, 0, &pBase); RC_CHECK(); 1889 1890 Log(("PlugCpu: rc=%Rrc\n", rc)); 1891 1892 CFGMR3Dump(pInst); 1893 1894 return VINF_SUCCESS; 1895 } 1896 1897 STDMETHODIMP Console::doCPUAdd(ULONG aCpu) 1898 { 1899 HRESULT rc = S_OK; 1900 1901 LogFlowThisFuncEnter(); 1902 LogFlowThisFunc(("mMachineState=%d\n", mMachineState)); 1903 1904 AutoCaller autoCaller(this); 1905 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1906 1907 AutoWriteLock alock(this); 1908 1909 if ( mMachineState != MachineState_Running 1910 && mMachineState != MachineState_Teleporting 1911 && mMachineState != MachineState_LiveSnapshotting 1912 /** @todo r=bird: This should be allowed on paused VMs as well. Later. */ 1913 ) 1914 return setError(VBOX_E_INVALID_VM_STATE, 1915 tr("Invalid machine state: %s"), 1916 Global::stringifyMachineState(mMachineState)); 1917 1918 /* protect mpVM */ 1919 AutoVMCaller autoVMCaller(this); 1920 if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc(); 1921 1922 /* Check if the CPU is present */ 1923 BOOL fCpuAttached; 1924 rc = mMachine->GetCPUStatus(aCpu, &fCpuAttached); 1925 if (FAILED(rc)) return rc; 1926 1927 if (fCpuAttached) 1928 return setError(E_FAIL, 1929 tr("CPU %d is already attached"), aCpu); 1930 1931 /* 1932 * Call worker in EMT, that's faster and safer than doing everything 1933 * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait 1934 * here to make requests from under the lock in order to serialize them. 1935 */ 1936 PVMREQ pReq; 1937 int vrc = VMR3ReqCall(mpVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 1938 (PFNRT)Console::plugCpu, 2, 1939 this, aCpu); 1940 1941 /* leave the lock before a VMR3* call (EMT will call us back)! */ 1942 alock.leave(); 1943 1944 if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc)) 1945 { 1946 vrc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT); 1947 AssertRC(vrc); 1948 if (RT_SUCCESS(vrc)) 1949 vrc = pReq->iStatus; 1950 } 1951 VMR3ReqFree(pReq); 1952 1953 rc = RT_SUCCESS(vrc) ? S_OK : 1954 setError(VBOX_E_VM_ERROR, 1955 tr("Could not add CPU to the machine (%Rrc)"), 1956 vrc); 1957 1958 if (RT_SUCCESS(vrc)) 1959 { 1960 uint32_t idCpuCore, idCpuPackage; 1961 1962 /* Notify the guest if possible. */ 1963 vrc = VMR3GetCpuCoreAndPackageIdFromCpuId(mpVM, aCpu, &idCpuCore, &idCpuPackage); 1964 AssertRC(vrc); 1965 1966 vrc = getVMMDev()->getVMMDevPort()->pfnCpuHotPlug(getVMMDev()->getVMMDevPort(), idCpuCore, idCpuPackage); 1967 /** @todo warning if the guest doesn't support it */ 1968 } 1969 1970 LogFlowThisFunc(("mMachineState=%d, rc=%08X\n", mMachineState, rc)); 1971 LogFlowThisFuncLeave(); 1972 return rc; 1973 } 1974 1732 1975 STDMETHODIMP Console::Pause() 1733 1976 { … … 3730 3973 while (it != mCallbacks.end()) 3731 3974 (*it++)->OnMediumChange(aMediumAttachment); 3975 } 3976 3977 LogFlowThisFunc(("Leaving rc=%#x\n", rc)); 3978 return rc; 3979 } 3980 3981 /** 3982 * Called by IInternalSessionControl::OnCPUChange(). 3983 * 3984 * @note Locks this object for writing. 3985 */ 3986 HRESULT Console::onCPUChange(ULONG aCPU, BOOL aRemove) 3987 { 3988 LogFlowThisFunc(("\n")); 3989 3990 AutoCaller autoCaller(this); 3991 AssertComRCReturnRC(autoCaller.rc()); 3992 3993 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 3994 3995 /* Don't do anything if the VM isn't running */ 3996 if (!mpVM) 3997 return S_OK; 3998 3999 HRESULT rc = S_OK; 4000 4001 /* protect mpVM */ 4002 AutoVMCaller autoVMCaller(this); 4003 if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc(); 4004 4005 if (aRemove) 4006 rc = doCPURemove(aCPU); 4007 else 4008 rc = doCPUAdd(aCPU); 4009 4010 /* notify console callbacks on success */ 4011 if (SUCCEEDED(rc)) 4012 { 4013 CallbackList::iterator it = mCallbacks.begin(); 4014 while (it != mCallbacks.end()) 4015 (*it++)->OnCPUChange(aCPU, aRemove); 3732 4016 } 3733 4017
Note:
See TracChangeset
for help on using the changeset viewer.